From c7c4e2b9dd8fab7c1f677957cf42cc0ddc14a4b4 Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Sat, 29 Oct 2016 12:46:05 +0200 Subject: [PATCH] Build ITS monitor from source code. --- .gitignore | 1 + .gitmodules | 6 + .travis.yml | 8 + Makefile | 29 + README.md | 11 +- bin/_/@.ddt | Bin 0 -> 18676 bytes bin/_/bt.rm03 | Bin 0 -> 4341 bytes bin/_/bt.rm80 | Bin 0 -> 4341 bytes bin/_/bt.rp06 | Bin 0 -> 4331 bytes bin/_/bt.rp07 | Bin 0 -> 4581 bytes bin/_/dskdmp.rm03 | Bin 0 -> 11541 bytes bin/_/dskdmp.rm80 | Bin 0 -> 11577 bytes bin/_/dskdmp.rp06 | Bin 0 -> 11598 bytes bin/_/dskdmp.rp07 | Bin 0 -> 12011 bytes bin/_/its.rm03 | Bin 0 -> 241430 bytes bin/_/its.rm80 | Bin 0 -> 241428 bytes bin/_/its.rp06 | Bin 0 -> 241500 bytes bin/_/its.rp07 | Bin 0 -> 241732 bytes bin/_/ram.ram | Bin 0 -> 30645 bytes bin/_/salv.rm03 | Bin 0 -> 57729 bytes bin/_/salv.rm80 | Bin 0 -> 57730 bytes bin/_/salv.rp06 | Bin 0 -> 58501 bytes bin/_/salv.rp07 | Bin 0 -> 58452 bytes bin/boot/dskdmp.rp06 | Bin 0 -> 32975 bytes bin/boot/ram.262 | Bin 0 -> 30720 bytes bin/boot/salv.rp06 | Bin 0 -> 79890 bytes bin/sys/atsign.ddt | Bin 0 -> 203895 bytes bin/sys/atsign.device | Bin 0 -> 2802 bytes bin/sys/atsign.hactrn | 1 + bin/sys/ts.dump | 1 + bin/sys/ts.ksfedr | Bin 0 -> 20618 bytes bin/sys/ts.lock | Bin 0 -> 10702 bytes bin/sys/ts.pdset | Bin 0 -> 7134 bytes bin/sys3/ts.midas | Bin 0 -> 109127 bytes bin/sysbin/dump.bin | Bin 0 -> 69551 bytes build/build.tcl | 93 + build/simh/boot | 5 + build/simh/init | 7 + doc/build.doc | 1068 ++ doc/build.info | 84 + src/system/bits.117 | 1111 ++ src/system/ch10.defs1 | 26 + src/system/ch11.defs1 | 58 + src/system/chaos.288 | 2782 +++++ src/system/chsdef.15 | 68 + src/system/config.196 | 926 ++ src/system/core.82 | 2989 +++++ src/system/dc10.defs27 | 270 + src/system/ddt.68 | Bin 0 -> 48256 bytes src/system/ddtdsk.31 | Bin 0 -> 28952 bytes src/system/disk.1224 | 6412 +++++++++++ src/system/dmpcpy.11 | 153 + src/system/dskdmp.215 | 1882 ++++ src/system/dz11.10 | 56 + src/system/ept.defs16 | 160 + src/system/evsyms.21 | 278 + src/system/fsdefs.43 | 216 + src/system/imp.365 | 931 ++ src/system/impold.wthncp | 1974 ++++ src/system/inet.138 | 1430 +++ src/system/ioelev.432 | 4944 +++++++++ src/system/its.1644 | 21930 +++++++++++++++++++++++++++++++++++++ src/system/itsdev.974 | 5321 +++++++++ src/system/itsdis.50 | 320 + src/system/itsmsp.30 | 315 + src/system/kaimp.defs1 | 63 + src/system/ksdefs.193 | 561 + src/system/ksnet.1 | 58 + src/system/lhdh.defs5 | 80 + src/system/mtape.197 | 1461 +++ src/system/ncp.9 | 2761 +++++ src/system/net.32 | 501 + src/system/ni1010.defs2 | 98 + src/system/nmtape.30 | 2432 ++++ src/system/rh10.defs26 | 230 + src/system/rh11.defs48 | 289 + src/system/rm03.defs5 | 41 + src/system/rm80.defs4 | 45 + src/system/rp06.defs1 | 41 + src/system/rp07.defs1 | 41 + src/system/rp10.defs16 | 106 + src/system/salv.311 | 6685 +++++++++++ src/system/sysjob.117 | 2796 +++++ src/system/t20mac.1 | 345 + src/system/t300.defs7 | 92 + src/system/tcp.275 | 3629 ++++++ src/system/tcpbuf.58 | 575 + src/system/time.950 | 343 + src/system/tm03s.defs4 | 151 + src/system/tm78s.defs2 | 178 + src/system/ts3tty.400 | 8214 ++++++++++++++ src/system/ttytyp.314 | 400 + src/system/tv.132 | 5995 ++++++++++ src/system/utape.952 | 2009 ++++ src/system/whovar.5 | 158 + tools/itstar | 1 + tools/tapeutils | 1 + 97 files changed, 96244 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 100644 .travis.yml create mode 100644 Makefile create mode 100644 bin/_/@.ddt create mode 100644 bin/_/bt.rm03 create mode 100644 bin/_/bt.rm80 create mode 100644 bin/_/bt.rp06 create mode 100644 bin/_/bt.rp07 create mode 100644 bin/_/dskdmp.rm03 create mode 100644 bin/_/dskdmp.rm80 create mode 100644 bin/_/dskdmp.rp06 create mode 100644 bin/_/dskdmp.rp07 create mode 100644 bin/_/its.rm03 create mode 100644 bin/_/its.rm80 create mode 100644 bin/_/its.rp06 create mode 100644 bin/_/its.rp07 create mode 100644 bin/_/ram.ram create mode 100644 bin/_/salv.rm03 create mode 100644 bin/_/salv.rm80 create mode 100644 bin/_/salv.rp06 create mode 100644 bin/_/salv.rp07 create mode 100644 bin/boot/dskdmp.rp06 create mode 100644 bin/boot/ram.262 create mode 100644 bin/boot/salv.rp06 create mode 100644 bin/sys/atsign.ddt create mode 100644 bin/sys/atsign.device create mode 120000 bin/sys/atsign.hactrn create mode 120000 bin/sys/ts.dump create mode 100644 bin/sys/ts.ksfedr create mode 100644 bin/sys/ts.lock create mode 100644 bin/sys/ts.pdset create mode 100755 bin/sys3/ts.midas create mode 100644 bin/sysbin/dump.bin create mode 100644 build/build.tcl create mode 100644 build/simh/boot create mode 100644 build/simh/init create mode 100644 doc/build.doc create mode 100644 doc/build.info create mode 100755 src/system/bits.117 create mode 100755 src/system/ch10.defs1 create mode 100755 src/system/ch11.defs1 create mode 100755 src/system/chaos.288 create mode 100755 src/system/chsdef.15 create mode 100755 src/system/config.196 create mode 100755 src/system/core.82 create mode 100755 src/system/dc10.defs27 create mode 100755 src/system/ddt.68 create mode 100755 src/system/ddtdsk.31 create mode 100755 src/system/disk.1224 create mode 100755 src/system/dmpcpy.11 create mode 100755 src/system/dskdmp.215 create mode 100755 src/system/dz11.10 create mode 100755 src/system/ept.defs16 create mode 100755 src/system/evsyms.21 create mode 100755 src/system/fsdefs.43 create mode 100755 src/system/imp.365 create mode 100755 src/system/impold.wthncp create mode 100755 src/system/inet.138 create mode 100755 src/system/ioelev.432 create mode 100755 src/system/its.1644 create mode 100755 src/system/itsdev.974 create mode 100755 src/system/itsdis.50 create mode 100755 src/system/itsmsp.30 create mode 100755 src/system/kaimp.defs1 create mode 100755 src/system/ksdefs.193 create mode 100755 src/system/ksnet.1 create mode 100755 src/system/lhdh.defs5 create mode 100755 src/system/mtape.197 create mode 100755 src/system/ncp.9 create mode 100755 src/system/net.32 create mode 100755 src/system/ni1010.defs2 create mode 100755 src/system/nmtape.30 create mode 100755 src/system/rh10.defs26 create mode 100755 src/system/rh11.defs48 create mode 100755 src/system/rm03.defs5 create mode 100755 src/system/rm80.defs4 create mode 100755 src/system/rp06.defs1 create mode 100755 src/system/rp07.defs1 create mode 100755 src/system/rp10.defs16 create mode 100755 src/system/salv.311 create mode 100755 src/system/sysjob.117 create mode 100755 src/system/t20mac.1 create mode 100755 src/system/t300.defs7 create mode 100755 src/system/tcp.275 create mode 100755 src/system/tcpbuf.58 create mode 100755 src/system/time.950 create mode 100755 src/system/tm03s.defs4 create mode 100755 src/system/tm78s.defs2 create mode 100755 src/system/ts3tty.400 create mode 100755 src/system/ttytyp.314 create mode 100755 src/system/tv.132 create mode 100755 src/system/utape.952 create mode 100755 src/system/whovar.5 create mode 160000 tools/itstar create mode 160000 tools/tapeutils diff --git a/.gitignore b/.gitignore index b25c15b8..db0f4ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *~ +out diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..2611e428 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "itstar"] + path = tools/itstar + url = https://github.com/PDP-10/itstar +[submodule "tapeutils"] + path = tools/tapeutils + url = https://github.com/brouhaha/tapeutils diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9fcbe668 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: c +sudo: required +install: + - sudo apt-get update -myq + - sudo apt-get install -my simh expect +script: make +notifications: + email: lars@nocrew.org diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..af4233b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +ITSTAR=${PWD}/tools/itstar/itstar +WRITETAPE=${PWD}/tools/tapeutils/tapewrite + +all: out/rp0.dsk + +out/rp0.dsk: build/simh/init out/minsys.tape out/salv.tape out/dskdmp.tape build/build.tcl + expect -f build/build.tcl + +out/minsys.tape: $(ITSTAR) + mkdir -p out + cd bin; $(ITSTAR) -cf ../$@ _ sys sys3 sysbin + cd src; $(ITSTAR) -rf ../$@ system + +out/salv.tape: $(WRITETAPE) bin/boot/ram.262 bin/boot/salv.rp06 + mkdir -p out + $(WRITETAPE) -n 2560 $@ bin/boot/ram.262 bin/boot/salv.rp06 + +out/dskdmp.tape: $(WRITETAPE) bin/boot/ram.262 bin/boot/dskdmp.rp06 + mkdir -p out + $(WRITETAPE) -n 2560 $@ bin/boot/ram.262 bin/boot/dskdmp.rp06 + +$(ITSTAR): + cd tools/itstar; make + +$(WRITETAPE): + cd tools/tapeutils; make + +clean: + rm -rf out diff --git a/README.md b/README.md index ee700d96..7b4997f0 100644 --- a/README.md +++ b/README.md @@ -12,5 +12,12 @@ to operate ITS systems to this day. This repository contains source code, tools, and scripts to build ITS from scratch. -...or at least, that's the plan. There will be some initial -experimentation in the [`test` branch](http://github.com/PDP-10/its/tree/test). +1. First, magnetic tape images are created from files in `src` and + `bin`. There are two bootable tapes, and one tape with files in + DSKDMP backup format. + +2. Then the tapes are used to create a file system on an RP06 disk and + populate it with a minimal system, and also source code. + +3. Finally, the system is booted from the disk, and MIDAS is invoked + to assemble ITS from source code. diff --git a/bin/_/@.ddt b/bin/_/@.ddt new file mode 100644 index 0000000000000000000000000000000000000000..7a1c2f7325a9ba7603a9a23e6d6544ad4094e9e4 GIT binary patch literal 18676 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 Y-W+U*;I0Gq8M__Y7u(e@;79R)0mE`7@&Et; literal 0 HcmV?d00001 diff --git a/bin/_/bt.rp06 b/bin/_/bt.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..cd17b267e06efb8714bb75784d5b11d50a0fd811 GIT binary patch literal 4331 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 Q8Jmr$psHr^D1Hk68w|V|X8-^I literal 0 HcmV?d00001 diff --git a/bin/_/bt.rp07 b/bin/_/bt.rp07 new file mode 100644 index 0000000000000000000000000000000000000000..3a92eb0d05487d719c4af0848511d6fe0812f976 GIT binary patch literal 4581 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 a)_r#-%0(#KZ=JMSi40xUX$$yIfd2wD$Xpfx literal 0 HcmV?d00001 diff --git a/bin/_/dskdmp.rm03 b/bin/_/dskdmp.rm03 new file mode 100644 index 0000000000000000000000000000000000000000..c47c9ebbb72504f5fb221d114247cba0ca8178f1 GIT binary patch literal 11541 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 literal 0 HcmV?d00001 diff --git a/bin/_/dskdmp.rp06 b/bin/_/dskdmp.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..4633cc19dba1c33405d7301c7d412a41a628fdc9 GIT binary patch literal 11598 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 E00y?`fdBvi literal 0 HcmV?d00001 diff --git a/bin/_/dskdmp.rp07 b/bin/_/dskdmp.rp07 new file mode 100644 index 0000000000000000000000000000000000000000..df1f6eae2cd6b71df4cf64407a2c95c5a3eda993 GIT binary patch literal 12011 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 Ji4=_x{~OcBc>MqX literal 0 HcmV?d00001 diff --git a/bin/_/its.rm03 b/bin/_/its.rm03 new file mode 100644 index 0000000000000000000000000000000000000000..0192dc57fd865d8e4dffd37161475fbe9b3afb52 GIT binary patch literal 241430 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⪻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

YgJ`lm^SI{=c@Aln3fwMOBd5)6TuS|@YR7IC6 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

BXzWd@*G7BKEq!#_9e11xXcrT-TjM1LMj@??z+B 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®rX*_?TUmfF;SQ8@AYQ_4)kMO&U#+p|4f>0t!zU)Og z#sLDStOFuk%3d=%SG^E{)+1%_KLzzk3BPP;f?C+sm3>MrS!gpH<3%)H&XqvoFE>G~ zujM}YvHF$=K^(0-OsHiw)=Vk;ZYH!xv}RIgd6Z~>EQZ#L)>;9@Lsn>`SpS1DDo;kU zQML`z(bBMPLK}yYph>KDtXZP%{~XE|dWrp0`99;}H*B*|k+o{QjqxpaNN=cpZ}}7Y znE!5(OyyNVxsgzvP|0R$z7D0JbwcWl-W4j!!ultDEU=PPQvQW#6|Le|;Vo1{iHblW zR#j8Q9igU3Xr)An+ACGWLG5UEp7BXsP*=KqywU?sWXh zg@#FMm2$oheB6(9110Fw$||X)l;xvRMp_@9hFXNwpGQ}Ai#3^esZ65{fPvR166EMS#apdmDAsck*ITX|jl)E96oJJ39^_CQ|HDApkSZbRzKKZML^pW&yD zCb4T<&rOEPdsyjHhljMKH&--=594+M%?B+HEeMU6bV!Wrz5Ad5sl`RgcF3sOToL%K z6O#MwLLuTe%ypb29cn;}gcwyvj?jLVL5K9(1OJCOa4?qp*&aBGrB%tVL8W57)roZj z#8T_%6uX5ICem)zDX(TIf#`J%nZl68@dA#O&;Vm$1#X4gX5T3J-YutjebQv zr{n9+tDQF=))|gRcoYG9z$rmC|d>X5$ljY*7f)?%c`oxPrYfRDg)xm zzG|EjoH_N`tg+BeDKX)Lby_rytw5E`BYm9FuR4rhDB513txLRST6SK{XtgxT=yq)rVAx=O7}nias5z#wr<3AEbAyUXYqoS<9+gh19QS zRc%tsopQAOQu9i6mam9azI7;?WIfwTGF;V7p%rAQD#k;7>$vJ|A*Q~mYE(Ai@2-L- z^_o4+Zc2QH7JxR7HZNMW{F(5hfBXXSm-?)Xeziq%`*t!zwal%+<_&0}5N)YmD_i~~ zrL7Y(_u?nxdsJh7RL2_69~wT2X5~DTmWuT4($FZKI ztQt46N_7)fGDx+o@%peCzgL8Y+-RM~)nDKF0+Jm{=pIId!5wq^vU(tr*&j zb{fC6lqJHPQCRuS(YYS$0)ACOtH=?~COO)E=8>}n+JxU`h>f&!kmEKfLQ8^1rM{W~ zNOm$W{EpFb&WhEc{Eo@UG)so)l8|l53vP+V%$$*)>=6 z(fN`6__avcmx7@EmiX!fb^tYtNy%-?#5!n6$r)$&S~DY~UmuV4 zb0|VImtA7x4~)Jm4UO9juGP>wvUnq-2^pc2zDJt@*kXNcNbA z>QqY?L>sR_tAIFjm+Zq1jXw@KD8WwJbs6FZ3|BqG<)G`T-qAExg4Q7#0cLV_L1w5= zYN;oSy86-lDDf7@Wz1cJXui;pCPnMA(dr9nw9Qzh)$?_vw%S**cA^bK?P!0(%7&?q5v$t@F=BOW5$ep)gJ?d`pU~Dp z??BPe+gNQKuIK2 z1d%!FN`y)oyE})5r9B5Jtwm@`jHWu-%N(j?{?sw2D!9I@ z>k_TvGpHB(6dJ-hOU<{0>OIjW^s$g)R*TF(5=F4rM?*w*eVp<9H=_vl`tZf)zgf%x z)@KN9eL;~}ODeyjv~WmvAt6g7yZLVxGx+s6&`Z=3N9);_*2^{DH;Z3H+lWT^)yt&$ zX7P2j&C;p~b}RLAJz<|9bn9j3bmB86cKue-+F3E{Geo<^4zON!vi5d=NOs>RZt2ib zG}f1Txr(s22T~#rs~znjeM~E1k*zO*?h}xCa=cU>LblRcDaoc@wy&D{oMF9ejkF!Z zXl+8pDNv`BDCVw0{Qy)&#j^3#in;8le+P|)x_$(012hg1VD+<5A~er&Q>8?MY&^AM zE(99n4w_a zq>qM8SPAxqOetHGfmP<`@uEyL*;;Bv1W7}h3`Y_(ra@-@HBt(i z0e#G~ocr00p2qWs%loB7qnw9lIa}IBX}yIn1YR*#}Iwc zxLHX3v0-DHSUovLqg|Pa&;87!CK;K-`-9N-i?&;p zkU4#Lw`!@3g6D2Vx@pjO{%glrjhfyOExiSjk?~9?wKvJg98P~4?N87p=oVHd)-k9C z?R}vHE`^)!3NcuwCfULtj%7RCG%M}%ufqBd(JF|}rq9uep)W)`{-h!)TR~hkGovj3j@e8LuMzuLsA2XFOs?AnoDDCA^NLJdT>QBI%GoVbgwc-~; zk2e=eEq(M$bAr^;r;f1+A|Etw$4WkE9)+^dWXwGiiP+}dM&RNEwUkx>Sd<1$gS;Ph8{;dE?fQKLNvK#iRxitYAKS9`)Y1S zwOka+XWegcY6EL}iMp2OgwziQEmw?&px!{NP1=B8cL3Ixg}PLmJGFuEPF3HqP&jAV za!V+T9MN)6YEDzf_*m~zuO>FNxEKHWy}zFnYg?q=KUBcc+Md*V;#;#s>zL7dw(g`) zJ3aKCutIvgGf3}uXJPGJsSo(CR@M!A|L}$$v~VHyIp)qBy=O}cBhwkL9ZdI(p=^_o zcRX5}Sev*M>73MiR;$fv=U%-%F*OqHA$?%wWGjBl74Qc$Gal*;lS_}X!%mhe`mD167*s3 zB&G2)MHsi_y3)mZKiikCS-D_cK|FWm8dqQb&MvgmdPn2hEVN3Y2sTSy&q&#<`vjT= z%mhxC+y{yFXYzFQ3xzA~mNaE}0&PkT@d#7D>q~v0BT*z%w~s!sYda?d71q$X-2wVQ zr)L(LulNnOq6O*$EmozOjjK_wvOshP$=}IlGYH*PLVJVJE;|NR1_q$D%DX+Am#HaE z?FhSjG$9g0_v=FWe)#no4ceUt(cTdHRRmg}QGYM{D%wq>{=dF+6|LWRAl8%Q)BUD3 zam=3uqIL9& z)DlG)^xP3j`V0yZDq!;TtdgVoGBQ0Dy`y)A!0w5Ywy5_q_VDZ1zFD+vq5Nt5;-vL2 ze~Q*1^ea`%R*+*ejC%UeR0{^tg7AAAGDGiRRob77 zfqcJiN{m@H$D|fO)5g>fik}tgHOZGb_A}jjy==a-8N^zz8Djb94bpmiG$w8DDyi=? ze@e*PCm(&5bL)-JLbjSo*}d{3_YVi@m)=dbgg{%Ajzy(-YQu= z$dyZPq-G19A`SKC$vZLk96*cHB8Dn7au?Po<=lSzG#Y(><6X38 zjlP(3A3)C;2cP`c8_*S@^K2PG3^Ty z>tASJ-#RqHLPw!I=rGm`9Aht91;=1v@2i6NrK|60tZwKkCBDGgBAU9A>}!K!&^pEX z5nF-28~CwB@9T%yEcLww)uHiWtRfrQyVOjd_WcRsu4&(GXcP24C5XwsgJ^8R`zF!I zFMaa9&u@Q}2Yrq;1gjhCX6Rv&*!lF`!^mphA4h>YXakffZvCNR9gKv+A#P9hr$g*i z`Xiw=Xf8^S4*F9eE=T(_#oEX2uYVVQ{Gix>9O5+kPvJ*H`xo#darKu94aGxc&<3bl z{O)iG-TxFs0_k@OeRu)wlJW4VzY;?IKejsJ2AZJD)chfS^=Qpd1IHbP+948Qe+PbV zLn=()p{xqichN@h8-hk@iw=!Lst?}RtS&2i`u@Ad!(X?)0)1+A_*qHv{c~uyMH}#e z-Vkj-g8l2(n`maKrQZXRu>ZQ177R$(`&kKgtbW!3tTF-oto_g`h{P}uK&v*Rg-Qzo z4x$A^{75@sGx8Eoe26s-`UuL9$+&_(9av+n7*anL4CIIwM0y#B61u}qV898npBQMN z#1zyGk)#IFp$fEN{79k$hmE|uCw{r(_4yoSgg;eX`5K4Z6WAtgIf$LaS2X4x!Ruj$x{YF*p z-+R&Cp`JGGa7z_b~KXD;7Y0QKO@jmp>VV?@tazSmL^og4ry?gSpS{a9n3)^o(E&ls?ZA2 zxRWuMWb{4uC`oy68`=&iL-%Oe$SfP&YxABPWb_AfjqAGyiT1(MXbsQ>h`1ko1|r%A z>maTH2d_}#GIR}k7P@Yn{4X;L;$SDlRr26##-(4beHyxG%l6isDl>JQYcXgkxqx6!rFpXOD)RpGS(!tMyw4`3q-ye+K-jA zJJfDT+P;GA#!$DAdNOZlP{^OeKXed{xEl6AW1~9kFHsk94hodGir_qkb)hxhQerq5 zV#_cbD}GTyP`XwcP(g1F`wcF7C=`+Tr& zfqc^9nMDE zj&=l%4a)Fwv`nn~pbV%SBF2ZS@tef&8GXK2%R;NOnG@#Onhie(vFHvrK{=3oXz=Fz zF{l-dXd3Q7W9jCM0verA7gkoGVTstA^DO7Xqgvs%Niy8<`$7|B;NcGpM}zvis^KZh zawRl8BfaszFF~_t+`Al}Uo?L3GjjWg32QIpuN5YFa=s(cnsv~Nwv1?6aZd~j_Q+;y zruP)FJ5p#|>wbvH8Hv~3v2njVixfXaKFqn%z;s zTo^eg+60lPXq0#vd4#fLu8|9nl@jHaW-TEYa%hE#<{els84l+$=Ke?%8Z%&|4N_5v{m7LABr(tztbI88^N?Rxu7uK*ZI^3|3Xk zXPk%X=UIpuFmlhBJbjm(IO+qv0GaiUT=iF$qw+z*_!M>-qw-@|yZ&W@s7@y(? zB?u*ZV|CihscDgDi8gatI=wOKvYAV#v(Ppg?Qa!dM5~igElWX5vc_#zUn3iBuz>)2obP0caq`RO$&-_9qHPF5+l-Z#PPPjTaYmC{gw*3}lbzN*2Ll+v$yB|3+u$82 z&FX6H8>Pf?i*>u&Tun%%2uHJ)n5{-;G`LVVwC&~ofm2VFFMPi+?HihnQh314Z=CFP)v||>{ zEpNJi=?k=baygivBHEOvP%bT)@)0UvM>{1KhI4sySObLi1w$+Fqb*aRnmuAG$DNAM zJ6ZMqh$wouw8v~01?tF|1G7pj?63y$jZbKVuycM4L+ zl@`qTtF}BTG!sl&m(a9oeJ!NgTrU(9iM3HkSM|N1&%1N8(Aq@{Z-u&qm;k1!ZlRU? zp+0^78G?Q4U6G2^!QPkCXq&<)-+`EGV|y?)4>2&)^7M1n-=2i5@+rmxrBEmuo0e&L zxp&py9zk0NJ&GpJL0A3l0_3DbIo2eo43g)dtNwNo+JaVzU#C8o$BxT1y-lCXz|AzB zuFvgoaca}ULZP&DdQ`0ASy=Z7^)Teq$Ax<7py^Vfz8JJeAQIPf8CI6d>5EcJtSVcD z#-L7L5>l5@)3y5C-av+T`dRVQTA}BJ)I!>oZCvCi<@~xD~=hYCueRz zP0&rl@w>s7@f(nHDzIW$kmjV9aY-yJZcnWefzScyj`UE}RwzhH z?2m@5a*VBv$E=L1DTw%+-2|mTsq!t6NVe3oX|!rBlpz$!xy?#Mc*3C{GHtfaaUz_!noh{!3}8IDxXu~_QC97 zp%uj1>~ZV5P3paHvnL?c`iI2o#X>h*Dcbs4$f4KdZREmhR{j7hZ=)*vq;<^cX8SVR z2&r?s0_~&bs}PYh+bmzuE9i#Wtd&g(Tn5bU7m8@$-R*>^Wbk0qZLK zUW9b$S*$Dd@{3bIuz)Y139zr7+n|>}+KOTmXhTU7(=@PIfTT26X*e1kbmm&HadUO9O>EpancE`JiP9~={l&TMIK2(+f?mZqtC!DrE4L$%6YE~Fc0Y~v zs8-PRv1)Rz;YhvD3+)8NrfKdZR@KHwgbpKJ6mYBdKcQ`DQZKleds=ASdMd7k*5UW8 zP^3tvxkktX?TS!D5A*_lB<#62jFKN+EX1!5%7ccma#v^WmQa)vx{a0PYwmrlvG`5s z>k2rmY3`uB%r9Qiq&3!>rF!#Y<9JaP`?9$y-MzKiMA=Vu_crxsymO!H?ixqDXl@S( ztJ}xsQ?)%yO1Qm+b};SSfe_Qq9VE1iWZ<^wZgq#%Tk^5smAp; zTVKO3!e&lx3dA)4=&Z*g2~D8{crYs%cKTF|8Zacd;T zRPCLFR$#04PNE->E}(pd1#(d`1XOFs<;qZfde%Lmy%Uo~mDAcg>y_=WKrYHr?VZi4 z1rKV!SKn557Z@#n8UB=-8bzAH>6)Ck+6lQ|6Jmf&?rx#otyo_d%GwFNCA5!J>K+#= zj)V@{e5%W`pedoWIsCp9Yb6bummaNFA6J+U&?BeRi{R!%g(jqcXoL zHQFk%s+Y*k#|h0wVwIORPJ3iwwM)&;5j43^QB}pc&Zk4FY$QYqnooo1fcZg*pmn5{ z`Rx#`pU;FwAi1W#GcRD8-(z+3W+{?u>O1OleDg0W(`)lj$c_6ad?0xgG-_fG^t8|zQ7|tLQb&!EBIg^S3Wz_U8S8-fGpsSD z?7TeC95r4_*_(RBs#p@n{0KEOjpzS_MmCurGrsk!&Ru99S~G*Y9B2oHdbr}5|HwMg zys88GROn75))`3k#w=8T^$SZ>uA3{U!$!~d-KPYOq7;hlP=ICKy6g~<4q4XKTY&p5 z>sEM$VAGABeO{>|ov_5s{{kh#l3c$j3tB7E@5S_O`TzeSL^C~XkW8o{wX->tCKSok zKa{Pt^=)L}4wVXRQq|X4o5H$GXq}onuv=9-suzc6D$T7IuMTO&DmOm*R}m72PTS1x zy`0jai{e+Rte13maS3bDp(|Qt5mYBMKoBXb^lS!ipPwDZq4bNo1?@Uh%u`}Z~i z_2W5L?kd+VlgUFK5X~vdlxZlmXq~|n$sYLajIZNo0)p&dQ<7N8!2eQaf!uaVands2nh2V!2$*XE}#+S8E zUt6kg@sr?*2bZh`tK%w{DKmeWvh6cPOC>%D|N3%S` zU*p93HR*%i9ac1YC^{Spm$Ehcpfyk)etA-&hPmn)ZPY((rFT7Jv62YCR*v-vw2e}W zKhJx8P0py-zY{H0tjAx4wn8_cY^>e*9f5kF8(3e*IsknN$td*tPeTXvlIZo!9?uDA z4myaH9n#nCLUMiW;WSe zb~3A1uvnwXonE?VRUE_1CNyuxZ?lk_?d%cG=nOILl_1)?7fb3qpgQVg>?B% z&%rWv9bC?R z{cWM%X0#!(mNuikBYm}r-0nRr$NlYXXq;MDalB`Z=W_nXQSm!Ugk>~{=Ho3bxN;HA z4n2yt0xP-1=MLH@YiTR^ zII4$Fl!?pV$vEfq(sa9Qs)LFJ^jdKT+v38)f{eNnLda<%) zIQj;(39TPLbqpdqVjbFuwKge&w)lE!orPva{$dTwl(OFlm6p!QtymA=JJ!VL8XvT9 zAt$rKH%R<4$SS^8q0IXPLIw6Xa7&d_bFmosGP$!|Xc<_G(IRaddsgQ|(Z;J=SC3;Y zl)onmVgmTaV$DD+rWP9N8z+>+H1bW*>++^6p(KbD@r@?qXZt@tfwmb<)hrWb|K}&M zN^s^)lT>`u(H=zO`_BJH8v2G?TBZK>?;FSD82wxVe&eKQQR$Q@5x-|G5JQy4K!4+c zXiXQON2NrQIwOXSpJP0HtI^c?UXtgek_mBNc{$5aG7GzJJ;c)Ujc0`t2tVHjh{WLA z~upjGn*UH`umPX$W=Ul?1+y)hrW2oz)Z@dbTxW4h4P-Z;zhP3Kx6@Go9?Nue1 zf;*DXhNM;VI)3kn-@H1bVXdGybO+WkU5?ui9n|G${rG)kT+=5BCbNfV`E0n4d5PaP z60q4vv@Vv$V;1W{y>c_!O5?%2hp~p-GXAE_aT;A^Mvl@ z)6Ayj*k{lk=pV*oFPh)R>XuZJ&jtIjFI`(Q`qzjS+$t$M&QC~dttzZbOBCy=aJ^)8 zZNXPmlOk5jN_k~mFA3O^46(I1)uj7ux5NrPtcd!on~cjVCm$EmH%Tp9c-;DQi%=?4 zUr&K-P@1)&|6ne(!?-$NKZ@UkeD>1LMbYUCLh36yr(Y7QjYM-={@!!I&ZwTz@tcKq zK@*Vt{pf)GL+C-F5FhASYGJ83^Nv0^>cbe>hK1C-kk7n}-&1HKHs5wRH6a#~07l`= zEo-bTfH`Oz(<|#HxcWGA+qm3w;03e;(5q-4=%p10SD;N8KZ_r{f%c*CvxsMIpdHj} zQ}+?EXFh_MAGS%T0_|hHHaliJ+LYF@dc=fw*IM5m#2B6VRPRa2?ZG;uhmSW5pnYci z^XG4Wh&F3H_V?c~H}V6-{ovAh4wVt?jyD(zZ4>lC82`?u@VW<-X;D%hJ#{L2THQZ07O+X4FE15U;)Ru%`&A*Jv%Y z3HgnqZ8jeJws)_EaJDmWqXLv=FqdLV0A?gy@Zybm#mE-2`r3T*KOu4!5(&Y)HVE+voIkczP=MJ6KY4B)GN}|-I9gp^vW^s zZCD!}MQwG2TSnoWpBOumtUae>E*kkJ1Bd?aJ^cuj<(OJ58a~5K4`dp z{gSOW1T&1t*^{bXH;yh zuTxKmon4T3F{d?_~mg+}1%+=0KXqDFH(v9ra&dNur_BE!UIjoJA zwv}j4$fvEog;XV3qmNbQ?330OpDEUskZLV0AWCUZN!HlN>Jj3U4eJgy98Zh2LuoZ) zE#r5OvzNr$$ovd($#&LPY0ns?dAG?zA+_4UjUB4K9~(_)c(C3hq)xP=e9B%Hnqy}X zQg8h9dUzh%v&K(fj%h<{kPz=CGo5`-2ER)UOrzZ6N>thvXeEA4#zJX=8mz0jcl~x1 zbj{ZI-gV0F1>=FOkEyaPmfE&(rCl=)rkqz=t5{E|V3JQaci)1&}O4z41GuNXiDqLoqc%>}W!BZC<`k zc447%>oU5SP4PMTy97Irvv`DdT5D7G5{T#Iv(5g`$Q0w4CgZa+#9qxM3HelGo1ZXXrIj|IGf$Zxtlg0&k{y3wBNYC zGoQ=!b8p(bXIIi|p#zK8cbD!_WL#}eW>0!f-V4zYe*sP2yU-b>w6~qEvL01p$eMew zTD5e@R=G=kDdF5ZPS@6D!kR|eVVjR0K-iyqS2Sk@+6YvI_9r8_;4FK?&{3i9s8-#g zYzo>Kl#1VN^=lz{7eTcz7?{70_nAmoN`54!4J6=W$Fs?uQ zb+Sg7ug&b6!xDKu(766$%BN^%(Xv@`&j%R~{QY+?qxl&RyzI^9>ijBs0&(;SG=JlP z`d_O0Eb=7f3;`A<3w+C}a{P4T>Y>L}*#P6}BTHrN@>Gd?J$@@JGc$HN@_eWt-+MaedTB*%!+MR_K zr~7uP2lmgGTXXUQxV#99moLD#1mjm}eEZf3b(R|}wbd)K(5i&AR{Rol--6*0G$-rL z=V*yWXXHl0<-AMJbT+7CY_xe*R}i}A>nxLZDpc<#8P{J*X9}K|EkR&96Dlm(7;C$~ z8?DLGQrxGZZIUeBMrfRGu_kUv89_@iuH}cZu|3~rTtDaAjkZPK9cBtc>$E0@`_-bQ zTBAAxSvSvjTN7g&s?oMu6Ft=5)SmA(sy!25LzAoYo?116{l?_&rpQ@od zf@cQfx+pPW^Iw-$fL|umh&Bn0pzYL4OSK(n(~=QOn9*UoY~BaeUg-R+Hox9EhgPXa z_O3AD_qguNEHt4xYOHZ1s+%36l}BQILddCxqe{xwsNsE*T9j5TR3D1pQ%1|F`c!Ih zqNy%@8jTqpRwFM64dk}m`AgQsc&7?K7o@_k7Gir6RtHr;^;+`gKw7oB+LF9py(9X& zPix6ria6SLuN%eZia6Tp{b(HRyRS(J*>Z~3FSNQ98Wl=w#d=q0C+GX!e+a1w5aFd2 z<(G3F5x&rzSTDp1@d%$sM2OV9hdg*8M@rbTpkl44(MgYAsMKSFwsD`}!lRV!p~Q&c zc>KoOXt$}Q1Z~ddyT6Yh{+>M9@Hl@4=ds3H=n|X6@A(^!|7KzXx5h`bdzaAUS%}B) zvEf?dD;uPVaI`>(Gyk4$bk*O!2t~;4r&j~;3xZamtrMzcJzQhcn|!O-cC1+=RLzRA zM!rh7C7ttKlfL-j-`}efijudHWc0{V;gQu^owMy=q)>LGD=}gw9m=ZCs&Z8<(Vl~M zILq8Dr+-WZX|lw$c=gi zc4TNju=q*%k>e(lr@TXJ`-(;%MT^G2zVwPB`Duvviip)!G@!*TQSr9v@nwoUAaO0$ zMdMn=v1R&2fy^wlhrj)?^op{cl6~zGEo_nySM}}RwP8uS8@)l=gx}rL%mX5*STrtcxsbEi?|@0sqOmgW;u2jB>6Y~lzk-DN{3Vj_#mF5WwBo)0bIHw! zczLOSD=V7&Rv3$_Qe{h`+;%m{5U5JJ%959@<`TI*BARrI@3m$6m+i9fiRLVc^$uFr zRyBOp8CPN>l;$dkcPwf0JI|UWzv?}+6HBKiAN%^lsQ7uyuU=1G9RI}R@lPLB=VV$3 zMGKBx{OhB~s3kJem9oWy6OYVtC9k?8Q^GS+hBUi`vg;&lA|{8SEZ3IAZhu9Ke|?UZ zM|nm?I{mdhUQkwb-q2n;E!tGQXPYcaP*qE2lLVUQUX!yrKxT=_vr=lwj*}quY?FQ& z*`8!FNpV;4w&Z9<)s>|=9YV2D&W->@aWSqfLwhAiy|zSFwIpoG5|VJu9hS^!@@k88 zZAstRD>M@6Dv0*oVlsJ4eYyJzCE-9t2h+=!XkT(rqoV4u+C*u+SQm|ms~L)%B`G}m zp|n%BN=1&Oq_*s3Ep_&*62E=#q|&6HXP1vwuyeVDE59f8E5FWY2{oxterMd|w_MAg z4n3;Kl^qf$=ONY_ulmuY7AzV+-W9RrcQ^IFf4p4c%zNvWN)%OXk&coQuHxwU&SlM9 zwxr3k-lK0Wmw5NE^e%pRp}qG3)sA(;GVg>I4XfviOU9zH*rg7VpbL}Xr9f7?udE69 z-SvBOVp)r>Z&}ieYjN*>MISt|Oe@2`YW)AmS#JFMXWo{LjiLpskJepakTGl{sldn*rtZkmAKv!;ekpzji>CN2k5=o4nCO%^K z=D0|HChMLVS+q^wD`cD<1F~p(2Jcz??i087h!))HDss#EWAaJJaut0`fzy>0C1W9y z(^;}fIskGNM=nvLE2pwvRu0c+?zxIaWgeJ(w(G9qT|5xudF`G|=x7-XpYALgFl{nP zZ%GK351LG70&Or?N|;wV<-K9P5@_aD+4bw+muzJ2G6_BR1r#awUfIxjy_an->PeJ= zG*1M}53Nx*71@h=*T+Ds#2Q5{6PnOY85Hw`#V~%F_$p)-jTalpZAYQ)a*bx5unDbA zf$TyXBs9$vAwsc|%FGj?LcQfsm>k0{)7U%_E_6qBzvhY6LKanDgx1`(k@J``*>eg? zX`j2*o>N#rtK4m(<O1oeG$Fuu`#=ch3X}dnB5~BO@l^7``%G#Oln!32#ve;@!Pe@e4neRMq*yT(cPOA zD)1k!qJ|k6aIbqeoj&HFP0$B&IzPG~#*Zf!@21wi0J(*JIF0oSS8kU&=*RP}B55Sr zmlC!c+Ko|{TmM}1XYek3o2MaymGQw~Bh=`-c@CG1`M_L*g6fU?r?^YxIRj+CXzbVsyo zdn6PonIq(&qF`5XR1}mTi(a@xQH85u$JjCzRZ91_N8)`_I3D0Zo4r>n4V=dzZYJGDg4l4w>7N)#nY^eD;?lY5Gavi;>w;*!=SF|$NA zwjip6`73Kt|5uci?h(0UE$AFt_RB4k!BQm(Hjn^RSw{%{^22McB6*NunOcUvq6wzP zorEb@aVF2p`Tp>pEd1^)p=**dh8ZIBk(-NmzyDL|@nDs3&7(_n_xt}Lt5hV(_4`+K zlPL>&+_WGM1u!ys`8|@_gbLyZ-AlBqBc)sNp32Q6{fR`3hf8P<&12E9{NofoKyZfEc(g(V@#b>+!nF9(maDIMdYV?`XznIY zmlyxUx~Ym@;b?{Gl~JY|KW(6gUNPA%an3A7(m~b;Kf1tfbBh+aL^Z*FS&(IOUE^J` zdKkBJ;_jh&*h7;yhN5{H?^QgThUN){qxsl_?}WCZc^S9f8+a4VY`pi~XO5zI+gE1o zoI~@s2PX{7q4^kpe&hNCT7a}FD;v$%__Oz;N6`Z9!SSO?lUm|`coHqh9#Xk}D}H`< z%{E{{TV=d=VW9=h-}v+F-xJX+c1!$l0a~DFpZTNdwA3Fh!1(h&Jz0omw+E-}aG|Y` zqYY1^g-VIvK8<$AxLxos`Do$x5Jz$x+DhZS#pxSp5ypE@m8-JSs;Y(L$RxY5R+eScnvpJu$b-M1URSUJnILueMew(DRuTAV$2 zD9anoDt+}?jSbAzAnq7K#cRSi9 z_JQCd>heL+if9nF=!d~RU3S!&?4-?vr{2xnbLoI4xp{ETWn_4SG$b&E>+z?TWb%? zvj^a}#~w0WT7(v94{2>x{gO?;sN=4)hm>_&@XN7>l&0n47iAA#JyVL7XAjMB^q@r> zw-0>%U9@}|%Ny^a#mE_T6rdH_gVMvM{8~*Wlbq2%f9SVg$gaz4uKYUC-ut@ggdZ8& zc<=gey49b3+QaH)_VnQwm0Yx2zx>C8{*lmo&9_hbXDRJu z+Oz(xLN-&cGmCuBl}{)2{^%1r9gJ)Nh-Tb5z;S@>($2Pg2;0&w@#7iyzd6 zeij@lWZSo^bS^k+iHc3ZtwJ?kPVa1u#I^X>7yq-+8n3j`ep8rLNNR4)j}$O1)_u0d z9aX4hnHHyhFz=443rmr*eR@I+Ij6>}?%?VeO4N9J?U{t z8GrlEa;ob=BkB1Eqj@dn|H#(;w^NnXm5Wzj|ARX|Th%gPGbM9!&RGAfGr^qzEnMe=qOQ-z%~oUgby%30S`^csgvow554u8)^LW)4z!bOypL| F{{vJ$m_z^o literal 0 HcmV?d00001 diff --git a/bin/_/ram.ram b/bin/_/ram.ram new file mode 100644 index 0000000000000000000000000000000000000000..462530fd15ed4c2f67b947c2ca37628ae46a2863 GIT binary patch literal 30645 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 literal 0 HcmV?d00001 diff --git a/bin/_/salv.rm03 b/bin/_/salv.rm03 new file mode 100644 index 0000000000000000000000000000000000000000..297cc73376c04004472b232f3eb525f30e716708 GIT binary patch literal 57729 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 M)q(%rg2nj%0ei?(z))m<76Di?Y3Sn3QMxg z{r%Rds&gnS-I@Ex?OUIHw9naluf1M-?X}ll=ipzdD2hK_QPMwaxL;9AY7`~Wk7p_` z4nDK#nJDpA+qxt4%pPfH^RJvx6t;6LBm)53#gt}-p2aVmP!v0#*#pUnlErojo0QNP ziT<@{%x4*qXO}i9y#~B2!GM?KEk{G+<^=yFgqm|x9KbA~t$KMDZ8j;ItpHE>OttL^ zY_KgY1t%`L9@sdbDO&J3)wWr8rx@+hig%%#?ndL_nTxJR(ZluF;&ZB!aQ%v+*ou#% zws@AH9=;zXHfG7T@bH}L@lERd?80NXlV&Wb#mCPnigaLGEwEzu($d1;0@95GJG*m< zo>MArY;-OyNr~X>H}`&f>DEmz00dJX0Ja?aKz>YZZ)jM}wO`LKR_x|8BJf1uKH zZM^-xFFKf}?kLifytLS2Me8fb*j_~Z)|NLZ%5LybDNJiBR&0x(xFFB@IW1%H&s60O zDfOOGbftK$rWN0;y!+gAoVMXePE-bLBWt( zu?)FM%~UpAQBx4!Q7}0)Wq4`nruyOhDP?%%R1D@jX2K>|4y8T# z_b(+pf>tensJu0Qw|W87UwLcfl(xLp3klDmRX1Uc0G74^cLR~T;rTjcWaO0UF(B)h zpX$PaIqis!390I_FwrufWXM(V7gp~=_gZ$JAY$(=E!|Qch}^!9%DTwi2dw-;V�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%0A?EtTcK_MD;uKUhA zJeq@Z#*tG-lDOD7WC6-)I8fM6{2meiiqEWxv9oBb>q=V+rNuyxqjPH|2H$~8eI7VD zdQ*AM;lmp0prv*oaE=NNNw3Pm&7<*b-w7883_$n^!6)JLmffxFP#}~YifCd!$S=oI zgeFN}M*t#U%ifJ+J9X(?^NGF9#P0>NP7Q!-{asa#%M($0O6`1!Ll*09t;R#td_-tB zFo?7D)lFXrOxd^Tu4`!wbL-PKY%P^Thy ztxk*MX_qmFhb7e-w~l&I_LZ%vLr6Hg7#GiJ>BB&}f{Wq-;l{IG89Z{H6*_r~#q9G! znaH{9U*Bfl80Sw!%^yL{&0VC*XOos^z>yi%aqdEF3|9tMD02Rp{T|!(rA-dBcM-q! zW)I;ys8pBmEc@f4I>&rzk@LGpV>yF=h=Umqj|w)p0WL2Fzyo=hQ%wyz0{?G(Nl_2v z!}^uhEt3Y>&0c^bm3@Bk;#~G3M4A&r|35CuXFT1|P`{qoHJaWddD|J) z&a5RUp2)}9g1=F7GHA-m#gyH+J7SJpTFxagM+CJKH0BiWQUX@zY{N6$-o^p0u1gnV zA6I#^7DV?qlk&CuyJ=kFc#0NxQWk{+RY;I08tWGG=HgBeHRBA>f+Veu2mFdYJ41d) zPSNcK=QFXC@x=6ytSYb}Iin*1=E$4`=oqo45 zTXVj}T6#J;{VesTxwV`@><)5hG;)3>M>4EED^{C8Z&8Br!JC;60lyF8zV^EXN?u*r z`?p2EMnY8FGkJ+;FZcolRn9fMeF1ppoI`%p=Jxq};=1w@+Ob0B|H_$!yTex$H3zA( zn>VuMvw4Zm3j=`y&588MTX8S4auJm!XxW|TY`-uXDEO6g6Yh?%>L#kn*zmc$OJ^?( z1`6(W!U*1qW1?sd@?1Appk+^9^5qL>0tJ8LM3QeDvvG5lP{q@dxNio|VS`lAo1%CM zdi5BkptmLtm&3YJ;EnU(k_WQ*EAV=hxB^V|lmhQLMK9<}M~}W5RVnC$0Wau}L*ITK zefvErxby-*|2Y5{$dK+(p_$bfXrP9d4n->%m{4L0e9p_~3Vb?%`pN***9@S(UR60g zaCcWR@%veU4+s_vrUUX|86Xcf1M=VmAP>$&Apds&J&8mAf|Esne9{BRCl3SNlji_= zC>@Z8$^d!jFwh;E0J_6OcbMo7*8u2n2Y?O}C=;9IS8ysFP)^kVz^TLNdujqbPRF6g z>7o?n?t|5pj26Z%6r3hPr-#sY1p9ZR?+7_L;z8q)!!Z8*-EOwr=)GT259d1u_0Kvn zOQCOTe|8K;Nz)6pc&F$zYw2^YeK!z47oSGA*=P(kU3<4QmUg1&JKb7*tW4xBGbcNF zniIc@3LEW66pTYC1>95!wRwXIu{ie^BE3GR#Zv1`DZ}uU(u~3|GiH8{b89K02JWVc!@UGQJB*f^iD6F7yPBwvFI<3}69oteDami&hHVjNC@HbC~U-yc200 z_DSNq7S{j80(YbF?aREA_;p(cwD<}S&sMoe^UNiF3(g;14*%m2+K(WO#B`c#SCsh z8qKy?ExtYo|0riMPmQ001fA6J+@EyiL*;LRgnb;mB#?Z+#)ItKpD+I5T>LBC4?7kg zR^uNdetpYz<1J1IryPf0`)n@vowR$k+zF=c&B2$9?_iI9Jj)TcNHpv%KJzxXF12yN ziGL36VeY#)zJco&Rzhhqc2j}xY(AsHO)b;R?h$ahu1!KluciZT6E%{;>|?_nIC9?p8E_&up@7 z;fIi~$>;KX#i=anbMde3+^)qRuSR+YU&Ig$^g^JaF_$o&@e`fm7G1ODP9LipJ#lmN zuipN!YV_EyW4BNky*c{d{_5?j@q?qsZlN%G^KDeih6{b;ucNQdIFLpet*|Z4|6-F$ z{N6*Fg=-)9*GhfXPvW9IiT!me!@o7gxjUXYPRfxOobOhf98NF*Gf73-!uV4r-)YGt z6m}C(2r}{zO_UYNU!$OhK8jqLJC@k@G!C9?>;eVdYHUcoh*9{=@JrWbtZzC2{8re| zw-u>6nqIxoq8?g8lU5tgAk^SE0z?4^E)dkjIYil7aXP6Y9pN4*9ErKWFlUmS_+m@n zstIZVCu;MGVm!U2MR7`8Km~x!$OO`YkE<)P((Z&RBWAH8LwCcFOX#V3yAgUyVz_a| zi~tD!(H}m%Nc{4yEny5C%dE%=XzN@va_GMqp#=Imp~li==a81PQg+K?55z$c`BE}< zEHUA6MTwXKDM_u^1AvNOFWBRm-^$8!r(*CTfW& zY>gs{sKE*4Ss5I)N%>(rl$8Ik5B_5HL9NwBOnV6BRRUnVH>5*?kluhM%QPZ{#>ekG z@j9a+EAA462;iLv8k@sJ>mTshKBz#YqNi*6*@ZT>^1eW+_TWeQVIEGT%vIJ0VpaVz zDyo+ZN%PbK-9l*=guDog1S9yliaeXJB=|1QAoLiX6pVdQv2WR)0&Dha%4x1|E6z)p z&X5*8#A+S>0D$JDZq7tIo`lEVi2bJP3#I55C-M~)SoqB|t{DT3hp6Dsnb;R%S$fN&X6@t4zb8jMkuY~2BmnHHIt9M?B z2pK{N85#1*$ZaxXbt0bX2E^)6O5phq!hV=rnCGw-W)=dVgc4Sm993M=fM7j(#1+Fl z6su)B(3l)w3Sb#i`h-_4^7F3|Kbrp)x3GoC+gym zz8DD&k`u%x-iT1DMJVL17LiN~rWK9=W56pa`hGSsybRpJ4ryB6hT`?!j9B28kh(En zbJa#0_$Dk4HwL->{vC3QMaYzICB&0gvT%GZff=^(6J){d_or*Myz&TYPL>RPAqLms z871U|Cwr?*c21mx-B>1Cl}|HlOG~SEw~WxgO4v-=^fI?n+Aby7`&JdFdabIolV`en z2y^;fECdq$0gI7(7R$A)X=RPFIDyfidNn*pNT`J}03H#S=^Pvbsf4lyNaitIgIM-5 zrLL4`5sps_Sw-&5k#XX;pMBSb?QX(4EQT(mVi~-TUoVss@-CM4A$9&t6Vd3Rj2Icz zN?03NKN60F#h7qpnHa^3%wt|?2nxq7=V%U~+o}X&0gtI?Of`0F-9A`T%xvz2(=wx^ z3GEu!RR>RL5CW%L%fXq{mT&+~JP~&xVP4uH&>Ev4!j8pyRP|s=A{Q9bSwdh5JC1KZ zgk0N5CK>?1HJzVJn3wsB?BN7Dk)a}QP{xS3Z|e=(5S&SJ zW5vk?MG5_avv3VPkgJCo@EV@wo!nS~DH!du(Z(YU+@-H@n|@J((glWu+M>!0o; ze%~kJPg0%vdWb8P2i^>ZCkzseQ-G5221YBU`nsloonuAx4(XK^G|9{My3Yia|S2hS^81lA21s^;nxwK zzVrF1k@t0UXd?8FWJVIHDehjAB+f6%X>zE{iz-PCJd90RM$i@#5m?$COY3 zFLL}X=MYJvDRI61>uCNGjakZ*d5v`B;36DO%nkE35lMEiHmv1-BYzVHf|1{@*kZBM zx)hiV2%C&>{zwkEEV;m7@VQ^sQ^4vVU(N-Q-w$!ckDEL@OBFu-DUyN73@;A#XaYU~I zO<-r(4&Cxk%WV^HS<9VxVqVxX<%`j*HgO3YBzbbL>}#E zb96^-3;zfJ<($matrIwWaNo7?bJhJVtUT_!N(V8Fa0~;`?==xp3gnH-2-mgQzl~^)2mrhmX~szJM$Zw$i2t7ugCj^$RS~q6hAI& zybTI81N3}t=b)Cz%}c&vxxwJXU0`tH3`-tVBt9ZNdK-)oP~vkG6PIx$h61P~0yO2* zRB9!FJ|FI(bFw8KLSKxAF}{Iu#h=OlmLu zEZKt}03krm|2Fay5-)I!*NEf=I3bDm-7cCe6OeqdWA~G|6Fy1)Al!$H(F4XU^1z=+Shw%_nwxD@HJazaNBHr{rd(LMwdb(vn%{#ZybC*8mAF!8%O&;*=8 zOwxLhYHw3Wv`Z*S_F(?qWU(bKUwf!g70lg%rbQKK{ z%w&GcGh7lSUzYK!{6$;}=-3pjV#V<&!L%>qW|qkyVT-`~G{sQABu0P|U#C1DflLaR zA1tA|#E!5{(n@ZQ{aHH?vXe?A=K<|(9Slw}xR>yp*!r;hA*(||Bc7R?q=W{vOXmA# zNqprY@j)n9ViU5t3$oxh6(mQf+{I@(eC9Nt5vx=>MNW2W1b`Y9x5@9pvy2g5m)zR6 z_$zLWlJ-?MCCSdKU`_B0HXI!C05-BR(~??_Z+9+p-*BwI6_}P$QxY05ZkY;S`BE{v zoy5{vz(hB^px!)(6_>T)kWU%%tmcy6L%V_!EGRX~?I6Q%2dS|j^?Ls9x0wi)Gz{#^ zqOh;a!$gkjJD4OXmq|0#C<$3Rf(LM7PHEi{Jo5#k_B`WP+$klUMmk@a3Ok?to-`qw zGH|)%;cYesDyXJZ`N~M*eSEf?M&Le~>%pIfx*ZNQ1K!774HZ8oe)9`|5BzWzUuI;7 z2a%(&0Jk>jK~PzSZ`c40NTE#iz*r~R^{4twP2f`j~)l|ZJGzmSMnJO^w(f^vR_1tk}Fog6Y*2mcC6nvL;P?; z2eLqAa(?AO?b5+CeC_27&~?Sa6HI=OL6+lc--D#I`7B)!JGGVUM?))Lcf44GI5cu8-wL^nC< zZ7?E{dyS;G3Hh56UW9fkHo<zDjY>*Ol@*%D;d+w~ltO%@`OMIBO%^Z#I+9$q( z?A&BMzZcKgcPHFPl ztIxjtAn`l9xf0e)Y5|}Ib`3o+18@|8m{yWZ=WwzgG$;0c%(w9NNv87-b9T#g#*3uM zOhdBeMuiUOMsuKo7fr6omQS2HUgCMn52JH^iaNRnLwMW2%l-vJgE<~g%JN%d^qYByzuJ^A@+m}oH zF8@yRiY(~l4}TByDwY+rx#`n5^TPJjt=`U_LUWv3#gs1oSJi3XuFTI;fT3MEN~%oN zdrPwnUH6!Wn)Y)42%%T$ZWD+j3ol zCQ~mfZLt}C7x9a{=jtqwC6ok3lrf2<83Y+q?tj1(=`LNt1jj{GX5q(p7To_OnVN2A zsS88gu)pXUz4jR@q}yWCT=K6udt(hKn5jv@Af7>zPMSOCR+w$vLjMhZe~;4YHGemsjh;fp&W)=z{*!5C*F@cEoYu-y_VO@5fD zZRWG}0d>yVjvhwEH#r7kBT@l$rH3fQqViztlf>@}=$m{B7SY*40EO_ao$CS`xPgk4 zZecqw?};NRJ|z6lf@*3CNl1BfGfOvnK@rlmoNdTnPCg@^BRmTOjrWPhba|bzOLRUg z6#(yau!3%b`vIDcT!<{T_zEsZ26lD*5fY%BPs`o>)VdCQf-L2LjjCmX1{I;{=YCkY z+zku+=iKiG>~qeiuHBk*U&J%#0l2j8#%mwVxgVr5s-JE}8nl$yMA%7v| zt((t)Hc2E7Jaj)i+#{HkT$ynJfgrzLVP3m!;VtwH*ij0AiMAW-(1c&EOh^OKUBVn< zf0-zk1$w$pJVUsY{Xh&%Ul0ciFCXFLOHgCPex9s4%{zf`_{m+G{Lb{0A)qUB{BM3L&`;05gVwA{+LdcIm; z#Mn}dAJ`xCAH>Cb5bWLAr=_lzmlk^uDjqJ+sjEoaH~dYS`w$ag)S_6&5 zfmhTa8{Kkx`BFN zOI$rQoHg%H-6X4pa3pqHbK_>9>{8r4x1GzMo8153K2Y5UT8roJaUn|tzon%c#fUXL z>cYnZ|KI#RZ?-8jkDg0eZXH zN6@>qwDhv;0l96)-cG6GWd|=+yp-{>kry{FYk5iMWhF0(yu|XN@PZ*GF5}+`q`EHq z)phjPxaztdI~q%k=~a=oq-aV4d&)241b-~r=P#eb7+V1j2HU>)AJCy^Y``}-JmwqF z2gm)R-YI>2!squ+jr&X419M18y%Xmu2M~HwF6F~A(oI#EG2rTk8r#;^c?a}<@5qQg zHGUfqi{17EJWX}IETFKFbiF`O$tEaNxLy`eEh8holirc#V1~!X^nq#r@YqTH)b!-k z@ZfO2cM1=e7?-)jfs7E z?Mdptsuvy6$NhTS23^Pp_Guc2w3|SY+GR2)EkTBiO{hG72Kc2p&31@jC~9*ifX)`` zx<1>4iyrAK3npkwlMr}9pyhr;YqRwF@v*7lv1wmK>(Y`rM!X3bh^H}jtR0>$?CELO zhsX3T@5tTWlRp3M-4VH^tz$PsZc0a=axd{?YCl3k_`nVW6c9jR2fFEl-rl+#GKRqc^9e0DnBfd#7^%35; zvTv^07Zqt=yLEN0qk#B51EQ(6dwf&+^rX+P4-ES!qwt7;>LREt6V$)VCQhaoKgXsX z@~2?7p;T{a(1$0%-eSGO+kcwRWFT=auD^Yx_9f!?J@Ho~lk;1I=Oo*CxS(Xonp4#2 z1Lk-81~x=6^|77BMo^mu(ZlvC2HbAQQXmt_H`!RT$})_QJ~lq3kB(1|!3KwwRl0q; z_*Ta+h~K+ZhEWly34knqN3@B1INRc%%-P3 z5}ffBsllQ5ia4?HIWAm2nk{S?_G57v_YeCZe#6>N40$IxtCSl@7OTz^KfWks%-`$L z!Yd4kqCF%4%A|I(-#0eEMGbnOkBRb%l-k4UXv%{n8^}-B2zj$9l-a_AKL7CGj6OAl zg?nnqr%(8~e1~ZF!mgcI)x16(_@(EBxjXAw5g)JXEra^Z_%xO+-`M&oeG)dXSU(Bf z9P*7!lu9+=&9FWMv^dn!J2s$?kHKP2%6hE#k7GeSiANoYFV2WNQAF9X)iw_p8{>=+d5Wlmek5-iirqS=mI(`-a zMFh}SDh6O}pIsN$(exRDvMkxCNWTwItltnLMVq1h6t-cc32?R{V!pzYB0?LDb{Qsm z`b84B?vtyxzVsOJd(>nd0_es^+#aDga%T&>{g|f&JTQKCOrIQr!VQFME#GVt?=yXW z6uL0uemy)bXQ1w&c1HIJB!LPqQO8nlSHuiCFk-lM(qq{ZY8wk2amqJCH z_a-7CHmZehffcgniwX?pY>92%lT$h{yq=iquxPNt#==&t3x}I9T`g>GXl!llZZxs4 z+*mq;?a0OS%aMuaCz5HVxUu45y2%DMRw{oc{O z5#NBxjV(lNy~$z>lyL{(#SFBeC#}1;SRe4A=kNqpIC-Ft-|h2{cqf#O+J?dX#E+3# znTQ#A6otXv2v1uC9=CyhA2wOOyS*dZ^+*r#S1p!ic3lI8(*@_qa!L$j>_|7f;=as4 zL6zm>QyH6SL3q?@Tf6kN(SJHg{7&+PEPmB1=DesZorwvEz~>vFF`3ct@%hIiR)AVE zOz@UHsDLMP#!c`76ja*R2+$D5Se(MpOw*jPlYF-LjRNnJW1g03;`aqYzV9}WGiD20 z+iM$ivTZ;%(8E|=xpZLJgm$8Y=kzrrDoSH($d@+4PW@}-;9Jc3!O`UFT5DN)qHD_Q zm$jgFV8HL2-=rH}Ap zASlyk18iIvwXi+N=q767u^5)sfQPjWh=?aCQr~WLHOPwey)&yao!&vlt3>LONnb=4 zPC(@LB9Tr%_Kx1+u}Pf>hgT4Qwb&Ek7lr>Ck;=Udypz~5%bw0Y-Nl7yGQ{<>!&5{0 zXNiOHD^3mWXqjHh@k?sVu2Gf+-Wo+sw# zFV7Y>4UY{^4sn^s!aQ4E)jeBy_6|24=gh3G*@~*}16US|XSY;z??oYGZ^fOEB~nC3 z#Yp0SX+%+snqhCR$EsxsVYffz&(VLPk;jq}5+b)kVYEX)VaW+^1L3VB$%c}Gg_-4L z$x2=v@w0qYl{?}~yzql__Jde9+x6LH4!fLva#6@M@*qv1*!dZrCNUc%BWZkR*O>@f z9F^tx?ID9@Q84jqzj6NYTf)CXrd<*IXttR8V*eIG9LCD96Id4Ok@2w?1k$3k5ylG6 z5*iSzXbeOKj=_jd>eCYgh?zkV#Zfi-l67K7E%pM6mq~wEJG^RSZEY?2$G0l*##iW# zL;IlNpMrMT{fOz%!xJcT2T4t`XdfrA)JCK~$0n9dWWM(vR|>Rr`Mig>73n5nbUV?# z7y++-a{k@F&m(?(u^QPxF#wu20Hwtwbsv+DE{8q*%!kk<7Qrky2v+kl+Y#|0pj^{U-rK9#w_?l7Xi?Cw&?}W97WWkzb zy%_0hxP}lsf}K+m6?CdS! z7C7Lc@J$3Y8@QI`ByECF#1t4o2b`e8d|4(=#g5rK%4XYVcj+KEte9xR(Il*DiM%4b zB(qX>orp)!x!e`snTEe6crj}OeAZd!hv7>D^mvJe1Xwdn#)kaT$c_vPy5Y)4D5s;6 zl};o-w>uC|v=#G09zw-G~ypdm!uXK zmshUrB7PDf%QO+^82udM^`e%xmhP6?R{dyWXZr?2M(n$lSXs82n2Ok!gq+$*>>{iK zZ6i-D9yz(ezbX>@x(?6C429|qrXnY!uMIY90L~7u{*4C_2nJS+3!1xB;G!$7E z2yeLyV|Td7Y5b?B0jIh{Zc!(drI~&_ybf~kX zyRoFBwYI*oq`AGdp|MlC8jRS|nR1q&QOSCWf_j1jS$qsa=^#Q+6m{3`Ybss6E z_jQpJ3o*~Kn`MWIxo(*YqLYV7uVwzu7Vh3H9yk`w1|6pgVR&JpvtALPH`agjy@!e4 zcTDopvku<8prRL`b9gk8AYQEHETd>|&;AY=pwNMfti)uP5m7aP7Ip1wiE1a4Se9Ok zDTptke;1MEox`<$zGsy63j&oeyhRETF_H(Lvtck_AvTFkB=+w|u}Kal5#NYzC+?$# zokfOjhnYxR&Xa#O`^d(=ZsK>-oEl&lA`pm+ice}VUoa&Gx1tmsjnQ&a_j&yzGgd)i zjBNR1LKeYaM?}URF;C*dQaB;(*&{AWRnBG==j*^P8+)|nE=y>+3`Nt(AuizA8N|-!F@*-FfsJNzPDw1`RmdoNpDfnl z_m~~dPqwMQ;rf={6OA9dO3SW{@Op^a^4)VbU!Jw1hRN>ObOmCBr{CFJUJiy~E81Dx zSghA~Rp^+lk)t|%>JdPFQS{;jT`8X}1otPW`-k)^e^Y)BcbD0d0?6<~>BU8+hCq=| zd0Lh%3V;C=+uCa_zy*yR^4T39OS@4KXOmCeNQpRqhvx^t6k+mFgwDCuE!87qa3*Kh zQ}vR}8P72qZ|$i)O#daDudCoy$625s0yREC5)f3L#OalQBE4TGy~{&K*^gQK@}xhq z%>+6VBe*r#cn)D|(>Kfh8WCE)ret>s(IE`bUfH>0Acy$9;0JAEgE-RyafcXEuje_A z&U1pg=}A2tbpV^aC$T1D6Bfbw8yv{8*+fM)1FH1;gljm+8Jh%hq1dh&vI|2I^(GU0 zNq(Nm#A`4A(cb5YAH4z!KpZM806lG8wM~tdtzc;W{+PH}oub0V`g+}%`f_j)j;WhV z0>>R;Hwnu|5+kz5MOyf@zOr&>oEEo=7!1fU%M@gXqnb%y|GnF*QG-pmf@Wz&A80^NZ-vwG{anu*f&#V&}{+G&YA$A3pr~| z0H6NVjyQfrC8rTaKw{51wH8pdNQjVe$yXYh9PyJZ+gfno95~e3ToSf*{Zk|Q4$E^9OAi&kRfei zbr&g;P>ZqOpc5Keyb#9VuI}z(|I{>cb|jQOraCe}X#6I)&-yPvvQ z^fk%iPAjLLxU4hn1a|ec;FPtUjJB8U9M*Qr)aSychH|IXuY_d}t9O z&fGxev=L|7*BShyN*w^@aqUI${AMf4!pR#lzu2RPJz~spFGnX$Azi$iwD9e|kWC^R}o5W@h276|N$`X#dMR1XGO3ONb%??pq;l=Dr z^DdgE>qT;wCktG}pfr?*Ha1ZPq{KFSfwAYDw@LI#673?<;Q&U%xN%JEh33LTnq<5T zC&tvcp0<{{o~{Vbp}1k;k;-=n%98UzUHbqW*A6%EFi%G`95V<#>Zkl8dSU2Zmsf2p z&o)$~l`t);`!IN2cW{tlbNmcdU>~DYfzlo-Z)am|!x8+eC>`yc-6dT(F{_7& z6{VrG+qLPkUY>1AONcxbXa1M1fHFk#X zyE+={u~#gqZ*ObBu5n=SGW44WL3@yBoV?G&Jh&Y;SEv@A}rp+D?wv)zaEt z($dz^(_Iq5Ql7Qe?wYR|uIJb0lH8zxlkt1NGqqBWaXYKwl;v%0tZuSDt1x}4z{=U>~AbNSlik{2!`Au3^Q&!Ivcwh+ra78+Aa#YzPr7%BE_wX21tcSKT1ouEe`V@0NY7t zL*u~~1QXEl>R%qU^K5nPH$)Dt?GRL5OLqvQ+!~2_m>`Cz!q|iU{UPlEl8v3U6mCar zkD!fFx*8kzL3CtO1aa*8L#PP4&CvHS8(Z3%(`N1%|9h zsL}+rfsS?5LQ_i)8QR#;(nTv+($fJ3msA+-IG3Q*(7d*=i44y|nut9mA;6rQ+hWgl z@l~x{hs;uANhqo91a}RALDL#x*aR}Av%hhFiD(go+16pqR%KsTdD(5PT-)IiLzSS@ zFqa2P>N>0Nf3TYAmUZz@(%{bBZJad<>1nf4-PUR z%i{kqOpz;b)cCR10S7-hpIdKw8p}StYU9~)uJKh^gonk`0?;CH^BA;(!w6R&nq@ls zCX!H#T=B%09elJQ^5{DUM~RENxT9uY_9&(z8DW6&6C<@}h@V&7XZrmi535!-zPhZt zA==otoP90JK6=1LcW+1f3if_v#~8UGyHdory(7bY$a0rtLo0^}O1#w#CSMQ=Hd4r$ zQ5ZV$8S-B$;y2xM??aBIIjeHdN1@S;<6=4Kc*4Gy&Ndh zq>|$Pn)pe~j0T}&i!}4jyx7|C7Go+DQ7+i1^_RESV?G@@WS`^^GyKLED_#!NL%`H z+FqCa#%y676bT2g!Z88Dcuaq2OFUVMA8p2_zO%O`ppX8 z^UYlh^$ooef$%yGSU@q-Nxda!m-6z1;ODp}NX$i6#qS1FUfau+Yb_LWnHR z{3Ot($4a-4y~lsc&*bQ9EC9@0Rj5dKWJ|n5mt%d)6vkdj=RrG@8fE(f?E(&*%;D$; zH$8gMY}bZjy|$m*(8vP{F(Nuqyd)xNlglSd`yYIh_-&ERQFw=>7f{2uaGz>yL)h37 z^w4ARsbFFyf7dGdrEfVN<|^NBq<@7YFO%W7S8xn|aY~KcR zsteInfqwR|?6(8IUmbig+@K7DdX_m3mN z9`nFRUc#jCngJetoRD2+Jb*mqH!B$6=|U`A4B0T#jE%5@#lq_MMOj#}Rc(?#ZERs7 z_^acyql``J4+*cp;#P$eU5uiL>AE~;)G?O45rBh_sd2C^q&ah~Jmu2A%x>1XAV?yH zH!d+d16^j~@#O%)JsNRJtDT5%5~8Pf)sFKcX8Q9Y-)Isj56}`yM;7dH+}z5rgnm$P zAr!*^MM$_EIw6|28$^Yaf$*43uHQ*e%VsEfPdInGrZpz6>90oSoOT?-8p{I@89D31-ST4C*y536R^-W7AJ%sIM!gfl zu>SFh8ETotL7EznKpCDQnCk{8@Gox_K}klF5tK#_h1C(c@|`nZnInD$ztbg&V3k5f zSdPev)oQ5iidU3Me62TgH7po@-8IkHpyDoCgvf!d3 zuZLy{Y3iMv?RbZ98hO3@k8N~Si+oQY1RQyl2##O`zfyu)w#FNYQx+M?ZY^rG;m~qd zPca)uQnv+PLy9cPGjMB|m=wm~6ZKnzHuCQR*}jvwEVKOBOpbrfvgXaPon<)*gS6m$ zF^WU5KEyOUzwv^MMW36Aq-9)wp0}}KdSYa_erz_8e^5E^3B1Z_96_0^+s|$mzJwPl zjKa4mCQHK^VWjN<5wf_;)XwlpRa5vKFRO>1_l+njXA3{i4PS5bfRFfnlauM?&-DM?RoV%JGJHR-D;}23S_V zyq^%4w9&zlI_}Q%er8eXzfds|H;)2JLrG|GF6G?x<-N^rmQ#7r)9^x{8J$tL>|Dl* zM?}4+KBs>@W1@h9@#JDs&%+Gv<}H}^Dbja_xL8hEqI8#1m7FSz=7jhnHaIMOkd-f| z{L59vKhCW0h$YOIw^S{lfJT0jCuf75{&PM*!A19yY%l5K?m~DUHl@HNKZ)orx61j6 zP&1rOT07JWuu)gH)=8&nT^Ufg) zLcHo49?AKdUnP3&NW4H0z~|44OyB(V>}rt-$>oWMZEcx?KRts_#wM=Sk%Fh<%do{t z5UggdUt%8q41J=Jj=smBkJr(2gtt5VlPU};jV=m!IimFAUurD7u>z#p{kC$hraYixX8#~E-ae$aK z6;Z6Ku_AP(uPJCDeh)&5ayFPhA7XB|cf!Zx^eI15v~iwvcASBO{t+a(m@M8yiY$u@ zrNfje$(1Ak98^f?M|6-AMbf7%LV-WPb`eA4_npO&aCjem#OAs?k@!8wzE5+s<=e7+ z;pK*+TqYpD9-b=3 zJMtu5kTA?+m|+F+oQM`bgnb<$hBdZ#N7}8S^erA(PUilW^{Fe{@^$$D$F;&geZ2+y zXXK1BadzpAAI@|6Ey%;P4v7crXksJQ(ZmN?YJy4?NQS*6Y#6(B`9>&aR8o83yZ9(x zem-;v-}$T|F_+3E@HolDqp(m4iqj z*3S2`by8w|NRhEu7u>~eL39Nh$$m=;;JimsKD+;G7k)zQ?qb)*`BRCtSYe?8t;h}} z`4M$5I3Z@#B*JLNln|faO17NNTC4}5i8c&L(}yTd?e% z*$pCK$v`tdX+W&_hGtl?1uK~$5%I`NsYZBt-QNC+bHwlC2!40V7(sjzQI(G}q9XY< z`OqppEbENF-G^4$v%tG^dR0847D{!yF~d~JXm9z z!(F#_;AdI{d^i~DmSE`ed{+1BPwJ+A&R3G%#ur0E`#;$V4PiUY+#*b5%kI)t6^5_e zVscX~o?9dzld?5llz>XPWzV|Yl(==_P{@{=${1!WyX|RD@41jd{A3qt;SgwZ8!4)x z8PCHgna@0oibR(Tbi15xtB6BOB`5J%3abOd1NG(z#t__-uQXwH@78rL z58PoOmUsECJ=*p$arkNk!w7 zR938FI~+vk4k6zocWCR??-e%N=KVz=PV?~6ij=G0j@aan;w&xwPX)1*-zsW-#id^5 z+W)nqC9NJPD|fYB+V7DsrQP`WKc#=@=uYTsncbTL|I}49vv29szgBFA>{UYmh2M>j zeqMMIosfoeXj{5iEBg&!^A|55y-O{>apjRikDx9_IaHUw?-)vPEHzG{l)}>4E|heX z3U;BOcog*b(q(kT2S~0wvil+63=__Aui#nM>LPEphtG1>v^w4Rc9^Q%;o9dv1qwA~ z?Mh$OUA-*jUF&u1eTSvORf^L+#CGi{?Z!(^nzG^ASD!fZI!nXXzWVqdXR-FJ)&9XG zAfPED*S`AI#`7#qto9!o%w=hM<-UwlMQr!cYQOJ{v^$F)E)Snw#j{I-%f~2X$g>5M zj_d4u{@Pdn@*gg<-6Ebe0OvJ}T>>rgsNDC%mIR!J$1 zC1hS`Y8Fd(vXq0;fQO|#lzb`dy9cG=7?xUCE2FJv>0Y+m$aZelo&X)TUOuZpDMrQ} z{(qV}^XRt9G|gX0mSo{gmhP4JMBWl7j$_A;m&BVKd6BJn*AgdoY{&Z+%XXa2b|{9) zp#wt!CqRY*iVk#!f}B(hBoq~>nvkYB=^~W@D#M|xDTeN$D2mOPOQotyb!g^!zN_?% z{_*cT@B4oD{r2x(NfxXdBx+Uie0h{8xlQR@XBuI|GwLOe@eR^Bxu-rPk)D(1_idRZ zokuC9qP!kZSu{)8E6+Eb5LbJdgrfDje)WmxZ%&a0<@rEVA7gLI^EEU4ZDSq!qh_xkdI;oj$6LHau(5H|% zBJ|lHi}1^}wT;6KezM#Qk=M9{XfuSn#wMczM~;G@>l z-L#K~y(lcX-n4G7AkHX^&WP5zhOwrzWi0B@y7(8#>WepSo}p&2ZJ$CYG`)JJ^(Wh? z8Rba}XL=N@6^SE9shRCd-779?QML-3XDc-etcS5ZM@h!+P;n~Wqs6PMzM>TWoE+pY zP1mQ3PkR_kdqY?clCd(BZ^QD!SFn6@{-~hvm%pBQ>pwJYwdm@vU@h_LRyG{M7{Z(n zmTz4ezD?@~1a&KUXi{4J-O^#qu9WUK3BUJ1 z`7T-yf^watIYiV6It21@cI!VURnd9`e)Xc1ua)ZEV%F+!fl6gsmq`j~g;vo=eP*N9Qnt4(7KLypNUc9P#O`#IXZVXk=zqykcA~T> zlqdWOq2UAjlCrzMDKF%TP*n(ymmE~JQINeK% zFT){)+CXyVG|KCUP*n)~j?g+n*r@~!hXNo+dAey!XpbP%_@2;SLB<$s2y2%lZ_01L z&mB=SWaVt(+A689y^}LL=LFgNn|4*rQvXAQ$zgYwb`s<<- z6s#WFD}A-B`yL1O00eZ*WH)};ny-Lie;Jz_ZtmJ5>|S_<*E0WfL!(db`A@$PBsNY# zzEHA(jSN3nAJXW{H!rUU^6wATYvqN1^iNgT5b^TQ#u<2=5ay3;Lz<1hM%t+iTG_!NzgRT?x;@%$%gJ(HL^p)fg-{hpDzpQOtq#h4$`r!5=VC&%!K|OZv zP__v2ue4Wh(`ZMxIa*Lx-(Z^->#wZ6T?*Rjvaklri&u9D@|i36J3n}JA80QYAo+J3 zsK=BRi%Ld*mLT>~m7ws$uUvdfqcd&q->;E+>4BRXty%ld3ktgGi?Bg((q^X*XAA1` zG@O{zw3UJ69hzUuct|HG{MGzJ=QL|sTaHJNZ)e4AKkMok79^2XddE6J-9yenSx{KL z_;H;eTP!{ctNFQVc2o%R*~;1?HF7)RokH_3=WiGg6n^cGe|kiVaQk*e%3E7ErPVFi zGG3-Ftp3Sr9xaeTpaDNtuSK}3_HKuS|GzxgT_pNLhraZRHq|k9QdoU??a4f@A=a>1 z-Yh8Ss;L~-sAXam+Yzkc*TQT3EH7v+tNVUIU7i&amoiD`>o-he0|NzJndzbjb^hGt z5s%QqS3=2RgV5P>u$c?Zx3hJIixA2?^{-n`3JRhP#JJ~j8jHgrPNz1GAVIwDlY;!q zn-7T=GWdG?hAK6yda2+AL71!iwAk?4y7(JH!=k)fw4cG(*k4?u`L#@>X@2;0_vE-% z%4=WTx>F2L(@Z7l056UNTLQiDs7KVw_s2`xaqR8cM{(C)u|F;`W#SR(Wo zB%?<)Ygf9JfPc2X_Th~Stgg}T91flkgoo-4VhS34JF|^qAQ}S=Q=?8{wH-uhg2MNu z{P?6sYwPr)1C8j)LQP|S0*Ex!d*3^UkYpZ)oC_ZXrWxaJF*|boS}jrDxOQX9}^m;R&9btZbt=o zfB3Ck|MV%1Ub}UrR3r7`XZHzG4o&ed{Co@eMuQ-f7caJysPL)xyCT+abilADCK3_+^{b-QP|8Gt z=#gmlWksZv+NNA)n%Fs5g+nu57XQj*g{ZG3{QZCV=$z0{qh3)Xd%!SsT$B=ro~f`g zRzX(JnMp}#p>IS)tXjEjoMUV(uUkZG3QBqFf}q6l-qhV14O@?iIk-x{GHPjw!`9xx7RWa(+M@U#!7~)C}|k{ICTKi_OZap8c;ci^CeUK$ciqt>Lv_HNB_# zxiYh2~JtK6SsKB*qpqq7Z)L{iJQs@*?D}9ZR5A5`K8}^>+bMYB>1I zKYS;MYe@qs9T8@+PVPV{O}InES4>H>q)J*hkZOZ&Uu!Hta$>xA#jJH=Bu}Q}CGtjWV?n;ledOF=!eN58^h@g^17Yk7#4l zqNkyKc2XQXT>jR=!Ck@{UiLkCRdyFj!Kdj>qX|(oPN>W6-_&YY6PC~z}vh7LZo7mGJZ`G1lBlKXqM(&o@fFQqV zKynE}U*_`ws!I$Q9T5s&_2z#>t3~a9CPMU^r=OjE8o^rp0{!9;@&9NWR|}njHBmn% z2G^< zT2E~owae5}NH0(;p;gp3mD;~jD<%DgerdE$Q!DRo&S!d(&Z*7^Qbfs4d-IkpqU1Vz zbN+IO)=W?*Z&-A0l4zkUP>?ISu7OlXzigC}$JIyI1Z|9W-?|)>=iN`Onb&xPTCO_p z|LQJkURVq8WJJXa$Myfa*4qcr4bnBet8TFI^s20nQ%XAzxpdPt@{w&|96s zGBX?lPs#(|G{O!vcsfqj)9%9wA2Ty(+@$;py&-Iv>AD`je zLdo9DcCH(Ge9^QtmV39}fz!xqeaO%7o!_!9oo#CP4%aPZDN%_1e4$(;_2L&FMzmk0 zaE9W^HRdYU1CY0>ifc}kq!|17p%TWb)_>wWC%yd=dxqtGw!|4vx*p3_6tVcWo?VbH zr^bC0WZL2{TXr8sE~cLDlFIr8LCEU#4Oq?0Y7{3dJ~4ND>zP3`v|ptw8mSk5_iBXR zew^2(^|PY;Zd<=NBM8}B*)FtRA9+L5JorVch;_WYQzLKXU{^#NoA!Y4e79Ekc)0a~*=8C)=j^`AweLkfyl#!f9?=5OR5sZHn?<{pQ}2po*P1 zX&vWzx8ew{A?_wzD8(6C2dfMDeRldQK|ybA5=T3=&wm(<(61UF*9iAkFWsj5BeZtC z=SiVq6uS#Ga<}**C1by2tKn*%tYKykYDi6u5cWZyl|8k-&Q>?~vd~fgaEze2#_)gs zQS%5Uqr`}fxTz$0Gj}5v#8KCvX*e?&G;+68)@y_lXpZK$cKrj4D-n^n4|NlC@e@V! zbNgc=e(I(BBc*t2%Fw#>TYK}HcO!m*P3B1KrPB8_`t(m}XkA^R6#o2Azeiu{vLwGH zrvp2pZntFXj^TXMbzp3?R^HFajqII=Fg65L@59&yh1JA;nx?e$7NH5CDcpK53n z+Ke)A#&m3d2zpeps}Cr6U#cNgAgh#FvdyKLj#8a0B9*aYdQr+ArDk821gjwtPpQjuNh#`ugFhQ1W#IX@ z6iv#Mdm2iTN%`_7$2!bky}{uynq0zK0CEd!ff83Xmq%;T?RP&6h0t6$kLwM|pvn+S z*#_E$JxXUNQR2#rJ4mIrR(*|!RPKnjwP9@NkpcQm_*L3Im>Z+C4$wodYGrDHzhi_C zusaSLvha{bXK1i*^)x!EWveg#!{RTgHQ78pT;BAC9Q*$9X10Z)lZ11J&M-(?CXIo- ztMtP=A3dFT{G&6>k=SO2BP8s7dP5CKWV}Keru9Bv7k8ofaS^3@U^tu9LBdL+H+0(M zx4F)Qxy#exPQX5jI&c7@Cu8}ZP^@ed; zagU`lyr=g3`cXf%S=(4{ijmrf&>o8+eN4?n`kWeeef<6dDUS3tt!C1n(cXtdeZM8K zzS!qL9VD|{S+^4pJ9SYRqylO-key>G%C3I@Urt}8bra~{&yosZJ<&-jq4o@^lp1Gh zREB!-dO`-ZN~J4ziaAF$fF_U8nya*z@v}tws0~W6=uiW#?W7&l@<9tbsSPT-XPhFd z3H4&x-(m;VMa|H0(S@LQmDk+F43V4zV%+^2L-SdY^0A(FUm3#=gw7(K2A64yPe z1pJxf^gBnIptYMN3+s7X|Au1R<>{h+LfS;@K8Iz~ zSg3YA5k}E^V-fvk7%^dM*>PN0UFx1ih2zgyM`|K9!B4?npf`Ht{H0>-rFvtFdhfU5 zeN^Kk)DE(g$5HcyXwsAR4N2Wqq;n+BE#tE!jz8lbv{l0E)Lww*!G#@&7$Va{utK-<4w>~H6vzNqa14QlLl_n(hRM$ z^us->-WXD5$E?R_{TQ_Bp>~|q3(cfcU;XC6-;gZO4zaCFiO~M|KKwL|H8&-(6qanV zGeTGu(g)NWwDM}2-yA6gnxmevCGdNcv({8g%}8se`t;GEx2U<*dwcJGi&~DnsiIr> zHG{fVsO2k`xm=vzb*4Uf(~bs?Khrk#>W@FUlT@snnCJ?TN*tyG-MC}YnI=F!wx8(; zDV_8XsfcvOVVV=8(}cbZ9pqRub(1)TOwWR5IZjPiK_QL<(*eW=b4f$$)fa-@wEogz zI>9%$^d|J%fq;|R4Ma>DNN#?5imaA47!6O;|PJ9s)U7m%t+rApbJ zmIYcfl(Ok`uGHpQrQF~X*uD5^7e!`RQpHE#h8ap;=+ zm9kJfj$?Xrky5rY%SJN~suzCN&gIIy4YWI-+K@b5xL2fH4C=vyb)9*{QErY;CXIn& z*tq8H%J#!X4sj$}dmu_gR4chhY#h$!yOd1HfSV7!*{y8kWkC%}di()A#?qPZQ*!pZ zxbU03O2!ea2B0n_<5-Mnf{W_&(d(wD?NjoSW`$obi5sH%Drk<=$b6U@r?2^IWkYpR z6e!xLTWf)bbo0J0(c5uqJ1qQW?Aua1MJhYg>DEr%*XyG1BAupR9qBTuiGF>gW@ugSklLa7 z@tjW=eGa2wl${m*6D4rKJVLsxzVw3mI_WC3c=VAT83Yc`M-n#H1C+1M3>2#ZNs_Sm@hS(0eAQ%g`vQ*t;WEgMPPQ7pM6H??k3CADG_ zo8D3)R|H}>?<^A}4{1s%o9vz--KAc5srx4V+@KC-YH23111)DrgQUkur)cd!te6v) z7pUQRhtBdc=-y{&?Sr+WhqRy8-;jo=&C>50v`!uAEtbOJXSu1A9ZlOydRHlr$!E`4 zrjcpvHc|*Diw)fMEq}q<_|wy%I}BJGv$^`+VF#6P1-l~!){AMRG-_PS?#Li<Pa@mmzv56dPlzcQe5iSqynY2aF?0ZO!Z>$6<#+k3);>UTK&{YsO8(O8KUj)=p(W1 z;|fu-m}GYxK?eVaHIJ*JR>;_6_>4psd+Uyq>W%-|HAlJ!pTn5vM2TxsFKkffNFJqh zb?YLnXGr6umq`<}V%cc?@l9&)P~((|3z4R%eM{?mr0=M4=ZVod4(nx3^B6tO(HSmS zV^Y*34_&*9#FHMj2UrtGc_an2pP9zg%I=uyY-&#R!8g9>q*e#(i4JPnwpLTy012Ok z%8?~nyKSu-;sy2CTJxes$=l%9AtK6@6}i{Nhzd|Y7pa&kEN0QMj74i4j!ULi4>Gfl zVj64{@jg*XqitxfM`VA7#6>jbN!vui0p1zJJO#f4?CF@ZpaF4>PSEH8wda(npjDLO zXDs)xn0=sT?piUI)jeOf{DoRSw3ZcWS3#{JmmzB0;bX4R?*sacQsWLE^A5H5N$*nQ z$c}kmeeG6iAL&DfVd5VdaL8epOx;ZBOGv*ZdLzjiu0HQ*2|CHals(+H=ch zA#DQ1T_hF2x{CclADcq$C2Hl2;MpK{9W|aXVx5fTsu7#1wAL1Lt%%*IUhIESl(&zX zh$y5M!&3UG@!mGJSeXpWFc549!RO0O}2 zS`Da*_f@egYX8#fcTuagtsL9Q@eq5b(!Q;Fh?+~i*Eqq^7kihS7n8<)JGKtmAXiPVaNNXtlu6%VZsxHMDU*AL z1w8^96RoyeedWTKXtk%5QYUsVM06;nS&7>j@f^uRI#24QH7M_z-okYz_GM53&mXb- zNpYk>TDe!nUXv^1k5rL-H$)z1 z?-(LR*&A_7%6QHJkzb8^_^Ic)zOL5V_ttI}8Mttb!voZIk%~$6%5coC9>$&{iLB14 zmyLgak=B6v%FRD=2(Nj!%^9GwX%b zs(!!zm>;q6)$$Jg9z6Hc$2;X6md)H9;@yZ?VtwPYNZf7W+tu$omr6+8a(C;&jkInh z@p(af1&L3l;w#mMf4}M`Rg-u>8DC3lF3GK&7+>JCf%sGEl}oR1C5wLm^wK+|CrMoU z;=4dECsMnp4*%Uw;dj|?^N8mF@%yRmqxBlKt)yQn8TnQHjAdI{j*;eU4bDw2T0fE} z^?WX=kDs>(>ua6VcrVq02Vwg71@+m!$y?MuQ8IQ;ayN|soZ3gA1S9EF_$5Tqx=76e zQrMCSW>P6B27byEt=ZJ@UbQYEAN^6_q&3yHv$1-dTB)P#XfrcNsI?uA+ayZK#51Zx zT>lfA{H2ZcTxSxRmC}~@fe5wn!+!b%oT%FPkuqI^S1BEv;_8yHLC%iV{91k4(OPV) zoNd)2Hj+d{yPUmAi^#KeSS7YgLZ@wUpnHI&6skV+w`}o*2S_`pwb{I}@&dK9wzh#o z3)DK*uEd&?)Shv)W%r5fyOhciLDocja@-NF-PTSybDNz#ZGA?)nH%_uT9`GhcaA3O0Yn6OmbBgkwX-Fy?~;~D zzX736@WWHI(T*HyUy(Swt>2K?R@UQq?pDGYS^tcZ|AA{>qQT}FpY}mZOi;VFPd`U3 z!RDFB=I)W03+)*TH4L?hY_7VAGBxgLiK)<9(&*YL zS2-daMm*6=;vKicfF~vYzKNPy-npyPNi9lQnJnc9b6D)jt2+j$8I@^!K%y2SJH`Jq z(mPCcd1gDunj=n`n)PvhILvly+EP8W1Y6_sQa!b3+l1A~_0*9F%Hgh$l52Jk9;asK zJwPJ0ILz9Qo~5R!|Lci`XQ{>TgvL7)2cJJUcyHv0MN`J6QcFR^<&)G_@f^j^G3iLN z8#3^l>d@kC`3r8IryUteyCZ>Xu_FPe*#|i`9P9CfruHpTzq}=TI*QgJ*_mC}OKs5B zS6M4sW1IRn*HbvV9Ya_*;y$Kdu{~vRAIFAcMDFotRZuIjDfP2lRUBjLz3)tlthS@P zYLV3ho>NSu)2|dy7r&QFzbW;<{o($&-axUXMHhn*}K9J{CYOgA-H6HF|Ir~B4l#}xdxyo`PM6KWE zY471I%b8Vw^h(w#P@bgz=(Oz=V)JzJV($X?lr2(Mcihq;L2}@?wIjnWif(&de+0(3+Ul$^^6+X0I-jqA4Zon>@Z z@?q3%)oBfSGF_z2{-C$g2S3yE-`VPm?eqLTT2WVhaW^^>Ur)2um&9ZE2`WB_Z3f?E zQ#(@*en~2U)qy1&-(U+?4;PJb7~u2m#j6EUEGYch+s|ic^u-Sxtr6|=Bj>n$OW`jb z8-7Yc*-|inecpl~XwRLO(xEB3{VkH@q~E7|63=P$+UIBPl+X|O6#w3#ZPIp7QgUav zQ*sIISmPGS0}7_hrqxSWLZqa$g?6W)@E1RjGom>gf_auoQ#8g2@{78B_t(&LpjY3I zc7b5s5lzj22>T7IR*%b1-m;3EKi!jZ%j!g|qp`Ym*@_5~SF#R(0tSCnosId0zj*!M znq^LhfMIS*N)@rV+6^Z&2pA@n%{gqVfT8DbI_|njixnGlT%;&N?NLFi&O@nxcbVcH>WWsT$> z?;)v(SK~Ji+BJIZyU(kO*apGe!lJPvim2QEP#OD|^~kJnYP6&N&$sIqqNX!!nQ@HW R6OyD7WBv@j&4kJLe*q9AVgLXD literal 0 HcmV?d00001 diff --git a/bin/_/salv.rp06 b/bin/_/salv.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..b8c0ecfb6a1bf8153314184f1e6c448a823b83b0 GIT binary patch literal 58501 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 literal 0 HcmV?d00001 diff --git a/bin/_/salv.rp07 b/bin/_/salv.rp07 new file mode 100644 index 0000000000000000000000000000000000000000..d21701793703515498d6a4843de322afd72831ab GIT binary patch literal 58452 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 literal 0 HcmV?d00001 diff --git a/bin/boot/dskdmp.rp06 b/bin/boot/dskdmp.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..e3fda3b666500b835fba5fa7f3baee600f1a8647 GIT binary patch literal 32975 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½Q$ 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

=>rPW+?O^Uo2j zR_Qm-2NTGZ-hPE8$e(`m*|4Bc`pqZeM4xKuH-DQeNKe1{lLwT8t088OYi;EQ7SQPM}QcQmJQ-dTS*-7H=+y z(EIo_f(Sl@4=jk_r}$=q2>y)EIf!VXb&?N0iH|)%qo3k{6KD*jY+%_(S=$EYdz582 z1b{}6yOAZHAa|oTXYXOjx6zlg_lu8(7RcKALxG@RPW2EQg)$qh1qok3;MZIZ4;Q4@ ze>u9z$lCIv&2{AL#b9DSXC&`8Hge_cO?DBQ8)yhM*aUPim9)>CKuMy_KqtWDmk9V0 zHBAueI1porE&i;%X@6mRw>s-@{%!SSS9b2md|UnXcLldOBERbZ5?<7Yz%3=(j{9nV zyIznJXow)(b^F^0T5^XDG@SjhgIsCb4j;L!cSk5|dwEZm*l7UWLrd;-5edx%>LWA{ z(0wei(?=S)yY$RY`5`%wD{b(qLP4Ii!5e;|N9@8Ep{q`iR^^Di{s8wbc#j=Dckg7% z+pUNwZ+C!*n(i@jyzdHak4Z$@UX6$)_PU5@p}qb#!H(7BR;xC_&d*XxwGP^!1UcFS z|8SCCSM6dxmaP_fLi4l<{wYi;)!sJ2Tc*=4)s&YiWrJ;kovx?keTucwPxooyK27dE z)Y0h!p*b*;#cKOd$DdxN6r$UIfp_40;QFtq_o24i9$;AAY$45sN=R8di#E~Y}Qh58+!R?=?=5D&7X zw+=AoNN**{eT*fNUZ8#~k@Nu-6CK2N!&${_`60!>jzMPJPn4=coKoIpc`=8Y76BmQ?> z2W<;!$C2+F88gRSkaC3W{W1VFg_@pl0!?B*L2nCkgZ8d)JwPuB3IY{T(-R>e?uziT ziHN@T73ICc_I^d~Yb^1#3G^ZJeeH`BecOxe{f4zoBkh|&v~A(Tquv(vqZo=S^R8R=D2Npij?|y5NwC`2cRaHD$jD4?V z4cl2IG*7GB*7DQb?d)tB_B| z(OC^hZoHm#1Bn-(^#O?&pABU9xvrcxJ?F^obN$=2={YwMedwH--RF1wJplZ+f28Sk z-&2EHmGk~m>GN7GJG-)6XpZcGx5WiH{~KRNC%m{9pNr!2=T7P6R9%SX{rsX!6%bwc zc6wg$gApNB1lqjd=QrwV3sGoee^Uzsq3i)CU-huWfAVGZykKc3J&jTtzOkMc!gqRn z%L92`yE{6i5Cu2)H9H9{<%(J*r>{I64A!CE1uEZ?66Y5N3W|XmzSN$Va^=@*=y1>; NY&onFuQOF#{XYtUY104z literal 0 HcmV?d00001 diff --git a/bin/boot/ram.262 b/bin/boot/ram.262 new file mode 100644 index 0000000000000000000000000000000000000000..2a69671842993cd72761f7af5fc06ade8c64432b GIT binary patch literal 30720 zcmeI5dz@ZXb@%r<&$&bx6NHgQcoLqF(Nc{%kV!-s$cWSnMjJ8GRG(t1sDR*`CNl}* zz?>uxn8X1?3?V>>V~Bt^ObJA4F%C$rRj?>XsiLBe7H#Sq$xH~C%lrMUea>^4*!K0) z&*%NTfAmQF%$l|L+H0@9_F8MNeVKv%r`23G=}<7qxv-pGI@-0%Wo}L8T-w*2E?)YT z^&vm&n^;aaAKYFGv!F-dspWKCZ|7j>dQJg~o}WBPpmPg_bkStP+Rx4fe_l=>Kd=bw zv^#?%ojYo7IiZT)OZz`WwbTaa2xM z_jcFR5MO#)ce>-?zfsqE9Q>-BE(HY0gg#QjnfVFlI$Q|tau;>GYHpQqeB~e-+f#Ex z?prQ$;W^^D0lvA6B)4tyC7pYPB>6S9JC9!lOJH*U7LCGFrAaQn$_uuM@`n9Cuem5V zr20WQS_&9O6CH&G!qs3~#iC8z`)=8y;O| z6u^Sepq!ldcf#q1)L++5-OiKRTxl9W_*y7Gv?t?7``W21QbWEW1D9lNCpjAi3SA3uOYpY~xE57KA zTve<`QkBKM->o&NnQ5J8!_6^S?V{ZqGAf^+&y@e$cAJJQ9_%0A?xmwA59VX!h7tR3 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 P;1##a9V5(iMLGRHyp`np literal 0 HcmV?d00001 diff --git a/bin/boot/salv.rp06 b/bin/boot/salv.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..57790686e951d3060befd31db240e6c0adf3f084 GIT binary patch literal 79890 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 literal 0 HcmV?d00001 diff --git a/bin/sys/atsign.hactrn b/bin/sys/atsign.hactrn new file mode 120000 index 00000000..65d411c7 --- /dev/null +++ b/bin/sys/atsign.hactrn @@ -0,0 +1 @@ +sys/atsign.ddt \ No newline at end of file diff --git a/bin/sys/ts.dump b/bin/sys/ts.dump new file mode 120000 index 00000000..857faedd --- /dev/null +++ b/bin/sys/ts.dump @@ -0,0 +1 @@ +sysbin/dump.bin \ No newline at end of file diff --git a/bin/sys/ts.ksfedr b/bin/sys/ts.ksfedr new file mode 100644 index 0000000000000000000000000000000000000000..324b7be4db696ebed9e83eec6e750ac34ddbe5f5 GIT binary patch literal 20618 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 literal 0 HcmV?d00001 diff --git a/bin/sys/ts.lock b/bin/sys/ts.lock new file mode 100644 index 0000000000000000000000000000000000000000..664f0e98d8a8880efb68a105ff09b7be2704b91b GIT binary patch literal 10702 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 literal 0 HcmV?d00001 diff --git a/bin/sys/ts.pdset b/bin/sys/ts.pdset new file mode 100644 index 0000000000000000000000000000000000000000..b127ef67f79dc625182a28dcc10a89dca775cdef GIT binary patch literal 7134 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 literal 0 HcmV?d00001 diff --git a/bin/sys3/ts.midas b/bin/sys3/ts.midas new file mode 100755 index 0000000000000000000000000000000000000000..04d662b8e1c738421a859cf77382b72e990443c4 GIT binary patch literal 109127 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

&$Lf0UdzJGKsm1xOnOTA)&^TY#bt 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 jWHtX|9@j3vQZZNOv+3bKpQoo5PVhG>q3!<*w literal 0 HcmV?d00001 diff --git a/bin/sysbin/dump.bin b/bin/sysbin/dump.bin new file mode 100644 index 0000000000000000000000000000000000000000..2ba32ab3c50c6a4e34cec7d26a5bd2223df5d54c GIT binary patch literal 69551 zcmd443wYc`b}v}nExB8d*4x&zrN3GaOR_Ar)RNkkEW7n~TW`toOE#7)%d%|iVM~5v z+!JPE2$}VGd zDS#L>map^2g$D3UN8-knBA$6R3IvE3Qk3G43!B}oR4C&@XQGr!C0@iTtwKk%~_y~+YIv%oc+JE62Gr7Z8C8xJd5Sh%5TkYX8I zShyC}kF-pNjx#jD#5x8~GI$b+c4Q38LdGpjYhc?GOAQwXN*$Fr3{PFxBlC@az*v6;Q+kAzd&dyFi?-0?x{x; z3EsbrESax;^lteF3kyF}gG*^K9HbJ2f_O{fmIRfdd3=Dx?y5&`>XaR?B1%~8b76sEuZhGEEzUm$^DDhJi(+XmD2LL zEv417GB&QweoG$7VW{44c?J1%rBzPu8oE;c{Xe@`as&wkp&6DD3@(ADRMhWF4cWQ< zoBH{Uxqs+=LfDY14x2-E_AMdm`}=pNUtC!Dm8B<`VC#ws%bQZ^EuSMtM=*XVbn~OT zE4Q+4{ca}hu3g=yreGLCXJ8_%h;h&mI%@E-47-&j-9@y2=g-ab8-MYATMqtpWV#Vv zh5r%v6U1GMQRbU^@ShPR`8o#uC|4Hat|6{_s`v+|U>@$VoRu7{xq}{Z;K&3O^^(NR zJ^9mBH1>{6CE?pXtBBVvQ8!3g@Px9&4aJRGFcK(-9dV8Zi5pBz&rbma#*w0g{1l{N zx}AK11m~KkC!ZpJ58qM{tA(6k5?{S=p+cFOG&drHpBa&cTbX}`XeIR%G)if~&A8$2 zmXnp5=Fd8S4C+-kQugA1rnarsQyCh7G?9vrp4z#wvZR^pUD8_?41^+4?1lLtkj?Lc zNAo*~Q>t*iQZcjVy%>|uW87uXK**Gss~lO5eL(RgdzIO;AJFW%U#JZw%m&$84$M9P zyuv$}0}wx!ml%wh?RSIT?@K)$<2mPJ&lsTFnhC+e zbY(frxN_ldrXQub-1y9d;iKiMl@{NpfO2zD%UM$Kp^uxGBQrajaed12nb4C|Aqwup zQYcOj;=-~JjJP~w@v2NM1Vzs8`t3a&mn~PXT=P1bGC?^c(XJfXJ_qXCgwZ;N?QWp% z8s;ERLt-{lAsACFQ+bo+hHadic&w8$!w7m}?6NFzz`m1S%kGkY~3PNvO7eFPQA#8{)?k zsZlOHGvP?c+eiWw-HjtE{vjcCV=WRSFZ+?y_c`Csl{)W&hP6SiI;jgcl7S~VB!SR{ zJ{EN2+bs`B`+iqaXN)1rguV7*-;Uc7 zq)4!4HELUul$r_sHrjmoAETweK#dq@V4R6@rrs46Wn@>2n6Y{>nOuzz<@~_(Keo2~ znDTpSeh|o+$Yu-mbID%Rnjπ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 z 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 literal 0 HcmV?d00001 diff --git a/build/build.tcl b/build/build.tcl new file mode 100644 index 00000000..60003643 --- /dev/null +++ b/build/build.tcl @@ -0,0 +1,93 @@ +proc type s { + sleep .2 + foreach c [split $s ""] { + send $c + expect -re . + } +} + +proc respond { w r } { + expect $w + type $r +} + +proc pdset {} { + respond "YOU MAY HAVE TO :PDSET" "\032" + respond "Fair" ":pdset\r" + set t [timestamp] + respond "PDSET" [expr [timestamp -seconds $t -format "%Y"] / 100]C + type [timestamp -seconds $t -format "%y%m%dD"] + type [timestamp -seconds $t -format "%H%M%ST"] + type "!." + expect "DAYLIGHT SAVINGS" { + type "N" + respond "IT IS NOW" "Q" + } "IT IS NOW" { + type "Q" + } + expect ":KILL" +} + +proc shutdown {} { + respond "*" ":lock\r" + expect "_" + send "5kill" + respond "GO DOWN?\r\n" "y" + respond "BRIEF MESSAGE" "\003" + respond "NOW IN DDT" "\005" +} + +spawn pdp10 build/simh/init + +respond "sim>" "b tu1\r" +respond "MTBOOT" "mark\033g" +respond "Format pack on unit #" "0" +respond "Are you sure you want to format pack on drive" "y" +respond "Pack no?" "0\r" +respond "Verify pack?" "n" +respond "Alloc?" "3000\r" +respond "ID?" "foobar\r" +respond "DDT" "tran\033g" +respond "onto unit" "0" +respond "OK" "y" +expect "EOT" +respond "DDT" "\005" + +respond "sim>" "b tu2\r" +respond "MTBOOT" "\033g" +respond "DSKDMP" "l\033ddt\r" +expect "\n"; type "t\033its rp06\r" +expect "\n"; type "\033u" +respond "DSKDMP" "m\033salv rp06\r" +expect "\n"; type "d\033its\r" +expect "\n"; type "its\r" +expect "\n"; type "\033g" +pdset +respond "*" ":ksfedr\r" +respond "File not found" "create\r" +expect -re {Directory address: ([0-7]*)\r\n} +set dir $expect_out(1,string) +type "write\r" +respond "Are you sure" "yes\r" +respond "Which file" "bt\r" +respond "Input from" ".;bt rp06\r" +respond "!" "quit\r" +expect ":KILL" +shutdown + +respond "sim>" "b tu1\r" +respond "MTBOOT" "feset\033g" +respond "on unit #" "0" +respond "address: " "$dir\r" +respond "DDT" \005 +respond "sim>" "quit" + +spawn pdp10 build/simh/boot +respond "DSKDMP" "its\r" +type "\033g" +pdset +respond "*" ":midas system;_its\r" +respond "MACHINE NAME =" "AI\r" +expect ":KILL" +shutdown +respond "sim>" "quit" diff --git a/build/simh/boot b/build/simh/boot new file mode 100644 index 00000000..3f003819 --- /dev/null +++ b/build/simh/boot @@ -0,0 +1,5 @@ +set cpu its +set tim y2k +set rp0 rp06 +at rp0 out/rp0.dsk +b rp0 diff --git a/build/simh/init b/build/simh/init new file mode 100644 index 00000000..1a852a0a --- /dev/null +++ b/build/simh/init @@ -0,0 +1,7 @@ +set cpu its +set tim y2k +at tu0 out/minsys.tape +at tu1 out/salv.tape +at tu2 out/dskdmp.tape +set rp0 rp06 +at rp0 out/rp0.dsk diff --git a/doc/build.doc b/doc/build.doc new file mode 100644 index 00000000..6b19dd7d --- /dev/null +++ b/doc/build.doc @@ -0,0 +1,1068 @@ +-*- Text -*- This is the file AI:KSHACK;BUILD DOC + + + + Building a new KS10 ITS from scratch + + + +1. Inventory + +Your KS10 ITS distribution kit includes: + + 1. A KS10 boot tape containing the Salvager (labeled "Salvager"). + + 2. A KS10 boot tape containing DSKDMP (labeled "DSKDMP"). + + 3. A DUMP tape containing the minimal files needed to bring ITS up for + the first time (labeled "MINSYS"). + + 4. Four DUMP tapes containing sources and binaries for ITS itself, and + various programs including EMACS and MacLisp (Labeled "Distribution + tape #..."). + + 5. Hardcopy of the files: + KSHACK;BUILD DOC + KSHACK;CONSOL > + KSHACK;DSKDMP ORDER + KSHACK;AINOTE > + KSHACK;KSDEFS > + SYSDOC;DUMP FORMAT + .INFO.;DUMP INFO + + + +2. General explanations + +This document contains step-by-step instructions for building a new ITS +system for a KS10. This section introduces the major players. The +following sections describe the steps in detail. + +We use "$" to indicate the altmode/escape character (ascii code 33 octal). +Control characters are indicated by a proceeding "^", so "^Z" indicates the +character Control-Z (ascii code 32 octal). "" is used to indicate the +carriage return character (ascii code 15 octal). + +In this document we use a trailing "." to indicate a decimal number. All +other numbers are in octal. (Thus "105" and "69." both denote the same +number.) However, when these instructions tell you to "type a decimal +number" it only means that the sequence of digits you type will be +interpreted as a decimal number. It does not mean that you need to employ +any special notation to indicate the radix (such as a trailing decimal +point), in fact, you must not. + + +2.1. The 8080 front end + +The 8080 front end processor serves as a front console for the KS10. It +can be used to start and stop the machine, examine and deposit memory, load +and debug both machine language and microcode, as well as boot the KS10 +from tape and disk. The 8080 also controls the system console. + +Under normal operations the 8080 simply passes characters between the +processor and the system console, however typing ^\ causes the 8080 to +enter command mode. When the machine is initially powered on, the 8080 is +already in command mode. Command mode is indicated by the prompt: + + KS10> + +The 8080 will leave command mode if you type ^Z. Relevant commands are: + +MT Loads the machine from a KS10 boot tape. (Boot tapes are explained + below.) + +BT Loads the machine from the front end filesystem on the disk. (Part + of the process described in this document is how one installs a + front end filesystem.) + +ST nn Starts the machine at address nn. + +HA Halts the machine. + +A wallchart of the most useful 8080 front end commands can be found in the +file KSHACK;CONSOL >, there are many many more documented in the DEC +manuals. + + +2.2. Tape formats + +There are two different tape formats used on the tapes in your distribution +kit. + +A "KS10 boot tape" is used to load a standalone program into the KS10 +directly from tape. The MT command to the 8080 front end causes it to +load a KS10 boot tape. Such a tape starts with several records of +microcode that the 8080 loads into the KS10 micromachine. This is followed +by a bootstrap program, called "MTBOOT", that the 8080 loads into main +memory and starts. MTBOOT reads an Exec DDT and some other program into +memory from the rest of the tape and starts DDT. + +[Footnote: We do not use the DEC standard microcode. The most important +differences are that the ITS microcode supports ITS-style paging and has a +different set of I/O instructions. The file KSHACK;KSDEFS > documents the +ITS microcode.] + +A "DUMP tape" contains files (and links) in the format produced by the ITS +DUMP program. It can be used to load files into the filesystem either +using the TRAN routine in the standalone Salvager or using the DUMP program +running under timesharing. The file SYSDOC;DUMP FORMAT describes the +format of DUMP tapes. + +The two kinds of tape are not in the slightest way compatible with +each other. + + +2.3. Exec DDT + +There are perhaps more versions of DDT in the world than there are species +of insect. The standalone DDT used by ITS (sometimes called "Exec DDT") is +incompatible with every other DDT, including the DDT used on ITS under +timesharing. It's not documented anywhere, but the usual commands ($G, /, +return, etc.) work in the usual ways. + +Exec DDT has very primitive rubout processing. Typing a rubout/delete will +cause it to completely abort all unprocessed characters. + +When Exec DDT is loaded its start address is 774000. Even under +timesharing, Exec DDT is always kept at that location. Thus you can +usually get to DDT by starting the KS10 at that address (using the ST +command to the 8080 front end). + + +2.4. The Salvager + +The Salvager is a program that runs standalone and performs various +filesystem maintenance operations. It knows how to format disk packs and +how to copy them, how to build filesystems, how to detect damage in a +filesystem, and it contains tools that enable a hacker to repair a damaged +filesystem. Documentation for the Salvager can be found in its source. +The Salvager used on the KS10 is a rewrite of the older salvager still used +for the KA10 and the KL10, its source can be found in the file +KSHACK;NSALV >. + +Routines in the Salvager are run by simply using DDT to start them. Thus +to run the Salvager routine "CHKR", one types (to Exec DDT): + + CHKR$G + +Relevant routines in the Salvager are: + +MARK Formats a disk pack. + +TRAN Reads files from a DUMP tape and writes them into the filesystem. + +CHKR Checks the filesystem for problems. + +FESET Sets the pointer on disk used by the 8080 front end to boot the + machine. + +Examples of using all of these routines appear in the following sections. + +Salvager routines prompt for and process input in a variety of +idiosyncratic and inconsistent ways. Sometimes numbers are read in +decimal, sometimes they are read in octal. Sometimes (for example when +asking for the number of a disk drive) only a single digit is read, and any +additional input you accidentally type, such as a carriage return, will be +taken as a response to the following command. In the instructions that +follow, I have tried to carefully specify exactly what you must type, and +how it will be interpreted. You should be equally careful about following +these instructions. + +When a Salvager routine is finished it will generally type: + + DDT + +and return you to Exec DDT. Serious errors will also cause Salvager +routines to print an error message and return to DDT. + +Whenever the Salvager is waiting for input, typing ^Z will abort and return +immediately to DDT. Remember this. It will come in useful the first time +you make a error while typing to a Salvager routine. (The Salvager's +rubout processing is generally pretty poor.) + +A copy of the Salvager is also merged in with a dumped out ITS. This is so +that before ITS starts running it can call the Salvager to check out the +filesystem (performing the same checks as CHKR). + + +2.5. DSKDMP + +DSKDMP is a sort of miniature disk operating system. It is used to load +programs from the ITS filesystem into memory and start them, and to dump +memory into the filesystem. The DSKDMP program itself is kept on disk in +the extra cylinders that are beyond those used by the filesystem. DSKDMP +also uses this area of the disk for swapping space. + +A short DSKDMP bootstrap program is always kept in the last 64. words of +memory, from 777700 through 777777, even when timesharing is running. This +bootstrap knows how to find DSKDMP on disk and swap it in, swapping out +whatever is currently in main memory. Thus once DSKDMP is installed you +can usually (unless something trashes those 64. words) start it up by +starting the KS10 at address 777700 (using the ST command to the 8080 +front end). + +The $U command in Exec DDT will check to see if the DSKDMP bootstrap is +present, and will jump to it if it is. This is the most common way of +starting DSKDMP. + +When the 8080 front end filesystem has been built as described below, the +BT command to the 8080 (or pressing the BOOT switch) will load the DSKDMP +bootstrap into memory and start it. This makes it possible to get a DSKDMP +no matter what main memory contains (for example, after powering on the +machine). + +DSKDMP commands are either simply the name of a file to load and start, or +a single letter followed by an altmode. Many single letter commands are +then followed by a filename argument. Relevant DSKDMP commands are: + +F$ Lists the current directory. + +L$file Loads the file into memory without starting it. + +T$file Loads the file into memory assuming Exec DDT is already loaded. + Gives the file's symbols to DDT and starts DDT. + +M$file Merges the file into memory. + Does not load symbols or start anything. + +D$file Dumps memory into the named file. + +Examples of using all of these commands appear in the following sections. + +DSKDMP has an unusual convention for reading filenames: if only a single +name is given, then that is taken to be the second name of the file, and +the first name is defaulted to "@". Thus when giving DSKDMP a filename +".;ITS" refers to the file .;@ ITS. + +DSKDMP commands that read and write files sometimes take a few seconds to +run. So that you will know when DSKDMP is done executing a command, DSKDMP +will not type a linefeed until after the command is finished. + +DSKDMP has very primitive rubout processing. Typing a rubout/delete will +simply cause it to start over and prompt for a new command. + +DSKDMP error messages are somewhat terse. A wallchart of DSKDMP commands +and error messages can be found in the file KSHACK;DSKDMP ORDER. + + + +3. Formatting the disk + +Mount the Salvager boot tape and give the MT command to the 8080. (Type ^\ +to get the 8080 into command mode if necessary.) This will load the +Salvager and Exec DDT into the KS10 and start DDT. MTBOOT announces +itself: + + ITS MTBOOT.176 + +If something goes wrong while reading the tape, MTBOOT will try and tell +you about it, otherwise when the tape stops spinning, MTBOOT is finished +and has started Exec DDT. (A common error here is to forget to put the +tape drive on line.) + +Mount a disk pack on a drive. Understand that you are about to lose any +information you had on that pack. Check that the drive is not write +protected. Just to be safe, you should probably write protect any other +drives you happen to have. + +Run the MARK routine the in Salvager: + + MARK$G + +The Salvager will begin by asking you: + + Format pack on unit # + +You should respond by typing the number of the drive in question. Do not +type a carriage return after typing the number, the Salvager is only waiting +for you to type a single digit. + +The Salvager now asks: + + Are you sure you want to format the pack on drive # 0 (Y or N) + +You should respond by typing "y" if this really is what you want to do. Do +not type a carriage return, the Salvager is only waiting for you to type a +single character. It will then ask you: + + Pack no ? + +The disk packs in an ITS filesystem are numbered. Pack numbers can be +anywhere from 0 to 31., and are customarily written in decimal. With this +question the Salvager is asking you what number you want this pack to be. +Your Salvager has been assembled to believe that pack number 0 is your +primary disk pack (you may have other secondary packs someday). Since this +is in fact your primary pack you are trying to build, answer by typing "0" +followed by a carriage return. The Salvager will type something like: + + Pack 0., Drive #0 is serial #2184. + Begin formatting 815. cylinders.... + +and will start formatting the pack. This will take several minutes (about +10. for an RP06), go make yourself a cup of tea while you wait. When the +formatting is finished the Salvager will type: + + Hardware formatting complete. + Verify pack? (Y or N) + +The Salvager is offering to check that the pack is OK by reading back +everything it has just written. Unless you like to live very dangerously, +you should answer "y". Do not type a carriage return, the Salvager is only +waiting for you to type a single character. + +There are likely to be ECC correctable errors detected during this +verification phase. For each such error the Salvager will tell you where +the error occurred by typing something like: + + Disk transfer error on unit 0. + ECC Corrected error: Unit #0 Cylinder 1264 Head 12 Sector 20 + +After verification is finished (it takes just as long as the writing +phase), the Salvager will count the number of ECC correctable errors that +occurred: + + 7 ECC-corrected errors during verification. + +An absurdly large number of ECC errors, or some other error occurring during +verification should make you start over with a better disk pack. + +The Salvager now asks you for the amount of swap space you want to allocate +on this pack for ITS to use: + + Swapping Alloc? + +This number (given in octal), is the number of blocks that ITS should avoid +using for file storage at the front of the pack. This assures that there +will always be some empty space on the disk for swapping. Since ITS will +use any free block on the disk for swapping, not just those in the swapping +area, this is really only the minimum amount of swapping space. However, +since the first 500. blocks of the disk are already committed for storing +directories and the "HOM blocks" (part of the front end filesystem), you +will actually get 500. blocks less guaranteed swapping space than the +number you type here. If you find this all confusing, just type +"3000". This gives you a minimum of 1036. blocks of swapping space. + +Now the Salvager asks: + + Pack #0. ID? + +The Salvager wants you to tell it the name of the physical disk pack. This +is whatever is actually written on the pack's physical label (probably a +little piece of paper glued to the cover). (This "pack ID" is different +from the pack number, because in the future you might copy the contents of +this pack to a fresh disk pack. That new pack would still be pack #0 in +the filesystem, but would have something different written on its label. +The pack number is the name of the information written on the pack, and the +pack ID as the name of the physical pack itself.) You should type a string +of up to six characters followed by a carriage return. + +The MARK routine is now finished formatting the pack, and it returns you to +DDT after typing: + + DDT + + + +4. Loading the minimal files + +The filesystem you just built is completely empty, so the next step is to +load a minimal set of files into the filesystem so that you can bring ITS +up for the first time. + +Mount the minimal filesystem tape (the one marked "MINSYS") on the tape +drive, and run the TRAN routine in the Salvager: + + TRAN$G + +The Salvager asks: + + onto unit # + +You should respond by typing the number of the drive where your ITS pack is +mounted. As before, you should not type a carriage return after the unit +number, since the salvager is only waiting for you to type a single digit. + +As usual, the Salvager wants to make sure you know what you are doing, so +it asks: + + Copy from unit #5 onto unit #0, OK (Y or N) + +By "unit #5" it means "the tape drive". This does not mean that it is +going to address the tape drive as drive number 5. The Salvager always +uses tape drive number 0. The digit "5" has absolutely no significance, +"unit #5" is just the Salvager's name for the tape drive. You should +respond by typing a "y" if the target unit number is correct. + +The Salvager now types: + + Tape #1 + .;@ DDT + +This means that header on the tape you have mounted identifies this tape as +being tape #1, and that the first file on the tape is the file .;@ DDT, +which the Salvager is now loading. When the file has been loaded, the +Salvager types "OK" and proceeds to the next file: + + .;@ DDT OK + + .;ITS BIN + +This process should continue for about 60. files until the end of the tape, +at which point the Salvager types: + + EOT + + DDT + +and returns you to DDT. + + + +5. Checking your new filesystem + +At this point you might want to satisfy yourself that there really is a +good filesystem out there. The CHKR routine in the Salvager is the +principal means for checking the consistency of the filesystem. To run it +type: + + CHKR$G + +Since this routine is the Salvager's most common function, the Salvager +starts by announcing itself: + + Salvager 215 + +before asking you: + + Active unit numbers? + +To answer this question the Salvager wants you to type a sequence of +digits, each representing the number of an active disk drive in your +filesystem. Since at this point you only have a single drive, you should +just type its number, followed by a carriage return. The Salvager will now +inform you about which packs are mounted on the drives you have specified: + + Unit #0. ID is DX001, Pack #0 + +The unit number, pack ID, and pack number should all look familiar to you. +Now the Salvager asks: + + Use MFD from unit: + +The ITS filesystem keeps duplicate copies of all directories on all packs +for safety. Here the Salvager is asking you which copy of the Master File +Directory (the catalog of all the user directories) you regard as +authoritative. If you were recovering from some accident to a multi-pack +filesystem, this would be a useful question. Since you only have a single +drive, just type the drive number again (and don't type a carriage return). +Now the Salvager asks: + + Read all blocks of all files? (Y or N) + +The Salvager is offering to test the readability of every file in your +filesystem. When you have more files in the filesystem, this will be quite +a slow operation, but at this point it won't delay things too much, so you +might as well type "y". + + Get user dirs from unit: + +Now the Salvager wonders which drive has the pack you regard as +authoritative for the user directories. Again, since you only have a +single pack, you can only answer by typing the number of its drive (and no +carriage return). + +Now the Salvager starts working. It is highly unlikely that there will be +any problem detected. There is a possibility of some ECC correctable +errors during this process, but these aren't fatal. If all is well the +Salvager simply returns you to DDT after typing (as usual): + + DDT + + + +6. Installing DSKDMP + +Now that you have a filesystem you need to install DSKDMP on your pack. +Start by mounting the DSKDMP boot tape and giving the MT command to the +8080. (Type ^\ to get the 8080 into command mode if necessary.) This will +load an Exec DDT and a program for installing DSKDMP into the machine. As +usual MTBOOT types: + + ITS MTBOOT.176 + +when it starts running, and leaves you in DDT after it has read the tape. +To go ahead and install a DSKDMP on disk, you have to actually run the +program that was just loaded, so type: + + $G + +This writes a copy of DSKDMP on your disk, installs the DSKDMP bootstrap in +memory, and starts DSKDMP running. DSKDMP announces itself: + + DSKDMP + +To check that all is well, you can start by listing the directory named "." +where non-timesharing binary programs, like ITS itself, are generally +stored. To do this, use the F$ command to DSKDMP: + + F$ + +DSKDMP should show you a listing like this: + + #00 RAM RAM + #00 BT BIN + #00 DSKDMP BIN + #00 SALV BIN + #00 ITS BIN + #00 @ DDT + +where "#00" is the pack number of your single pack. We will see what each +of these files is for in the following sections. + + + +7. Dumping an ITS + +Now it is time to dump out an executable binary for ITS. Start by using +the L$ command to DSKDMP to load (but not start) a copy of Exec DDT by +typing: + + L$DDT + +This loads the file .;@ DDT into your machine. Now use the T$ command to +load .;ITS BIN into memory, give its symbols to Exec DDT, and start DDT, by +typing: + + T$ITS BIN + +Since DSKDMP has started DDT running, you can take this opportunity to use +DDT to patch ITS in any way that might be appropriate. It's is unlikely +that you know of any such patches under the circumstances, so use the $U +command to DDT to return to DSKDMP by typing: + + $U + +which should cause DSKDMP to return and announce itself: + + DSKDMP + +Now use the M$ command to DSKDMP to merge the file .;SALV BIN into the +programs already in memory by typing: + + M$SALV BIN + +Finally, dump the whole mess out by typing: + + D$ITS + +which will dump memory into the file .;@ ITS. If you give the F$ command +now by typing: + + F$ + +DSKDMP should show you a directory like this: + + #00 @ ITS + #00 RAM RAM + #00 BT BIN + #00 DSKDMP BIN + #00 SALV BIN + #00 ITS BIN + #00 @ DDT + + + +8. Bringing up ITS for the first time + +Now you are ready to run timesharing for the first time. The installation +procedure is not yet finished, because you have not yet built a front end +filesystem. However the program for manipulating the front end filesystem +only runs under timesharing. + +You should still be talking to DSKDMP after having dumped out an executable +ITS binary. To load that binary, and start it in Exec DDT, you need only +type the name of the file to DSKDMP: + + ITS + +After DSKDMP is finished (indicated by typing a linefeed), tell DDT to +start ITS by typing: + + $G + +ITS starts by calling the Salvager, which starts by announcing itself: + + Salvager 215 + +The Salvager will not ask you any questions this time. It will make some +reasonable assumptions about what you want done, and will return to ITS +after it is finished. (It exits to DDT if there are problems with the +filesystem. "GO$G" will start ITS without running the Salvager, should you +be in foolish desperation.) ITS now initializes itself. ITS will discover +that it does not know the time, so it will complain: + + THE KS-10 CLOCK HAS BEEN RESET, IF THE TIME CANNOT + BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET + YEAR, PDTIME OFFSET, NOT ON DISK. + PLEASE SETLOC APPROPRIATELY. + +One of the things you will do when timesharing starts is learn how to set +the time. + +When ITS finally starts running the system console will type: + + DX ITS 1631 SYSTEM JOB USING THIS CONSOLE. + LOGIN TARAKA 0 + TARAKA DMPCPY . _DMPCP OUTPUT WRITE + TARAKA DMPCPY . @ ITS DELRNM + +The first line tells you what version of ITS is running, what machine (DX) +it was assembled for, and that this terminal is currently functioning as +the system console. The second line tells you that someone with user name +"TARAKA" has logged in. TARAKA is the system demon charged with starting +all other system demons. One of the demons TARAKA will start is named +DMPCPY. The next two lines show the job named "TARAKA DMPCPY" copying the +file .;@ ITS. (ITS logs all file operations in system directories on the +system console.) It is beyond the scope of this document to explain why +DMPCPY is copying this file. + +Now you are ready to log in. Type ^Z. After a moment ITS should respond: + + DX ITS.1631. DDT.1513. + TTY 0 + You're all alone, Fair share = 75% + + (ITS does not know the date, so messages cannot be reviewed right now.) + + +8.1. Setting the time using PDSET + +You are now talking to timesharing DDT, a program you will get to know much +better as you learn more about using ITS as a user. At this point all you +need to know is that you run a program by typing a ":", the name of the +program, and then a carriage return. You want to begin by telling the +system what the time is. So run the PDSET program by typing: + + :PDSET + +You will then see: + + (Please Log In) + ___002 PDSET IOTLSR + + PDSET.113 + Please don't use this program unless you know how. + You are certain to break something if you happen to hit the wrong key. + Type Control-Z to exit, or ? for a reminder of the commands. + +The reminder to log in (first line) was typed by timesharing DDT, which +wants to discourage you from running programs before you tell the system +who you are. For the moment you can ignore it since your machine doesn't +have a reasonable database of user names yet anyway. + +The second line was typed by ITS on the system console to advertise the +fact that the job named "___002 PDSET" is going into User I/O mode (see the +processor manual if you don't know what that is). This message isn't +actually part of your output at all, its only because you have chosen to +log in from the system console that causes you to see this message. +"___002 PDSET" is the name of the job that timesharing DDT has created for +you to run the PDSET program in. + +The rest of this output is coming from the PDSET program itself. It tries +to scare you away from using it because normally you don't want people +randomly playing with the system's clock. At this point you can type "?" +to see a list of the available commands if you like. All you need to type +is: + + yymmddD + +where the current year is 19yy, and this is the dd'th day of the mm'th +month. Then type: + + hhmmssT + +where the current time is hh:mm:ss in 24-hour time. And then type: + + !. + +(That's right, an exclamation point followed by a period.) The instant +you type the "." will be taken to be the time you have specified with the D +and T commands. At this point the system will type on the system console +something like: + + 114562/ 0 773322,,1757 ___002 + + 114561/ 0 3702 ___002 + IT IS NOW 9:05:06 PM EDT, TUESDAY, APR 29,1986 + +These messages indicate that PDSET has persuaded ITS about the current date +and time. To exit PDSET type: + + Q + +and you will be back at timesharing DDT. + + +8.2. Building a front end filesystem using KSFEDR + +Now run the KSFEDR program to build the front end filesystem. To DDT type: + + :KSFEDR + +DDT will remind you: + + (Please Log In) + +and then run KSFEDR, which will start by looking for the front end +filesystem. It won't find one, of course, so it will say: + + ERROR: File not found: PK0000: .; .FEFS. PK0000 + ! + +You should cause KSFEDR to create a fresh front end filesystem by typing: + + create + +ITS will now type on the system console something like: + + ___002 KSFEDR . .FEFS. PK0000 WRITE 21:06:01 + +which indicates that the job ___002 KSFEDR has written a file named +.;.FEFS. PK0000, at the indicated time. (All messages on the system +console include the time of day once the system knows what that is.) +KSFEDR now informs you of what it has done: + + FE filesystem DSK: .; .FEFS. PK0000 on pack #0. + Directory address: 6000000004 + ! + +Remember that directory address! You will need to remember that number +later so that you can give it to the FESET routine in the Salvager and +complete the process of installing the front end filesystem. Make sure you +get it right, it tends to have a lot of zeros in the middle which makes it +hard to remember. + +Now you need to put two files in the front end filesystem. Tell KSFEDR +that you want to write a file by typing: + + write + +It responds: + + Are you sure you want to scribble in the FE filesystem? + +You type: + + yes + +It asks: + + Which file? + +You say: + + ram + +because you want to write the microcode file. It says: + + Input from (Default DSK: USERS3; RAM RAM): + +which is almost right, you actually want the file DSK: .; RAM RAM, so you +type + + .; + +and the microcode is written. Next you want to write the DSKDMP bootstrap, +so again you say: + + write + +It responds: + + Are you sure you want to scribble in the FE filesystem? + +Again you type: + + yes + +When it asks: + + Which file? + +This time you say: + + bt + +And it offers + + Input from (Default DSK: USERS3; BT BIN): + +which is almost right, you actually want DSK: .; BT BIN, so you type + + .; + +and the bootstrap is in place. Get out of KSFEDR and back to timesharing +DDT by typing + + quit + + +8.3. Bringing ITS down using LOCK + +Now you are done using timesharing, so it is time to take ITS down again. +Run the LOCK program by typing: + + :LOCK + +LOCK responds (after DDT asks you to log in again): + + LOCK.154 + _ + +Say you want the system to go down in 5 minutes (you can't ask for it to +happen faster) by typing: + + 5kill + +LOCK asks: + + DO YOU REALLY WANT THE SYSTEM TO GO DOWN? + +since you do, you type "y". ITS now types on the system console: + + ___002 LOCK SYS DOWN MAIL WRITE 21:07:36 + +because your LOCK job is writing the file SYS;DOWN MAIL to contain an +explanation of why the system is going down. LOCK will then demand: + + PLEASE ENTER A BRIEF MESSAGE TO USERS, ENDED BY ^C + +Since you are the only user, you hardly need to be considerate, so you +might as well immediately type a ^C. All kinds of things now start +happening: + +Timesharing DDT types on your terminal: + + DX ITS going down in 4:59 + +because it thinks you might want to know about this. ITS types on the +system console: + + CULPRIT = ___002 LOCK 21:07:40 + +to tattle about who took the system down. Then, because nobody is logged +in, ITS decides it is OK to go down immediately. (DDT kept telling you to +log in, but you wouldn't listen!) It types: + + DX ITS 1631 NOT IN OPERATION 21:07:41 + +Then, the system demon named "PFTHMG DRAGON", who performs various +accounting functions and therefore has special dispensation to run after +the system is officially down, finishes up: + + PFTHMG DRAGON CHANNA _DRGN_ TIMES WRITE 21:07:42 + PFTHMG DRAGON CHANNA LOGOUT TIMES DELRNM 21:07:42 + +And finally ITS types: + + SHUTDOWN COMPLETE + PI LEVEL 7 BUG + YOU ARE NOW IN DDT. + BUGPC/ CAIA COFFI4+1 $Q-2/ JRST COFFI7 + +and returns you to Exec DDT. Don't worry about the use of the word "BUG" in +this message, there is no problem. + + + +9. Installing the front end filesystem + +Now you want to run the FESET routine in the salvager. You could use the +Salvager boot tape to get back to the salvager, but now that you have +DSKDMP in place it is more convenient to use it to create an executable +Salvager. (The Salvager merged in with the ITS binary currently in memory +doesn't have any of its symbols loaded into DDT, so it's kind of +inconvenient to use.) Start by returning to DSKDMP by typing: + + $U + +DSKDMP announces itself: + + DSKDMP + +Tell it: + + L$DDT + +to get a fresh copy of Exec DDT, then + + T$SALV BIN + +to load the file .;SALV BIN, give its symbols to DDT and start DDT. Now +you can run the FESET routine by typing: + + FESET$G + +The Salvager will ask you: + + Set FE filesystem directory pointer on the pack on unit # + +to which you should respond by typing the number of the drive on which your +ITS pack is mounted. Remember not to type a carriage return, as the +Salvager is only waiting for a single digit. The Salvager now asks: + + Directory address: + +You should now type the directory address that KSFEDR told you about above. +The FESET routine now returns to DDT. + +Now return to DSKDMP by typing: + + $U + +Since the Salvager currently in memory is a useful tool to have around, you +might as well save it as .;@ SALV. Type: + + D$SALV + + + +10. Bringing up ITS as usual + +Now you should have a bootable ITS disk pack. To test that it really +works, you can try booting it from scratch. First type ^\ to get the 8080 +into command mode. Then tell it to boot from the front end filesystem on +disk by giving the BT command: + + BT + +After a few moments DSKDMP should come up and announce itself in the usual +way. Tell DSKDMP to load the file .;@ ITS, and start it in Exec DDT by +simply typing that file's name: + + ITS + +When DSKDMP indicates it is finished by typing a linefeed, tell DDT to +start ITS running by typing: + + $G + +And ITS should come up. (You will need to run PDSET again, because the BT +command halted the machine.) The file KSHACK;AINOTE > is the notice we +keep posted on the front of AI to explain to users about crash dump +procedures, etc., you might want to go and read it next. + + + +11. Loading the rest of the filesystem using DUMP + +Now that ITS is running, you will want to load in system sources and +binaries from your distribution tapes. Type ^Z to get a timesharing DDT, +and run PDSET to set the time as you did before. Mount the first tape, and +start up the DUMP program by typing (to timesharing DDT): + + :DUMP + +DUMP will announce itself: + + DUMP .399 + + _ + +The file .INFO.;DUMP INFO documents the commands accepted by the dump +program. To load all the files (and links) from a distribution tape into +your filesystem tell DUMP: + + LOAD MERGE NOASK CRDIR + +("MERGE" tells DUMP that it should be careful about writing over any file +that already exists in your filesystem. "NOASK" tells DUMP that when faced +with such a situation, it should always leave the existing file alone. +"CRDIR" tells DUMP to create any directories that are needed.) DUMP will +want to know which files you want to load from the tape, so it will prompt +you: + + FILE= + +You respond by typing: + + *;* * + +Which means "all the files". Now DUMP will go ahead and start loading. It +will type something like: + + TAPE NO 50 CREATION DATE 860601 + +After DUMP has read the entire tape, it will prompt you again with: + + _ + +Then you can use the command: + + UNLOAD + +to rewind and unload the tape. Then mount the next tape and start over +with the LOAD command again. + +Note that the entire set of sources and binarys will probably not fit on a +single RM02 or RM03 disk pack. If you have an RM02 or RM03 system, you +will have to be more selective about what you load. + +If you don't want ITS to type out a line on the system console every time +DUMP loads a file into a system directory, patch the system as follows: + + MNGDIR/ JRST POPJ1 + +12. Getting started using ITS + +Congratulations! Now you should have a functional ITS. + +A good way to get started is to run the INFO program (":INFO" to +timesharing DDT). It is pretty much self documenting. Type "H" the first +time you run it for a tutorial on its commands. After you understand how +to use it, visit the nodes names "INTRO" and "DDT". Then you are on your +own. + +Since we haven't distributed many ITS, I don't know what problems you will +run into. Just off the top of my head, here are a few problems that you +will probably notice: + +ITS itself, and all programs that run under ITS assume the machine is +located in the time zone for the east coast of the United States. + +Many programs have the string "MIT" built in to them. + +A few programs have little tables of the names of other known ITS machines +built into them. One of the worst offenders here is the database that +finds the name of a users home directory given his user name (binary in +INQUIR;DIRS BIN, source in INQUIR;DMUNCH >). Another example is +SYS;ATSIGN DEVICE whose source is in SYSENG;@DEV >. + +MacLisp will not work because it won't recognize the name of your machine. +Programs that are built on top of MacLisp won't work either. An +adventurous hacker can probably find the place in the MacLisp sources to +fix this problem, and assemble a new version. If I ever get around to +fixing MacLisp to handle this problem gracefully, I'll certainly send you +the fix. + +I have no idea what you might have to do to get the ITS mail demon (COMSAT) +to run and deliver local mail. It may not work to build a COMSAT for a +machine with no network interfaces. I haven't been able to get a COMSAT +maintainer to sit down and think about the problem of distributing COMSATs +to far-away places. Send mail to Bug-COMSAT at AI if you want to complain +about this. + +The INQUIR system, which is a database of all the users who use ITS +machines, needs COMSAT to run in order to process changes. Until somebody +figures out how to get you a working COMSAT, you are stuck with the +database that came on your tape. This database contains all of us here at +MIT, but you won't have any way to add yourselves. There are other changes +you have to make to get INQUIR run on your machine as well, for example, +one part of the INQUIR system is a MacLisp program. + +I haven't told you anything about how to expand your filesystem to multiple +disk packs, or what to do if something seriously bad happens to your +filesystem, or what procedures are reasonable for backing up your +filesystem on tape. + +Have fun. diff --git a/doc/build.info b/doc/build.info new file mode 100644 index 00000000..8c1aa675 --- /dev/null +++ b/doc/build.info @@ -0,0 +1,84 @@ +How to build a bootable NSALV tape for ITS on a KS10 with one RM80: + +Write the following to a tape using dd and mt or whatever. All files have +2560-byte records (in TM03 format, the KS will see them as 512 words). +Rumors of PDP-10s using all 9 tracks as data tracks are utterly false, that +would be stupid. You can write the tapes on any machine that can write +unlabeled 1600bpi tapes with 8-bit data. I used an IBM ES/9000 running MTS, +about as far from the 10 as you can get! + +ram.262 (ITS microcode) + +mtboot.bin (boot block) +@.ddt (standalone DDT) +salv.rm80 (NSALV built for RM80) +<2 tape marks> cosmetic, not used but this way the tape is easily copied + using any machine you have handy since 2 tape marks + traditionally mean "end of tape" + +Building the DSKDMP tape is the same but substitute dskdmp.rm80 for salv.rm80. + +This directory also contains the other versions of DSKDMP and [N]SALV from +the MINSYS; directory, converted to TM03 magtape format, but since all I +have that works is an RM80 I haven't tested the others so I don't know for +sure that the files aren't mangled and I don't know whether the patch given +below is required for those versions of MARK to work. If you know, tell me! + +DSKDMP and NSALV tapes will help you build a blank disk but you'll still need +to make DUMP tapes of the MINSYS files if you want to load ITS, and you'll +need a lot more files to run and/or rebuild a real system. Writing DUMP tapes +from a non-ITS machine isn't too difficult, send me email and I'll give you +my code. + +*** NOTE *** + +As distributed there is a bug in the salvager, which needs to be patched before +you run MARK. Here's what to do (user input shown in lower case): + +KS10>mt +KS10>USR MOD +ITS MTBOOT.176 +qcnvt/' MOVSI B,-1 +QCNVT+1/ CAMN A,QTRAN(B) came a,qtran(b) +markg +Format pack on unit # + +... and so on, from here on out it's just like what BUILD DOC says. + +Note that the distributed ITS 1644 binaries are built with the tape RH11 at a +non-standard address, and the system will crash if you try to run DUMP w/o +either moving the RH11 or reassembling a new system with the addr fixed. +So either edit SYSTEM; TM03S DEFS4 to change %TMBAS back to 772440 (instead +of 772400), or just delete the file since SYSTEM; TM03S DEFS3 has it right, and +reassemble the system. + +IMPORTANT STUFF THAT APPARENTLY NOT EVERYONE KNOWS: + +Before you go borrowing peripherals off of a VAX or PDP-11, you need to make +sure that your tape drive has the "universal data formatter" board (also known +as the "universal bit fiddler"), since otherwise it won't support 36-bit words +(packed into 5 tape frames each with 4 wasted bits) and you will lose. In +the TM03 formatter this board is M8915-YA, and it's quite rare since VAXen +don't need it. + +You *can* use VAX Massbus disks with the KS since they all support 18-bit mode +and MARK handles the reformatting (rumors of needing an HDA swap are greatly +exaggerated), but with RM drives (including the RM80) you need to add a jumper +or else 18-bit operation will not work correctly. This jumper must connect +pins E06E1 and E06C2 on the RM Adapter backplane, which is the card cage that +goes under the drive in an RM02/03/80 or next to the drive in an RM05. +THIS IS NOT OPTIONAL! + +The RH11s used in the KS10 are not quite vanilla either (naturally), the M7294 +board used in the RH11-AB (used in some PDP-11s and VAXen) is replaced by an +M7294-YA in the RH11C (used in the KS). I'm fairly sure that all the other +parts interchange though so feel free to gut your VAX for spares. + +DRIVES OTHER THAN THE RM80: +RM80s are all I have that works, so I have no way to test the other versions +of the "dskdmp.*" and "salv.*" files in this directory, so I don't know if +the bug in "MARK" is fixed in them. Give it a try... Anyway otherwise the +instructions for making the tapes are the same as for the RM80 versions, as +far as I know RP06 drives need no jumper changes but the RM drives do. + +John Wilson 31-Jan-1995 diff --git a/src/system/bits.117 b/src/system/bits.117 new file mode 100755 index 00000000..fa77889e --- /dev/null +++ b/src/system/bits.117 @@ -0,0 +1,1111 @@ +; -*-MIDAS-*- + +;;; ITS BITS THAT ARE OFTEN NEEDED + +.AUXIL + +;;; CATALOGUE OF RESERVED BIT NAME AND CONSTANT PREFIXES IN ITS + +.SEE %CA ;BITS IN CLRAC FOR CORE LINK DEVICE +.SEE %CB ;BITS FOR CORBLK SYMBOLIC SYSTEM CALL +.SEE %CL ;.CALL ARGUMENT TYPES. +.SEE %CLS ;BITS IN LH OF CLSTB ENTRY +.SEE %DC ;DTE20 IOELEVEN COMMANDS +.SEE %DF ;T-300 FAULT (DSCFLT) +.SEE %DM ;T-300 COMMAND (DSCCMD) +.SEE %DO ;DSK OPEN MODE BITS +.SEE %DP ;DATAPOINT CURSOR CONTROL CONSTANTS +.SEE %DS ;T-300 STATUS (DSCSTS) +.SEE %DT ;DTE20 COMMANDS BITS AND CONSTANTS +.SEE %DV ;BITS IN DEVTAB +.SEE %E ;.CALL AND OPEN ERROR CODES +.SEE %GO ;SUPDUP GRAPHICS PROTOCOL COMMANDS +.SEE %H1 ;RP04 (RH10/RH11) ERROR REGISTER 1 +.SEE %H3 ;RP04 (RH10/RH11) ERROR REGISTER 3 +.SEE %HA ;RP04 (RH10/RH11) ADDRESS REGISTER +.SEE %HC ;RP04 (RH10) CONTROL REGISTER +.SEE %HD ;RH10 ERROR BITS IN DRIVE REGISTERS +.SEE %HI ;RH10 CONI BITS +.SEE %HM ;RP04 (RH10/RH11) COMMAND CONSTANTS +.SEE %HO ;RH10 CONO BITS +.SEE %HR ;RH10 CONTROLLER AND RP04 DRIVE REGISTER NUMBERS + ; OR RH11 UNIBUS REGISTER ADDRESSES +.SEE %HS ;RP04 (RH10/RH11) STATUS REGISTER BITS +.SEE %HW ;FOR KL AND KS, BITS IN RH OF RESULT OF APRID +.SEE %HX ;RH11 BITS IN %HRCS1 +.SEE %HY ;RH11 BITS IN %HRCS2 +.SEE %IL ;Interlan NI1010 bits and constants +.SEE %IOT ;BITS IN IOTTB +.SEE %IR ;BITS IN IP ROUTE ENTRY FLAGS +.SEE %JB ;BITS IN JBWST VARIABLE +.SEE %JG ;BITS IN JOBGET FIRST VALUE +.SEE %JO ;OPCODES IN JOBGET FIRST VALUE +.SEE %JS ;SPECIAL VALUES FOR SPECS +.SEE %KE ;BITS IN KS10 MEMORY STATUS REGISTER (KSECCS) +.SEE %LH ;BITS AND CONSTANTS FOR ACC LH/DH IMP INTERFACE (KS10) +.SEE %MA ;BITS IN MSRAC (MAGTAPE STATUS TABLE) +.SEE %NC ;NETWORK SOCKET CLOSE REASONS +.SEE %NE ;ETHERNET - constants and bits (%EN taken..) +.SEE %NO ;INTERNET - bits for TCPOPN system call +.SEE %NS ;NETWORK SOCKET STATES +.SEE %NT ;INTERNET - TCP channel states (almost = to %NS. See also %NX) +.SEE %NX ;INTERNET - TCP connection close reasons (almost = to %NC) +.SEE %OP ;BITS IN LH OF .OPTION USER VARIABLE +.SEE %PC ;KA10 PC FLAGS +.SEE %PF ;KL10 AND KS10 PAGE FAIL WORD BITS (DEFINITIONS DIFFER + ; BETWEEN MACHINES) +.SEE %PI ;BITS IN PIRQC USER VARIABLE +.SEE %PJ ;BITS IN LH OF PIRQC USER VARIABLE +.SEE %PS ;KL10 AND KS10 PC FLAGS +.SEE %QA ;BITS IN QSRAC (DISK STATUS TABLE) +.SEE %QM ;DISK ACTION MODES IN RH OF QSRAC +.SEE %RL ;BITS FOR COMMANDS TO .REALT UUO +.SEE %SCV ;BITS IN SYSCVL TO CONTROL SYMBOLIC SYSTEM CALLS +.SEE %SS ;STY STATUS BITS IN STYSTS +.SEE %SW ;LH(USWST) BITS +.SEE %SY ;NAMES FOR SQUOZE FLAGS IN SYMBOL TABLES (NOT DEFINED IN ITS) +.SEE %TA ;BITS IN TTYSTA +.SEE %TB ;BITS IN TTYTBL USER VARIABLE +.SEE %TC ;BITS IN TTYCOM +.SEE %TD ;SOFTWARE TTY CURSOR CONTROL CODE CONSTANTS +.SEE %TF ;BITS IN TPFLAG +.SEE %TG ;BITS IN TTYST1 AND TTYST2 +.SEE %TI ;BITS IN LEFT HALF OF TTY INPUT IOCHNM WORD +.SEE %TJ ;BITS IN LH OF TTY OPTPUT IOCHNM +.SEE %TM ;BITS AND CONSTANTS FOR TM03/RH11 TAPE CONTROLLER (KS10) +.SEE %TN ;CONSTANTS FOR TCTYP +.SEE %TO ;BITS IN LEFT HALF OF TTYOPT +.SEE %TP ;BITS IN RIGHT HALF OF TTYOPT +.SEE %TQ ;BITS IN LEFT HALF OF TTYSMT +.SEE %TR ;BITS IN RIGHT HALF OF TTYSMT +.SEE %TS ;BITS IN TTYSTS +.SEE %TT ;BITS IN LEFT HALF OF TTYTYP +.SEE %TX ;ASCII CHARACTER BITS (META, TOP, CONTROL, ETC.) +.SEE %TY ;BITS IN RIGHT HALF OF TTYTYP +.SEE %UB ;BITS IS KS10 UNIBUS STATUS REGISTER (UBASTA) +.SEE %UC ;FOR KL AND KS, BITS IN LH OF RESULT OF APRID +.SEE %UM ;BITS IN UMAPS VARIABLE, AND ARGS TO PGLD, MPLD1, PLD1. +.SEE %UP ;BITS IN KS10 UNIBUS PAGE MAP (WHEN MAP IS READ) (UBAPAG) +.SEE %UQ ;BITS IN KS10 UNIBUS PAGE MAP (WHEN MAP IS WRITTEN) (UBAPAG) +.SEE %UST ;BITS IN USTP VARIABLE. +.SEE %WY ;WHYINT CODES +.SEE $11 ;BYTE POINTERS TO PDP11 FIELDS IN PDP-10 WORDS, ON AI-KA + ;10-11 INTERFACE. +.SEE ..R ;ARGUMENT CODES FOR .BREAK 12, READING. +.SEE ..S ;ARGUMENT CODES FOR .BREAK 12, WRITING. +.SEE .XC ;INTERNET - TCP connection close reasons (almost = to %NC) + ; (Old names. Use %NX instead.) + +.SEE MMP ;BITS IN MMP ENTRY 1ST WORD L.H. +.SEE OPTTRP ;BITS IN LH OF .OPTION VARIABLE + ; (Old names. Use %OP instead) +.SEE SCL ;BITS IN LH OF SUPCOR +.SEE SCR ;BITS IN RH OF SUPCOR + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,.QUOTE/.QUOTE/X +.ELSE [ + $$TEM1==Z + .QUOTE/.QUOTE/X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +;OPEN-FAILURE CODE NAMES. +;3RD AND 4TH LETTER: "TM" = "TOO MANY", "BD" = "BAD OR ILLEGAL", +; "TF" = "TOO FEW", "RO" = "READ-ONLY", "NA" = "NOT AVAILABLE", +; "NS" = "NO SUCH", "EX" = "ALREADY EXISTS", "FL" = "FULL", +; "NR" = "NOT READY". +;5TH AND 6TH LETTER: "JB" = "JOB", "RG" = "ARG", "DV" = "DEVICE", +; "DR" = "DIRECTORY", "IO" = "DIRECTION", "FL" = "FILE", +; "FN" = "FILE NAME" +DEFSYM %E==:-100 ;BIT TYPEOUT MASK +DEFSYM %ENSDV==:1 ;NO SUCH DEVICE +DEFSYM %ENSIO==:2 ;WRONG DIRECTION +DEFSYM %ETMTR==:3 ;TOO MANY TRANSLATIONS +DEFSYM %ENSFL==:4 ;FILE NOT FOUND +DEFSYM %EFLDR==:5 ;DIRECTORY FULL +DEFSYM %EFLDV==:6 ;DEVICE FULL +DEFSYM %ENRDV==:7 ;DEVICE NOT READY +DEFSYM %ENADV==:10 ;DEVICE NOT AVAILABLE +DEFSYM %EBDFN==:11 ;ILLEGAL FILE NAME +DEFSYM %ENSMD==:12 ;MODE NOT AVAILABLE +DEFSYM %EEXFL==:13 ;FILE ALREADY EXISTS +DEFSYM %EBDCH==:14 ;BAD CHANNEL NUMBER +DEFSYM %ETMRG==:15 ;TOO MANY ARGUMENTS (CALL) +DEFSYM %ENAPK==:16 ;PACK NOT MOUNTED + ;17 FORMERLY DIRECTORY NOT AVAIL +DEFSYM %ENSDR==:20 ;NON-EXISTENT DIRECTORY +DEFSYM %ELCDV==:21 ;LOCAL DEVICE ONLY +DEFSYM %ESCO==: 22 ;SELF-CONTRADICTORY OPEN +DEFSYM %ENAFL==:23 ;FILE LOCKED +DEFSYM %ETMDR==:24 ;M.F.D. FULL +DEFSYM %EMCHN==:25 ;DEVICE NOT ASSIGNABLE TO THIS PROCESSOR +DEFSYM %ERODV==:26 ;DEVICE WRITE-LOCKED +DEFSYM %ETMLK==:27 ;LINK DEPTH EXCEEDED +DEFSYM %ETFRG==:30 ;TOO FEW ARGUMENTS (CALL) +DEFSYM %EROJB==:31 ;CAN'T MODIFY JOB +DEFSYM %EROPG==:32 ;CAN'T GET THAT ACCESS TO PAGE +DEFSYM %EBDRG==:33 ;MEANINGLESS ARGS +DEFSYM %EBDDV==:34 ;WRONG TYPE DEVICE +DEFSYM %ENSJB==:35 ;NO SUCH JOB +DEFSYM %EBOJ==: 36 ;VALID CLEAR OR STORED SET +DEFSYM %ENACR==:37 ;NO CORE AVAILABLE +DEFSYM %ETOP==: 40 ;NOT TOP LEVEL +DEFSYM %ENAPP==:41 ;OTHER END OF PIPELINE GONE OR NOT OPEN +DEFSYM %ENAJB==:42 ;JOB GONE OR GOING AWAY +DEFSYM %ENSCL==:43 ;ILLEGAL SYSTEM CALL NAME +DEFSYM %ENSCH==:44 ;CHANNEL NOT OPEN +DEFSYM %ENRBF==:45 ;INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL +DEFSYM %EBDFL==:46 ;UNRECOGNIZABLE FILE (LOAD) +DEFSYM %EBDLK==:47 ;LINK TO NON-EXISTENT FILE + +NOPNLS==:47 ;NO DEFSYM BECAUSE THIS SYMBOL IS NOT TO BE PREDEFINED TO USERS + +; BITS IN .PIRQC USER VARIABLE - FIRST-WORD INTERRUPTS +; CLASSES ARE: +; [1] STOPS JOB AND INTERRUPTS SUPERIOR (FATAL INTR) +; [2] STOPS JOB AND INTERRUPTS SUPERIOR UNLESS ENABLED +; [3] DOES NOTHING UNLESS ENABLED +; BITS IN THE LH HAVE TWO NAMES: %PI... AS A BIT IN THE WORD, +; AND %PJ... SHIFTED DOWN BY 18. BITS. + +.SEE PIRQC + +DEFSYM %PI==:525252,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %PIRLT==:200000,, ;REAL-TIME TIMER WENT OFF [3] +DEFSYM %PIRUN==:100000,, ;RUN-TIME TIMER WENT OFF [3] +DEFSYM %PINXI==:40000,, ;NON-EX IO REG (KS10 UNIBUS) [2] +DEFSYM %PIJST==:20000,, ;JOB STATUS DISPLAY REQUEST [3] +DEFSYM %PIDCL==:10000,, ;DEFERRED CALL [1] +DEFSYM %PIATY==:4000,, ;WAS JUST GIVEN THE TTY [3] +DEFSYM %PITTY==:2000,, ;DON'T HAVE TTY (SEE %TBINT) [2] +DEFSYM %PIPAR==:1000,, ;MEMORY PARITY ERROR [2] +DEFSYM %PIFOV==:400,, ;FLOATING OVERFLOW [3] +DEFSYM %PIWRO==:200,, ;WRITE IN READ-ONLY PAGE [2] +DEFSYM %PIFET==:100,, ;FETCHED INSN FROM IMPURE PAGE [2] +DEFSYM %PITRP==:40,, ;SYSTEM UUO IN TRAP MODE [1] +DEFSYM %PIDBG==:2,, ;SYSTEM BEING DEBUGGED STATE CHG[3] +DEFSYM %PILOS==:1,, ;.LOSE INSTRUCTION EXECUTED [2] +DEFSYM %PICLI==:400000 ;CLI DEVICE OPENED TO THIS JOB [3] +DEFSYM %PIPDL==:200000 ;PUSHDOWN LIST OVERFLOW [3] +DEFSYM %PILTP==:100000 ;LIGHT PEN [3] +DEFSYM %PIMAR==:40000 ;MAR ADDRESS TRAP [2] +DEFSYM %PIMPV==:20000 ;MEMORY PROTECTION VIOLATION [2] +DEFSYM %PICLK==:10000 ;SLOW (1/2 SEC) CLOCK [3] +DEFSYM %PI1PR==:4000 ;SINGLE-INSTRUCTION PROCEED [1] +DEFSYM %PIBRK==:2000 ;.BREAK INSTRUCTION EXECUTED [1] +DEFSYM %PIOOB==:1000 ;ADDRESS OUT OF BOUNDS [2] +DEFSYM %PIIOC==:400 ;I/O CHANNEL ERROR [2] +DEFSYM %PIVAL==:200 ;.VALUE INSTRUCTION EXECUTED [1] +DEFSYM %PIDWN==:100 ;SYSTEM GOING DOWN STATUS CHANGE[3] +DEFSYM %PIILO==:40 ;ILLEGAL OPERATION (E.G. UUO) [2] +DEFSYM %PIDIS==:20 ;DISPLAY MEMORY PROTECT [2] +DEFSYM %PIARO==:10 ;ARITHMETIC OVERFLOW [3] +DEFSYM %PIB42==:4 ;BAD LOCATION 42 [1] +DEFSYM %PIC.Z==:2 ;^Z OR CALL TYPED [1] +DEFSYM %PITYI==:1 ;TTY INPUT (OBSOLETE) [3] + +DEFSYM %PJ==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %PJRLT==:200000 ;REAL-TIME TIMER WENT OFF [3] +DEFSYM %PJRUN==:100000 ;RUN-TIME TIMER WENT OFF [3] +DEFSYM %PJNXI==:40000 ;NON-EX IO REG (KS10 UNIBUS) [2] +DEFSYM %PJJST==:20000 ;JOB STATUS DISPLAY REQUEST [3] +DEFSYM %PJDCL==:10000 ;DEFERRED CALL [1] +DEFSYM %PJATY==:4000 ;WAS JUST GIVEN THE TTY [3] +DEFSYM %PJTTY==:2000 ;DON'T HAVE TTY (SEE %TBINT) [2] +DEFSYM %PJPAR==:1000 ;MEMORY PARITY ERROR [2] +DEFSYM %PJFOV==:400 ;FLOATING OVERFLOW [3] +DEFSYM %PJWRO==:200 ;WRITE IN READ-ONLY PAGE [2] +DEFSYM %PJFET==:100 ;FETCHED INSN FROM IMPURE PAGE [2] +DEFSYM %PJTRP==:40 ;SYSTEM UUO IN TRAP MODE [1] +DEFSYM %PJDBG==:2 ;SYSTEM BEING DEBUGGED STATE CHG[3] +DEFSYM %PJLOS==:1 ;.LOSE INSTRUCTION EXECUTED [2] + +;;; PC FLAGS (LEFT HALF) + +DEFSYM %PC==:1,,525240 ;FOR BIT-TYPEOUT MODE +DEFSYM %PCARO==:400000 ;ARITHMETIC OVERFLOW +DEFSYM %PCCR0==:200000 ;CARRY OUT OF BIT 0 +DEFSYM %PCCR1==:100000 ;CARRY OUT OF BIT 1 +DEFSYM %PCFOV==:040000 ;FLOATING OVERFLOW +DEFSYM %PCFPD==:020000 ;FIRST PART DONE + ; (E.G. ILDB PTR INCREMENTED, BYTE NOT FETCHED) +DEFSYM %PCUSR==:010000 ;USER MODE +DEFSYM %PCUIO==:004000 ;USER I/O +DEFSYM %PCPUR==:002000 ;GIVE %PIFET IF FETCH INSTR FROM WRITABLE + ; PAGE (KA-10 ONLY) +DEFSYM %PCSPC==:001000 ;"SPECIAL" - OBSOLETE +DEFSYM %PC1PR==:000400 ;1 PROCEED - GIVE %PI1PR AFTER ONE INSTRUCTION +DEFSYM %PCX17==:000200 ;XR 17 = PC (AI-KA ONLY) +DEFSYM %PCFXU==:000100 ;FLOATING EXPONENT UNDERFLOW +DEFSYM %PCDIV==:000040 ;DIVIDE ERROR + +;;; PC FLAGS FOR KL-10 AND KS-10 + +DEFSYM %PS==:1,,525240 ;FOR BIT-TYPEOUT MODE +DEFSYM %PSARO==:400000 ;ARITHMETIC OVERFLOW +DEFSYM %PSPCP==:400000 ;PREVIOUS CONTEXT PUBLIC - PXCT CAN'T + ;REFERENCE CONCEALED PAGE THIS APPLIES ONLY + ;IN EXEC MODE. IN USER MODE AND ON KS IS + ;STILL %PSARO. +DEFSYM %PSCR0==:200000 ;CARRY OUT OF BIT 0 +DEFSYM %PSCR1==:100000 ;CARRY OUT OF BIT 1 +DEFSYM %PSFOV==:040000 ;FLOATING OVERFLOW +DEFSYM %PSFPD==:020000 ;FIRST PART DONE (E.G. ILDB PTR + ;INCREMENTED, BYTE NOT FETCHED) +DEFSYM %PSUSR==:010000 ;USER MODE ; 0 0 1 1 +DEFSYM %PSUIO==:004000 ;USER I/O ;; KERNEL SUPERV CONCEAL PUBLIC +DEFSYM %PSPUB==:002000 ;PUBLIC MODE ; 0 1 0 1 + ;%PSPUB ALWAYS 0 ON KS. +DEFSYM %PSPCU==:004000 ;IN EXEC MODE %PSUIO MEANS PREVIOUS CONTEXT + ;USER. +DEFSYM %PSINH==:001000 ;INHIBIT ADDRESS BREAK & TRAP 3 (TURNS OFF + ;AFTER 1 INST) %PSINH ALWAYS 0 ON KS. +DEFSYM %PSTR2==:000400 ;TRAP 2 (PDL OVERFLOW) ;TRAP 1 PLUS TRAP 2 +DEFSYM %PSTR1==:000200 ;TRAP 1 (ARITH OVERFLOW) ; MAKES TRAP 3 + ; (ONE PROCEED + ; ON KL) +DEFSYM %PSFXU==:000100 ;FLOATING EXPONENT UNDERFLOW +DEFSYM %PSDIV==:000040 ;DIVIDE ERROR + +DEFSYM %PS1PR==:001600 ;BITS TO SET TO CAUSE A 1-PROCEED ON KL. + +; INTERNET and ARPANET + +.SEE NETRFC +DEFSYM %NQ==:1,,525252 ; Control bits for NETRFC system call +DEFSYM %NQREF==:1 ; Refuse this connection request. Arg 2 must be a + ; previously returned RFC identifier. + +.SEE TCPOPN +DEFSYM %NO==:1,,525252 ; Control bits for TCPOPN system call +DEFSYM %NOLSN==:100 ; Listen mode - wait for SYN (request for conn) + +DEFSYM %NS==:,-1 ; NCP (old ARPANET) SOCKET STATES +DEFSYM %NSCLS==:0 ;CLS RECEIVED. CONNECTION CLOSED (IMSCLS GIVES REASON) +DEFSYM %NSLSN==:1 ;LISTENING FOR RFC +DEFSYM %NSRFC==:2 ;RFC RECEIVED WHILE IN LISTENING STATE +DEFSYM %NSRCL==:3 ;CLS RECEIVED WHILE IN RFC RECEIVED STATE +DEFSYM %NSRFS==:4 ;RFC SENT +DEFSYM %NSOPN==:5 ;CONNECTION OPEN +DEFSYM %NSRFN==:6 ;RFNM WAIT ON WRITE LINK +DEFSYM %NSCLW==:7 ;CLS SENT. WAITING FOR MATCHING CLS +DEFSYM %NSCLI==:10 ;CLS RECEIVED BUT INPUT STILL AVAILABLE +DEFSYM %NSINP==:11 ;INPUT AVAILABLE + +DEFSYM %NT==:,,-1 ; TCP port states as seen by user + ; Legend: - Pre-Open, * Open, + Post-open, ? impossible. + ; I = can read, O = can write. + ; Note that the input and output channels for a TCP connection + ; will usually have different states. Also, note that + ; for all practical purposes, %NT and %NS symbols with the same + ; value have the same meaning. SYN = Request for connection. + ; In Out +DEFSYM %NTCLS==:0 ; - - Closed (reason available from WHYINT) +DEFSYM %NTLSN==:1 ; - - Listening for a SYN +DEFSYM %NTSYR==:2 ; - - SYN received +DEFSYM %NTCLU==:3 ; + ? Being closed by fgn host +DEFSYM %NTSYN==:4 ; - - SYN sent, waiting for response +DEFSYM %NTOPN==:5 ; *I *O Open +DEFSYM %NTWRT==:6 ; ? *O Output buffer full +DEFSYM %NTCLX==:7 ; ? + Being closed by user +DEFSYM %NTCLI==:10 ; +I ? Closing/closed, input still available +DEFSYM %NTINP==:11 ; *I ? Open, input available + + +DEFSYM %NC==:,-1 ; NCP (old ARPANET) CLOSE REASONS (IN IMSCLS) +DEFSYM %NCNTO==:0 ;NEVER OPENED +DEFSYM %NCUSR==:1 ;CLSED BY USER +DEFSYM %NCFRN==:2 ;CLSED BY FOREIGN HOST +DEFSYM %NCRST==:3 ;RST +DEFSYM %NCDED==:4 ;HOST DEAD +DEFSYM %NCINC==:5 ;INCOMPLETE TRANSMISSION +DEFSYM %NCBYT==:6 ;BYTE SIZE MISMATCH. +DEFSYM %NCNCP==:7 ;OUR NCP WENT DOWN. +DEFSYM %NCRFS==:10 ;REQUEST FOR CONNECTION REFUSED + +;;; .XC is being phased out for the name %NX instead. +;;; The .XC symbols will be flushed "soon". + +DEFSYM .XC==,,-1 ; TCP port cls reasons (valid for ALL post-open states) + ; Note .XC and %NC symbols with the same value + ; have pretty much the same meanings. +DEFSYM .XCNTO==:0 ; Never opened +DEFSYM .XCUSR==:1 ; Closed by user +DEFSYM .XCFRN==:2 ; Closed by foreign host +DEFSYM .XCRST==:3 ; Fgn host refused or aborted connection. +DEFSYM .XCDED==:4 ; Fgn host dead (not used yet) +DEFSYM .XCINC==:5 ; Incomplete transmission (retransmission timeout) + ; This is the usual indication when a foreign host + ; or the intervening network crashes. + ; ==:6 ; Byte size mismatch - can't happen +DEFSYM .XCNCP==:7 ; Local TCP went down (not used yet) +DEFSYM .XCRFS==:10 ; RST received while in SYN-SENT state. + ; (foreign host refused connection) + +DEFSYM %NX==,,-1 ; TCP port cls reasons (valid for ALL post-open states) + ; Note %NX and %NC symbols with the same value + ; have pretty much the same meanings. +DEFSYM %NXNTO==:0 ; Never opened +DEFSYM %NXUSR==:1 ; Closed by user +DEFSYM %NXFRN==:2 ; Closed by foreign host +DEFSYM %NXRST==:3 ; Fgn host refused or aborted connection. +DEFSYM %NXDED==:4 ; Fgn host dead (not used yet) +DEFSYM %NXINC==:5 ; Incomplete transmission (retransmission timeout) + ; This is the usual indication when a foreign host + ; or the intervening network crashes. + ; ==:6 ; Byte size mismatch - can't happen +DEFSYM %NXNCP==:7 ; Local TCP went down (not used yet) +DEFSYM %NXRFS==:10 ; RST received while in SYN-SENT state. + ; (foreign host refused connection) + + + +;;; BITS IN RESULT OF APRID (BLKI APR,) ON KL-10 AND KS-10 +DEFSYM %UC==:1,,525000 ;FOR BIT-TYPEOUT MODE +DEFSYM $UCOPT==:331100 ;MICROCODE OPTIONS: +DEFSYM %UCKLP==:400000 ; KL-10-STYLE PAGING +DEFSYM %UCITS==:20000 ; ITS-STYLE PAGING +DEFSYM %UCTRK==:1000 ; TRACKS FEATURE +DEFSYM $UCVRS==:221100 ;MICROCODE VERSION NUMBER +DEFSYM %UCVRS==:1 +DEFSYM %HW==:0,,527777 ;FOR BIT-TYPEOUT MODE +DEFSYM $HWOPT==:140600 ;HARDWARE OPTIONS +DEFSYM $HWSER==:001400 ;PROCESSOR SERIAL NUMBER + + +;;; .CALL ARGUMENT TYPES +DEFSYM %CL==:1,,400777 +DEFSYM %CLIN==:0 ;INPUT ARGUMENT +DEFSYM %CLIMM==:1000 ;IMMEDIATE ARGUMENT +DEFSYM %CLOUT==:2000 ;OUTPUT ARGUMENT +DEFSYM %CLERR==:3000 ;ERROR CODE OUTPUT ARGUMENT +DEFSYM %CLBTW==:4000 ;DIRECT CONTROL BITS +DEFSYM %CLBIT==:5000 ;IMMEDIATE CONTROL BITS + + +;;; CONTROL BITS FOR CORBLK SYSTEM CALL + +.SEE NCORBLK +DEFSYM %CB==:0,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %CBWRT==:400000 ;TRY FOR WRITE ACCESS, OK IF CAN'T GET IT +DEFSYM %CBRED==:200000 ;TRY FOR READ ACCESS, OK IF CAN'T GET IT +DEFSYM %CBNDW==:100000 ;NEED WRITE ACCESS, FAIL IF CAN'T GET IT +DEFSYM %CBPUB==:040000 ;MAKE PAGE PUBLIC, REQUIRES WRITE ACCESS +DEFSYM %CBPRV==:020000 ;MAKE PAGE PRIVATE, REQUIRES WRITE ACCESS +DEFSYM %CBNDR==:010000 ;NEED READ ACCESS, FAIL IF CAN'T GET IT +DEFSYM %CBCPY==:004000 ;MAKE A COPY (DISK FILES ONLY) +DEFSYM %CBLOK==:002000 ;LOCK PAGE IN CORE. +DEFSYM %CBULK==:001000 ;UNLOCK PAGE (ALLOW SWAP-OUT) +DEFSYM %CBSLO==:000400 ;MAY ONLY RESIDE IN SLOWEST MEMORY +DEFSYM %CBUSL==:000200 ;ALLOWS USE OF ANY MEMORY. + ;ABOVE BITS ALL ZERO MEANS DELETE PAGE FROM MAP + +;;; SPECIAL VALUES FOR SPECS + +DEFSYM %JS==:,,-1 +DEFSYM %JSELF==:,,-1 ;SELF (ALL SPECS) +DEFSYM %JSTVB==:,,-2 ;11TV BUFFER (CORBLK) +DEFSYM %JSNUL==:,,-3 ;NULL JOB (KLPERF) +DEFSYM %JSALL==:,,-4 ;ALL JOBS (KLPERF) +DEFSYM %JSNEW==:,,-5 ;FRESH PAGE (CORBLK) +DEFSYM %JSABS==:,,-6 ;ABSOLUTE CORE (CORBLK) +DEFSYM %JSNUM==:400000 ;THIS + JOB # => THAT JOB (ALL SPECS) +DEFSYM %JSSIX==:400376 ;PDP6 IS USER NUMBER 376 +DEFSYM %JSSUP==:400377 ;SUPERIOR (ALL SPECS) +;A SPEC MAY ALSO BE THE NUMBER OF A CHANNEL OPEN ON USR:, BOJ:, OR STY: + +;;; CONTROL BITS FOR ".REALT AC," UUO. +;;; FLAG BITS ARE IN LH(AC). + +.SEE AREALT +DEFSYM %RL==:1,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %RLFLS==:400000 ;FLUSH OLD TIMER +DEFSYM %RLSET==:200000 ;SET NEW CLOCK RATE +DEFSYM %RLUSR==:100000 ;TRY TO SEIZE REAL TIME USER FACILITY +DEFSYM %RLPSD==:020000 ;ONLY WANT PSEUDO REAL TIME +DEFSYM %RLNPS==:040000 ;CANNOT ACCEPT PSEUDO REAL TIME +DEFSYM %RLBLK==:010000 ;PROGRAM TO BE BLOCKED EXCEPT FOR HIGH PRIORITY + ; PHASE OR INTERRUPT LEVEL +DEFSYM %RLGET==:004000 ;GET PREVIOUS STATUS IN WORDS 3+4 + ;REMAINING BITS MUST BE ZERO + +;;; BITS OF .OPTION USER VARIABLE. + +.SEE OPTION +DEFSYM OPTTRP==:400000 ;ALL SYSTEM UUOS TRAP TO SUPERIOR (%PITRP) +DEFSYM OPTDEC==:100000 ;UUOS 40,41 AND 47 ARE USER UUOS + ;THE FOLLOWING 3 BITS ARE NOT USED BY SYSTEM. + ;THEY ARE FOR COMMUNICATION FROM SUPERIOR. +DEFSYM OPTCMD==:040000 ;SUPERIOR SAYS IT HAS CMD STRING - DO + ; .BREAK 12,. +DEFSYM OPTBRK==:020000 ;SUPERIOR SAYS IT HANDLES ALL .BREAK'S. +DEFSYM OPTDDT==:010000 ;SUPERIOR SAYS HE'S DDT. (CLEARED WHEN DDT + ; DISOWNS) +DEFSYM OPTINT==:004000 ;NEW STYLE VECTORING INTS. +DEFSYM OPTOJB==:002000 ;ALLOW OTHER JOBS TO OPEN ME ON THE OJB + ; DEVICE. OPENING ME ON OJB DEVICE TURNS + ; ME INTO A JOB DEVICE. +DEFSYM OPTLOK==:001000 ;ENABLE SWITCH-UNLOCKING FEATURE + .SEE IODCSW ; SEE COMMENT THERE FOR DESCRIPTION. +DEFSYM OPTLIV==:000400 ;DON'T KILL THIS TOP LEVEL JOB WHEN SYS + ; GOES DOWN. +DEFSYM OPTOPC==:000200 ;INTERRUPTS THAT ABORT AN INSTRUCTION + ; SHOULD LEAVE THE PC POINTING TO THAT + ; INSTRUCTION (OTHERWISE IT GETS AOS'ED) +DEFSYM OPTLSP==:000100 ;SUPERIOR SAYS HE'S LISP +DEFSYM OPTLKF==:000040 ;UNLOCK LOCKS ON FATAL INTERRUPT IN + .SEE SYSDT ; TOP-LEVEL NON-DISOWNED JOB. + +;;; NEW NAMES FOR BITS IN LH(.OPTION) + +DEFSYM %OP==:525252(1) ;FOR BIT-TYPEOUT MODE +DEFSYM %OPTRP==:400000 ;ALL SYSTEM UUOS TRAP TO SUPERIOR (%PITRP) +DEFSYM %OPDEC==:100000 ;UUOS 40,41 AND 47 ARE USER UUOS + ;THE FOLLOWING 3 BITS ARE NOT USED BY SYSTEM. + ;THEY ARE FOR COMMUNICATION FROM SUPERIOR. +DEFSYM %OPCMD==:040000 ;SUPERIOR SAYS IT HAS CMD STRING - DO + ; .BREAK 12,. +DEFSYM %OPBRK==:020000 ;SUPERIOR SAYS IT HANDLES ALL .BREAK'S. +DEFSYM %OPDDT==:010000 ;SUPERIOR SAYS HE'S DDT. (CLEARED WHEN DDT + ; DISOWNS) +DEFSYM %OPINT==:004000 ;NEW STYLE VECTORING INTS. +DEFSYM %OPOJB==:002000 ;ALLOW OTHER JOBS TO OPEN ME ON THE OJB + ; DEVICE. OPENING ME ON OJB DEVICE TURNS + ; ME INTO A JOB DEVICE. +DEFSYM %OPLOK==:001000 ;ENABLE SWITCH-UNLOCKING FEATURE + .SEE IODCSW ; SEE COMMENT THERE FOR DESCRIPTION. +DEFSYM %OPLIV==:000400 ;DON'T KILL THIS TOP LEVEL JOB WHEN SYS + ; GOES DOWN. +DEFSYM %OPOPC==:000200 ;INTERRUPTS THAT ABORT AN INSTRUCTION + ; SHOULD LEAVE THE PC POINTING TO THAT + ; INSTRUCTION (OTHERWISE IT GETS AOS'ED) +DEFSYM %OPLSP==:000100 ;SUPERIOR SAYS HE'S LISP +DEFSYM %OPLKF==:000040 ;UNLOCK LOCKS ON FATAL INTERRUPT IN + .SEE SYSDT ; TOP-LEVEL NON-DISOWNED JOB. + +;;; LOSING ERROR CODES + +DEFSYM %LS==:777400 ;RH OF .LOSE INSTRUCTION +DEFSYM %LSINT==:1 +DEFSYM %LSSYS==:1000 ;INTERPRET LAST OPEN LOSS CODE, USING .BCHN +DEFSYM %LSFIL==:1400 ; DO THAT AND PRINT FILE NAMES FROM CALL'S CHNL + +;;; FIRST RESULT OF .CALL WHYINT + +DEFSYM %WY==:,-1 +DEFSYM %WYTYI==:1 ;TTY INPUT +DEFSYM %WYTYO==:2 ;TTY OUTPUT +DEFSYM %WYSTI==:3 ;STY INPUT +DEFSYM %WYSTO==:4 ;STY OUTPUT +DEFSYM %WYNET==:5 ;ARPANET (NCP) +DEFSYM %WYCHA==:6 ;CHAOS NET +DEFSYM %WYTCP==:7 ;INTERNET (TCP) +DEFSYM %WYUBI==:10 ;UNIBUS INTERRUPT + +;I/O MODES FOR OPENS. + +DEFSYM .UAI==0 ;UNIT ASCII INPUT. +DEFSYM .UAO==1 ;UNIT ASCII OUTPUT. +DEFSYM .BAI==2 ;BLOCK ASCII INPUT. +DEFSYM .BAO==3 ;BLOCK ASCII OUTPUT. +DEFSYM .UII==4 ;UNIT IMAGE INPUT. +DEFSYM .UIO==5 ;UNIT IMAGE OUTPUT. +DEFSYM .BII==6 ;BLOCK IMAGE INPUT. +DEFSYM .BIO==7 ;BLOCK IMAGE OUTPUT. + +;OPEN BITS FOR DEVICE DSK: + +DEFSYM %DO==1,,525252 ;BIT TYPEOUT MASK +DEFSYM %DOOUT==1 +DEFSYM %DOBLK==2 +DEFSYM %DOIMG==4 +DEFSYM %DONRF==10 ;DON'T SET REFERENCE DATE. +DEFSYM %DONLK==20 ;DON'T CHASE LINKS. +DEFSYM %DORWT==40 ;ON OUTPUT OPEN, MAKES WOULD-BE READERS + ;WAIT TILL WE CLOSE. +DEFSYM %DOWOV==100000 ;WRITE OVER (USE WITH %DOOUT, TO OVERWRITE + ;EXISTING FILE). + +;ARGUMENT CODES FOR .BREAK 12,'S. +;..R AND ..S ARE BIT TYPEOUT MASKS, NOT MADE PREDEFINED TO MIDAS +;SINCE THEY ARE USEFUL ONLY IN DDT, WHICH DEFINES THEM ITSELF. + +..R==0 ;(FOR .SEE) +DEFSYM ..RSTART==1 ;READ STARTING ADDRESS +DEFSYM ..RLFILE==2 ;READ LOADED FILE'S NAMES +DEFSYM ..RSTP==3 ;READ SYMBOL TABLE POINTER +DEFSYM ..RSYM==4 ;READ VALUE OF SYMBOL. +DEFSYM ..RJCL==5 ;READ JOB COMMAND LINE. +DEFSYM ..RPFILE==6 ;READ :PRINT FILENAME DEFAULTS. +DEFSYM ..RSTB==7 ;READ WHOLE SYMBOL TABLE. +DEFSYM ..RCONV==10 ;READ NAME OF SYMBOL CLOSEST IN VALUE TO + ; ARGUMENT. +DEFSYM ..RLJB==13 ;READ IDX OF PREVIOUSLY CURRENT JOB. +DEFSYM ..RRND==14 ;READ RANDOM JOB-SPECIFIC BITS. +DEFSYM ..RPUR==15 ;UNPURIFY PAGE +DEFSYM ..RHSNAME==16 ;ASK SUPERIOR TO LOOKUP AN HSNAME FROM XUNAME +DEFSYM ..RMAIL==17 ;ASK A SUPERIOR TO LOOKUP USER'S MAIL FILE NAME + +..S==0 ;(FOR .SEE) +DEFSYM ..SSTART==400001 ;SET STARTING ADDRESS +DEFSYM ..SLFILE==400002 ;SET LOADED FILE'S NAMES +DEFSYM ..SSYM==400004 ;SET VALUE OF SYMBOL. +DEFSYM ..SJCL==400005 ;CLEAR JOB COMMAND LINE. +DEFSYM ..SPFILE==400006 ;SET :PRINT FILENAME DEFAULTS. +DEFSYM ..SSTB==400007 ;PASS WHOLE SYMBOL TABLE TO SUPERIOR. +DEFSYM ..SRND==400014 ;SET RANDOM JOB-SPECIFIC BITS. +DEFSYM ..SPUR==400015 ;SAME AS ..RPUR + +;.CALL JOBGET +;ARG 1 - BOJ CHNL +;UP TO SIX WDS RETURNED +;WD1 BITS: +DEFSYM %JG==:1,,525252 + ;4.9-4.7 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT + ; 4.9-4.7 SHOULDN'T BE USED, SINCE THE FULL MODE IS IN + ; WD7 ON AN OPEN +DEFSYM %JGCLS==:40000 ;4.6 => CLOSE (NOTE 4.5 USED TO BE A CLS BIT ALSO) +DEFSYM %JGSIO==:1000 ;4.1 => SIOT (ONLY IF OPCODE = 1) +DEFSYM %JGFPD==:200 ;3.8 => THIS CALL WAS PCLSRED AND IS RESTARTING +;1.4-1.1 => TYPE OF OPERATION +DEFSYM %JO==:,,-1 +DEFSYM %JOOPN==:0 ;OPEN +DEFSYM %JOIOT==:1 ;IOT/SIOT +DEFSYM %JOLNK==:2 ;MLINK +DEFSYM %JORST==:3 ;RESET +DEFSYM %JORCH==:4 ;RCHST +DEFSYM %JOACC==:5 ;ACCESS +DEFSYM %JORNM==:6 ;FDELE (DELETE OR RENAME) +DEFSYM %JORWO==:7 ;FDELE (RENAME WHILE OPEN) +DEFSYM %JOCAL==:10 ;SYMBOLIC .CALL + +;MODE BITS FOR TTY OPENS: +;3.1 0 -> IN 1 -> OUT +;3.2 0 -> UNIT 1 -> BLOCK + +;OUTPUT +;3.3 => IMAGE MODE (SET ALL %TGIMG BITS IN TTYST1 AND TTYST2) +;3.4 0 -> NORMAL 1 -> ECHO MODE OUTPUT (SET %TJECH, %TJPP2, %TJMOR). +;3.5 0 -> NORMAL 1 -> DISPLAYMODE, LOOK FOR ^P (SET %TJDIS). +;3.6 0 -> NORMAL 1 -> SUPER-IMAGE OUTPUT (SET %TJSIO). +;OUTPUT IOCHNM BITS MAY ALSO BE SPECIFIED, EXCEPT FOR +;%TJCNS, %TJCP1, AND %TJCP2 + +;INPUT +;3.3 => IMAGE MODE (CLEAR ALL ECHO BITS IN TTYST1, TTYST2). +;3.4 => "DDT" (DON'T ECHO CR, LF, TAB) +;3.6 => WANT 3 LINES IN ECHO AREA. +;INPUT IOCHNM BITS MAY ALSO BE SPECIFIED, EXCEPT FOR %TICNS. + +;BITS 3.4 AND 3.6 ON INPUT, AND BIT 3.3, HAVE EFFECT +;ONLY ON THE FIRST OPEN IN EITHER DIRECTION. +;(THEY ARE OBSOLETED BY THE TTYSET SYSTEM CALL) + +;BITS IN LH OF A TTY CHANNEL IOCHNM WORD +;THESE BITS MAY BE TEMPORARILY COMPLEMENTED BY SPECIFYING +;THEM IN THE CONTROL-BIT ARGUMENT TO A SYMBOLIC IOT +;(EXCEPT FOR %TICNS AND $TIIDX). +DEFSYM %TI==:1,,525277 ;BIT TYPEOUT MASK +DEFSYM %TJ==:1,,525277 ;BIT TYPEOUT MASK + +DEFSYM %TICNS==:400000 ;4.9 1-> CONSOLE 0 -> DEVICE +DEFSYM %TJCNS==:400000 ;4.9 1-> CONSOLE 0 -> DEVICE + +;THE FOLLOWING INTERPRETATIONS OF BITS ARE FOR OUTPUT ONLY. +DEFSYM %TJCP1==:200000 ;^P-CODE ANTICIPATION STATE. +DEFSYM %TJCP2==:100000 ; ". 0=>NORMAL, 1=> CHAR AFTER ^P, 2=> ^PH, 3=>^PV. +DEFSYM %TJECH==:40000 ;SET => ECHO MODE OUTPUT.-MODE OUTPUT (ALL CHARS + ; OUTPUT THE WAY THEY WOULD BE ECHOED) +DEFSYM %TJCTN==:20000 ;SET => DON'T DO LINE-CONTINUATION. +DEFSYM %TJSTP==:10000 ;SET => THIS CHANNEL IS HUNG IN **MORE**. +DEFSYM %TJDIS==:4000 ;SET => LOOK FOR ^P CODES. +DEFSYM %TJSIO==:2000 ;SET => SUPERIMAGE OUTPUT, NO PADDING OR CURSOR CTL. +DEFSYM %TJMOR==:1000 ;SET => DON'T DO **MORE** PROCESSING. +DEFSYM %TJPP2==:400 ;SET => USE ALTERNATE PC PPR (THE ECHO AREA) +DEFSYM %TJINK==:200 ;SET => NEXT CHAR OUT TAKEN AS PRINTING + ; REGARDLESS (^PI) +DEFSYM %TJHDE==:100 ;SET => ACCOUTING FOR CURSOR MOTION DUE TO + ;CHAR ECHOED ON A HALF-DUPLEX TTY. + +;INPUT +DEFSYM %TIECH==:40000 ;CAN READ EVEN IF CHAR NEEDS PI ECHOING. +DEFSYM %TIPEK==:20000 ;DON'T REMOVE CHAR FROM BUFFER. +DEFSYM %TIACT==:4000 ;SET => DON'T WAIT FOR ACTIVATION CHARACTER. +DEFSYM %TIINT==:2000 ;SET => CAN READ A CHAR EVEN IF IT IS SUPPOSED TO + ; INTERRUPT & HASN'T YET. +DEFSYM %TINWT==:1000 ;SET => IF NO INPUT AVAILABLE, DON'T WAIT, JUST + ; RETURN -1. +DEFSYM %TIFUL==:400 ;SET => GIVE FULL CHARACTER (SIGNIFICANT ON IMLAX, TVS) + +DEFSYM $TIIDX==:220600 ;3.6-3.1 CONSOLE #, OR 77 FOR A "DISOWNED" CONSOLE + ; TTY CHNL, IE, ONE THAT CORRESPONDS TO NO REAL TTY. + ; THEY EXIST ONLY IN TREES WITH NO TTY, IN JOBS + ; THAT CAME FROM TREES WITH TTYS. +DEFSYM %TIIDX==:1 ;FOR BIT TYPEOUT MODE +DEFSYM %TJIDX==:1 ;FOR BIT TYPEOUT MODE +DEFSYM %TINON==:77 ;"TTY #" FOR A CHANNEL WITH NO REAL TTY. + +;EACH CHARACTER IN THE INPUT BUFFER OCCUPIES 18 BITS +;THE UPPER BITS ARE AS FOLLOWS (NOTE THAT AN IOTTED +;CHARACTER MAY ACTUALLY CONTAIN %TXPIE, %TXMPE, %TXECI, OR %TXINT) +DEFSYM %TX==:525200 ;BIT TYPEOUT MASK +DEFSYM %TXMPE==:400000 ;MAIN PROGRAM ECHO CHARACTER +DEFSYM %TXPIE==:200000 ;PI ECHO CHARACTER +; DEFSYM %TXCOM==:100000 ;COM MODE ECHO CHAR; DO PI ECHO EVEN IF HDX +; ; TTY. +; DEFSYM %TXIGN==:40000 ;IGNORE THIS CHAR AT .IOT TIME. +; DEFSYM %TXACT==:20000 ;THIS IS AN ACTIVATION CHAR. +; THESE CAN'T BE NEEDED EXCEPT INSIDE THE SYSTEM. +DEFSYM %TXINT==:10000 ;THIS CHAR SHOULD INTERRUPT THE USER. +;GAP +DEFSYM %TXECI==:2000 ;THIS CHAR WAS ECHOED BY AN ECHOIN SYSTEM CALL. + +;NOW COME THE BITS OF THE CHARACTER ITSELF: +DEFSYM %TXTOP==:4000 ;The "TOP" key. +;GAP +DEFSYM %TXSFT==:1000 ;What used to be the "SHIFT" key is now the +DEFSYM %TXSUP==:1000 ;"SUPER" key. (def'ed in this order for DDT) +DEFSYM %TXMTA==:400 ;"META" key. +DEFSYM %TXCTL==:200 ;"CONTROL" key. +DEFSYM %TXASC==:177 ;The ASCII part of the character. + +;DISPLAY COMMANDS (WHICH LIVE IN THE OUTPUT BUFFER). +;NOTE THAT ALL OF THEM HAVE 200-BIT SET. +DEFSYM %TD==:777400 +DEFSYM %TDMOV==:200 ;MOVE CURSOR +DEFSYM %TDMV1==:201 ;DUMMY COMMAND CREATED BY TYMOV. + ;MAKES IT POSSIBLE FOR TYMOV TO STOP WHEN BUFFER FULL + ;AND BE REENTERED NEXT INTERRUPT. +DEFSYM %TDEOF==:202 ;CLEAR REST OF PAGE +DEFSYM %TDEOL==:203 ;CLEAR REST OF LINE +DEFSYM %TDDLF==:204 ;DELETE FORWARD (FOR IMLACS AND TVS) +DEFSYM %TDMTF==:205 ;MOTOR OFF (FOR TERMINETS) +DEFSYM %TDMTN==:206 ;MOTOR ON (FOR TERMINETS) +DEFSYM %TDCRL==:207 ;CRLF ON DATAPOINTS, IMLACS. +DEFSYM %TDNOP==:210 ;NO-OP FOR SUPERDUPERIMAGE MODE. +DEFSYM %TDBS==:211 ;BACKSPACE (FOR TTY'S WITH %TORAW SET). +DEFSYM %TDLF==:212 ;LINEFEED ("). +DEFSYM %TDRCR==:213 ;CARRET ("). +DEFSYM %TDORS==:214 ;"OUTPUT RESET" FOR SAKE OF SOFTWARE TTYS +DEFSYM %TDQOT==:215 ;MYSTERY COMMAND -- SEND IN A JINGLE IN 25 WORDS OR + ; LESS AND WIN +DEFSYM %TDFS==:216 ;CURSOR FORWARD ONE COLUMN +DEFSYM %TDMV0==:217 ;MOVE CURSOR, FOLLOWED BY NEW VERT POS, NEW HOR POS +DEFSYM %TDCLR==:220 ;CLEAR THE SCREEN +DEFSYM %TDBEL==:221 ;DING THE BELL +DEFSYM %TDINI==:222 ;SYSTEM JUST CAME UP, RE-INITIALIZE INTELLIGENT + ; TERMINAL +DEFSYM %TDILP==:223 ;INSERT LINE-POSITION, FOLLOW BY COUNT +DEFSYM %TDDLP==:224 ;DELETE LINE-POSITION, FOLLOW BY COUNT +DEFSYM %TDICP==:225 ;INSERT CHARACTER-POSITION, FOLLOW BY COUNT +DEFSYM %TDDCP==:226 ;DELETE CHARACTER-POSITION, FOLLOW BY COUNT +DEFSYM %TDBOW==:227 ;ENTER BLACK ON WHITE MODE +DEFSYM %TDRST==:230 ;DESELECT ALL SPECIAL MODES (SUCH AS BLACK-ON-WHITE). +DEFSYM %TDGRF==:231 ;ENTER GRAPHICS MODE +DEFSYM %TDRSU==:232 ;REGION SCROLL UP +DEFSYM %TDRSD==:233 ;REGION SCROLL DOWN + +; Apparently codes 234 - 237 are used for an undocumented kludge for +; sending ARDS graphics protocol. See SYSENG;IMPRIN (the source of +; :ARDPRN). + +;%TDSYN THROUGH %TDMLT ARE USED ONLY ON TERMINALS WHICH HAVE %TRLED SET IN +; TTYSMT. +DEFSYM %TDSYN==:240 ;RESYNCH REPLY TO LOCAL EDITING TERMINAL +DEFSYM %TDECO==:241 ;ASK TERMINAL TO TRY LOCAL EDITING BY SENDING A + ; RESYNCH. +DEFSYM %TDEDF==:242 ;SET LOCAL EDITING TERMINAL COMMAND DEFINITION. + ; FOLLOWED BY TWO BYTES, DECODED AS DESCRIBED IN + ; LOCAL EDITING PROTOCOL. +DEFSYM %TDNLE==:243 ;STOP DOING LOCAL EDITING. +DEFSYM %TDTSP==:244 ;DISPLAYS LIKE SPACE, BUT IS PART OF A TAB. USED + ; ONLY FOR LOCAL EDITING TERMINALS, TO ENABLE THEM + ; DISTINGUISH SPACES FROM TABS. +DEFSYM %TDCTB==:245 ;THIS LINE IS CONTINUED AT THE BEGINNING. +DEFSYM %TDCTE==:246 ;THIS LINE IS CONTINUED AT THE END. +DEFSYM %TDMLT==:247 ;%TDMLT => NEXT COLS ARE DISPLAY REP FOR + ; ONE CHAR OF TEXT. +;%TDSVL THROUGH %TDSLL ARE USED ON TERMINALS WHICH HAVE NONZERO %TRLSV. +DEFSYM %TDSVL==:250 ; => SAVE LINES' CONTENTS UNDER + ; LABELS STARTING WITH *200+. +DEFSYM %TDRSL==:251 ;SAME THREE ARGS. RESTORE LABELED CONTENTS ONTO + ; LINES. +DEFSYM %TDSSR==:252 ; SET RANGE OF COLUMNS TO COPY IN + ; %TDSVL, %TDRSL. +DEFSYM %TDSLL==:253 ; SET LABEL FOR NEXT LINE PUSHED OFF + ; SCREEN LOCALLY. +DEFSYM %TDMAX==:254 ;1 + LARGEST DISPLAY CODE. + +;THE TCTYP WORD FOR A TTY CONTAINS A NUMBER WHICH SAYS HOW TO +;PERFORM CURSOR-CONTROL FUNCTIONS ON THE TTY. THE POSSIBILITIES ARE: +DEFSYM %TN==:777777 +DEFSYM %TNPRT==:0 ;PRINTING TTY. +DEFSYM %TNDP==:1 ;TTY USES DATAPOINT CURSOR CTL CODES. +DEFSYM %TNODP==:2 ;TTY IS A LOSING DATAPOINT. +DEFSYM %TNIML==:3 ;TTY USES IMLAC CURSOR CODES. +DEFSYM %TNTEK==:4 ;TEKTRONIX 4000 SERIES +DEFSYM %TNTV==:5 ;TTY IS A KNIGHT TV DISPLAY. +DEFSYM %TNMEM==:6 ;TTY IS A MEMOWRECK. +DEFSYM %TNSFW==:7 ;"SOFTWARE" TTY THAT WANTS I.T.S. CURSOR-MOTION CODES. +DEFSYM %TNTRM==:10 ;TTY IS A TERMINET. +DEFSYM %TNESC==:11 ;TTY WANTS ASCII STANDARD ESCAPE SEQUENCES. (E.G. VT52) +DEFSYM %TNDTM==:12 ;DATAMEDIA +DEFSYM %TNRAY==:13 ;TELERAY 1061 +DEFSYM %TNHDS==:14 ;HDS CONCEPT-100 +DEFSYM %TNH19==:15 ;H19 +DEFSYM %TNAAA==:16 ;Ann Arbor Ambassador +DEFSYM %TNMAX==:17 + + +;TTYOPT WORD DESCRIBES CHARACTERISTICS OF THE PARTICULAR +;TERMINAL ATTACHED TO EACH LINE. + +;LEFT HALF BITS ARE: +DEFSYM %TO==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TOALT==:200000 ;4.8 => STANDARDIZE ALTMODES. +DEFSYM %TOCLC==:100000 ;4.7 => CONVERT LOWER CASE TO UPPER. +DEFSYM %TOERS==:40000 ;4.6 => THIS TTY CAN SELECTIVELY ERASE. +DEFSYM %TOHDX==:20000 ;4.5 => THIS TTY IS HALF-DUPLEX. +DEFSYM $TOHDX==:370100 +DEFSYM %TOMVB==:10000 ;4.4 => THIS TTY CAN BACKSPACE. +DEFSYM %TOSAI==:4000 ;4.3 => THIS TTY HAS SAIL CHAR SET ON OUTPUT. +DEFSYM %TOSA1==:2000 ;4.2 INIT %TSSAI OF NEW JOBS. +DEFSYM %TOOVR==:1000 ;4.1 => THIS TTY CAN OVERPRINT SUCCESSFULLY. +DEFSYM %TOMVU==:400 ;3.9 => THIS TTY CAN MOVE CURSOR UP (I.E. IT'S A + ; DISPLAY). +DEFSYM %TOMOR==:200 ;3.8 => DO **MORE** PROCESSING ON THIS TTY + ; (ACTUALLY JUST USED TO INIT %TSMOR FOR NEW JOBS). +DEFSYM %TOROL==:100 ;3.7 SIMILARLY, INIT %TSROL FOR NEW JOBS. +DEFSYM %TORAW==:40 ;3.6 => SUPPRESS CURSOR MOTION OPTIMIZATION. +DEFSYM %TOLWR==:20 ;3.5 => THIS TTY HAS LOWER CASE KEYBOARD. +DEFSYM %TOFCI==:10 ;3.4 => KEYBOARD CAN GENERATE FULL 12-BIT CHARACTER SET +DEFSYM %TOIML==:4 ;3.3 => SPACE, BS DON'T EQUAL ^PF, ^PB; ALSO ^PC + ; SENDS ^L. +DEFSYM %TOLID==:2 ;3.2 => %TDILP, %TDDLP WORK (INSERT AND DELETE LINES) +DEFSYM %TOCID==:1 ;3.1 => %TDICP, %TDDCP WORK + ; (INSERT AND DELETE CHARACTERS) + +;RIGHT HALF: +DEFSYM %TP==:707252 ;BIT TYPEOUT MASK +DEFSYM %TPPLF==:100000 +DEFSYM $TPPLF==:170300 ;3-BIT FIELD SAYING HOW TO PAD LF. + ; 0 - DON'T. 1 - MEMOWRECK, 2741. 2 - TERMINET. +DEFSYM %TPPCR==:10000 +DEFSYM $TPPCR==:140300 ;3-BIT FIELD SAYING HOW TO PAD CR. + ; 7 - UNUSED. 6 - MEMOWRECK. 5 - 2741. 4 - EXECUPORT. + ; 0 - DON'T. 1 - NORMAL. 2 - DOUBLE. + ; ON DATAPOINTS, = # CHARS PADDING NEEDED FOR ALL + ; CURSOR MOTION. + ; 4 IS RIGHT FOR 2400 BAUD; 3, FOR 1200. + ; ON TERMINETS, 0 => NO PADDING, ELSE 1,2,3,4,5 + ; ARE PADDING FOR SPEEDS 10,15,30,60,120 CPS. +DEFSYM %TPPCW==:6 ;FOR MEMO WRECK. +DEFSYM %TPPTB==:1000 +DEFSYM $TPPTB==:110300 ;3 BIT FIELD SAYING HOW MUCH PADDING NEEDED AFTER + ; TAB. 0 => TABS NOT ALLOWED; ELSE 1 +<# PADDING + ; CHARS NEEDED> BUT ON A DISPLAY, TABS ARE NEVER + ; PADDED AND THIS FIELD IS 1 TO USE TABS, 2 TO USE + ; ABSOLUTE CURSOR POSITIONING, 3 TO USE BOTH, 0 TO + ; USE NEITHER. +DEFSYM %TPMTA==:400 ;1.9 => HARDWARE META KEY SETS 8TH BIT +DEFSYM %TPPRN==:200 ;1.8 => INTERCHANGE () WITH [] ON INPUT +DEFSYM %TPTEL==:100 ;1.7 => HANDLE CR-LF ON INPUT AS CR, FOR TELNET + ; PROTOCOL +DEFSYM %TPCBS==:40 ;1.6 => ENABLE SPECIAL HANDLING OF CONTROL BACK + ; SLASH ON INPUT (THE "INTELLIGENT TERMINAL + ; PROTOCOL"). +DEFSYM %TP11T==:20 ;1.5 => PDP-11 TV TTY. REFLECTS %TY11T. NOT + ; SETTABLE BY USER. +DEFSYM %TPORS==:10 ;1.4 => OUTPUT RESET ON THIS TTY SHOULD REALLY DO + ; SOMETHING. +DEFSYM %TPRSC==:4 ;1.3 => THIS TTY SUPPORTS %TDRSU, %TDRSD + +;DEFINE BITS WHICH ARE USER-OPTIONS +DEFSYM %TOUSR==:%TOCLC+%TOSA1+%TOMOR+%TOROL +DEFSYM %TPUSR==:%TPPRN+1 ;THE 1 IS TO AVOID INTEFERING WITH BIT-TYPE-OUT + +DEFSYM %TQ==1,,701725 ;TTY "SMARTS" BITS IN LH(TTYSMT) +DEFSYM %TQIM1==300000 ;TTY IS A PDS1 +DEFSYM %TQIM4==200000 ;TTY IS A PDS4 +DEFSYM %TQP11==100000 ;TTY IS A PDP11 +DEFSYM %TQMCH==700000 ;4.7-4.9 MACHINE TYPE, 0 => NOTHING SPECIAL +DEFSYM %TQGRF==1 ;3.1 UNDERSTANDS GRAPHICS PROTOCOL +DEFSYM %TQGPH==1 ;3.1 UNDERSTANDS GRAPHICS PROTOCOL (OBSOLETE NAME) +DEFSYM %TQSET==2 ;3.2 HAS MULTIPLE OBJECT SETS +DEFSYM %TQREC==4 ;3.3 HAS RECTANGLE COMMANDS +DEFSYM %TQXOR==10 ;3.4 HAS XOR MODE +DEFSYM %TQBNK==20 ;3.5 HAS BLINKING +DEFSYM %TQVIR==40 ;3.6 VIRTUAL COORDINATES +DEFSYM %TQHGT==76000 ;4.2-4.6 CHARACTER HEIGHT IN DOTS +DEFSYM %TQWID==1700 ;3.7-4.1 CHARACTER WIDTH IN DOTS + +DEFSYM %TR==534052 ;RH(TTYSMT) +DEFSYM %TRGIN==400000 ;2.9 HAS GRAPHIC INPUT +DEFSYM %TRGHC==200000 ;2.8 HAS GRAPHIC HARDCOPY +DEFSYM %TRLED==100000 ;2.7 HAS LOCAL EDITING PROTOCOL. +DEFSYM %TRSCN==040000 ;2.6 HAS RASTER COMMANDS +DEFSYM %TRLSV==034000 ;2.3-2.5 NONZERO MEANS TERMINAL SUPPORTS 4**N SAVED + ; LINES. +DEFSYM %TRTIM==003700 +DEFSYM $TRTIM==060500 ;5 BIT FIELD WHICH IS THE SIGNED OFFSET FROM GMT + ; MINUS #o20; A VALUE OF ZERO MEANS DON'T KNOW, + ; DON'T CARE, OR USER PROGRAM HASN'T IMPLEMENTED IT + ; YET + +;GROUP NUMBER CHARACTERS +;[ 0 ^A-^F ^K-^L ^N-^R ^T-^Z ^] ^^ ^_ ^@ ^\ +; 1 A-Z LOWER CASE A-Z +; 2 0-9 +; 3 !"#$(DOLLAR)%&',.:;?@\ (ACCENT GRAVE) +; (VERTICAL BAR) (TILDE) +; 4 *+-/=^_ +; 5 <>[]() (LEFT BRACE) (RIGHT BRACE) +; 6 ^G ^S +; 7 LF ^I(TAB) +; 10 (ALTMODE) +; 11 CR +; 12 RUBOUT +; 13 SPACE ^H(BACKSPACE) + +;TTYST1 HAS GROUPS 0 THROUGH 5 FROM LEFT TO RIGHT +;TTYST2 HAS 6 THROUGH 13 +;EACH GROUP HAS SIX BITS AS FOLLOWS: +DEFSYM %TG==:777725 ;BIT TYPEOUT MASK +DEFSYM %TGINT==:1 ;N.1 => INTERRUPT ON THIS GROUP +DEFSYM %TGACT==:2 ;N.2 => ACTIVATE ON THIS GROUP (FOR SWAPPING) +DEFSYM %TGSPC==:4 ;N.3 => SPECIAL HACKS. + ; (THIS SET ON GROUP 1 => CONVERT LOWER CASE) +DEFSYM %TGIMG==:10 ;N.4 => IMAGE MODE OUTPUT (N.4=0 => ASCII MODE) + ;N.6-N.5 => ECHO MODE + ; 00 => NO ECHO +DEFSYM %TGPIE==:20 ; 01 => PI ECHO (ECHO CHARACTER WHEN TYPED) +DEFSYM %TGMPE==:40 ; 10 => MAIN PROGRAM ECHO (ECHO WHEN MAIN + ; PROGRAM RECEIVES CHARACTER) + +;TTYSTS HAS RANDOM BITS ASSOCIATED WITH THE TELETYPE +DEFSYM %TS==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TSFRE==:400000 ;4.9 => TTY FREE +DEFSYM %TSCLE==:200000 ;4.8 => ECHO ^L AS UPARROW-L EVEN ON DISPLAYS + ;(OTHERWISE WOULD ECHO AS CLEAR SCREEN) +DEFSYM %TSHDX==:100000 ;4.7 REFLECTS %TOHDX BIT. +DEFSYM %TSFCO==:040000 ;4.6 => HANDLE 9-BIT CHARS ON OUTPUT, USING ALPHA, + ; BETA, EPSILON. +DEFSYM %TSALT==:020000 ;4.5 => DON'T STANDARDIZE ALTMODE. +DEFSYM %TSROL==:010000 ;4.4 => SCROLL MODE. +DEFSYM %TSSAI==:004000 ;4.3 => ECHO AND ASCII MODE SHOULD USE SAIL CHAR SET. +DEFSYM %TSACT==:002000 ;4.2 => GOBBLE NEXT CHAR REGARDLESS OF ACTIVATION + ; STATUS +DEFSYM %TSNEA==:001000 ;4.1 => DON'T ECHO IN ECHO AREA; ECHO IN M.P. AREA +DEFSYM %TSINT==:000400 ;3.9 => INT ON NEXT CHAR REGARDLESS +DEFSYM %TSMOR==:000200 ;3.8 => INHIBIT **MORE**. +DEFSYM %TSATY==:000100 ;3.7 SET BY .ATTY, SAYS TTY WAS TAKEN AWAY & RETURNED. + ;3.6-3.5 UNUSED. +DEFSYM %TSNOE==:000010 ;3.4 => DEFER ECHOING, AND MAKE INPUT IOT'S ACT AS + ; IF %TIECH=1. +DEFSYM %TSLCZ==:000004 ;3.3 => LAST CHARACTER TYPED WAS ^Z + ; (NOT PRECEEDED BY ^_) +DEFSYM %TSSII==:000002 ;3.2 => SUPER IMAGE INPUT MODE. ^Z AND ^_ INHIBITED. +DEFSYM %TSCNS==:000001 ;3.1 => TTY IN USE AS CONSOLE CONTROLLING A TREE. +DEFSYM $TSCNS==:220100 + ;RH => USER INDEX + ; -1 => NO USER + +;TTYCOM VARIABLE. +;4.9 => TTY IN COMMUNICATE MODE +DEFSYM %TC==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TCLFT==:200000 ;4.8 => LOCAL FEED THROUGH (SET IF MY PRGM + ; RECEIVING HIS CHRS) +DEFSYM %TCRFT==:100000 ;4.7 => REMOTE FEED THROUGH (SET IF HIS PRGM + ; RECEIVING MY CHRS) +DEFSYM %TCICO==:40000 ;4.6 => INPUT COMMUNICATE OVERRIDE (SET IF MY + ; CONSOLE FEEDING MY PRGM EVEN THO IN COMM MODE). + ; ALSO IMPLIES OUTPUT OVER-RIDE +DEFSYM %TCOCO==:20000 ;4.5 => OUTPUT COMMUNICATE OVERRIDE (SET IF MY + ; PRGM'S OUTPUT TO APPEAR ON MY CONSOLE ONLY EVEN + ; THO IN COM MODE) + ;4.4-4.3 => MESSAGE RECEIPT SWITCH + ; 00 => ACCEPT +DEFSYM %TCRFS==:10000 ; 10 => REFUSE +DEFSYM %TCQRY==:4000 ; 01 => INTERROGATE +DEFSYM %TCMTR==:2000 ;4.2 SET FOR TTY WHOSE MOTOR IS OFF & MUST BE + ; TURNED ON BEFORE ANY OTHER OUTPUT IS DONE. (ONLY + ; TERMINETS HAVE THEIR MOTORS SHUT OFF BY ITS). +DEFSYM %TCECH==:1000 ;4.1 THE OUTPUT BUFFER CONTAINS ECHOING OUTPUT. + ; THIS MAKES OUTPUT RESET DO NOTHING. THE BUFFER + ; MUST NOT CONTAIN ECHO OUTPUT AND NORMAL OUTPUT AT + ; ONE TIME. +DEFSYM %TCLED==:400 ;3.9 JOB WHICH OWNS TTY WANTS LOCAL EDITING IN + ; TERMINAL. SET BY CTL BIT 1.1 IN SCPOS; CLEARED + ; BY SWITCHING JOBS. +DEFSYM %TCDET==:200 ;3.8 CONSOLE'S TREE DETACHED BY TOP LEVEL + ; INTERRUPT. SET BY NDETAC AS SIGNAL TO SYSCFM + ; (CNSL-FREE-MSG TYPER) +DEFSYM %TCDNG==:100 ;3.7 => TYPE BELL ON TTY (BECAUSE INPUT BFR FULL). +DEFSYM %TCCBK==:40 ;3.6 => READING UNAME OR TTY # AFTER ^_K. +DEFSYM %TCCBS==:20 ;3.5 => READING UNAME OR TTY # AFTER ^_S. +DEFSYM %TCFPD==:10 ;3.4 => FIRST PART OF MULTI-CHAR OUTPUT SEQUENCE DONE. +DEFSYM %TCTPN==:4 ;3.3 TYPE ^_N ON LEAVING COM MODE (UNLESS USER + ; EXPLICITLY TYPES ^_N) +DEFSYM %TCPAD==:2 ;3.2 0 => PADDING NECESSARY ON DATAPOINT. +DEFSYM %TCHNG==:1 ;3.1 TTY'S DONE FLAG APPEARS TO BE FRIED, TIME OUT + ; QUICKLY +;RH => USER INDEX COMMUNICATING WITH (-1 NONE) + +;TTYTYP TABLE +;THIS TABLE HOLDS BITS THAT DESCRIBE THE LINE +;AND ITS CONTROLLER, RATHER THAN THE TTY ATTACHED TO THE LINE. +DEFSYM %TT==:1,,525360 ;BIT TYPEOUT MASK +DEFSYM %TTLCL==:400000 ;BIT 4.9 ONE => LOCAL TTY +DEFSYM %TT340==:200000 ;BIT 4.8 ONE => CONSOLE NEXT TO 340 OR A 340 SLAVE +DEFSYM %TT3HP==:100000 ;BIT 4.7 HIGH PRIORITY ON 340 +DEFSYM %TTPAR==:004000 ;BIT 4.3 +DEFSYM %TTDDI==:002000 ;BIT 4.2 DONT DING ON EXCESS INPUT +DEFSYM $TTISP==:260400 ;3.8-3.5 INPUT SPEED CODE +DEFSYM %TTISP==:20 +DEFSYM $TTOSP==:220400 ;3.4-3.1 OUTPUT SPEED CODE +DEFSYM %TTOSP==:1 +;RIGHT HALF BITS +DEFSYM %TY==:525252 ;BIT TYPEOUT MASK +DEFSYM %TYDPK==:400000 ;BIT 2.9 (DATAPOINT KLUDGE TTY LINE) +DEFSYM %TYSTY==:200000 ;BIT 2.8 PSEUDO TTY +DEFSYM %TYNVA==:100000 ;BIT 2.7 NOVA TTY +DEFSYM %TYMTY==:040000 ;BIT 2.6 MORTON BOX +DEFSYM %TYDIL==:020000 ;BIT 2.5 DIAL UP +DEFSYM %TY11T==:010000 ;BIT 2.4 PDP-11 TV TTY. +DEFSYM %TYDL==:004000 ;BIT 2.3 DL-11 TTY +DEFSYM %TYOTY==:002000 ;BIT 2.2 KA-10 CONSOLE TTY +DEFSYM %TYETY==:001000 ;BIT 2.1 DTE20 TTY +DEFSYM %TYNTY==:000400 ;BIT 1.9 TK-10 TTY +DEFSYM %TYMDM==:000200 ;BIT 1.8 LINE DETECTS DIALINS AND HANGUPS +DEFSYM %TYKST==:000100 ;BIT 1.7 KS-10 CONSOLE TTY +DEFSYM %TYDZT==:000040 ;BIT 1.6 DZ-11 TTY ON KS-10 +DEFSYM %TYRLM==:000020 ;BIT 1.5 ROLM DATA SWITCH + +;SPEED CODES ARE DOCUMENTED ON PAGE 3 OF ITS (DEFINE SPEED1) + +;SUPDUP GRAPHICS PROTOCOL COMMANDS: + +DEFSYM %GO==:,,-1 + +DEFSYM %GODLR==:101 ;

Draw line relative, from the cursor to

. +DEFSYM %GODPR==:102 ;

Draw point relative, at

. +DEFSYM %GODRR==:103 ;

Draw rectangle relative, corners at

and + ; at the current cursor position. +DEFSYM %GODCH==:104 ; <0> + ;Display the chars of starting at the current + ;graphics cursor position. +DEFSYM %GODSC==:105 ; Draws scan bits starting at + ;the current gaphics cursor position. come + ;in bits of 6-6-4. has 100 bit (character + ;gobbled) or 200 bit (interpreted as %TD code) set. +DEFSYM %GODRN==:106 ; <0> Draw run length encoded raster line + ;starting at current graphic cursor. Low six bits are + ;count. 100 bit determines point type (on/off). + +DEFSYM %GODLA==:121 ;

Draw line absolute, from the cursor to

. + ; The same effect as %GODLR, but the arg absolute. +DEFSYM %GODPA==:122 ;

Draw point absolute, at

. +DEFSYM %GODRA==:123 ;

Draw rectangle absolute, corners at

and + ; at the current cursor position. + +DEFSYM %GOELR==:141 ;

Erase line relative, from the cursor to

. +DEFSYM %GOEPR==:142 ;

Erase point relative, at

. +DEFSYM %GOERR==:143 ;

Erase rectangle relative, corners at

and + ; at the current cursor position. +DEFSYM %GOECH==:144 ; <0> + ;Erase the chars of starting at the current + ;graphics cursor position. +DEFSYM %GOESC==:145 ; . Erase scan bits starting at + ;the current graphics cursor position. +DEFSYM %GOERN==:146 ; <0> Erase run-length encoded rasters + ;starting at current grphaics cursor position. + +DEFSYM %GOELA==:161 ;

Erase line absolute, from the cursor to

. +DEFSYM %GOEPA==:162 ;

Erase point absolute, at

. +DEFSYM %GOERA==:163 ;

Erase rectangle absolute, corners at

and + ; at the current cursor position. + +DEFSYM %GOMVR==:001 ;

Move cursor to point

+DEFSYM %GOMVA==:021 ;

Move cursor to point

, absolute address. +DEFSYM %GOXOR==:002 ; Turn on XOR mode. Bit matrix terminals only. +DEFSYM %GOIOR==:022 ; Turn off XOR mode. +DEFSYM %GOSET==:003 ; Select set. is a 1-character set number, + ; 0 - 177. +DEFSYM %GOMSR==:004 ;

Move set origin to

. Display list + ; terminals only. +DEFSYM %GOMSA==:024 ;

Move set origin to

, absolute address. +DEFSYM %GOINV==:006 ; Make current set invisible. +DEFSYM %GOVIS==:026 ; Make current set visible. +DEFSYM %GOBNK==:007 ; Make current set blink. Canceled by %GOINV + ; or %GOVIS. +DEFSYM %GOCLR==:010 ; Erase whole screen. +DEFSYM %GOCLS==:030 ; Erase entire current set (display list + ; terminals). +DEFSYM %GOPSH==:011 ; Push all input-stream status information, to be + ; restored when graphics mode is exited. +DEFSYM %GOVIR==:012 ; Start using virtual co-ordinates +DEFSYM %GOPHY==:032 ; Resume giving co-ordinates in units of dots. +DEFSYM %GOHRD==:013 ; Divert output to output subdevice . + ; =0 reselects the main display screen. +DEFSYM %GOGIN==:014 ; Request graphics input (mouse, tablet, etc). + ; is the reply code to include in the answer. +DEFSYM %GOLMT==:015 ; + ;Limits graphics to a subrectangle of the + ;screen. %GOCLR will clear only that area. + ;This is for those who would use the rest for text. + +;THE TTYTBL VARIABLE EXISTS FOR EACH JOB. +;IT DESCRIBES THE ATTY-DTTY STATE OF THE JOB +;AND OTHER THINGS THAT HAVE TO DO WITH THE TREE'S +;CONTROLLING TTY ONLY. +DEFSYM %TB==:1,,525277 ;BIT TYPEOUT MASK +DEFSYM %TBNOT==:400000 ;4.9 THIS JOB DOES NOT HAVE THE TTY NOW. +DEFSYM %TBNVR==:200000 ;4.8 IF JOB DOESN'T HAVE TTY, OPENS SHOULD FAIL. +DEFSYM %TBINT==:100000 ;4.7 IF JOB DOESN'T HAVE TTY, ATTEMPT TO USE TTY + ; SHOULD INTERRUPT. +DEFSYM %TBWAT==:040000 ;4.6 IF SET, OVERRIDES %TBINT AND %TBNVR, AND + ; FORCES TTY USAGE ATTEMPTS TO HANG. MAY BE ALTERED + ; ONLY BY SUPERIOR. +DEFSYM %TBDTY==:010000 ;4.4 THE JOB DOESN'T HAVE THE TTY, BUT IT IS IN A + ; DTTY'ING STATE. IN OTHER WORDS, THIS JOB DOESN'T + ; WANT TO GIVE THE TTY TO ONE OF ITS INFERIORS. +DEFSYM %TBOUT==:004000 ;4.3 ALLOW TYPEOUT EVEN IF DON'T HAVE TTY (SETTABLE + ; BY SUPERIOR) +DEFSYM %TBINF==:002000 ;4.2 ALLOW INFERIORS TO TAKE ADVANTAGE OF THEIR + ; %TBOUTS. +DEFSYM %TBOIG==:001000 ;4.1 IGNORE OUTPUT (NORMALLY SET BY SUPERIOR). + ; OVERRIDES %TBWAT, %TBINT. +DEFSYM %TBIIN==:000400 ;3.9 INTERRUPT ON ATTEMPT TO DO INPUT. OVERRIDES + ; %TBWAT. NORMALLY SET BY SUPERIOR. +DEFSYM $TBECL==:220600 ;3-6-3.1 # ECHO LINES IF I DONT HAVE DISPLAY +DEFSYM %TBECL==:77 + +;RH - IF %TBNOT IS 0, THE RH HAS THE TTY NUMBER. +;OTHERWISE, IF %TBDTY IS 0, THE RH HAS THE USR INDEX OF +;THE INFERIOR THAT THIS JOB GAVE OR WOULD LIKE TO GIVE +;THE TTY TO. OTHERWISE, THE RH IS 0. + +;BITS IN THE PER-STY VARIABLE STYSTS, RETURNED BY STYGET SYSTEM CALL. +DEFSYM %SS==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %SSHNG==:400000 ;4.9 = 1 => DON'T HANG ON INPUT IOTS +DEFSYM %SSUSE==:200000 ;4.8 = 1 => IN USE +DEFSYM %SSINT==:100000 ;4.7 = 1 => HAVE GIVEN INT ON STY OUTPUT + ; CHNS ALREADY +DEFSYM %SSONT==:040000 ;4.6 = 1 => DITTO FOR STY INPUT (TTY OUTPUT) +DEFSYM %SSOHG==:20000 ;4.5 = 1 => DON'T HANG ON OUTPUT IOT + ;RH = USER INDEX THAT HAS IT OPEN + + +IFN $$TEMP, EXPUNGE DEFSYM diff --git a/src/system/ch10.defs1 b/src/system/ch10.defs1 new file mode 100755 index 00000000..8c325e39 --- /dev/null +++ b/src/system/ch10.defs1 @@ -0,0 +1,26 @@ +;Hardware definitions for CH10 PDP-10 CHAOSNET interface + +CHX==470 ;I/O Device number + +;CONI/CONO BITS + ;1.1-1.3 PIA +CHXTEN==10 ;1.4 Transmit interrupt enable +CHXREN==20 ;1.5 Receive interrupt enable +CHXSPY==40 ;1.6 Match any destination (on receive) +CHXLUP==100 ;1.7 Loop back +CHXSWB==200 ;1.8 Swap bytes +CHXHLF==400 ;1.9 Halfword DATAO +CHXXMT==1000 ;2.1 Transmit done (CONI) + ; Transmit or retransmit packet (CONO) +CHXRCV==2000 ;2.2 Receive done (CONI) + ; Enable to receive next packet (CONO) +CHXABT==4000 ;2.3 Transmit aborted (CONI) + ; Reset transmitter (CONO) +$CHXLC==140400 ;2.4-2.7 Lost count (CONI) +CHXRST==10000 ;2.4 Reset (CONO) +CHXCRC==200000 ;2.8 CRC error (CONI) +CHXWLE==400000 ;2.9 Word length error (CONI) +CHXPLE==1,, ;3.1 Packet length error (CONI) +CHXOVR==2,, ;3.2 Overrun (CONI) +$CHXAD==242000 ;3.3-4.9 Chaosnet address (CONI) + diff --git a/src/system/ch11.defs1 b/src/system/ch11.defs1 new file mode 100755 index 00000000..31e60f26 --- /dev/null +++ b/src/system/ch11.defs1 @@ -0,0 +1,58 @@ +;; CH11 Unibus Chaosnet Interface definitions + +CAICSR=3,,764140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + $CALOS==110400 ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN==3,,764142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=3,,764142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=3,,764144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=3,,764146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=3,,764152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. diff --git a/src/system/chaos.288 b/src/system/chaos.288 new file mode 100755 index 00000000..e29d65b5 --- /dev/null +++ b/src/system/chaos.288 @@ -0,0 +1,2782 @@ +IFE IMPP, IFE CH11P, .ERR NOT EVERYTHING IN CHAOS WILL WORK WITHOUT IMP +IFNDEF FTRCHK, FTRCHK==0 ;PROBABLY FOUND ALL THE BUGS THIS WAS GOOD FOR + ; LONG AGO +IFN FTRCHK, .ERR REDUNDANT CHECKING ENABLED IN CHAOS ROUTINES + +;NOTES: +; WINDOW SIZE ADJUSTMENT STUFF +; ROUND TRIP TIME MEASUREMENT & OTHER METERING +; BETTER METERING, SOME METERS ARE CURRENTLY MISSING + +SUBTTL CH-10 HARDWARE DEFINITIONS + +IFN CH10P,[ +CHX==470 ;I/O DEVICE NUMBER + +;CONI/CONO BITS + ;1.1-1.3 PIA +CHXTEN==10 ;1.4 TRANSMIT INTERRUPT ENABLE +CHXREN==20 ;1.5 RECEIVE INTERRUPT ENABLE +CHXSPY==40 ;1.6 MATCH ANY DESTINATION +CHXLUP==100 ;1.7 LOOP BACK +CHXSWB==200 ;1.8 SWAP BYTES +CHXHLF==400 ;1.9 HALFWORD DATAO +CHXXMT==1000 ;2.1 TRANSMIT DONE (CONI) + ; TRANSMIT OR RETRANSMIT PACKET (CONO) +CHXRCV==2000 ;2.2 RECEIVE DONE (CONI) + ; ENABLE TO RECEIVE NEXT PACKET (CONO) +CHXABT==4000 ;2.3 TRANSMIT ABORTED (CONI) + ; RESET TRANSMITTER (CONO) +$CHXLC==140400 ;2.4-2.7 LOST COUNT (CONI) +CHXRST==10000 ;2.4 RESET (CONO) +CHXCRC==200000 ;2.8 CRC ERROR (CONI) +CHXWLE==400000 ;2.9 WORD LENGTH ERROR (CONI) +CHXPLE==1,, ;3.1 PACKET LENGTH ERROR (CONI) +CHXOVR==2,, ;3.2 OVERRUN (CONI) +$CHXAD==242000 ;3.3-4.9 CHAOSNET ADDRESS (CONI) +];CH10P + +IFN CH11P,[ +$INSRT KSNET +];CH11P + +SUBTTL CHAOS NET VARIABLES + +EBLK + +$CHXRI==001200 ;REAL INDEX PART (LOW TEN BITS) - IS IN LH(IOCHNM) +$CHXUN==120600 ;UNIQUIZATION PART (TOP SIX BITS) +CHXMUN==1_6-1 ;MAXIMUM VALUE OF UNIQUIZER +MXWIND==100 ;MAXIMUM WINDOW SIZE (8K WORDS) +.SEE MYCHAD ;SUBNET AND HOST OF MYSELF +.SEE DLCP ;1 MEANS USE DL10 TO GET TO CHAOS NET +.SEE T11CHP ;1 MEANS USE TEN-11 INTERFACE TO GET TO CHAOS NET +.SEE CH10P ;1 MEANS USE CH10 HARDWARE TO GET TO CHAOS NET +.SEE CH11P ;1 MEANS USE UNIBUS CHAOSNET HARDWARE ON KS10 + +;Internet address of my Chaosnet Interface +IMPUS4==<.BYTE 4 ? 0 ? .BYTE 8 ? 128. ? 31. ? .BYTE 16. ? MYCHAD> + +;PER-INDEX VARIABLES + +CHSUSR: REPEAT NINDX,-1 ;-1 INDEX NOT IN USE + ;OTHERWISE RH USER + $CHSUO==220600 ;3.1-3.6 OUTPUT CHANNEL NUMBER (77=IOPUSHED) + $CHSUI==300600 ;3.7-4.3 INPUT CHANNEL NUMBER (77=IOPUSHED) + ;4.9 ZERO IF IN USE + +CHSSTA: REPEAT NINDX,-1 ;RH STATE, LH FLAGS + %CF==525252(1) + %CFOFF==400000 ;SIGN BIT MEANS TURNED OFF AT PI LEVEL, NO TALKING TO NETWORK + %CFSTS==200000 ;SEND STS PACKET AS SOON AS POSSIBLE (1/2 SECOND CLOCK) + %CFCLS==100000 ;HALF-CLOSED FLAG + %CFSTY==040000 ;DIRECT-CONNECTED TO STTY FLAG + $CFTTN==220600 ;TTY NUMBER OF STTY CONNECTED TO + + %CS==,,-1 + .SEE %CSCLS ;FOR SYMBOLS FOR STATES + +CHSNBF: BLOCK NINDX ;LH LENGTH(CHSPBF), RH LENGTH(CHSIBF) +CHSNOS: BLOCK NINDX ;NUMBER OF FREE OUTPUT SLOTS IN THE WINDOW +CHSIBF: BLOCK NINDX ;RECEIVE BUFFER POINTERS FIRST,,LAST +CHSPBF: BLOCK NINDX ;OUT OF ORDER RECEIVE BUFFER POINTERS FIRST,,LAST +CHSOBF: BLOCK NINDX ;TRANSMIT BUFFER POINTERS FIRST,,LAST +CHSITM: BLOCK NINDX ;TIME OF LAST INPUT FROM NET +CHSWIN: BLOCK NINDX ;WINDOW SIZE RECEIVE,,TRANSMIT +CHSPKN: BLOCK NINDX ;LAST PACKET# GIVEN TO USER,,LAST PACKET# SENT BY USER +CHSACK: BLOCK NINDX ;LAST PACKET# ACKNOWLEDGED RECEIVE,,TRANSMIT (START OF WINDOW) +CHSLCL: REPEAT NINDX,<.BYTE 16. ? MYCHAD ? 100000+.RPCNT> + ;BYTE (16) LOCAL HOST, LOCAL INDEX (4) 0 + ;NOTE THIS SAVES THE UNIQUIZER BITS FOR THIS INDEX +CHSFRN: BLOCK NINDX ;BYTE (16) FOREIGN HOST, FOREIGN INDEX (4) 0 +;THESE FOUR ARE FOR BYTE-STREAM I/O +CHSOBP: BLOCK NINDX ;BYTE PNTR TO OUTPUT BUFFER, 0 IF NONE +CHSOBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF BYTE SPACES LEFT IN OUTPUT BUFFER +CHSIBP: BLOCK NINDX ;BYTE PNTR TO INPUT BUFFER, 0 IF NONE +CHSIBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF VALID BYTES REMAINING IN INPUT BUFFER + +CHAOSW: -1 ? 0 ;SWITCH FOR ALLOCATING INDICES +CHALCP: 0 ;LAST INDEX ALLOCATED, USED TO CIRCULARIZE ALLOCATION + +CHIRFJ: SIXBIT/CHAOS/ ? 0 ;AGENT OF CHAOS +.SEE NETUSW ;NON-ZERO ENABLES RFC'S FROM HOSTS OTHER THAN SELF. + +;METERS + +CHNPI: 0 ;NUMBER OF PACKETS INPUT (REALLY TO 10) +CHNPO: 0 ;NUMBER OF PACKETS OUTPUT (ALL CAUSES) +CHNPF: 0 ;NUMBER OF PACKETS FORWARDED +CHNSTS: 0 ;NUMBER OF STS PACKETS OUTPUT +CHNSNS: 0 ;NUMBER OF SNS PACKETS OUTPUT +CHNRTR: 0 ;NUMBER OF RETRANSMITTED PACKETS OUTPUT +CHNPFL: 0 ;NUMBER OF PACKETS DISCARDED (FORWARDING LOOP) +CHNPD: 0 ;NUMBER OF PACKETS DISCARDED (DUPLICATES) +CHNIPI: 0 ;NUMBER OF INTERNET PACKETS IN FROM CHAOSNET +CHNIPO: 0 ;NUMBER OF INTERNET FRAGMENTS OUT TO CHAOSNET + +;BUFFER QUEUES. EACH HAS A ONE-WORD HEADER, WHICH IS ZERO +;IF IT IS EMPTY, OR CONTAINS FIRST,,LAST BUFFER ADDRESS. + +CHQFRE: 0 ;FREE LIST +CHQRFC: 0 ;PENDING RFCS +CHQLSN: 0 ;PENDING LISTENS +CHCLNQ: 0 .SEE CHCLN + +CHFRBF: 0 ;NUMBER OF FREE BUFFERS +CHTTBF: 0 ;TOTAL NUMBER OF BUFFERS +IF2 CHMXBF==50.*<1024./<%CPMXW+2>> ;MAX CORE FOR CHAOS NET 50K +CHMXTM: 0 ;TIME OF LAST COMPLAINT ABOUT USING TOO MUCH CORE + +IFN T11CHP,[ +;VARIABLES FOR TEN-11 INTERFACE CONNECTING TO CHAOS NET + +.SEE T11CHS ;EXEC ADDRESS OF PDP11 COMMUNICATION AREA +T11VER=T11CHS ;VERSION NUMBER +T11I10=T11CHS+1 ;INIT 10 +T11I11=T11CHS+2 ;INIT 11 +T11PRM=T11CHS+3 ;.WORD BUFFER SIZE, # BUFFERS + ;THEN 4 SPARE DOUBLEWORDS +T11IBB: T11CHS+8 ;BEGINNING OF INPUT BUFFERS +T11IBE: 0 ;END OF INPUT BUFFERS +T11IBP: 0 ;POINTER TO NEXT INPUT BUFFER +T11OBB: 0 ;BEGINNING OF OUTPUT BUFFERS +T11OBE: 0 ;END OF OUTPUT BUFFERS +T11OBP: 0 ;POINTER TO NEXT OUTPUT BUFFER +T11BSZ: 0 ;BUFFER SIZE IN PDP10 WORDS +T11WIN: 0 ;1 WINNING, -1 HAVE TOLD 11 TO INIT, 0 NOT WINNING +T11XMQ: 0 ;QUEUED TRANSMISSION QUEUE +T11CKE: 0 ;COUNT OF CHECKSUM ERRORS +;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR +;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE. +;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS +;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW, +; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED +; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT. +;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0. +];T11CHP + +IFN DLCP,[ +;VARIABLES FOR INTERFACE TO CHAOS NET ON PDP11 ON DL10 +;.SEE INDICATES A VARIABLE SHARED BETWEEN 10 AND 11 +;NOTE THAT THE DL10 HARDWARE LIMITS PACKET LENGTH TO 256 WORDS (1K BYTES) + +.SEE DLCINI ;WHEN THE 11 SEES THIS NON-ZERO, IT KNOWS ITS HAS + ; BEEN RELOADED AND RESETS ITS PACKET POINTER TO 0 + ; AND CLEARS DLCINI. +DLCSBF: 0 ;CURRENT BUFFER, 10 SEND SIDE (1 OR 0) + +DLCSA1: 0 ;ADDRESS OF PACKET BEING SENT +DLCSA2: 0 ;DITTO, SECOND BUFFER +.SEE DLCSP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) +.SEE DLCSP2 ;DITTO, SECOND BUFFER +.SEE DLCSS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 SENT TO 11, 2 11 DONE +.SEE DLCSS2 ;STATE FOR BUFFER 2 + +DLCRA1: 0 ;ADDRESS OF PACKET BUFFER RECEIVING A PACKET +DLCRA2: 0 ;DITTO, SECOND BUFFER +.SEE DLCRP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) +.SEE DLCRP2 ;DITTO, SECOND BUFFER +.SEE DLCRS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 AWAITING 11, 2 CONTAINS A PACKET +.SEE DLCRS2 ;STATE FOR BUFFER 2 + +DLCXMQ: 0 ;TRANSMIT BUFFER LIST FOR DL10 + ;NOTE THAT THIS IS NOT A REGULAR BUFFER LIST SINCE + ;IT IS THREADED THROUGH LH INSTEAD OF RH. WE DO MAINTAIN + ;POINTERS TO FIRST,,LAST HOWEVER +];DLCP + +IFN CH10P,[ +;VARIABLES FOR CH10 INTERFACE ONLY + +CHXCNO: CHXREN+CHXTEN+CHXCHN ;CONO BITS CURRENTLY IN EFFECT +];CH10P + +IFN CH11P,[ +;VARIABLES FOR CH11 INTERFACE ONLY + +CHXCSR: %CAREN+%CATEN ;CURRENT BITS WANTED IN CSR +];CH11P + +IFN CH10P+CH11P,[ +;VARIABLES THAT WOULD OTHERWISE BE IN THE FRONT-END + +CHXXMQ: 0 ;HEAD,,TAIL OF TRANSMIT QUEUE +CHOSTA: 0 ;OUTPUT STATUS: 0 IDLE, ELSE NUMBER OF TRANSMISSIONS +NCHRTR==4 ;TRANSMIT UP TO 4 TIMES IN FACE OF COLLISIONS + +;ROUTING STUFF +NSUBNT==122. ;122 is maximum possible +SBNRUT: REPEAT NSUBNT, 1000,,3040 ;COST,,GATEWAY ADDRESS + +;EXTRA METERS +CHNABT: 0 ;NUMBER OF TRANSMIT ABORTS +CHNCRC: 0 ;NUMBER OF CRC ERRORS BEFORE READING PACKET +CHNCR2: 0 ;NUMBER OF CRC ERRORS AFTER READING PACKET +CHNWLE: 0 ;NUMBER OF WORD LENGTH ERRORS (NOT MULTIPLE OF 16 BITS) +CHNPLE: 0 ;NUMBER OF PACKET LENGTH ERRORS (DISAGREES WITH LENGTH IN HEADER) +CHNLOS: 0 ;NUMBER OF PACKETS LOST DUE TO RECEIVER BUSY +];CH10P+CH11P +IFN CH11P,[ +CHNSPZ: 0 ;NUMBER OF TIMERS BIT COUNTER SPAZZED +];CH11P + +BBLK + +;Get definitions of packet format + +IF1,[ +$INSRT CHSDEF + +PKTBSZ==%CPMXW+2 ;PACKET BUFFER IS 2 HEADER WORDS + MAX SIZE PACKET +IFN >-PKTBSZ, .ERR PKTBSZ IS SUPPOSED TO BE A POWER OF 2 + +$CPKSX==$CHXRI+40000,,2 ;REAL PART OF SOURCE INDEX +$CPKDX==$CHXRI+40000,,1 ;REAL PART OF DESTINATION INDEX + +];IF1 + +;;; Debugging Info + +;;; This contains the last N headers received from the network +NRECHD==20 +EBLK +RECHDP: RECHDR ;POINTER TO NEXT +RECHDR: BLOCK NRECHD*%CPKDT +BBLK + +SUBTTL CHAOS NET OPEN (.CALL CHAOSO) + +;.CALL CHAOSO,RCVCHN,XMTCHN, + +CHASO: JRST OPNL12 ; Say "mode not avail" +CHAOSO: HRRZS A + HRRZS B + CAIGE A,20 + CAIL B,20 + JRST OPNL14 ;BAD CHANNEL NUMBER ARGUMENT + CAMN A,B + JRST OPNL33 ;BOTH CHANNELS SAME IS ILLEGAL + PUSH P,A ;SAVE ARGS, CLOSE THE SPECIFIED CHANNELS + PUSH P,B + PUSH P,C + MOVE R,A + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + MOVE R,-1(P) ;B + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + POP P,C + POP P,B + POP P,A + MOVE U,USER ;TO SAVE ULCERS + HRRZM A,UUAC(U) ;REMEMBER INPUT CHNL # FOR ERRS + PUSHJ P,SWTL ;LOCK CHAOS INDEX ASSIGNMENT SWITCH + CHAOSW + MOVE I,CHALCP ;ALLOCATE AN INDEX + SOJL I,CHASO2 +CHASO1: SKIPL CHSUSR(I) + SOJGE I,CHASO1 + JUMPGE I,CHASO3 +CHASO2: MOVEI I,NINDX ;REACHED BEGINNING, WRAP AROUND TO END + CAMN I,CHALCP + JRST OPNL6 ;ALL INDICES IN USE + MOVEM I,CHALCP + SOJA I,CHASO1 + +CHASO3: MOVEM I,CHALCP ;SAVE SCAN POINTER FOR NEXT TIME + PUSHJ P,CHASO4 ;INIT VARIOUS STUFF + CAILE C,MXWIND ;SET UP WINDOW SIZE + MOVEI C,MXWIND ;DON'T LET USER USE UP TOO MUCH WIRED CORE + HRLZM C,CHSWIN(I) + HRRZM U,CHSUSR(I) ;VARIABLES INITIALIZED, MAKE INDEX IN USE. + DPB A,[$CHSUI,,CHSUSR(I)] + DPB B,[$CHSUO,,CHSUSR(I)] + HRLZ T,I ;SET UP USER'S IOCHNM WORDS + HRRI T,CHAIDN + ADDI A,IOCHNM(U) + MOVEM T,(A) + HRRI T,CHAODN + ADDI B,IOCHNM(U) + MOVEM T,(B) + JRST LSWPJ1 ;SUCCESS RETURN + +;INITIALIZE CONNECTION IN I +CHASO4: SETZM CHSNBF(I) + SETZM CHSNOS(I) + SETZM CHSIBF(I) + SETZM CHSPBF(I) + SETZM CHSOBF(I) + SETZM CHSACK(I) + SETZM CHSPKN(I) ;START PACKET NUMBERING AT ONE + SETZM CHSOBP(I) + SETZM CHSOBC(I) + SETZM CHSIBP(I) + SETZM CHSIBC(I) + MOVSI T,%CFOFF .SEE %CSCLS + MOVEM T,CHSSTA(I) + LDB TT,[$CHXUN+40000,,CHSLCL(I)] + CAIE TT,CHXMUN ;INCREMENT THE UNIQUIZER + AOSA TT + MOVEI TT,1 ;BUT MAKE SURE IT ISN'T ZERO + DPB TT,[$CHXUN+40000,,CHSLCL(I)] + SETZM CHSFRN(I) + POPJ P, + +SUBTTL CHAOS NET CLOSE, FINISH, WHYINT, NETBLK, CHAOSQ + +;CLOSE A CHAOS CHANNEL. +CHACLS: HLRZ I,(R) ;GET VARIABLES INDEX + MOVSI A,%CFCLS + TDNN A,CHSSTA(I) ;ONLY REALLY CLOSE WHEN BOTH CHANNELS CLOSED + JRST CHACS7 + PUSHJ P,CHACS1 ;FLUSH ALL BUFFERS OF THIS CONNECTION + HRRZ T,CHSSTA(I) + CAIN T,%CSOPN + PUSHJ P,CHABGI ;SEND A CLS IF OPEN AND MEM AVAIL + JRST CHACS4 + MOVE T,CHSFRN(I) + MOVEM T,%CPKS(A) + MOVE T,CHSLCL(I) + MOVEM T,%CPKD(A) + MOVEI B,[ASCIZ/Channel closed/] + PUSHJ P,CHIRF2 +CHACS4: CONO PI,NETOFF + SETZM (R) ;CLOSE THIS CHANNEL + SETOM CHSUSR(I) ;RETURN INDEX + MOVE W,CHQLSN ;FLUSH ANY PENDING LSN PACKET + SETZM CHQLSN +CHACS5: MOVEI Q,W ;GET NEXT PACKET OFF OLD LIST + PUSHJ P,CHAQGF + JUMPE A,NETONJ ;EXHAUSTED + LDB B,[$CPKSX(A)] ;GET OWNER + CAME B,I + JRST [ MOVEI Q,CHQLSN ;NOT THIS INDEX, PUT BACK + PUSHJ P,CHAQPL + JRST CHACS5 ] + PUSHJ P,CHABRT ;FREE + JRST CHACS5 + +CHACS7: IORM A,CHSSTA(I) .SEE %CFCLS + HRRZ B,(R) ;GET DIRECTION + CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER + SKIPA B,[$CHSUI,,CHSUSR(I)] + MOVE B,[$CHSUO,,CHSUSR(I)] + MOVEI T,77 ;CLOSE THAT CHANNEL + DPB T,B + SETZM (R) + POPJ P, + +;THIS FLUSHES ALL BUFFERS FOR CONNECTION IN I +CHACS1: MOVSI A,%CFOFF ;INHIBIT RETRANSMISSIONS + IORB A,CHSSTA(I) + LDB E,[$CFTTN,,CHSSTA(I)] + EXCH E,I + TLNE A,%CFSTY + PUSHJ P,NSTYN0 ;DISCONNECT FROM STY + JFCL + EXCH E,I +IFN DLCP,[ + MOVEI Q,DLCXMQ ;REMOVE THIS INDEX'S BUFFERS FROM DL10 TRANSMIT LIST + PUSHJ P,CFLXMQ +];DLCP +IFN T11CHP,[ + MOVEI Q,T11XMQ ;REMOVE THIS INDEX'S BUFFERS FROM TEN11 TRANSMIT LIST + PUSHJ P,CFLXMQ +];T11CHP +IFN CH10P+CH11P,[ + MOVEI Q,CHXXMQ ;REMOVE THIS INDEX'S BUFFERS FROM CH10 TRANSMIT LIST + PUSHJ P,CFLXMQ +];CH10P+CH11P + MOVEI Q,CHSIBF(I) ;RETURN RECEIVE BUFFERS + PUSHJ P,CHALFR + MOVEI Q,CHSPBF(I) ;RETURN OUT OF ORDER RECEIVE BUFFERS + PUSHJ P,CHALFR + MOVEI Q,CHSOBF(I) ;RETURN TRANSMIT BUFFERS + PUSHJ P,CHALFR +IFE FTRCHK,[ + SKIPE A,CHSOBP(I) ;RETURN STREAM I/O BUFFERS + PUSHJ P,CHBPFR + SKIPE A,CHSIBP(I) + PUSHJ P,CHBPFR +];FTRCHK +IFN FTRCHK,[ + SKIPN A,CHSOBP(I) + JRST .+3 + SETZM CHSOBP(I) + PUSHJ P,CHBPFR + SKIPN A,CHSIBP(I) + JRST .+3 + SETZM CHSIBP(I) + PUSHJ P,CHBPFR +];FTRCHK + POPJ P, + +;.CALL FORCE ON A CHAOS OUTPUT CHANNEL. +CHAFRC: HLRZ I,(R) + SKIPGE CHSSTA(I) .SEE %CFOFF + JRST OPNL7 ;DEVICE NOT READY + AOS (P) ;WILL TAKE SUCCESS RETURN +CHAFC1: SKIPN A,CHSOBP(I) + POPJ P, ;NO BUFFERED OUTPUT TO BE FORCED + SUBI A,1 ;SIOKT LIKES TO POINT BP AT NEXT BUFFER + ANDI A,-PKTBSZ ;GET PACKET POINTER + ADDI A,2 + MOVSI T,(SETZ) ;DATA OPCODE + MOVEM T,(A) .SEE $CPKOP + MOVEI T,%CPMXC ;SET BYTE COUNT + SUB T,CHSOBC(I) + DPB T,[$CPKNB(A)] + PUSHJ P,[JUMPN T,CHODT1 ;IF THERE IS ANYTHING IN THE BUFFER, TRANSMIT IT + JRST CHABRT ] ;OTHERWISE, JUST THROW IT AWAY + SETZM CHSOBP(I) ;NOW THERE IS NO BUFFER + SETZM CHSOBC(I) + POPJ P, + +;.CALL FINISH ON A CHAOS OUTPUT CHANNEL. WAIT FOR ALL BUFFERS +;ON SEND LIST TO GET SENT AND ACKNOWLEDGED. +;HANGS FOREVER IF SOCKET GETS INTO AN IMPROPER STATE, BUT YOU SHOULD GET AN INTERRUPT +CHAFIN: HLRZ T,(R) + PUSHJ P,[HRRZ A,CHSWIN(T) + CAMG A,CHSNOS(T) + AOS (P) + POPJ P, ] + PUSHJ P,UFLS + JRST POPJ1 + +;.CALL WHYINT ON A CHAOS CHANNEL. +;RESULTS ARE: A/ %WYCHA +; B/ STATE +; C/ LH NUMBER OF INPUT PACKETS AVAILABLE +; RH NUMBER OF OUTPUT SLOTS AVAILABLE +; D/ WINDOW SIZE (RECEIVE,,TRANSMIT) +; E/ INPUT CHNL#,,OUTPUT CHNL# +CHAWHY: HLRZ I,(R) + MOVEI A,%WYCHA + HRRZ B,CHSSTA(I) + HRLZ C,CHSNBF(I) ;NUMBER OF PACKETS AVAILABLE + SKIPE CHSIBP(I) + ADD C,[1,,] ;ADD 1 IF PARTIALLY-READ INPUT BUFFER EXISTS + MOVSI D,%CFSTY + TDNE D,CHSSTA(I) + MOVEI C,0 ;NO INPUT AVAILABLE IF DIRECT-CONNECTED + SKIPLE CHSNOS(I) + HRR C,CHSNOS(I) + MOVE D,CHSWIN(I) + LDB E,[$CHSUO,,CHSUSR(I)] + CAIN E,77 + MOVEI E,-1 + LDB T,[$CHSUI,,CHSUSR(I)] + CAIN T,77 + TLOA E,-1 + HRL E,T + JRST POPJ1 + +;.CALL RFNAME on a CHAOS channel. A contains index. +;Returns results analogous to RFNAME on TCP: and (almost) RFNAME on NET:. +;"FN1" is local index, "FN2" is foreign index, "SNAME" is foreign host +;number in HOSTS3 format. +CHARCH: LDB B,[042000,,CHSLCL(A)] + LDB C,[042000,,CHSFRN(A)] + LDB D,[242000,,CHSFRN(A)] + TLO D,(NW%CHS) + POPJ P, + +;IOPDL ROUTINES. I IS 0 FOR IOPUSH, 1 FOR IOPOP. R POINTS AT IOCHNM WORD. +;C(R) IS SET UP TO THIS DEVICE IN EITHER CASE. +CHAIOP: HRRZ T,R ;DISCOVER CHANNEL NUMBER + SUBI T,IOCHNM(U) + SKIPN I + MOVEI T,77 ;IOPUSH, USE 77 + HLRZ I,(R) ;GET CHAOS INDEX + HRRZ B,(R) ;GET DIRECTION + CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER + SKIPA B,[$CHSUI,,CHSUSR(I)] + MOVE B,[$CHSUO,,CHSUSR(I)] + DPB T,B ;ADJUST SAVED CHANNEL NUMBER + POPJ P, + +;.CALL NETBLK ON A CHAOS CHANNEL. +;ARG 1 - CHANNEL (COMES IN IN R) +;ARG 2 - UNDESIRED STATE +;ARG 3 - OPTIONAL TIMEOUT, WRITTEN BACK UNLESS IMMEDIATE +;VAL 1 - NEW STATE +;VAL 2 - TIME LEFT +CHANBK: HRRZ T,(R) + CAIL T,CHAIDN + CAILE T,CHAODN +IFN NCPP, JRST ANETBL ;NOT A CHAOS CHANNEL, TRY ARPANET +IFE NCPP, JRST OPNL34 + HLRZ I,(R) + MOVE T,I ;SAVE INDEX IN T FOR FLSINS + CAIGE W,3 + JRST [ HRLOI D,377777 ;NO TIME GIVEN, USE INFINITY + JRST CHANB4 ] + TLNE C,1000 ;SKIP IF POINTER RATHER THAN IMMEDIATE + JRST [ HRRZ D,C ;GET IMMEDIATE TIME + ADD D,TIME + JRST CHANB4 ] + XCTR XRW,[MOVES D,(C)] ;GET TIME, CHECK WRITEABILITY + JUMPGE D,[ MOVNS D ;RELATIVE TIME, MAKE NEGATIVE ABSOLUTE + SUB D,TIME + JRST .+1 ] + UMOVEM D,(C) ;STORE BACK ABSOLUTE TIME + MOVNS D ;MAKE POSITIVE +CHANB4: MOVEM D,AC0S+D(U) ;SAVE ABSOLUTE TIME TO WAIT UNTIL + MOVEM B,AC0S+B(U) ;SAVE UNDESIRED STATE + PUSHJ P,CHANB2 ;SKIP IF STATE CHANGE OR TIMEOUT + PUSHJ P,UFLS + MOVE B,D + SUB B,TIME ;HOW MUCH USED? + HRRZ A,CHSSTA(I) ;NEW STATE + JRST POPJ1 + +CHANB2: HRRZ A,CHSSTA(T) ;CURRENT STATE + CAME A,AC0S+B(U) ;SKIP IF STILL MATCH + JRST POPJ1 + MOVE A,AC0S+D(U) ;TIMEOUT TIME + CAMG A,TIME + AOS (P) + POPJ P, + +;.CALL CHAOSQ +;ARG 1 - ADDRESS OF A %CPMXW-WORD PACKET BUFFER +;FINDS THE FIRST PACKET ON THE PENDING-RFC QUEUE, COPIES IT +;INTO THE USER'S BUFFER, AND RETURNS IT TO THE QUEUE. +CHAOSQ: MOVE C,A ;SAVE POINTER TO USER'S BUFFER + HRL A,A ;MAKE SURE USER'S BUFFER IS SWAPPED IN + XCTR XBRW,[BLT A,%CPMXW-1(C)] ;AND NO MAR BREAK SET + MOVEI Q,CHQRFC ;GET FIRST PACKET ON RFC QUEUE + PUSHJ P,CHAQGF + JUMPE A,OPNL4 ;QUEUE IS EMPTY + PUSHJ P,CHAQPL ;PUT BACK AT END OF QUEUE + HRL C,A ;COPY PACKET TO USER + MOVE T,C + XCTR XBW,[BLT T,%CPMXW-1(C)] + JRST POPJ1 + +SUBTTL CHAOS NET IOT ROUTINES + +;.CALL PKTIOT. ARG1 CHANNEL, ARG2 ADDRESS OF %CPMXW-WORD BUFFER +PKTIOT: HRRZ A,(R) + CAIN A,CHAODN + JRST CHPKO + CAIE A,CHAIDN + JRST OPNL34 ;WRONG TYPE DEVICE +;CHAOSNET INPUT PKTIOT +;B POINTS TO %CPMXW-WORD PACKET BUFFER +CHPKI: PUSHJ P,CHAIOS ;SET UP I, E + HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER + JUMPE A,[PUSHJ P,CHPKI0 ;LIST EMPTY + JRST CHPKI ] + HRL B,A ;COPY TO USER BEFORE REMOVING FROM LISTS + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + ADDI T,4*%CPKDT+3 ;HEADER PLUS ROUND-UP TO NEXT WORD BOUNDARY + LSH T,-2 ;CONVERT BYTES TO WORDS + ADDI T,-1(B) ;ADDRESS OF LAST DESTINATION WORD + XCTR XBW,[BLT B,(T)] + LDB TT,[$CPKOP(A)] ;GET OPCODE + CAIGE TT,%CODAT ;ACKNOWLEDGE IF DATA + CAIN TT,%COEOF ;OR EOF MARK + PUSHJ P,CHPKIA + SOS CHSNBF(I) ;NOW REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + PUSHJ P,CHABRT ;AND RETURN TO FREE + JRST POPJ1 ;SUCCESS + +;INPUT WITH INPUT BUFFER EMPTY. MUSTN'T BASH B,C,E. +CHPKI0: SKIPGE CHSSTA(I) .SEE %CFOFF + JRST [ HRRZ T,CHSSTA(I) + CAIE T,%CSFRN ;CHAOSNET OR FOREIGN PROTOCOL? + JRST IOCR10 ;IOT WITH CHANNEL IN IMPROPER STATE + JRST .+1 ] ;WAIT BUT DON'T TRY TO TOUCH WINDOW SIZE + ;HERE CONSIDER INCREASING WINDOW SIZE + SKIPN CHSIBF(I) ;AWAIT INPUT + PUSHJ P,UFLS + POPJ P, ;RETRY + +;ACKNOWLEDGE DATA PACKET IN A. ITS OPCODE IN TT. +CHPKIA: LDB T,[$CPKPN(A)] ;GET PACKET # + HRLM T,CHSPKN(I) ;IT NOW NEEDS TO BE ACKNOWLEDGED + CAIN TT,%COEOF ;ALWAYS ACKNOWLEDGE EOF RIGHT AWAY + JRST CHASTO + HLRZ TT,CHSACK(I) ;GET LAST ONE REALLY ACKNOWLEDGED + SUB T,TT ;GET NUMBER OF PACKETS AWAITING ACK + SKIPGE T + ADDI T,200000 + IMULI T,3 ;MORE THAN ONE THIRD THE WINDOW SIZE? +IFN FTRCHK,[ + MOVE TT,-1(A) + CAMN TT,[ASCII/LUNCH/] + BUG PAUSE,[CHAOS BUFFER ADDRESS TRASHED],OCT,A +];FTRCHK + HLRZ TT,CHSWIN(I) + CAML T,TT + PUSHJ P,CHASTO ;YES, SEND ACK (CAN'T PCLSR) + POPJ P, + +;SET UP FOR CHAOS IOT +CHAIOS: HLRZ I,(R) ;GET INDEX + MOVE E,CHSSTA(I) + TLNE E,%CFSTY+%CFCLS + JRST IOCR10 ;CAN'T DO I/O WHILE DIRECT-CONNECTED OR HALF-CLOSED + HRRZS E ;RETURN STATE IN E + POPJ P, + +;UNIT-MODE INPUT. +;1.4 IN CTLBTS IS DON'T-HANG MODE + SKIPA T,[SIOKT] +CHAUI: MOVEI T,CHRKT + PUSHJ P,CHAIOS ;SET UP I, E + MOVE E,[440800,,4] + JSP B,(T) + CHSIBP(I) + CHSIBC(I) + CHAIBG + CHAIBD + 0 + TRNA + +;CHAOS INPUT BUFFER DISCARD +CHAIBD: SKIPN A,CHSIBP(I) + POPJ P, + SETZM CHSIBP(I) + SETZM CHSIBC(I) + JRST CHBPFR + +;CHAOS INPUT BUFFER GET +CHAIBG: HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER + JUMPE A,CHAIB2 ;NONE + LDB TT,[$CPKOP(A)] ;IS IT NORMAL DATA? + CAIE TT,%CODAT + JRST CHAIB1 ;NO + PUSHJ P,CHAIB3 ;YES, ACKNOWLEDGE AND REMOVE FROM LIST + LDB J,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEI TT,%CPKDT(A) + JRST SIOBG1 + +CHAIB3: PUSH P,B + PUSH P,C + PUSH P,E + PUSHJ P,CHPKIA ;SEND ACKNOWLEDGEMENT + POP P,E + POP P,C + POP P,B + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + JRST CHAQGF + +CHAIB1: CAIE TT,%COEOF + JRST CHAIB2 + PUSHJ P,CHAIB3 ;EOF PACKET, ACKNOWLEDGE IT + PUSHJ P,CHABRT ;RETURN IT TO FREE + JRST POPJ2 ;AND SIGNAL EOF + +CHAIB2: MOVE TT,CTLBTS(U) ;CHECK DON'T-HANG MODE + TRNE TT,10 + JRST POPJ2 ;YES, EOF + JUMPN A,IOCR10 ;NO, ABNORMAL PACKET, BARF + PUSHJ P,CHPKI0 ;AWAIT INPUT + JRST CHAIBG ;RETRY + +;UNIT-MODE OUTPUT. +;1.4 IN CTLBTS IS DON'T-HANG MODE + SKIPA T,[SIOKT] +CHAUO: MOVEI T,CHRKT + PUSHJ P,CHAIOS ;SET UP I, E + CAIE E,%CSOPN + JRST IOCR10 ;NOT OPEN, ERROR + MOVE E,[440800,,4] + JSP B,(T) + SETZ CHSOBP(I) + CHSOBC(I) + CHAOBG + CHAOBW + 0 + TRNA + +;GET NEW OUTPUT BUFFER +CHAOBG: SKIPG CHSNOS(I) ;WINDOW FULL + PUSHJ P,[ MOVE TT,CTLBTS(U) + TRNN TT,10 + JRST UFLS + SUB P,[1,,1] + JRST POPJ2 ] ;DON'T HANG MODE, RETURN "EOF" + PUSH P,B + PUSHJ P,CHABGT ;SET UP AN OUTPUT BUFFER + POP P,B + + MOVEI TT,%CPKDT(A) + MOVEI J,%CPMXC + JRST SIOBG1 + +;WRITE OUTPUT BUFFER +CHAOBW: PUSH P,B + PUSH P,C + PUSH P,E + PUSHJ P,CHAFC1 + POP P,E + JRST POPCBJ + +;CHAOSNET OUTPUT PKTIOT. +;B POINTS TO %CPMXW-WORD PACKET BUFFER +CHPKO: PUSHJ P,CHAIOS ;SET UP I, E + UMOVE H,(B) ;GET HEADER WORD OF USER'S PACKET BUFFER + LDB D,[$CPKNB H] ;GET BYTE COUNT + CAIG D,%CPMXC + TLNE H,(.BM $CPKMV) ;WE DON'T SUPPORT MUPPETS ANY MORE + JRST IOCER3 ;BYTE LENGTH OUT OF BOUNDS + ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS, INCLUDING HEADER WDS + LSH D,-2 + MOVSI J,1(B) ;SAVE ADDRESS+1 OF USER'S PACKET + PUSHJ P,CHABGT ;GET A BUFFER + PUSHJ P,LOSSET ;RETURN IT IF PCLSR + CHPKO2 + MOVEM H,(A) ;STORE PACKET HEADER, NOT STORED WITH BLT + HRRI J,1(A) ; BECAUSE MIGHT HAVE CHANGED AFTER ERROR CHECK + ADDI D,-1(A) + XCTR XBR,[BLT J,(D)] ;COPY USER'S PACKET INTO SYSTEM + AOS (P) ;GOING TO SUCCEED + SKIPGE (A) ;SKIP IF CONTROL PACKET + JRST CHODAT ;DATA + LDB D,[$CPKOP(A)] ;GET OPCODE + CAIGE D,%COMAX ;DISPATCH ON IT + JRST @.+1(D) + OFFSET -. + JRST IOCER3 ;OPCODE OUT OF BOUNDS +%CORFC::JRST CHORFC +%COOPN::JRST CHOOPN +%COCLS::JRST CHOCLS +%COFWD::JRST CHOFWD +%COANS::JRST CHOFWD +%COSNS::JRST IOCER3 +%COSTS::JRST IOCER3 +%CORUT::JRST IOCER3 +%COLOS::JRST IOCER3 +%COLSN::JRST CHOLSN +%COMNT::JRST IOCER3 +%COEOF::JRST CHOEOF +%COUNC::JRST CHOUNC +%COBRD::JRST IOCER9 ;UNTIL I IMPLEMENT IT +%COMAX::OFFSET 0 + +;LOSSET ROUTINE TO RETURN BUFFER A POINTS TO. +CHPKO2: MOVE A,AC0S+A(U) + PUSH P,Q ;MAY CLOBBER ONLY A AND T + PUSHJ P,CHABRT + JRST POPQJ + +;SENDING %COEOF (END-FILE MARK) +CHOEOF: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST IOCR10 + SKIPG CHSNOS(I) + PUSHJ P,UFLS ;WINDOW FULL, WAIT + JRST CHOOP1 ;SEND RETRANSMITTABLE CONTROL PACKET + +;SENDING REQUEST FOR CONNECTION +CHORFC: PUSHJ P,CHORF1 ;RE-INITIALIZE CONNECTION + MOVSI B,777774 ;SAVE DESTINATION HOST, CLEAR OTHER BITS + ANDB B,%CPKD(A) + MOVEM B,CHSFRN(I) + MOVEI E,%CSRFS ;PUT INTO RFC-SENT STATE + JRST CHOOP1 ;GO SEND + +;RE-INITIALIZE CONNECTION WHEN USER OUTPUTS RFC OR LSN +;FLUSHES ANY OLD PACKET BUFFERS, CHANGES UNIQUIZER IN INDEX# +CHORF1: JUMPN E,IOCR10 .SEE %CSCLS ;CONNECTION MUST BE CLOSED + PUSH P,A + PUSH P,B + PUSHJ P,CHACS1 ;FLUSH BUFFERS FROM CONNECTION + PUSHJ P,CHASO4 ;REINITIALIZE VARIABLES + JRST POPBAJ + +;"SENDING" LISTEN +CHOLSN: PUSHJ P,CHORF1 + PUSHJ P,LSWDEL ;GOING TO USE PACKET + MOVEI E,%CSLSN ;PUT INTO LISTENING STATE + HRRM E,CHSSTA(I) + MOVEI Q,CHQRFC ;NOW SEARCH PENDING-RFC QUEUE + CONO PI,NETOFF + PUSHJ P,CHAQSR + JRST [ CONO PI,NETON ;NO MATCH, PUT ONTO LISTENING QUEUE + MOVEI Q,CHQLSN + MOVE T,CHSLCL(I) + MOVEM T,%CPKS(A) + JRST CHAQPL ] + PUSHJ P,CHIRF0 ;MATCH, JOIN INTERRUPT LEVEL CODE + JRST NETONJ + +;SENDING OPEN +CHOOPN: CAIE E,%CSRFC ;CONNECTION MUST BE RFC-RECEIVED + JRST IOCR10 + MOVEI TT,4 ;SET BYTE COUNT TO 4 + DPB TT,[$CPKNB(A)] + PUSHJ P,DPBRCP ;INCLUDE RECEIPT + HLRZ B,CHSWIN(I) ;INCLUDE WINDOW SIZE + DPB B,[042000,,%CPKDT(A)] + MOVEI E,%CSOPN ;MAKE IT OPEN +;HERE TO SEND A RETRANSMITTABLE CONTROL PACKET (RFC OR OPN), NEW STATE IN E +;THIS PACKET WILL GET TAKEN OFF THE CHSOBF LIST BY RECEIPT IN THE NORMAL WAY +;THIS CODE COPIED FROM CHODAT WITH SOME MODIFICATIONS +CHOOP1: MOVE T,TIME ;UPDATE CHSITM SO WON'T THINK HOST IS DOWN + MOVEM T,CHSITM(I) + MOVEM E,CHSSTA(I) ;AND CLEAR %CFOFF (NO OTHER LH FLAGS CAN BE ON) + PUSHJ P,LSWDEL ;BUFFER WILL BE USED + HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER + CAIL B,177777 + TDZA B,B + ADDI B,1 + HRRM B,CHSPKN(I) + DPB B,[$CPKPN(A)] + HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE + HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN + DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE + MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] + ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD + MOVE B,CHSLCL(I) ;SET UP SOURCE + MOVEM B,%CPKS(A) + MOVE D,CHSFRN(I) ;SET UP DESTINATION + MOVEM D,%CPKD(A) + SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET + CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT + CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A + ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE + ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. + MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST + PUSHJ P,CHAQPL + JRST CHAXM0 ;GO TRANSMIT + +;SENDING CLOSE +CHOCLS: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN +;SEND FWD OR ANS +CHOFWD: CAIN E,%CSRFC ; OR RFC-RECEIVED + TLOA E,%CFOFF ;PUT IT INTO THE CLOSED STATE + JRST IOCR10 + HLLZM E,CHSSTA(I) .SEE %CSCLS + PUSHJ P,LSWDEL ;BUFFER WILL BE USED + JRST CHODT2 ;GO TRANSMIT + +;Here for transmitting an UNC packet. It could be part of a connection +;or it could be foreign-protocol mode. In any case transmit it without +;munging the header very much. +CHOUNC: CAIN E,%CSFRN + JRST CHOUN1 ;Okay to transmit UNC now + CAIN E,%CSOPN + JRST CHOUN2 + JUMPN E,IOCR10 .SEE %CSCLS ;Bad state + SKIPE CHSPBF(I) ;I guess out of order packets would + JRST IOCR10 ; cause some confusion in the NCP. + MOVE E,[%CFOFF,,%CSFRN] ;Put into foreign-protocol state + MOVEM E,CHSSTA(I) +CHOUN1: MOVE D,%CPKD(A) ;Save destination + MOVEM D,CHSFRN(I) +CHOUN3: MOVE B,CHSLCL(I) ;Set up source + MOVEM B,%CPKS(A) + PUSHJ P,LSWDEL + SETOM -2(A) + JRST CHAXMT + +CHOUN2: MOVE D,CHSFRN(I) ;Set up destination + MOVEM D,%CPKD(A) + JRST CHOUN3 + +OVHMTR CHX + +;SENDING REGULAR PACKET +CHODAT: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST IOCR10 + SKIPG CHSNOS(I) + PUSHJ P,UFLS ;WINDOW FULL, WAIT + PUSHJ P,LSWDEL ;BUFFER WILL BE USED +CHODT1: HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER + CAIL B,177777 + TDZA B,B + ADDI B,1 + HRRM B,CHSPKN(I) + DPB B,[$CPKPN(A)] +CHODT2: HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE + HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN + DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE + MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] + ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD + MOVE B,CHSLCL(I) ;SET UP SOURCE + MOVEM B,%CPKS(A) + MOVE D,CHSFRN(I) ;SET UP DESTINATION + MOVEM D,%CPKD(A) + SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET + SKIPL (A) ;SKIP IF DATA PACKET + JRST CHAXMT + CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT + CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A + ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE + ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. + MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST + PUSHJ P,CHAQPL + SOSA CHSNOS(I) ;USE UP WINDOW, SKIP +;SKIPS THROUGH INTO CHAXMT + ;SKIPS IN +SUBTTL CHAOS NET PACKET TRANSMIT ROUTINE + +;CALL WITH PACKET IN A, SMASHES B, C, D, E, T, TT, Q, J +;USES E TO SAVE THE PI STATUS, NOTHING BETTER CLOBBER THIS, OR, BOY, WILL IT EVER LOSE! +;YOU BETTER SETOM -2(A) BEFORE CALLING THIS, AND IF YOU'RE +;PUTTING IT ON A SEND LIST, DO THAT FIRST ALSO. +;THIS CODE ASSUMES THERE IS ONLY ONE INTERFACE, AND IT IS ON A +;PDP11 WHICH WILL TAKE CARE OF THE ROUTING. +;;THIS ROUTINE IS SKIPPED INTO FROM THE PREVIOUS PAGE! +CHAXMT: CONI PI,E ;SAVE PI STATUS BEFORE TURNING NETOFF; CALLED FROM MANY LEVELS +CHAXM0: ANDI E,177 + AOS CHNPO + MOVE T,TIME + MOVEM T,-1(A) ;SET TIME OF LAST TRANSMISSION + CONO PI,NETOFF ;ONE PROCESS AT A TIME, TO PROTECT INTERFACE VARIABLES +IFN FTRCHK,[ + HLRZ J,-2(A) ;I TOLD YOU TO SETOM -2(A) + CAIE J,-1 + BUG PAUSE,[CHAOS BUFFER THREAD TRASHED],OCT,A,OCT,-2(A) +];FTRCHK +IFN DLCP,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE DL10 +IFN FTRCHK,[ + HLRZ J,DLCXMQ ;MAKE SURE NOT PUTTING ON LIST TWICE + JUMPE J,.+7 + CAMN J,A + BUG PAUSE,[CHAOS BUFFER ALREADY ON DLCXMQ],OCT,A + HLRZ J,-2(J) + CAIN J,-1 + BUG PAUSE,[DLCXMQ THREAD TRASHED] + JUMPN J,.-5 + MOVEI J,1 ;MAKE SURE NOT ACTIVE TO 11 + HRRZ T,DLCSA1(J) + CAMN T,A + BUG PAUSE,[CHAOS BUFFER ALREADY ACTIVE TO 11],OCT,A + SOJGE J,.-3 +];FTRCHK + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH (FLAGS TRANSMIT ACTIVE) + MOVE J,DLCSBF ;SEE IF SEND BUFFER IS FREE + SKIPE DLCSS1(J) + JRST CHXMD1 + PUSHJ P,DLCXMT ;YES, SEND THE PACKET NOW + JRST CHXMD2 + +CHXMD1: HRRZ B,DLCXMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE + JUMPE B,[ HRLZM A,DLCXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,DLCXMQ +CHXMD2: CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];DLCP +IFN T11CHP,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE TEN11 + PUSHJ P,T11CHK ;SEE IF TEN-11 IS READY + JRST CHXME3 ;NO + SKIPE @T11OBP ;SEE IF HAVE AVAILABLE OUTPUT BUFFER + JRST CHXME1 ;NO + PUSHJ P,T11XMT ;SEND THE PACKET NOW + JRST CHXME2 + +CHXME3: HRROS T,-2(A) ;TEN11 DOWN, DISCARD PACKET + AOJN T,CHXME2 + PUSHJ P,CHABRT + JRST CHXME2 + +CHXME1: HRRZ B,T11XMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE + JUMPE B,[ HRLZM A,T11XMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,T11XMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH +CHXME2: CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];T11CHP +IFN CH10P,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH10 + HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE + JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,CHXXMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH + MOVEI B,CHXTEN ;ENABLE TRANSMIT-DONE INTERRUPT + IORM B,CHXCNO + CONO CHX,@CHXCNO + CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];CH10P +IFN CH11P,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH11 + HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE + JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,CHXXMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH + MOVEI B,%CATEN ;ENABLE TRANSMIT-DONE INTERRUPT + IORB B,CHXCSR + IOWRI B,CAICSR + CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];CH11P + +SUBTTL CHAOS NET DIRECT CONNECT TO STY + +OVHMTR CHS + +;CALLED AT CLOCK LEVEL FROM STYNTC WHEN A CHAOS STY IS ENCOUNTERED +;TTY NUMBER IN I & R +STYCHA: MOVE I,STYNTI-NFSTTY(R) ;GET CHAOS INDEX + MOVE TT,CHSSTA(I) + TLNN TT,%CFSTY + JRST 4,. ;CHAOS CONNECTION CLAIMS NOT BE CONNECTED? + JUMPL TT,STYCH9 .SEE %CFOFF ;OK TO USE? IF NOT, DISCONNECT + SKIPGE TTYOAC(R) ;ANY OUTPUT? + JRST STYCH1 ;NO, CHECK FOR INPUT + SKIPN D,CHSOBP(I) ;IF BUFFER ALLOCATED, USE IT + JRST [ SKIPG CHSNOS(I) ;OTHERWISE ALLOCATE ONE + JRST STYCH1 ;WINDOW FULL, WAIT UNTIL REACTIVATED + PUSHJ P,CHABGI + JRST STYCH3 ;NO CORE, WAIT ONE CLOCK TICK + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSOBP(I) + MOVEI E,%CPMXC + MOVEM E,CHSOBC(I) + JRST .+3 ] + SKIPG E,CHSOBC(I) + JRST STYCH4 ;BUFFER FULL, FORCE IT + EXCH R,I ;I GETS TTY, R GETS CHAOS + CONO PI,TTYOFF + MOVEM D,DBBBP ;SET UP BUFFER FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;GENERATE OUTPUT + SETZM TYPNTF + POP P,R + EXCH R,I ;I GETS CHAOS, R GETS TTY + MOVE D,DBBBP ;ADVANCE POINTERS + MOVEM D,CHSOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ;MINUS # CHARS OUTPUT GENERATED + CONO PI,TTYON + ADDM E,CHSOBC(I) +STYCH4: PUSHJ P,CHAFC1 ;FORCE THE BUFFER + JRST STYCHA ;CHECK FOR MORE OUTPUT + +STYCH3: PUSHJ P,CHINTI ;REACTIVATE SO WILL COME BACK ON NEXT CLOCK TICK +STYCH1: SOSGE CHSIBC(I) ;GET INPUT, IF ANY + JRST [ PUSHJ P,CHAIBD ;DISCARD EXHAUSTED INPUT BUFFER, IF ANY + HLRZ A,CHSIBF(I) + JUMPE A,STYNT8 ;NONE, RETURN TO STYNTC + LDB TT,[$CPKOP(A)] + CAIE TT,%CODAT + JRST STYCH9 ;RANDOM PACKET, DISCONNECT + PUSHJ P,CHPKIA ;ACKNOWLEDGE GOBBLING OF THIS PACKET + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + LDB E,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEM E,CHSIBC(I) + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSIBP(I) + JRST STYCH1 ] + ILDB A,CHSIBP(I) ;GET CHARACTER OF INPUT + TRNE A,200 + JRST [ AOS CHSIBC(I) ;WOOPS, SPECIAL CHARACTER, NEEDS USER ATTENTION + MOVSI A,8_14 ;SO PUT IT BACK AND DISCONNECT + ADDM A,CHSIBP(I) + JRST STYCH9 ] + EXCH R,I ;I GETS TTY, R GETS CHAOS + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL + CONO PI,TTYON + POP P,R + POP P,I ;I GETS CHAOS, R GETS TTY ((POP IN REVERSE ORDER)) + JRST STYCH1 ;TRY FOR MORE INPUT + +STYCH9: PUSH P,I + MOVE I,R ;I GETS TTY + PUSHJ P,NSTYN0 ;DISCONNECT THE STY + JRST 4,. + POP P,I ;I GETS CHAOS + PUSHJ P,CHINTI ;WAKE UP THE TELNET SERVER + JRST STYNT8 ;GO HANDLE OTHER STYS + +SUBTTL CHAOS NET CLOCK LEVEL STUFF + +OVHMTR CHC + +;HERE FROM 1/2 SECOND CLOCK. DO RETRANSMISSIONS AND DELAYED STS'S +CHACLK: +IFN DLCP,[ + CONO PI,NETOFF + PUSHJ P,DLCIBG ;GET MEMORY FOR INPUT BUFFERS IF NEEDED + CONO PI,NETON +];DLCP + MOVEI I,NINDX-1 ;SCAN ALL INDICES +CHACL0: SKIPL CHSUSR(I) ;SKIP THIS ONE IF NOT IN USE + SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL + SOJGE I,CHACL0 + JUMPL I,CPOPJ ;JUMP IF ALL INDICES DONE + PUSHJ P,CHARTR ;RETRANSMIT IF NEEDED + MOVSI B,%CFSTS + TDNE B,CHSSTA(I) ;SEND STS IF NEEDED + PUSHJ P,CHASTO + SOJGE I,CHACL0 + POPJ P, + +;HERE EVERY 5 SECONDS, TO DO PROBES +CHA5CL: MOVEI I,NINDX-1 ;SCAN ALL INDICES +CHA5C0: SKIPL CHSUSR(I) ;SKIP IF THIS ONE NOT IN USE + SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL +CHA5C1: SOJGE I,CHA5C0 + JUMPL I,CHA5C4 ;JUMP IF ALL INDICES DONE + MOVE T,TIME + SUB T,CHSITM(I) ;TIME SINCE LAST COMMUNICATION FROM OTHER END + CAILE T,90.*30. + JRST [ MOVEI W,%CSINC ;TOO LONG, CONNECTION BROKEN + PUSHJ P,CHINT + JRST CHA5C1 ] + HRRZ B,CHSSTA(I) ;ONLY PROBE IF OPEN (COULD BE RFC-SENT) + CAIE B,%CSOPN + JRST CHA5C1 + HRRZ B,CHSWIN(I) ;SEE IF NO TRANSMIT WINDOW (LOST STS DURING OPEN) + JUMPE B,CHA5C2 + HRRZ B,CHSACK(I) ;SEE IF AWAITING ACK (WINDOW NOT EMPTY) + HRRZ C,CHSPKN(I) + CAMN B,C + CAIL T,60.*30. +CHA5C2: PUSHJ P,CHABGI ;AWAITING ACK OR IDLE FOR 1 MINUTE, PROBE + JRST CHA5C1 ;NO PROBE, OR NO BUFFER AVAILABLE + MOVSI T,(.DPB %COSNS,($CPKOP),0) ;SENSE PACKET, BYTE-COUNT=0 + MOVEM T,(A) + AOS CHNSNS + PUSHJ P,CHODT2 + JRST CHA5C1 + +CHA5C4: MOVEI B,[ASCIZ/Timeout/] + MOVEI Q,CHQRFC ;TIME-OUT FIRST RFC ON LIST + PUSHJ P,CHAQGF + JUMPE A,CHA5C5 + MOVE T,-1(A) + ADDI T,60.*30. ;TIME-OUT IS ONE MINUTE + PUSHJ P,[ CAMG T,TIME + JRST CHIRF2 + JRST CHAQPF ] +CHA5C5: +IFN CH10P,[ + MOVEI T,CHXREN+CHXTEN ;WAKE UP IN CASE OF TIMING ERROR + IORM T,CHXCNO ;IN DEALING WITH CHXCNO + CONO CHX,@CHXCNO + MOVSI T,-NSUBNT ;DECAY ROUTING COSTS + CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN +CHA5C6: HLRZ TT,SBNRUT(T) + ADDI TT,1 + CAIG TT,1000 + HRLM TT,SBNRUT(T) + AOBJN T,CHA5C6 + CONO PI,NETON +];CH10P +IFN CH11P,[ + MOVEI T,%CAREN+%CATEN ;WAKE UP IN CASE OF TIMING ERROR + IORB T,CHXCSR ;IN DEALING WITH CHXCSR + IOWRI T,CAICSR + MOVSI T,-NSUBNT ;DECAY ROUTING COSTS + CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN +CHA5C6: HLRZ TT,SBNRUT(T) + ADDI TT,1 + CAIG TT,1000 + HRLM TT,SBNRUT(T) + AOBJN T,CHA5C6 + CONO PI,NETON +];CH11P + MOVEI T,5*60. + MOVEI C,CHA5CK + JRST CLQREE + +OVHMTR CHR + +;RETRANSMIT FOR INDEX IN I +CHARTR: CONI PI,W ;SAVE PI CHANNELS ACTIVE + ANDI W,177 ;CHAXMT BETTER NOT CLOBBER W! + CONO PI,NETOFF ;PI BETTER BE OFF THROUGHOUT THIS ZONE + ; SO WE DON'T GET INTO CHIACK + HLRZ A,CHSOBF(I) ;SCAN DOWN OUTPUT BUFFER LIST + JUMPE A,CHART2 ;EMPTY +CHART1: MOVE T,-1(A) ;DON'T RETRANSMIT IF DONE TOO RECENTLY + HLRZ TT,-2(A) ;OR IF ALREADY ON ITS WAY OUT (DON'T LINK TWICE ON XMIT LIST) + CAME T,TIME + CAIE TT,-1 + JRST CHART2 ;ANYTHING AFTER THIS IS LIKELY TO LOSE ALSO + AOS CHNRTR + PUSHJ P,CHAXMT ;RETRANSMIT THIS +; HRRZ A,-2(A) ;THREAD TO NEXT +; JUMPN A,CHART1 +CHART2: CONO PI,PICON(W) + POPJ P, + +;THIS ROUTINE SENDS A STS PACKET, OR TRIES TO. FAILURE => SLOW CLOCK WILL TRY AGAIN. +;CANNOT PCLSR NOR WAIT, CALLABLE FROM INTERRUPT LEVEL. +;INDEX IN I, CLOBBERS A,B,C,D,E,T,TT,Q,J +CHASTO: MOVSI D,%CFSTS + IORM D,CHSSTA(I) + PUSHJ P,CHABGI ;GET A BUFFER, WITHOUT WAITING + POPJ P, ;CAN'T GET ONE, WILL RETRY AT CLOCK LEVEL + ANDCAM D,CHSSTA(I) ;OK, A STS WILL BE SENT, CLEAR NEED-STS FLAG + MOVE T,[.DPB %COSTS,($CPKOP),<.DPB 4,($CPKNB),0>] + MOVEM T,(A) ;SEND A STS WITH 4 DATA BYTES + PUSHJ P,DPBRCP ;FIRST PAIR IS RECEIPT + HLRZ B,CHSWIN(I) ;SECOND PAIR IS WINDOW SIZE + DPB B,[042000,,%CPKDT(A)] + AOS CHNSTS + JRST CHODT2 ;FIRE IT OFF + +DPBRCP: HLRZ B,CHSPKN(I) + SKIPE T,CHSIBF(I) + LDB B,[$CPKPN(T)] + DPB B,[242000,,%CPKDT(A)] + POPJ P, + +SUBTTL CHAOS NET INTERRUPT-LEVEL INPUT PROCESSING + +OVHMTR CHI + +;PROCESS A PACKET RECEIVED AT INTERRUPT LEVEL. BY THE TIME WE GET HERE +; A BUFFER HAS BEEN ALLOCATED AND FILLED WITH THE DATA FROM THE DEVICE. +; ITS ADDRESS IS IN A. RETURN VIA POPJ P, WITH ALL REGISTERS CLOBBERED. +CHAPII: MOVE B,RECHDP ;SAVE HEADER FOR DEBUGGING IN RING BUFFER + MOVEI D,%CPKDT(B) + HRL B,A + BLT B,-1(D) + CAIN D,RECHDR+ + MOVEI D,RECHDR + MOVEM D,RECHDP + ;END OF DEBUGGING CODE + LDB D,[$CPKMV(A)] ;MUPPET? + JUMPN D,CHABRT ;FLUSH, NOT SUPPORTED + LDB D,[$CPKOP(A)] ;GET OPCODE + LDB B,[$CPKDA(A)] ;CHECK DESTINATION + CAIE B,MYCHAD ;IF FOR ME, + SKIPN B ;OR FOR ME BY VIRTUE OF BROADCAST + AOSA CHNPI ;ACCEPT IT + JRST CHAPFW ;NOT ME, FORWARD + LDB C,[$CPKNB(A)] ;PASS LENGTH IN C TO OP ROUTINES + MOVEI B,[ASCIZ/Illegal byte count/] + CAILE C,%CPMXC + JRST CHALOS + SKIPGE (A) ;TEST OPCODE + JRST CHIDAT ;DATA PACKET + MOVEI B,[ASCIZ/Illegal opcode/] + CAIGE D,%COMAX + JRST @.+1(D) + OFFSET -. + JRST CHALOS ;ILLEGAL, FLUSH +%CORFC::JRST CHIRFC +%COOPN::JRST CHIOPN +%COCLS::JRST CHICLS +%COFWD::JRST CHIANS +%COANS::JRST CHIANS +%COSNS::JRST CHISNS +%COSTS::JRST CHISTS +%CORUT:: +IFE CH10P+CH11P,JRST CHABRT ;IGNORE +IFN CH10P+CH11P,JRST CHIRUT +%COLOS::JRST CHILOS +%COLSN::JRST CHALOS ;ILLEGAL, FLUSH +%COMNT::JRST CHABRT ;IGNORE +%COEOF::JRST CHIDAT +%COUNC::JRST CHIUNC +%COBRD::JRST CHIBRD +%COMAX::OFFSET 0 + +;FORWARDING +CHAPFW: LDB B,[$CPKDA(A)] ;CHECK DESTINATION HOST + TRNN B,377_8 ;SUBNET 0? + JRST CHABRT ;FLUSH IT, XX-NETWORK-11 IS TRYING TO MAKE US CRASH + LDB B,[$CPKFC(A)] ;INCREMENT FORWARDING COUNT + ADDI B,1 + CAIL B,20 + JRST [ AOS CHNPFL ? JRST CHABRT ] ;LOOP, DISCARD + DPB B,[$CPKFC(A)] + SETOM -2(A) ;NOT ON SEND LIST + AOS CHNPF + JRST CHAXMT + +IFN CH10P+CH11P,[ ;INCOMING ROUTING INFO +CHIRUT: LSH C,-2 ;NUMBER OF SUBNET ENTRIES + JUMPE C,CHABRT ;COULD BE ZERO-LENGTH + MOVEI D,%CPKDT(A) + HRLI D,442000 + LDB E,[$CPKSA(A)] ;SOURCE HOST IS GATEWAY +CHIRU1: ILDB T,D ;SUBNET + ILDB TT,D ;COST + HLRZ B,SBNRUT(T) ;COST OF EXISTING ROUTE + CAIGE T,NSUBNT + CAMLE TT,B + JRST CHIRU2 + HRLM TT,SBNRUT(T) ;THIS IS BEST ROUTE NOW + HRRM E,SBNRUT(T) +CHIRU2: SOJG C,CHIRU1 + JRST CHABRT +];CH10P+CH11P + +;INTERRUPT-LEVEL PROCESSING OF SNS PACKET +;NOTE THAT WE DO NOT BARF AT SNS'S TO EXISTENT NON-OPEN CONNECTIONS. IF IT +;WAS AN RFC-SENT CONNECTION, THIS COULD BREAK IT PREMATURELY IF AN OPN WAS +;LOST AND THEN A SNS WAS NOT. +CHISNS: MOVEI E,%CSOPN + PUSHJ P,CHFNDX + JRST [ CAIE E,%CSOPN + JRST CHABRT ;CONNECTION EXISTS AND IS NOT OPEN, IGNORE PACKET + JRST CHALOS ] ;CONNECTION DOES NOT EXIST, COMPLAIN + PUSHJ P,CHABRT ;CONNECTION DOES EXIST + CAIE E,%CSOPN + POPJ P, ;NOT OPEN, IGNORE + JRST CHASTO ;REPLY WITH STS + +;INTERRUPT LEVEL PROCESSING OF RECEIVED FWD OR ANS +CHIANS: PUSHJ P,CHFNDX ;FIND CONNECTION + JRST CHABRT ;NOBODY AT OTHER END TO RECEIVE A LOS ANYWAY + CAIE E,%CSRFS + JRST CHABRT ;NOT IN RFC-SENT STATE, LOSS +; JRST CHICL1 ;CLOSE THE CONNECTION BUT GIVE TO USER AS INPUT + ;DROPPING THROUGH WILL DO + +;INTERRUPT LEVEL PROCESSING OF RECEIVED CLS PACKET +CHICLS: PUSHJ P,CHFNDX ;FIND CONNECTION BEING CLOSED + JRST CHALOS ;NONE, LOSS +CHICL1: MOVEI W,%CSCLS ;CLOSE THE CONNECTION +CHICL2: PUSHJ P,CHINT ;SET TO STATE IN W, INTERRUPT + PUSH P,A + MOVEI Q,CHSPBF(I) ;DISCARD OUT-OF-ORDER PACKETS + PUSHJ P,CHALFR + HRRZS CHSNBF(I) +CHIC2A: MOVEI Q,CHSOBF(I) ;DISCARD TRANSMIT PACKETS, E.G. RFC WHICH RECEIVED + PUSHJ P,CHAQGF ;AN ANS OR FWD, DON'T WANT TO TRANSMIT AGAIN + JUMPE A,CHIC2B + PUSHJ P,CHABR1 + JRST CHIC2A + +CHIC2B: POP P,A + JRST CHIDT1 ;GIVE PACKET TO USER AS DATA + ;INTERRUPT LEVEL PROCESSING OF RFC PACKET +CHIRFC: MOVE T,%CPKDT(A) ;CHECK FOR STATUS REQUEST + CAMN T,[.BYTE 8 ? "S ? "T ? "A ? "T] + CAIE C,6 + JRST CHIRF7 + MOVS TT,%CPKDT+1(A) + XORI TT,(<.BYTE 8 ? "U ? "S>) + TRNN TT,(<.BYTE 8 ? -1 ? -1>) + JRST CHIRF3 +CHIRF7: MOVEI Q,CHQLSN ;SEARCH LISTENING QUEUE + PUSHJ P,CHAQSR + JRST CHIRF1 ;NOT FOUND, LOAD SERVER + EXCH A,B ;A LSN, B RFC + LDB I,[$CPKSX(A)] ;GET CORRESPONDING INDEX + HRRZ E,CHSSTA(I) + CAIE E,%CSLSN + JRST 4,. +CHIRF0: PUSHJ P,CHABRT ;FOUND, DISCARD LISTEN PACKET + MOVE A,B ;GET OTHER HOST'S RFC + LDB B,[$CPKPN(A)] ;INITIALIZE RECEIVER'S PACKET NUMBER + HRLM B,CHSPKN(I) + MOVE B,%CPKS(A) + MOVEM B,CHSFRN(I) ;HOOK 'EM UP + MOVEI W,%CSRFC ;PUT INTO RFC-RECEIVED STATE + MOVE T,TIME ;AND ENGAGE PI LEVEL + MOVEM T,CHSITM(I) + JRST CHICL2 + +;RFC RECEIVED AND NOT IMMEDIATELY MATCHED TO A LSN. QUEUE AND LOAD SERVER JOB. +;BUT FIRST CHECK WHETHER THIS IS A DUPLICATE WHICH SHOULD BE DISCARDED. +CHIRF1: MOVE C,%CPKS(A) ;SEARCH PENDING RFC QUEUE FOR RFC FROM + HLRZ T,CHQRFC ;THE SAME SOURCE AS THIS. + JUMPE T,CHIRD1 +CHIRD0: CAMN C,%CPKS(T) + JRST CHABRT ;THIS RFC IS A DUPLICATE, IGNORE IT + HRRZ T,-2(T) + JUMPN T,CHIRD0 +CHIRD1: MOVSI T,-NINDX ;SEARCH OPEN AND RFC-RECEIVED CONNECTIONS +CHIRD2: SKIPL CHSUSR(T) ;FOR ONE CONNECTED TO SAME GUY AS SENT RFC + CAME C,CHSFRN(T) + AOBJN T,CHIRD2 + JUMPGE T,CHIRD3 ;NO DUPLICATE OF THIS RFC, QUEUE IT + HRRZ TT,CHSSTA(T) + CAIE TT,%CSOPN + CAIN TT,%CSRFC + JRST CHABRT ;REALLY A DUPLICATE, DISCARD + AOBJN T,CHIRD2 +CHIRD3: MOVEI B,[ASCIZ/System not up/] + SKIPL SYSDBG ;REFUSE INCOMING CONNECTIONS IF LOGINS REFUSED + SKIPE NETUSW ;ALLOWING INCOMING NET CONNECTIONS? + JRST CHIRF2 ;NO, REFUSE (EVEN IF FROM OURSELVES) + HRROI T,CHIRFJ ;LOAD JOB + CONI PI,Q ;MUST TURN UTCOFF TO CALL NUJBST + ANDI Q,177 ;SINCE THIS MAY RUN AT OTHER INT LEVELS + CONO PI,NETOFF + PUSHJ P,NUJBST + JRST [ CONO PI,PICON(Q) + JRST CHABRT ] ;RING BUFFER FULL, IGNORE, RETRY WILL CATCH + CONO PI,PICON(Q) + MOVE T,TIME ;REMEMBER WHEN THIS RFC WAS QUEUED + MOVEM T,-1(A) + MOVEI Q,CHQRFC + JRST CHAQPF ;PUT ON FRONT OF QUEUE + +;COME HERE TO SEND A LOS PACKET IN RESPONSE TO CRUFTY INPUT IN A +;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. +CHALOS: SKIPA T,[%COLOS] +;HERE TO REFUSE AN RFC. TURN IT INTO A CLS AND SEND IT BACK. +;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. +CHIRF2: MOVEI T,%COCLS + HRLI B,440700 ;BP TO MESSAGE + SETZB C,(A) .SEE $CPKFC + DPB T,[$CPKOP(A)] + MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION + EXCH T,%CPKD(A) + MOVEM T,%CPKS(A) + MOVE D,[440800,,%CPKDT(A)] +CHIRF4: ILDB T,B + JUMPE T,CHIRF5 + IDPB T,D + AOJA C,CHIRF4 + +CHIRF5: DPB C,[$CPKNB(A)] + SETOM -2(A) ;NOT ON ANY SEND LIST + JRST CHAXMT ;SEND IT + +;HERE FOR RFC TO "STATUS" +EXPUNGE FOO,BAR +DEFINE FOO NAME +BAR==0 +.BYTE 8 +IRPC CH,,NAME +"CH +BAR==BAR+1 +TERMIN +IFG BAR-4, .ERR NAME MORE THAN 4 CHARACTERS +REPEAT 4-BAR, 0 +.BYTE +TERMIN + +CHIRF3: MOVE B,[MNAME FOO ,,] ;NAME OF MACHINE IN 8-BIT ASCII +EXPUNGE FOO,BAR + MOVEM B,%CPKDT(A) + SETZM %CPKDT+1(A) + MOVSI B,%CPKDT+1(A) + HRRI B,%CPKDT+2(A) + BLT B,%CPKDT+7(A) + MOVE B,[.BYTE 8 ? MYCHAD/400 ? 1 ? 4+IFN CH10P+CH11P,[10.] ? 0 ] + MOVEM B,%CPKDT+10(A) + MOVEI B,%CPKDT+11(A) + HRLI B,441000 + MOVE T,CHNPI + PUSHJ P,CHRF3A + MOVE T,CHNPO + PUSHJ P,CHRF3A +IFN CH10P+CH11P,[ + MOVE T,CHNABT + PUSHJ P,CHRF3A + MOVE T,CHNLOS + PUSHJ P,CHRF3A + MOVE T,CHNCRC + PUSHJ P,CHRF3A + MOVE T,CHNCR2 + PUSHJ P,CHRF3A + MOVE T,CHNPLE + ADD T,CHNWLE + PUSHJ P,CHRF3A +];CH10P+CH11P + MOVEI T,%COANS + SETZM (A) .SEE $CPKFC + DPB T,[$CPKOP(A)] + MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION + EXCH T,%CPKD(A) + MOVEM T,%CPKS(A) + MOVEI C,13*4+IFN CH10P+CH11P,[20.] ;BYTE COUNT + JRST CHIRF5 ;SEND + +CHRF3A: MOVEI TT,4 + IDPB T,B + LSH T,-8 + SOJG TT,.-2 + POPJ P, + +;HERE TO CONVERT A BRD INTO AN RFC + +CHIBRD: LDB T,[$CPKAN(A)] ;NUMBER OF BITMAP BYTES + LDB TT,[$CPKNB(A)] ;NUMBER OF TOTAL DATA BYES (INCLUDES BITMAP) + CAIG T,32. ;ACK NUMBER NO GREATER THAN 32. + TRNE T,3 ; MUST BE MULTIPLE OF 4 + JRST CHABRT ; FREE THE PACKET IF NO GOOD + CAMG TT,T ;MUST BE SOME TEXTUAL RFC DATA AS WELL + JRST CHABRT ; IF NOT, FREE PACKET + MOVE C,TT ;GET NUMBER OF BYTES (CHIRFC WANTS COUNT IN C) + SUB C,T ;WITHOUT BITMAP + DPB C,[$CPKNB(A)] ;NEW BYTE COUNT + LSH T,-2 ;CONVERT BITMAP BYTE COUNT TO WORD COUNT + ADDI TT,3 ;CONVERT BYTE COUNT TO... + LSH TT,-2 ;... WORD COUNT + MOVEI D,%CPKDT(A) ;GET POINTER TO BEGINNING OF DATA + HRL D,D ;IN UPPER AND LOWER HALVES (ALMOST BLT POINTER) + HRLZ T,T ;BITMAP WORD COUNT,,0 + ADD D,T ;RFC-STRING,,DATA-FIELD + ADDI TT,%CPKDT-1(A) ;LAST LOCATION FOR BLT + BLT D,(TT) + SETZI TT, + DPB TT,[$CPKAN(A)] ;ZERO THE ACK FIELD + MOVE TT,MYCHAD + DPB TT,[$CPKDA(A)] ;PRETEND IT WAS FOR ME + JRST CHIRFC ;AND HANDLE IT AS AN RFC + + +;ROUTINE TO FIND INDEX PACKET CORRESPONDS TO, SKIP IF FOUND, INDEX IN I. +;ALSO RETURNS STATE IN E SINCE THAT'S OFTEN HANDY. +;ALSO SETS B FOR CHALOS +CHFNDX: MOVEI B,[ASCIZ/Connection does not exist at this end/] + LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX + CAIGE I,NINDX + SKIPGE CHSUSR(I) + POPJ P, ;NO MATCH + SKIPGE CHSSTA(I) .SEE %CFOFF + POPJ P, ;NOT TALKING TO NETWORK + HRRZ E,CHSSTA(I) + MOVE TT,%CPKD(A) + MOVE T,%CPKS(A) + CAIN E,%CSRFS ;IF IN RFC-SENT STATE, ONLY + AND T,[.BYTE 16. ? -1 ? 0] ;THE SOURCE HOST HAS TO MATCH + CAMN TT,CHSLCL(I) ;COMPARE LOCAL ADDRESS + CAME T,CHSFRN(I) ; AND FOREIGN ADDRESS + POPJ P, ;NO MATCH + MOVE T,TIME + MOVEM T,CHSITM(I) + JRST POPJ1 ;SUCCEED, CALLER CHECKS THE STATE + +;INTERRUPT LEVEL PROCESSING OF RECEIVED OPN PACKET +CHIOPN: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE OPENED + JRST CHALOS + CAIE E,%CSRFS ;NOT IN RFC-SENT STATE, + JRST CHABRT ; MUST BE DUPLICATE, DISCARD. + LDB B,[$CPKPN(A)] ;GET ITS PACKET NUMBER + HRLM B,CHSPKN(I) ;INITIALIZE PACKET NUMBERING OF RECEIVED MESSAGES + MOVE B,%CPKS(A) + MOVEM B,CHSFRN(I) ;HOOK 'EM UP + PUSHJ P,CHIST1 ;PROCESS AS A STS, DISCARD + PUSHJ P,CHASTO ;RESPOND WITH A STS + MOVEI W,%CSOPN + ;DROP INTO CHINT + +;COME HERE WITH INDEX IN I AND NEW STATE IN W, TO CHANGE STATE AND INTERRUPT +CHINT: HRRM W,CHSSTA(I) + MOVE T,TIME + MOVEM T,CHSITM(I) ;IN CASE GOT HERE FROM CHOLSN + MOVSI T,%CFOFF + CAIE W,%CSOPN + IORM T,CHSSTA(I) ;DISENGAGE PI LEVEL + CAIN W,%CSOPN + ANDCAM T,CHSSTA(I) ;NOW OPEN, ENGAGE PI LEVEL +;COME HERE TO INTERRUPT ON THE INPUT CHANNEL. SMASHES T,TT,W +CHINTI: LDB T,[$CHSUI,,CHSUSR(I)] +CHINT2: MOVE TT,CHSSTA(I) ;SIGNAL USER OR STY? + TLNN TT,%CFSTY + JRST CHINT4 ;USER + LDB T,[$CFTTN,,TT] ;STY, GET TTY NUMBER + CONO PI,PIOFF ;PROTECT LIST MODIFICATION + SKIPL STYNTL-NFSTTY(T) ;DON'T PUT ON LIST TWICE + JRST PIONJ + MOVE TT,STYNTA ;ADD TO LIST + MOVEM TT,STYNTL-NFSTTY(T) + MOVEM T,STYNTA + JRST PIONJ + +CHINT4: SKIPGE TT,CHSUSR(I) + JRST 4,. + MOVSI W,(SETZ) ;PCLSR THE JOB SO IT GETS AN IOC ERROR IF NEEDFUL + IORM W,PIRQC(TT) ;EVEN IF NORMAL INTERRUPTS ARE NOT ENABLED + CAIN T,77 + POPJ P, ;IOPUSH'D, NO INTERRUPT + MOVE T,CHNBIT(T) + AND T,MSKST2(TT) + IORM T,IFPIR(TT) + POPJ P, + +OVHMTR CHD + +;INTERRUPT LEVEL PROCESSING OF RECEIVED DATA PACKET +CHIDAT: PUSHJ P,CHFNDX ;FIND ASSOCIATED CONNECTION + JRST CHALOS ;NONE, LOSS + CAIE E,%CSOPN ;STATE MUST BE OPEN + JRST CHALOS ;BAD, LOSS + PUSHJ P,CHIACK ;PROCESS ACKNOWLEDGEMENT FIELD +;NOW DECIDE WHETHER IT GOES ON CHSIBF(I), OR ON CHSPBF(I), OR GETS DISCARDED. + HLRZ B,CHSPKN(I) ;LAST PACKET NUMBER GIVEN TO USER + LDB C,[$CPKPN(A)] ;GET PACKET NUMBER OF THE NEW PACKET + HLRZ T,CHSWIN(I) ;RECEIVE WINDOW SIZE + ADDI T,(B) ;HIGHEST LEGAL PACKET NUMBER + SUB T,C + TRNE T,100000 ;SKIP IF T >= C + JRST CHABRT ;FOO ON YOU, OVER WINDOW SIZE + HRRZ T,CHSIBF(I) ;COMPUTE NEXT IN-ORDER PACKET EXPECTED + JUMPE T,CHIDT6 ;BASED ON LAST IN-ORDER PACKET + LDB TT,[$CPKOP(T)] + CAIE TT,%COUNC + JRST [ LDB B,[$CPKPN(T)] + JRST CHIDT6 ] + HLRZ T,CHSIBF(I) ;IF IT'S AN UNC, HAVE TO GO FIND CORRECT PACKET +CHIDT5: LDB TT,[$CPKOP(T)] + CAIE TT,%COUNC + LDB B,[$CPKPN(T)] + HRRZ T,-2(T) + JUMPN T,CHIDT5 +CHIDT6: ADDI B,1 + ANDI B,177777 ;NEXT IN-ORDER PACKET EXPECTED + CAMN B,C + JRST CHIDT1 ;EQUAL, IT GOES ON THE END OF CHSIBF(I) LIST. + SUB B,C ;NOT EQUAL, COMPARE THEM MODULO 2^16. + TRNN B,100000 + JRST CHIDTD ;B GREATER, THIS IS AN OLD PACKET, DISCARD IT + ;PUT ON CHSPBF(I) IN PROPER ORDER + ;A IS THIS PACKET, C IS HIS NUMBER, B IS PREDECESSOR, D IS NEXT, E IS HIS # + MOVEI B,0 ;SIGNIFY AT FRONT OF LIST + HLRZ D,CHSPBF(I) ;GET FIRST PACKET ON OUT-OF-ORDER LIST + JUMPE D,CHIDT4 ;LIST IS EMPTY +CHIDT3: LDB E,[$CPKPN(D)] + SUB E,C ;COMPARE PACKET NUMBERS + JUMPE E,CHIDTD ;DUPLICATE, DISCARD + TRNE E,100000 + JRST [ MOVE B,D ;E IS LESS, KEEP LOOPING + HRRZ D,-2(B) + JUMPN D,CHIDT3 + JRST .+1 ] ;REACHED END PUT IT HERE + SKIPE B + HRRM A,-2(B) ;THREAD ONTO PREVIOUS PACKET + SKIPN D +CHIDT4: HRRM A,CHSPBF(I) ;THREAD ONTO BACK OF LIST + SKIPN B + HRLM A,CHSPBF(I) ;THREAD ONTO FRONT OF LIST + HRRM D,-2(A) ;THREAD IN BEFORE PACKET IN D + MOVSI B,1 + ADDM B,CHSNBF(I) + POPJ P, + +;HERE IT GOES ON CHSIBF(I). A HAS PACKET, C HAS ITS PACKET NUMBER. +;IF GETTING HERE FROM CHICL1, C HAS GARBAGE BUT IT WILL NEVER BE USED. +CHIDT1: SKIPN CHSIBF(I) + PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT + AOS CHSNBF(I) + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQPL ;PUT ON END OF RECEIVE LIST + HLRZ A,CHSPBF(I) ;GET FIRST OUT-OF-ORDER PACKET + JUMPE A,CPOPJ ;NONE + LDB B,[$CPKPN(A)] ;SEE IF THIS PACKET IS NOW IN-ORDER + CAIL C,177777 ;BY COMPARING AGAINST C+1 MODULO 2^16. + TDZA C,C + ADDI C,1 + CAME B,C + POPJ P, ;NO + MOVEI Q,CHSPBF(I) + PUSHJ P,CHAQGF ;YES, PULL PACKET OF OUT-OF-ORDER LIST + MOVSI B,-1 + ADDM B,CHSNBF(I) + JRST CHIDT1 ;AND GO PUT ONTO IN-ORDER LIST + +;HERE IF PACKET IS A DUPLICATE AND IS TO BE DISCARDED. MUST SEND +;RECEIPT TO SHUT OFF EXCESS RETRANSMISSION. +CHIDTD: PUSHJ P,CHABRT + AOS CHNPD + JRST CHASTO + +;HERE FOR RECEIVING AN UNC PACKET +CHIUNC: LDB I,[$CPKDI(A)] ;Destination index zero? + JUMPE I,CHIUN2 + LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX + CAIGE I,NINDX + SKIPGE CHSUSR(I) + JRST CHALOS ;NO MATCH + MOVE TT,%CPKD(A) ;DESTINATION ADDRESS MATCHES? + CAME TT,CHSLCL(I) + JRST CHALOS + HRRZ E,CHSSTA(I) ;IN FOREIGN PROTOCOL MODE? + CAIN E,%CSFRN + JRST CHIUN1 + MOVE TT,%CPKS(A) ;NORMAL PROTOCOL, SOURCE ADDRESS MUST MATCH + CAMN TT,CHSFRN(I) + CAIE E,%CSOPN ;AND STATE MUST BE OPEN + JRST CHALOS +CHIUN1: MOVE TT,TIME + MOVEM TT,CHSITM(I) + SKIPE T,CHSIBF(I) ;DISCARD PACKET IF OVER WINDOW SIZE + JRST [ LDB TT,[$CPKOP(T)] ; AND ALREADY HAVE AN UNC + HRRZ T,CHSNBF(I) + HLRZ Q,CHSWIN(I) + CAML T,Q + CAIE TT,%COUNC + JRST .+2 + JRST CHABRT ] + PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT + AOS CHSNBF(I) ;PUT ON END OF RECEIVE LIST. + MOVEI Q,CHSIBF(I) ;PACKET NUMBER IS RANDOM, NOTHING LOOKS AT IT + JRST CHAQPL + +CHIUN2: +IFE INETP,JRST CHALOS ;No comprendo internet +IFN INETP,[ + LDB I,[$CPKAN(A)] ;Protocol number + CAIE I,8_8 ;DOD Internet #x0800 + JRST CHALOS + AOS CHNIPI ;Meter Internet packets in from Chaosnet + MOVE J,A ;Save Chaosnet packet + LDB A,[$CPKNB(A)] ;Compute size of Internet datagram in words + ADDI A,3 + LSH A,-2 + MOVE C,A ;Save word count + CALL IPGIPT ;Get buffer to copy datagram into + JRST CHIUN3 ;No buffers available, discard packet + MOVSI T,%CPKDT(J) ;Make BLT pointer + HRRI T,1(B) + ADDI B,(C) ;Address of last destination word + BLT T,(B) + EXCH A,J ;Free the Chaosnet packet + CALL CHABRT + MOVE A,J ;Datagram structure + MOVE B,C ;Word count + MOVEI C,0 ;Offset to start of IP header + CALRET IPRDGM ;Dispose of datagram + +CHIUN3: MOVE A,J ;Discard Chaosnet packet + CALRET CHABRT +];INETP + +OVHMTR CHJ + +;INTERRUPT LEVEL PROCESSING OF LOS +CHILOS: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE BROKEN + JRST CHABRT ;NONE, IGNORE + MOVEI W,%CSLOS ;PUT INTO LOST STATE + JRST CHICL2 ;GIVE PACKET TO USER AS DATA, DISENGAGE, AND INTERRUPT + +;INTERRUPT LEVEL PROCESSING OF STS +CHISTS: PUSHJ P,CHFNDX + JRST CHALOS + CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST CHALOS +CHIST1: LDB B,[042000,,%CPKDT(A)] ;GET NEW WINDOW SIZE + CAILE B,MXWIND + MOVEI B,MXWIND + HRRM B,CHSWIN(I) + LDB B,[242000,,%CPKDT(A)] ;PROCESS RECEIPT + PUSHJ P,CHIAK0 + PUSHJ P,CHABRT + JRST CHARTR ;RETRANSMIT + +OVHMTR CHA + +;INTERRUPT LEVEL PROCESSING OF RECEIVED ACKNOWLEDGEMENT. +;REMOVE THE ACKNOWLEDGED PACKETS FROM THE INDEX'S SEND LIST AND UPDATE CHSNOS(I). +;NOTE THAT THE LIST IS ASSUMED TO BE SORTED SO WE ONLY +;REMOVE PACKETS FROM THE FRONT. CLOBBERS B,C,D,T,TT,Q. +CHIACK: LDB B,[$CPKAN(A)] ;PACKET NUMBER BEING RECEIPTED +CHIAK0: LDB T,[$CPKAN(A)] ;ENTER HERE FROM CHISTS + HRRZ D,CHSACK(I) ;GET MAX OF THIS ACKNOWLEDGE AND PREVIOUS + SUB D,T + TRNE D,100000 + HRRM T,CHSACK(I) ;ACKNOWLEDGED PACKET NUMBER IS NEW START OF WINDOW + PUSH P,A + HLRZ A,CHSOBF(I) ;MAP DOWN SEND LIST + JUMPE A,CHIAK2 ;LIST EMPTY +CHIAK1: LDB D,[$CPKPN(A)] + SUBM B,D + TRNE D,100000 + JRST CHIAK2 ;RCP# LESS THAN PKT# + HRRZ C,-2(A) ;GET NEXT PACKET + HLLOS D,-2(A) ;MARK NOT ON SEND LIST + AOJE D,CHIAK3 ;AND JUMP IF NOT ON TRANSMIT LIST +IFN DLCP,[ + MOVEI Q,DLCXMQ ;ON TRANSMIT LIST, TRY TO TAKE OFF + PUSHJ P,CHIAKF +];DLCP +IFN T11CHP,[ + MOVEI Q,T11XMQ + PUSHJ P,CHIAKF +];T11CHP +IFN CH10P+CH11P,[ + MOVEI Q,CHXXMQ + PUSHJ P,CHIAKF +];CH10P+CH11P + CAIA ;AND DON'T FREE IT +CHIAK3: PUSHJ P,CHABRT + HRLM C,CHSOBF(I) + SKIPE A,C + JRST CHIAK1 + SETZM CHSOBF(I) ;SEND LIST NOW EMPTY +CHIAK2: MOVE D,CHSNOS(I) ;COMPUTE NEW VALUE OF CHSNOS + HRRZ T,CHSACK(I) ;START OF WINDOW + HRRZ C,CHSPKN(I) ;LAST PACKET SENT + SUB T,C + SKIPLE T + SUBI T,200000 ;T GETS NEGATIVE AMOUNT OF WINDOW OCCUPIED + ADD T,CHSWIN(I) ;RH(T) GETS AVAILABLE PORTION OF WINDOW + HRREM T,CHSNOS(I) ;WHICH IS NUMBER OF OUTPUT SLOTS + JUMPG D,POPAJ ;IF FORMERLY THERE WERE NO OUTPUT SLOTS, + LDB T,[$CHSUO,,CHSUSR(I)] + SKIPLE CHSNOS(I) ;AND NOW THERE ARE, + PUSHJ P,CHINT2 ;INTERRUPT ON THE OUTPUT CHANNEL + JRST POPAJ + +;TRY TO TAKE PACKET IN A OFF OF TRANSMIT LIST IN Q. +;CLOBBER T,Q,D. CALLED WITH INTERRUPTS OFF. +;MAY RETURN WITH A POINTING TO FREE BUT THAT IS OK AT THIS TIME. +CHIKF1: SKIPA D,T +CHIAKF: MOVEI D,2(Q) ;LH[-2(D)] POINTS TO (T) + HLRZ T,-2(D) + JUMPE T,CPOPJ ;NOT FOUND + CAIE T,(A) + JRST CHIKF1 + HLRZ T,-2(A) ;LINK OUT + HRLM T,-2(D) + JUMPN T,CHABRT ;JUMP IF DIDN'T DELETE LAST PACKET IN LIST + HRRM D,(Q) ;NEW LAST PACKET IN LIST + CAIN D,2(Q) + SETZM (Q) ;FOO, TRANSMIT LIST NOW EMPTY + JRST CHABRT + +SUBTTL CHAOS NET DL10 INTERRUPT ROUTINE + +OVHMTR CHH + +IFN DLCP,[ + +;COME HERE FROM EACH DL10 INTERRUPT AT TTY LEVEL. SMASH ALL REGISTERS EXCEPT P AND 0. +DLCWAK: CONI PI,E ;SAVE PI STATUS AND SWITCH TO NETWORK INTERRUPT LEVEL + ANDI E,177 + PUSH P,E + CONO PI,NETOFF +DLCWK1: MOVEI J,1 ;ALWAYS CHECK BOTH BUFFERS SO WE CAN'T GET OUT OF PHASE WITH 11 + MOVEI R,2 ;CHECK FOR INPUT AVAILABLE + CAME R,DLCRS1(J) + SOJGE J,.-1 + JUMPL J,DLCWK2 + MOVE A,DLCRA1(J) ;GOT INPUT, PROCESS IT + SETZM DLCRS1(J) ;BUFFER SLOT NOT OCCUPIED NOW +IFN KS10P, CLRCSH +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE IN CASE ANYONE HAPPENED TO TOUCH BUFFER + SKIPE A ;THIS CAN HAPPEN IF PDP11 WAS JUST STUFFED + PUSHJ P,CHAPII ;PROCESS THE PACKET + PUSHJ P,DLCIBG ;SUPPLY A NEW INPUT BUFFER TO 11 + JRST DLCWK1 ;TRY FOR MORE INPUT + +DLCWK2: MOVEI J,1 ;SCAN CHANNELS FOR OUTPUT DONE + CAME R,DLCSS1(J) +DLCWK3: SOJGE J,.-1 + JUMPL J,DLCWK4 + MOVE A,DLCSA1(J) ;FOUND AN OUTPUT DONE BUFFER + HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST + AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST + PUSHJ P,CHABRT ;RETURN IT TO FREE + SETZM DLCSA1(J) ;IDLE THIS BUFFER + SETZM DLCSS1(J) + JRST DLCWK3 + +DLCWK4: MOVE J,DLCSBF ;TRY TO SEND SOME OUTPUT + SKIPE DLCSS1(J) + JRST DLCWK9 ;BUFFER BUSY + HLRZ A,DLCXMQ ;GET ANOTHER OFF TRANSMIT QUEUE + JUMPE A,DLCWK9 ;QUEUE EMPTY + HLRZ T,-2(A) +IFN FTRCHK,[ + CAIN T,-1 + BUG PAUSE,[CHAOS LIST THREAD TRASHED],OCT,A,OCT,-2(A) +];FTRCHK + HRLM T,DLCXMQ +IFN FTRCHK,[ + JUMPN T,.+4 + CAME A,DLCXMQ ;REACHED END OF LIST, END IN RIGHT PLACE? + BUG PAUSE,[DCLXMQ THREAD TRASHED] + SETZM DLCXMQ +];FTRCHK +IFE FTRCHK,[ + SKIPN T + SETZM DLCXMQ +];FTRCHK + PUSHJ P,DLCXMT ;SEND IT ON THIS BUFFER + JRST DLCWK4 ;GO TRY TO SEND ON OTHER BUFFER + +DLCWK9: POP P,E + CONO PI,PICON(E) ;RESTORE PI + POPJ P, + +;THIS ROUTINE SUPPLIES AN INPUT BUFFER TO THE 11 ON ALL BUFFERS THAT NEED IT +;CALL WITH INTERRUPTS OFF OR IN PROGRESS +DLCIBG: MOVEI J,1 + SKIPE DLCRS1(J) +DLCIB1: SOJGE J,.-1 + JUMPL J,CPOPJ + PUSHJ P,CHABGI ;GET A BUFFER + JRST [ SETZM DLCRA1(J) ;NO MEMORY, WILL TRY AGAIN AT CLOCK LEVEL + SETZM DLCRS1(J) + POPJ P, ] + SETZM (A) ;CLEAR THE BUFFER SINCE THE DL10 DOESN'T TOUCH LOW 4 BITS + HRLZ T,A + HRRI T,1(A) + BLT T,%CPMXW-1(A) + MOVEM A,DLCRA1(J) ;MAKE AVAILABLE TO PDP11 + HRLI A,120000 + MOVEM A,DLCRP1(J) + SOS DLCRP1(J) +IFN KS10P, .ERR CLRCSH not needed here? +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE BEFORE SIGNALLING 11 + MOVEI T,1 + MOVEM T,DLCRS1(J) + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + JRST DLCIB1 ;TRY FOR OTHER BUFFER ALSO + +;THIS ROUTINE SENDS PACKET IN A TO DL10 (CALL WITH NETOFF OR IN PROGRESS) +;SWITCHES BUFFERS, LEAVES NEW ONE IN J +DLCXMT: MOVE J,DLCSBF + MOVEM A,DLCSA1(J) + HRLI A,120000 + MOVEM A,DLCSP1(J) ;GIVE 11 POINTER TO NEW PACKET + SOS DLCSP1(J) +IFN KS10P, .ERR CLRCSH not needed here? +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE, PUTTING PACKET INTO CORE + MOVEI T,1 + MOVEM T,DLCSS1(J) ;ACTIVATE PDP11 + CONO DLC,100040+TTYCHN + XORI J,1 ;NEXT BUFFER + MOVEM J,DLCSBF + POPJ P, + +IFN KL10P,[ +;THIS ROUTINE SWEEPS PACKET IN A OUT OF THE CACHE, +;CLOBBERING B, C, AND D. +IFG PKTBSZ-1000, .ERR PKTBSZ BIGGER THAN HARDWARE PAGE SIZE, CACHE SWEEP LOSES +DLCSWP: LDB D,[111100,,A] ;SWEEP ONE PAGE OF CACHE + SWPUO (D) ;STORING PACKET INTO CORE + MOVE B,[CONSZ 200000] ;AWAIT COMPLETION IN ACS + MOVE C,[JRST B] ;TO MINIMIZE CACHE INTERFERENCE + MOVSI D,(POPJ P,) + JRST B +];KL10P +];DLCP + +SUBTTL CHAOS NET TEN-11 INTERFACE STUFF + +IFN T11CHP,[ +;THIS ROUTINE CHECKS FOR TEN-11 INITIALIZATION, SKIP-RETURNS IF OK TO USE +;CLOBBERS T,TT +T11CHK: SKIPE TEN11F + JRST T11LUZ ;NOT SUPPOSED TO USE TEN11 + MOVE T,T11VER ;CHECK VERSION TO MAKE SURE RIGHT PROGRAM, ETC. + CAME T,[.BYTE 8 ? "H ? "C ? 0 ? 1] + JRST T11LUZ ;PROBABLY TURNED OFF OR WRONG PROGRAM + SKIPE T11I10 ;SHOULD WE REINIT? + JRST T11CK1 ;YES, GO DO SO + SKIPLE T,T11WIN ;ARE WE WINNING? + JRST POPJ1 ;YES, FINE + JUMPE T,[SETOM T11WIN ;NOW THAT VERSION IS OK, TELL 11 TO INIT + MOVSI T,-1 + MOVEM T,T11I11 + JRST T11CK1 ] ;AND INIT OURSELVES + SKIPE T11I11 ;WAITING FOR 11 TO REINIT? + POPJ P, ;YES, WAIT +;HERE TO REINIT. FIRST, PICK UP PARAMETERS. +T11CK1: LDB TT,[242000,,T11PRM] ;BYTES PER PACKET BUFFER + CAIGE TT,<%CPMXW+1>*4 ;BETTER BE RIGHT SIZE + JRST T11LUZ ;TOO SMALL (ASSUME IF TOO BIG, PACKETS WON'T BE) + LSH TT,-2 + MOVEM TT,T11BSZ ;SAVE BUFFER SIZE IN PDP10 WORDS + LDB T,[042000,,T11PRM] ;NUMBER OF BUFFERS IN EACH DIRECTION + IMULB T,TT ;NUMBER OF PDP10 WORDS IN EACH DIRECTION + ADD TT,T11IBB + MOVEM TT,T11IBE ;INIT POINTERS + MOVEM TT,T11OBB + MOVEM TT,T11OBP + ADD TT,T + MOVEM TT,T11OBE + HRREI T,-T11CHS-2000(TT) + JUMPG T,T11LUZ ;COMMUNICATION AREA LONGER THAN 1K + MOVE T,T11IBB + MOVEM T,T11IBP +T11CK2: SETZM (T) ;CLEAR BUFFER HEADERS + ADD T,T11BSZ + CAMGE T,TT + JRST T11CK2 + MOVEM T,T11WIN ;WE'RE WINNING (MAKE T11WIN POSITIVE NON-ZERO) + SETZM T11I10 ;INIT DONE + JRST POPJ1 + +;HERE IF PDP11 PARAMETERS DON'T MATCH WHAT WE EXPECT +T11LUZ: SETZM T11WIN ;NOT WINNING + POPJ P, + +;HERE FROM CLOCK LEVEL TO CHECK ON TEN-11 CHAOS NET CHANNEL +T11WAK: PUSHJ P,T11CHK ;IS EVERYTHING OK? + POPJ P, ;NO. +T11WK0: MOVE C,T11IBP ;CHECK INPUT + SKIPN (C) + JRST T11WK1 ;NONE AVAILABLE + MOVSI J,2(C) ;POINT TO PACKET + LDB D,[$CPKNB+2(C)] ;GET SIZE OF PACKET + ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS INCLUDING HEADER + LSH D,-2 + CAILE D,%CPMXW ;DON'T GET FAKED OUT BY CLOBBERED COUNT + MOVEI D,%CPMXW + PUSHJ P,CHABGI ;GET PLACE TO PUT IT + JRST T11WK1 ;NONE AVAILABLE + HRLOI E,-1(D) + EQVI E,(A) ;AOBJN POINTER TO PACKET BUFFER + HRRI J,(A) ;BLT POINTER TO COPY PACKET + ADDI D,-1(A) ;LAST WORD + BLT J,(D) ;COPY PACKET FROM 11 TO 10 + MOVEI H,0 ;COMPUTE CHECKSUM +T11WK4: ADD H,(E) + LSH H,-1 + TRZE H,10 + TLO H,(SETZ) + AOBJN E,T11WK4 + MOVE TT,1(C) ;GET PDP11'S CHECKSUM + SETZM (C) ;GIVE THE 11 BACK THE BUFFER + ADD C,T11BSZ ;ADVANCE THE POINTER + CAML C,T11IBE + MOVE C,T11IBB + MOVEM C,T11IBP + CAME H,TT + JRST [ AOS T11CKE ;COUNT CHECKSUM ERRORS + PUSHJ P,CHABRT ;AND DISCARD PACKET + JRST T11WK0 ] + CONO PI,NETOFF + PUSHJ P,CHAPII ;PROCESS THE INPUT + CONO PI,NETON + JRST T11WK0 + +T11WK1: CONO PI,NETOFF + SKIPE T11XMQ ;ANY OUTPUT? + SKIPE @T11OBP ;AND OUTPUT BUFFER SPACE AVAILABLE? + JRST NETONJ ;NO, RETURN FROM T11WAK + HLRZ A,T11XMQ ;GET PACKET OFF TRANSMIT QUEUE + HLRZ B,-2(A) ;GET NEXT AFTER THAT + HRLM B,T11XMQ ;BECOMES NEW HEAD OF QUEUE + SKIPN B + SETZM T11XMQ + PUSHJ P,T11XMT ;COPY PACKET INTO 11 + CONO PI,NETON + JRST T11WK1 ;LOOK FOR MORE OUTPUT + +;SEND PACKET A-> TO 11. SMASHES B,C,T,TT,Q. CALL WITH NETOFF. +T11XMT: LDB C,[$CPKNB(A)] ;GET BYTE COUNT + MOVE Q,C ;MUST CLEAR UNUSED BYTES AT END OF LAST WORD + ANDI Q,3 ;TO MAKE THE CHECKSUM COME OUT RIGHT + ADDI C,4*%CPKDT+3 + LSH C,-2 ;CONVERT TO WORD COUNT + MOVE Q,(Q)[ -1 ;MASK FOR BYTES TO RETAIN IN LAST WORD + <.BYTE 8 ? -1> + <.BYTE 8 ? -1 ? -1> + <.BYTE 8 ? -1 ? -1 ? -1> ] + MOVEI TT,-1(C) + ADD TT,A + ANDM Q,(TT) ;MASK OFF LAST WORD + HRLOI C,-1(C) + EQVI C,(A) ;AOBJN PTR + MOVEI TT,0 ;COMPUTE XOR CHECKSUM IN TT + SKIPA B,T11OBP ;-> CURRENT OUTPUT BUFFER IN 11 +T11XM1: ADDI B,1 + MOVE T,(C) + TRZ T,17 ;CLEAR BITS 10-11 TREATS SPECIALLY + ADD TT,T ;COMPUTE CHECKSUM + LSH TT,-1 + TRZE TT,10 + TLO TT,(SETZ) + MOVEM T,2(B) + AOBJN C,T11XM1 + MOVE B,T11OBP + MOVEM TT,1(B) ;GIVE CHECKSUM TO 11 + MOVSI TT,-1 + MOVEM TT,0(B) ;GIVE PACKET TO 11 + ADD B,T11BSZ ;ADVANCE BUFFER POINTER + CAML B,T11OBE + MOVE B,T11OBB + MOVEM B,T11OBP + HRROS T,-2(A) ;TAKE PACKET OFF TRANSMIT LIST + AOJN T,.+2 + PUSHJ P,CHABRT ;NOT ON SEND LIST, FREE IT + POPJ P, +];T11CHP + +SUBTTL CH-10 INTERRUPT ROUTINES + +;THE GENERAL IDEA IS THAT WE INTERRUPT ON A LOW-PRIORITY INTERRUPT LEVEL, +;AND DO THE TIME-INTENSIVE PACKET COPYING AT THAT LEVEL. THE GENERAL +;CHAOS ROUTINES ARE THEN CALLED WITH NETOFF. + +IFN CH10P,[ + +EBLK + +CHXACS: BLOCK 20 +CHXPDL: -60,,. + BLOCK 60 + +CHXBRK: 0 +BBLK + MOVEM 17,CHXACS+17 + MOVEI 17,CHXACS + BLT 17,CHXACS+16 + MOVE P,CHXPDL + CONSO CHX,CHXRCV ;PACKET RECEIVED? + JRST CHXBK5 + PUSHJ P,CHABGI ;GET PLACE TO PUT PACKET + JRST [ MOVEI T,CHXREN ;NONE AVAILABLE, DISABLE INTR + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + JRST CHXBK5 ] + CONSZ CHX,CHXCRC+CHXWLE ;CHECK FOR ERRORS + JRST [ CONSZ CHX,CHXCRC + AOSA CHNCRC + AOS CHNWLE + JRST CHXBK4 ] ;IGNORE PACKET + DATAI CHX,T ;FIRST DATAI YIELDS GARBAGE + MOVEI T,CHXSWB ;DISABLE BYTE SWAPPING + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + HRLI A,-%CPKDT ;READ HEADER + DATAI CHX,(A) + AOBJN A,.-1 + HRRZI A,-%CPKDT(A) + PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + CAILE T,%CPMXC ;DON'T RUN OFF END OF BUFFER + JRST CHXBK4 + ADDI T,3 ;ROUND UP TO NEXT WORD BOUNDARY + LSHC T,-2 ;CONVERT BYTES TO WORDS, TT GETS REMAINDER + HRLOI D,-1(T) ;MAKE AOBJN POINTER + EQVI D,%CPKDT(A) + JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE + DATAI CHX,(D) + AOBJN D,.-1 + DATAI CHX,T ;NOW READ AND IGNORE HARDWARE HEADER + TLNE T+1,400000 + DATAI CHX,T ;THIRD HALFWORD + CONI CHX,T ;CHECK FOR ERRORS + TDNE T,[CHXPLE+CHXCRC+CHXOVR] + JRST [ TLNE T,(CHXOVR) + JRST CHXBKZ ;OVERRRUN CAN'T HAPPEN UNLESS HARDWARE BROKEN + TLNE T,(CHXPLE) + AOSA CHNPLE + TRNN T,CHXCRC + JRST CHXBK4 + AOS CHNCR2 + JRST CHXBK4 ] + CONO PI,NETOFF-1 + PUSHJ P,CHAPII ;PROCESS THE INPUT + CONO PI,NETON-1 + CAIA +CHXBK4: PUSHJ P,CHABRT ;DIDN'T USE BUFFER AFTER ALL + CONI CHX,T ;COUNT LOST PACKETS + LDB T,[$CHXLC,,T] + ADDM T,CHNLOS + MOVEI T,CHXREN ;ENABLE RECEIVER FOR NEXT PACKET + IORB T,CHXCNO + CONO CHX,CHXRCV(T) +CHXBK5: CONSO CHX,CHXXMT ;TRANSMIT DONE? + JRST CHXBK9 + SKIPE T,CHOSTA ;TRANSMIT IN PROGRESS? + CONSO CHX,CHXABT ;AND WAS ABORTED? + JRST CHXBK7 ;NO TO EITHER, LOOK FOR MORE WORK + AOS CHNABT ;METER TRANSMIT ABORTS + CAIL T,NCHRTR ;ABORTED TOO MANY TIMES? + JRST CHXBK7 ;DONE WITH PACKET + AOS CHOSTA ;COUNT RETRANSMISSIONS + MOVEI T,CHXTEN + IORB T,CHXCNO + CONO CHX,CHXXMT(T) ;RETRANSMIT PACKET + JRST CHXBK9 + +CHXBK7: SETZM CHOSTA ;TRANSMITTER IDLE, LOOK FOR NEXT PACKET + CONO PI,PIOFF + HLRZ A,CHXXMQ ;ANYTHING QUEUED FOR TRANSMISSION? + JUMPE A,[ MOVEI T,CHXTEN ;DISABLE INTERRUPTS + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + CONO PI,PION + JRST CHXBK9 ] + HLRZ B,-2(A) ;CDR TRANSMIT QUEUE + HRLM B,CHXXMQ + SKIPN B + SETZM CHXXMQ ;QUEUE EMPTY NOW + CONO PI,PION + AOS CHOSTA ;NOW SEND THIS PACKET + MOVEI T,CHXHLF+CHXSWB ;CLEAR HALFWORD, BYTE-SWAP MODES + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + HRLI A,-%CPKDT ;TRANSMIT HEADER + DATAO CHX,(A) + AOBJN A,.-1 + HRRZI A,-%CPKDT(A) + PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + ADDI T,1 ;ROUND UP TO NEXT HALF WORD BOUNDARY + LSHC T,-2 ;CONVERT BYTES TO WORDS, T+1 GETS REMAINDER + HRLOI D,-1(T) ;MAKE AOBJN POINTER + EQVI D,%CPKDT(A) + JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE + DATAO CHX,(D) + AOBJN D,.-1 + MOVEI T,CHXHLF+CHXTEN ;SWITCH TO HALFWORD MODE, ENABLE DONE INTR + IORM T,CHXCNO + CONO CHX,@CHXCNO + TLNE T+1,400000 ;SEND EXTRA HALFWORD IF NEEDED + DATAO CHX,(D) + MOVEI T,CHXSWB ;DISABLE SWAP BYTES MODE + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + LDB T,[$CPKDN(A)] ;GET DESTINATION SUBNET + HRRZ D,SBNRUT(T) ;GATEWAY TO THAT SUBNET + CAIGE T,NSUBNT + CAIN T,MYCHAD_-8 ;IF ON LOCAL CABLE + LDB D,[$CPKDA(A)] ;GO DIRECT + LSH D,16.+4 + DATAO CHX,D ;STORE HARDWARE DESTINATION ADDRESS + MOVE T,CHXCNO ;TRANSMIT PACKET + CONO CHX,CHXXMT(T) + CONI CHX,T + TLNE T,(CHXOVR) ;CAN'T HAPPEN UNLESS HARDWARE BROKEN +CHXBKZ: BUG HALT,[CHAOS: I/O BUS OVERRUN] + HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST + AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST + PUSHJ P,CHABRT ;RETURN IT TO FREE +CHXBK9: MOVSI 17,CHXACS ;DISMISS INTERRUPT + BLT 17,17 + JRST 12,@CHXBRK + +CHSWAB: LDB T,[$CPKOP(A)] ;DOES THIS PACKET NEED BYTE SWAPPING? + TRNE T,200 + JRST [ TRNE T,100 + POPJ P, ;BINARY DATA + JRST CHSWB1 ] ;CHARACTER DATA + IDIVI T,40 + MOVE T,CHSWBT(T) + LSH T,(T+1) + JUMPL T,CPOPJ ;BINARY CONTROL PACKET +CHSWB1: MOVEI T,CHXSWB ;CHARACTER, SWAP DEM BYTES + IORM T,CHXCNO + CONO CHX,@CHXCNO + POPJ P, + +CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> + 0 ? 0 ? 0 +];CH10P + +SUBTTL CH-11 INTERRUPT ROUTINES + +;The Unibus Chaosnet board interrupts on the same level as TTYs, +;and comes to CHXBKH via vectored interrupt. We use a programmed +;interrupt request to drop down to a lower interrupt level for the +;slow packet-copying operation, so as not to interfere with the TTYs, +;then turn NETOFF when we call into the Chaosnet NCP. +;(We actually use NETOFF-1 and NETON-1 so as not to interfere with +;CLKOFF. This assumes that interrupt levels between CLKCHN and +;CHXCHN are never turned off.) + +IFN CH11P,[ + +;;; Macros that will eventually be instructions + +DEFINE PACK16 AC,E ;AC,AC+1 right-aligned and zero-filled + LSH AC,16. + IOR AC,AC+1 + LSH AC,4 + MOVEM AC,E +TERMIN + +DEFINE PACK8 AC,E ;AC: ...B2B1 AC+1: ...B4B3 zero-filled!! + ROTC AC,-8 ;B3...B2 B1...B4 + ROT AC,-16. ;B1,B2,B3 in position, B4 right-aligned + ADDI AC+1,(AC+1) ;Shift RH(AC+1) left 4 bits + ADDI AC+1,(AC+1) + ADDI AC+1,(AC+1) + ADDI AC+1,(AC+1) ;B1,B4 in position in AC+1 + IOR AC,AC+1 + MOVEM AC,E +TERMIN + +DEFINE UNPK16 AC,E ;Doesn't bother masking off garbage bits + MOVE AC,E + MOVE AC+1,AC + ROT AC,16. ;First halfword right-aligned + LSH AC+1,-4 ;Second halfword right-aligned +TERMIN + +DEFINE UNPK8 AC,E + MOVE AC,E ;B1B2B3B4... + ROT AC,8 ;B2B3B4...B1 + MOVE AC+1,AC + AND AC,[377_2,,377] ;...B3...B1 zero-filled + ROT AC+1,16. ;B4...B1B2B3 + AND AC+1,[377_12,,377_8];B4...B2... zero-filled + IORB AC,AC+1 ;B4B3...B2B1 + ROT AC+1,16. ;...B4B3, garbage in high bits +TERMIN + +EBLK + +CHXACS: BLOCK 20 +CHXSVH: 0 +CHXPDL: -60,,. + BLOCK 60 + +CHXBKH: 0 ;Hardware interrupt on TTYCHN comes here +BBLK + CONO PI,CHXRQ ;Redirect to lower interrupt level + MOVEM T,CHXSVH ;Clear hardware interrupt enable + MOVEI T,%CAREN+%CATEN ; so the Chaos board will stop interrupting + ANDCAB T,CHXCSR + IOWRI T,CAICSR + MOVE T,CHXSVH + JRST 12,@CHXBKH +EBLK + +CHXBRK: 0 ;Software interrupt on CHXCHN comes here +BBLK + CONO PI,020000+200_<-CHXCHN> ;BAG-BITING DEC LOSERS + MOVEM 17,CHXACS+17 + MOVEI 17,CHXACS + BLT 17,CHXACS+16 + MOVE P,CHXPDL + IORDI T,CAICSR ;Check for received packet + TRNN T,%CARDN + JRST CHXBK3 ;No incoming packet yet + TRNE T,%CAERR ;Check for error in received packet + JRST [ AOS CHNCRC + JRST CHXBK1 ] ;Ignore packet + IORDI R,CAIRBC ;Number of bits in packet - 1 + SUBI R,31. ;Exclude the three extra hardware words + TRNE R,17 + JRST [ AOS CHNWLE ;Length not a multiple of 16 + JRST CHXBK1 ] + ASH R,-5 ;32-bit word count, rounded up + PUSHJ P,CHABGI ;Get place to put packet + JRST [ AOS CHNLOS ;No buffers, lose this packet + JRST CHXBK1 ] + HRLI A,-%CPKDT ;Copy out the packet header +CHSRC1: IORDI B,CAIRBF + IORDI C,CAIRBF + PACK16 B,(A) + AOBJN A,CHSRC1 + PUSHJ P,CHSHDR ;Decode the header + JRST CHSRC4 ;No byte swapping + JUMPGE D,CHSRC3 +CHSRC2: IORDI B,CAIRBF ;Read out the data, byte-swapped + IORDI C,CAIRBF + PACK8 B,(D) + AOBJN D,CHSRC2 +CHSRC3: JUMPGE H,CHSRC7 ;Jump if even packet length + IORDI B,CAIRBF ;Residual halfword + SETZ C, ;Somebody depends on zero here + PACK8 B,(D) + AOJA D,CHSRC7 + +CHSRC4: JUMPGE D,CHSRC6 +CHSRC5: IORDI B,CAIRBF ;Read out the data, halfwords + IORDI C,CAIRBF + PACK16 B,(D) + AOBJN D,CHSRC5 +CHSRC6: JUMPL H,[ IORDI B,CAIRBF ;Residual halfword + SETZ C, ;Somebody depends on zero here + PACK16 B,(D) + AOJA D,CHSRC7 ] +CHSRC7: SUB D,R ;AOBJN pointer minus number of words in packet + CAIE A,(D) + JRST [ AOS CHNPLE ;Packet length disagrees with hardware length + JRST CHXBK2 ] + IORDI T,CAIRBF ;Read the three hardware header words + IORDI T,CAIRBF + IORDI T,CAIRBF + IORDI T,CAICSR + TRNE T,%CAERR ;Make sure packet came out of RAM okay + JRST [ AOS CHNCR2 ;Garbage, try again + JRST CHXBK2 ] + IORDI T,CAIRBC ;Make sure counter didn't spazz + CAIE T,7777 + JRST [ AOS CHNSPZ + JRST CHXBK2 ] + CONO PI,NETOFF-1 ;Get to network interrupt level + PUSHJ P,CHAPII ;Process the input + CONO PI,NETON-1 +CHXBK1: IORDI T,CAICSR ;Count lost packets + LDB TT,[$CALOS,,T] + ADDM TT,CHNLOS + MOVE TT,CHXCSR + IORI TT,%CARCL ;Enable receiver for next packet + IOWRI TT,CAICSR +CHXBK3: TRNN T,%CATDN ;Transmit done? + JRST CHXBK8 ;No, dismiss + SKIPN TT,CHOSTA ;Transmit in progress? + JRST CHXBK7 ;No, look for something to transmit + TRNN T,%CATAB ;Yes, was it aborted? + JRST CHXBK5 ;No, we're done with that packet + AOS CHNABT ;Meter transmit aborts + CAIGE TT,NCHRTR ;Aborted too many times? + JRST CHXBK7 ;No, retransmit it +CHXBK5: CONO PI,PIOFF ;Lock transmit list + HLRZ A,CHXXMQ ;Get packet probably being transmitted now + JUMPE A,[ CONO PI,PION ;It vanished? + JRST CHXBK6 ] + HLRZ B,-2(A) ;CDR transmit queue + HRLM B,CHXXMQ + SKIPN B + SETZM CHXXMQ ;Queue empty now + CONO PI,PION + HRROS B,-2(A) ;Mark it not on transmit list + AOJN B,CHXBK6 ;And unless it is on send list + PUSHJ P,CHABRT ;Return it to free +CHXBK6: SETZM CHOSTA ;Transmitter idle, look for next packet +CHXBK7: HLRZ A,CHXXMQ ;Anything queued for transmission? + JUMPE A,CHXBK9 ;No, leave interrupts disabled + AOS CHOSTA ;Count retransmissions + MOVE T,CHXCSR ;Reset transmitter + IORI T,%CATDN + IOWRI T,CAICSR + HRLI A,-%CPKDT ;Transmit header +CHXXM1: UNPK16 B,(A) + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN A,CHXXM1 + PUSHJ P,CHSHDR ;Decode the header + JRST CHXXM4 ;No byte swapping + JUMPGE D,CHXXM3 +CHXXM2: UNPK8 B,(D) ;Transmit data with byte swapping + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN D,CHXXM2 +CHXXM3: JUMPGE H,CHXXM7 ;Jump if even packet length + UNPK8 B,(D) ;Transmit residual bytes + IOWRI B,CAIWBF + JRST CHXXM7 + +CHXXM4: JUMPGE D,CHXXM6 +CHXXM5: UNPK16 B,(D) ;Transmit data with byte swapping + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN D,CHXXM5 +CHXXM6: JUMPGE H,CHXXM7 ;Jump if even packet length + UNPK16 B,(D) ;Transmit residual bytes + IOWRI B,CAIWBF +CHXXM7: LDB T,[$CPKDN(A)] ;Get destination subnet + HRRZ D,SBNRUT(T) ;Gateway to that subnet + CAIGE T,NSUBNT + CAIN T,MYCHAD_-8 ;If on local cable, + LDB D,[$CPKDA(A)] ; go direct + IOWRI D,CAIWBF ;Store hardware destination address + IORDI T,CAIXMT ;Transmit packet +CHXBK8: MOVEI A,%CATEN ;Enable transmit-done interrupt if xmitting +CHXBK9: IORI A,%CAREN ;Enable receive-done interrupt always + IORB A,CHXCSR + IOWRI A,CAICSR + MOVSI 17,CHXACS ;Dismiss software interrupt + BLT 17,17 + JRST 12,@CHXBRK + +CHXBK2: PUSHJ P,CHABRT ;Packet no good, discard it + JRST CHXBK1 + +;Examine packet in A, return AOBJN pointer to data in D, +; H is negative if there is an extra halfword after that. +; W gets number of full words of data (same as LH D). +; T,U get clobbered +; Returns: +; +1 16-bit data +; +2 8-bit data +CHSHDR: HRRZI A,-%CPKDT(A) ;Restore packet address + LDB W,[$CPKNB(A)] ;Get size of packet in bytes + CAILE W,%CPMXC + MOVEI W,%CPMXC ;Self-defense + ADDI W,1 ;Round up to next word boundary + LSHC W,-2 ;Convert bytes to words, H gets remainder + HRLOI D,-1(W) ;Make AOBJN pointer + EQVI D,%CPKDT(A) + LDB T,[$CPKOP(A)] ;Does this packet need byte swapping? + TRNE T,200 + JRST [ TRNN T,100 + AOS (P) ;Character data + POPJ P, ] ;Binary data + IDIVI T,40 + MOVE T,CHSWBT(T) + LSH T,(T+1) + JUMPL T,CPOPJ ;Binary control packet + JRST POPJ1 ;Characters + +CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> + 0 ? 0 ? 0 +];CH11P + +SUBTTL CHAOS NET BUFFER LIST STUFF + +OVHMTR CHL + +;BUFFERS ARE PKTBSZ WORDS LONG; 2 HEADER WORDS AND %CPMXW PACKET WORDS. +;PKTBSZ IS A POWER OF 2 AND LESS THAN 1K (MEMORY PAGE SIZE). +;NOTE THAT A BUFFER ADDRESS POINTS AT THE FIRST PACKET WORD +;AND THE HEADER WORDS ARE AT NEGATIVE ADDRESSES. +;FIRST HEADER WORD: -2(A) +; RH LIST THREAD FOR MOST LISTS, 0=END, -1=NOT ON LIST +; LH LIST THREAD FOR TRANSMIT LIST +;SECOND HEADER WORD: -1(A) +; TIME RECEIVED OR TIME PUT ON TRANSMIT LIST +; OR VALUE OF I FOR A PACKET ON THE LSN QUEUE +; ASCII/LUNCH/ FOR A PACKET ON THE FREE LIST + +;I DO IT THIS WAY (PIOFF) TO AVOID HAVING TO PUSH AND POP PI STATUS, +;CONO PI,NETOFF CAN LOSE AT INTERRUPT LEVEL (MAINLY THE NETON LOSES) + +;THESE ROUTINES TURN OFF INTERRUPTS MOMENTARILY SO THAT +;LISTS MAY BE SAFELY MANIPULATED. + +;Q POINTS TO THE HEADER WORD OF A QUEUE, REMOVE THE FIRST +;THING AND RETURN IN A. (ZERO IF NONE) CLOBBERS T +CHAQGF: CONO PI,PIOFF + HLRZ A,(Q) ;GET FIRST + JUMPE A,PIONJ ;EMPTY + HRRZ T,-2(A) ;GET SECOND + HRLM T,(Q) ;MAKE FIRST +IFN FTRCHK,[ + JUMPN T,PIONJ + HRRZ T,(Q) + CAIE T,(A) + BUG PAUSE,[CHAOS LIST TRASHED],OCT,Q + SETZM (Q) ;IS NOW EMPTY +];FTRCHK +IFE FTRCHK,[ + SKIPN T + SETZM (Q) ;IS NOW EMPTY +];FTRCHK + CONO PI,PION + POPJ P, + +;RETURN BUFFER INTO WHICH THE BYTE POINTER IN A POINTS. CLOBBERS A,T,Q +CHBPFR: SUBI A,1 ;SIOKT LIKES TO MAKE BP POINT AT NEXT BUFFER + ANDI A,-PKTBSZ + ADDI A,2 + JRST CHABRT + +;RETURN BUFFER POINTED TO BY A TO FREE UNLESS ON TRANSMIT LIST. +CHABR1: HLLOS T,-2(A) ;RH GETS -1, NO LONGER ON REGULAR LIST + AOJN T,CPOPJ ;EXIT IF STILL ON TRANSMIT LIST + ;DROPS THROUGH +;RETURN BUFFER POINTED BY A TO FREE STORAGE. CLOBBERS T, Q. +CHABRT: MOVEI Q,CHQFRE +IFN FTRCHK,[ + SKIPN A + BUG PAUSE,[FREEING 0] +];FTRCHK + MOVE T,[ASCII/LUNCH/] ;TANSTAAFL + MOVEM T,-1(A) + SETOM -2(A) ;NOT ON TRANSMIT LIST NOW (THIS IS WHAT INITS + AOS CHFRBF ; LH[-2(A)] WHEN BUFFER FIRST CREATED) + ;JRST CHAQPL ;DROPS THROUGH + +;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE LAST THING. BASHES T. +CHAQPL: HLLZS -2(A) ;PUT ENDLIST IN RH + CONO PI,PIOFF + HRRZ T,(Q) ;GET LAST + HRRM A,(Q) ;MAKE NEW LAST + JUMPN T,[HRRM A,-2(T) ;MAKE A COME AFTER IT + JRST PIONJ ] + HRLM A,(Q) ;WAS EMPTY, ALSO IS NEW FIRST + CONO PI,PION + POPJ P, + +;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE FIRST THING. SMASHES T. +CHAQPF: CONO PI,PIOFF + HLRZ T,(Q) ;GET FIRST + HRRM T,-2(A) ;MAKE SECOND + HRLM A,(Q) ;MAKE NEW FIRST + SKIPN T + HRRM A,(Q) ;WAS EMPTY, ALSO MAKE NEW LAST + CONO PI,PION + POPJ P, + +;ALLOCATE A BUFFER AT MAIN PROGRAM LEVEL, TO A, MASHES T, TT, Q, B. +CHABG0: PUSHJ P,UDELAY ;WAIT FOR MEMORY +CHABGT: PUSHJ P,CHABGI + JRST CHABG0 + POPJ P, ;WIN + +;ALLOCATE A BUFFER, RETURN POINTER TO IT IN A, SKIP. BLOWS AWAY T, TT, Q. +;NON-SKIP IF NO BUFFERS AVAILABLE. (DOESN'T MAKE NEW ONES IF FREE LIST EMPTY) +CHABAL: MOVEI Q,CHQFRE + PUSHJ P,CHAQGF + JUMPE A,CPOPJ + SETZM -1(A) ;NO LUNCH + SOS CHFRBF + JRST POPJ1 + +;ALLOCATE A BUFFER TO A, MAKE NEW IF NONE FREE. OBLITERATES T,Q,B. +;NON-SKIP IF CAN'T GET MEMORY. (SUITABLE FOR CALLING FROM INT LEVEL) +CHABGI: PUSHJ P,CHABAL ;TRY TO ALLOCATE A BUFFER FROM FREE LIST + CAIA + JRST POPJ1 ;WON, RETURN + CONI PI,Q ;SAVE PI CHANNELS ON STATUS + ANDI Q,177 + CONO PI,UTCOFF ;MAKE THE WORLD SAFE FOR IOMQ + MOVE B,CHTTBF + CAIL B,CHMXBF ;MAKE SURE NOT TO USE UP ALL CORE + JRST CHABG4 + PUSHJ P,IOMQ ;GET 1K OF MEMORY + JRST CHABG3 ;MEM NOT AVAILABLE, FAIL + CONO PI,PICON(Q) ;WON, RESTORE PI STATUS + MOVEI B,MUCHA + DPB B,[MUR,,MEMBLT(A)] + LSH A,10. ;ADDRESS OF 1K OF ALLOCATED MEMORY + ADD A,[-<2000/PKTBSZ>,,2] ;-BUFFERS PER 1K,,OFFSET TO HEADER +CHABG2: PUSHJ P,CHABRT ;PUT THEM ALL ON FREE LIST + ADDI A,PKTBSZ-1 + AOBJN A,CHABG2 + MOVEI B,<2000/PKTBSZ> ;THIS MANY MORE BUFFERS HAVE BEEN CREATED + ADDM B,CHTTBF + JRST CHABGI ;NOW GO ALLOCATE ONE + +;HERE IF CHAOS NET TRYING TO USE UP TOO MUCH CORE +CHABG4: MOVE B,CHMXTM ;DON'T COMPLAIN TOO OFTEN + ADDI B,60.*30. ;JUST ONCE A MINUTE + CAMLE B,TIME + JRST CHABG3 +IFE CH10P, BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE] +IFN CH10P,[ + CONI CHX,B + BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE, CONI=],OCT,B,[CONO=],OCT,CHXCNO,[CHOSTA=],OCT,CHOSTA +];CH10P + MOVE B,TIME + MOVEM B,CHMXTM +CHABG3: CONO PI,PICON(Q) ;LOST, RESTORE PI STATUS + POPJ P, ;AND TAKE ERROR RETURN + +;FREE A WHOLE LIST OF BUFFERS, Q-> HEAD. DESTROYS A,T +CHALFR: PUSHJ P,CHAQGF + JUMPE A,CPOPJ + PUSH P,Q + PUSHJ P,CHABR1 ;FREE UNLESS STILL ON TRANSMIT LIST + POP P,Q + JRST CHALFR + +;Q -> A TRANSMIT QUEUE, FLUSH ALL BUFFERS BELONGING TO INDEX I. +;CLOBBERS A,B,C,T +CFLXMQ: PUSH P,Q + CONO PI,NETOFF ;DON'T LET TRANSMIT LIST CHANGE (AT ALL) + HLRZ A,(Q) ;HEAD OF TRANSMIT LIST + JUMPE A,CFLXM3 + MOVEI B,2(Q) ;B PREVIOUS PACKET, A CURRENT, C NEXT +CFLXM1: HLRZ C,-2(A) ;GET THREAD TO NEXT +IFN FTRCHK,[ + CAIN C,-1 + JRST 4,. ;CLAIMS NOT TO BE ON LIST? +];FTRCHK + LDB T,[$CPKSX(A)] ;GET THIS PACKET'S INDEX + CAME T,I + JRST CFLXM2 + HRLM C,-2(B) ;THREAD PREVIOUS TO NEXT + HRROS T,-2(A) ;IF THIS BUFFER IS NOT ALSO ON SEND LIST, + AOJN T,.+2 + PUSHJ P,CHABRT ;RETURN IT + SKIPA Q,(P) +CFLXM2: MOVE B,A + SKIPE A,C + JRST CFLXM1 + HRRM B,(Q) ;LAST PACKET ON LIST MAY HAVE CHANGED + CAIN B,2(Q) + SETZM (Q) ;TRANSMIT QUEUE IS NOW EMPTY +CFLXM3: POP P,Q + JRST NETONJ + +;SEARCH LIST IN Q FOR PACKET WHOSE CONTACT NAME MATCHES THAT +;OF PACKET IN A, RETURN IT IN B, SKIPPING IF WINNING. CLOBBERS T,TT,C,D,E,H,J. +;THE PACKET RETURNED IN B IS DE-LINKED FROM THE SEARCHED QUEUE. +;HAS TO BE CALLED WITH NETOFF OR IN PROGRESS, SO LIST CAN'T GET MUNGED. +;I HOPE IT'S NOT TOO BLETCHEROUSLY SLOW. +CHAQSR: HLRZ B,(Q) ;GET START OF LIST TO SEARCH + JUMPE B,CPOPJ ;EMPTY, LOSE + MOVEI J,0 ;PACKET PREVIOUS TO B +CHAQS1: LDB C,[$CPKNB(A)] ;SET UP STRING COMPARE LOOP + LDB H,[$CPKNB(B)] ;THIS ASSUMES NO ZERO-LENGTH STRINGS + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEI E,%CPKDT(B) + HRLI E,440800 +CHAQS2: ILDB T,D + ILDB TT,E ;DON'T IGNORE CASE, THAT WOULD JUST SLOW THIS + CAME T,TT ;BAG-BITER DOWN EVEN MORE. EVERYONE SHOULD + JRST CHAQS4 ;PUT THEIR CONTACT NAMES IN UPPER-CASE. + CAIN T,40 ;TERMINATE ON SPACE + JRST CHAQS5 + SOJLE C,CHAQS3 + SOJG H,CHAQS2 + ILDB T,D + CAIE T,40 + JRST CHAQS4 +CHAQS5: HRRZ C,-2(B) ;WON, DELINK PACKET FROM LIST + JUMPE J,[ HRLM C,(Q) + JUMPN C,POPJ1 + IFN FTRCHK,[ + HRRZ C,(Q) ;CHECK LIST ENDING IN RIGHT PLACE + CAIE C,(B) + JRST 4,. + ];FTRCHK + SETZM (Q) + JRST POPJ1 ] + HRRM C,-2(J) + JUMPN C,POPJ1 + HRRM J,(Q) ;TOOK LAST PACKET, STORE NEW LAST + JRST POPJ1 + +CHAQS3: SOJLE H,CHAQS5 + ILDB TT,E + CAIN TT,40 + JRST CHAQS5 +CHAQS4: MOVE J,B ;THIS ONE DOESN'T MATCH, TRY NEXT + HRRZ B,-2(B) + JUMPN B,CHAQS1 + POPJ P, ;NO MATCHES + +;THIS ROUTINE RUNS IN THE CORE JOB AND CLEANS UP MEMORY USED BY CHAOS BUFFERS +;SMASHES ALL ACS +CHCLN: SKIPE A,CHTTBF ;SEE IF 2/3 OR MORE OF BUFFERS FREE + SKIPN B,CHFRBF + POPJ P, ;NO BUFFERS OR NONE FREE, NOTHING TO DO + SUBM A,B + IDIV A,B ;GET RATIO OF TOTAL TO USED + CAIGE A,3 ;NOTE IF B IS ZERO A IS UNCHANGED + POPJ P, ; AND AT LEAST 32. +IFL TSYSM-256., MOVEI D,TSYSM-1 ;SCAN MEMORY FOR CHAOS BUFFER PAGES +.ELSE MOVEI D,255. +CHCLN0: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUCHA +CHCLN4: SOJGE D,CHCLN0 + JUMPL D,CPOPJ + MOVE A,D ;QUICKLY DETERMINE IF ANY NON-FREE BUFFERS + LSH A,10. ; ON THIS PAGE + HRLI A,-<2000/PKTBSZ> + MOVE T,[ASCII/LUNCH/] +CHCLN5: CAME T,1(A) + JRST CHCLN4 ;NOT FREE, DON'T BOTHER WITH SLOW STUFF + ADDI A,PKTBSZ-1 + AOBJN A,CHCLN5 + SETZB C,CHCLNQ ;COLLECT ALL FREE BUFFERS THAT ARE ON THIS PAGE + MOVE E,CHFRBF ;LOOP ABOUT AS MANY TIMES AS THERE ARE FREE BUFFERS +CHCLN1: PUSHJ P,CHABAL ;GET NEXT FREE BUFFER + JUMPE A,CHCLN2 + LDB B,[121000,,A] + CAMN B,D + JRST [ MOVEI Q,CHCLNQ ;THIS ONE'S ON THE PAGE, SAVE IT + PUSHJ P,CHAQPL + AOJA C,.+2 ] ;COUNT THEM + PUSHJ P,CHABRT ;NOT ON THE PAGE, PUT BACK + SOJG E,CHCLN1 +CHCLN2: CAIE C,<2000/PKTBSZ> ;DID WE GET THE WHOLE PAGE? + JRST [ MOVEI Q,CHCLNQ ? PUSHJ P,CHALFR ? JRST CHCLN4 ] + MOVNS C ;YES, GET RID OF THESE BUFFERS + ADDM C,CHTTBF + MOVE A,D + PUSHJ P,MEMR + JRST CHCLN + +OVHMTR CHZ diff --git a/src/system/chsdef.15 b/src/system/chsdef.15 new file mode 100755 index 00000000..b53fa8ca --- /dev/null +++ b/src/system/chsdef.15 @@ -0,0 +1,68 @@ +;;; CHAOS NET PACKET DEFINITION + +;NOTE, IF YOU MAKE CHANGES TO OPCODES OR CONNECTION STATE SYMBOLS, +;ALSO CHANGE AI:MAINT;CHS DEFS. +;THIS FILE IS FOR PDP-10'S - CHS DEFS IS FOR PDP-11'S. + + +;PACKET HEADER +;NOTE THESE ARE FULL WORD BYTE POINTERS, INCLUDING A WORD OFFSET + +$CPKOP==341000,,0 ;OPCODE + %CO==,,-1 + %CORFC==1 ;REQUEST FOR CONNECTION + %COOPN==2 ;OPEN + %COCLS==3 ;CLOSE + %COFWD==4 ;FORWARD + %COANS==5 ;ANSWER + %COSNS==6 ;SENSE STATUS + %COSTS==7 ;REPORT STATUS + %CORUT==10 ;ROUTING INFO (NOT YET USED) + %COLOS==11 ;REPORT LOSSAGE + %COLSN==12 ;LISTEN FOR RFC + %COMNT==13 ;MAINTENANCE USE, IGNORED BY NORMAL NCPS + %COEOF==14 ;END OF FILE + %COUNC==15 ;UNCONTROLLED USER PACKET + %COBRD==16 ;Software broadcast packet + %COMAX==17 ;HIGHEST NON-DATA OPCODE +1 + %CODAT==200 ;NORMAL DATA OPCODE (NOTE SIGN BIT OF WORD IS SET) + %CODWD==300 ;16-BIT DATA +$CPKMV==241000,,0 ;"MUPPET" VERSION (MUST BE ZERO, NO MUPPETS EXIST!) +$CPKFC==200400,,0 ;FORWARDING COUNT +$CPKNB==041400,,0 ;NUMBER OF BYTES +$CPKDA==242000,,1 ;DESTINATION ADDRESS + $CPKDN==341000,,1 ;DESTINATION SUBNET + $CPKDH==241000,,1 ;DESTINATION HOST +$CPKDI==042000,,1 ;DESTINATION INDEX + %CPKD==1 ;DESTINATION ADDRESS WORD +$CPKSA==242000,,2 ;SOURCE ADDRESS + $CPKSN==341000,,2 ;SOURCE SUBNET + $CPKSH==241000,,2 ;SOURCE HOST +$CPKSI==042000,,2 ;SOURCE INDEX + %CPKS==2 ;SOURCE ADDRESS WORD +$CPKPN==242000,,3 ;PACKET NUMBER +$CPKAN==042000,,3 ;ACKNOWLEDGE NUMBER + %CPKDT==4 ;FIRST WORD OF DATA + +;PACKET SIZE + +;THESE NUMBERS ARE FOR 1K PACKET BUFFERS +;%CPMXW==30. ;MAXIMUM NUMBER OF PDP10 WORDS IN WHOLE PACKET +;%CPMXC==104. ;MAXIMUM NUMBER OF CHARACTERS OF DATA + +;THESE NUMBERS ARE FOR 4K PACKET BUFFERS +%CPMXW==126. ;MAXIMUM NUMBER OF PDP10 WORDS IN WHOLE PACKET +%CPMXC==488. ;MAXIMUM NUMBER OF CHARACTERS OF DATA + +;CONNECTION STATES + +%CS==,,-1 +%CSCLS==0 ;CLOSED +%CSLSN==1 ;LISTENING +%CSRFC==2 ;RFC RECEIVED +%CSRFS==3 ;RFC SENT +%CSOPN==4 ;OPEN +%CSLOS==5 ;BROKEN BY RECEIPT OF "LOS" +%CSINC==6 ;BROKEN BY INCOMPLETE TRANSMISSION (NO RESPONSE TO SNS) +%CSFRN==7 ;OPEN IN FOREIGN PROTOCOL MODE +%CSBRS==10 ;BRD sent state diff --git a/src/system/config.196 b/src/system/config.196 new file mode 100755 index 00000000..352b6558 --- /dev/null +++ b/src/system/config.196 @@ -0,0 +1,926 @@ +.AUXIL + +;;; "INSTALLATION" RELATED SWITCHES + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +IFNDEF DEFOPT,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFOPT FOO==BAR DOES IT UNLESS FOO ALREADY DEFINED +DEFINE DEFOPT X/ +IRPS Z,,[X] +IFNDEF Z, X +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEM2==1 +] +.ELSE $$TEM2==0 + +IFE MCOND AIKA,[ +DEFOPT KA10P==1 ;AI-KA HAS KA10 PROCESSOR +DEFOPT MAXJ==85. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1=> SWAP BLOCKING, 0=> PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ;PAGE-IN PREEMPTION +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==8. ;# 2314 UNITS +DEFOPT NTUTBL==2 ;TUTS ARE 2 BLOCKS LONG (THIS DEFN BETTER AGREE WITH DC10 DEFS) +DEFSYM NUDSL==440. ;# USER DIRECTORIES ON DISK. NOTE: JUST CHANGING THIS + ; IS NOT SUFFICIENT!! +DEFOPT NQCHN==40. ;NUMBER 2314 CHNLS +DEFOPT DC10P==1 ;HAS SYSTEMS CONCEPTS DISK CONTROL +DEFOPT DMDSK==0 ;DOES NOT USE DM DSK FORMAT (I.E. HAS EXTRA WORDS) +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS (SECONDARY PACK) +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;CHNL 1 MPX FEATURE +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10A==1 ;IO-BUS MAG TAPE +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==0 ; But punch doesn't work! +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK +DEFOPT DPKPP==1 ;DATA POINT KLUDGE (TTY mux) + +DEFOPT NETP==1 ; Connected to a network +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==206 ; ARPA net host number +DEFOPT IMPUS3==<1200,,400006> ; Internet host number +DEFOPT NCPP==1 ; Include NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels + +DEFOPT TK10P==1 ;HAS TK10 TTY SCANNER (NO MORE, BUT LEAVE IT SO TTY#S DON'T CHANGE) +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NNTYS==16. ;# TTYS ON KNIGHT KLUDGE +DEFOPT NDPTYS==9. ;# TTYS ON DATAPOINT KLUDGE +DEFOPT NSTTYS==16. ;# OF STY'S (PSEUDO-TTY'S) +DEFOPT APL==10 ;AP TTY # (really?) + +DEFOPT CODP==1 ; Has Morse code output device (no antenna though) + +; The following AI-KA stuff is broken since the 10-11 interface doesn't work, +; but is retained in case it gets fixed. +DEFOPT TEN11P==0 ; Rubin 10-11 interface +IFN TEN11P,[ + DEFOPT XGP==1 ; Has XGP + DEFOPT CHAOSP==1 ; Has CHAOS net + DEFOPT MYCHAD==2026 ; CHAOS net address + DEFOPT NINDX==50. ; Number of Chaosnet indices + DEFOPT T11CHP==1 ; CHAOS net goes through TEN-11 interface + DEFOPT CH11NM==7 ; # of 10-11 PDP11 handling CHAOS net. + DEFOPT TT11NM==0 ; # of 10-11 PDP11 that handles TV TTYs. + DEFOPT N11TYS==16. ; # PDP11 TV TTYS + DEFOPT MXVBN==40 ; Max video bfr # for assignment purposes. +] ;TEN11P ; These actually correspond to video switch inputs. + + +; The following stuff used to be on AI-KA and is unlikely to ever +; come back. +;DEFOPT PDP6P==0 ;HAS PDP6 (ALAS, NO MORE) +;DEFOPT 340P==0 ;HAS 340 DISPLAY (ALAS, NO MORE) +;DEFOPT TABP==0 ;DOESN'T HAVE SYLVANIA TABLET ANY MORE +;DEFOPT DSDP==0 ;HAS DESELECTION DEVICE (ALAS, NO MORE) +;DEFOPT NEWDTP==0 ;HAD OLD DECTAPE CONTROLLER +;DEFOPT RBTCP==0 ;ROBOT CONSOLE +;DEFOPT HCLKP==0 ;HOLLOWAY CLOCK (ALAS, NO MORE) +;DEFOPT ARMP==0 ;HAS NO ARM (AMF MOSTLY) (R.I.P.) +;DEFOPT OMXP==0 ;HAS OMX (OUTPUT MULTIPLEXOR) (ALAS, NO MORE) +;DEFOPT IMXP==0 ;HAS IMX (INPUT MULTIPLEXOR) (ALAS, NO MORE) +;DEFOPT VIDP==0 ;HAD VIDI (R.I.P.) +;DEFOPT CCLKP==0 ;NO CHESS TOURN CLOCK STUFF +;DEFOPT NDAP==0 ;NEW D/A CONVERTERS (ALAS, NO MORE) + +; Physical memory variables + +DEFOPT TSYSM==768. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT ECCMEM==1 ;HAS HIC'S ERROR CORRECTING MEMORY +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.); + +DEFSYM PMRCM==1777 ;CORE ADR FIELD IN PAGE MAP (AI-KA HAS 10 BITS) +DEFSYM PMAGEM==16000 ;AI-KA HAS ONE LESS AGE BITS +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS + +IFDEF TEN11P,IFN TEN11P,DEFSYM T11CPA==3776000 ;ADRS OF TEN-11 CONTROL PAGE +IFDEF PDP6P,IFN PDP6P,DEFSYM PDP6BM==3000000 ;BASE ADR OF PDP6 MEM AS SEEN FROM 10 +IFDEF PDP6P,IFN PDP6P,DEFSYM LPDP6M==16. ;LENGTH OF PDP6 MEM IN PAGES +] ;AIKA + +IFE MCOND MLKA,[ +DEFOPT KA10P==1 ;ML-KA HAS KA PROCESSOR +DEFOPT MAXJ==60. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1 => SWAP BLOCKING, 0 => PRIV USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ; Page-in preemption +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQCHN==30. ;NUMBER 2314 CHNLS +DEFOPT NQS==7 ;# DISK UNITS +DEFOPT NTUTBL==1 ;TUTS ARE ONE BLOCK LONG +DEFSYM NUDSL==250. ;# USER DIRECTORIES ON DISK +DEFOPT RP10P==1 ;HAS DEC RP10 DISK CONTROL (RP02) +DEFOPT QRDCMP==1 ;SOFTWARE READ-COMPARE +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS (SECONDARY PACK) +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;CHANNEL 1 MPX FEATURE +DEFOPT NEWDTP==1 ;HAS NEW DECTAPE CONTROLLER +;DEFOPT NUNITS==4 ; Number of utape units (R.I.P.) +DEFOPT NMTCS==1 ;NUMBER OF MAG TAPE UNITS +DEFOPT TM10A==1 ;IO-BUS MAG TAPE +DEFOPT NLPTP==1 ;HAS NEW LPT (ODEC) +DEFOPT TPLP==1 ;PSEUDO LPT +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==1 ; And punch works. +DEFOPT MTYP==1 ;HAS MORTON MULTIPLEX BOX +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==306 ; ARPA net host number +DEFOPT IMPUS3==<1200,,600006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==20. ; # NCP net channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels +DEFOPT CHAOSP==1 ;CHAOS NET +DEFOPT MYCHAD==3114 ;CHAOS NET ADDRESS +DEFOPT NINDX==30. ;NUMBER OF INDICES +DEFOPT CH10P==1 ;CHAOS NET VIA PDP-10 I/O BUS, NOT FRONT-END + +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +;DEFOPT NNVTTS==0 ;# NOVA TTYS (used to have?) +DEFOPT NMTYS==33 ;# TTYS ON MORTON BOX +DEFOPT NSTTYS==8 ;# STY'S (PSEUDO-TTY'S) + +DEFOPT TSYSM==512. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==777 ;9 BIT REAL CORE ADR +DEFSYM PMAGEM==17000 ;4 BIT AGE +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS +] ;MLKA + +IFE MCOND DM,[ +DEFOPT KA10P==1 ;DM HAS KA10 PROCESSOR +DEFOPT MAXJ==63. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==0 ;1 => SWAP BLOCKING, 0 => PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==0 ;NO PAGE-IN PREEMPTION +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==6 ;# OF DISK UNITS +DEFOPT NTUTBL==1 ;TUTS ARE ONE BLOCK LONG +DEFSYM NUDSL==200. ;# USER DIRECTORIES ON DISK +DEFOPT NQCHN==30. ;NUMBER 2314 CHNLS +DEFOPT RP10P==1 ;HAS DEC RP10 DISK CONTROL (RP02) +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;HAS CHANNEL 1 MPX FEATURE +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10B==1 ;DF10-BASED CONTROLLER +DEFOPT TTLPTP==1 ;LPT IS A TTY (I.E. ON A TTY LINE) VALUE IS LINE #. +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==1 ;PUNCH DOES WORK. +DEFOPT MTYP==1 ;HAS MORTON MULTIPLEX BOX +;DEFOPT CODP==0 ;NO COD DEVICE (used to?) +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT DMIMP==1 ; This is a DM IMP interface +DEFOPT IMPUS==106 ; ARPA net host number +DEFOPT IMPUS3==<1200,,200006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels + +DEFOPT MSPP==1 ;HAS MESSAGE SLURPER +DEFOPT DEMON==1 ;HAS DEMON ROUTINES +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NMTYS==12. ;# TTYS ON MORTON BOX +DEFOPT NSTTYS==16. ;# OF STY'S (PSEUDO-TTY'S) + + +DEFOPT TSYSM==512. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==777 ;9 BIT REAL CORE ADR +DEFSYM PMAGEM==17000 ;4 BIT AGE +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS +] ;DM + +IFE MCOND MX,[ +DEFOPT KL10P==1 ;MX IS WHAT WE CALL THE KL10 NOW +DEFOPT MAXJ==120. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1 => SWAP BLOCKING, 0 => PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ;PAGE-IN PREEMPTION +DEFOPT SCHBLN==20. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==6 ;# OF DISK UNITS (3 RP04'S AND 3 T-300'S) +DEFOPT NTUTBL==2 ;TUTS ARE TWO BLOCKS LONG +DEFSYM NUDSL==500. ;# USER DIRECTORIES ON DISK +DEFOPT NQCHN==50. ;NUMBER 2314 CHNLS +DEFOPT RH10P==1 ;HAS DEC RH10 DISK CONTROL (RP04) +DEFOPT T300P==3 ;TRIDENT T-300S VIA PDP-11 START AT DRIVE 3 +DEFOPT QRDCMP==0 ;SOFTWARE READ-COMPARE, HARDWARE IS PINING FOR THE + ; FJORDS (But this isn't debugged yet.) +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10B==1 ;DF10-BASED TAPE CONTROLLER + +DEFOPT DL10P==1 ;HAS DL10/DC76 TTY CONTROLLER +DEFOPT PDCLKP==1 ;HAS "DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT INETP==1 ; Include Internet IP code +DEFOPT TCPP==1 ; Include Internet TCP code +DEFOPT XBL==25. ; # TCP connections +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==106 ; ARPA net host number +DEFOPT IMPUS3==<1200,,200006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT CHAOSP==1 ;HAS CHAOS NET +DEFOPT MYCHAD==1440 ;CHAOS NET ADDRESS +DEFOPT NINDX==50. ;NUMBER OF INDICES +DEFOPT DLCP==1 ;CHAOS NET GOES THROUGH DL10 + +DEFOPT NOTYS==0 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NETYS==33. ;# KL-10 DTE20 TTYS +NEWDTE==1 ;TEMPORARY CONDITIONAL TO ENABLE NEW DTE20 PROTOCOL +DEFOPT NDLTYS==4. ;# TTYS ON DL10/DC76 + ;Note: 3d TTY on DL10 is VT52 by console. +DEFOPT NSTTYS==25. ;# OF STY'S (PSEUDO-TTY'S) + +DEFOPT TSYSM==2048. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==7 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==7777 ;12 BIT REAL CORE ADDR +DEFSYM PMCSHM==10000 ;CACHE ENABLE BIT +DEFSYM PMAGEM==160000 ;3 BIT AGE +DEFSYM PMUNSD==0 ;NO UNUSED BITS + +DEFINE ITSIRP BODY +IRPS ITS,,[MX] +BODY +TERMIN +TERMIN +] ;MX + +IFE MCOND AI,[ +DEFOPT KS10P==1 ;The new AI has a KS10 processor. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==2 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with two RP06s + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT NETP==1 ;Has one kind of network anyway +;AI's IMP is gone 5/5/89 +;DEFOPT INETP==1 ; Include Internet code +;DEFOPT TCPP==1 ; Include TCP code +;DEFOPT XBL==30. ; # TCP network channels +;DEFOPT IMPP==1 ; Has an IMP interface +;DEFOPT KSIMP==1 ; ACC LH/DH interface on KS unibus +;DEFOPT IMPUS==206 ; ARPA net host number +;DEFOPT IMPUS3==<1200,,400006> ; Internet host number of IMP +;DEFOPT PKTTRC==-1 ;Packet tracing code enabled +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3130 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==12. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC] +BODY +TERMIN +TERMIN +] ;AI + +IFE MCOND MC,[ +DEFOPT KS10P==1 ;MC is now a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==30. ; # TCP network channels +;MC's IMP is gone 5/18/89 +;DEFOPT IMPP==1 ; Has an IMP interface +;DEFOPT KSIMP==1 ; ACC LH/DH interface on KS unibus +;DEFOPT IMPUS==354 ; ARPA net host number +;DEFOPT IMPUS3==<1200,,600054> ; Internet host number of IMP +DEFOPT IPUNCP==1 ; IP in Chaos UNC is our only Internet address +DEFOPT PKTTRC==-1 ;Packet tracing code enabled +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3131 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==6. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC] +BODY +TERMIN +TERMIN +] ;MC + +IFE MCOND ML,[ +DEFOPT KS10P==1 ;ML is now a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3133 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==4 ; 4 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + DEFSYM DZ2BA=:760030 + DEFSYM DZ3BA=:760040 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==4. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC ML] +BODY +TERMIN +TERMIN +] ;ML + +IFE MCOND MD,[ + +DEFOPT KS10P==1 ;MD is a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==3 ;# 1K blocks in a TUT (better agree with disk DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM80P==1 ; with one RM80 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3132 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==4 ; 4 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + DEFSYM DZ2BA=:760030 + DEFSYM DZ3BA=:760040 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==4. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC ML MD] +BODY +TERMIN +TERMIN +] ;MD + +IFE MCOND SI,[ ;Stacken ITS +DEFOPT KS10P==1 ;SI is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==2 ; 2 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==16. ;# DZ-11 TTYs +DEFOPT NSTTYS==8. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[SI] +BODY +TERMIN +TERMIN +] ;SI + +IFE MCOND FU,[ ;Australian KS10 +DEFOPT KS10P==1 ;FU is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[FU] +BODY +TERMIN +TERMIN +] ;FU + +IFE MCOND PM,[ ;MRC's KS10 (PandaMonium) +DEFOPT KS10P==1 ;PM is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==2 ;# 1K blocks in a TUT (better agree with RM03 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM03P==1 ; with one RM03 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==5. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[PM] +BODY +TERMIN +TERMIN +] ;PM + +IFE MCOND DX,[ ;Digex's KS10 +DEFOPT KS10P==1 ;DX is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==2 ;# 1K blocks in a TUT (better agree with RM03 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM03P==1 ; with one RM02/3 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[DX] +BODY +TERMIN +TERMIN +] ;DX + +; Default settings for all configuration-dependent assembly parameters. +; If a system definition has already set a value for a parameter, the +; default here will NOT be used. + +DEFOPT KL10P==0 ;1= KL10 processor +DEFOPT KS10P==0 ;1= KS10 processor +DEFOPT KA10P==0 ;1= KA10 processor + +IFE KL10P\KS10P\KA10P, .ERR Processor type required - KL10P, KS10P or KA10P + +IFN KS10P, DEFOPT KSFREQ==4100000./60. ; KS-ticks per PD-tick. + +DEFOPT C1MXP==0 ;1= Has PI channel 1 MPX feature + +DEFOPT MAXJ==63. ; Max number of jobs allowed +DEFOPT NQCHN==30. ; Max number of user disk channels open in system +DEFOPT SCHBLN==10. ; Number of runnable jobs to remember +DEFOPT SWBLK==0 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==0 ;1= Use page-in preemption + +; Disk parameters + +IFNDEF NQS, .ERR NQS required - # of disk drive units +IFNDEF NTUTBL,.ERR NTUTBL required - # 1K blocks in a TUT + ; (This defn better agree with DC/RP/RH/T3 defs) +IFNDEF NUDSL, .ERR NUDSL required - # directories in file system + ; Just changing this will not work!! +DEFOPT DC10P==0 ;1= Has Systems Concepts disk control +DEFOPT RP10P==0 ;1= DEC RP10 disk control (RP02) +DEFOPT RH10P==0 ;1= DEC RH10 disk control (RP04) +DEFOPT RH11P==0 ;1= DEC RH11 disk control +DEFOPT RP06P==0 ;1= RH11 with RP06's +DEFOPT RM03P==0 ;1= RH11 with RM03's +DEFOPT RM80P==0 ;1= RH11 with RM80's +DEFOPT T300P==0 ;1= Trident T-300 via PDP-11 +DEFOPT QRDCMP==0 ;1= Software read-compare +DEFOPT DMDSK==0 ;1= Use DM DSK format +DEFOPT QRSRVP==0 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==0 ;1= Keep track of file authors + + +; Magtape parameters +DEFOPT NMTCS==0 ; # Mag tape units +DEFOPT TM10A==0 ;1= IO-bus TM10 Mag tape +DEFOPT TM10B==0 ;1= DF10/TM10 Magtape +DEFOPT TM03S==0 ;1= TM03/RH11 KS Magtape +IFN NMTCS,IFE TM10A\TM10B\TM03S,.ERR No Magtape Controller type specified? + + +; Network parameters +DEFOPT NETP==0 ;1= Connected to some network, include net code. +DEFOPT CHAOSP==0 ;1= Has CHAOS net (Must have some interface def'd) +DEFOPT NCPP==0 ;1= Include NCP code (must have IMPP) +DEFOPT INETP==0 ;1= Include Internet Protocol code +DEFOPT TCPP==0 ;1= Include TCP code (must have INETP) +DEFOPT IPUNCP==0 ;1= IP in Chaos UNC is our only Internet address + +;NCP-specific parameters +DEFOPT NNETCH==30. ; # of NCP network channels system supports + +;IP-specific paramters +IFN INETP,[ +IFE IPUNCP,IFNDEF IMPUS3,.ERR IMPUS3 must be defined as Internet host addr +IFN IPUNCP,IFE CHAOSP,.ERR Chaosnet must exist for IP encapsulation scheme +] + +;Chaos-specific parameters +IFN CHAOSP,IFNDEF MYCHAD, .ERR MYCHAD must be defined as CHAOSnet host addr +DEFOPT NINDX==0 ; Number of indices for CHAOS connections +DEFOPT CH10P==0 ;1= CHAOS net via PDP-10 I/O bus +DEFOPT CH11P==0 ;1= CHAOS net via Unibus Chaos board on KS10 +DEFOPT DLCP==0 ;1= CHAOS net via DL10 +DEFOPT T11CHP==0 ;1= CHAOS net via Rubin 10-11 interface +IFN T11CHP,DEFOPT CH11NM==7 ; CHAOS net is on PDP-11 #7 of 10-11 interface + +;IMP interface specific parameters +DEFOPT IMPP==0 ;1= Has IMP interface to ARPAnet +IFN IMPP,IFNDEF IMPUS, .ERR IMPUS must be defined as ARPAnet host # +DEFOPT DMIMP==0 ;1= Has DM IMP interface +DEFOPT KAIMP==0 ;1= Has AI-KA/ML-KA/MX-KL IMP interface +DEFOPT KSIMP==0 ;1= Has KS10 UNIBUS ACC LH-DH IMP interface +IFN IMPP,IFE DMIMP+KAIMP+KSIMP,.ERR IMPP requires an interface type +IFN IMPP,IFN IPUNCP,.ERR IPUNCP and IMPP are incompatible + +; TTY line parameters +DEFOPT MTYP==0 ;1= Has Morton box multiplexor +DEFOPT DL10P==0 ;1= Has DL10/DC76 TTY controller +DEFOPT TK10P==0 ;1= Has TK10 TTY scanner +DEFOPT DPKPP==0 ;1= Has Datapoint kludge TTY mpxr +DEFOPT DZ11P==0 ;1= Has DZ11 Multiplexors + +IFN DZ11P, IFNDEF DZ11NB, .ERR DZ11P requires a value for DZ11NB +IFE DZ11P, DEFSYM DZ11NB==0 ; # DZ11s + +DEFOPT NOTYS==0 ; # KA-10 console 0 TTYs +DEFOPT NETYS==0 ; # KL-10 DTE20 console 0 TTYs +DEFOPT NKSTYS==0 ; # KS-10 8080 console 0 TTYs +DEFOPT NNVTTS==0 ; # Nova TTYs +DEFOPT NNTYS==0 ; # TTYs on Knight kludge +DEFOPT NDZTYS==0 ; # TTYs on DZ11s +DEFOPT NDPTYS==0 ; # TTYs on Datapoint kludge +DEFOPT NMTYS==0 ; # TTYs on Morton box +DEFOPT NDLTYS==0 ; # TTYs on DL10/DC76 +DEFOPT NSTTYS==0 ; # of STY's (Pseudo-TTY's) +DEFOPT N11TYS==0 ; # PDP11 TV TTYs (formerly 16. of them) +IFN N11TYS,[ + DEFOPT TT11NM==0 ; # of PDP11 that handles TTYs. + DEFOPT MXVBN==40 ; Max video buffer # for assignment purposes. +] ; These actually correspond to video switch inputs. +DEFOPT NF2741==0 ; First 2741 console # +DEFOPT N2741==0 ; # 2741's (formerly 3; flushed 3/21/76) +DEFOPT SYSCON==0 ; TTY # of system job console +DEFOPT APL==0 ; AP TTY # + +; Miscellaneous devices + +DEFOPT TEN11P==0 ;1= Rubin 10-11 interface (late of AI-KA) +DEFOPT XGP==0 ;1= Has XGP +DEFOPT NEWDTP==0 ;1= Has new dectape controller +DEFOPT NUNITS==0 ; # Utape (DECtape) units +DEFOPT OLPTP==0 ;1= Has old LPT (Data Products) +DEFOPT NLPTP==0 ;1= Has new LPT (ODEC) +DEFOPT GLPTP==0 ;1= Has Gould LPT +DEFOPT TTLPTP==0 ;1= LPT is on a TTY line (value = line #) +DEFOPT PTRP==0 ;1= Has paper tape reader/punch +DEFOPT PTPP==0 ;1= Paper tape punch works +DEFOPT PDCLKP==0 ;1= Has "DeCoriolis" clock +DEFOPT HCLKP==0 ;1= Has Holloway clock (device 710, 714) +DEFOPT CCLKP==0 ;1= Hack chess tournament clock stuff (device 374) +DEFOPT 340P==0 ;1= Has 340 display +DEFOPT TABP==0 ;1= Has Sylvania tablet +DEFOPT PLTP==0 ;1= Has Calcomp plotter +DEFOPT DSDP==0 ;1= Has deselection device +DEFOPT ARMP==0 ;1= Has arm (AMF mostly) (R.I.P.) +DEFOPT IMXP==0 ;1= Has IMX (input A/D multiplexor) (alas, no more) +DEFOPT OMXP==0 ;1= Has OMX (output D/A multiplexor) (alas, no more) +DEFOPT VIDP==0 ;1= Has VIDI (R.I.P.) +DEFOPT NTYP==0 ;1= Has DM kludge for talking to 11 +DEFOPT CODP==0 ;1= Has Morse code F1 92Mhz broadcast output device +DEFOPT PDP6P==0 ;1= Has PDP-6 (alas, no more) + ; (turning this on probably won't work) +DEFOPT RBTCP==0 ;1= Has Robot console +DEFOPT NDAP==0 ;1= Has "new" D/A converters (alas, no more) +DEFOPT STKP==0 ;1= Has Stanford keyboard (not any more) +DEFOPT E.SP==0 ;1= Has E&S LDS-1 display + +; Some software options + +DEFOPT MSPP==0 ;1= Want message slurper +DEFOPT DEMON==0 ;1= Want crufty DM demon facility +DEFOPT TPLP==0 ;1= Want pseudo LPT + + +; Physical memory parameters + +DEFOPT ECCMEM==0 ;1= Has HIC's error correcting memory +DEFOPT NMMP==4 ; # exec pages for MMP table (# vir pgs/512.) +IFNDEF TSYSM, .ERR TSYSM required - Total PDP10 1K mem blocks + +IFNDEF PMRCM, .ERR PMRCM required - Mem addr field in page map +IFNDEF PMAGEM,.ERR PMAGEM required - Age bits in page map +IFNDEF PMCSHM,.ERR PMCSHM required - Cache bit +IFNDEF PMUNSD,.ERR PMUNSD required - Unused bits + +IFNDEF ITSIRP,.ERR ITSIRP required - Names of local ITS machines + +; Any parameter conflict checks can be made here. + +IFN DZ11P,[ +IFG NDZTYS-, .ERR More DZ11 TTYs than controllers? +REPEAT DZ11NB,[ +IFNDEF CONC DZ,\.RPCNT,BA, .ERR DZ11 bus address not specified. +] +] +IFN $$TEMP,EXPUNGE DEFSYM +IFN $$TEM2,EXPUNGE DEFOPT diff --git a/src/system/core.82 b/src/system/core.82 new file mode 100755 index 00000000..cd3a18b1 --- /dev/null +++ b/src/system/core.82 @@ -0,0 +1,2989 @@ + +;;; CORE JOB + +SUBTTL CORE ALLOCATOR - USER ROUTINES +; +; USER ROUTINES (TO COMMUNICATE WITH CORE JOB) +; +UACORE: ;U HAS INDEX CORE REQUEST IS FOR +ACORE: CAILE B,400 + POPJ P, + MOVE Q,U ;USER TO MAKE CORE FOR +ACORE1: PUSH P,U + MOVE U,USER + PUSHJ P,ACRF1 + SKIPA + AOS -1(P) + POP P,U + POPJ P, + +;EXCESSIVE CORE REQUEST CHECK +ACRTST: CAILE B,400 + POPJ P, + JRST POPJ1 + ;CORTYP SYSTEM CALL. +;IF 2 ARGS,1ST ARG IS JOB SPEC, LIKE CORBLK'S 2ND AND 4TH ARGS. +;2ND ARG IS PAGE NUMBER IN THAT JOB. +;IF ONLY 1 ARG, IT IS THE PAGE NUMBER IN THE EXECUTING JOB. +;RETURNED VALUES: +;1ST VALUE BITS: +; %CBWRT ;4.9 PAGE IS WRITEABLE +; %CBRED ;4.8 PAGE IS READABLE (EXISTS) +; %CBPUB ;4.6 PAGE IS PUBLIC +; %CBLOK ;4.2 PAGE IS LOCKED IN CORE +; %CBSLO ;3.9 PAGE IS IN SLOW MEMORY +; FOR NON EX PAGE, ALL THE REST ARE 0. +;2ND IS 0 => PAGE IS ABSOLUTE, -1 => UNSHARED, +; ELSE IS JOB NUMBER OF NEXT JOB IN CIRCULAR LIST. +;3RD IF ABSOLUTE PAGE, HAS PAGE NUMBER. +; IF PAGE IS SHARED, HAS PAGE NUMBER IN THE JOB +; WHOSE NUMBER IS THE 2ND VALUE. ELSE, 0. +;4TH BIT 4.9 => PAGE IS IN CORE. +; RH IS NUMBER OF TIMES PAGE IS SHARED +; (WILL BE 0 FOR ABS PAGE OR IF NO PAGE, +; OTHERWISE WILL BE >= 1) + +NCORTY: PUSHJ P,SWTL ;DON'T LET PAGE MAPS CHANGE. + CIRPSW + SOSG W ;IF 1 ARG, USE -1 (SELF) FOR JOB SPEC. + SKIPA B,[-1] + EXCH A,B ;ELSE 1ST ARG IS JOB SPEC. + MOVE J,B + JSP T,NCRUI2 ;DECODE THE JOB SPEC IN J, + JFCL ;RETURNS USR IDX IN J. + TDNE A,[-400] + JRST OPNL33 ;BAD PAGE NUM. + PUSHJ P,NCORT0 ;DO THE ACTUAL WORK. + PUSHJ P,LSWPOP ;UNLOCK CIRPSW, + JRST POPJ1 ;GIVE VALUES TO USER, SKIP. + +;CALL HERE FROM AUSET5 (ALWAYS COMES WITH CIRPSW LOCKED) +NCORT0: PUSH P,U +IFN PDP6P,[ + CAIN J,-1 + JRST [ SETZB B,D ;DON'T CALL UPLC IF PDP6, WOULD CRASH SYSTEM + MOVEI C,PDP6BM_-12(A) + CAIL A,LPDP6M + TDZA A,A + MOVSI A,%CBRED+%CBWRT + JRST POPUJ ] +];PDP6P + MOVEI U,(J) ;UPLC USES USER IN U. + PUSHJ P,UPLC ;NOTE PAGE NUM IS IN A. + LDB J,T ;GET PAGE'S HARDWARE HALFWD, + LDB C,Q ;GET CIRC. LIST POINTER. + JUMPE C,NCORTE ;J IF NO PAGE THERE. + MOVEI A,(J) + TRNE A,600000 ;GET ACCESS INTO A 1.1-1.2 + LDB A,[200200,,A] + CAIN A,2 ;CHANGE READ-WRITE-FIRST TO READ-WRITE. + MOVEI A,3 + ROT A,-2 ;SHIFT INTO 4.8-4.9 + CAIN C,-1 + JRST NCORTA ;J IF ABSOLUTE PAGE(CIRC PTR -1) + PUSHJ P,CHACK ;PG MUST HAVE REAL CIRC LIST, TRACE IT. + EXCH C,D ;D HAD MMP IDX; C HAD IN-CORE,,LIST LENGTH. + ADD C,MMPEAD + SKIPGE C,(C) .SEE MMPPUB + TLO A,%CBPUB + TLNE C,MMPLOK + TLO A,%CBLOK + TLNE C,MMPSLO + TLO A,%CBSLO + SUBI D,1 ;LIST LENGTH COUNTS THE MMP ENTRY, + SKIPGE D + SUBI D,1 ;COUNTS THE MEMBLT ENTRY IF PAGE IN CORE. + TRNN D,-2 ;RH NOW HAS # SHARERS, + JRST NCORTS ;ONLY 1 => PAGE NOT SHARED. + MOVE C,Q + MOVE B,P + PUSHJ P,UCPRL ;>1 SHARER => FIND NEXT SHARER, + 400000,,.+1 + MOVE P,B ;UN-SCREW STACK (UCPRL PUSHJ'D BACK) + LDB B,[101100,,T] + MOVE C,I ;2ND, 3RD VALUES USR NUM & PAGE NUM + JRST POPUJ ;OF THE NEXT SHARER. + +;COME HERE IF NO PAGE WITH THAT PAGE NUM. +NCORTE: SETZB A,B + SETZB C,D ;RETURN ALL ZEROS. + JRST POPUJ + +;COME HERE IF ABS PAGE, ACCESS ALREADY IN A. +NCORTA: SETZB B,D ;JOB # 0 (SYS JOB) FOR ABS PAGE. + LDB C,[PMRCAD,,J] ;GET ABS PAGE NUM FROM HARDWARE HALFWD. + JRST POPUJ + +;COME HERE IF UNSHARED NORMAL PAGE. +;ACCESS ALREADY IN A, 4TH VALUE IN D. +NCORTS: SETO B, ;2ND VALUE -1 FOR UNSHARED. + SETZ C, + JRST POPUJ + +;CORBLK CALL +;1ST ARG FLAG BITS: (RH XOR'D INTO LH BEFORE DECODING) + +%CB==0,,525252 +%CBWRT==400000 ; 4.9 GET WRITE ACCESS IF OK, DON'T FAIL IF NOT. +%CBRED==200000 ; 4.8 GET READ ACCESS +%CBNDW==100000 ; 4.7 GET WRITE ACCESS, FAIL IF CAN'T. +%CBPUB==40000 ; 4.6 MAKE PAGE PUBLIC +%CBPRV==20000 ; 4.5 MAKE IT PRIVATE (BOTH FAIL IF COULDN'T GET WRITE ACCESS) +%CBNDR==10000 ; 4.4 FAIL IF CAN'T GET READ ACCESS.(COPYING NONEXISTANT PAGE) +%CBCPY==4000 ; 4.3 MAKE COPY (CURRENTLY ONLY IMPLEMENTED FOR PAGE OF FILE) +%CBLOK==2000 ; 4.2 LOCK PAGE IN CORE. +%CBULK==1000 ; 4.1 UNLOCK PAGE (ALLOW SWAP-OUT) +%CBSLO==400 ; 3.9 MAY ONLY RESIDE IN SLOWEST MEMORY +%CBUSL==200 ; 3.8 ALLOWS USE OF ANY MEMORY. + ;IF ALL 0, DELETE. + +%CBNWP==563600 ;BITS THAT NEED WRITE-PERMISSION. + +;2ND ARG SPECIFIES JOB TO PUT PAGE IN +; IS EITHER CHNL NUM, -1 FOR SELF, OR 400000+USRNUM +;JOB SPECIFIED MUST BE CURRENT JOB OR INFERIOR. + +;3RD ARG RH. IS PAGE NUM. IN IT. +; LH. IF NEGATIVE, BLOCK MODE, REPEAT THAT MANY TIMES, +; INCREMENTING BOTH PAGE NUMS EACH TIME. +;IN BLOCK MODE, REWRITES 3RD AND 5TH ARGS EACH TIME. + +;4TH ARG IS SOURCE OF PAGE, +; A DISK CHANNEL NUMBER (GET N'TH PAGE IN FILE), OR +; A SPEC: +; A USR, JOB, BOJ, OR STY CHANNEL NUMBER +; OR ONE OF THE FOLLOWING SPECIAL CODES: +%JS==,-1 +%JSNUM==400000 ;400000+JOB NUMBER => THAT JOB +%JSSUP==400377 ;CURRENT JOB'S SUPERIOR +%JSELF==,,-1 ;SELF +%JSTVB==,,-2 ;TV11 VIDEO BUFFER IN FIRST 8 PAGES, 1ST WD OF 9TH PG IS CONSOLE REG +%JSNUL==,,-3 ;NULL JOB (NOT VALID FOR CORBLK) +%JSALL==,,-4 ;ALL JOBS (NOT VALID FOR CORBLK) +%JSNEW==,,-5 ;FRESH PAGE +%JSABS==,,-6 ;ABSOLUTE PAGE (PHYSICAL MEMORY) +; JOB 0 = SYSTEM JOB = EXEC VIRTUAL ADDRESS SPACE +; JOB 1 = CORE JOB = FRESH PAGE (OBSOLESCENT, USE %JSNEW, EVENTUALLY WILL GO AWAY) +;IF NO 4TH ARG, SAME AS 2ND + +;5TH ARG IS PAGE NUM IN SOURCE (IGNORED FOR FRESH PAGE) +;IF NO 5TH ARG, SAME AS 3RD IF 4TH ARG SPECIFIES JOB. + +;IF 4TH ARG SPECS FILE, USE CURRENT ACCESS PNTR +;IF INSERTING DISK PAGES, THE ACCESS PTR WILL BE +;POSITIONED AT THE BEGINNING OF THE PAGE AFTER THE LAST PAGE INSERTED. + +;BITS IN REGS R AND I: +NCOR$P==400000 ;SOURCE USER ISN'T WRITEABLE. PAGES ARE, IFF PUBLIC. +NCOR$Q==200000 ;SOURCE IS A DISK FILE. + +;CORBLK - COMMENTS ON PRECEDING PAGE. +NCORBL: TSC A,CTLBTS(U) + TLC A,(A) ;WIN FOR IMMEDIATE FIRST ARG + HRRZM C,SRN3(U) ;SAVE PTRS TO 3RD, 5TH ARGS IN SRN3, SRN4 RESPECTIVELY + TLNE C,1000 + TLZA C,-1 + UMOVE C,(C) + SKIPGE C ;IF WILL REWRITE,CHECK FOR PURE + XCTR XRW,[MOVES @SRN3(U)] + HRRZM E,SRN4(U) + CAIGE W,5 ;BUT IF NO 5TH ARG, SAY SO & USE 3RD. + JRST NCORB1 ;DEFAULT E TO C,SETOM SRN4 + TLNN E,1000 ;IMMEDIATE 5TH ARG LEGAL + JRST NCORB8 + JUMPGE C,NCORB7 ;ONLY IF WON'T HAVE TO REWRITE IT + JRST OPNL33 + +NCORB1: SETOM SRN4(U) + MOVE E,C + JRST NCORB7 + +NCORB8: UMOVE E,(E) + SKIPGE C + XCTR XRW,[MOVES @SRN4(U)] +NCORB7: ANDI E,-1 + MOVE J,B + JSP T,NCRUI1 ;GET USER INDEX OF TARGET. + JRST NCORB0 ;IF DOESN'T SKIP, CAN CERTAINLY WRITE. + CAIE J,-1 ;CAN'T STICK PAGE IN 6. + JSP T,NCORWR ;ELSE CHECK. + JRST OPNL31 ;CANT WRITE SO CANT STICK PAGE IN +NCORB0: MOVEI TT,(J) ;SAVE DEST. USER IDX. + CAIN TT,(U) ;IF NOT ACTING ON SELF, PCLSR TARGET JOB. + JRST NCORC1 + EXCH A,TT + PUSHJ P,RPCLSR + PUSHJ P,LSWPOP ;SOS DIELOK(A) + MOVEM A,SRN5(U) + MOVSI T,BSSTP ;BUT LEAVE BSSTP SET INSTEAD OF RH + IORM T,USTP(A) + SOS USTP(A) ;BECAUSE CORE JOB WANTS RH TO BE CLEAR + EXCH A,TT + PUSHJ P,LOSSET ;UNDO SETTING OF BSSTP IF WE PCLSR OR FAIL + NCORFS + CAIA +NCORC1: PUSHJ P,LSWPOP ;SOS DIELOK(TT) +;DROPS THROUGH. + +;DROPS THROUGH. ALSO COME HERE FROM ACBLK. +;TARGET DECODED AND STOPPED IF NEC.; USER IDX IN TT. +; NOW DECODE SOURCE IF NEC. +NCORB9: PUSHJ P,SWTL + CIRPSW + TLNE A,%CBNDW ;FORCE WRITE => WRITE. + TLO A,%CBWRT + JUMPE A,NCORD ;0 ACCESS WANTED => DELETE PAGES. + TLO A,%CBRED ;NOT DELETE, WANT AT LEAST READ ACCESS. + CAIGE W,4 ;IF HAD 4TH ARG, DECODE, + JRST NCORC2 ;ELSE USE DECODED 2ND (STILL IN J). + HRRZ J,D + CAIE J,%JSNEW + CAIN J,%JSABS + JRST NCORC2 ;SPECIAL NON-JOB SOURCE, SKIP DECODE +IFN N11TYS,[ + CAIN J,%JSTVB + JRST [ SKIPN TEN11F ;TV11 SOURCE + SKIPL TT11P + JRST OPNL10 ;DEVICE NOT AVAIL + JRST NCORC2] +] + MOVE J,D + JSP T,NCRUI1 ;GET SOURCE USR IDX + JRST NCORB2 + JRST NCORC0 + TLNN H,%CLSQ ;COME HERE IF ARG IS RANDOM IO CHANNEL. + JRST OPNL34 ;NOT DSK => NO GOOD. + MOVE R,J ;2 SKIPS => DISK CHNL; PUT ITS # IN R. + TLO R,NCOR$Q ;INDICATE DISK CHNL + MOVSI T,%QAACC + TDNE T,QSRAC(R) ;INSURE THAT %QAACC WILL BE ON IF OUR + JRST NCORQD + IORM T,QSRAC(R) ;CALL TO QFNTR FINDS EOF. + MOVE T,QFBLNO(R) ;IF %QAACC WAS 0, THEN QRADAD ISN'T SET UP. + MOVEM T,QRADAD(R) +NCORQD: SETOM NCORQC ;1ST TIME THRU NCORL LOOP COMING UP. + CAIGE W,5 + JRST NCORL + MOVE T,E ;DON'T SMASH E, WILL BE WRITTEN BACK TO USER + LSH T,10. ;5TH ARG GIVES PAGE ADDRESS IN FILE FOR DISK CHNL + IMULI T,@QSBYTE(R) + MOVEM T,QRADAD(R) ;SET ACCESS PTR OF DSK CHNL -> SPEC'D PAGE. + JRST NCORL + +NCORC0: TLNN A,%CBNWP ;IF REQUIRE ALTERATION, + JRST NCORB2 + JSP T,NCORW1 ;IF CAN'T WRITE THAT JOB, + HRLI J,NCOR$P ;SET FLAG TO CHECK FOR PUBLIC. +NCORB2: CAIE J,-1 ;IF NOT PDP6, + PUSHJ P,LSWPOP ;SOS DIELOK(J) + CAIN J,LUBLK ;IF SOURCE IS CORE JOB (EVENTUALLY DELETE THESE TWO LINES) + MOVEI J,%JSNEW ; THAT MEANS GET FRESH PAGE +NCORC2: MOVE R,J + CAIN R,%JSNEW ;FRESH PAGE IMPLIES WRITING + TLO A,%CBNDW+%CBWRT + +;DROPS THROUGH + +;DROPS IN + +;NOW HAVE TARGET IDX IN TT, SOURCE IN R (USER INDEX, -1 FOR +; PDP6, %JSTVB, %JSNEW, OR %JSABS). +;TARGET PAGNUM IN C; SOURCE IN E (MAYBE INVALID). +;R 4.9 => WRITE REQUIRES PUBLIC PAGE. +;R 4.8 => R HAS DISK CHNL (AND NCORQC IS -1 THE 1ST TIME AROUND) +;DECIDE WHAT KIND PAGE WANTED AND FIND IT. +;CIRPSW MUST BE ON TOP OF LSWPR. IT WILL BE +;UNLOCKED EVENTUALLY (AND ALSO 1 MORE UNDERNEATH IT +;IF THE TARGET JOB ISN'T US). FAILURE DOES A LSWCLR. +NCORL: MOVEI I,(R) ;I WILL HAVE USR IDX FOR ACTUAL PAGE. + HLRS A ;RH OF A WILL GET ACCESS TO BE GRANTED. + TRNE C,-400 ;CHECK DEST PAGE NUM IN RANGE. + JRST OPNL33 + + PUSH P,U + PUSH P,C + TLNE R,NCOR$Q + JRST NCORQ1 ;DISK FILE +IFN PDP6P,[ + CAIN I,-1 + JRST NCORE4 ;-1 => PDP6 PAGE. +] +IFN N11TYS,[ + CAIN I,%JSTVB + JRST NCORV1 ;TV11 +] + CAIN I,%JSNEW + JRST NCORF0 ;FRESH PAGE. + CAIN I,%JSABS + JRST NCORE1 ;ABSOLUTE PAGE. + CAIL E,400 + JRST NCORE7 ;ELSE SOURCE PAGNUM MUST BE < 400 + MOVEI U,(R) ;SOURCE IS A USER +NCORF2: EXCH E,A ;GET SOURCE PAGNUM IN A + PUSHJ P,UPLC;(A,U) ;FIND THE PAGE WANTED. + EXCH E,A + LDB J,Q ;UPLC RETURNS IN T,Q. + JUMPE J,NCORE6 ;FAIL OR DELETE IF HE HAS NO PAGE THERE. + CAIN J,-1 + JRST NCORE5 ;IF THAT PAGE IS ABS,CHANGE TO ABS REQ. + PUSHJ P,CHACK ;A REAL PAGE, FIND MMP, PREV. PTR. + ADD D,MMPEAD + MOVE B,Q + MOVEI I,(R) ;CHACK CLOBBERS I + TLNN A,%CBNDW+%CBWRT ;IF WANTED ALTERATION, CHECK LEGAL. + JRST NCORB3 + LDB J,T ;1ST OF ALL, SOURCE MUST HAVE WRITE PERM. + TRNN J,600000 + LSH J,20 + TRNN J,400000 + JRST NCORB5 + CAIN R,%JSNEW + JRST NCORF3 +NCORF4: CONO PI,UTCOFF ;DSK XFER COULD COMPLETE, CHANGING INTRANSIT BIT + MOVE J,(D) ; HE HAS WRITE PERM.; GET MMP IN J. + TLNE R,NCOR$P ; CAN'T ALTER IF NEEDED PUBLIC BUT IT ISN'T. + JUMPGE J,[ CONO PI,UTCON .SEE MMPPUB + JRST NCORB5] + TLNE A,%CBPUB ;WE CAN ALTER; CHANGE PUBLIC IF REQ. + TLO J,MMPPUB + TLNE A,%CBPRV + TLZ J,MMPPUB + TLNE A,%CBLOK + TLO J,MMPLOK + TLNE A,%CBULK + TLZ J,MMPLOK + TLNE A,%CBSLO + TLO J,MMPSLO + TLNE A,%CBUSL + TLZ J,MMPSLO + MOVEM J,(D) + CONO PI,UTCON + JRST NCORB3 + +NCORF0: MOVEI U,(TT) ;WHEN CREATING A FRESH PAGE, HAVE TO RE-USE A PREVIOUSLY + MOVEI E,(C) ;EXISTING PAGE IF POSSIBLE, BECAUSE AFTER THE FRESH PAGE + JRST NCORF2 ;IS GIVEN, USER WILL BE PCLSR'ED AND WILL COME IN AGAIN + ;LOOKING FOR A FRESH PAGE. CURRENTLY THIS CAUSES A BUG + ;THAT A "FRESH PAGE" IS NOT ALWAYS ZERO. + +NCORF3: CAIE C,2 ;WANT FRESH PAGE + CAMN C,[SETZ 3] + JRST .+2 + JRST NCORD0 ;SHARED PAGE CAN'T SERVE AS FRESH PAGE + MOVEI I,(TT) + JRST NCORF4 + +;COME HERE IF REQ WRITE ON REAL PAGE BUT CAN'T GRANT. +NCORB5: CAIN R,%JSNEW + JRST NCORD0 ;JUST REPLACE WITH FRESH PAGE + TLNE A,%CBNDW+%CBPUB+%CBPRV+%CBSLO+%CBUSL+%CBLOK+%CBULK ;IF HE INSISTED, FAIL. + JRST NCORE0 + TRZ A,%CBWRT ;ELSE GIVE HIM ONLY READ PERM. +;COME HERE IF PAGE EXISTS TO GIVE ACCESS AS IN A 2.8,2.9 +NCORB3: HRRZ J,(P) + CAIN TT,(I) ;ARE WE REPLACING PAGE BY ITSELF? + CAME E,J + JRST NCORD0 ;NO, DELETE OLD, INSERT NEW. + LDB J,T ;REPLACING PG W/ SELF, SET ACCESS & EXIT. + TRNN J,600000 + JRST NCORI1 + TRNN J,400000 ;CHANGE READ TO RWF + TRC J,600000 + TRNE A,%CBWRT + JRST NCORI2 + MOVSI I,40000 + TROE J,200000 + ANDCAM I,(D) + TRZ J,400000 + JRST NCORI2 + +NCORI1: MOVEI J,1 + TRNE A,%CBWRT + TRO J,2 +NCORI2: DPB J,T + POP P,C + POP P,U + JRST NCORX ;TO END OF LOOP. + +NCORQ1: PUSH P,A + PUSH P,TT + PUSH P,R + MOVEI A,(R) + AOSN NCORQC ;THE 1ST TIME AROUND LOOP? + JRST NCORQ0 ;YES, ACCESS TO 1ST PAGE TO BE INSERTED. + PUSHJ P,QFNTN ;NO, JUST MOVE FORWARD 1 PAGE + JRST NCORE8 ;REACHED EOF, CAN'T INSERT PAGE +NCORQF: POP P,R + POP P,TT + POP P,A + MOVE I,R ;FOUND THE PAGE, GO INSERT IT. + JRST NCORD0 + +NCORQ0: MOVE Q,QRADAD(A) + PUSHJ P,QFNTR + JRST NCORE8 + PUSHJ P,QUDULK ;QFNTR LEAVES IT LOCKED + AOS QSLGL(A) ;DON'T BE FOOLED BY QFNTR'S TRICK + SOS QSBI(A) ;ON THE DISK PI RTNS. + JRST NCORQF + +NCORE8: POP P,R + POP P,TT + POP P,A +NCORE6: CAIN R,%JSNEW ;COPY NONEXISTANT PAGE + JRST NCORD0 ;JUST PUT IN A FRESH PAGE + HRRI A,0 ;CHANGE TO DELETE RQ. + TLNN A,%CBNDR+%CBNDW+%CBPUB+%CBPRV+%CBLOK+%CBULK+%CBSLO+%CBUSL + JRST NCORD0 ;IF INSIST ON ACCESS, FAIL. +NCORE0: PUSHJ P,OPNL32 ;CAN'T GRANT ACCESS OPNL. +POPCUJ: POP P,C ;FAIL OUT OF CALL. + JRST POPUJ + +IFN PDP6P,[ +;REQ FOR PDP6 PAGE. +NCORE4: CAIL E,LPDP6M + JRST NCORE7 ;OUT OF RANGE. + MOVEI B,PDP6BM_<-10.>(E) + JRST NCORE3 ;CONVERT TO ABS REQ, WRITE OK +] + +IFN N11TYS,[ +;REQ FOR TV11 PAGE. +NCORV1: CAIL E,NTVBP + JRST NCORE7 + SKIPL TVCREG(TT) ;IF CONSOLE REGISTER NOT ALREADY SET UP + JRST NCORV2 + MOVE B,TVVBN(TT) ;INITIALIZE IT FROM BLINKER + MOVEM B,TVCREG(TT) + CAMN TT,USER + MOVEM B,400000+TTR10*2000 ;INITIALIZE HARDWARE CONSOLE REGISTER. +NCORV2: LDB B,TTCRT(E) ;GET MAP ENTRY OUT OF EXEUMP + ANDI B,PMRCM ;MASK TO PAGE # + JRST NCORE3 ;CONVERT TO ABS REQ, WRITE OK +] +;REQ FOR ABS PAGE. +NCORE1: MOVEI B,(E) + CAIGE B,TSYSM + JRST NCORE2 ;ACCESS AVAILABLE, READ ONLY + JRST NCORE6 ;CAN'T GET ACCESS TO PAGE. + +NCORE7: PUSHJ P,OPNL33 ;BAD ARG OPNL. + JRST POPCUJ + +;PAGE TO COPY WAS AN ABS PAGE. +NCORE5: CAIN R,%JSNEW + JRST NCORD0 ;SUBSTITUTE A FRESH PAGE + LDB B,T ;GET ABS PAGE NUM. + TRZE B,400000 ;IF HE HASN'T WRITE PERM. + JUMPGE R,NCORE3 ;OR WE CAN'T WRITE IN HIM, +NCORE2: TRZ A,%CBWRT ;CAN'T GET WRITE, + TLNN A,%CBNDW ;FAIL IF INSIST. +NCORE3: TLNE A,%CBPUB+%CBPRV+%CBLOK+%CBULK+%CBSLO+%CBUSL + JRST NCORE0 ;OR IF TRYING TO CHANGE PUBLICNESS. + MOVE D,B ;GET JUST THE PAGE # (NOT THE ACCESS CODE) + ANDI D,PMRCM ;TO INDEX INTO TABLES WITH. +IFN TEN11P,[ + LDB I,[.BP D] ;GET MOBY # + CAIE I,T11CPA_-18. + JRST NCORE9 + MOVE Q,D + SUBI Q,_8 + CAIL Q,256. + JRST 4,. + SKIPN I,T11MP(Q) + JRST 4,. ;SHOULDNT HAVE ABS PNTR TO NOT SET UP PAGE + AOJE I,NCOREA ;CONFLICT PAGE + LDB I,[350500,,T11MP(Q)] + CAIN I,37 + JRST NCOREA ;USAGE COUNT FULL + ADDI I,1 + DPB I,[350500,,T11MP(Q)] + JRST NCOREA +NCORE9:] +IFN PDP6P,[ + CAIL D,PDP6BM_-10. ;IS ABS PAGE # WITHIN RANGE OF PDP6 PAGES? + CAIL D,PDP6BM_-10.+LPDP6M + JRST NCOREB + SKIPL PDP6UP ;IF SO, ALLOW PAGE COPYING, IFF PDP6 IS UP. + JRST NCORE6 + JRST NCOREA + +NCOREB:] + CAIL D,TSYSM + JRST NCORE6 ;DONT ALLOW POINTER TO PAGE ABOVE TOTAL SYSTEM MEMORY + LDB I,[MUR,,MEMBLT(D)] + CAIN I,MUHOLE ;DON'T GIVE ABS PAGE THAT IS NXM. + JRST NCORE6 +NCOREA: MOVEI I,%JSABS ;INDICATE ABS REQ. + JRST NCORD0 + +EBLK +NCORQC: 0 ;COUNTS PASSES THRU NCORL, IF SOURCE IS DISK FILE. + ;FORCES COMPLETE REPOSITIONING IN FILE THE 1ST TIME THRU. +BBLK + +;THIS IS FOR DELETE RQS WHAT NCORL IS FOR INSERTS. +.SEE NCORL ;ABOUT CIRPSW, ACS, ETC. + ;ALSO SEE COMMENTS HALFWAY DOWN THIS PAGE. +NCORD: TRNE C,-400 + JRST OPNL33 ;PAGE NUM. OUT OF RANGE. + PUSH P,U + PUSH P,C +NCORD0: PUSH P,A ;COME IN HERE ON VALID INSERT RQ. +NCORD1: MOVE U,TT + HRRZ A,-1(P) + PUSH P,T + PUSH P,B + PUSHJ P,UPLC ;SAVE TIME BY CHECKING WHETHER PAGE EXISTS. + LDB B,T + SKIPE B + PUSHJ P,PAGERT ;IT EXISTS; DELETE IT. + POP P,B + POP P,T + POP P,A ;FLAG WORD + POP P,C ;TARGET PAGNUM + POP P,U + TRNN A,%CBRED+%CBWRT ;IF NO ACCESS REQ, IS DELETE, THRU. + JRST NCORX +;RH. OF A HAS ACCESS TO GRANT. LH(A) HAS ORIGINAL CONTROL BITS. +;IF I=%JSABS, ABS PAGE, NUM. IN B. +;IF I=%JSNEW, FRESH PAGE. +;IF 4.8 IN I SET, DISK PAGE POINTED TO BY CHNL IN I +;ELSE OLD PAGE, B IS BP -> CIRC LIST, T -> OLD ACCESS. + PUSH P,C ;-3 + PUSH P,E ;-2 + PUSH P,TT ;-1 + PUSH P,A ;0 + TLNE I,NCOR$Q + JRST NCORQ2 ;INSERT PAGE FROM FILE + CAIN I,%JSABS + JRST NCORA ;GO INSERT ABS PAGE + CAIE I,%JSNEW + JRST NCORR ;GO INSERT REAL PAGE. + PUSH P,R + LSH C,9 ;INSERT FRESH PAGE. + MOVEI Q,(TT) ;TARGET JOB + IDIVI TT,LUBLK ;CLOBBERS I. + IORI TT,400000(C) + HRLI TT,204000 + TLNE A,%CBPUB ;MAYBE RQ PUBLIC + TLO TT,1000 + PUSHJ P,NACRFL ;PUT IN CORE RQ (FREES CIRPSW) + JRST NCORF1 + POP P,R + PUSHJ P,SWTL + CIRPSW + HRRZ E,-3(P) ;GET TARGET PAGE NUM + JRST NCORR2 + +NCORF1: SUB P,[5,,5] + JRST OPNL37 ;NO CORE OPNL. + +;COME HERE IF NEED TO WAIT FOR CORE AVAILABLE FOR NEW MMP PAGE. +NCORQW: PUSHJ P,LSWPOP ;UNLOCK TUT. + PUSHJ P,LSWPOP ;AND CIRPSW, SO CORE JOB CAN OPERATE. + MOVEI T,3 ;WAIT TILL MEM HAS BEEN FREED BY CORE JOB. + CAMLE T,LMEMFR + PUSHJ P,UFLS + PUSHJ P,SWTL ;RE-LOCK CIRPSW + CIRPSW + MOVE TT,(P) + JRST NCORQB ;THEN RETRY, RELOCKING TUT. + ;FIND OR CREATE MMP ENTRY FOR BLOCK <- DISK CHNL IN I. +;ACCESS TO GRANT IS IN A. +;RETURNS STUFF IN B,T ACCORDING TO COMMENT +;AFTER NCORD1 (IF NEW MMP, IT POINT TO SELF AND B -> IT) +NCORQ2: PUSH P,R + PUSH P,[NCORR3] ;RETURN TO NCORR3, SKIPPING UNLESS MMP FULL + MOVE TT,A + MOVE A,I +NCORQ7: PUSH P,TT ;ENTRY FROM NLOAD +NCORQB: MOVE I,QDSKN(A) + MOVE W,QSLGL(A) + HRL W,I + PUSHJ P,QTLOCK + TRNE TT,%CBCPY ;SPECIFIED COPY-ON-WRITE? + JRST NCORQ6 ;GET FRESH COPY OF PAGE + MOVE B,W ;ELSE TRY TO SHARE EXISTING COPY OF PAGE + IDIVI B,SHRHSL ;LOOK UP IN SHAREABLE-PAGE HASH TABLE + MOVEI B,SHRHSH-1(C) +NCORQ5: HRRZ B,1(B) ;THREAD TO NEXT MMP ENTRY IN BUCKET + JUMPE B,NCORQ6 ;END OF LIST, DESIRED PAGE NOT FOUND + HLRZ C,1(B) ;GET DISK ADDRESS OF THIS PAGE + LDB R,[$MMPUN,,(B)] + CAIN C,(W) + CAIE R,(I) + JRST NCORQ5 ;NOT THE ONE WE WANT + MOVEI R,(B) ;SET UP MMP IDX IN R + SUB R,MMPEAD ;AS GMMPP RETURNS IT. + PUSHJ P,QTULK ;TUT ALREADY AOS'ED. + MOVSI T,MMPGON + TDNE T,(B) + JRST [ MOVSI T,MMPTMP ;MMP ENTRY GOING AWAY. + TDNE T,(B) ;IF DISK TRANSFER ALSO IN PROGRESS, + JRST NCRMMW ; GO WAIT FOR THINGS TO SETTLE WITH CIRPSW FREE. + PUSH P,A + PUSHJ P,RETMM4 ;CLEAR PENDING FREEAGE + POP P,A + JRST NCORQB ] ;AND TRY AGAIN + MOVEI C,-1 + HRRZ T,(B) ;GET CIRC PNTR OUT OF MMP ENTRY. + CAIL T,600000 ;SKIP IF DOESN'T POINT TO MEMORY + TDNE C,MMSWP-600000(T) ;SKIP IF IT'S A LOOSE PAGE + JRST NCORQ8 + HRRZ C,MEMPNT-600000(T) + CAIE C,400000(R) ;SKIP IF NO USERS IN CIRCULAR LIST + JRST NCORQ8 ;NOT REALLY LOOSE, USERS LINKED BUT NOT CONNECTED + MOVEI C,0 ;REMOVE FROM LOOSE PAGE LIST + MOVE W,FLOOSP +NCORQ3: MOVE TT,C ;TT PREDECESSOR + SKIPN C,W ;W SUCCESSOR + JRST 4,. ;NOT IN LOOSE PAGE LIST? + LDB W,[MLO,,MEMBLT(C)] + CAIE C,-600000(T) + JRST NCORQ3 + SKIPE TT + DPB W,[MLO,,MEMBLT(TT)] + SKIPN TT + MOVEM W,FLOOSP + SKIPN W + MOVEM TT,LLOOSP + SOSL NLOOSP + JRST NCORQ8 + JRST 4,. ;NLOOSP WAS TOO SMALL? + +NCORQ6: SOSGE MMPFR ;NEED TO CREATE NEW MMP ENTRY; COMMIT ONE + JRST [ AOS MMPFR ;MMP FULL + JRST POPTTJ ] ;TAKE ERROR RETURN + PUSHJ P,GMMPP ;GET FREE MMP ENTRY (CAN'T PCLSR AFTER THIS SUCCEEDS) + JRST NCORQW ;WAIT FOR MORE MEM + PUSHJ P,QTAOS1 ;AOS TUT FOR BLOCK (TUT ALREADY LOCKED) + HRLZM W,1(TT) ;STORE DISK ADR + MOVE D,R + IOR D,[MMPOUT+MMPWOD,,400000] ;SWAPPED OUT, MMP POINTING TO SELF + DPB I,[$MMPUN,,D] + MOVE C,(P) ;A + TRNE C,%CBCPY + TLCA D,MMPWOD+MMPISW ;COPYING, SO SET INITIAL-SWAPIN + JRST [ MOVE B,W ;NO COPYING, SO + IDIVI B,SHRHSL ;STICK INTO SHAREABLE-PAGE HASH TABLE + MOVE B,SHRHSH(C) + HRRM B,1(TT) + HRRZM TT,SHRHSH(C) + TLO D,MMPSHR ;FLAG MMP ENTRY AS IN SHRHSH TABLE + JRST .+1 ] + MOVEM D,(TT) + HRRZ B,TT + AOS NPGSWO +NCORQ8: MOVE T,[300,,[3]] + HRLI B,2200 + AOS -1(P) ;SUCCESS RETURN + JRST POPTTJ + +NCORA: MOVEI A,(C) + MOVE U,TT ;INSERT ABS PAGE. + PUSHJ P,UPLC ;FIND TARGET PAGE + IOR B,(P) ;COMBINE ACCESS W/ PAGE NUM. + TRZ B,PMAGEM\PMUNSD\PMCSHM +IFE KA10P,[ + TRNE B,PMRCM ;PAGE 0 NOT CACHED + IORI B,PMCSHM +] + LDB D,T + TRZ D,PMAGEM ;TURN OFF REMNANT AGE BITS + JUMPN D,[JRST 4,.] ;SHOULD HAVE DELETED PAGE ALREADY + DPB B,T + MOVNI B,1 ;CIRC. PTR. IS -1. + DPB B,Q + MOVEI E,(A) + JRST NCORR2 + + ;VIRTUAL PUSHJ AT NCORQ2 +NCORR3: JRST [ SUB P,[5,,5] ;MMP WAS FULL + JRST OPNL37 ] + POP P,R ;COME HERE FOR DSK PG, AFTER FINDING MMP. + MOVE C,QRADAD(A) ;MOVE ACCESS POINTER OF FILE TO + IDIVI C,@QSBYTE(A) ;NEXT PAGE BOUNDARY, BEING CAREFUL + IORI C,1777 ;ABOUT BYTES. + AOS C + IMULI C,@QSBYTE(A) ;NEXT USE OF FILE WILL GET + MOVEM C,QRADAD(A) ;WHAT FOLLOWS PAGES MAPPED. + MOVSI C,%QAACC ;INDICATE ACCESS PTR CHANGED. + IORM C,QSRAC(A) +;COME HERE TO INSERT PG FROM OTHER USER. +NCORR: HRRZ E,-3(P) ;TARGET PAGE # C + HRRZ U,-1(P) ;TARGET JOB TT + HRRZ TT,(P) ;ACCESS (WRITE BIT IN 2.9) + PUSHJ P,NCORR1 ;ACTUALLY MUNG MAP. +NCORR2: PUSHJ P,GHUSRA ;TARGET PAGE NUM MUST BE IN E + POP P,A + POP P,TT +NCORA1: POP P,E + POP P,C +;COME HERE AFTER HANDLING 1 PAGE. +NCORX: MOVE U,USER + CLRPGM (U) + JUMPGE C,NCORX1 ;IF LH POS, DON'T REWRITE. + ADD C,[1,,1] + ADDI E,1 + UMOVEM C,@SRN3(U) + SKIPL SRN4(U) ;REWRITE 5TH ARG ONLY IF WAS GIVEN. + UMOVEM E,@SRN4(U) + JUMPGE C,NCORX1 + TLNN A,%CBRED + JRST NCORD ;LOOP AROUND FOR DELETE RQ + JRST NCORL ;FOR INSERT RQ. + +NCORX1: AOS (P) +NCORX0: PUSHJ P,LSWPOP ;FREE CIRPSW +NCORX2: CAIN TT,(U) ;IF NOT ACTING ON SELF, + POPJ P, + JRST LSWPOP ;CAN'T FALL THRU SINCE MIGHT BE NULSET. + +;THIS IS A LOSSET ROUTINE TO CLEAR THE BSSTP BIT OF THE JOB +;WHOSE INDEX IS IN THE SRN5 OF THE RUNNING JOB. +NCORFS: MOVE A,SRN5(U) + MOVSI T,BSSTP + ANDCAM T,USTP(A) + POPJ P, + ;JSP T,NCORUI WITH JOB-SPEC IN J, RETURNS USER IDX IN J (OR ,,-1 FOR PDP6) + +;JOB SPECS ARE: +; -1 OR ,,-1 FOR SELF. +; (MUST BE USR, STY, JOB OR BOJ DEVICE ELSE OPNL34) +; 400000+ JOB WITH THAT NUMBER (OPNL35 IF NONE) +; ( -1,, ALSO WORKS) +;IF THIS JOB IS CERTAINLY ALLOWED TO MODIFY SPEC'D JOB, DOESN'T SKIP. +;IF SKIPS ONCE, MUST CHECK FARTHER. IN EITHER CASE, DIELOK OF JOB HAS BEEN AOS'D +;AND SOSSET'ED, UNLESS ENTRY POINT WAS NCRUI2, OR JOB IS PDP6. +;2 SKIPS => ARG IS RANDOM I-O CHANNEL; CLSTB ENTRY IN H. +;IN THAT CASE, NO SOSSET WAS DONE. RANDOM CHANNELS ALLOWED ONLY IF ENTRY POINT IS NCRUI1. + +NCRUI2: HRLI T,200000 ;ENTRY TO SUPPRESS AOS'ING OF DIELOK, AND SOSSET'ING. + JRST NCRUI3 + +NCRUI1: TLOA T,400000 ;ENTRY FOR RANDOM CHNLS OK (SKIP TWICE IF SO) +NCORUI: TLZ T,400000 ;RANDOM DEVS NOT OK + TLZ T,200000 +NCRUI3: TRZE J,400000 + HRLI J,-1 + JUMPL J,NCORU1 + CAIL J,NIOCHN ;>0 => CHNL NUM. + JRST OPNL14 + ADDI J,IOCHNM(U) + MOVE H,(J) + HLRZ J,H + SKIPGE H,CLSTB(H) + JRST NCORU4 ;IF INFERIOR, CAN WRITE. + TLNE H,%CLSBJ ;OR IF BOJ DEVICE + JRST [HRRZ J,JBCUI(J) ? JRST NCORU4] + TLNE H,%CLSST ;STY => USE JOB THAT HAS ASSOCIATED TTY. + JRST [ SKIPGE J,TTYSTS(J) + JRST OPNL41 ;NO JOB HAS THAT TTY. + ANDI J,-1 + JRST NCORU4] + TLNE H,%CLSFU ;FOREIGN USR, MUST CHECK. + AOJA T,NCORU4 +IFN PDP6P,[ + TLNN H,%CLS6 + JRST NCORU5 ;RANDOM DEVICE. (MAYBE DISK) +NCRUI6: MOVEI J,-1 ;PDP6, MUST CHECK. + JRST 1(T) +];PDP6P +NCORU5: JUMPL T,2(T) ;RANDOM DEVICE, SKIP TWICE IF THATS OK + JRST OPNL34 + +NCORU1: TRNE J,777400 ;CHECK FOR -1 FOR SELF. + JRST NCORU2 + ANDI J,377 + CAIN J,377 ;CHECK FOR 377 => SUPERIOR. + JRST NCORU3 +IFN PDP6P,[ ;AND FOR 376 => PDP6. + CAIN J,376 + JRST NCRUI6 +] + IMULI J,LUBLK ;ELSE WAS USRNUM, + CAMGE J,USRHI ;CHECK FOR VALID USER + SKIPN UNAME(J) + JRST OPNL35 ;IF NOT, NO SUCH JOB. + AOJA T,NCORU4 + +NCORU2: CAME J,[-1,,377777] + JRST OPNL33 + MOVEI J,(U) +NCORU4: CONO PI,CLKOFF + MOVE H,APRC(J) ;IS THE JOB WE'RE HACKING DIEING? + TLNE H,BULGOS + JRST OPNL42 ;YES, PREVENT TIMING ERRORS. + TLNE T,200000 ;UNLESS ENTRY POINT WAS NCRUI2, + JRST NCORU6 + AOS DIELOK(J) ;PREVENT THE JOB FROM DIEING. + PUSH P,T + PUSHJ P,SOSSET + DIELOK(J) + POP P,T +NCORU6: CONO PI,CLKON + JRST (T) + +NCORU3: SKIPGE J,SUPPRO(U) ;GET SUPERIOR, + JRST OPNL35 + MOVEI J,(J) + AOJA T,NCORU4 + +;SKIP IF ALLOWED WRITE ACCESS TO PAGES FROM SOURCE IN J +;USE IF NCORUI ETC. SKIPS ONCE. CALL BY JSP T,. + +NCORW1: +IFN PDP6P,[ + CAIN J,-1 ;IF IT GETS THIS FAR, USER HAS A PDP6 CHANNEL, + JRST 1(T) ; THEREFORE OBVIOUSLY IS ALLOWED TO WRITE PDP6 MEMORY. +];PDP6P + CAIE J,LUBLK ;CAN GET WRITE ACCESS TO FRESH PAGE, +;SKIP IF ALLOWED TO MODIFY PAGE MAP OF TARGET JOB IN J. +NCORWR: CAIN J,(U) ;CAN DO THAT AND STICK PAGE IN SELF + JRST 1(T) + HRRZ H,SUPPRO(J) + CAIE U,(H) ;AND OUR INFERIORS + CAMN U,SERVER(J) ; and anyone who thinks we are a server + JRST 1(T) + SKIPL H,JBI(U) ;AND OUR BOJ DEVICE. + CAIE J,JBCUI(H) + JRST (T) + JRST 1(T) + +;.CBLK AC, +;(OBSOLESCENT) + ;AC 4.9 MUST BE ZERO + ;4.7 USED INTERNALLY IN CODE (W RQ ON PDP6) + ;4.3-4.1 = 0 GET PAGE FROM SELF + ; = 1 GET ABSOLUTE PAGE + ; = 2 GET PAGE FROM USER OPEN ON CH # 3.1-3.8 + ; = 3 GET PAGE FROM USER NUMBER 3.1-3.8 + ; = 4 GET PAGE + ; = 5 GET PAGE (PUBLIC) + ; = 6 MAKE PAGE PRIVATE + ; = 7 MAKE PAGE PUBLIC + ;3.9=1 REQUEST WRITE PERMISSION (IGNORED ON FRESH PAGE, OTHERWISE VALID ONLY FOR + ; SELF OR DIRECT INFERIOR OPEN ON CH OR PUBLIC PAGE) + ;3.1-3.8 USER NUMBER OR CH # (377 => CREATOR IF JOB DEVICE) + ;2.9=1 INSERT PAGE, 0 DELETE (IGNORES 4.3-4.1 EXCEPT FOR 6 OR 7 WHEN IT IS IGNORED) + ;2.1-2.8 VIRTUAL PAGE TO BE AFFECTED + ;1.1-1.9 BLOCK # IN ABSOLUTE OR OTHER USER (OR SELF IF 4.3-4.1 = 0) + +;TO CALL NCBLK, SET UP Q WITH USER INDEX REQUEST IS FOR AND U WITH +;THE USER INDEX MAKING THE REQUEST + +;NEW .CBLK CODE, PASSES THE BUCK TO CORBLK. +;SAME AS FAR AS CALLER IS CONCERNED. + +ACBLK: MOVE TT,U ;TARGET USR IDX. + UMOVE B,(J) +NCBLK0: MOVEI W,5 ;FAKE 5 ARGS TO NCORBL + LDB C,[111000,,B] ;TARGET PAGNUM. + LDB E,[1100,,B] ;SOURCE PAGNUM. + TRNN B,400000 + JRST NCBLKD ;LIKELY TO BE DELETE RQ. +NCBLK1: MOVSI A,210000 ;NOT DELETE => RQ READ, FAIL IF CAN'T. + LDB D,[221000,,B] ;SOURCE USR IDX OR CHNL NUM. + LDB H,[330300,,B] ;REQUEST TYPE-CODE. + JRST .+1(H) + + JRST NCBLKS ;TYPE 0, SOURCE IS SELF. + JRST NCBLKA ;TYPE 1, GET ABS PAGE. + JRST NCBLKC ;2, USE SPEC'D CHNL NUM. + JRST NCBLKI ;3, USE SPEC'D USR IDX. + JRST NCBLKF ;4, FRESH PAGE. + JRST NCBLKP ;5, FRESH PUBLIC PAGE. + TLOA A,420000 ;6, MAKE PRIVATE, SOURCE=TARGET. + TLO A,440000 ;7, MAKE PUBLIC, " " + MOVE E,C ;SOURCE PAGNUM _ TARGET PAGNUM, +NCBLKS: TROA D,-1 ;GET PAGE FROM SELF. (%JSELF=-1) +NCBLKA: MOVEI D,%JSABS ;GET ABS PAGE +;IF GET-FROM-CHANNEL, THE CHNL NUM IN D IS DESIRED JOB-SPEC. +NCBLKC: TLNE B,400 ;IF WRITE-RQ BIT ON, + TLO A,100000 ;INSIST ON WRITE ACCESS. +NCORBX: CAIE TT,(U) ;IF TARGET .NE. SELF, + PUSHJ P,NULSET ;FAKE OUT THOSE EXPECTING A LOSSET. + JRST NCORB9 + +NCBLKI: IORI D,%JSNUM ;GET FROM USR IDX, MAKE JOB SPEC. + JRST NCBLKC + +NCBLKP: TLO A,40000 ;GET FRESH PUBLIC PAGE. +NCBLKF: MOVEI D,%JSNEW ;GET FRESH PAGE + JRST NCBLKC + +NCBLKD: TLC B,6000 ;COME HERE IF BIT 2.9 IS 0 + TLCN B,6000 + JRST NCBLK1 ;(TYPES 6,7 IGNORE THAT BIT) + SETZB A,B ;OTHERWISE IS DELETE REQUEST. + JRST NCBLKS + +NCBLK: MOVE B,TT + MOVE TT,Q + JRST NCBLK0 + +;ACTUALLY COPY A PAGE FROM ONE MAP TO ANOTHER +;T PNTR TO MAP COPYING FROM +;TT 400000 BIT 1=> WRITE +;E TARGET PAGE # +;U TARGET USER +;B PNTR TO CIRC LIST + +NCORR1: LDB J,T ;ENTRY FROM NCORR + TRNN J,600000 + JRST ACBK3A ;PAGE NON EXISTANT OR SWAPPED OUT + TRNN TT,400000 ;WRITE RQ ? + TRZ J,400000 ;DOESN'T RQ MORE + TRNN J,600000 + TRO J,200000 ;IN CASE OF RWF +ACBK3B: MOVE A,E ;TARGET PAGE # + PUSHJ P,UPLC + LDB C,T ;GET PTW ABOUT TO BE CLOBBERED + TRZ C,PMAGEM ;TURN OFF AGE BITS + JUMPN C,[JRST 4,.] ;SHOULD HAVE DELETED PAGE BY NOW + DPB J,T ;SET UP MAP + TRNN J,600000 + JRST ACBK3C ;JUMP IF PAGE SWAPPED OUT + ANDI J,PMRCM + CAIL J,TSYSM + JRST 4,. +IFE SWPWSP, AOS MMSWP(J) ;AOS NUMBER OF USERS POINTING TO PAGE +IFN SWPWSP,[ + HRRZ TT,MMSWP(J) + AOS MMSWP(J) ;AOS NUMBER OF USERS POINTING TO PAGE + MOVSI C,1 ;ADJUST WORKING SET OF TARGET JOB + IDIV C,TT ;1,,0 IF DIVISION BY ZERO + ADDM C,UWRKST(U) + JUMPE TT,ACBK3D ;JUMP IF NO SHARERS + IMULI TT,1(TT) ;COMPUTE ADJUSTMENT TO ALL WORKING SETS + MOVSI C,-1 ;DUE TO INCREASE IN SHARING + IDIV C,TT + MOVE D,C + PUSH P,U + PUSH P,I + PUSHJ P,UCPRL7 ;CLOBBERS C,H,I,U + 400000,,SWOP6B + POP P,I + POP P,U +];SWPWSP +ACBK3D: LDB J,B ;POINTER TO PREVIOUS IN CHAIN + DPB J,Q ;PATCH + MOVE C,U + IDIVI C,LUBLK + DPB C,[101000,,A] + DPB A,B ;PATCH + AOS NMPGS(U) + AOS SNMPGS ;SYSTEM HAS 1 MORE PAGE + POPJ P, + +ACBK3A: TRNN TT,400000 + TRZ J,2 + TRO J,1 ;IN CASE OF R/W/F + JRST ACBK3B + +ACBK3C: AOS NSWPGS(U) + AOS SNSWPG + JRST ACBK3D + ACRF1: MOVE TT,B + MOVE W,Q ;INDEX OF USER THAT REQUEST IS FOR + IDIVI W,LUBLK ;CLOBBERS H + HRL TT,W + TLNE TT,600000 + JRST 4,. + JRST ACRFL + +NACRFL: PUSHJ P,LSWPOP ;UNLOCK CASW OR CIRPSW +ACRFL: PCLT + SKIPL CORRQ(U) ;CURRENT USER IN U COR RQ FOR USER IN Q + PUSHJ P,UFLS ;WAIT FOR MY CORE RQ TO CORE JOB TO CLEAR + MOVSI J,BUSRCR + MOVE T,J + TDNE T,APRC(Q) + PUSHJ P,UFLS ;SOMEBODY ELSE HAS RQ IN ON THIS JOB WAIT TO CLEAR + PUSHJ P,SWTL + CASW ;GET CORE ASSIGN SW + TDNE J,APRC(Q) + JRST NACRFL ;CHECK FOR TIMING ERROR + TLNN TT,200000 + JRST ACRF6 ;OLD TYPE + MOVNI J,1 ;ADDING ONE BLOCK + MOVEI B,105 ;FAKE OUT CORE TO ZERO CHECK + JRST ACRF8 + +ACRF6: MOVE J,HUSRAD(Q) + LSH J,-10. + CAMN J,B + JRST LSWPJ1 ;SAME AMOUNT AS NOW + MOVE T,APRC(Q) + TLNE T,BULGOS + JUMPN B,LSWPOP ;TRYING TO CORE NON-ZERO A JOB THAT IS DYING? + SUB J,B ;GET AMT OF DECREASE (- => INCREASE) + CAMGE J,[-20.] + JRST ACRF6A ;GET 20 AT A WHACK MAX +ACRF8: MOVN I,J ;I GETS POSITIVE # OF PAGES ADDED + ADD J,MEMFR + SUB J,NCBCOM ;J GETS AMT THAT WILL BE LEFT + CAIGE J,5 + JUMPG I,ACRF7 ;NOT ENUF CORE + MOVEI J,0 ;INDICATE RQ WILL BE COMPLETELY SATISFIED + CAIL I,20. + MOVNI J,1 ;MAKE SURE RQ IS REALLY FILLED +ACRF5: JUMPL I,ACRF2 ;JUMP IF DECREASING CORE + JUMPE Q,ACRF3 ;SYSTEM JOB DOESN'T USE MMP + MOVN T,I + ADDB T,MMPFR ;COMMIT SUFFICIENT NUMBER OF MMP ENTRIES + JUMPGE T,ACRF3 ;JUMP IF THAT MANY ARE AVAILABLE + ADDM I,MMPFR ;MMP FULL, DECOMMIT THE MMP ENTRIES + JRST LSWPOP ;AND TAKE ERROR RETURN + +ACRF2: AOSA NCRQL ;COUNT # REQUESTS FOR LESS +ACRF3: ADDM I,NCBCOM ;IF EXPANDING, COMMIT SUFFICIENT AMOUNT OF PHYSICAL CORE + MOVSI T,BUSRCR + IORM T,APRC(Q) ;CORING USER + MOVEM TT,CORRQ(U) + AOS NCORRQ + PUSHJ P,LSWPOP ;UNLOCK +IFN SCHBLN,[ + CONO PI,CLKOFF ;GET CORE JOB TO RUN RIGHT AWAY + MOVE I,USER ;THEN COME RIGHT BACK TO US (WHAT A CROCK THIS ALL IS) + PUSHJ P,SCHSB + MOVEI I,LUBLK + PUSHJ P,SCHSB + CONO PI,CLKON +];SCHBLN + PCLT + SKIPL CORRQ(U) ;WILL NOT SKIP AT FIRST + PUSHJ P,UFLS + JUMPN J,ACRF1 ;REALLY NEED TO TAKE ANOTHER WACK AT THIS + JRST POPJ1 + +ACRF7: PUSHJ P,LSWPOP + PCLT + MOVE T,I + PUSHJ P,CFHPO3 + PUSHJ P,UFLS + TLNE TT,200000 + JRST ACRFL + JRST ACRF1 + +ACRF6A: ADDI J,20. + ADD TT,J ;GET REDUCED RQ + MOVNI J,20. + JRST ACRF8 + +SUBTTL CORE ALLOCATOR - CORE JOB ROUTINES + +CORJI: MOVE P,USRPDL+L ;SET UP CORE JOB PDL + JRST CORJOB + +CORJ2: AOSN UTBFLF + JRST UTBFF ;FLUSH UTAPE + AOSN UFDFLF + JRST UFDFF ;FLUSH 2314 UFDS + SKIPE MMPFS2 + JRST RETMM2 ;FLUSH PARTIALLY-RETURNED MMP ENTRIES + SKIPE QFBTS + JRST [ PUSHJ P,QDLFBT ;RETURN DISK BLOCKS TO FREE + SOS NCORRQ + JRST CORJOB ] + SKIPE NCRQL + JRST CORJOB ;RQ'S FOR LESS HAVE COME IN. BETTER EXECUTE THEM OR MAY NOT HAVE ENUF CORE + SKIPL CORUPU + JRST CORUP ;FOUND USER IN SEARCH WHO WANTS MORE GIVE IT TO HIM + SKIPL CORSRV + JRST CORJOB + MOVE A,LMEMFR + CAMGE A,MINCOR + PUSHJ P,CFLM1 ;FREE SOME LOW MEMORY BY SHUFFLING + SKIPLE NCORRQ + SOS NCORRQ ;CAN'T FIND ANYTHING TO DO SO DECREMENT COUNT + ;THIS CAN HAPPEN AS A RESULT OF EXCESS ATTEMPTED UTAPE FLUSHAGE + ;OR DUE TO CALLING CFLM1 +CORJOB: PUSHJ P,ACMTC ;XFER ANY "SPECIAL FREE" MEM BLOCKS TO FREE + SKIPN NCORRQ ;ANYONE WANT CORE? + PUSHJ P,[ ;IF NOT, WAIT UNTIL SOMEONE DOES, BUT FIRST + MOVE TT,QMDRO ;SEE IF MFD AND TUTS NEED TO BE READ IN + AOJE TT,IDSK + JRST UFLS ] ;WAIT + SETOM CORSRV ;INITIALIZE NO RQS SERVED THIS PASS + SETOM CORUPU + MOVNI U,LUBLK ;SCAN FOR USER WITH HIGHEST PRIORITY +CORLUP: ADDI U,LUBLK + CAML U,USRHI + JRST CORJ2 ;THRU EXAMINE RESULTS OF SEARCH + SKIPGE B,CORRQ(U) + JRST CORLUP + TLNE B,200000 + JRST CORNEW + LDB Q,[221000,,B] + IMULI Q,LUBLK + MOVE A,HUSRAD(Q) + LSH A,-10. ;COMPUTE # BLKS JOB HAS NOW + CAIN A,(B) + JRST 4,CORL1 ;SAME AS NOW, CHECKED FOR AT ACORE + CAIG A,(B) + JRST CORLUG ;INCREASE + MOVEM U,CORUPU ;DECREASE HAS PRIORITY + HRRZS B + SUB B,A + MOVEM A,CORUPS + MOVEM B,CORUPA ;DIFFERENCE + MOVEM Q,CORUUC + JRST CORUP + +CUSTOP: PUSHJ P,RPCLSR ;STOP USER WHO IS BEING CORED + MOVSI T,BUCSTP ;(THE BUCK STOPS HERE) + IORM T,USTP(A) + PUSHJ P,UPCLSR + MOVEI T,-1 ;GET MASK FOR RH + TDNE T,USTP(A) ;WAIT FOR RANDOM STOPS TO CLEAR + PUSHJ P,UFLS + POPJ P, + +;Core job initializes disks while system job stands around and supervises +;This makes it possible for system job to print any resulting error messages +;Provided no one hits ^Z too soon +IDSK: MOVE I,MDSK + MOVE U,USER + PUSHJ P,QMCH1 + MOVSI I,-NQS + SKIPL QACT(I) + PUSHJ P,QTCH1 + AOBJN I,.-2 + MOVSI TT,SCLIDK ;System is up now + IORM TT,SUPCOR + JRST CORJI + +EBLK + +CORUPU: -1 ;BEST USER SO FAR TO CHANGE CORE + ;IF SETOMED AT CORUPR, REQUEST NOT COMPLETELY FILLED +CORUPA: 0 ;INCREASE AMOUNT(1 FOR .CBLK) +CORUPS: 0 ;CURRENT SIZE +CORUUC: 0 ;USER CORE REQ ACTUALLY FOR +CORSRV: -1 ;0 => RQ SRVED THIS TIME THRU USER VARS +NCRQL: 0 ;# RQS FOR LESS + +BBLK + +CORLUG: HRRZS B ;GUY WANTS MORE GIVE GUY WHO WANTS LEAST PRIORITY + SUB B,A +CORLUH: MOVE A,NMPGS(Q) + SKIPGE CORUPU + JRST CORLG1 ;FIRST + CAMGE B,CORUPA ;IS RQ SMALLER? + JRST CORLG1 +CORLG2: CAME B,CORUPA ;OR IF TIE GIVE IT TO GUY WHO IS SMALLER NOW + JRST CORG1A + CAML A,CORUPS ;IS RQ= & SIZE SMALLER? + JRST CORG1A +CORLG1: MOVEM U,CORUPU ;HIGHEST PRIORITY SO FAR + MOVEM B,CORUPA + MOVEM A,CORUPS + MOVEM Q,CORUUC +CORG1A: JRST CORLUP + +CORNEW: LDB Q,[1100,,B] ;.CBLK TYPE RQ + IMULI Q,LUBLK + MOVEI B,1 + JRST CORLUH + +CORUP: ;EXECUTE REQUEST + MOVE U,CORUUC + MOVEM U,CUSER + SKIPL D,CORUPU + SKIPN UNAME(U) + JRST 4,. + MOVE A,CORUUC + JUMPE A,CORUP8 ;DONT USTOP SYS JOB + PUSHJ P,CUSTOP ;STOP GUY +CORUP8: PUSHJ P,SWTL + CIRPSW + MOVE TT,CORRQ(D) + TLNE TT,200000 + JRST CORUPN ;.CBLK TYPE + MOVE B,CORUPS + MOVE A,B ;A HAS CURRENT SIZE + ADD B,CORUPA ;B HAS NEW SIZE + PUSHJ P,SWTL + MEMFRZ + SKIPL J,CORUPA + JRST CORM1C ;WANTS MORE THAN NOW +CORL2: LDB A,[121100,,HUSRAD(U)] + CAMG A,B + JRST CORUPR + SOS A + PUSH P,B + PUSHJ P,UPGRTN ;RETURN USER PG + POP P,B + JRST CORL2 + +CORUPR: MOVE U,CUSER ;FINISHED FOR NOW ANYWAY REVIVE USER + SKIPN UNAME(U) + JRST 4,. +IFN E.SP,[ + CAMN U,DISUSR + PUSHJ P,E.SLPM ;LOAD PAGE MAP +] +IFN 340P,[ + CAMN U,DISUSR + PUSHJ P,DCRRST ;DIS IS RUNNING BUT UPDATE UPR ETC +] + MOVSI A,BUCSTP + ANDCAM A,USTP(U) ;RESTART USER + PUSHJ P,LSWPOP ;UNLOCK MEMORY + PUSHJ P,LSWPOP + PUSHJ P,ACMTC ;XFER IN PROCESS BLOCKS TO FREE + SKIPGE U,CORUPU + JRST CORJOB ;NOT THRU WITH THIS RQ + MOVE A,CORUUC ;THRU WITH RQ + SETOM CORUPU + SKIPGE CORUPA + SOS NCRQL ;FINISHED A REQUEST FOR LESS, DECREMENT COUNT OF THEM + MOVSI TT,BUSRCR + ANDCAM TT,APRC(A) ;CLEAR RQ PENDING THIS USER FLAG +CORL1: SETOM CORRQ(U) + CLEARM CORSRV + SOSE NCORRQ + JRST CORLUP + JRST CORJOB + +CORUPN: LDB A,[111000,,TT] + PUSHJ P,SWTL + MEMFRZ + PUSH P,A + PUSHJ P,UPGRTN + POP P,E + TLNE TT,4000 + TRNN TT,400000 + JRST 4,. + TLO E,600000+PMCSHM ;ADD FRESH PAGE + PUSH P,TT + PUSHJ P,CORGP + POP P,TT + LDB A,[111000,,TT] + PUSHJ P,UPLC + LDB B,T + TRNN B,400000 + JRST 4,. ;LOSEY + MOVE C,Q + PUSHJ P,UCPRL + 200000,,[ LDB B,[330100,,TT] + DPB B,[430100,,(C)] + POPJ P, ] ;SET TO DESIRED PUBLICNESS + SOS NCBCOM + JRST CORUPR + +CORM1C: MOVEM J,CORCNT +CORM1A: JUMPE U,CORS2 ;SNIFFLE +CORM1B: MOVE U,CORUUC + LDB E,[121100,,HUSRAD(U)] + TLO E,600000+PMCSHM + PUSHJ P,CORGP + SOS NCBCOM + SOSLE CORCNT + JRST CORM1A + JRST CORUPR + + ;INSERT FRESH PAGE INTO USR MEM IN PLACE SPECIFIED BY E PROT BITS IN LH +;MMPFR SHOULD HAVE BEEN SOS'ED ALREADY + +CORGP: JUMPN U,CORGP0 ;JUMP UNLESS GIVING PAGE TO SYS JOB + MOVE A,SJSPG ;GOBBLE PAGE RESERVED + SETZM MEMBLT(A) + CAIL A,SYSB + JRST CORGP1 ;USER VARIABLES, CLEAR IT OUT + JRST CORGP2 ;INITIAL GET OF SYSTEM, DON'T ZERO IT + +CORGP0: PUSHJ P,GMMPP ;RETN MMP PNTR IN R + JRST CORGPZ + PUSHJ P,TCALL + JRST HMEMRQ ;GET MEM, HIGH IF POSSIBLE + JRST 4,. +CORGP1: PUSHJ P,CZRR +CORGP2: AOS NMPGS(U) + AOS SNMPGS ;INCR SYS PAGE COUNT (VIRT) + PUSH P,A ;REAL CORE BLOCK # + HRRZ A,E ;ADDR IN USERS MAP + PUSHJ P,UPLC + POP P,A + LDB B,Q + SETZM MMSWP(A) + JUMPE U,CORGP3 ;IF SYS JOB, DON'T TRY TO SET UP MAP + JUMPN B,[JRST 4,.] ;ALREADY HAS PAGE + AOS MMSWP(A) ;INDICATE THAT ONE USER MAP POINTS AT THIS PAGE + TSO A,E ;SET PROTECTION BITS + DPB A,T ;STORE IN USER'S MAP + MOVE C,R ;MMP IDX + TRO R,400000 ;MAKE USERS CP POINT AT MMP + DPB R,Q +IFN SWPWSP,[ + MOVSI TT,1 ;INCREASE WORKING SET + ADDM TT,UWRKST(U) +];SWPWSP + ANDI A,PMRCM ;TURN ACCESS BITS BACK OFF +CORGP3: CAIL A,TSYSM + JRST 4,. + MOVEI TT,MURUSR + DPB TT,[MUR,,MEMBLT(A)] ;SET USER FIELD IN MEMBLT + MOVE TT,U + IDIVI TT,LUBLK + LSH TT,8 + IOR TT,E ;PG # IN USER'S MAP + SKIPN U + MOVEI TT,600000(A) ;IF SYS JOB, MEM BLOCK POINTS AT SELF + HRRZM TT,MEMPNT(A) ;ELSE MAKE MEM BLOCK POINT AT USERS MAP + JUMPE U,GHUSRA ;IF SYS JOB, NO MMP ENTRY + DPB C,[MMMPX,,MEMBLT(A)];STORE INDEX OF MMP ENTRY IN MEMBLT + TRO A,600000 + HRRM A,MMP(C) ;MAKE MMP POINT AT MEM BLOCK + PUSHJ P,CHACK ;FOR CHECKING ONLY + CAME C,[SETZ 3] ;REAL MEM, 3 ENTRIES (MMP, MEMPNT, USER) + JRST 4,. +GHUSRA: AOS E + LSH E,10. ;COMP NEW HUSRAD AFTER GETTING PAGE + TLZ E,-2 ;FLUSH PROTECT BITS (LEAVE 3.1) + CAMLE E,HUSRAD(U) + MOVEM E,HUSRAD(U) + POPJ P, + +CORGPZ: PUSH P,E ;SAVE REGISTERS + PUSH P,U + PUSHJ P,CFLM2 ;TRY TO FREE UP SOME LOW MEMORY + POP P,U + POP P,E + SKIPE LMEMFR + JRST CORGP ;SHOULD WORK NOW + PUSHJ P,LSWPOP ;MEMFRZ + PUSHJ P,LSWPOP ;CIRPSW + BUG INFO,[NO CORE AVAIL FOR MMP PAGE] + PUSHJ P,UDELAY ;Break possible infinite loop if no user pgs in low mem + SKIPG MEMFR ;WAIT FOR SWAPPER TO MAKE ROOM (PANIC!) + PUSHJ P,UFLS + PUSHJ P,SWTL + CIRPSW + PUSHJ P,SWTL + MEMFRZ + JRST CORGP + +PAGERT: PUSHJ P,SWTL + MEMFRZ + PUSHJ P,UPGRTN + JRST LSWPOP + +UPGRTN: PUSH P,R ;RETURN VIRT PG # IN A USER IN U + PUSH P,I + PUSH P,TT + PUSH P,E +IFN XGP,[ + PUSHJ P,UPLC ;SEE IF PAGE XGP LOCKED + LDB E,T + TRNN E,600000 + JRST UPGRT7 ;SWAPPED OUT, OBVIOUSLY NOT XGP + ANDI E,PMRCM ;E := PHYS PAGE NO + CAIL E,TSYSM + JRST UPGRT7 + IDIVI E,36. + MOVNS TT + PUSH P,T + MOVSI T,400000 + LSH T,(TT) + TDNE T,XGPMTB(E) + PUSHJ P,UFLS ;WAIT FOR XGP TO CLEAR + POP P,T +UPGRT7: ] +.ELSE PUSHJ P,UPLC ;FIND PAGE IF DIDN'T ALREADY + JUMPE U,UPGRT8 ;SYS JOB, NO SWAPPING NOR MMP ENTRY + LDB B,Q + CAIN B,-1 + JRST UPRABS ;ABSOLUTE PAGE + JUMPE B,RHUSRA ;DOESNT REALLY HAVE PG + PUSH P,T + PUSHJ P,CHACK + ADD D,MMPEAD ;D HAS MMP ADDRESS +UPGRTA: MOVSI T,MMPTMP + TDNE T,(D) + JRST UPGRTW ;WAIT FOR PAGE TO TRANSIT BUT UNLOCK SWITCHES + MOVNI I,1 ;ASSUME NO DISK SPACE + HLRZ A,1(D) ;SEE IF DISK SPACE ASSIGNED + JUMPE A,UPGRT5 + LDB I,[$MMPUN,,(D)] + PUSHJ P,QTLOCK ;LOCK APPRO TUT +UPGRT5: POP P,T ;POINTER TO ORIG MAP ENTRY OF USER + MOVE H,(T) ;SAVE MAP WORD FOR DEBUGGING + LDB TT,T ;IF PROT BITS=0 PAGE IS SWAPPED OUT FOR PURPOSES + MOVEI E,0 ;OF USER'S SWAP OUT COUNT, EVEN IF IN CORE + DPB E,T ;CLEAR USER MAP ENTRY + TRCN TT,600000 ;IS USER MAPPED TO PAGE? + JRST UPGRT9 + MOVSI E,MMPWRT ;YES, CHECK IF ACCESS BITS = RW + TRNN TT,600000 + IORM E,(D) ;PAGE WRITTEN BY USER WHO HAS DETACHED IT + ANDI TT,PMRCM ;MASK TO MEM PAGE # + CAIE TT,(J) + JRST 4,. ;PTW POINTED TO WRONG PAGE + MOVSI E,MMPOUT+MMPTMP + TDNE E,(D) + JRST 4,. ;PAGE NOT IN, IN MMP +IFE SWPWSP, SOS MMSWP(J) ;ONE LESS USER POINTING AT PAGE +IFN SWPWSP,[ + HRRZ E,MMSWP(TT) ;DECREASE THIS USER'S WORKING SET + MOVSI T,-1 + IDIVM T,E + ADDM E,UWRKST(U) + SOS MMSWP(TT) + HRRZ E,MMSWP(TT) + JUMPE E,UPGRTB ;JUMP IF NO OTHER SHARERS, FOR SPEED AND NO ZERODIVIDE + PUSH P,C ;ADJUST OTHER SHARER'S WORKING SETS + PUSH P,D + PUSH P,I + PUSH P,U + IMULI E,1(E) + MOVSI D,1 + IDIV D,E + PUSHJ P,UCPRL7 ;CLOBBERS H ALSO C,T,U,I + 400000,,SWOP6F + POP P,U + POP P,I + POP P,D + POP P,C +];SWPWSP + JRST UPGRTB + +;RETURNING A PAGE TO WHICH USER IS NOT CURRENTLY MAPPED (MAY BE IN OR OUT) +UPGRT9: SOS NSWPGS(U) + SOS SNSWPG ;DECR CNT OF SWAPPED OUT FOR SYS + JUMPGE C,UPGRT4 ;NO MEM IN CP S, PAGE REALLY SWAPPED OUT +;RETURNING A PAGE WHICH IS SWAPPED IN +UPGRTB: HLRE E,MMSWP(J) ;GET # EXEC PGS POINTING TO THIS + JUMPL E,[JRST 4,.] ;<0 EXEC PAGES + JUMPE E,UPGRT4 ;NO EXEC PGS POINTING TO THIS + PUSH P,J + MOVE TT,J + MOVSI T,-NEXPGS ;LOOK FOR EXEC PGS SET UP TO PNT + MOVE E,[442200,,EXEUMP] ;TO USER PAGE FLUSHED +UPGRT3: ILDB J,E + TRZN J,600000 + JRST UPGRT2 + ANDI J,PMRCM + CAMN TT,J + JRST UPGRT1 +UPGRT2: AOBJN T,UPGRT3 +IFN E.SP,[ + MOVSI T,-1 + TDNE T,MMSWP(TT) + PUSHJ P,E.SPRT ;SEE IF E&S HAS IT +] +IFN XGP,[ + MOVSI T,-1 + TDNE T,MMSWP(TT) ;FLUSH XGP TIE DOWNS AND RETURN + PUSHJ P,XGPCFL +] + POP P,J +UPGRT4: LDB T,Q ;DELINK CIRC PNTR + DPB T,B + MOVEI T,0 + DPB T,Q ;CLOBBER CIRC P + SOS NMPGS(U) + SOS SNMPGS ;SYSTEM HAS 1 LESS PAGE + CAME C,[SETZ 3] + CAIN C,2 + JRST MMPRTN ;RETURN MMP ENTRY SINCE PAGE NO LONGER IN USE +MMPRT4: MOVE A,J + CAMN C,[SETZ 3] + JRST MMPRT5 ;FLUSH REAL MEM +MMPRT6: SKIPL I + PUSHJ P,QTULK +RHUSRA: POP P,E + POP P,TT + POP P,I + POP P,R +RHUSR1: LDB A,[121100,,HUSRAD(U)] ;COMP HUSRAD AFTER RETURNING PAGE + JUMPE A,CPOPJ + SOS A + PUSHJ P,UPLC + LDB B,Q + JUMPN B,CPOPJ ;FOUND ACTIVE PAGE + MOVNI C,2000 ;KEEP LOOKING + ADDM C,HUSRAD(U) + JRST RHUSR1 + +UPGRT8: SOS NMPGS ;RETURNING PAGE FROM SYS JOB + SOS SNMPGS + DPB A,[121100,,HUSRAD(U)] ;NORMAL METHOD OF COMPUTING HUSRAD WON'T WORK + MOVNI I,1 ;NO DISK SPACE +MMPRT5: SKIPE MMSWP(A) ;MAKE SURE NO ONE (EXEC OR USER) IS POINTING AT PAGE + JRST 4,. + PUSHJ P,CMEMR ;HAS REAL MEM, CIRC LENGTH =3 SO FLUSH MEM + JRST MMPRT6 + +UPRABS: +IFN TEN11P,[ + LDB B,T + LDB E,[.BP B] ;GET MOBY # + CAIE E,T11CPA_-18. + JRST UPRAB1 + ANDI B,377 + PUSHJ P,T11DL ;DELETE PAGE REF TO TEN11 MAP +UPRAB1:] + MOVEI B,0 + DPB B,Q + DPB B,T + JRST RHUSRA + +IFN E.SP,[ +;TT/MMSWP INDEX +E.SPRT: CAME U,DISUSR ;IS HE USING THE DISPLAY? + POPJ P, ;NO, DON'T UNTIE ANYTHING + PUSH P,H + MOVE T,TT ;FOR E.SPCH + PUSHJ P,E.SPCH ;LOOK IN E&S TABLES + SKIPA ;FOUND, INDEX IN H + JRST E.SPR2 ;NOT FOUND, DO NOTHING + MOVSI T,-1 + ADDM T,MMSWP(TT) ;SOS COUNT + SETZM DISSWP(H) ;CLEAR DISPLAY MMSWP TABLE + AOS E.SNUT ;COUNT FOR UNTIES +E.SPR2: POP P,H + POPJ P, +] +UPGRT1: MOVSI J,-1 + XCT EXPFT(T) ;MAYBE XFERR TO ROUTINE TO DO SOMETHING ABOUT THIS + JRST UPGRT6 ;NOT USER CONCERNED ABOUT (THERE HAD BETTER BE ANOTHER) + MOVEI J,0 + DPB J,E ;CLEAR OUT EXEC PAGE ENTRY + MOVE J,USER + CLRPGM (J) +UPGRT6: CONO PI,UTCON + JRST UPGRT2 + +;WAIT FOR PAGE TO TRANSIT, WITH CIRPSW FREE (IN CASE SWAP READ ERROR!) +;COME HERE WITH T/MMPTMP,, D/MMP.ENTRY.ADDR +UPGRTW: MOVE B,D +NCRMMW: MOVE U,USER + PUSHJ P,LSWCLR + PCLT + TDNE T,(B) + PUSHJ P,UFLS ;WAIT FOR ACTIVE PAGE TO SETTLE DOWN + CAIE U,LUBLK ;SKIP IF CORE JOB + JRST UUOTROLL ;AS IF PCLSR'ED OUT OF WAIT FOR PAGE & CAME BACK + SETOM CORUPU ;REQUEST FOR THIS USER NOT SATISFIED + MOVE P,USRPDL+LUBLK ;CLEAN UP AND RE INIT CORE JOB + PUSHJ P,NULSET + PUSHJ P,NULSET + JRST CORUPR + +EXPFT: +IFN 340P, REPEAT 2+N340PB, PUSHJ P,DISACR + REPEAT 2,JFCL ;CORJF, CORJT +IFN VIDP, REPEAT 2,PUSHJ P,SCNACR +IFN TEN11P, JRST 4,. ;TEN-11 CONTROL PAGE + JRST 4,. ;PAREP +IFN ECCMEM, JRST 4,. ;ECCPG +IFN XGP, REPEAT 3,JRST 4,. +IFN N11TYS, REPEAT NTTPG+NTVBP,JRST 4,. +IFN CHAOSP, IFN T11CHP, JRST 4,. + REPEAT NMMP,JRST 4,. ;MMP +IFN .-EXPFT-NEXPGS, .ERR LOSE AT EXPFT + ;CIRCULAR MEM LIST HACKER +;CALL WITH Q CONTAINING BYTE POINTER TO CIRC PNTR IN LIST TO BE HACKED +;THE BYTE POINTER MUST POINT AT A UPGCP ENTRY (RATHER THAN MEMPNT OR MMP) +;OR THIS CODE WILL LOOP FOREVER. +;RETN BYTE PNTR IN B TO GUY WHO PNTS TO THAT PNTR +;COUNT FOR ENTRIES IN C (RH) +; 4.9 C SAYS ACTUAL MEM IN LOOP +;RETN IN D MMP INDEX +;RETURN MEM PAGE IF ANY IN J +;CLOBBERS H,I,W + +CHACK: PUSH P,A + LDB J,Q ;PICK UP STARTING C. P. + SETZM C + MOVNI D,1 + MOVE B,Q +CHACK1: JUMPE B,[JRST 4,.] + AOS C + CAIE J,-1 ;SKIP ON ABS PAGE + TRNE C,776000 + JRST 4,. ;CIRC CHAIN TOO LONG? + TRZE J,400000 + JRST CHACK3 ;MEMPNT OR MMP PNTR + LDB I,[1000,,J] ;PG # + LDB H,[101100,,J] ;USER # + IMULI H,LUBLK + SKIPE UNAME(H) + CAML H,USRHI + JRST 4,. ;POINTER TO NON-EXISTENT USER + MOVEI W,UPGCP(H) + ROT I,-1 + ADDI W,(I) + HRLI W,222200 + SKIPGE I + HRLI W,2200 + CAMN W,Q + JRST CHACK2 ;FOUND ENTRY WHICH PNTS AT ORIGINAL ENTRY + LDB J,W + MOVE B,W + JRST CHACK1 ;KEEP LOOKING + +CHACK2: MOVE J,A + JUMPL D,[JRST 4,.] ;NO MMP ENTRY ? + JRST POPAJ + +CHACK3: TRZE J,200000 + JRST CHACK4 ;ACTUAL CORE + CAML J,MMPMX + JRST 4,. ;GARBAGE POINTER + MOVSI B,2200 ;MMP ENTRY + HRR B,MMPEAD + ADDI B,(J) + JUMPGE D,[JRST 4,.] ;MORE THAN 1 MMP ENTRY + MOVE D,J + LDB J,B + JRST CHACK1 + +CHACK4: TLOE C,400000 + JRST 4,. ;PAGES IS IN TWO PLACES IN CORE + CAIL J,TSYSM + JRST 4,. ;GARBAGE POINTER + MOVE A,J ;SAVE MEMBLT INDEX + MOVSI B,2200 + HRRI B,MEMPNT + ADDI B,(J) + LDB J,B + JRST CHACK1 + +;LOOK UP PAGE IN USER MAP +;USER IN U, VIR PG # IN A +;GET PNTR TO MAP HW IN T, TO CIRC IN Q + +UPLC: SKIPL A + CAIL A,400 + JRST 4,. ;BAD VIRTUAL PAGE NUMBER + PUSH P,A + MOVEI Q,UPGCP(U) + MOVEI T,UPGMP(U) + ROT A,-1 + ADDI T,(A) + HRLI T,222200 + SKIPGE A + HRLI T,2200 + ADDI Q,(A) + HLL Q,T + JRST POPAJ + +;FREE THE MMP ENTRY D POINTS AT, SOSING TUT IF DISK SPACE ASSIGNED. +;I HAS DSK #, C HAS WHAT CHACK RETURNED IN C, A HAS TRACK #. +;TUT MUST BE LOCKED ALREADY. CIRPSW AND MEMFRZ SHOULD BE LOCKED. +;EXIT TO MMPRT4 OR RHUSRA + +MMPRTN: MOVEM C,MMPRTC ;SAVE IN CASE OF BUG HALT LATER + JUMPL I,MMPRT3 ;NO DISK SPACE ASSIGNED + PUSH P,B + LDB B,[$MMPUN,,(D)] + CAME B,I + JRST 4,. ;WRITING WRONG DISK + MOVE H,D ;H SAVES POINTER TO MMP ENTRY + MOVE D,A ;D GETS DISK TRACK NUMBER + PUSHJ P,TUTPNT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] ;DETECT OVER-SOS + DPB B,D + EXCH D,H ;D GETS MMP PNTR, H GETS TUT BYTE PNTR + JUMPN B,MMPRT2 + MOVE T,QTUTO(I) + CAML A,QSWAPA(T) + AOS QSFT(I) + CAMGE A,QSWAPA(T) + AOS QSFTS(I) +MMPRT2: MOVE T,DCHBT(I) + IORM T,QTUTO(I) + MOVE A,(D) ;ELSE DELETE MMP ENTRY NOW + SKIPGE C + JUMPN B,MMPRT0 ;IF PG IS IN FILE, AND SWAPPED IN, MAYBE WRITE OUT. + TLNN A,MMPSHR + JRST MMPRT8 + HLRZ A,1(D) ;ALSO REMOVE FROM SHAREABLE PAGE TABLE + HRL A,I + IDIVI A,SHRHSL + ADDI B,SHRHSH-1 +MMPRT7: MOVE A,B + HRRZ B,1(B) + JUMPE B,[JRST 4,.] + CAME B,D + JRST MMPRT7 + HRRZ B,1(B) + HRRM B,1(A) +MMPRT8: POP P,B + JUMPL C,MMPRT3 ;WAS MEM IN LOOP SO NOT SWAPPED OUT FOR SYSTEM'S COUNT + SOS NPGSWO ;IT WAS SWAPPED OUT +MMPRT3: PUSHJ P,MMPRT1 + SOS MMPCNT ;1 LESS IN USE + AOS MMPFR ;1 MORE FREE + JRST MMPRT4 + +;FLUSHING AN MMP ENTRY FOR A PAGE SHARED WITH A FILE WHICH IS CURRENTLY IN CORE. +;WE MAY WANT THIS PAGE AGAIN, SO TRY TO KEEP IT AROUND FOR A WHILE. +;BUT IF PAGE HAS BEEN MODIFIED, IMMEDIATELY SWAP IT OUT SO FILE GETS UPDATED. + +MMPRT0: POP P,B + LDB C,H ;UN-SOS THE TUT + CAIGE C,TUTMNY ;DON'T OVER-AOS + AOS C + DPB C,H + PUSHJ P,QTULK + MOVEI C,.BM MLO + ANDCAM C,MEMBLT(J) + SKIPE C,LLOOSP ;ADD TO TAIL OF LOOSE PAGE LIST + DPB J,[MLO,,MEMBLT(C)] + MOVEM J,LLOOSP + SKIPN C + MOVEM J,FLOOSP + AOS NLOOSP + TLNN A,MMPWRT + JRST RHUSRA + PUSH P,U ;PAGE WAS MODIFIED, SWAP IT OUT RIGHT AWAY + CONO PI,CLKOFF ;CALL SWAPPER AT IMITATION CLOCK LEVEL + MOVEM J,SWOBK + MOVEM D,SWOMMP + AOS CIRPSW ;SWOP1A WILL SOS IT BEFORE RETURNING + PUSHJ P,SWOP1A ;WILL RETURN THE MMP ENTRY SINCE NO USERS ARE LINKED TO IT + JRST 4,. ;EXEC PAGES STILL POINT TO PAGE, ALTHOUGH UPGRTN FLUSHED THEM + CONO PI,CLKON + POP P,U + JRST RHUSRA + +;HERE TO RETURN AN MMP ENTRY AND SOS THE TUT, AT P.I. LEVEL +;IF TUT OR CIRPSW IS LOCKED, PUTS ON MMPFS2 AND WAKES UP CORE JOB +;OTHERWISE, CLEARS OUT AND PUTS ON MMPFS +;A -> MMP ENTRY, CLOBBERS B,D,E,I + +RETMMP: PI2SAF + LDB I,[$MMPUN,,(A)] + SKIPGE CIRPSW + SKIPGE QTUTO(I) + JRST RETMM1 ;CAN'T SET LOCKS, LET CORE JOB DO IT +RETMM0: HLRZ D,1(A) + PUSHJ P,TUTPNT ;SOS THE TUT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] + DPB B,D + JUMPN B,RETMM7 + MOVE E,QTUTO(I) ;RETURNING BLOCK TO FREE, AOS APPROPRIATE FREE COUNT + HLRZ D,1(A) + CAML D,QSWAPA(E) + AOSA QSFT(I) + AOS QSFTS(I) +RETMM7: MOVSI D,MMPSHR + TDNN D,(A) + JRST RETMM6 + HLRZ D,1(A) ;REMOVE FROM SHAREABLE PAGE HASH TABLE + HRL D,I + IDIVI D,SHRHSL + MOVEI D,SHRHSH-1(E) +RETMM5: MOVE E,D + HRRZ D,1(D) + JUMPE D,[JRST 4,.] ;NOT IN TABLE OR MIS-HASHED? + CAME D,A + JRST RETMM5 + HRRZ D,1(D) + HRRM D,1(E) +RETMM6: MOVE D,A + SOS MMPCNT + AOS MMPFR +MMPRT1: EXCH D,MMPFS ;ADD THIS ENTRY ONTO THE FRONT OF + MOVE A,MMPFS ;THE LIST OF AVAILABLE MMP ENTRIES + MOVEM D,(A) ;CLEAR LH OF FIRST WORD OF ENTRY + SETZM 1(A) ;CLEAR SECOND WORD OF ENTRY + POPJ P, + +RETMM1: MOVE D,A ;ADD THIS ENTRY TO LIST OF ONES TO HACK LATER + EXCH D,MMPFS2 + HRRM D,(A) ;ONLY CLOBBER THE CIRC PNTR, WHICH POINTS TO SELF + SKIPN D + AOS NCORRQ ;LIST WAS EMPTY, AWAKEN CORE JOB + POPJ P, + +;CORE JOB COMES HERE WHEN MMPFS2 IS NON-ZERO + +RETMM2: SOS NCORRQ + PUSHJ P,SWTL + CIRPSW + PUSHJ P,RETMM4 + PUSHJ P,LSWPOP + JRST CORJOB + +RETMM4: MOVEI A,0 ;HERE, WITH CIRPSW LOCKED, TO FINISH RETURNING MMP ENTRIES + EXCH A,MMPFS2 +RETMM3: JUMPE A,CPOPJ + LDB I,[$MMPUN,,(A)] + PUSHJ P,QTLOCK + HRRZ H,(A) + PUSHJ P,RETMM0 + PUSHJ P,QTULK + MOVE A,H + JRST RETMM3 + +;GET AN MMP ENTRY, RET. IDX IN R, ADDR IN TT. +;CLEARS BOTH WDS OF MMP ENTRY. CLOBBERS NO ACS. +;SKIPS IF SUCCESSFUL. DOESN'T SKIP IF NO LOW CORE FOR NEW MMP PAGE. +;YOU BETTER ALREADY HAVE COMMITTED THE MMP ENTRY VIA SOSGE MMPFR + +GMMPP: HRRZ TT,MMPFS + JUMPE TT,GMMP1 ;FREE LIST IS EMPTY + CAMGE TT,MMPEAD + JRST 4,. ;IDX GOT ON FREE LIST; SHOULD BE ADDR + MOVE R,TT + SUB R,MMPEAD + CLEARM 1(TT) + HRL TT,(TT) + CLEARM (TT) + HLRZM TT,MMPFS + AOS MMPCNT ;1 MORE MMP ENTRY IN USE. + JRST POPJ1 + +GMMP1: SKIPN MMPFS2 + JRST GMMP4 + PUSH P,A ;PROTECT ACS CLOBBERED BY RETMM4 + PUSH P,B + PUSH P,D + PUSH P,E + PUSH P,H + PUSH P,I + PUSH P,T + PUSHJ P,RETMM4 + POP P,T + POP P,I + POP P,H + POP P,E + POP P,D + POP P,B + POP P,A + JRST GMMPP + +GMMP4: PUSH P,A ;CREATE ANOTHER PAGE-FULL OF MMP ENTRIES + PUSH P,B + PUSH P,D + PUSHJ P,TCALL + ;JRST IOMQ ;ALLOCATE LOW CORE SO GETS DUMPED WITH CRASHES + JRST NMMRQ ;IOMQ LOSES BECAUSE WE GET CALLED WITH MEMFRZ LOCKED + ;NMMRQ ISN'T QUITE RIGHT, BECAUSE OF NCBCOM. FIX LATER. --- + JRST GMMP3 ;NO LOW CORE AVAIL NOW + MOVEI B,MUMMP + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,2000 + ADDM B,MMPMX ;INCREMENT MAX ALLOWABLE ADDR OF MMP + AOS B,MMPNP + CAILE B,NMMP + JRST 4,. ;SOMEONE DIDN'T CHECK MMPFR? + MOVEM A,MMMPG-1(B) + TRO A,600000+PMCSHM + DPB A,MMPPPP-1(B) ;PUT NEW MMP PAGE INTO EXEC MAP + MOVE D,USER + CLRPGM (D) + SOS B + LSH B,10. + HRLI B,-1000 +GMMP2: MOVEI D,MMP(B) ;PUT ALL ENTRIES IN PAGE ON THE FREE LIST + PUSHJ P,MMPRT1 + AOS B + AOBJN B,GMMP2 + POP P,D + POP P,B + POP P,A + JRST GMMPP + +GMMP3: POP P,D + POP P,B + POP P,A + POPJ P, + +;HERE IF TRANSIENT CONDITION PREVENTS GRABBING PAGE RIGHT NOW + +CORS18: MOVE T,LSWPR+LUBLK + CAIE T,MEMFRZ + JRST 4,. + PUSHJ P,LSWPOP ;MEMFRZ + PUSHJ P,UDELAY + PUSHJ P,ACMTC + PUSHJ P,SWTL + MEMFRZ + +;GROW A JOB'S CONTIGUOUS MEMORY. USED ONLY FOR SYSTEM JOB THESE DAYS. + +CORS2: +IFN XGP,[ + SKIPL XGPUSR ;AVOID EXPANDING INTO XGP PAGE. + PUSHJ P,UFLS +] + LDB J,[121100,,HUSRAD(U)] + LDB E,[MUR,,MEMBLT(J)] + CAIN E,MUFR + JRST COSFR ;FREE PAGE, TAKE IT. + CAIE E,MUINP + CAIN E,MUFRT + JRST CORS18 ;WAIT UNTIL IT STABILIZES + CAIN E,MUSWPG + JRST CORS18 ;WAIT UNTIL IT GETS WHERE IT'S GOING + CAIE E,MURUSR ;USER PAGE, SHUFFLE IT AWAY. + JRST 4,. ;SHOULDN'T HAVE TO SHUFFLE SYSTEM PAGES. + +;SHUFFLE A USER PAGE +CORS4: PUSHJ P,TCALL + JRST HMEMRQ ;GET FREE PAGE TO SHUFFLE IT INTO + JRST 4,. ;THERE OUGHT TO BE ONE + PUSHJ P,CORS5 + JRST CBMRT + +;Shuffle user page in J into page in A +;Clobbers C,D,E,H,I,Q,U,T +CORS5: MOVE D,A + SKIPGE E,MMSWP(J) + JRST 4,. ;BLOCK IS ON SWAP OUT LIST (??) + TRNN E,-1 + PUSHJ P,CORS6 ;SHUFFLING A POSSIBLY LOOSE PAGE, FIX POINTERS + SETOM DLSRCH ;CAN'T BE BEING SWAPPED OUT ETC BECAUSE SWAPOUT + PUSHJ P,UCPRL7 ;BLOCKS HAVE MUR=MU23B, AND CIRPSW IS SIEZED + SETZ CORSTU ;STOP DIRECT TO MEM DEVICES AND FIX USER MAPS + TLC C,200 ;CHANGE TO 20 BIT BYTE + DPB D,C ;RELOCATE PTR TO MEMPNT ENTRY + PUSHJ P,CMOVE1 ;MOVE CONTENTS OF BLOCK + MOVSI C,-NEXPGS + MOVE T,[442200,,EXEUMP] + PUSHJ P,CORPS1 ;FIX ANY EXEC PAGE MAP PNTRS TO THIS PAGE + PUSHJ P,UCPRL4 + SETZ DEVSTR ;RESTART DIRECT TO MEM DEVICES + SETZM DLSRCH ;MAPS ARE CONSISTENT AGAIN, LET USERS RUN + POPJ P, + +CORSTU: PUSHJ P,DEVSTP ;STOP DIRECT-TO-MEM DEVICES + MOVE A,I ;COMPUTE USER'S MAP ENTRY LOCN + PUSHJ P,UPLC + LDB C,T + TRNN C,600000 + POPJ P, ;PAGE SWAPPED IN BUT NOT YET LINKED UP + ANDI C,PMRCM + CAIE C,(J) + JRST 4,. + TLC T,2200# ;CHANGE TO ADDRESS REAL CORE ADR FIELD + DPB D,T ;RELOCATE USER'S MAP + POPJ P, + +COSFR: MOVE D,J + PUSHJ P,MEMMF +CBMRT: MOVEM J,SJSPG ;SAVE PAGE # RESERVED + JRST CORM1B + +;CORE SHUFFLER, TO KEEP LOW MEMORY FREE +CFLM1: PUSHJ P,SWTL + CIRPSW + PUSHJ P,SWTL + MEMFRZ + PUSHJ P,CFLM2 + PUSHJ P,LSWPOP ;MEMFRZ + JRST LSWPOP ;CIRPSW + +CFLM2: MOVEI J,LIOBLK ;Scan through "low" memory + SKIPE MEMHPT ;Make sure there is likely to be free high mem + JRST CFLM4 + AOS SWPOPR ;Kick swapper more than kicked already + POPJ P, ;And give up + +CFLM3: CAIN J,128. + MOVEI J,128.+NEXPGS + CAIL J,256. ;Assume USEMDM is always on (safe assumption) + POPJ P, ;All done, couldn't find anything +CFLM4: LDB A,[MUR,,MEMBLT(J)] + CAIE A,MURUSR + AOJA J,CFLM3 + PUSHJ P,TCALL + JRST HMEMRQ ;Get free page to shuffle it into + POPJ P, ;No memory free, give up for now + PUSHJ P,CORS5 ;Shuffle page into new memory + MOVE A,J ;Free old page + PUSHJ P,CMEMR + MOVE A,LMEMFR + CAMGE A,MINCOR + AOJA J,CFLM3 + POPJ P, ;Freed sufficient low pages, stop now + +;STOP DIRECT TO MEM DEVICES + +DEVSTP: +IFN VIDP,[ + CAMN U,SCNUSR ;STOP DIRECT MEM DEVICES + PUSHJ P,SCNSTC ;STOP DIRECT VIDI INPUT +] +IFN 340P\E.SP,[ + CAMN U,DISUSR ;STOP DISPLAY IF THIS GUY HAS IT + PUSHJ P,DCRSTP +] + POPJ P, + +;RESTART DIRECT TO MEM DEVICES + +DEVSTR: CLRPGM +LUBLK ;CLEAR PAGE MAP ASSOC REGS IN HARDWARE +IFN VIDP,[ + CAMN U,SCNUSR ;RESTART DIRECT MEM DEVICES + PUSHJ P,SCNRST ;RESTART DIRECT VIDI INPUT +] +IFN 340P\E.SP,[ + CAMN U,DISUSR + PUSHJ P,DCRRST ;RESTART DISPLAY +] + POPJ P, + +;HERE TO RELOCATE EXEC PAGES WHICH POINT TO PAGE IN J + +CORPS1: MOVEI I,0 +CORPS4: ILDB Q,T + TLC T,2200# ;CHANGE SIZE FIELD TO ADDRESS REAL CORE ADR + ANDI Q,PMRCM + CAME Q,J + JRST CORPS3 + AOS I ;COUNT # OF EXEC PGS POINTING TO THIS ONE + DPB D,T ;RELOCATE EXEC PG PNTR +CORPS3: TLC T,2200# ;CHANGE SIZE BACK TO 22 + AOBJN C,CORPS4 + HLRZ T,MMSWP(D) + CAMN T,I ;CHECK COUNT OF EXEC PAGES + POPJ P, ;COUNTED CORRECTLY, WIN + +IFN E.SP,[ ;SEE IF E&S CAN ACCOUNT FOR SOME PAGES + MOVSI Q,-MXDISP ;SET UP INDEX + CAMN J,DISSWP(Q) ;J/ OLD INDEX, D/ NEW + AOJA I,E.SX2 ;COUNT I IF FOUND, AND RECHECK COUNT + AOBJN Q,.-2 ;ELSE CONTINUE SEARCH + JRST 4,. ;NOT FOUND, BOMB +E.SX2: MOVEM D,DISSWP(Q) ;RELOCATE PAGE + AOS E.SREL ;# PAGES RELOCATED (FOR DEBUGGING) + CAMN T,I ;SKIP IF COUNT IS STILL BAD + POPJ P, ;E&S COUNT WAS CULPRIT -- HAPPY AGAIN +] +IFN XGP,[ + PUSH P,A + PUSH P,B + MOVE B,J + PUSHJ P,XGPBIT + TDNE A,XGPMTB(B) + AOS I + CAMN I,T + JRST POPBAJ +] + JRST 4,. ;EXEC PGS COUNT OFF + +CORS6: MOVE T,FLOOSP ;FIX POINTERS TO LOOSE PAGE BEING SHUFFLED +CORS7: SKIPN C,T + JRST CORS8 + LDB T,[MLO,,MEMBLT(C)] + CAME T,J + JRST CORS7 + DPB D,[MLO,,MEMBLT(C)] +CORS8: CAMN J,FLOOSP + MOVEM D,FLOOSP + CAMN J,LLOOSP + MOVEM D,LLOOSP + POPJ P, + +;RUN AROUND CIRC LIST STRUCTURE +;WORD AFTER CALL IS POINTER TO ROUTINE TO BE CALLED FOR EACH ITEM IN LIST ACCORDING +;TO FLAGS IN LH: 4.9 USER PAGE (U=USER,I=PG#), 4.8 MMP (T=IDX), 4.7 MEMPNT (T=PG#) +;CALLED ROUTINE MUSTN'T CLOBBER C,H; NOR U,I IF A USER PAGE; NOR T IF MEMPNT. +;RETURNS IN C BYTE POINTER TO PLACE THAT POINTS TO +;STARTING BYTE POINTER THAT WAS IN C +;ENTRIES: +; UCPRL - STARTING BYTE POINTER IN C +; UCPRL4 - STARTING CORE PAGE # IN D +; UCPRL7 - STARTING CORE PAGE # IN J +;PDL DEEPENED BY TWO PUSH'S AND TWO PUSHJ'S. +;---WARNING--- : CLOBBERS U ------- ALSO CLOBBERS H,T,I + +UCPRL7: SKIPA C,[2200,,MEMPNT(J)] +UCPRL4: MOVE C,[2200,,MEMPNT(D)] +UCPRL: MOVE H,@(P) + HRRI C,@C + TLZ C,37 + PUSH P,C + PUSH P,C + JRST UCPRL5 + +UCPRL2: CAMN C,-1(P) + JRST UCPRL6 + MOVEM C,(P) +UCPRL5: LDB T,C + JUMPE T,[JRST 4,.] + TRZE T,400000 + JRST UCPRL1 + LDB I,[1000,,T] ;PAGE # + LDB U,[101100,,T] ;USER # + IMULI U,LUBLK + CAML U,USRHI + JRST 4,. + SKIPGE H + PUSHJ P,(H) + MOVEI C,UPGCP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + JRST UCPRL2 + +UCPRL1: TRZE T,200000 + JRST UCPRL3 + CAML T,MMPMX + JRST 4,. ;MMP ADR OUT OF RANGE + MOVSI C,2200 ;MMP + HRR C,MMPEAD + ADDI C,(T) + TLNE H,200000 + PUSHJ P,(H) + JRST UCPRL2 + +UCPRL3: CAIL T,TSYSM + JRST 4,. ;MEMBLT ADR OUT OF RANGE + TLNE H,100000 ;MEMPNT + PUSHJ P,(H) + MOVE C,[2200,,MEMPNT] + ADDI C,(T) + JRST UCPRL2 + +UCPRL6: MOVE C,(P) + SUB P,[2,,2] + JRST POPJ1 + ;DISCARD IDLE DISK UFD'S. + +UFDFF: PUSHJ P,SWTL + UDRSW + MOVEI C,MEMR + PUSHJ P,QDFLS + JRST UTBFF5 + +;FLUSH "UTAPE" (200-WD) BUFFERS +;TRY TO COMPACTIFY INTO FEWER PAGES BY DELETING PAGES CONTAINING +;ONLY FREE ONES AND BY MOVING NETWORK BUFFERS AROUND. OTHER KINDS +;OF BUFFERS DON'T STAY AROUND VERY LONG AND ARE HARD TO MOVE +;WITHOUT INTRODUCING TIMING/PCLSR'ING BUGS. + +UTBFF: PUSHJ P,SWTL + MEMFRZ + MOVSI J,-TSYSM +UTBFF3: LDB R,[MUR,,MEMBLT(J)] + CAIN R,MUIOB + PUSHJ P,UTBFF2 + AOBJN J,UTBFF3 +UTBFF5: SOS NCORRQ + PUSHJ P,LSWPOP +IFN CHAOSP, PUSHJ P,CHCLN ;ALSO, CLEAN UP CHAOS NET BUFFERS +IFN INETP, PUSHJ P,PKBCLN ; Clean up network packet buffers +;SWAP OUT ALL LOOSE PAGES. THE REASON THIS IS DONE IS THAT IF THE +;SYSTEM LOAD IS LIGHT LOOSE PAGES FOR DELETED INQUIR DATA BASE FILES +;CAN STAY AROUND INDEFINITELY, TYING UP DISK SPACE. +;SWAPPING OUT LOOSE PAGES DOES NOT CAUSE ANY DISK I/O. +;SWPOPG MAY NON-SKIP RETURN IF CIRPSW OR A TUT IS LOCKED, +;IN WHICH CASE WE GIVE UP UNTIL THE NEXT 2-MINUTE CLOCK. +UTBFF6: CONO PI,CLKOFF + SKIPN A,FLOOSP ;GET A LOOSE PAGE + JRST UTBFF7 + MOVNI C,1 + PUSHJ P,SWPOPL ;SWAP OUT EVEN IF LOCKED (SHOULDN'T BE) + JRST UTBFF7 ;COULDN'T SWAP OUT, GIVE UP FOR NOW + CONO PI,CLKON ;ALLOW CHANCE FOR AN INTERRUPT + JRST UTBFF6 + +UTBFF7: CONO PI,CLKON + JRST CORJOB + +;RH(J) HAS PAGE NUMBER OF A BLOCK OF 200-WD BUFFERS +UTBFF2: LDB R,[MNUMB,,MEMBLT(J)] ;GET LIST OF IOBFT ENTRIES IN THIS BLOCK + CLEARB Q,TT +COSIO1: MOVSI E,200000 ;ALLOC INH ALL BUFFERS IN BLOCK + IORM E,IOBFT(R) + LDB E,[IOCH,,IOBFT(R)] + CAIE E,77 + AOS Q ;COUNT NUMBER USED FOR SOMETHING + CAIL E,NFNETC + CAIL E,NFNETC+NNETCH + CAIA + AOS TT ;COUNT NUMBER USED FOR NETWORK + LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST COSIO1 + JUMPE Q,COSIO3 ;IF ALL BUFFERS FREE, FLUSH THIS PAGE + CAME Q,TT + JRST UTBFF1 ;CONTAINS NON-NET BUFFERS, LEAVE ALONE + MOVEI E,0 + EXCH E,UTTBF + CAIL E,8 ;IF THERE ARE ENOUGH FREE IN OTHER BLOCKS + JRST CISHUF ;THEN GO SHUFFLE THE NET BUFFERS + EXCH E,UTTBF +UTBFF1: LDB R,[MNUMB,,MEMBLT(J)] ;ABANDON IDEA OF FLUSHING THIS BLOCK + MOVSI E,200000 ;UN-INHIBIT THE BUFFERS.. +UTBFF4: ANDCAM E,IOBFT(R) + LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST UTBFF4 + POPJ P, ;RETURN OUT OF UTBFF2 + ;SHUFFLE BUFFERS +;COME HERE WITH UTTBF SET TO 0 AND OLD VALUE IN E +;LEAVE UTTBF 0 WHILE SHUFFLING SO NO ONE ELSE CAN ALLOCATE + +CISHUF: PUSH P,E + LDB R,[MNUMB,,MEMBLT(J)] +CISHF1: LDB Q,[IOCH,,IOBFT(R)] + CAIN Q,77 + JRST CISHF2 ;FREE, IGNORE + CAIL Q,NFNETC + CAILE Q,NFNETC+NNETCH + JRST 4,. ;SOME RANDOM UNSHUFFABLE BUFFER + PUSHJ P,CINET +CISHF2: LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST CISHF1 + POP P,UTTBF ;ALLOW ALLOC AGAIN. THIS MEM BLOCK NOW + ;CONTAINS 8 FREE, ALLOC INH BUFFERS. + ;SO FALL INTO COSIO3 TO FLUSH THEM. +;FLUSH ALL 8 BUFFERS. + +COSIO3: LDB R,[MNUMB,,MEMBLT(J)] + MOVEI TT,7 +COSIO4: LDB Q,[IOCH,,IOBFT(R)] + CAIE Q,77 + JRST 4,. ;BUFFER WAS SUPPOSED TO BE FREE?? + MOVEI Q,UTFS-IOBFT ;PNTR TO F.S. LIST + SOS UTTBF ;SOON WILL BE ONE LESS FREE UTAPE BUFFER + CONO PI,UTCOFF +COSIO5: MOVE E,Q ;REMOVE IOBFT ENTRY IN R FROM F.S. LIST + LDB Q,[IOLO,,IOBFT(Q)] + CAIN Q,377 + JRST 4,. ;IT WASN'T IN THE LIST + CAME Q,R + JRST COSIO5 + + LDB Q,[IOLO,,IOBFT(R)] + DPB Q,[IOLO,,IOBFT(E)] + MOVE A,R ;GIVE IOBFT ENTRY BACK TO LIST OF UNUSED IOBFTS + LDB R,[IOLC,,IOBFT(R)] + PUSHJ P,IOBR + CONO PI,UTCON + CAIE R,377 + SOJA TT,COSIO4 + + JUMPN TT,[JRST 4,.] ;BLOCK DIDN'T CONTAIN 8 BUFFERS + MOVNI A,8 + ADDB A,UTTLB + CAMGE A,[-NUTIC-NUTOC] + JRST 4,. + PUSHJ P,FSCMP + HRRZ A,J ;THIS BLOCK OF MEMORY IS FREE NOW + JRST CMEMR ;AND RETURN OUT OF UTBFF2 + +;EXCHANGE BUFFER IN R WITH SOME FREE BUFFER, RETURNED IN A +;CALL WITH UCTOFF, CHANNEL NUMBER IN Q, TURNS UTCON + +COSIMG: MOVEI D,NFNETC(Q) ;CHNL NO TO CONS FOR + AOS UTTBF ;UNRESERVE ONE BUFFER MOMENTARILY + PUSHJ P,IUTCONS + JRST 4,. + CONO PI,UTCON + LDB TT,[IOSA1,,IOBFT(R)] ;TRANSFER BUFFER R TO BUFFER A + LDB T,[IOSA1,,IOBFT(A)] + HRL T,TT + LSH T,7 + HRRZ TT,T + BLT T,177(TT) + EXCH R,A + CONO PI,UTCOFF + PUSHJ P,IBRTN ;RETURN THE OLD BUFFER + SOS UTTBF ;BUT RESERVE IT + EXCH R,A + JRST UTCONJ + +;SHUFFLE OFF A NCP NETWORK BUFFER +;R HAS IOBFT INDEX, Q HAS CHANNEL NUMBER, E MUST BE PRESERVED + +CINET: +IFE NCPP,JRST 4,. +IFN NCPP,[ + SUBI Q,NFNETC ;GET IMSOC INDEX + HRRZ A,IMSOC1(Q) ;USER WHO OWNS THIS BUFFER + MOVSI T,200000 + TDNE T,IMSOC1(Q) ;SKIP OVER USER STOP IF BEING CLOSED + TROA A,-1 ; SINCE USER CAN'T REFERENCE BUFFER ANY MORE + PUSHJ P,RPCLSR ;AND LEAVE A=USER # STOPPED OR 0,,-1 IF NONE + MOVSI T,200000 ;MUSTN'T BE ACTIVE AT PI LEVEL + PUSHJ P,LWAIT + TDNE T,IMSOC6(Q) + SKIPN IMSOC6(Q) ;LWAIT RETURNS WITH NETOFF + JRST CINET2 ;BUFFER HAS BEEN RETURNED + MOVSI T,400000 ;LOCK THE BUFFER SO PI LEVEL WON'T TOUCH + IORM T,IMSOC6(Q) + LDB T,[221000,,IMSOC6(Q)] + CAIE T,(R) + JRST 4,. ;IOBFT ENTRY POINTS TO WRONG CHANNEL + PUSH P,A ;SAVE INDEX OF STOPPED USER + PUSHJ P,COSIMG ;COPY BUFFER + LDB TT,[IOSA,,IOBFT(A)] + LSH TT,6 + MOVE T,TT + HRRZ D,IMSOC6(Q) + SUB T,D ;OFFSET NEW BUFFER MINUS OLD + HRL TT,A + DPB TT,[003200,,IMSOC6(Q)] ;STORE NEW BUFFER ADDR, LEAVE FLAGS ALONE + ADDM T,IMSBFE(Q) ;RELOCATE VARIOUS POINTERS + ADDM T,IMSMPP(Q) + ADDM T,IMSPIP(Q) + MOVE TT,IMSOC2(Q) + TRNN TT,1 + AOSA IMNISH + AOS IMNOSH + CONO PI,NETOFF + MOVE TT,IMSOC6(Q) + TLNN TT,100000 ;SKIP IF INPUT OCCURRED WITH BUFFER LOCKED + JRST CINET1 +IFE DMI,[ + MOVE TT,IMPSVP ;RESTART INPUT + MOVEM TT,IMPPIA + CONO IMP,(TT) +] +IFN DMI,CONO FI,FIIN+NETCHN*11 +CINET1: MOVSI TT,500000 ;UNLOCK THE BUFFER, CLEAR INPUT WITH LOCK FLAG + ANDCAM TT,IMSOC6(Q) + PUSHJ P,IMPIOS ;RESTART OUTPUT + POP P,A ;AND FALL INTO CINET2 TO RESTART USER +CINET2: CONO PI,NETON + JRST NJUPCL ;RESTART USER IF ONE WAS STOPPED +] ;END IFN NCPP + +;FREE BLOCKS THAT BECAME FREE AT INT LEVEL. +ACMTC: SKIPN MEMFP1 ;ANY BLKS BECAME FREE AT INT LVL? + POPJ P, + CONO PI,UTCOFF + SKIPL MEMFRZ ;IF MEMFRZ IS LOCKED, CAN'T DO THIS. JUST + JRST UTCONJ ;HOPE ENOUGH CORE IS FREE. MUST BE BETTER WAY! + MOVE A,MEMFP1 ;GET # OF ONE OF THEM, + LDB B,[MLO,,MEMBLT(A)] ;REMOVE IT FROM LIST OF SUCH BLOCKS + HRRZM B,MEMFP1 + LDB B,[MUR,,MEMBLT(A)] + CAIE B,MUFRT + JRST 4,. + PUSHJ P,MEMR + JRST ACMTC + +;COPY A PHYSICAL PAGE'S DATA FROM PAGE (J) TO PAGE (D) +CMOVE1: MOVE C,MEMBLT(J) + MOVEM C,MEMBLT(D) + CLEARM MEMBLT(J) + MOVE C,MEMPNT(J) + MOVEM C,MEMPNT(D) + CLEARM MEMPNT(J) + MOVE C,MMSWP(J) + MOVEM C,MMSWP(D) + HRRZ A,D + CAIGE A,SYSB + JRST 4,. + TRO D,600000+PMCSHM + TRO J,600000+PMCSHM + DPB D,[.CORJT+EXEUMP] + DPB J,[.CORJF+EXEUMP] + TRZ D,600000+PMCSHM + TRZ J,600000+PMCSHM + CLRPGM +LUBLK + MOVE A,[400000+CORJF*2000,,400000+CORJT*2000] + BLT A,400000+CORJT*2000+1777 + MOVEI A,0 + DPB A,[.CORJT+EXEUMP] + DPB A,[.CORJF+EXEUMP] + POPJ P, + +MEMMF: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUFR + JRST 4,. + HRRZ A,D + PUSHJ P,TCALL + JRST MPOUT + POPJ P, + +UDELAY: PUSH P,T + MOVE T,TIME + ADDI T,15. ;SLEEP 1/2 SEC. (REALLY SHOULD DO A LOW + CAMLE T,TIME ;PRIORITY UNBLOCK IF SYS LIGHTLY LOADED) +UDELA1: PUSHJ P,UFLS + JRST POPTJ + +CZRR: PUSH P,A + CAIGE A,SYSB ;CORE ZEROER + JRST 4,. + TRO A,600000+PMCSHM + DPB A,[.CORJT+EXEUMP] + CLRPGM +LUBLK + CLEARM 400000+CORJT*2000 + MOVE A,[400000+CORJT*2000,,400000+CORJT*2000+1] + BLT A,400000+CORJT*2000+1777 + MOVEI A,0 + DPB A,[.CORJT+EXEUMP] + JRST POPAJ + +;ROUTINES TO ALLOCATE BLOCKS OF MEMORY +;CALL ONLY AT UTC LEVEL OR WITH UTC OFF + +OVHMTR ALC ;CORE ALLOCATION + +;SEE IF CAN ALLOCATE MEMORY +MQTEST: MOVE A,MEMFR + SUB A,NCBCOM + JUMPLE A,CPOPJ + SKIPLE MEMFR + SKIPL MEMFRZ + POPJ P, + JRST POPJ1 + +;ALLOCATE PREFERRING HIGH MEMORY, FOR RANDOM USER PAGE. SHUFFLEABLE PAGE OK. +HMRQC: PUSHJ P,MQTEST + POPJ P, +HMEMRQ: PUSH P,B + PUSH P,E + HRREI B,MEMHPT-MEMBLT +HMRQ3: LDB A,[MLO,,MEMBLT(B)] + JUMPE A,HMRQ1 ;HIGH HALF FULL TRY LOW + CAIL A,SYSB ;DON'T ALLOCATE PART OF THE SYSTEM + SKIPGE MEMBLT(A) ;DON'T ALLOCATE IF LOCKED + SKIPA B,A ;THIS PAGE NOT AVAIL, TRY NEXT + JRST IMRQ8 ;GOBBLE IT + JRST HMRQ3 + +HMRQ1: POP P,E + POP P,B + JRST NMMRQ ;THAT DIDNT WORK, TRY LOW HALF + +;ALLOCATE A BLOCK OF MEM FOR 200-WORD BUFFERS +UIMRQ: MOVE A,IOBFC + CAIGE A,8 + POPJ P, ;NOT ENOUGH ROOM IM IOBFT + MOVE A,MEMFR + SUB A,NCBCOM + CAIG A,3 + POPJ P, + +;GET A BLOCK THAT WON'T BE SHUFFLED, AND IS DIRECTLY ACCESSIBLE. +IOMQ: PUSHJ P,MQTEST ;GET LOW OR MEDIUM MEMORY FOR I/O + POPJ P, + +;ALLOCATING LOW MEM +NMMRQ: MOVEI A,0 ;MEMFP = MEMBLT+0 +IMRQ7: PI2SAF + PUSH P,B + PUSH P,E +IMRQ2: LDB A,[MLO,,MEMBLT(A)] + JUMPN A,IMRQ3 + PUSH P,C + PUSH P,H + PUSH P,TT + MOVEI C,IMEMR + SKIPGE UDRSW + PUSHJ P,QDFLS ;TRY FLUSHING DISK DIRS + POP P,TT + POP P,H + POP P,C + MOVEI A,0 +IMRQ6: LDB A,[MLO,,MEMBLT(A)] + JUMPE A,IMRQR ;NO MEM AVAIL IN LOW HALF, TAKE NON-SKIP RETURN + SKIPGE MEMBLT(A) + JRST IMRQ6 + JRST IMRQ9 + +MPOUT1: +IMRQR: POP P,E + JRST POPBJ + +IMRQ3: SKIPGE MEMBLT(A) + JRST IMRQ2 ;LOCKED LOOK FOR ANOTHER +IMRQ9: TDZA B,B ;GOBBLE FROM LOW +IMRQ8: MOVNI B,1 ;GOBBLE FROM HIGH + AOS -2(P) ;CAUSE RETURN TO SKIP + LDB E,[MUR,,MEMBLT(A)] + CAIN E,MUFR + JUMPN A,IMRQ4 + JRST 4,. ;BLOCK GOT PUT ON FREE STORAGE LIST WITHOUT USAGE FIELD GETTING "FREE" + ;ROUTINES FOR RETURNING MEMORY +IMEMR: PI2SAF ;HERE OTHERWISE (SEE BELOW) + CAIGE A,TSYSM + CAIGE A,SYSB + JRST 4,. ;DON'T RETURN PART OF SYSTEM + SKIPL MEMFRZ + JRST IMEMR1 +CIMEMR: PUSH P,B ;ENTER HERE IF OK TO HACK WITH MEM FROZEN + LDB B,[MUR,,MEMBLT(A)] ;I E CALLING FROM CORE ALLOCATOR + CAIN B,MUFR + JRST 4,. ;ALREADY FREE, LOSSAGE + SETZM MEMBLT(A) ;INITIALIZE RANDOM FIELDS + CAIGE A,256. ;HIGH MOBY GOES ON HIGH LIST + CAIGE A,LIOBLK ;LOW SHUFFLEABLE GOES ON HIGH LIST + JRST CIMEM1 + CAIGE A,128. ;LOW NON-SHUFFLEABLE GOES ON LOW LIST + JRST CIMEM0 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES GO ON HIGH LIST + SKIPN USEMDM ;MEDIUM MEMORY GOES ON LOW OR HIGH DEPENDING ON USEMDM + JRST CIMEM1 +CIMEM0: LDB B,[MLO,,MEMFP] ;PICK UP HEAD OF APPRO FS LIST + DPB B,[MLO,,MEMBLT(A)] ;STORE AS LINK OUT OF CURRENT WD + CAIE B,0 ;SKIP IF NO BLOCK PREVIOUSLY ON LIST + DPB A,[MLU,,MEMBLT(B)] ;MAKE FORMER HEAD'S BACK PNTR POINT TO CURRENT + MOVEI B,0 ;NO BACK PTR, THIS WILL BE FIRST IN LIST + DPB B,[MLU,,MEMBLT(A)] + DPB A,[MLO,,MEMFP] ;STORE THIS AS FREE LIST HEAD + AOS LMEMFR +CIMEM3: MOVEI B,MUFR + DPB B,[MUR,,MEMBLT(A)] ;STORE FREE IN USER + CLEARM MEMPNT(A) + AOS MEMFR + JRST POPBJ + +CIMEM1: LDB B,[MLO,,MEMHPT] ;PICK UP HEAD OF APPRO FS LIST + DPB B,[MLO,,MEMBLT(A)] ;STORE AS LINK OUT OF CURRENT WD + CAIE B,0 ;SKIP IF NO BLOCK PREVIOUSLY ON LIST + DPB A,[MLU,,MEMBLT(B)] ;MAKE FORMER HEAD'S BACK PNTR POINT TO CURRENT + MOVEI B,0 ;NO BACK PTR, THIS WILL BE FIRST IN LIST + DPB B,[MLU,,MEMBLT(A)] + DPB A,[MLO,,MEMHPT] ;STORE THIS AS FREE LIST HEAD + JRST CIMEM3 + +IMEMR1: PUSH P,B ;FREE A PAGE WHEN MEMFRZ LOCKED. + MOVE B,MEMFP1 ;ADD IT TO FRONT OF MEMFP1 LIST + DPB B,[MLO,,MEMBLT(A)] + HRRZM A,MEMFP1 + MOVEI B,MUFRT ;THEN SAY THIS BLK BECAME FREE WITH MEM FROZEN. + DPB B,[MUR,,MEMBLT(A)] + SETZM MEMPNT(A) + JRST POPBJ + +;ROUTINES TO RETURN MEMORY CONTINUED + +MGMEMR: PUSHJ P,TMEMR ;MAG TAPE MEMR + MUMGB + POPJ P, + +TMEMR: PUSH P,B + LDB B,[MUR,,MEMBLT(A)] + CAME B,@-1(P) + JRST 4,. ;RETURNING BLOCK NOT OF TYPE EXPECTED + POP P,B + AOS (P) ;SKIP OVER ARG +MEMR: CONO PI,UTCOFF + PUSHJ P,IMEMR + JRST UTCONJ + +CMEMR: CONO PI,UTCOFF + PUSHJ P,CIMEMR + JRST UTCONJ + +; ROUTINES TO UNTHREAD BLOCKS FROM FREE LISTS + +MPOUT: PI2SAF +MPOUT2: JUMPE A,[JRST 4,.] ;ENTER HERE FROM INITIALIZATION IF HOLE FOUND + PUSH P,B + PUSH P,E + CAIGE A,256. ;HIGH MOBY GOES ON HIGH LIST + CAIGE A,LIOBLK ;LOW NON-SHUFFLEABLE GOES ON HIGH LIST + JRST MPOUT4 + CAIGE A,128. ;LOW SHUFFLEABLE GOES ON LOW LIST + JRST MPOUT3 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES GO ON HIGH LIST + SKIPN USEMDM ;MEDIUM MEMORY GOES ON LOW OR HIGH DEPENDING ON USEMDM +MPOUT4: SKIPA B,[-1] ;IT'S HIGH MEM +MPOUT3: MOVEI B,0 ;IT'S LOW MEM + +IMRQ4: PUSH P,B ;0 LOW -1 HIGH + LDB B,[MLU,,MEMBLT(A)] ;LINK UP + LDB E,[MLO,,MEMBLT(A)] ;LINK OUT + JUMPN B,IMRQ5 ;JUMP IF NOT FIRST IN LIST + JUMPE E,IMRQ5 ;JUMP IF LAST BLOCK IN LIST + LDB B,[MUR,,MEMBLT(E)] ;FIRST AND FOLLOWED + CAIE B,MUFR + JRST 4,. ;DOESNT LINK TO A FREE BLOCK + MOVEI B,0 ;PUT BACK 0 +IMRQ5: SKIPE E ;SKIP IF NO BLOCK FOLLOWS + DPB B,[MLU,,MEMBLT(E)] ;STORE LINK UP OF PATCHED OUT BLOCK IN LINK OUT BLOCK + JUMPE B,IMRQ5A + DPB E,[MLO,,MEMBLT(B)] ;STORE LINK OUT OF PATCHED OUT BLOCK IN LINK UP BLOCK + POP P,B ;GET BACK WHICH PART OF MEM IT'S IN + JRST IMRQ5C + +IMRQ5A: POP P,B ;GET BACK WHICH PART OF MEM IT'S IN + DPB E,[MLO,,MEMFP(B)] ;THIS WAS FIRST IN FREE LIST, ADJUST LIST HEADER +IMRQ5C: SKIPL B ;SKIP IF NOT IN LOW HALF + SOS LMEMFR ;ADJUST FREE BLOCKS IN LOWER HALF + SOS MEMFR ;1 LESS FREE BLOCK IN SYSTEM + SETZM MEMBLT(A) ;CLEAN UP MEMBLT ENTRY FOR CALLER'S SAKE + MOVEI B,MUINP ;IN PROCESS + DPB B,[MUR,,MEMBLT(A)] + JRST MPOUT1 + +OVHMTR UUO ;MORE MISC UUOS ETC. + +TCALL: CONO PI,UTCOFF + PUSHJ P,@(P) + SKIPA + AOS (P) + JRST UTCOJ1 + +EBLK + +SUBTTL MEMORY ALLOCATION TABLES + +IOBFTL: MXIOB ;BEG FOR GETSYS (MEMORY) +IOBFT: REPEAT MXIOB-1,176000,,.RPCNT+1 ;MAX DYN ALLOC IO BUFFERS + 176000,,377 ;4.9 FREEZE + ;4.8 ALLOC INHIBIT +IOCH==340600 ;4.7-4.2 SYS CHN NO 77 => FREE +IOLC==241000 ;4.1-3.3 LINK TO NEXT SEQ BUF IN CORE (W/IN 1K BLK) +IOLO==1000 ; LINK TO FOLLOWING BUFFER OR + ;SPECIAL STATES LINK OUT + ;-1 LAST BUFFER CURRENTLY FILLED + ;-2 END OF FILE + ;-3 BUFFER ACTIVE AT MAIN PROG LEVEL + ;-4 BUFFER ACTIVE AT PI LEVEL +;IF CHN IS NUTIC+NUTOC (UTAPE FILE DIR) THEN IOLO IS TAPE NO +;CHNLS NUTIC+NUTOC+1 (NFCLC)=>$Q+NCLCH-1 ARE CORE LINK DEVICE +;CHNLS NFNETC => $Q+NNETCH-1 ARE NET CHNLS +SCNCLO==NUTIC+NUTOC+1 + +IOSA==101400 ; BUFFER SA _-6 +IOSA1==111300 ;ONLY RELEVANT BITS FOR 200 WD BUFFERS + + +IOBFP: 0 ;FREE STG TO IOBFT ENT +IOBFC: MXIOB-8 ;CNT OF AVAIL + ;LEAVE 8 AVAIL SO CORE HACKER CAN NOT RUN OUT + +UTFS: 377 ;FREE STG PNTR TO 200 WD BUFFERS +UTTLB: -NUTIC-NUTOC ;TOTAL BUFFERS ALLOCATED TO UTAPES +UTTBF: 0 ;TOTAL UT BUFFERS FREE + +;EXEC MAPS +IF2,[ +EXEUMP=UPGMP+100 ;EXEC UPPER MAP LIVES IN SYSTEM JOB'S MAP AREA +EXELMP==UPGMP ;KL10 AND KS10 ALSO NEED EXEC LOWER MAP, + EXISTS +];IF2 ;SO USERS CAN COPY PAGES FROM THE SYSTEM JOB + +;TABLE OF BYTE POINTERS THAT POINT TO VIDEO BUFFER AREA OF EXEUMP +IFN N11TYS,[ +TTCRT: REPEAT NTVBP,[ + CONC [.TTR]\.RPCNT,+EXEUMP +] +] + +IFN PDP6P,[ +;DBR FOR REFERENCING PDP6 MEM +PDP6MP: _1,,PDPUMP + +;PAGE MAP FOR REFERENCING PDP6 MEM +PDPUMP: REPEAT LPDP6M/2,600000++2*.RPCNT,,600000++2*.RPCNT+1 +] + +IFN 340P,[ +DDEXCF: BLOCK NEXPGS ;-1 IF EXEC PAGE SET UP FOR 340 +] + +IFN KA10P, EXECMP: 100_1,,EXEUMP ;EXEC DBR + ;MEMORY ORGANIZATION + +;PAGE 0 ALWAYS BELONGS TO THE SYSTEM AND IS NEVER ALLOCATED OR FREED. +; +;N PAGES OF SYSTEM CODE AND VARIABLES ARE ACQUIRED BY THE SYSTEM JOB AT STARTUP. +; +;N PAGES OF USER-VARIABLE BLOCKS BELONG TO THE SYSTEM JOB. THESE ARE +;ALLOCATED AND DEALLOCATED AS REQUIRED. LIOBLK-1 IS THE HIGHEST THIS CAN GO. +;USER PAGES BELOW LIOBLK CAN BE SHUFFLED OUT WHEN THE SYSTEM JOB NEEDS THE CORE. +; +;FROM LIOBLK TO 128K IS THE "LOW HALF." THESE PAGES ARE DIRECTLY ADDRESSABLE +;IN EXEC MODE AND NEVER NEED TO BE SHUFFLED. I/O BUFFERS, DISK DIRECTORIES, +;ETC. ARE ALLOCATED IN THESE PAGES. +; +;128K TO 128K+NEXPGS ARE PAGES WHICH CAN'T BE ADDRESSED DIRECTLY FROM +;EXEC MODE BECAUSE THEIR EXEUMP SLOTS ARE USED BY "EXEC PAGES." +; +;THE REST OF THE LOW MOBY, UP TO FDDTPG, IS DIRECT-MAPPED AND +;USED FOR ADDITIONAL "LOW HALF" PAGES. +; +;FDDTPG TO 256K CONTAINS DDT AND THE SYSTEM SYMBOL TABLE. +; +;PAGES ABOVE 256K ARE IN THE "HIGH MOBY". +; +;PAGES NOT IN THE "LOW HALF" (BELOW LIOBLK, SHADOWED BY EXEC, OR HIGH MOBY) +;ARE CONSIDERED TO BE IN THE "HIGH HALF". USER PAGES PREFER TO GO HERE. +; +;COMPLICATIONS: +; IF USEMDM IS OFF, THE DIRECT MAPPED PAGES IN THE HIGH HALF +; OF THE LOW MOBY ARE CONSIDERED HIGH RATHER THAN LOW. THIS IS USED +; MOSTLY FOR DEBUGGING, TO CATCH REFERENCES TO RANDOM ADDRESSES. +; THERE CAN BE HOLES IN MEMORY (NXM). +; +;THE MEMBLT TABLE HAS ONE WORD FOR EACH 1K BLOCK OF MEMORY. +;IT SAYS WHAT THAT BLOCK IS USED FOR AND CONTAINS LINKS TO OTHER +;BLOCKS AND OTHER TABLES. THE MEMPNT AND MMSWP TABLES ALSO CONTAIN +;ONE WORD PER BLOCK AND CONTAIN ADDITIONAL INFORMATION. + +FDDTPG: 0 ;# OF LOWEST BLOCK USED BY DDT & SYMTAB (SET AT STARTUP) + +MEMFR: 0 ;# OF FREE BLOCKS IN ALL OF MEMORY. + +LMEMFR: 0 ;# OF FREE BLOCKS IN LOW LIST (MEMFP). + +MINCOR: 8 ;TRY TO KEEP THIS MANY PAGES FREE IN LOW MEMORY + ;MUST BE >= 3, SINCE LESSER-PRIORITY CONSUMERS OF + ;MEMORY WAIT IF LMEMFR IS < 3. + +MEMFP1: 0 ;LIST (THREADED THROUGH MLO, TERMINATED BY 0) + ;OF BLKS THAT BECAME FREE WHILE MEMFRZ WAS LOCKED. + +MEMHPT: 0 ;FREE LIST OF HIGH HALF PAGES AND HIGH MOBY PAGES + ;AND SHUFFLEABLE LOW HALF PAGES. MUST BE AT MEMFP-1. +MEMFP:: +MEMBLT: 0 ;FREE LIST POINTER FOR LOW PGS AND ALSO WD FOR BLOCK 0 + BLOCK TSYSM-1 .SEE BEGF0 ;FILLS THIS IN + +;FIELDS IN MEMBLT ENTRY: +;4.9 FREEZE OR ALLOC INHIBIT +;IF 4.9=1, DONT SET UP ANY MORE EXEC PGS POINTING TO THIS ONE +MUR==360500 ;4.4-4.8 USAGE CODE + MURUSR==1 ;USER PAGE, MMMPX=MMP INDEX + MUEX==2 ;EXEC (?) + MUIOB==3 ;200 WD BUFFERS, MNUMB=FIRST IOBFT ENTRY IN BLOCK + MUFR==4 ;FREE + MUINP==5 ;IN PROCESS OF BEING ALLOCATED + MUMGB==6 ;MAG TAPE BUFFER, MNUMB=TAPE NO+EOF BIT, MWC=WORD COUNT + MUMMP==7 ;MMP TABLE + MUDISB==10 ;340 DISPLAY BUFFER + MUFRT==11 ;BLOCK RETURNING TO FREE WHEN MEM LOCKED + MU23B==12 ;DISK BUF, MWC=WORD COUNT, MNUMB=CHANNEL + MU23UD==13 ;DISK USER DIR, MNUMB=QSNUD SLOT + MU23MD==14 ;DISK MASTER DIR + MU23TT==15 ;DISK TUT MNUMB=DISK NO. + MU23LS==16 ;DISK COPY OF USER DIR FOR LISTING + MUHOLE==17 ;"HOLE" IN REAL MEM + MUDDT==20 ;"DDT" PAGE + MUNET==21 ;NETWORK "BIG" BUFFER + MUSWPG==22 ;PAGE IN SWAPPING QUEUE, MMMPX=MMP INDEX + MUCHA==23 ;CHAOS NET BUFFERS + MU23FB==24 .SEE QSFBT ;DISK FREED-BLOCKS TABLES + MUPKT==25 ; Net packet buffers + MUDVB==26 ;Semi-static device IO buffer page +;ADD NEW MUR TYPES HERE ^ +MURMAX==27 ;HIGHEST VALID CODE + 1 + +MWC==221400 ;3.1-4.3 WORD COUNT IN I/O BUFFERS + +MLU==221400 ;3.1-4.3 LINK UP FOR DOUBLY-THREADED FREE LIST + +MNUMB==140600 ;2.4-2.9 MAGIC NUMBER SEE COMMENTS UNDER MUR ABOVE + +MMMPX==142200 ;2.4-4.3 MMP INDEX IN USER PGS + SWAP BUFFERS + +MLO==001400 ;1.1-2.3 LINK TO NEXT PAGE IN A LIST + ;0 = END OF LIST + ;UNLIKE IOLO AND PREVIOUS VERSION OF MLO, THERE ARE NO MAGIC NEGATIVE CODES + ;N.B.: MLO MUST BE AT RIGHT-HAND END OF WORD - CODE DEPENDS + +MEMPNT: BLOCK TSYSM ;RH USED FOR CIRC MEM USE PNTR IF USER MEM + ;LH FOR DISK ADDRESS CAME FROM OR GOING TO + ;MEMPNT HAS BLOCK NUMBER + ;DISK NUMBER COMES FROM CHANNEL LINKED TO + ;CIRCULAR PAGE LINK FORM + ;2.9=0 + ;1.1-1.8 PAGE # + ;2.8-1.9 USER # + ;2.9=1 + ;2.8=0 2.7-1.1 LINK TO MMP TABLE + ;2.8=1 2.7-1.1 LINK TO MEM PNT TABLE + ;EXCEPT 2.9-1.1=777777 => ABSOLUTE PAGE, NOT LINKED + +MMSWP: BLOCK TSYSM ;IF USER MEM, HAS NUMBER OF PAGE TABLE WORDS + ; WHICH POINT AT THIS PAGE. LH IS NUMBER OF EXEC + ; PAGES, RH IS NUMBER OF USER PAGES. NOTE THAT THE + ; NUMBER OF UPGCP ENTRIES COULD BE MORE, FOR VARIOUS + ; REASONS, E.G. CIRPSW LOCKED WHEN PAGE SWAPPED IN, + ; OR A USER WAS SWAPPED OUT. + ;IFN SWPWSP, RH(MMSWP) IS USED AS NUMBER OF SHARERS. + +EMEMTL==.-1 ;END FOR GETSYS (MEMORY) + +MMPRTC: 0 ;C AT MMPRTN, FOR DEBUGGING + +MMPFS: 0 ;FREE-LIST OF MMP ENTRIES. VALUE IS ADDRESS. (FORMERLY WAS IDX). + +MMPFS2: 0 ;LIST OF MMPS THAT NEED TO HAVE TUT SOS'ED BEFORE THEY CAN BE FREED. + ;TUT COULDN'T BE SOS'ED AT P.I. LEVEL BECAUSE IT WAS LOCKED. + ;THESE MMPS MAY ALSO NEED TO BE REMOVED FROM THE SHAREABLE + ;PAGE TABLE, WHICH REQUIRES CIRPSW. + +MMPCNT: 0 ;# OF MMP ENTRIES IN USE. + +MMPFR: NMMP*1000 ;MAX POSSIBLE # MMP ENTRIES, MINUS # IN USE OR COMMITTED. + +;MMP TABLE - TWO WDS PER ENTRY +MMPPUB==400000 ;WD1 4.9 INDICATES A PUBLIC PAGE IF ON (ANYONE CAN ATTACH TO WRITE) +MMPOUT==200000 ;4.8 => PAGE IS SWAPPED OUT OR ON WAY OUT. +MMPTMP==100000 ;4.7 => IN TRANSIT (ON WAY IN OR ON WAY OUT). +MMPWOD==40000 ;4.6 => THIS PAGE HAS BEEN WRITTEN ON DISK AT LEAST ONCE +MMPISW==20000 ;4.5 PAGE ON INITIAL SWAPIN, BEING COPIED SO SWAP OUT TO DIFF PLACE +MMPWRT==10000 ;4.4 HAS BEEN WRITTEN SINCE LAST DISK WRITE BY USER WHO HAS DETACHED THIS PAGE +MMPGON==4000 ;4.3 FILE PAGE BEING WRITTEN OUT AFTER + ;DELETED FROM ALL MAPS (MMP ENTRY WILL SOON GO AWAY.) +MMPBAD==2000 ;4.2 PAGE GOT PAR ERR SINCE LAST TIME SWAPPED OUT OR IN. +MMPLOK==1000 ;4.1 => PAGE MAY NOT BE SWAPPED OUT. +MMPSLO==400 ;3.9 => PAGE SHOULD GO IN SLOW MEMORY. +MMPSHR==200 ;3.8 MMP ENTRY IS IN SHAREABLE PAGE HASH TABLE +MMPPGA==100 ;3.7 BEING SWAPPED IN BY PAGE-AHEAD. DON'T PUT IN USER MAPS; WAIT FOR FAULTS. +MMPPGB==40 ;3.6 BEING SWAPPED OUT BY PAGE-BEHIND. +$MMPUN==220300 ;3.1-3.3 UNIT NUMBER (GOES WITH DISK ADDR IN WD2 LH) + ;WD1 RH CIRC MEM USE PNTR + ;WD2 LH READ DISK ADR OR 0 + ;WD2 RH THREAD FOR SHAREABLE PAGE HASH TABLE + +MMPNP: 0 ;#MMP PGS ACTUALLY IN USE +MMPMX: 0 ;HIGHEST VALID MMP INDEX (MMPNP*2000) + +MMMPG: BLOCK NMMP ;BLOCK NOS OF BLOCKS ACTUALLY USED + +;SHAREABLE PAGE HASH TABLE +;MMP ENTRIES THAT ARE SHARED WITH FILES ARE LISTED HERE TO SAVE TIME AT NCORQ2 +;SIMPLE REMAINDER HASH ON UNIT#,,DISK ADDRESS, +;BUCKETS THREADED THROUGH RH(MMPE+1) + +SHRHSL==31. ;NUMBER OF BUCKETS +SHRHSH: BLOCK SHRHSL + +;"LOOSE" PAGES (NOT USED BY ANY USER, BUT NOT YET SWAPPED OUT.) +;MMP ENTRY GOES AWAY WHEN SWAPPED OUT, OR GETS PUT BACK INTO SERVICE AT NCORQ3. +NLOOSP: 0 ;NUMBER OF LOOSE PAGES +FLOOSP: 0 ;HEAD OF LIST. THREADED THROUGH MLO IN MEMBLT. +LLOOSP: 0 ;TAIL OF LIST. ADD AT TAIL, SWAPPER REMOVES FROM HEAD. + +BBLK +MMPEAD: REPEAT NMMP, CONC MMP,\.RPCNT,*2000+400000 ;EXEC ADR +MMPPPP: REPEAT NMMP, CONC .MMP,\.RPCNT,+EXEUMP ;PNTR TO EXEC PC MP +USEMDM: DIRMAP ;NON-ZERO => USE MEDIUM MEMORY. + ;DON'T CHANGE AFTER SYSTEM STARTUP + +SUBTTL 200-WORD I/O BUFFER ROUTINES + +;SYS CHANNEL ASSIGN +; 77=>FREE +; 0 - NUTIC+NUTOC-1 => UTAPE CHNL +;NUTIC+NUTOC (=NFCLC-1) =>UTAPE FILE DIR +;NFCLS-NFCLC+NCLCH-1 (=NFNETC-1) => CORE LINK +;NFNETC-NNETCH => NETWORK + +IOBCNS: MOVEI A,IOBFP-IOBFT +IOBC1: MOVE E,A + LDB A,[IOLO,,IOBFT(A)] + CAIN A,377 + JRST 4,. ;IOBFT POINTERS FOULED UP + +IOBC2: LDB B,[420200,,IOBFT(A)] + JUMPN B,IOBC1 + LDB B,[IOLO,,IOBFT(A)] + DPB B,[IOLO,,IOBFT(E)] + SOS IOBFC + POPJ P, + + +IOBR: MOVE B,IOBFP ;RETURN IOBFT WORD + CLEARM IOBFT(A) + DPB B,[IOLO,,IOBFT(A)] + MOVEM A,IOBFP + MOVEI B,77 + DPB B,[IOCH,,IOBFT(A)] + AOS IOBFC + POPJ P, + +IUTCONS: ;ALLOCATE 200 WORD BUFFER +IUTCO1: PI2SAF + SKIPG UTTBF ;CLOBBERS A B E TT, RETURNS IOBFT INDEX IN A + JRST IUTC1 ;NO UTAPE BUFFERS FREE + MOVEI E,UTFS-IOBFT + MOVE A,UTFS ;CHNL NO IN D +IUTC3: CAIN A,377 + JRST IUTC1 + LDB B,[420200,,IOBFT(A)] + JUMPN B,IUTC2 + LDB B,[IOCH,,IOBFT(A)] + CAIE B,77 + JRST 4,. ;BUFFER BEING ALLOCATED ISN'T FREE. + LDB B,[IOLO,,IOBFT(A)] + DPB B,[IOLO,,IOBFT(E)] + DPB D,[IOCH,,IOBFT(A)] + SOS UTTBF + JRST POPJ1 + +IUTC2: MOVE E,A + LDB A,[IOLO,,IOBFT(A)] + JRST IUTC3 + +IUTC1: PUSHJ P,UIMRQ + POPJ P, + PUSHJ P,UTMGB + JRST IUTCO1 + +IBRTN: PI2SAF + PUSH P,B ;FREE 200 WORD BUFFER (SEE BRTN) +; LDB B,[IOCH,,IOBFT(A)] +; CAIN B,77 +; JRST 4,. ;RETURNING A BUFFER THAT'S FREE? + MOVE B,UTFS + DPB B,[IOLO,,IOBFT(A)] + MOVEM A,UTFS + MOVEI B,77 + DPB B,[IOCH,,IOBFT(A)] + LDB B,[IOSA,,IOBFT(A)] + SKIPN B + JRST 4,. + AOS UTTBF + JRST POPBJ + +UTMGB: PUSH P,J ;GOBBLE MEM BLK IN A FOR UTAPE BUFFER + PUSH P,R + PUSH P,Q + PUSH P,B + PUSH P,E + MOVEI B,MUIOB + DPB B,[MUR,,MEMBLT(A)] + MOVE J,A + LSH A,10.-6. ;CONV TO BUF SA + MOVE TT,A ;INCR TO NEXT BUF ADR + MOVEI R,8 + ADDM R,UTTLB ;UTTBF AOSED AT IBRTN + MOVNI Q,1 +UTMG1: PUSHJ P,IOBCNS + DPB TT,[IOSA,,IOBFT(A)] + JUMPL Q,UTMG2 + DPB A,[IOLC,,IOBFT(Q)] +UTMG3: MOVE Q,A + PUSHJ P,IBRTN + ADDI TT,2 + SOJG R,UTMG1 + MOVEI TT,377 + DPB TT,[IOLC,,IOBFT(A)] + POP P,E + POP P,B + POP P,Q + POP P,R + POP P,J +FSCMP: ;RECOMPUTE UTAPE BUFFER FAIR SHARE +IFN NUNITS,[ + MOVE A,UTTLB + PUSH P,A+1 + IDIV A,NUTCA + POP P,A+1 + MOVEM A,UPCHFS +] + POPJ P, + +UTMG2: DPB A,[MNUMB,,MEMBLT(J)] + JRST UTMG3 + +BRTN: CONO PI,UTCOFF ;RETURN A 200-WD BUFFER + PUSHJ P,IBRTN + JRST UTCONJ diff --git a/src/system/dc10.defs27 b/src/system/dc10.defs27 new file mode 100755 index 00000000..618dc86c --- /dev/null +++ b/src/system/dc10.defs27 @@ -0,0 +1,270 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + +;SYSTEMS CONCEPTS DC10 PHYSICAL CHARACTERISTICS + +DEFSYM NCYLS==400. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS==6 ;# EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==20. ;# TRACKS/CYLINDER +DEFSYM NSECS==2 ;# BLKS/TRK +DEFSYM SECBLK==1 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS ;# BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ;TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ;# XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ;TOTAL BLOCKS + +DEFSYM NTUTBL==2 ;2 BLOCKS PER TUT (DUAL-DENSITY CALCOMPS THESE DAYS) +DEFSYM DECADE==20. ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS + +;EXTRA WORDS IN BLOCK + +DEFSYM XWBWC==0 +DEFSYM XWBLK==1700,, ;BP TO PREV BLK # IN FILE FLD +DEFSYM XWAWC==171200,, ;BP TO ACTIVE WD CNT +DEFSYM XWSYSN==1 +DEFSYM XWFN1==2 +DEFSYM XWFN2==3 +DEFSYM NXWDS==4 ;NUMBER OF EXTRA WORDS + +DEFSYM DC0==610 ;MAIN DEVICE CODE +DEFSYM DC1==614 ;READS ERR STATUS ETC, SETS TIMER DRIVER # ON CONO + +;FIELDS IN HEADER WORD 0 + +DEFSYM DPKID==240700,, ;PACK ID FIELD +DEFSYM DCYL==131100,, ;CYLINDER CHECK FIELD +DEFSYM DSURF==60500,, ;SURFACE CHECK FIELD +DEFSYM DSECT==600,, ;SECTOR FIELD + +;WORD 1 HEADER + +DEFSYM DHIND==1000,, ;4.1 INDIRECT IF 1, CYL, SURF, SECTOR SAME AS ABOVE +DEFSYM DHSPRT==400,, ;BIT 3.9 SOFTWARE PROTECT +DEFSYM DHHPRT==200,, ;3.8 HARDWARE PROTECT +DEFSYM DHNXAD==270200,, ;3.7, 3.6 HOW TO COMPUTE NEXT DISK ADR + ;=00 ADD 1 TO SECTOR + ;01 SET SECTOR TO 0, ADD 1 TO SURF + ;10 SET SECTOR AND SURFACE TO 0, ADD 1 TO CYL + ;11 END OF DISK +DEFSYM DHEPB==10,, ;PARITY BIT FOR EVEN BITS OF 56 BIT HEADER +DEFSYM DHOPB==4,, ;PARITY BIT FOR ODD BITS OF 56 BIT HEADER +DEFSYM DHSLNG==1600,, ;-LENGTH OF SECTOR FIELD + +;DISK ADDRESS DATA COMMANDS (OP CODES) + +DEFSYM DRC==400000,, ;READ COMPARE +DEFSYM DWRITE==440000,, ;WRITE +DEFSYM DREAD==500000,, ;READ +DEFSYM DSEEK==540000,, ;SEEK +DEFSYM DRCC==600000,, ;READ COMPARE CONTINUOUS +DEFSYM DWRITC==640000,, ;WRITE CONTINUOUS +DEFSYM DREADC==700000,, ;READ CONTINUOUS + +DEFSYM DUNENB==20000,, ;ENABLE LOAD UNIT FIELD +DEFSYM DUNFLD==330400,, ;UNIT FIELD +;PKID, CYL, SURF, AND SECTOR SAME AS ABOVE + +;COPY / COMPARE / SKIP COMMAND + +DEFSYM DCOPY==40000,, ;COPY +DEFSYM DCCOMP==100000,, ;COMPARE +DEFSYM DCSKIP==140000,, ;SKIP + +DEFSYM DCWC==241400,, ;-WC FIELD +DEFSYM DCCA==2400,, ;CORE ADDRES +DEFSYM DCBN==121200,, ;BLOCK NUMBER + +;JUMP COMMANDS +DEFSYM DHLT==0 ;0 IN 4.9-4.5 = JUMP AND IN 3.5,3.6 = HALT +DEFSYM DXCT==20,, ;XCT +DEFSYM DJMP==40,, ;JUMP +DEFSYM DJSR==60,, ;JSR + +;"B" COMMAND BITS 3.3, 3.4 +;0 ALWAYS +DEFSYM DAOJNC==4,, ;AOJN THE CONTROL COUNTER +DEFSYM DDOK==10,, ;ON NO DATA ERROR +DEFSYM DSRQF==14,, ;IF SEEK RQ FLAG ON + +;STORE REGISTER COMMAND +DEFSYM DSREG==240400,, ;STORE REG +;USE, UNIT BITS SAME +DEFSYM DSREGS==240300,, ;SOURCE REGISTER SELECT FIELD +DEFSYM DSRDB==0 ;STORE DATA BUFFER +DEFSYM DSRDL==4,, ;STORE DISK LOCATION +DEFSYM DSRCC==10,, ;STORE COMMAND COUNT +DEFSYM DSRPC==24,, ;STORE PC (IN FORM OF JMP INST.) +DEFSYM DSRWC==30,, ;STORE WORD COUNT +DEFSYM DSRCA==34,, ;STORE CORE ADDRESS (TO XFER DATA TO OR FROM) + +;ALU COMMAND +DEFSYM DALU==300000,, ;BASIC ALU OP CODE +DEFSYM DALUX==40000,, ;INDEX BIT (ADD CC TO ADR) +DEFSYM DALUD==40,, ;DIRECT BIT IF 1, REF MEM OT GET B OP + +DEFSYM DASL==4000,, ;SKIP ON <0 +DEFSYM DASE==10000,, ;SKIP ON = 0 +DEFSYM DASLE==14000,, ;SKIP ON < OR = 0 +DEFSYM DASA==20000,, ;ALWAYS SKIP +DEFSYM DASGE==24000,, ;SKIP ON > OR = 0 +DEFSYM DASN==30000,, ;SKIP ON NOT = 0 +DEFSYM DASG==34000,, ;SKIP ON > 0 + +;DESTINATION SUB OP (ALSO SPECIFIES SOURCE A) +DEFSYM DLDB==0 ;OP A FROM DB, STORE IN DB +DEFSYM DLDL==4,, ;OP FROM DL, STORE IN DL +DEFSYM DLCC==10,, ;OP FROM CC, STORE IN CC +DEFSYM DLCA==14,, ;OP A =0, STORE IN CA +DEFSYM DLTDB==20,, ;TEST DB (OP A FROM DB, NO STORE) +DEFSYM DLDBPC==24,, ;OP A FROM DB, STORE IN PC +DEFSYM DLDBWC==30,, ;OP A FROM DB, STORE IN WC +DEFSYM DLDBM==34,, ;OP A FROM DB, STORE IN MEM (DIRECT MUST BE ONE TO REALLY MAKE IT) + +;SOME USEFUL (?) OPS +DEFSYM DLADD==100,, ;A+B +DEFSYM DLSOS==200,, ;B-1 +DEFSYM DLLB==300,, ;B +DEFSYM DLSUB==400,, ;B-A + +DEFSYM DLAND==2300,, ;A&B +DEFSYM DLIOR==2500,, ;A IOR B +DEFSYM DLLA==3100,, ;LOAD A +DEFSYM DLSETO==3200,, ;-1 +DEFSYM DLSETZ==3300,, ;0 + +;OPR COMMAND +DEFSYM DOPR==200000,, ;BASIC OPR +DEFSYM DOHXFR==400,, ;HALT DURING XFER (SO MB WILL BE SAFE) +DEFSYM DOCSRQ==200,, ;CLEAR SEEK RQ +DEFSYM DOSSRQ==100,, ;SET SEEK RQ +DEFSYM DOSCFL==40,, ;SET C FLAG + +;STORE DRIVE STATUS +DEFSYM DSDRST==240000,, ;STORE DRIVE STATUS +;UNIT ENABLE, UNIT FIELD SAME +DEFSYM DSDCNT==240400,, ;COUNT-1 FIELD + +;BITS IN DRIVE STATUS STORED + +DEFSYM DDSWC==40,, ;WRITE CURRENT SENSED +DEFSYM DDSUNS==20,, ;DRIVE UNSAFE +DEFSYM DDSRDO==10,, ;READ ONLY +DEFSYM DDSSIC==4,, ;SEEK INCOMPLETE +DEFSYM DDSRDY==2,, ;DRIVE READY +DEFSYM DDSONL==1,, ;DRIVE ON LINE +DEFSYM DDSSEL==400000 ;DRIVE SELECTED +DEFSYM DDSCYL==101000,, ;PRESENT CYLINDER +DEFSYM DDSLAT==1000,, ;LATENCY TIMER + +;DISK ADR "SPECIAL COMMAND" + +DEFSYM DSPC==740000,, ;BASIC OP CODE +;USE, UNIT FIELDS AS NORMAL + +; E CONDITION (WAIT) +;0 NONE +DEFSYM DSWIDX==20,, ;WAIT UNTIL INDEX PULSE +DEFSYM DSWSEC==40,, ;WAIT UNTIL SECTOR PULSE +DEFSYM DSWINF==60,, ;NEVER (USE WITH G=3 OR 7) + +; F CONDITION (OTHER WAIT) +DEFSYM DSWHDM==0 ;WAIT FOR MATCHING HEADER +DEFSYM DSWAGH==4,, ;ANY GOOD HEADER +DEFSYM DSWAH==10,, ;ANY HEADER +DEFSYM DSWNUL==14,, ;NO WAIT + +;G OPERATION +DEFSYM DSCRDC==0 ;READ DATA THRU DECODERS +DEFSYM DSCRIM==100,, ;READ DATA IMAGE +DEFSYM DSCRHD==200,, ;READ HEADER WORDS +DEFSYM DSRCAL==300,, ;(RECALIBRATE) +DEFSYM DSCWDC==400,, ;WRITE THRU DECODERS +DEFSYM DSCWIM==500,, ;WRITE IMAGE +DEFSYM DSMAIT==700,, ;MAINTENANCE (PUT CYL FIELD ON BUS LINES WITH CONTROL TAG) + +;BITS IN CONI DC0, +DEFSYM DASSGN==400000,, ;ASSIGNED TO PROC (WITH SWITCH) +DEFSYM DPIRQC==400000 ;PI REQ BEING GENERATED +DEFSYM DSSRQ==200000 ;SEEK REQUEST +DEFSYM DSDEEB==10000 ;ENABLE INTERRUPT ON DATA ERROR OR READ/ COMP ERROR +DEFSYM DSSERR==4000 ;ERROR FLAG +DEFSYM DSSAEB==2000 ;ATTENTION ENABLE FLAG +DEFSYM DSSATT==1000 ;ATTENTION FLAG +DEFSYM DSIENB==400 ;IDLE FLAG ENABLE +DEFSYM DSSRUN==200 ;RUN +DEFSYM DSSACT==100 ;ACTIVE +DEFSYM DSSCEB==40 ;CHANNEL ENABLE +DEFSYM DSSCHF==20 ;CHANNEL FLAG +DEFSYM DSSCFL==10 ;CPU FLAG +;PIA 1.3-1.1 + +;DATAO DC0, SENDS COMMAND TO DISK +; (IGNORED IF EXECUTING COMMANDS FROM MEMORY) + +;CONO DC0, +DEFSYM DCSET==400000 ;SET SELECTED +DEFSYM DCCLR==200000 ;CLEAR SELECTED +DEFSYM DCCSET==600000 ;RESET CONTROLLER THEN SET SELECTED +DEFSYM DCDENB==10000 ;DATA ERROR ENABLE +DEFSYM DCERR==4000 ;SET ERROR FLAG OR CLEAR ALL ERRORS +DEFSYM DCATEB==2000 ;ATTENTION ENABLE +DEFSYM DCCATT==1000 ;CLEAR ATTENTION +DEFSYM DCSSRQ==1000 ;SET SEEK REQUEST +DEFSYM DCIENB==400 ;IDLE ENABLE +DEFSYM DCSTAR==200 ;START (SET) +DEFSYM DCSSTP==200 ;STOP (CLEAR) +DEFSYM DCSGL==100 ;DO SINGLE COMMAND +DEFSYM DCCENB==40 ;CHANNEL ENABLE +DEFSYM DCCFLG==20 ;CHANNEL FLAG +DEFSYM DCCPUF==10 ;CPU FLAG +;1.1-1.3 PIA + +;CONO DC1, + +;SET TIMER DRIVE # FROM 1.1-1.3 + +;CONI DC1, +;LH +DEFSYM DSATDN==360400,, ;ATTENTION DRIVE # +DEFSYM DSTMDN==320400,, ;TIMER DRIVE # +DEFSYM DSLAT==221000,, ;LATENCY TIMER FOR DRIVE ABOVE + +;RH (ERROR FLAGS) +DEFSYM DIPE==4000 ;INTERNAL PARITY ERROR +DEFSYM DRLNER==2000 ;RECORD LENGTH +DEFSYM DRCER==1000 ;READ COMPARE ERROR +DEFSYM DOVRRN==400 ;OVERRUN +DEFSYM DCKSER==200 ;CKSUM OR DECODER ERR +DEFSYM DWTHER==100 ;WATCHDOG TIMER +DEFSYM DFUNSF==40 ;FILE UNSAFE, SEEK INCOMPLETE OR END OR DSK +DEFSYM DOFFL==20 ;OFF LINE OR MULT SEL +DEFSYM DPROT==10 ;WRT KEY OR RD ONLY OR PROTECT +DEFSYM DDOBSY==4 ;DATAO WHEN BSY +DEFSYM DNXM==2 ;NON-EX MEM +DEFSYM DCPERR==1 ;CORE PARITY ERR + +DEFSYM LRIBLK==16 ;CONSISTENCY CHECK DSKDMP VS MARK + + +IFN $$TEMP,EXPUNG DEFSYM + \ No newline at end of file diff --git a/src/system/ddt.68 b/src/system/ddt.68 new file mode 100755 index 0000000000000000000000000000000000000000..fbbfe57b5c01edd2b12cc86f863e023499d1b952 GIT binary patch literal 48256 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 VpRc~%D0wwwFg4%YHbUe0e*k(WWr_d* literal 0 HcmV?d00001 diff --git a/src/system/ddtdsk.31 b/src/system/ddtdsk.31 new file mode 100755 index 0000000000000000000000000000000000000000..e20ecf6038ce41788dd6f946fac080ace5f5ea1c GIT binary patch literal 28952 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 XF7@pKFU25%-Zi9uDM(B) + ADD B,QMDRO + MOVE A,(B) + JRST NRDM1 +];QAUTHP + +ASREAP: PUSHJ P,QCHNLT ;SET NO REAP BIT + DPB B,[.BP (UNREAP),UNRNDM(C)] + JRST NSDM1 + +ARQDAT: CONO PI,CLKOFF ;GET DSK TIME AND DATE + SKIPL A,QDATE + HRR A,TIMOFF + MOVE B,QDATEI ;2ND VALUE = DATE & TIME SYS CAME UP, IN DISK FORMAT. + CONO PI,CLKON + JRST POPJ1 + +ADSKUP: PUSHJ P,QCHNLT ;SET CREATION DATE, REF DATE AND CLEAR DUMP BIT + CONO PI,CLKOFF + SKIPL TT,QDATE + HRR TT,TIMOFF + CONO PI,CLKON + MOVEM TT,UNDATE(C) + HLRS TT + DPB TT,[UNREFD+UNREF(C)] + MOVSI TT,UNDUMP + ANDCAM TT,UNRNDM(C) + JRST NSDM1 + +DELEWO: TLNN R,%CLSQ ;DELETE WHILE OPEN + JRST OPNL34 ;WRONG TYPE DEVICE + PUSHJ P,QCHNLT + PUSH P,W + PUSH P,C + MOVEI W,4 + MOVE A,UNFN1(C) ;Get names of file being hacked. + MOVE B,UNFN2(C) + MOVE C,QSNUD(H) + PUSHJ P,MNGDIR ;If this is a sanctified dir + PUSHJ P,SYSDSK ; get SYS job to tattle about it. + POP P,C + POP P,W + MOVSI T,%QADEL ;SET DELETE BIT IN QSK CHNL + IORM T,QSRAC(R) + MOVSI T,UNCDEL ;AND IN FILE + IORM T,UNRNDM(C) + JRST NSDM1 + +;.CALL FILLEN +;RETURNS (1) FILE LENGTH IN BYTES (BYTE SIZE CURRENTLY OPEN IN) +; (2) BITS PER BYTE (BYTE SIZE CURRENTLY OPEN IN) +; (3) FILE LENGTH IN BYTES (BYTE SIZE WRITTEN IN) +; (4) BITS PER BYTE (BYTE SIZE WRITTEN IN) + +NFILLEN:PUSHJ P,QCHNLT + MOVE A,QSRAC(R) + TLNE A,%QALNK + JRST OPNL34 ;NOT A FILE + SKIPGE QSCRW(R) + TLNE A,%QAMWO + JRST NFILL1 ;READ CHANNEL OR WRITE-OVER, GET FILE'S STORED LENGTH. + MOVE A,QFBLNO(R);NORMAL WRITE, GET ACCESS POINTER. + SKIPGE QSMDN(R) + JRST NFILL2 ;NO BUFFER ACTIVE + ADD A,QMPBSZ(R) ;END OF CURRENT BUFFER + SUB A,QSMPRC(R) ;BACK UP TO CURRENT LOC +NFILL2: PUSHJ P,QUDULK + LDB B,[QSBSIZ(R)] ;CURRENT BYTE SIZE + MOVE D,B ;WRITTEN BYTE SIZE SAME AS CURRENT + MOVE C,A ;WRITTEN LENGTH SAME AS CURRENT + JRST POPJ1 + +NFILL1: LDB TT,[UNDSCP+UNRNDM(C)] + IDIVI TT,UFDBPW + HLL TT,QBTBLI(I) ;GET DESCRIPTOR POINTER + LDB E,[UNWRDC+UNRNDM(C)] + SKIPN E + MOVEI E,2000 ;E GETS NUMBER OF WORDS IN LAST BLOCK + LDB D,[UNBYTE+UNREF(C)] ;D GETS BYTE INFO + ANDI C,-2000 ;C GETS BASE ADDR OF DIR + ADDI TT,UDDESC(C) ;TT GETS DESC PNTR + SETOM A ;INITIALIZE NUMBER OF BLOCKS IN FILE + PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE MINUS ONE + PUSHJ P,QUDULK + IMULI A,2000 ;NUMBER OF WORDS IN COMPLETE BLOCKS + ADD A,E ;ADD WORDS IN LAST BLOCK + PUSHJ P,QBDCD ;D GETS BYTE SIZE, E NUMBER OF RESIDUE BYTES + MOVEI Q,36. + IDIV Q,D ;Q GETS BYTES PER WORD + MOVE C,A ;C WRITTEN LENGTH, A CURRENT (B.S. DIFFERENT) + IMUL C,Q ;CONVERT WORD LENGTH TO BYTES + SUB C,E ;C NOW HAS CORRECT WRITTEN LENGTH + IMUL E,D ;E GETS NUMBER OF RESIDUE BITS + LDB B,[QSBSIZ(R)] ;B GETS BYTE SIZE OPENED IN + IMULI A,@QSBYTE(R) ;A GETS LENGTH IN THOSE SIZE BYTES + IDIV E,B ;NUMBER OF RESIDUE BYTES, -ROUNDING DOWN- + SUB A,E ;ADJUST THE LENGTH + JRST POPJ1 ;RETURN VALUES IN A,B,C,D + +NFLLN2: ADD A,B ; NEXT N BLOCKS +NFLLN1: ILDB B,TT ; GET NEXT DESC BYTE + JUMPE B,CPOPJ ; NO MORE + CAIG B,UDTKMX + JRST NFLLN2 ; TAKE-N + CAIGE B,UDWPH + AOJA A,NFLLN1 ; SKIP-N, TAKE-1 + CAIN B,UDWPH + JRST NFLLN1 ; IGNORE WRITE-PLACEHOLDER +REPEAT NXLBYT, IBP TT ; LOAD-ADDRESS, TAKE-1 + AOJA A,NFLLN1 + +;DIRSIZ - READ OR SET DISK QUOTAS, READ # BLOCKS IN ALL FILES IN DIRECTORY. +;1ST VALUE IS GRIM REAP QUOTA,,DIR SIZE +;2ND VALUE IS 0 OR PACK#,,ALLOCATION FOR DIR ALLOCATED TO SPECIFIC PACK +;LH OF 2ND ARG SETS GRIM REAP QUOTA; 3RD ARG SETS PACK#,,ALLOCATION +NDIRSI: MOVE D,C + PUSHJ P,QCHNLT + MOVE C,QSNLCN(H) + MOVE A,UDBLKS(C) + JUMPL B,NDIRS1 + CAIE W,1 + HLLM B,UDBLKS(C) +NDIRS1: MOVE B,UDALLO(C) + CAILE W,2 + MOVEM D,UDALLO(C) +IFN QRSRVP,[ + HLRZS D ;PACK ALLOCATED TO + SETO E, + JUMPE D,NDIRS2 + MOVEI E,NQS-1 ;UPDATE ALLOC DRIVE NUM + CAME D,QPKID(E) + SOJGE E,.-1 +NDIRS2: MOVEM E,QSALLO(H) +];QRSRVP + JRST NSDM1 + +SUBTTL DISK OPEN ROUTINES + +%DO==1,,525252 ;Special mode bits for disk opens. +%DOWOV==100000 ;Write over mode +%DONRF==10 ;Don't set ref-date +%DONLK==20 ;Don't chase links; actually open the link itself. +%DORWT==40 ;Make readers wait (used on opens for write or write-over). + +IFN TPLP+UNSPLP,[ +TPLO: MOVE C,[SIXBIT /.LPTR./] ;PSEUDO LINE PRINTER (DISC) + JUMPGE D,TPLO2 + MOVE B,UNAME(U) + AOS A,TPLFNO ;GENERATE RANDOM FILE NAME + JRST TPLO2 +] + +COMO: SKIPA C,[SIXBIT /COMMON/] ;.OPEN ENTRY FOR "COM" DEVICE +SYSO: MOVSI C,(SIXBIT /SYS/) ; " FOR "SYS" DEVICE +TPLO2: MOVEM C,USYSN1(U) + MOVNI I,1 + JRST QSKO + +QSKPO: MOVSI TT,-NQS ;PACK # OPEN + CAME I,QPKID(TT) + AOBJN TT,.-1 ;I <= PHYSICAL UNIT WITH SPECIFIED PACK + JUMPL TT,QSKPO1 + PUSHJ P,QPKNFP + JRST QSKPO + CAIE W,4 ;IF RENAME/DELETE, OK, DOESN'T TOUCH FILE ANYWAY + JRST OPNL16 ;OTHERWISE COMPLAIN PACK NOT MOUNTED +QSKPO1: HRRZ I,TT +QSKUO: CAIGE I,NQS ;DISK UNIT # OPEN + SKIPE QACT(I) ;I <= UNIT # + JRST OPNL10 ;BAD UNIT # OR NOT ENGAGED +IFE MCOND DM,[ ;; Security check in reserved pack feature only on DM. +IFN QRSRVP,[ + JUMPN W,QSKOB ;WRITE-OVER OR RENAME OK. + JUMPGE D,QSKOB ;READ OK. + SKIPE QRESRV(I) ;WRITE: IS PACK ON THIS DRIVE RESERVED? + JRST OPNL10 ;YES, CAN'T WRITE ON IT. +];QRSRVP +];DM + JRST QSKOB + +;DNRF: DEVICE IS LIKE DSK: BUT DOESN'T SET REFERENCE DATE +DNRFO: TRO D,%DONRF/2 ;SET MODE BIT AND DROP INTO QSKO + +; Regular DSK: device +; +; RH(D) has open mode, rotated 1 bit right. +; W has operation code (0=r/w, 2=link, 4=del/rnm, 1=wov) + +QSKO: MOVNI I,1 ;DSK OPEN, I <= # DETERMINED BY SYS +QSKOB: MOVEM I,EPDL(U) ;SAVE DISK # + MOVE C,USYSN1(U) + CAIN W,4 + JUMPE A,QSKOB2 ;IF RENAME OF OPEN FILE TRAP OUT +QSKOA: MOVE I,MDSK ;IS MFD IN? + PUSHJ P,QMCH1 ;READ IN MFD OF MASTER DISK + CLEARM QLD(U) ;LINK DEPTH +QSKOL: PUSHJ P,MFDCK + JRST SYSDS2 + JUMPN W,OPNL11 + JUMPL D,OPNL11 ;MUST BE NORMAL READ + JRST QMLSTF ;USER WANT TO READ THE MASTER DIRECTORY + +MFDCK: CAMN A,[SIXBIT /M.F.D./] + CAME B,[SIXBIT /(FILE)/] + POPJ P, + JRST POPJ1 + +SYSDS2: PUSHJ P,QFLD ;H <= PTR TO USER DIR TABLE + PUSHJ P,QSKO1 ;LOSER DIR NOT IN CORE + SKIPG QSNNR(H) + BUG + PUSHJ P,QUDLK ;RETURN WITH SOS OF QSNNR ON LSWPR + MOVSI TT,40000 + TDNE TT,QSNLCN(H) + JRST QSKDP1 ;PAW OVER USER DIRECTORY +QSKDP2: PUSHJ P,QUDULK + PUSHJ P,FLDRCK + JRST QSKDP9 ;NOT SPECIAL DIRECTORY FILE + JUMPN W,QPNL11 + JUMPL D,QPNL11 + JRST QLISTF ;USER WANTS TO READ HIS USER DIRECTORY + +QSKDP9: JUMPN W,QSKDPY ;If doing IO? + SKIPL D ; and reading + JRST QSKDPZ ; then don't bother with "security". +QSKDPY: PUSHJ P,MNGDIR ;Else if this is a sanctified dir + PUSHJ P,SYSDSK ; get SYS job to tattle about it. +QSKDPZ: JUMPL D,QWRO ;WRITE + CAIN W,4 + JRST QRNAM ;RENAME/DEL + CAIN W,2 + JRST QALINK ;MAKE LINK + JUMPN W,QPNL22 +QWROR: JUMPE A,QPNL11 ;ALSO ENTER FOR VARIOUS WRITE OVER, COPY OVER MODES + JUMPE B,QPNL11 + PUSHJ P,QCHNF ;GET CHANNEL FOR READ + PUSHJ P,LOSSET + QCHNRT + PUSHJ P,QUDLK ;LOCK USER DIR + PUSHJ P,QLOOK ;LOOK UP FILE + JRST [ PUSHJ P,QROR1C ;Not found => decide whethe error or wait. + POPJ P, ;Error (error code already set up). + PUSHJ P,QUDULK ;If retrying, first unlock directory, + PUSHJ P,LSWPOP ;Return the channel, + PUSHJ P,UDELAY ;Wait a little while, + JRST QWROR] ;Try again. + TRNE D,3 ;SKIP IF UNIT ASCII MODE + JRST QSKO2 + MOVE J,[440700,,5] ;BYTE SIZE IS 7 BITS + MOVEM J,QSBYTE(E) +QSKO2: HLLZ J,QSBYTE(E) ;GET PROPER BYTE POINTER LH + MOVEM J,QSMPRP(E) + TRNN D,%DONRF/2 ;3.4 BIT IN OPEN IMPLIES DONT SET REFERENCE DATE + PUSHJ P,QFREF ;"REFERENCE" FILE + MOVE C,Q + SUB C,QSNLCN(H) + HRRZM C,QUDFPR(E) ;SET UP PTR FROM CHNL TO FILE NAME AREA + LDB TT,[UNDSCP+UNRNDM(Q)] ;FOUND FILE SET UP CHNL + MOVEM TT,QDIRP(E) ;SET UP CHAR PTR TO DESC AREA + MOVE C,UNRNDM(Q) + TLNE C,UNLINK + JRST QLINK ;FILE IS A LINK + MOVSI C,%QALOP + SKIPE QLD(U) ;IF WE TRACED A LINK TO OPEN THE FILE, REMEMBER THAT. + IORM C,QSRAC(E) + MOVSI C,%QARWT + TRNE D,%DORWT/2 + IORM C,QSRAC(E) + LDB J,[UNPKN+UNRNDM(Q)] ;GET PACK NUMBER FILE IS ON + MOVSI I,-NQS + CAME J,QPKID(I) + AOBJN I,.-1 ;TRANSLATE LOGICAL TO PHYSICAL DISK UNIT + JUMPGE I,QPKNF ;PACK NOT ON * + HRRZM I,QDSKN(E) ;SET CHNL DISK NUMBER + JUMPL D,QWROR1 ;REALLY WANT TO WRITE OVER, ETC + MOVEI TT,%QMRD ;PUT CHANNEL IN NORMAL READ MODE + HRRM TT,QSRAC(E) +QOEX1: PUSHJ P,QUDULK ;UNLOCK USER DIR + PUSHJ P,LSWDEL ;QUSR ENTRY + PUSHJ P,LSWDEL ;QSNNR ENTRY + SKIPG QSNNR(H) + BUG + PUSHJ P,QSTRTR + MOVE C,D + ROT C,1 + HRL A,E + JSP Q,OPSLC7 ;SET UP IOCHNM AND DEPART + DQUAI,,DQUAO + DQBI,,DQBO + DQUII,,DQUIO + DQBI,,DQBO + +QWROR1: SOJN W,OPNL12 ;NORMAL WRITE OVER MODE + HRRZS H ;CLEAR GARBAGE IN USER DIR NUM + HRRZS E ;CLEAR GARBAGE IN CHNL NUM + HRRZ J,QUDFPR(E) ;PICK UP LOCN OF FILE WITH U.F.D + MOVSI I,-NQCHN ;MAKE SURE THIS FILE NOT OPEN FOR READING +QROR1A: CAIE E,(I) ;DONT GET FAKED OUT BY OWN CHNL + SKIPGE QUSR(I) + JRST QROR1B + CAMN H,QUDPR(I) + CAME J,QUDFPR(I) + JRST QROR1B + JRST OPNL23 + +QROR1B: AOBJN I,QROR1A + PUSHJ P,QAUTH + MOVSI TT,UNWRIT + IORM TT,UNRNDM(Q) ;SET WRITE BIT + MOVSI TT,UNDUMP + ANDCAM TT,UNRNDM(Q) + PUSH P,D + PUSH P,Q + PUSH P,R + PUSH P,E ;CONVERT FROM ORIGINAL BYTE SIZE TO ONE OPENED IN NOW + LDB D,[UNBYTE+UNREF(Q)] + PUSHJ P,QBDCD ;GET INFO FROM ORIGINAL WRITE OF FILE + MOVEI Q,36. + IDIV Q,D ;BYTES PER WORD + SUB Q,E ;# VALID BYTES + IMUL Q,D ;VALID BITS IN LAST WORD + POP P,E ;RESTORE QSK CHNL # + HRRZ R,QSBYTE(E);BYTES PER WORD IN NEW BYTE SIZE + LDB J,[QSBSIZ(E)] ;BITS PER BYTE IN NEW BYTE SIZE + IDIV Q,J ;NUMBER OF NEW-SIZE BYTES IN LAST WORD + SUB R,Q ;RESIDUE IN NEW-SIZE BYTES + LDB Q,[QSBSIZ(E)] ;NEW BYTE SIZE + PUSHJ P,QBENC ;RH(Q) GETS NEW BYTE INFO + MOVE R,-1(P) + DPB Q,[UNBYTE+UNREF(R)] ;CLOBBER FILE'S BYTE SIZE + POP P,R + POP P,Q + POP P,D + CONO PI,CLKOFF + SKIPL TT,QDATE + HRR TT,TIMOFF + CONO PI,CLKON + MOVEM TT,UNDATE(Q) + HLRS TT + DPB TT,[UNREFD+UNREF(Q)] + HLLM TT,OLDRDT(E) + MOVE TT,QACTB + IORM TT,QSNLCN(H) + MOVSI TT,%QAMWO ;WRITE OVER MODE + IORM TT,QSRAC(E) ;LEAVE %QMIDL UNTIL FIRST .IOT SINCE + JRST QOEX1 ; THE USER WILL PROBABLY DO A .ACCESS + +;Call here if lookup fails on open. +;Either signal some error and return, +;or skip-return if caller should wait and retry the lookup. +;Assumes H has dir slot, Q has address of filename block, +;E has channel number allocated for this open. +;Clobbers C, J. +QROR1C: HRRZ C,QSNLCN(H) + SUBI Q,-LUNBLK(C) + SKIPL Q ;SEE IF STILL POINTED INSIDE DIR + CAILE Q,2000-LUNBLK + JRST QROR1D ;NO - REALLY FNF + ADDI Q,(C) + CAMN A,UNFN1(Q) ;DO NAMES MATCH? + CAME B,UNFN2(Q) + JRST QROR1D ;NO - REALLY FNF + HRRZ J,Q ;Find channel that has this file open. + SUB J,QSNLCN(H) + ANDI J,-1 + HRRZS H ;Clear garbage in user dir num + HRRZS E ;Clear garbage in chnl num + MOVSI I,-NQCHN +QROR1E: CAIE E,(I) ;Dont get faked out by our own chnl. + SKIPGE QUSR(I) + JRST QROR1F + CAMN H,QUDPR(I) + CAME J,QUDFPR(I) + JRST QROR1F +;Found the channel. Does it want us to wait? + MOVE I,QSRAC(I) + TLNN I,%QARWT + JRST OPNL23 ;He didn't say so => get "file locked". + JRST POPJ1 + +QROR1F: AOBJN I,QROR1E + JRST POPJ1 ;Cannot find channel => maybe was closed. Retry. + +QROR1D: SKIPN QLD(U) + JRST OPNL4 ;FILE NOT FOUND + JRST OPNL47 ;LINK WAS FOUND, BUT NOT THE FILE IT POINTED TO + +;COME HERE FOR RENAME-WHILE-OPEN +QSKOB2: HRRZ A,B ;DO RENAME WHILE OPEN HERE TO AVOID + CAIL A,20 ;IN CASE SYS NAME HAS CHANGED + JRST OPNL14 + SKIPE SRN3(U) + SKIPN SRN4(U) + JRST OPNL11 + ADD A,U + HLRZ E,IOCHNM(A) + MOVE H,QUDPR(E) + MOVE A,SRN3(U) + MOVE B,SRN4(U) + PUSHJ P,MFDCK + JRST .+2 + JRST QPNL11 + PUSHJ P,FLDRCK + JRST .+2 + JRST QPNL11 + PUSHJ P,QUDLK + MOVE Q,QUDFPR(E) + ADD Q,QSNLCN(H) + PUSHJ P,QGRLSC ;EITHER NAME > OR FROM POINTER + MOVE I,D ;I => TO POINTER + HRLOI E,377777 ;PREVIOUS FN1 (BIT 4.9 COMPLEMENTED) + MOVE W,E ;FN2 + MOVEI J,0 ;J NEGATIVE => NEED SORT, NON-ZERO => DIR MODIFIED +QSKDP4: SUBI I,LUNBLK +QSKDP5: SUBI D,LUNBLK + CAMLE C,D + JRST QSKDP8 ;THROUGH + SKIPN A,UNFN1(D) + SKIPE UNFN2(D) + JRST QSKDP3 + HLLOS J + JRST QSKDP5 ;NAME BLOCK FREE + +QSKDP3: MOVE Q,UNRNDM(D) + TLNN Q,UNIGFL + JRST QSKDPR ;NOT OPEN FOR WRITE OR BEING DELETED + HLLOS J ;NEED TO WRITE OUT DIR + SKIPN A,UNFN1(D) + MOVSI A,(SETZ) + SKIPN B,UNFN2(D) + MOVSI B,(SETZ) +QSKDP7: PUSHJ P,QGRLSC ;DON'T CREATE ANY FILE WITH NAME OF < OR > + AOJA A,QSKDPA ;CHANGE BOTH JUST TO BE SURE + AOJA A,QSKDPA + MOVE Q,QSNLCN(H) ;SEE IF THAT NAME EXISTS + MOVEI Q,2000-LUNBLK(Q) ;THERE MAY BE DUPLICATE ENTRIES +QSKDPU: CAMN A,UNFN1(Q) ;DURING THIS SEARCH BUT IT DOESN'T + CAME B,UNFN2(Q) ;MATTER + JRST QSKDPT + CAIE Q,(D) ;DON'T CHANGE NAME IF NOT DUPLICATE +QSKDPA: AOJA B,QSKDP7 ;FOUND IT. CHANGE SECOND NAME +QSKDPT: SUBI Q,LUNBLK + CAMG C,Q + JRST QSKDPU + MOVEM A,UNFN1(D) + MOVEM B,UNFN2(D) + MOVSI Q,UNIGFL + ANDCAM Q,UNRNDM(D) +QSKDPR: CAMN D,I + JRST QSKDP6 + HRLZ Q,D ;RELOCATE FILE BLOCK + HRR Q,I + BLT Q,LUNBLK-1(I) +QSKDP6: JUMPL J,QSKDP4 ;ALREADY NEEDS SORT + MOVE B,UNFN2(D) ;MAY NOT HAVE YET IF GOT HERE FASTEST WAY + TLC A,(SETZ) + TLC B,(SETZ) + EXCH A,E + EXCH B,W + CAMLE A,E + JRST QSKDP4 ;ORDER OK + CAMN A,E + CAMGE B,W + MOVNI J,1 ;NEED SORT + JRST QSKDP4 + +QSKDP8: ADDI I,LUNBLK ;I POINTED TO EMPTY SLOT + MOVE D,I + SUBI D,(TT) + EXCH D,UDNAMP(TT) + ADDI D,(TT) + CAML D,I + JRST QSKDPV + SETZM (D) ;CLEAR VACATED AREA + HRLS D + ADDI D,1 + BLT D,-1(I) +QSKDPV: JUMPL J,QSKDPS ;SORT + TRNN J,-1 + JRST QSKDPK +QSKDPX: MOVE I,QACTB + IORM I,QSNLCN(H) +QSKDPK: MOVE W,QSNLCN(H) +IFN QRSRVP,[ + HLRZ A,UDALLO(W) ;IF THIS DIR HAS ALLOCATION + JUMPE A,QSKBK0 + MOVEI B,NQS-1 ;CONVERT PACK # TO DRIVE # + CAME A,QPKID(B) + SOJGE B,.-1 + SKIPGE A,B +QSKBK0: SETO A, ;ALLOCATED PACK NOT MOUNTED, USE ANY + MOVEM A,QSALLO(H) ;SAVE DRIVE # (-1 IF NONE) +];QRSRVP + HLLZS UDBLKS(W) + MOVE A,UDNAMP(W) + ADDI A,(W) +QSKBK1: CAIL A,2000(W) ;COUNT BLOCKS USED + JRST QSKBK2 + MOVE B,UNRNDM(A) + TLNE B,UNLINK + JRST QSKBK3 + LDB B,[UNDSCP+UNRNDM(A)] + IDIVI B,UFDBPW + HLL B,QBTBLI(C) + ADDI B,UDDESC(W) ;B GETS BYTE PNTR TO DESC +QSKBK4: ILDB C,B + JUMPE C,QSKBK3 + CAIN C,UDWPH + JRST QSKBK4 + CAIG C,UDTKMX + JRST [ADDM C,UDBLKS(W) ? JRST QSKBK4] + CAIG C,UDWPH + JRST [AOS UDBLKS(W) ? JRST QSKBK4] + REPEAT NXLBYT, IBP B + AOS UDBLKS(W) + JRST QSKBK4 + +QSKBK3: ADDI A,LUNBLK + JRST QSKBK1 + +QSKBK2: POP P,W + POP P,I + POP P,D + POP P,C + POP P,B + POP P,A + JRST QSKDP2 + +QSKDPS: MOVEI T,LUNBLK + ADD P,[3,,3] +QSKDPB: MOVEI Q,(I) ;BEGINNING OF NAME AREA + SKIPGE T + MOVEI Q,2000-LUNBLK(TT) ;START AT END + MOVEI W,2000(TT) + SKIPGE T + MOVEI W,-LUNBLK(I) + SETZM (P) + TDZA J,J ;0 => SORTED -1 => MAKE ANOTHER PASS +QSKDPE: ADD Q,T + CAIE Q,(W) + JRST QSKDPC + JUMPE J,QSKDPW + MOVNS T + JRST QSKDPB + +QSKDPW: SUB P,[3,,3] + JRST QSKDPX + +QSKDPC: SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + JRST QSKDPD + BUG + +QSKDPD: MOVE B,UNFN2(Q) + TLC A,(SETZ) + TLC B,(SETZ) + SKIPE E,(P) ;FIRST ENTRY + JRST QSKDPF +QSKDPG: MOVEM A,-2(P) + MOVEM B,-1(P) +QSKDPI: MOVEM Q,(P) + JRST QSKDPE + +QSKDPF: JUMPL T,QSKDPJ + CAMLE A,-2(P) + JRST QSKDPG + CAME A,-2(P) + JRST QSKDPH + CAML B,-1(P) + JRST QSKDPG +QSKDPH: REPEAT LUNBLK,[ + EXCH A,.RPCNT(E) + EXCH A,.RPCNT(Q) + EXCH A,.RPCNT(E) +] + MOVNI J,1 + JRST QSKDPI + +QSKDPJ: CAMGE A,-2(P) + JRST QSKDPG + CAME A,-2(P) + JRST QSKDPH + CAMG B,-1(P) + JRST QSKDPG + JRST QSKDPH + +SUBTTL OPEN FOR WRITE + +;RETURNS WITH QUSR(E) AND QSNLCN(E) ON LSWPR +QWRO2: JUMPE A,QPNL11 + JUMPE B,QPNL11 + SKIPGE I,EPDL(U) ;PICK UP DESIRED DISK UNIT + JRST QWRO2A ;SYSTEMS CHOICE +QWRO2B: CAIGE I,NQS + SKIPE QACT(I) + BUG ;WE LOST SOMEHOW... + MOVE TT,QTUTO(I) + SKIPL QDPWF(I) ;TUT IN BUT NOT PAWED OVER + TLNE TT,40000 ;TUT NOT IN + PUSHJ P,QTCH1 ;READ IN TUT OF DISK INVOLVED + PUSHJ P,QCHNF ;GET CHANNEL + PUSHJ P,LOSSET + QCHNRT + MOVE TT,[440700,,5] + TRNN D,3 + MOVEM TT,QSBYTE(E) ;UNIT ASCII MODE, BYTE SIZE=7 + PUSHJ P,QUDLK ;LOCK USER DIRECTORY + PUSHJ P,QGRLSC ;CHECK < AND > + JRST QPNLBN ;LOSE + PUSHJ P,QFNG ;REPLACE WITH COMPUTED EFFECTIVE NAME + PUSHJ P,QFREEF ;FIND FREE FILE NAME AREA AND STORE IN QDIRP(E) + JRST QFDF ;FILE DIR FULL + MOVSI TT,UNWRIT ;SET WRITE IN PROGRESS + IORM TT,UNRNDM(Q) + MOVE TT,QPKID(I) + DPB TT,[UNPKN+UNRNDM(Q)] + PUSHJ P,QAUTH ;SET FILE AUTHOR, MAY NOT PCLSR + MOVE TT,QACTB + IORM TT,QSNLCN(H) + SETOM QSCRW(E) ;SET CHNL WRITE SWITCH + POPJ P, + +QWRO2A: +IFN QRSRVP,[ + SKIPL I,QSALLO(H) + JRST QWRO2B ;THIS DIR GOES ON A PARTICULAR UNIT +] + SKIPGE I,QWRU ;GET CURRENT WRITING UNIT + JRST QWRO2E ;NO CURRENT UNIT, GO FIND ONE + MOVE TT,QSFT(I) + CAML TT,QFTTHR + JRST QWRO2B ;ENOUGH ROOM ON PREFERRED UNIT +QWRO2E: SETOB T,I ;NOT MUCH SPACE LEFT TRY OTHER UNITS + MOVSI E,-NQS +QWRO2C: SKIPGE QACT(E) ;SKIP ON UNIT ACTIVE + JRST QWRO2D +IFN QRSRVP,SKIPN QRESRV(E) ;DONT CHOOSE THIS PACK IF RESERVED + CAML T,QSFT(E) ;NOTE QSFT IS -1 IF TUT NEVER BEEN READ IN + JRST QWRO2D ;OTHERWISE CONTAINS VALID BLOCK COUNT + MOVE T,QSFT(E) + HRRZ I,E +QWRO2D: AOBJN E,QWRO2C + SKIPGE I + BUG ;NO ACTIVE UNRESERVED UNITS + CAMN I,QWRU + JRST QWRO2B ;DON'T WRITE MFD IF UNCHANGED + MOVEM I,QWRU + MOVE E,QACTB + IORB E,QMDRO + MOVEM I,MPDWDK(E) + JRST QWRO2B + +QWRO: JUMPN W,QWROR ;REALLY WANT TO MODIFY OR OTHERWISE HACK AN EXISTING FILE + PUSHJ P,QWRO2 ;MAKING NEW FILE, DECIDE WHICH UNIT TO PUT IT ON + SETOM QMFTP(E) ;TRACK TO SCAN IN TUT + SETOM QMTTR(E) + CLEARM QMPTN(E) + CLEARM QMPTC(E) + MOVEI TT,%QMWRT ;ENTER NORMAL WRITE MODE + HRRM TT,QSRAC(E) + MOVSI TT,%QARWT + TRNE D,%DORWT/2 + IORM TT,QSRAC(E) + JRST QOEX1 ;EXIT + + +SUBTTL File hacking tracking + +; MNGDIR checks the file name (sname in C) +; Fails to skip if the file is an important system file. +; Skips if the file is of the everyday sort. + +MNGDIR: HLRZ TT,C +IFN KL10P, CAME C,[SIXBIT /.KLFE./] + CAIN TT,'SYS ;A sys directory? + POPJ P, + CAME C,[SIXBIT /ACOUNT/] + CAMN C,[SIXBIT /./] + POPJ P, + CAME C,[SIXBIT /DEVICE/] + CAMN C,[SIXBIT /CHANNA/] + POPJ P, + AOS (P) ;Not a system directory. skip return. + POPJ P, + +; SYSDSK notifies the SYS job to print a message on the +; console about the file being hacked. +; File names in C;A B, the opcode in W (or zero) specifies the hacking. + +SYSDSK: JUMPE U,CPOPJ ;Avoid deadly embrace! + MOVSI T,SCLWRT ;Writing on SYS directory. + PUSHJ P,CWAIT ;Take turns like nice little lusers. + TDNE T,SUPCOR ;Wait for previous req to finish. + MOVE TT,W ;Check file operation code. + CAILE TT,4 ;If impossible opcode + SETZ TT, ; probably supposed to be R/W. + MOVEM TT,SWMOD ;Store opcode. + MOVE TT,UNAME(U) + MOVEM TT,SWUNAM ;Luser. + MOVE TT,JNAME(U) + MOVEM TT,SWJNAM + MOVEM A,SWFN1 + MOVEM B,SWFN2 + MOVEM C,SWFN3 ;Sname. + IORM T,SUPCOR ;Notify the SYS job. + JRST CLKONJ ;Turn on the clock and return. + + +SUBTTL DIRECTORY ROUTINES + +QFREEF: PUSH P,A ;Q_PTR TO USER DIR FREE FILE QDIRP(E)_PTR TO FREE DESC AREA + PUSH P,B ;GET FREE FILE AREA + PUSH P,I + MOVEI I,0 ;SIGNAL NO GC YET +QFREFA: SETZM QUDFPR(E) ;CLEAR SO WILL NOT POINT TO RANDOMNESS IN CASE OF G C + MOVE TT,QSNLCN(H) + SKIPL Q,UDESCP(TT) + CAIL Q,2000*UFDBPW + BUG ;FREE DESC POINTER OUT OF RANGE + IDIVI Q,UFDBPW + MOVE C,UDNAMP(TT) + CAIL Q,-UDDESC-7-LUNBLK(C) + JRST QAGARB ;NOT ENOUGH ROOM BETWEEN DESC AND NAME AREAS + PUSHJ P,QLGLK ;FIND WHERE FILE OUGHT TO GO + JRST QFREFF ;DIR WAS EMPTY + TRNN J,1777 + JRST QFREFE ;GOES AT END OF DIR +QFREFC: CAMN A,UNFN1(J) + CAME B,UNFN2(J) + JRST QFREFE + MOVE C,UNRNDM(J) + TLNE C,UNIGFL ;* FILES MUST COME AFTER NON * FILES + JRST QFREFE ;OF SAME NAME + ADDI J,LUNBLK + CAIGE J,2000(TT) + JRST QFREFC +QFREFE: CAMN Q,J + JRST QFREFF ;GOES AT BEGINNING + PUSHJ P,QINSRT + JRST QFREFD + +QFREFF: SUBI Q,LUNBLK ;Q -> NAME BLOCK FILE WILL GO IN +QFREFD: MOVNI T,LUNBLK ;ALLOCATE MORE SPACE FOR NAME AREA + ADDM T,UDNAMP(TT) + HRRZ A,UDESCP(TT) ;FIRST FREE DESCRIPTOR LOC + DPB A,[UNDSCP+UNRNDM(Q)];STORE IN FILE AREA + MOVEM A,QDIRP(E) ;STORE IN CHANNEL + MOVEI B,6*UFDBPW+1 ;ENOUGH FOR A LINK WITH EVERY CHAR QUOTED PLUS ONE ZERO + ADDM B,UDESCP(TT) ;ALLOCATE MORE SPACE FOR DESC AREA + MOVE B,Q + SUB B,QSNLCN(H) + HRRZM B,QUDFPR(E) ;ASSOCIATE CHANNEL WITH FILE + CONO PI,CLKOFF + SKIPL B,QDATE ;GET TIME AND DATE + HRR B,TIMOFF + CONO PI,CLKON + MOVEM B,UNDATE(Q) ;SET CREATION DATE + HLLM B,OLDRDT(E) + HLRS B + DPB B,[UNREFD+UNREF(Q)] ;SET REFERENCE DATE + IDIVI A,UFDBPW ;GET WRD AND CHAR ADRS + HLLZ B,QBTBLI(B) + ADDI B,UDDESC(A) + HRRZ A,QSNLCN(H) + ADD B,A + ILDB A,B + SKIPE A + BUG ;DESCRIPTOR AREA ALREADY OCCUPIED + MOVEI A,UDWPH + DPB A,B + ILDB A,B + SKIPE A + BUG ;NOT FOLLOWED BY ZERO + POP P,I + POP P,B + POP P,A + MOVEM A,UNFN1(Q) ;SET FILE NAMES + MOVEM B,UNFN2(Q) + JRST POPJ1 + +QAGARB: JUMPL I,QNOFRE ;IF GC WAS ALREADY TRIED, DON'T TRY IT AGAIN - GIVE UP. + PUSHJ P,QGC ;GC. BTW, IT IS OK TO PCLSR HERE. + JFCL + MOVNI I,1 ;SIGNAL GC HAS BEEN TRIED + JRST QFREFA + +;MAKE ROOM FOR FILE BEFORE J. Q POINTS TO NEW EMPTY FILE SLOT +QINSRT: PUSH P,A + PUSH P,TT + HRRZ TT,QSNLCN(H) + HRRZ A,UDNAMP(TT) + PUSH P,A + ADDI A,(TT) + HRLS A + SUBI A,LUNBLK + BLT A,-LUNBLK-1(J) + SETZM -LUNBLK(J) + HRRZI A,-LUNBLK+1(J) + HRLI A,-LUNBLK(J) + BLT A,-1(J) + SUB J,QSNLCN(H) + MOVSI A,-NQCHN +QINSR1: HRRZ TT,QUDPR(A) + SKIPL QUSR(A) + CAIE TT,(H) + JRST QINSR2 + MOVE TT,QUDFPR(A) + CAMGE TT,(P) + JRST QINSR2 + CAIGE TT,(J) + SUBI TT,LUNBLK + MOVEM TT,QUDFPR(A) +QINSR2: AOBJN A,QINSR1 + ADD J,QSNLCN(H) + HRRZI Q,-LUNBLK(J) + SUB P,[1,,1] + POP P,TT + POP P,A + POPJ P, + +;DIR NOT IN CORE. GET IT FROM DISK, CREATE IT IF DOESN'T ALREADY +; EXIST, OR GIVE NO SUCH DIRECTORY ERROR. +;C HAS SNAME. RETURNS DIRECTORY NUMBER IN H. + +QSKO1: PUSHJ P,SWTL + QSKOSW ;PREVENT TIMING ERROR IF TWO PCS SHOULD + PUSHJ P,QFLD ; ATTEMPT TO BRING IN SAME DIRECTORY + JRST QSKO11 + MOVEI T,2 ;SOMEONE ELSE BROUGHT IT IN, RELEASE QSKOSW + JRST LSWPON ;BUT LEAVE QSNNR(H) LOCKED. + +QSKO11: PUSH P,J + PUSH P,I + PUSHJ P,QFL ;LOOK UP DIR IN MFD, RET TRACK IN J + JRST QSKON ;NON EXISTENT + PUSHJ P,QFLDF ;FIND FREE LOSER DIR SLOT + MOVE I,MDSK + PUSHJ P,QCHNF ;FIND FREE CHNL (TO READ IN DIR) + MOVEM C,QSNUD(H) ;SET USER NAME IN DIR SLOT + MOVEM J,QSLGL(E) ;REQUEST READ IN OF USER DIR FROM TRACK IN J + MOVEI TT,%QMUDR + MOVEM TT,QSRAC(E) +QSKON1: MOVEI T,2 + PUSHJ P,LSWPON ;RELEASE QSKOSW, LEAVE SOSSET OF QSNNR(H) + POP P,I ;GO AWAY WILL HANG UP WAITING IN QUDLK + POP P,J ;DIR IS LOCKED BUT NOT ON LSWPR, PI WILL UNLOCK AFTER READIN + JRST QSTRTR + +QNOFRE: POP P,I ;NO FREE FILES AVAIL + JRST POPBAJ + +QPNL24: PUSHJ P,OPNL24 + JRST URET + +QPNL20: PUSHJ P,OPNL20 + SKIPE QLD(U) + PUSHJ P,OPNL47 ;FOUND LINK, BUT IT POINTS TO NON-EXISTENT DIRECTORY + JRST URET + +AUTOCR: ;AUTOMATICALLY CREATED DIRECTORIES +IFN TPLP+UNSPLP,SIXBIT /.LPTR./ ;FOR TPL SPOOLING + SIXBIT /.MSGS./ ;FOR MESSAGES TO ALL LOSERS + SIXBIT /.MAIL./ ; Programs like to write mail here + SIXBIT /CRASH/ ; Programs like to dump themselves here + SIXBIT /.TEMP./ ; Programs like to write randomness here +NATOCR==.-AUTOCR + +QSKON: JUMPE C,QPNL20 ;DON'T ALLOW ZERO USER NAME + PUSH P,TT + MOVSI TT,-NATOCR +QSKONA: CAMN C,AUTOCR(TT) + JRST QSKONB + AOBJN TT,QSKONA + CAMN A,[SIXBIT /..NEW./] + CAME B,[SIXBIT /(UDIR)/] + JRST [POP P,TT + JRST QPNL20] + BUG INFO,[DSK: DIR ],SIXBIT,C,[CREATED BY ],SIXBIT,UNAME(U),SIXBIT,JNAME(U) +QSKONB: POP P,TT + SKIPG NQFUS + JRST QPNL24 ;NO MFD SLOTS AVAILABLE + PUSH P,A + PUSH P,B + PUSH P,C +QSKONE: PUSHJ P,QFLDF ;FIND FREE DIR SLOT + PUSHJ P,QMLOCK + PUSHJ P,TCALL + JRST IOMQ + JRST [PUSHJ P,LSWPOP ;QMDRO + PUSHJ P,LSWPOP ;QSNNR + PUSHJ P,UDELAY ;HOPEFULLY MEMORY WILL APPEAR SHORTLY + JRST QSKONE] + MOVEM C,QSNUD(H) + SOS NQFUS ;NO TIMING ERR DUE TO QSKOSW + MOVEI J,MU23UD + DPB J,[MUR,,MEMBLT(A)] + DPB H,[MNUMB,,MEMBLT(A)] + LSH A,10. + HRRM A,QSNLCN(H) + SETZM (A) + HRLS A + AOS B,A + BLT A,2000-2(B) + MOVEI A,2000 + MOVEM A,UDNAMP-1(B) + MOVE A,QSNUD(H) + MOVEM A,UDNAME-1(B) + MOVE B,QACTB ;NOW PUT UFD INTO MFD + IORB B,QMDRO + MOVE TT,MDNAMP(B) ;LOOK FOR A FREE SLOT + ADDI TT,(B) +QSKONC: TRNN TT,1777 + JRST QSKOND + SKIPN MNUNAM(TT) + JRST QSKONF + ADDI TT,LMNBLK + JRST QSKONC + +QSKONF: SUBI TT,(B) + JRST QSKONG + +QSKOND: MOVNI TT,LMNBLK ;NO FREE SLOTS, SO EXTEND DOWNWARD + ADDB TT,MDNAMP(B) +QSKONG: ADDI B,(TT) + MOVEM A,MNUNAM(B) + SUBI TT,2000-2*NUDSL ;GET DISK BLOCK NUMBER +IFN KA10P, SKIPGE TT +IFE KA10P, CAIGE TT,2 ; Don't clobber 'HOM' blocks + BUG ;TOO MANY UFDS (NQFUS CHECK DIDN'T WORK) + LSH TT,-1 + MOVEM TT,QSNMI(H) + MOVE TT,QACTB ;UNLOCK UFD AND CAUSE IT TO GET WRITTEN + HLLM TT,QSNLCN(H) + PUSHJ P,QMULK ;UNLOCK MFD + POP P,C + POP P,B + POP P,A + JRST QSKON1 + +SUBTTL MAKE LINK + +QALINK: MOVE I,MDSK ;ENTER WITH QSNNR ON LSWPR + MOVEM I,EPDL(U) + PUSHJ P,QWRO2 ;MAKES NEW FILE WITH MINIMUM OF 37 BYTES OF DESC SPACE + MOVSI A,UNLINK ; AND ADDS QUSR AND QSNLCN ON LSWPR + IORM A,UNRNDM(Q) ;SET LINK BIT + MOVE A,E ;QSK CHANNEL NUMBER + MOVE C,SRN5(U) ;SNAME LINKED TO + PUSHJ P,LDEP + PUSHJ P,QUDS + MOVE C,SRN3(U) ;FN1 LINKED TO + PUSHJ P,LDEP + PUSHJ P,QUDS + MOVE C,SRN4(U) ;FN2 LINKED TO + PUSHJ P,LDEP + JFCL + MOVE E,A ;QSK CHANNEL NUMBER FOR QCHNRT + MOVEI R,EPDL(U) ;DON'T CLOSE A REAL IOCHNM WORD + PUSHJ P,QSOCL4 ;CLOSE CHNL & FILE + PUSHJ P,LSWDEL ;DELETE QUSR, HAS BEEN SETOM'ED + PUSHJ P,LSWDEL ;DELETE QSNRR, HAS BEEN SOS'ED + JRST POPJ1 + +LDEP: MOVEI E,6 ;STORE SIXBIT FROM C INTO LINK DESC +LDEPL: MOVEI B,0 ;GET NEXT CHAR + LSHC B,6 + JUMPE B,LDEPS ;*THIS ALLOWS EMBEDDED BLANKS. + CAIE B,'; + CAIN B,': + JRST LDEPS +LDEPS2: MOVE D,B + PUSHJ P,QUDS + SOS E ;NUMBER OF CHARACTERS LEFT IN WORD + JUMPN C,LDEPL ;JUMP IF ANY MORE NON-BLANK CHARS TO STORE + MOVEI D,'; + JUMPE E,POPJ1 ;JUMP IF STORED 6 CHARACTERS + POPJ P, ;STORED FEWER, NEED TERMINATOR + +LDEPS: MOVEI D,': ;THIS CHAR NEEDS TO BE QUOTED + PUSHJ P,QUDS + JRST LDEPS2 + +;LINK ENCOUNTERED DURING LOOKUP + +QLINK: TRNE D,%DONLK/2 ;CHECK 3.5 BIT IN OPEN MODE + JRST QOLINK ;JUMP IF DON'T CHASE LINKS MODE + AOS A,QLD(U) + CAIL A,100. + JRST OPNL27 ;LINK DEPTH EXCEEDED + PUSH P,E ;SAVE XR NEEDED BY LSWPOP OF QUSR ENTRY + MOVE E,TT + IDIVI E,UFDBPW + ADD E,QSNLCN(H) + ADDI E,UDDESC + MOVE TT,QBTBLI(TT) + HRR TT,E + MOVE I,[440600,,A] + SETZB A,B + SETZ C, +QL1: ILDB J,TT + JUMPE J,QL3 ;END DESC + CAIN J,': + JRST QL4 ;QUOTE NEXT CHAR + CAIN J,'; + TLZA I,770000 ;TERMINATE THIS WORD +QL5: IDPB J,I + JRST QL1 + +QL4: ILDB J,TT ;GET CHAR THAT WAS QUOTED + JRST QL5 + +QL3: EXCH A,C ;END OF DESC REACHED + EXCH A,B ;MAKE A FN1 B FN2 C SNM + SKIPN C + MOVE C,USYSN1(U) + PUSHJ P,QUDULK ;UNLOCK DIR + POP P,E ;RESTORE XR USED BY LSWPOP OF QUSR ENTRY + PUSHJ P,LSWPOP ;QUSR ENTRY + PUSHJ P,LSWPOP ;QSNNR ENTRY + PUSHJ P,OPBRK ;IF TRYING TO BE PCLSRED, SUBMIT + JRST QSKOL + +QOLINK: MOVSI TT,%QALNK ;OPENING UP A LINK + IORM TT,QSRAC(E);DON'T ALLOW FILE-ONLY OPERATIONS SUCH AS IOT + JUMPL D,QWROR1 ;LEAVE RH(QSRAC)=%QMIDL SO PI LEVEL WON'T MESS WITH IT + JRST QOEX1 ;AND FINISH OPENING + +SUBTTL PAW OVER MFD + +QMCH1: CONO PI,UTCOFF + MOVE TT,QMDRO + TLNE TT,40000 + AOJE TT,QMCH2 ;NOT ON WAY IN +QMCH3: CONO PI,UTCON + SKIPGE QMDRO + PUSHJ P,UFLS + MOVSI E,2 + TDNN E,QMDRO + POPJ P, ;PAWED OVER + PUSHJ P,QMLOCK + ANDCAM E,QMDRO + HRRZ E,QMDRO + MOVE TT,MDCHK(E) + CAME TT,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] +QMCH1A: MOVEI E,2000-LMNBLK*NUDSL(E) +IFN KA10P, SETZM NQFUS +IFE KA10P,[ + MOVNI TT,2 ;PROTECT DEC 'HOM' BLOCKS SO KLDCP OR 8080 + MOVEM TT,NQFUS ; CAN FIND ITS CRUFT +] ;IFE KA10P +QMCH1E: LDB TT,[1200,,E] + JUMPE TT,QMULK + SKIPN (E) + AOS NQFUS + ADDI E,LMNBLK + JRST QMCH1E + +QMCH2: SOS QMDRO ;INDICATE ON WAY IN + CONO PI,UTCON + SKIPG QFCHN + BUG ;DON'T WANT TO WAIT FOR CHANNEL? + PUSHJ P,QCHNF + MOVEI TT,MFDBLK ;MFD TRACK + MOVEM TT,QSLGL(E) + MOVEI TT,%QMMDR + MOVEM TT,QSRAC(E) + PUSHJ P,QSTRTR + JRST QMCH3 + +SUBTTL PAW OVER TUT + +QTCH1: CONO PI,UTCOFF + MOVSI TT,200000 + TDNE TT,QTUTO(I) + JRST QTCH2 ;GO READ IT IN + CONO PI,UTCON +QTCH1A: PUSHJ P,QTLOCK ;TO MAKE SURE IT'S IN + AOSE QDPWF(I) + JRST QTULK ;ALREADY PAWED OVER + PUSH P,A + PUSH P,B + MOVE T,QTUTO(I) + MOVE E,QSWAPA(T) + IDIVI E,DECADE + SKIPE TT + ADDI E,1 + IMULI E,DECADE ;ROUND SWAPPING ALLOC TO MULTIPLE OF A DECADE + MOVEM E,QSWAPA(T) + PUSH P,D + PUSH P,E ;FIRST TRACK OF NON-SWAPPING (FILE) AREA + MOVE E,QTUTP(T) ;ROUND TUT POINTER TO MULTIPLE OF A DECADE + ADDI E,DECADE-1 + IDIVI E,DECADE + IMULI E,DECADE + CAMGE E,(P) ;KEEP IT WITHIN THE FILE AREA + MOVE E,(P) + MOVEM E,QTUTP(T) + MOVE E,QPKNUM(T) +IFN DC10P,[ + CAME E,QPKID(I) + BUG HALT,[PACK ID ],OCT,E,[IN TUT FOR UNIT ],DEC,I,[DIFFERS FROM HARDWARE PACK ID],OCT,QPKID(I) +] +IFE DC10P, MOVEM E,QPKID(I) + MOVE E,QPAKID(T) + MOVEM E,QPKNM(I) +IFN QRSRVP,[ + MOVE E,QTRSRV(T) + MOVEM E,QRESRV(I) +] +;DROPS THROUGH + ;DROPS IN + CLEARM QSFTS(I) ;FREE SPACE IN SWAPPING AREA + SETZB D,QSFT(I) + MOVE B,QTUTO(I) + HRLI B,(TUTBP) + ADDI B,LTIBLK +QTCH1D: ILDB A,B + JUMPN A,QTCH1F + CAML D,(P) + AOS QSFT(I) ;BLOCK IN NON-SWAPPING AREA + CAMGE D,(P) + AOS QSFTS(I) ;BLOCK IN SWAPPING AREA +QTCH1F: ADDI D,1 + CAMGE D,QLASTB(T) + JRST QTCH1D + SUB P,[1,,1] + POP P,D + POP P,B + POP P,A + JRST QTULK + +QTCH2: SETOM QDPWF(I) + ANDCAM TT,QTUTO(I) + CONO PI,UTCON + SKIPG QFCHN + BUG ;DON'T WANT TO WAIT FOR CHANNEL? + PUSHJ P,QCHNF + HRRZM I,QDSKN(E) + MOVEI TT,MFDBLK ;TELL PI LEVEL TO READ IT ALL IN + SUB TT,NTBL(I) + MOVEM TT,QSLGL(E) + LDB TT,[121000,,QTUTO(I)] + MOVEM TT,QSCABN(E) + MOVEI TT,%QMTTR + MOVEM TT,QSRAC(E) + PUSHJ P,QSTRTR + JRST QTCH1A + +;ROUTINE TO ACCESS TUT +;CALL WITH DISK UNIT NUMBER IN I, BLOCK NUMBER IN D +;RETURNS IN D AN LDB-STYLE POINTER TO THE TUT AND IN B THE BYTE +;THAT YOU WOULD GET BY LDB'ING THAT POINTER. +;CLOBBERS E +;CALLER MUST LOCK TUT + +TUTPNT: MOVE B,QTUTO(I) + CAML D,QFRSTB(B) + CAML D,QLASTB(B) + BUG ;BLOCK NUMBER NOT IN RANGE COVERED BY TUT + SUB D,QFRSTB(B) + IDIVI D,TUTEPW + ADDI D,LTIBLK(B) + HLL D,TBTBL(E) + LDB B,D + POPJ P, + +QSTRTR: +IFN DC10P,[ +QSTRT1: CONSO DC0,DSKCHN + SETOM QHUNGF ;SOMEONE PUSHED RESET BUTTON, RECOVER AT PI LEVEL + CONO DC0,DCSET+DCIENB+DSKCHN ;ENABLE IDLE INTERRUPT +] +IFN RP10P+RH10P+RH11P,[ + CONO PI,UTCOFF + PUSHJ P,QSTRT1 + CONO PI,UTCON +] + POPJ P, + +IFN RP10P+RH10P+RH11P,[ ;START DISK WITH UTC ALREADY OFF +QSTRT1: SETOM QGTBZY ;NOTE: TURNS UTC BACK ON BUT NOT CLOCK +IFN RP10P, CONSO DPC,20 ;ONLY IF DISK IDLE +IFN RH10P, CONSO DSK,%HIBSY +IFN RH11P, IORDQ TT,%HRCS1 +IFN RH11P, TRNE TT,%HXRDY + CONO PI,DSKRQ + POPJ P, +] + +;TRY TO FLUSH UNNEEDED UFDS FROM CORE. +;ARG IN C IS ROUTINE TO FREE THE MEMORY. +;CALL WITH UDRSW SIEZED, OR WITH PI 2 IN PROGRESS AND UDRSW NOT LOCKED BY ANYONE +;CLOBBERS H, TT. DOESN'T SKIP. +QDFLS: MOVSI H,-QNUD +QDFLS1: SKIPE QSNUD(H) + SKIPE QSNNR(H) +QDFLS2: AOBJN H,QDFLS1 ;CAN'T FLUSH IF SLOT NOT USED OR CHANNELS OPEN IN DIR + JUMPGE H,CPOPJ + MOVE TT,QACTB + TLO TT,600000 + TDNE TT,QSNLCN(H) + JRST QDFLS2 ;CAN'T FLUSH IF LOCKED OR NOT WRITTEN OUT + PUSHJ P,QDFCHK ;CHECK THAT NO POINTERS TO THIS DIRECTORY REMAIN + CLEARM QSNUD(H) ;FLUSH + AOS QFUD + PUSH P,A + HRRZ A,QSNLCN(H) + LSH A,-10. + PUSHJ P,(C) ;RETURN THE MEMORY + POP P,A + JRST QDFLS2 ;TRY FLUSHING SOME MORE + +;CALL WITH UFD SLOT# IN H, WHEN YOU THINK THAT UFD IS FREE. +QDFCHK: PUSH P,C + PUSH P,J + MOVSI C,-NQCHN +QDFCH1: SKIPGE QUSR(C) + AOBJN C,QDFCH1 + JUMPGE C,QDFCH2 + HRRZ J,QUDPR(C) + CAIN J,(H) + BUG ;IT WASN'T REALLY FREE, MAYBE QSNNR IS SCREWED UP? + AOBJN C,QDFCH1 +QDFCH2: POP P,J + POP P,C + POPJ P, + +;FIND A FREE UFD SLOT, RETURN INDEX IN H. PUTS QSNNR ON LSWPR. +;CLOBBERS T, TT. + +QFLDF: PUSHJ P,SWTL + UDRSW + MOVSI H,-QNUD + SKIPLE QFUD + JRST QFLDF1 + PUSH P,C ;ALL UFD SLOTS IN USE, TRY FLUSHING SOME + MOVEI C,MEMR + PUSHJ P,QDFLS + POP P,C + MOVSI H,-QNUD + SKIPLE QFUD + JRST QFLDF1 + PUSHJ P,LSWPOP ;UDRSW + PUSHJ P,UDELAY ;WAIT 1/2 SECOND THEN TRY AGAIN, INCLUDING QDFLS + JRST QFLDF + +QFLDF1: SKIPN QSNNR(H) ;SLOT ALREADY GOBBLED + SKIPE QSNUD(H) ;OR ALREADY OCCUPIED + AOBJN H,QFLDF1 ;MEANS CAN'T TAKE IT + SKIPL H + BUG ;NONE FREE, QFUD OUT OF PHASE WITH REALITY + HRRZS H + SOS QFUD + MOVSI TT,600000 ;DOUBLE LOCK + MOVEM TT,QSNLCN(H) + AOSG QSNNR(H) + BUG + PUSHJ P,LSWPOP ;UDRSW + PUSHJ P,LOSSET + QFLDRT + POPJ P, + +;LOSSET ROUTINE +QFLDRT: SKIPL A,AC0S+H(U) + CAIL A,QNUD + BUG ;H CLOBBERED + SOSGE T,QSNNR(A) + BUG + JUMPG T,CPOPJ ;HOW DID SOMEONE ELSE GET IT? + SKIPN QSNUD(A) + AOS QFUD ;READ-IN NEVER STARTED, SLOT BECOMES FREE + POPJ P, ;OK TO LEAVE 600000,, SET IN QSNLCN + +;C HAS DIR NAME. +;IF IN CORE, SET H TO UFD SLOT#, AOS QSNNR, PUT ON LSWPR, AND SKIP. +;IF DIRECTORY NOT IN CORE, NO SKIP. CLOBBERS T,TT. +QFLD: PUSHJ P,SWTL + UDRSW +QFLD1A: MOVSI H,-QNUD +QFLD1: CAME C,QSNUD(H) + AOBJN H,QFLD1 + JUMPGE H,LSWPOP ;JUMP ON FAILED TO FIND USER. +QFLD2A: AOSG QSNNR(H) + BUG ;MUST HAVE GOTTEN NEGATIVE SOMEHOW + PUSHJ P,LSWPOP ;UDRSW +; PUSHJ P,SOSSET +; QSNNR(H) +;THIS IS AN ATTEMPT TO FIND A BUG. + PUSH P,T + MOVEI T,QSNNR(H) + MOVEM T,IOTBTS(U) + PUSHJ P,LOSSET + [ SOSGE @IOTBTS(U) + BUG + POPJ P, ] + POP P,T +;END TEMPORARY CODE + JRST POPJ1 + +;C <=SYS NAME, RETURNS TRACK ADDR OF DIR IN J, SKIPS IF FINDS LOSER +QFL: PUSHJ P,QMLOCK + PUSHJ P,QFL0 + JRST QMULK + AOS (P) + JRST QMULK + +QFL0: PUSH P,Q + HRRZ Q,QMDRO + ADD Q,MDNAMP(Q) ;PTR TO USER AREA +QFL1: LDB J,[1200,,Q] + JUMPE J,QFL3 + CAMN C,MNUNAM(Q) + JRST QFL2 + ADDI Q,LMNBLK + JRST QFL1 + +QFL2: SUBI J,2000-LMNBLK*NUDSL ;J <= TRACK ADDR OF USER DIR + LSH J,-1 + AOS -1(P) ;SUCCESS +QFL3: POP P,Q + POPJ P, + +;ROUTINE TO ASSIGN A DISK CHANNEL. +;ARGS: U USER TO GO IN QUSR, H UFD SLOT# TO GO IN QUDPR, I DSK# TO GO IN QDSKN +;RETURNS QSK CHNL INDX IN E. +;DOESN'T DO A LOSSET OF QCHNRT, BUT CALLER MAY WANT TO. +;CLOBBERS T. NEVER SKIPS. + +QCHNF: PUSHJ P,SWTL ;PREVENT ANYONE ELSE FROM ALLOCATING CHANNELS + QCHSW + MOVSI E,-NQCHN + SKIPLE QFCHN + JRST QCH2 ;SOME CHANNELS ARE AVAILABLE, GO FIND ONE + PUSHJ P,LSWPOP ;QCHSW + SKIPG QFCHN + PUSHJ P,UFLS + JRST QCHNF + +QCH2: SKIPGE QSRAC(E) .SEE %QALOK + JRST QCH3 + SKIPGE QUSR(E) + JRST QCH1 +QCH3: AOBJN E,QCH2 + BUG ;WHERE DID THAT FREE CHANNEL GO? + +QCH1: HRRZS E ;CHANNEL ALLOCATED, INITIALIZE VARIABLES + HRRZM I,QDSKN(E) + SETOM QSCABN(E) + SETOM QSGL(E) + SETOM QSLGL(E) ;IN CASE OF WRITE-OVER ON 0-LENGTH FILE. + SETZM QBFP(E) + SETZM QSBFS(E) + CLEARM QSLBLK(E) + SETOM QSMDN(E) + SETZM QSCRW(E) + SETZM QSBI(E) + SETZM QSRAC(E) .SEE %QMIDL + CLEARM QFBLNO(E) + SETZM QSMPRC(E) + SETZM QSMPRP(E) + MOVE T,[444400,,1] ;ASSUME BYTES=WORDS, WILL BE FIXED LATER + MOVEM T,QSBYTE(E) + SETZM QPCLSR(E) + HRRZM H,QUDPR(E) + SETZM QUDFPR(E) ;NOT YET SET UP TO ANY PARTICULAR FILE + MOVEM U,QUSR(E) ;CHANNEL IS NOW IN-USE + SOSGE QFCHN + BUG + JRST LSWPOP ;QCHSW + +;LOSSET ROUTINE TO RETURN TENTATIVELY ASSIGNED QSK CHNL +;E HAD BETTER CONTAIN THE QSK CHANNEL NUMBER AT "ALL" TIMES +QCHNRT: SKIPL T,AC0S+E(U) + CAIL T,NQCHN + BUG ;E CLOBBERED + HRRZ A,U ;LSWPOP MESSES WITH LH(U) + CAME A,QUSR(T) + BUG + SETOM QUSR(T) + AOS QFCHN + POPJ P, + +SUBTTL DELETE, RENAME +;COME HERE FOR DELETE, OR RENAME NOT WHILE OPEN, ON DISK. + +QRNAM: SKIPN SRN3(U) + JRST QDEL + PUSH P,A + PUSH P,B + SKIPN B,SRN4(U) + JRST QPNL11 + MOVE A,SRN3(U) + PUSHJ P,MFDCK + JRST .+2 + JRST QPNL13 + PUSHJ P,FLDRCK + JRST .+2 + JRST QPNL13 + POP P,B + POP P,A + PUSH P,SRN3(U) + PUSH P,SRN4(U) + PUSHJ P,QUDLK + PUSHJ P,QLOOK + JRST [ SUB P,[2,,2] + JRST QROR1C ] ;GIVE FILE NOT FOUND OR FILE LOCKED + MOVE I,Q + POP P,B + POP P,A + PUSHJ P,QGRLSC + JRST QPNLBN ;FILE ALREADY EXISTS + PUSHJ P,QFNG +QRNAM4: PUSHJ P,QLOOK + JRST QRNAM3 + CAME I,Q ;ALLOW RENAME THAT DOESN'T CHANGE NAMES. + JRST QPNL13 +QRNAM3: MOVE Q,I + MOVSI TT,UNDUMP ;SAY FILE NOT DUMPED. + ANDCAM TT,UNRNDM(Q) + MOVNI E,1 ;TELL QFREF NOT TO CLOBBER NON-EX DISK CHNL. + PUSHJ P,QFREF ;"REFERENCE" FILE + PUSHJ P,QRELOC ;STORE NEW NAMES IN DIR +QRNAM2: MOVE TT,QACTB + IORM TT,QSNLCN(H) +QRNAM1: MOVE U,USER ;U MAY NOT HAVE USER IF CAME HERE FROM LOGOUT + PUSHJ P,LSWCLR + JRST POPJ1 + +QGRLSC: CAME A,[SIXBIT />/] ;SKIP NONE IF BOTH A+B ARE SPECIAL + CAMN A,[SIXBIT //] ;AND TWICE IF NEITHER + CAMN B,[SIXBIT / LOOK UP FILE TO DELETE +;Q .NE. 0 => DELETE FILE POINTED TO BY QUDFPR OF CHNL IN D +;H MUST HAVE DIR SLOT INDEX +QDELA: MOVEI Q,0 +QDLA1: PUSHJ P,SLUGH + QCHSW + 1000,,QSNLCN(H) + 1000,,QTUTO(I) + JUMPN Q,QDLA2 + PUSHJ P,QLOOK + JRST QDEL4A ;FNF + SETO D, ;NO ASSOCIATED CHANNEL +QDLA3: LDB A,[UNLNKB+UNRNDM(Q)] + LDB TT,[UNPKN+UNRNDM(Q)] + CAME TT,J + JUMPE A,QDELA1 ;ON DIFFERENT DISK (DIDN'T LOCK RIGHT TUT TRY AGAIN) + MOVE A,Q + SUB A,QSNLCN(H) + MOVSI J,-NQCHN +QDEL1: CAIN D,(J) + JRST QDEL2 ;IGNORE CHANNEL (IF ANY) WHOSE CLOSING CAUSED THIS + HRRZ TT,QUDPR(J) + SKIPL QSCRW(J) ;ONLY LOOK AT READ CHNLS + CAIE TT,(H) + JRST QDEL2 + HRRZ TT,QUDFPR(J) + SKIPL QUSR(J) + CAIE TT,(A) + JRST QDEL2 + MOVSI TT,%QADEL ;FOUND CHNL WITH THIS FILE OPEN + IORM TT,QSRAC(J) ;DELETE FILE WHEN THIS CHNL CLOSED + MOVSI TT,UNCDEL ;SET DELETED BIT + IORM TT,UNRNDM(Q) +QDEL4: MOVE TT,QACTB + IORM TT,QSNLCN(H) + MOVE TT,DCHBT(I) + IORM TT,QTUTO(I) +QDEL4B: PUSHJ P,QTULK + PUSHJ P,QUDULK + PUSHJ P,LSWPOP + JRST POPJ1 + +QDLA2: MOVE Q,QUDFPR(D) ;COMPUTE FILE ADR FROM CHNL IN D + ADD Q,QSNLCN(H) ;DIR MAY HAVE MOVED + JRST QDLA3 + +QDEL4A: SOS (P) + JRST QDEL4B + +QCDLWO: PUSH P,R ;OUTPUT CLOSE BUT FILE WAS DELEWO'ED + SETZM QSCRW(D) ;FAKE OUT ERROR CHECK AT QSQSH6 + PUSHJ P,QUDULK +QSICLD: MOVE H,QUDPR(D) ;ENTRY FROM INPUT CLOSE, FILE WAS DELETED + MOVE I,QDSKN(D) + PUSHJ P,QUDLK + MOVE Q,QSNLCN(H) + ADD Q,QUDFPR(D) + MOVE J,QPKID(I) + PUSHJ P,QUDULK + PUSH P,D + PUSHJ P,QDLA1 + BUG ;FILE ISNT THERE? + POP P,D + MOVE H,QUDPR(D) ;DIRECTORY NUMBER + SETOM QUSR(D) ;FREE THE DISK CHANNEL + AOS QFCHN + JRST QICLX + +QDELA1: PUSHJ P,QDEL4B ;NOT OUR DISK IN J + JFCL + MOVE J,TT ;DISK ITS REALLY ON +QDELA2: MOVSI I,-NQS ;TRANSLATE PACK # IN J TO DRIVE # IN I + CAME J,QPKID(I) + AOBJN I,.-1 + JUMPGE I,QPKNF1 + JRST QDELA + +QSOCLD: PUSH P,D ;DELETE FILE WHEN CLOSING OVER IT + PUSH P,R + LDB J,[UNPKN+UNRNDM(Q)] + PUSHJ P,QUDULK + PUSHJ P,QDELA2 + JFCL +QPKNF7: POP P,R + POP P,D + POPJ P, + +QPKNF1: PUSHJ P,QPKNFP ;MAYBE TUT NOT IN YET? + JRST QDELA2 ;YUP, TRY AGAIN + PUSHJ P,QUDLK + PUSHJ P,QLOOK + JRST QUDULK ;GONE AWAY BETWEEN LOCKS + JRST QDFPK ;GO DELETE OFF OF NON-MOUNTED PACK + +QDL2: PUSHJ P,QTULK ;DELETE LINK + MOVEI T,2 + PUSHJ P,LSWPON ;UNLOCK QCHSW +QDLINK: LDB E,[UNDSCP+UNRNDM(Q)] + IDIVI E,UFDBPW + ADD E,QSNLCN(H) + ADDI E,UDDESC + HLL E,QBTBLI(TT) + ILDB A,E + SKIPN E + BUG ;NULL LINK? + MOVEI B,0 +QDL1: DPB B,E ;CLEAR OUT THE CHAR + CAIN A,': + IDPB B,E ;CLEAR A QUOTED CHAR WITHOUT LOOKING AT IT + ILDB A,E + JUMPN A,QDL1 + PUSHJ P,QSQSH ;REMOVE ENTRY + MOVE TT,QACTB + IORM TT,QSNLCN(H) + PUSHJ P,QUDULK + JRST POPJ1 + +QDEL2: AOBJN J,QDEL1 ;CHECK NEXT DISK CHANNEL + MOVE C,UNRNDM(Q) ;NOT OPEN, SO REALLY DELETE IT + TLNE C,UNLINK + JRST QDL2 + ANDI C,.BM UNDSCP + IDIVI C,UFDBPW + ADD C,QSNLCN(H) + ADDI C,UDDESC + HLL C,QBTBLI(D) ;GET DESCRIPTOR POINTER IN C AND TT + MOVE TT,C + MOVEI A,0 + PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE + PUSH P,A + SKIPN D,QSFBT(H) ;SEE IF ENOUGH QSFBT STORAGE EXISTS + JRST QDEL11 +QDEL10: HLRE B,(D) ;NUMBER OF FREE LOCATIONS IN THIS PAGE + ADD A,B ;DECREASE LOCATIONS NEEDED + MOVE D,1(D) ;CDR + JUMPN D,QDEL10 +QDEL11: JUMPLE A,QDEL12 ;JUMP IF SUFFICIENT STORAGE EXISTS + PUSHJ P,TCALL ;GET MORE + JRST IOMQ + JRST [ MOVE U,USER ;U MAY NOT HAVE USER IF CAME FROM LOGOUT + PUSHJ P,LSWCLR ;HAVE TO WAIT FOR MEMORY + PUSHJ P,MQTEST ;AVOID DEADLOCKS BY UNLOCKING EVERYTHING + PUSHJ P,UFLS + JRST UUOTRO ] + MOVEI D,MU23FB + DPB D,[MUR,,MEMBLT(A)] + LSH A,10. + MOVEI D,2(A) + HRLI D,-1776 + MOVEM D,(A) + MOVE D,A + EXCH A,QSFBT(H) ;ADD TO FRONT OF LIST + MOVEM A,1(D) + MOVE A,(P) ;GET BACK NUMBER OF BLOCKS NEEDED + JRST QDEL10 ;SEE IF THERE ARE ENOUGH NOW + +QDEL12: POP P,A ;GET RID OF BLOCKS COUNT + PUSHJ P,QSQSH ;REMOVE ENTRY, CANNOT PCLSR AFTER THIS + CLEARB J,D ;J GETS NUMERIC TRACK NUMBER, D BYTE POINTER TO TUT + MOVE TT,QTUTO(I) ;D ZERO SO WILL HALT IF DESC DOESN'T START WITH LOAD-ADDR! + MOVE Q,QSFBT(H) ;Q -> AOBJN POINTER FOR STORING BLOCK NUMBERS +QDEL3: ILDB B,C ; INTO QSFBT AS DESCRIPTORS ARE ZEROED OUT + MOVEI A,0 ;I DISK, C BP TO DESCRIPTOR, A,B,E TEMP. + DPB A,C + JUMPE B,QDEL4 ;END OF FILE DESCRIPTION + TRNE B,40 + JRST QDEL6 + CAILE B,UDTKMX + JRST QDEL7 +QDEL8: SKIPN Q + BUG ;OOPS, OUT OF QSFBT STORAGE + SKIPL E,(Q) ;PICK UP AOBJN POINTER + JRST [ MOVE Q,1(Q) ;THIS PAGE FULL, TRY NEXT + JRST QDEL8 ] + MOVEM J,(E) ;STORE DISK,,BLOCK FOR LATER FREEING + AOBJN E,.+1 + MOVEM E,(Q) ;INCREMENT POINTER + MOVE E,QSNLCN(H) ;DECREASE DIR'S BLOCKS-USED + HRRZ A,UDBLKS(E) + SOSL A + HRRM A,UDBLKS(E) + ILDB A,D ;CHECK TUT + SKIPN A + BUG ;TUT SHOWS TRACK NOT USED + AOS J ;DO NEXT BLOCK IN CONTIGUOUS GROUP + SOJG B,QDEL8 + JRST QDEL3 + +IFN NXLBYT-2, .ERR THIS ROUTINE AND OTHERS KNOW IMPLICITLY THAT NXLBYT=2 +QDEL6: MOVEI D,0 ;LOAD ADDRESS + DPB B,[140500,,D] + ILDB B,C + DPB B,[060600,,D] + DPB A,C ;A HAS ZERO FROM QDEL3 + ILDB B,C + DPB B,[0600,,D] + DPB A,C + MOVE J,D + HRL J,I + PUSHJ P,TUTPNT + ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER + JRST QDEL7A + +QDEL7: CAIN B,UDWPH + JRST QDEL3 + SUBI B,UDTKMX + ADD J,B + IBP D + SOJG B,.-1 +QDEL7A: MOVEI B,1 ;LOAD ADDRESS OR SKIP AND TAKE, SO ONLY ONE TRACK + JRST QDEL8 + +QDFNF: PUSHJ P,OPNL4 + JRST URET + +QDELB: CONO PI,UTCON + JRST QDELA + +;PERFORM BLOCK-FREEING SPECIFIED BY QFBTS +QDLFBT: CONO PI,UTCOFF ;PROTECT QFBTS + SKIPN B,QFBTS + JRST UTCONJ + MOVE T,1(B) + MOVEM T,QFBTS + CONO PI,UTCON + HRRZ T,(B) ;FIRST FREE LOCATION + SUBI T,2(B) ;NUMBER OF LOCATIONS TO DO + HRLO A,T + EQVI A,1(B) + AOBJP A,QDLFB9 ;A NOW -> BLOCKS TO FREE, & CHECK FOR EMPTY + SETO I, ;NO TUT LOCKED YET +QDLFB1: HLRZ J,(A) ;DISK NUMBER + CAMN J,I ;MAKE SURE RIGHT TUT IS LOCKED + JRST QDLFB2 + SKIPL I + PUSHJ P,QTULK + MOVE I,J + PUSHJ P,QTLOCK +QDLFB2: HRRZ D,(A) ;BLOCK NUMBER TO FREE + PUSHJ P,TUTPNT + CAIGE B,TUTMNY ;USED IN "MANY" FILES(1,2,...,TUTMNY,TUTLK) + SOJL B,[JRST 4,.] ;HALT IF TUT SHOWS TRACK NOT USED + JUMPN B,QDLFB3 ;NOT LAST USE + HRRZ T,(A) ;BLOCK NUMBER AGAIN + MOVE TT,QTUTO(I) + CAML T,QSWAPA(TT) + AOSA QSFT(I) + AOS QSFTS(I) ;TRACK IN SWAPPING AREA +QDLFB3: DPB B,D ;DECREASE USAGE COUNT IN TUT + AOBJN A,QDLFB1 + PUSHJ P,QTULK +QDLFB9: MOVEI A,-1(A) ;GET AN ADDRESS ON THAT PAGE + LSH A,-10. ;DONE WITH THIS PAGE, FREE IT + PUSHJ P,TMEMR ;RETURN PAGE TO FREE AND TRY FOR MORE + MU23FB + JRST QDLFBT + +;REMOVE HOLE FROM NAME AREA AT Q +QSQSH: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,TT + HRRZ TT,QSNLCN(H) + MOVE A,UDNAMP(TT) + CAILE A,2000 + BUG ;UDNAMP BAD + ADDI A,(TT) + HRRZ C,Q + SUB C,A + SKIPL C + CAIL C,2000-UDDESC + BUG ;Q BAD + HRRZ C,Q +QSQSH1: SUBI C,LUNBLK + CAMLE A,C + JRST QSQSH2 + HRLZ B,C + HRRI B,LUNBLK(C) + BLT B,2*LUNBLK-1(C) + JRST QSQSH1 + +QSQSH2: +REPEAT LUNBLK,SETZM .RPCNT(A) + SUBI A,-LUNBLK(TT) + HRRZM A,UDNAMP(TT) + HRRZ C,Q + SUBI C,(TT) ;INDEX OF DELETED FILE + HRRZI TT,-LUNBLK(A) ;INDEX OF OLD BEGINNING OF NAME AREA + MOVSI A,-NQCHN +QSQSH3: HRRZ B,QUDPR(A) + SKIPL QUSR(A) + CAIE B,(H) + JRST QSQSH4 + SKIPN B,QUDFPR(A) + JRST QSQSH4 + CAIGE B,(TT) + BUG + CAIN B,(C) + JRST QSQSH6 ;PNTR TO FLUSHED HOLE, CHECK IF READ CHNL + CAIG B,(C) ;IF AFTER DELETED FILE DON'T RELOCATE + ADDI B,LUNBLK + HRRZM B,QUDFPR(A) + SKIPL QSCRW(A) + JRST QSQSH4 ;READ CHNL + ADD B,QSNLCN(H) + MOVE B,UNRNDM(B) + TLNN B,UNWRIT + BUG ;CHNL WRITING BUT BEING WRITTEN BIT NOT SET +QSQSH4: AOBJN A,QSQSH3 + POP P,TT + POP P,C + POP P,B + POP P,A + POPJ P, + +QSQSH6: MOVE B,QSRAC(A) ;FOUND PNTR TO DELETED FILE + TLNE B,%QADEL ;SKIP IF NOT DELETE AFTER CLOSE + SKIPGE QSCRW(A) ;ALSO ERROR IF NOT READ CHNL + BUG + JRST QSQSH4 ;WAS DELETE AFTER CLOSE ON READ CHNL + +SUBTTL DIRECTORY LOOK UP, > FEATURE + +;A contains the FN1 and B contains the FN2. +;H is the index of the directory slot. The dir must be locked. + +;Returns the address of the filename block in Q. +;Clobbers C. + +;Internally, J and Q point to the bottom and top of the +;area of the dir we are still searching. +;Bit 4.9 of J is set to indicate one of the names is ">". +;C used as a flag: sign bit says creating a file. +;Bit 1.1 of C says FN2 is > or <. + +;Look for place to create new file, +;and generate new version for >. +QFNG: MOVEM Q,EPDL3(U) + SKIPA C,[SETZ] +;Look for existing files only +QLOOK: MOVEI C,0 + PUSH P,J + HRRZ J,QSNLCN(H) + MOVEI Q,2000-LUNBLK(J) + ADD J,UDNAMP(J) + CAMN A,[SIXBIT />/] + TLOA J,400000 + CAMN A,[SIXBIT / + CAMN B,[SIXBIT />/] + TLOA J,400000 + CAMN B,[SIXBIT //] + JRST POPJJ ;MUST BE READ RETN FILE NOT FOUND +QLOOK1: JUMPGE C,QLOOK9 + CAMN B,[SIXBIT /" +QLOOK9: PUSH P,D + PUSH P,TT + PUSH P,I + PUSH P,[-1] ;BEST INDEX + PUSH P,[SETZ] ;BEST "NUMERIC" PART + PUSH P,[SETZ] ;BEST ALPHA PART +QLOOK4: CAIGE Q,(J) + JRST QLOOK2 + XCT QLKI1(C) + JRST QLOOK3 + MOVE D,UNRNDM(Q) + TLNE D,UNIGFL + JUMPGE C,[ SKIPGE -2(P) ;FILE LOCKED, REMEMBER IT IF WE HAVE NO BETTER, + HRRM Q,-2(P) ; BUT DON'T CONSIDER IT IF READING + JRST QLOOK3 ] ;BUT IF WRITING, CONSIDER ALL FILES + SKIPE TT,@QLKI1+1(C) +QLOOK6: TRNE TT,77 ;RIGHT ADJ + JRST QLOOK5 + LSH TT,-6 + JRST QLOOK6 + +QLOOK5: MOVEI I,0 +QLOOK8: LDB D,[600,,TT] + CAIL D,'0 + CAILE D,'9 + JRST QLOOK7 ;NOT A DIGIT +QLOK5B: TRNE I,77 ;RIGHT ADJ LOW NON NUM PART + JRST QLOK5A + LSH I,-6 + JUMPN I,QLOK5B +QLOK5A: TLC TT,400000 ;AVOID CAM LOSSAGE + TLC I,400000 + SKIPGE -2(P) + JRST QLOK5D ;FIRST MATCH + JUMPGE J,QLOK5E ;GET LEAST + CAMGE TT,-1(P) ;GET GREATEST + JRST QLOOK3 + CAME TT,-1(P) + JRST QLOK5D + CAMGE I,(P) + JRST QLOOK3 ;NOT AS GOOD +QLOK5D: HRRZM Q,-2(P) + MOVEM TT,-1(P) + MOVEM I,(P) +QLOOK3: SUBI Q,LUNBLK + JRST QLOOK4 + +QLOK5E: CAMLE TT,-1(P) + JRST QLOOK3 + CAME TT,-1(P) + JRST QLOK5D + CAMLE I,(P) + JRST QLOOK3 + JRST QLOK5D + +QLOOK7: LSHC TT,-6 ;LOW DIGIT NOT NUMERIC + JUMPN TT,QLOOK8 ;NO NUMERIC DIGITS AT ALL ("BIN", MAYBE?) + JUMPL J,QLOK5B ;IF LOOKING FOR GREATEST, LET THIS BE LEAST + MOVNI TT,1 ;GREATEST IF LOOKING FOR LEAST + JRST QLOK5B + +QLOOK2: JUMPL C,QFNG1 ;REALLY WANT TO MAKE F.N.'S FOR WRITE + SUB P,[1,,1] + POP P,C ;BEST "NUMERIC" PART + POP P,Q ;ADR + POP P,I + POP P,TT + POP P,D + AOJE Q,POPJJ + MOVE A,UNFN1-1(Q) ;ACTUAL MATCHED FILE NAMES + MOVE B,UNFN2-1(Q) + SOJGE Q,POPJJ1 ;FOUND A FILE THAT WASN'T LOCKED + MOVEI Q,-LUNBLK(Q) + JRST POPJJ + +QFNG1: SKIPGE -2(P) + JRST QFNG2 ;NOT FOUND START W/ 1 + MOVE TT,-1(P) + TLC TT,400000 + MOVE I,[600,,TT] +QFNG3: LDB D,I + CAIL D,'0 + CAILE D,'9 + JRST QFNG4 ;REACH END OF NUMERIC FIELD + AOS D + CAILE D,'9 + JRST QFNG5 + DPB D,I +QFNG5A: TLNE TT,770000 + JRST QFNG3A + LSH TT,6 + JRST QFNG5A + +QFNG2: MOVSI TT,(SIXBIT /1/) +QFNG3A: MOVEM TT,A(C) ;STORE INTO A OR B AS APPRO + SUB P,[3,,3] + POP P,I + POP P,TT + POP P,D + MOVE Q,EPDL3(U) + JRST POPJJ + +QFNG5: MOVEI D,'0 + DPB D,I + ADD I,[60000,,] + JUMPL I,QFNG5A + JRST QFNG3 + +QFNG4: TLNN TT,770000 ;SKIP ON ALREADY 6 CHAR NAME + LSH TT,6 + MOVEI D,'1 + DPB D,I + MOVEI D,'0 +QFNG4B: TLNN I,770000 + JRST QFNG5A + IDPB D,I + JRST QFNG4B + +QLKI1: CAME B,UNFN2(Q) + CAME A,UNFN1(Q) + UNFN2(Q) + +QPKNF: MOVE C,QSNUD(H) + PUSHJ P,QUDULK ;UNLOCK DIR + PUSHJ P,LSWPOP ;QUSR ENTRY + PUSHJ P,LSWPOP ;QSNNR ENTRY + PUSHJ P,QPKNFP + JRST QSKOL + PUSHJ P,OPNL16 ;PACK NOT MOUNTED + JRST URET + +QPKNFP: MOVSI I,-NQS +QPKNF3: SKIPGE QACT(I) + JRST QPKNF4 + MOVE TT,QTUTO(I) + SKIPL QDPWF(I) + TLNE TT,40000 + JRST QPKNF2 ;PACK NOT IN OR NOT PAWED OVER +QPKNF4: AOBJN I,QPKNF3 + JRST POPJ1 + +QPKNF2: JRST QTCH1 ;MAYBE THIS UNIT HAS GOODIES + +QFDF: PUSHJ P,OPNL5 ;FILE DIR FULL ON WRITE + JRST URET + +QPNL13: PUSHJ P,OPNL13 + JRST URET + +QPNL22: PUSHJ P,OPNL22 + JRST URET + +QPNLBN: +QPNL11: PUSHJ P,OPNL11 + JRST URET + +;ROUTINE TO FIND PLACE IN DIRECTORY WHERE A B WOULD GO +;SKIPS ONLY IF DIRECTORY CONTAINS AT LEAST ONE FILE +;FOR INSERTION, FILE GOES BEFORE PNTR RETURNED IN J +;RETURNS PNTR IN Q TO BEGINNING OF NAME AREA +;(ONLY WORKS FOR LUNBLK = 5) +QLGLK: HRRZ J,QSNLCN(H) + HRRZ Q,UDNAMP(J) + ADDI Q,(J) + CAIL Q,2000(J) + POPJ P, ;DIRECTORY EMPTY + TLC A,(SETZ) + TLC B,(SETZ) + PUSH P,D + PUSH P,E + ADDI J,600 ;128. NAME BLOCKS FROM END +REPEAT 7,[ ;THIS CODE DELIBERATELY NOT INDENTED. NEED 4 DIMENSIONS. + CAMGE J,Q + JRST .+6 + MOVE D,UNFN1(J) + TLC D,(SETZ) + CAMN A,D + JSP E,QLGLE + CAML A,D + ADDI J,<1_<7-.RPCNT>>*LUNBLK + SUBI J,<1_<6-.RPCNT>>*LUNBLK +] + CAMGE J,Q + ADDI J,LUNBLK + CAMGE J,Q + BUG + MOVE D,UNFN1(J) + TLC D,(SETZ) + CAME A,D + JRST QLGL1 + MOVE D,UNFN2(J) + TLC D,(SETZ) + CAMLE B,D +QLGL2: ADDI J,LUNBLK +QLGL3: TLC A,(SETZ) + TLC B,(SETZ) + POP P,E + POP P,D + JRST POPJ1 + +QLGL1: CAML A,D + JRST QLGL2 + JRST QLGL3 + +;CALL BY JSP E,QLGLE +QLGLE: MOVE D,UNFN2(J) + TLC D,(SETZ) + CAMN B,D + JRST QLGL3 + CAML B,D + JRST 1(E) + JRST 2(E) + +SUBTTL LOCKING ROUTINES + +QMLOCK: PUSHJ P,LSWTL + QMDRO + POPJ P, + +QMULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QMDRO + BUG + POP P,U + JRST LSWPOP + +QTLOCK: PUSHJ P,LSWTL + QTUTO(I) + POPJ P, + +QTULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QTUTO(I) + BUG + POP P,U + JRST LSWPOP + +QUDLK: PUSHJ P,LSWTL + QSNLCN(H) + POPJ P, + +QUDULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QSNLCN(H) + BUG + POP P,U + JRST LSWPOP + +SBTBLI: +QBTBLI: 440600,, ;IF GOING TO ILDB +SBTBL: +QBTBL: 360600,, + 300600,, + 220600,, + 140600,, + 060600,, + 000600,, + +TBTBL=.+1 +TBTBLI: REPEAT 1+TUTEPW, TUTBP-<.RPCNT*TUTBYT*010000,,> + +SUBTTL DIRECTORY GARBAGE COLLECTOR + +; MOVE H, directory number +; lock the directory +; PUSHJ P,QGC +; return if directory full. +; return if won. +; No ACs clobbered. +; All pointers to directory relocated appropriately. + +; Called from disk open routines if a new file is to be created +; and there are less than 6+LUNBLK words in the free area of the directory. +; Called from QSBWG if %QAFUL is set in QSRAC. +; %QAFUL means "must have successful GC before committing another track to this file." + +;NOTE NOTE NOTE: +; This GC allocates an extra block of core for temporary storage. +; If no memory is free in low half, waits without unlocking directory. +; Can possibly PCLSR. No deadly embrace to not unlock directory since +; it can't be flushed from core anyway and it's not holding anything else in. + +QAPBMN==NXLBYT+3 ;minimum number of descriptor bytes which + ; must be available at the end of a file to + ; commit another track to the file. + ;1 for a take-N, NXLBYT+1 for jump, 1 for ending zero. +QAPBMX==36. ;maximum number of descriptor bytes to allocate at a time. + +QGC: IRPC X,,ABCDQIJTR + PUSH P,X + TERMIN + +;Old GC prints message on system console. Any reason to with fast one? + +; validate the directory + +QGC00: SKIPL A,QSNLCN(H) + BUG ;directory not locked + MOVE C,UDNAME(A) + MOVEM C,LASTGC ;save name of last dir GCed + CAME C,QSNUD(H) + BUG ;directory clobbered + SKIPLE C,UDNAMP(A) + CAILE C,2000 + BUG ;name pointer out of bounds + IMULI C,UFDBPW + SKIPL D,UDESCP(A) + CAIL D,-UDDESC*UFDBPW(C) + BUG ;descriptor/name overlap + +; Get a block of core to use for temporary storage. +; The block is left in the "in-process" state. + + HRRZ Q,A + PUSHJ P,TCALL + JRST IOMQ + JRST [ PUSHJ P,UDELAY ;no core available in low half + JRST QGC00 ] ;so wait, then loop back to beginning + LSH A,10. + MOVEI B,1(A) ;zero it out + HRL B,A + SETZM (A) + BLT B,1777(A) + EXCH Q,A ;A -> directory, Q -> temporary core +;Drops through + ;Drops in +; Scan the directory and count: +; I all files +; J files open for writing +; R active bytes of descriptor + + SETZB I,J + SETZ R, + MOVEI B,2000(A) ;end of name area + ADD A,UDNAMP(A) ;start of name area +QGC10: CAML A,B + JRST QGC19 ;jump if all files done + SKIPE UNFN2(A) + SKIPN UNFN1(A) + BUG ;zero name block? + AOJA I,QGC12 ;file exists + +QGC11: ADDI A,LUNBLK ;advance to next file + AOJA R,QGC10 ;also count the zero byte that ends the descriptor + +QGC12: MOVE C,UNRNDM(A) + TLNE C,UNWRIT + ADDI J,1 + ANDI C,.BM UNDSCP ;get descriptor ptr (undscp has pos=0) + IDIVI C,UFDBPW + HLL C,QBTBLI(D) + ADDI C,UDDESC-2000(B) + MOVE D,UNRNDM(A) + TLNE D,UNLINK + JRST QGC14 +QGC13: ILDB T,C ;get byte of descrip + JUMPE T,QGC11 ;eof + CAIG T,UDWPH + AOJA R,QGC13 ;1-byte desc +REPEAT NXLBYT, IBP C ;multi-byte desc + ADDI R,NXLBYT+1 + JRST QGC13 + +QGC14: ILDB T,C ;count bytes of link descriptor + JUMPE T,QGC11 + CAIN T,': + AOJA R,[IBP C ;quoted + AOJA R,QGC14 ] + AOJA R,QGC14 + + +; Compute number of bytes of descriptor to add after each +; file open for output. If > QAPBMX, set to QAPBMX. +; If < QAPBMN, take directory-full exit. + +QGC19: MOVE C,I ;save number of files + IMULI I,LUNBLK*UFDBPW ;number of bytes in name area + ADDI R,UDDESC*UFDBPW(I) ;R := total number of bytes claimed + MOVEI A,2000*UFDBPW-1 + SUB A,R ;A := number of bytes left + SKIPE J + IDIV A,J ;number of bytes available to extend open files + CAIGE A,QAPBMN + JRST QGC69 ;if < minimum, dir. full + CAILE A,QAPBMX + MOVEI A,QAPBMX ;limit to at most QAPBMX bytes at a time +;Drops through + ;Drops in +; A = number of bytes of room to leave after each file open for writing +; B -> name block under consideration +; C -> old descriptors +; D = disk channel number under consideration. Also D = C+1 +; J counts new descriptor bytes generated +; Q -> new descriptors (in temporary core block) +; R -> base of directory + + SETZ J, + HRRZ R,QSNLCN(H) ;old dir + ADDI Q,UDDESC ;new dir + HLL Q,QBTBLI + MOVE B,UDNAMP(R) + ADD B,R + +; Loop over files + +QGC20: CAIL B,2000(R) + JRST QGC40 ;all files done + LDB C,[UNDSCP UNRNDM(B)] ;get old desc ptr + DPB J,[UNDSCP UNRNDM(B)] ;store new desc ptr + +; Loop over all disk channels, relocating the ones that point to this file + + MOVSI D,-NQCHN +QGC31: HRRZ T,QUDPR(D) + SKIPL QUSR(D) + CAIE T,(H) + AOBJN D,QGC31 ;not in use or not same directory + JUMPGE D,QGC39 ;jump if all disk channels done + LDB T,[1200,,B] + CAME T,QUDFPR(D) + JRST QGC32 ;not same file + MOVE T,J ;relocate descriptor pointer + SUB T,C + ADDM T,QDIRP(D) +QGC32: AOBJN D,QGC31 + +QGC39: IDIVI C,UFDBPW ;make desc pntr into byte pointer + HLL C,QBTBLI(D) + ADDI C,UDDESC(R) + MOVE T,UNRNDM(B) + TLNE T,UNLINK + JRST QGC22 +QGC21: ILDB T,C ;copy descriptor bytes of a file into temporary core + IDPB T,Q + JUMPE T,QGC23 + CAIG T,UDWPH + AOJA J,QGC21 +REPEAT NXLBYT,[ + ILDB T,C + IDPB T,Q +] ADDI J,NXLBYT+1 + JRST QGC21 + +QGC22: ILDB T,C ;copy descriptor bytes of a link into temporary core + IDPB T,Q + JUMPE T,QGC23 + CAIN T,': + AOJA J,[ILDB T,C + IDPB T,Q + AOJA J,QGC22 ] + AOJA J,QGC22 + +QGC23: MOVE T,UNRNDM(B) + TLNN T,UNWRIT + JRST QGC25 + ADD J,A ;file being written, increase desc area + MOVE T,A + IBP Q + SOJG T,.-1 + +QGC25: ADDI B,LUNBLK ;next file + AOJA J,QGC20 ;also account for final zero at end of descriptor + +; Paranoia: check that all disk channels to this directory look OK + +QGC40: MOVEM J,UDESCP(R) ;store free-desc pointer + LDB A,[1200,,Q] ;last word used by descriptors + CAML A,UDNAMP(R) + BUG ;overlap + ANDI Q,-2000 ;base of temp core block again + MOVSI A,-NQCHN +QGC41: HRRZ T,QUDPR(A) + SKIPL QUSR(A) + CAIE T,(H) + AOBJN A,QGC41 ;channel not in use, or to some other dir + JUMPGE A,QGC49 ;all channels done + SKIPN B,QUDFPR(A) ;get file open on this channel + JRST QGC42 ;channel not set up to any particular file + CAIGE B,2000 + CAMGE B,UDNAMP(R) + BUG ;file pointer screwed + ADD B,R + SKIPL J,QDIRP(A) ;get descriptor pointer + CAMLE J,UDESCP(R) + BUG ;descriptor pointer screwed + LDB C,[UNDSCP UNRNDM(B)] + CAIGE B,2000-LUNBLK(R) ;skip if last file in dir + LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get desc pntr for next file + CAIL B,2000-LUNBLK(R) + MOVEI D,2000*UFDBPW ;but if last file, get infinity + CAML J,C ;verify that QDIRP points to this file + CAML J,D + BUG +QGC42: AOBJN A,QGC41 ;do next channel + +; If you thought that was paranoid, get a load of this: + +QGC49: MOVE B,UDNAMP(R) + ADD B,R +QGC50: CAIL B,2000(R) + JRST QGC60 + LDB C,[UNDSCP UNRNDM(B)] + SOS C + IDIVI C,UFDBPW ;NOTE if UNDSCP = 0 we depend on bytes + HLL C,QBTBL(D) ; off left end of word LDB'ing as zero + ADDI C,UDDESC(Q) + LDB T,C + SKIPE T + BUG ;descriptor not preceeded by zero + MOVE J,UNRNDM(B) + TRZ J,#.BM UNDSCP ;LH(J) flags, RH(J) just desc pntr + TLNE J,UNLINK + JRST QGC52 +QGC51: ILDB T,C + JUMPE T,QGC53 + CAIG T,UDWPH + AOJA J,QGC51 +REPEAT NXLBYT, IBP C + ADDI J,NXLBYT+1 + JRST QGC51 + +QGC52: ILDB T,C + JUMPE T,QGC53 + CAIE T,': + AOJA J,QGC52 + IBP C + ADDI J,2 + JRST QGC52 + +QGC53: TLNE J,UNWRIT ;RH(J) has desc pntr to the zero that ends the file + ADDI J,QAPBMN ;if being written, needs room for one more track + CAIL B,2000-LUNBLK(R) ;now set D to point to next descriptor area + SKIPA D,UDESCP(R) ;do this instr if last file in dir + LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get next file's desc pntr + CAIG D,(J) + BUG ;descriptors overlap + ADDI B,LUNBLK + JRST QGC50 + +; Copy the descriptors back into the directory + +QGC60: MOVSI C,UDDESC(Q) ;make BLT pointer to copy it back + HRRI C,UDDESC(R) + MOVE B,UDNAMP(R) ;use same BLT to zero out the free area + ADD B,R + BLT C,-1(B) + +; Take win return. + + AOS -9(P) +QGC69: LDB A,[121000,,Q] ;core block number of temporary page + PUSHJ P,TMEMR ;return it + MUINP ;verifying that it is the right one. + IRPC X,,RTJIQDCBA + POP P,X + TERMIN + POPJ P, + +SUBTTL INTERPRET DESCRIPTORS + +QFNTR: MOVE H,QUDPR(A) ;BYTE # IN Q CHNL # IN A + PUSHJ P,QUDLK ;DONT SKIP IF OFF FILE + MOVE T,QSNLCN(H) ;RETN BLOCK IN QSLGL(A) AND QSBI(A) DIR PNTR IN QDIRP(A) + ADD T,QUDFPR(A) ;FIRST ADR OF BLOCK IN QFBLNO(A) + LDB TT,[UNDSCP+UNRNDM(T)] ;CHAR ADR OF FILE BEG + MOVEM TT,QDIRP(A) ;SKIPS IF FINDS BLOCK AND LEAVES USER DIR LOCKED + CLEARM QSBI(A) + CLEARM QFBLNO(A) + CLEARB J,QSLGL(A) ;J HAS ORG OF FIRST NON-EX-BLOCK IF OFF END OF FILE +QFNT1A: PUSHJ P,QFNT1 + JRST QUDULK ;OFF END OF FILE RETN NOT SKIPPING + CAMLE J,Q + JRST QFNT7 ;LOCATED BLOCK CONTAINING WORD + MOVEM J,QFBLNO(A) + JRST QFNT1A + +QFNTN: MOVE H,QUDPR(A) ;LIKE ABOVE BUT SCAN FORWARD ONLY FROM CURRENT SPOT + PUSHJ P,QUDLK + PUSHJ P,QFNT1 + CAIA ;EOF, DON'T SKIP RETURN + AOS (P) + MOVEM J,QFBLNO(A) + JRST QUDULK + +QFNT1: SKIPE QSBI(A) ;DECODE NEXT BLOCK, CHNL IN A, SKIP UNLESS EOF. + JRST QFNT2 ;BLOCK # IN QSLGL FILE ADR IN J (TAKE N PENDING) +QFNT3: PUSHJ P,QMPDCH ;GOBBLE NEXT CHR OF DESC IN R (POINTED TO BY QDIRP) INCR QDIRP + CAIN R,UDWPH ;ALSO RET BYTE PNTR IN TT + JRST QFNT3 ;NULL + JUMPN R,QFNT8 ;NOT OFF END OF FILE + SOS QDIRP(A) + POPJ P, + +QFNT8: TRNE R,40 + JRST QFNT4 + CAILE R,UDTKMX + JRST QFNT6 ;SKIP AND TAKE + MOVEM R,QSBI(A) +QFNT2: SOS QSBI(A) + AOS QSLGL(A) +QFNT5: MOVEI J,2000 ;ACTIVE BYTES IN BLOCK + IMULI J,@QSBYTE(A) + ADD J,QFBLNO(A) + JRST POPJ1 + +QFNT7: MOVSI T,%QALBK ;SET UP PROC LAST BLOCK FLG AND RETN + ANDCAM T,QSRAC(A) ;CLEAR LAST BLOCK OF FILE BIT + SKIPE QSBI(A) + JRST QFNT7A ;NOT LAST BLOCK + ILDB R,TT ;GET NEXT CHR IN DIR + JUMPN R,QFNT7A + IORM T,QSRAC(A) ;PROCESSING LAST BLOCK +QFNT7A: AOS QSBI(A) ;FAKE OUT PI ROUTINE WHICH WILL TRY TO INCREMENT + SOS QSLGL(A) + JRST POPJ1 + +QFNT4: MOVEI J,0 ;LOAD ADR + DPB R,[140400,,J] + PUSHJ P,QMPDCH + DPB R,[060600,,J] + PUSHJ P,QMPDCH + DPB R,[0600,,J] + MOVEM J,QSLGL(A) + JRST QFNT5 + +QFNT6: MOVEI J,1-UDTKMX(R) + ADDM J,QSLGL(A) + JRST QFNT5 + EBLK + +SUBTTL DISK CHANNEL DATA AREAS + +QBFP: BLOCK NQCHN ;BUFFER LIST LH LAST RH FIRST + ;READ: PI IN MP OUT. WRITE: MP IN PI OUT. +SINLST: BLOCK NQS ;SWAP-IN LISTS FOR EACH DISK +SOUTLS: BLOCK NQS ;SWAP-OUT LISTS FOR EACH DISK + +;READ/WRITE LISTS LINK THROUGH MLO IN MEMBLT. +;LH(MEMPNT) HAS DISK ADDR, RH(MEMPNT) HAS # BYTES IN BLOCK IF FILE READ +;MWC IN MEMBLT HAS WORD COUNT IF WRITE (FOR EXTRA-WORDS) + +QFCHN: NQCHN ;NUMBER OF FREE QSK CHNLS (NOT COUNTING DIR WRITE AND SWAP CHANNELS) + +QUSR: REPEAT NQCHN,-1 ;USER +DWUSR: -1 ;0 IF DIR WRITE ACTIVE +SWUSR: REPEAT NQS,-1 ;0 IF SWAP XFER ACTIVE +QDIRP: BLOCK NQCHN ;CHAR ADR PNTR TO DESC AREA FOR FILE +QSLBLK: BLOCK NQCHN+NQS+1 ;LAST BLOCK NUMBER OF FILE WRITTEN +QSLGL: BLOCK NQCHN ;LAST QSGL +QSGL: REPEAT NQCHN+NQS+1,-1 ;-1 IDLE + ACTIVE TRACK + ;LAST NQS+1 FOR FD WRITE AND SWAPPING +QSBI: BLOCK NQCHN ; COUNT CONSECUTIVE BLOCKS +QSBFS: BLOCK NQCHN ;NUMBER OF BUFFS THIS CHNL +1 IF EOF AT PI WITH QSBFS=0 +QPCLSR: BLOCK NQCHN ;PCLSR STATUS OF MAIN PROGRAM - LOAD SYSTEM CALL +QSMDN: BLOCK NQCHN ;MAIN PRGM ACTIVE BUFFER NUM +OLDRDT: BLOCK NQCHN ;STORAGE FOR PREVIOUS REFERENCE DATE +QSRAC: BLOCK NQCHN+1 + REPEAT NQS, %QMSWP ;SWAPPING CHANNELS START OUT IN SWAP MODE + %QA==525252(1) + %QALOK==400000 ;4.9 CHNL LOCKED (NOT USED) + %QAEFR==200000 ;4.8 EOF REACHED READ + %QAEFW==100000 ;4.7 EOF WRITE + %QACTH==40000 ;4.6 DONT RELOAD. CORE JOB HUNG ON ACTIVE BUFFER + %QAFUL==20000 ;4.5 GC DIR BEFORE COMMITTING ANOTHER BLOCK TO FILE + %QADEL==10000 ;4.4 DELETE WHEN CLOSED + %QAACC==4000 ;4.3 FILE ADDRESS ALTERED BY .ACCESS OR OTHERWISE + %QAPAR==2000 ;4.2 NON RECOV PARITY ERR (OR OTHER DISK ERR) AT PI + %QAOUT==1000 ;4.1 ASSOC USER OUT DONT RELOAD (NOT IMPLEM.) + %QALBK==400 ;3.9 READ CHNL PROCESSING LAST BLOCK FLAG + %QAMPU==200 ;3.8 UPDATE QSMPRP, QSMPRC ON NEXT BUFFER GOBBLE + %QAWOV==100 ;3.7 FILLING OUT LAST BLK OF FILE IN WRITE OVER MODE PAST ORIG EOF + %QALNK==40 ;3.6 FILE IS REALLY A LINK + %QALOP==20 ;3.5 LINKS WERE TRACED IN OPENING THIS FILE. + %QARWT==10 ;3.4 MAKE WOULD-BE READERS WAIT (RATHER THAN GETTING FILE LOCKED ERROR) + %QAFNY==4 ;3.3 "FUNNY BLOCK", WORD COUNT IN LAST WORD + ; 8/20/90 No longer ever gets set. + $QAMOD==220200 ;3.2-3.1 READ/WRITE MODE 0 NORMAL 1 WRITE OVER 2 COPY OVER WRITE + %QAMWO==1 ;3.1=1 => WRITE-OVER MODE. + %QM==777777 ;RH CHANNEL MODE. INDEX INTO ACTION TABLES USED AT PI LEVEL. +.SEE %QMIDL ;FOR TABLE OF CHANNEL MODES + +QDSKN: BLOCK NQCHN ;DISK UNIT NUMBER +DWSKN: 0 ;DISK WRITING DIR ON +SWSKN: REPEAT NQS,.RPCNT ;DISK SWAP XFER +QSCRW: BLOCK NQCHN ;0 READ -1 WRITE + -1 ;D.W. + BLOCK NQS ;SWAP +QSCABN: BLOCK NQCHN ;ACTIVE BUFFER NUMBER PI LEVEL OR -1 IF NONE +DWABN: -1 ;DISK D.W. A.B.N +SWABN: REPEAT NQS,-1 ;SWAP ABN +QUDPR: BLOCK NQCHN ;NUMBER OF ASSOCIATED USER DIR PNTR +QUDFPR: BLOCK NQCHN ;RELATIVE PNTR TO FILE AREA, ZERO IF NO PARTICULAR FILE +QMPTN: BLOCK NQCHN ;HAS LAST TRACK STORED IN DIRECTORY +QMPTC: BLOCK NQCHN ;MAIN PRGM TRACK COUNT +QMTTR: BLOCK NQCHN ;TRACK RESERVED OR -1 +QMFTP: BLOCK NQCHN+1 ;TRACK NUMBER FOR SCAN FOR FREE TRACKS IN TUT ON WRITE + REPEAT NQS,NUDSL; DITTO FOR SWAP CHANNELS +QERRS: BLOCK NQCHN+NQS+1 ;NUMBER ERRORS TRYING LAST OP +QSMPRP: BLOCK NQCHN ;MAIN PRGM BYTE POINTER +QSMPRC: BLOCK NQCHN ;M.P. COUNT (BYTES LEFT IN BUFFER) +QSBYTE: BLOCK NQCHN ;LH BYTE PNTR (P=44), RH BYTES PER WORD +QSBSIZ==300600,,QSBYTE ;BYTE POINTER TO CHANNEL BYTE SIZE +QFBLNO: BLOCK NQCHN ;BYTE # IN FILE OF BEG OF BLOCK BEING PROCESSED AT M.P. LEVEL +QRADAD: BLOCK NQCHN ;DESIRED BYTE ADR (LOOKED AT IF %QAACC OR %QAMPU IN QSRAC SET) +QPIBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN BLOCK ACTIVE AT P.I. LEVEL (READ) + ;BIT 4.9 => GET FROM LAST WORD IN BLOCK (%QAFNY) + ; 8/20/90 %QAFNY can no longer happen. +QMPBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN MN PROG ACTIVE BUFFER +QLDPTR: BLOCK NQCHN .SEE NLDSBQ ;DURING SBLK LOADING, HOLDS THE AOBJN POINTER + ;INTO USER CORE FOR DOING A DISK TRANSFER ON. +QSMMP: BLOCK NQS ;MMP ADDRESS OF BLOCK ACTIVE ON SWAPPING CHANNEL + +;VARIABLES FOR CURRENT TRANSFER + +QSDU: -1 ;UNIT TRANSFERING DATA, -1 IF NONE. +QSDCH: -1 ;CHNL READY TO BE TRANSFERED ON QSDU +QERS1: -1 ;ERR VERIFY SWITCH -1 NO ERR 0 EXPECTING COMPLETION OF VERIFY OP +QDWIP: 0 ;NUMBER OF DIR WRITE IN PROGRESS 4.9=1=>MASTER + +IFN T300P,[ +QSDU1: -1 ;QSDU FOR OTHER CONTROLLER +QSDCH1: -1 ;ASSOCIATED CHANNEL +QTUNT1: -1 ;UNIT TO TRANSFER NEXT +QTCHN1: -1 ;CHANNEL TO TRANSFER NEXT +NRXFR1: 0 ;METERS +NWXFR1: 0 +NSRXF1: 0 +NSWXF1: 0 +LQTM1: 0 ;TIME LAST TRANSFER STARTED +];T300P + +;MASTER FILE DIRECTORY + +QMDRO: -1 ;ORIGIN OF MASTER DIR 4.9 IF LOCKED + ;-2 ON WAY IN + ;4.6 NOT IN + ;4.5, 4.4, 4.3, ... CHANGED + NOT WRITTEN UNIT 0, 1, 2, ... + ;3.2=1 NOT RECONCILED (NQFUS NOT SET UP) + ;3.1-3.5 MUST BE ZERO (AT LEAST AFTER ITS RECONCILED) +QAMDNO: -1 ;ASCENDING MASTER DIRECTORY NUMBER, -1 NOT SET UP +NQFUS: 0 ;NUMBER OF FREE LOSER SLOTS IN MFD + +;TRACK UTILIZATION TABLES + +QTUTO: REPEAT NQS,-1 ;ADDRESS OF TUT. LH SIMILAR TO QMDRO + ;4.9 LOCK + ;4.8 READ-IN NOT STARTED YET + ;4.6 NOT READ IN YET + ;CHANGED AND NOT WRITTEN ON UNIT + ;0 = 4.5 1 = 4.4 2 = 4.3 3 = 4.2 4 = 4.1 + ;5 = 3.9 6 = 3.8 + ;3.1-3.5 MUST BE ZERO +QDPWF: BLOCK NQS ;-1 TUT NOT RECONCILED (CALL QTCH1) +QTWRTM: BLOCK NQS ;TIME TUT LAST WRITTEN +QSFT: REPEAT NQS,-1 ;NUMBER TRACKS FREE IN USER AREA +QSFTS: BLOCK NQS ;NUMBER TRACKS FREE IN SWAPPING AREA +QPKNM: BLOCK NQS ;NAME OF PACK +QPKID: REPEAT NQS,-1 ;PACK ID OF DISK ON DRIVE +IFN QRSRVP,[ +QRESRV: REPEAT NQS,-1 ;NON-ZERO => PACK ON THIS DRIVE RESERVED. SET FROM TUT. + ;NOT 0 AND NOT -1 => SIXBIT DEVICE NAME FOR "SECONDARY" PACK +];QRSRVP +NTBL: ;NUMBER OF BLOCKS IN TUT ON THIS DRIVE +IFE T300P, REPEAT NQS, NTUTBL +IFN T300P,[ + REPEAT T300P, NTUTBL + REPEAT NQS-T300P, NTUTB1 +];T300P + +;POSITIONER VARIABLES (INDEXED BY PHYSICAL DRIVE) + +QSKT1: REPEAT NQS,-1 ;CHANNEL POSITIONER SET FOR OR -1 IF NONE +QRCAL: REPEAT NQS,0 ;-1 IF RECALIBRATING +QSPPS: REPEAT NQS,-1 ;INTENDED POSITIONER POSITION (NOT USED???) +QSEEK: BLOCK NQS ;-1 IF SEEKING +QPOS: REPEAT NQS,-1 ;CURRENT CYLINDER +QPOSGL: BLOCK NQS ;CYLINDER TRYING TO POSITION TO +IFN DC10P,[ +QRCTIM: BLOCK NQS ;RECALIBRATE TIMEOUT IN HALF SECONDS. THE ATTNS +];DC10P ; TEND TO GET LOST FOR SOME REASON + +;MISCELLANEOUS DISK VARIABLES + +QACT: REPEAT NQS,0 ;ONLY USE UNITS WITH 0 +QACTB: 0 ;4.5 UNIT 0 ACT 4.4 1 ACT 4.3 2 4.2 3 4.1 4 + ;3.9 5 3.8 6 +QWBUFS: 0 ;TOTAL NUMBER OF WRITE BUFFERS ACTIVE + +QWBFMX: 10.*DC10P+15.*RP10P+30.*RH10P+20.*RH11P ;MAX # ALLOWED. SHOULD BE + ; ABOUT 1 SEC DISK XFER. +QHUNGF: 0 ;-1 => DISK CONTROL HUNG, PI LEVEL SHOULD RESET, RECALIBRATE, RETRY +NTQHNG: BLOCK NQS ;NUMBER OF TIMES TRANSFER HUNG ON THIS UNIT + +QTUNT: 0 ;UNIT TO TRANSFER ON NEXT +QTCHN: 0 ;CHNL .. +QLCHN: 0 .SEE QINT2C +QWRU: -1 ;DEFAULT WRITE UNIT (-1 if there isn't a default unit yet) +MDSK: 0 ;DRIVE # OF MASTER DISK +QACTTM: -1 ;SETOM ON READ OR WRITE DATA TRANSFER + ;AOS AT SSLCK IF + OK TO WRITE DIRS + ;IE DON'T TIE UP DISK TO WRITE DIR UNLESS THINGS ARE QUIET +QDWFAR: -10. .SEE QINT3 ;WRITE DIRS SOME OF THE TIME ANYWAY +LQTM: 0 ;TIME AT WHICH LAST COMMAND GIVEN TO DISK +QFTTHR: 600. ;IF FREE TRKS ON QWRU GOES BELOW THIS, SWITCH TO UNIT WITH MOST FREE TRACKS +QRDAHD: IFE MCOND DM,[0] .ELSE 2 ;NUMBER OF BLOCKS TO READ AHEAD + +LASTGC: 0 ;NAME OF LAST DIRECTORY TO GET GC'ED + +;USER DIRECTORIES + +QNUD==40. ;NUMBER USER DIRECTORIES + +QFUD: QNUD ;NUMBER OF FREE UFD SLOTS + +QSNUD: BLOCK QNUD ;USER NAME OR 0 IF FREE +QSNLCN: BLOCK QNUD ;4.9 LOCKED, 4.8 ALSO NOT IN CORE RH CORE ADR + .SEE DCHBT ;4.6 =1 NOT PAWED OVER 4.5 CHNGD AND NOT WRITTEN ON UNIT 0 + ;4.4 UNIT 1 4.3 UNIT 2 4.2 UNIT 3 4.1 UNIT 4 + ;3.9 UNIT 5 3.8 UNIT 6 3.7 UNIT 7 + %QUDWM==40 ;3.6 WRITE IMMEDIATELY ON MASTER DISK + ;@ + XR BITS MUST = 0 + +QSNNR: BLOCK QNUD ;NUMBER PC'S LOOKING AT THIS IE + ;+1 FOR FILE OPEN AND USER IN CORE(?) +QSNMI: BLOCK QNUD ;TRACK N OF USER DIR IF NOT NEWLY CREATED +QSFBT: BLOCK QNUD ;FREED-BLOCKS-TABLE. HEAD OF A LIST OF PAGES, + ;THREADED THROUGH THE SECOND WORD AND ENDING WITH + ;ZERO. FIRST WORD IS AOBJN POINTER TO FREE PART + ;OF PAGE. FROM THIRD WORD UP TO BELOW WHERE AOBJN + ;POINTS ARE WORDS UNIT,,BLOCK WHICH RECORD DISK + ;BLOCKS TO BE FREED ONCE THE DIR HAS BEEN WRITTEN + ;OUT TO THE MASTER DISK. ELIMINATES REUSED ADDRESS + ;PROBLEMS BY GUARANTEEING THAT IF THE SYSTEM SHOULD + ;CRASH AT ANY TIME, THERE CANNOT BE TWO DIRECTORIES + ;ON DISK THAT BOTH POINT TO THE SAME BLOCK. + +IFN QRSRVP,[ +QSALLO: BLOCK QNUD ;-1 OR DRIVE # DIRECTORY ALLOCATED TO +] + +;LOCKS + +UDRSW: -1 ;USER DIR AREA LOCKED + 0 +QCHSW: -1 ;CHNL AREA LOCKED + 0 +QSKOSW: -1 ;QSKO1 LOCKED (USER DIR READIN) + 0 + +;LIST OF PAGES CONTAINING BLOCKS WHICH CAN NOW BE FREED. MOVED TO +;HERE FROM QSFBT WHEN THE DIR IS WRITTEN OUT. THE ACTUAL FREEING +;IS DONE BY THE CORE JOB. + +QFBTS: 0 + +;VARIABLES FOR SYSTEMS CONCEPTS DISK CONTROL + +IFN DC10P,[ +QRCSW: 105 ;- NO READ COMPARE 0 COMPARE WRITES + COMPARE ALL +QCST: 0 ;CONI DC0, AT QINT +QERST: 0 ;HAS CONI DC1, BITS WHEN AN ERROR HAPPENS +PKIDM: 0 ;-1 WAITING FOR PACK ID TO BE READ +RPKID: -1 ;PACK ID READ INTO HERE BY DISK CONTROL +QDRSTS: 0 ;DRIVE STATUS WORD STORED BY DISK CONTROL +] +IFE DMDSK,[ + 0 ;FOR BLT INTO QXWDS +QXWDS: BLOCK NXWDS +] +IFN DC10P,[ +QCHPRG: 0 +QCHPR2: DCOPY (-2000_2&37774) + DCOPY (-NXWDS_2&37774)QXWDS +QCHPR4: DHLT ;OR DRC +QCHPR3: DCCOMP (-2000_2&37774) + DCCOMP (-NXWDS_2&37774)QXWDS + DHLT + +GPKID: DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +QRECAL: DSPC+DSRCAL+DUNENB +] + +;VARIABLES FOR DEC RP10 DISK CONTROL + +IFN RP10P,[ +QERST: 0 ;CONI DPC, ON ERROR +QERDTI: 0 ;DATAI DPC, ON ERROR +QCST: 0 ;CONI DPC, AT QINT +QCHPRG: 0 ;SEEK COMM +IFN KA10P, QIOWD: -2000,, ;XFER DATA (HRRM ADR-1 IN RH) +IFE DMDSK,[ + -NXWDS,,QXWDS-1 + -200+NXWDS,,0 +];DMDSK + 0 + +QRECAL: 700000,, +QGTBZY: 0 ;FLAG FOR SOFTWARE AT INT +];RP10P +IFN QRDCMP,[ +QRCSW: 0 ;NON-ZERO TO ENABLE READ-COMPARING +RDCPHS: 0 ;0 NORMAL, -1 DOING OPERATION WHICH SHOULD BE READ-COMPARED + ; AFTERWARD, + DOING READ-COMPARE +IFN KA10P,[ +RCIOWD: BLOCK 2 ;CHANNEL PROGRAM FOR READ INTO QRCBUF +];KA10P ;ON KL WE HAVE TO PUT IT IN THE EPT! +QRCBUF: BLOCK 2000 +];QRDCMP + +;VARIABLES FOR DEC RH10 DISK CONTROL + +IFN RH10P,[ +QCHPRG: 0 ;DATA TRANSFER COMMAND +QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH) +NCSHI: 0 ;NUMBER OF CACHE INVALIDATES +NCSHIL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE INVALIDATES +NCSHU: 0 ;NUMBER OF CACHE UNLOADS +NCSHUL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE UNLOADS +QERST: 0 ;CONI AT LAST ERROR (LEAVE THIS THROUGH QECPAT IN SAME ORDER) + 0 ;DATAI AT LAST ERROR +QERSTS: 0 ;%HRSTS AT LAST ERROR +QERER1: 0 ;%HRER1 AT LAST ERROR +QERER2: 0 ;%HRER2 AT LAST ERROR +QERER3: 0 ;%HRER3 AT LAST ERROR (IBM WOULD CALL THIS A CHANNEL LOGOUT AREA) +QERDCL: 0 ;%HRDCL AT LAST ERROR +QECPOS: 0 ;%HRPOS AT LAST ERROR +QECPAT: 0 ;%HRPAT AT LAST ERROR +QCST: 0 ;CONI AT LAST INTERRUPT +QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT +QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE +QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR +RHDATO: -1 ;LAST DATAO DSK, FOR DEBUGGING +ECCPAG: BLOCK 8 ;TEMP FOR SAVING PAGE MAP VARS AT QECC (WITH SPM) +NQDRE: BLOCK NQS ;# MASSBUS TIMEOUTS PER DRIVE. +NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER +NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS +] + +;VARIABLES FOR DEC RH11 DISK CONTROL (ON THE KS10 UNIBUS) + +IFN RH11P,[ +QCHPRG: 0 ;DATA TRANSFER COMMAND +QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH) +QIOWD: 0 ; BA,,WC for RH11 +QCST: 0 ;CS1 AT LAST INTERRUPT +QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT + +QERST:: ;Gubbish saved at last error +QERCS1: 0 ; CS1 Control & Status 1 +QERCS2: 0 ; CS2 Control & Status 2 +QERSTS: 0 ; STS Drive status +QERBA: 0 ; BA Unibus address for transfer +QERWC: 0 ; WC Word count for transfer +QERER1: 0 ; ER1 Error 1 +QERER2: 0 ; ER2 Error 2 +QERER3: 0 ; ER3 Error 3 +QERPOS:: +QECPOS: 0 ; POS ECC position +QERPAT:: +QECPAT: 0 ; PAT ECC pattern +QERMAP: 0 ? 0 ; Unibus map to disk buffer + +QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE +QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR + +NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER +NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS +NQOFFL: BLOCK NQS ;# TIMES DISK WENT OFFLINE +] + +DIRHNG: 0 ;LH POINTS TO LIST OF DIRHNG DEVICE CHANNELS, + ;CHAINED THROUGH LH'S OF IOCHNM WORDS. + ;0 MEANS END OF LIST + ;MODIFY ONLY WITH THE CLOCK OFF. + ;EACH DIRHNG DEVICE CHANNEL'S IOCHST WORD RH CONTAINS THE + ;TRACK NUMBER OF THE DIRECTORY IT IS LOOKING AT. + +BBLK + +;DISK CONSTANTS + +IFN RP10P,[ +QATTNS: REPEAT NQS,500000+.RPCNT_14,,1_<10-.RPCNT> +;WORDS TO CLEAR ATTNS AND SELECT DRIVES +] + +SWAPL: SINLST(Q) + SOUTLS(Q) + +DCHBT: 20000,, ;BIT SET IF DIR NOT WRITTEN OUT ON UNIT + 10000,, + 4000,, + 2000,, + 1000,, + 400,, + 200,, + 100,, +IFL .-DCHBT-NQS,.ERR YOU BETTER FIND ANOTHER BIT FOR QACTB,QSNLCN,QTUTO + +IFN DC10P,[ +QTRAN: 0 ;FORMERLY MAPPED 203 CYL VIRTUAL DRIVES TO 406 CYL CALCOMPS + 1 ;4.9 => 2ND HALF OF PHYSICAL DRIVE + 2 ;(DOESN'T DO ANYTHING NOW THAT MEMOWRECKS ARE GONE, + 3 ; BUT KEEP AROUND IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +IFL .-QTRAN-NQS, .ERR BARF AT QTRAN +] + +SUBTTL DISK CLOSE ROUTINES + +QICL: PUSH P,R + SKIPGE QUSR(A) + BUG + MOVSI Q,%QAACC + ANDCAM Q,QSRAC(A) ;FLUSH RANDOM ACCESS HACKERY + PUSHJ P,QICLW1 ;WAIT FOR INPUT TO STOP + MOVE TT,QSRAC(D) + TLNE TT,%QADEL ;DELETE? + JRST QSICLD ;YES + MOVE H,QUDPR(D) ;DIRECTORY NUMBER + SETOM QUSR(D) + AOS QFCHN +QICLX: SOSGE QSNNR(H) ;FREE DIRECTORY CHANNEL HAD BEEN USING + BUG + POP P,R + SETZM (R) + POPJ P, + +QICLW1: MOVE D,A ;IDLE CHANNEL AND FLUSH READ BUFFERS + CONO PI,UTCOFF + SKIPGE QSGL(D) + JRST QSICL3 + SKIPL QSCABN(D) + JRST QSICL4 + SETOM QSGL(D) + +QSICL3: HLLZS QSRAC(D) .SEE %QMIDL ;STOP PI + CONO PI,UTCON +QSICL5: PUSHJ P,QSBRB1 ;RETURN M.P. BUFFER IF ANY +QOCL7: HRRZ A,QBFP(D) ;ALSO ENTER TO RETURN UNUSED READ BUFFER ON WRITE OVER MODE +QSICL2: JUMPE A,QSICL6 + LDB C,[MLO,,MEMBLT(A)] + PUSHJ P,MEMR + MOVE A,C + SOS QSBFS(D) + JRST QSICL2 + +QSICL6: SETZM QBFP(D) + POPJ P, + +QSICL4: MOVEI A,%QMRD1 ;STOP PI AFTER THIS BLOCK + HRRM A,QSRAC(D) + CONO PI,UTCON + SKIPL QSGL(D) ;WAIT FOR CHANNEL TO DEACTIVATE + PUSHJ P,UFLS + JRST QSICL5 + +;OUTPUT CLOSE +QOCL: PUSHJ P,QSOCL5 ;CLEAN UP THE DISK CHANNEL +QSOCL4: MOVE D,A ;ENTRY FROM QALINK +QSOCL6: MOVE Q,QUDFPR(D) + MOVE H,QUDPR(D) + ADD Q,QSNLCN(H) + MOVE TT,QSRAC(D) + TLNE TT,%QADEL + JRST QCDLWO ;DELETED (PRESUMABLY VIA DELEWO) + MOVE A,UNFN1(Q) ;Get names of file being hacked. + MOVE B,UNFN2(Q) + PUSHJ P,QLOOK ;FILING OVER ANYTHING? + JRST QSOCL3 + HRRZ I,QSNLCN(H) + ADD I,QUDFPR(D) + CAMN I,Q ;BEING WRITTEN BITS WENT AWAY? + BUG ;TRYING TO DELETE THE FILE WE'RE WRITING + PUSHJ P,QSOCLD ;YES FLUSH IT + PUSHJ P,QUDLK ;RELOCK DIR UNLOCKED BY QSOCLD ETC + JRST QSOCL6 ;MAKE SURE ONE HASN'T REAPPEARED WHILE DIR UNLOCKED + +QSOCL5: LDB H,[$QAMOD,,QSRAC(A)] + JUMPN H,QOCL6 ;DONT HACK ACTIVE WD COUNT IN WRITEOVER MODE +QOCL6A: MOVN D,QSMPRC(A) ;- NUMBER OF BYTES IN BLOCK NOT USED + ADDB D,QMPBSZ(A) ;ADJUST BYTE COUNT OF LAST BLOCK TO REFLECT WHATS USED + CLEARM QSMPRC(A) ;SO WILL BE A NOOP IF PCLSR OUT AND COME BACK THRU HERE +QOCL4: MOVSI Q,%QAEFW + IORM Q,QSRAC(A) ;SET EOF BIT FOR QSBWW AND QUDS + JUMPN H,QOCL5 + SKIPL QSMDN(A) ;NO M.P. BUFFER ANYWAY + JUMPE D,QOCL1 ;ABOUT TO WRITE NULL BLOCK, DON'T +QOCL5: PUSHJ P,QSBWW +QOCL2: MOVE T,A + PUSHJ P,[ SKIPGE QSCRW(T) ;WAIT FOR CHANNEL EITHER LEAVING WRITE MODE + SKIPN QSBFS(T) ;OR WRITING OUT ALL ITS BUFFERS, I.E. PI LEVEL + JRST POPJ1 ;ISN'T GOING TO DO ANYTHING MORE TO IT. + POPJ P, ] + PUSHJ P,UFLS + SKIPE QBFP(A) ;MAKE SURE IF QSBFS NON-ZERO THAT IS ONLY EOF + BUG ;NOT A BUFFER SITTING AROUND FORGOTTEN +QOCL3: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + SKIPN D,QMPTC(A) ;SKIP ON NEXT "N" STILL PENDING + POPJ P, + PUSHJ P,QUDS ;STORE IT AWAY + CLEARM QMPTC(A) + POPJ P, + +QOCL6: SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO IDLE OR HANG UP IN READ + PUSHJ P,UFLS + SKIPL QSGL(A) + PUSHJ P,UFLS + MOVE D,A + PUSHJ P,QOCL7 + MOVE A,D + MOVE Q,QSRAC(A) + MOVE B,QSBFS(A) + JUMPE B,QOCL6B + TLNE Q,%QAEFW + JRST QOCL6B + TLNE Q,%QAEFR + SOS B,QSBFS(A) ;COMPENSATE FOR EXTRA AOS ON EOF READ +QOCL6B: CAILE B,1 + BUG + TLNE Q,%QAWOV + JRST QOCL6A ;HACKING LAST BLOCK PAST EOF, UPDATE ACTIVE WD COUNT + JRST QOCL4 + +QOCL1: PUSHJ P,QSBRB ;DISCARD BUFFER + SOS QSBFS(A) + SOS QWBUFS + MOVE D,QDSKN(A) + AOS QSFT(D) ;RESTORE TRACK + JRST QOCL2 + +QSOCL3: MOVE Q,QUDFPR(D) + MOVE TT,QSNLCN(H) + ADDI Q,(TT) + MOVSI T,UNWRIT + ANDCAM T,UNRNDM(Q) ;CLEAR WRITE IN PROG + MOVE TT,QSNLCN(H) + MOVE T,UDNAMP(TT) ;MAKE SURE IT GOES BEFORE * FILE OF SAME NAME + ADDI T,(TT) + CAMN T,Q + JRST QSOC3E ;NO PREV FILE + MOVE J,Q +QSOC3A: SUBI J,LUNBLK + CAMN A,UNFN1(J) + CAME B,UNFN2(J) + JRST QSOC3B ;PREV FILE HAS DIFFERENT NAME + CAILE J,(T) + JRST QSOC3A +QSOC3C: CAMN J,Q + JRST QSOC3E +REPEAT LUNBLK, PUSH P,.RPCNT(J) + MOVE T,J + HRL T,Q + BLT T,LUNBLK-1(J) +REPEAT LUNBLK, POP P,LUNBLK-.RPCNT-1(Q) + SUB Q,J + SUBI J,(TT) + MOVSI T,-NQCHN +QSOC3D: HRRZ A,QUDPR(T) + SKIPL QUSR(T) + CAIE A,(H) + JRST QSOC3F + HRRZ A,QUDFPR(T) + CAIN A,(J) + ADD A,Q + MOVEM A,QUDFPR(T) +QSOC3F: AOBJN T,QSOC3D +QSOC3E: SETOM QUSR(D) ;FREE THE DISK CHANNEL + AOS QFCHN + MOVE C,QSNUD(H) +IFN TPLP+UNSPLP,[ + MOVEI TT,SCRTPC + CAMN C,[SIXBIT /.LPTR./] + IORM TT,SUPCOR ;CLOSING FILE ON TPL DEVICE SO SET FLAG FOR SYS JOB +];TPLP + CAMN C,[SIXBIT/.MAIL./] + AOS NQMFWR ;CLOSING FILE ON .MAIL. => BUMP COUNT TO WAKE MAILER DEMON +IFN XGP,[ + CAMN C,[SIXBIT/.XGPR./] + AOS NXGPFW ;WAKE XGPSPL +];XGP + MOVE A,QSNMI(H) ;TELL DIRHNG DEVICE ABOUT IT + PUSHJ P,DIRSIG + MOVE TT,QACTB ;DIR CHANGED (AT LEAST WRITE-IN-PROG BIT TURNED OFF) + IORM TT,QSNLCN(H) + PUSHJ P,QUDULK + SOSGE QSNNR(H) + BUG + PUSHJ P,QSTRTR + SETZM (R) ;CLEAR IOCHNM WORD. + POPJ P, + +QSOC3B: ADDI J,LUNBLK + JRST QSOC3C + +QOCLR: MOVE Q,QSRAC(A) ;CLOSE UNIT ASCII OUTPUT + TLNN Q,%QAWOV + TLNN Q,%QAMWO+%QALNK + PUSHJ P,QOCLPD ;PUT NEEDED PADDING UNLESS NOT A FILE OR NOT AT END + JRST QOCL + +QOCLPD: LDB Q,[360600,,QSMPRP(A)] ;NUMBER OF BITS NOT WRITTEN IN LAST WORD + CAIL Q,44 + POPJ P, ;LAST WORD NOT WRITTEN AT ALL + LSH Q,18.+6 ;FILL THOSE BITS WITH ^CS + HRR Q,QSMPRP(A) + MOVE C,[EOFWRD] + SKIPLE QSMPRC(A) ;INHIBIT STORE IF NO BUFFER ETC. + DPB C,Q + POPJ P, + +SUBTTL DISK INTERRUPT ROUTINES + +OVHMTR QIN ;DISK INTERRUPT LOW-LEVEL + +IFN RP10P,[ + +QINT: AOS QGTBZY + MOVEM TT,QCST +IFN DMDSK,[ + TRNN TT,200000 ;END OF CYLINDER + JRST QINT0 + SKIPGE C,QSDCH + BUG + MOVE D,QSGL(C) + IDIVI D,NBLKSC ;IS IT LEGITIMATE? + SKIPL QSDU ;IF NO TRANSFER IN PROGRESS, IGNORE + CAIN E,NBLKSC-1 ;IS LEGITIMATE FOR LAST BLOCK IN CYLINDER + CAIA ;IGNORE + BUG PAUSE,[MAYBE DISK CONTROL IS WRITING ALL OVER THE DISK AGAIN] +QINT0: ];DMDSK + TDNE TT,[17177700] ;ANY ERRORS? + JRST QINTE +QINTN2: DATAI DPC,R + SKIPGE QSDU ;DONT CLOB CMD BUF TO CLR ATTS DURING DATA XFER + TRNN R,776 ;ANY ATTNS + JRST QINTA ;NO + LDB I,[11000,,R] ;YES,FIND WHICH DRIVE + JFFO I,.+1 ;CLOBBERS Q + SUBI Q,28. + +QINTAT: DATAO DPC,QATTNS(Q) ;CLEAR ATTNS + DATAI DPC,E + TLNN E,40 + JRST QRECAT ;NOT ON CYLINDER, RECALIBRATE + LDB A,[DCYLI E] + TRNE E,.BM DCYLXI + ADDI A,400 + CAME A,QPOSGL(Q) + JRST QRECAT ;SEEK TO THE WRONG PLACE (CALCOMPS LIKE TO DO THIS) + MOVEM A,QPOS(Q) ;REMEMBER WHERE IT IS AT + SETZM QSEEK(Q) + SETZM QRCAL(Q) + JRST QINT ;TRY AGAIN + +QINTA: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING DATA COMPLETION - FIND NEW TRANSFER + CONSO DPC,400000 + CONSO DPC,10 + JRST DSKEX ;TRANSFER STILL IN PROGRESS, DISMISS + CONSZ DPC,20 + JRST .-1 ;BUSY? + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + JRST QINTA1 ;TRANSFER COMPLETE... + +QINTE: DATAI DPC,R + CONI DPC,TT ;THIS LOOKS REDUNDANT BUT APPARENTLY IS NECESSARY + ;DUE TO TIMING OF THE DISK-NOT-READY CONDITION + CONO DPC,175700+DSKCHN ;RESET CONDITIONS + MOVEM TT,QERST + MOVEM R,QERDTI + CONSZ DPC,20 ;WAIT FOR UNBUSY + JRST .-1 + MOVE Q,QSDU ;FOR QOVR + MOVE E,QCHPRG + TRNE TT,20000 ;OVERRUN + JRST QOVR + TRNE TT,2000 ;NOT READY + JRST QNRDY + TDNE TT,[12010700] ;BITS 14,16,23,27-29 ARE LOSERS + BUG HALT,[DSK: TOTALLY FATAL ERROR, CONI=],OCT,QERST + TLNE TT,5 ;WD OR SECTOR PARITY ERROR + JRST QDE + TRNE TT,1000 ;WRITE LOCKED + JRST QIRWRE + TRNE TT,40000 ;SEARCH FAILED + JRST QHE + TRNN TT,100000 ;POWER FAILURE + JRST QINTE1 + CONSZ DPC,100000 ;TRY IT AGAIN + JRST 4,.-1 + JRST QHE + +QINTE1: TLNE R,10 ;FILE UNSAFE--NEED OPERATOR INTERVENTION + BUG PAUSE,[DSK: FILE UNSAFE UNIT ],DEC,Q + TLNE R,4 + BUG ;NO SUCH DRIVE + TLNE R,110 ;POSITION FAILURE (OR PROCEEDED FILE UNSAFE) + JRST QHE + AOS NQSE(Q) ;SPURIOUS ERROR + JRST QINTX ;IGNORE + +QIRWRE: BUG PAUSE,[DSK: WRITE LOCKED UNIT ],DEC,Q + JRST QHE + +QNRDY: LDB Q,[410300,,R] ;WHICH DPC + SKIPN QSEEK(Q) + SKIPGE QRCAL(Q) ;NOT SEEKING OR RECALIBRATING IS ERROR + JRST QINTN2 + BUG PAUSE,[DSK: UNIT ],DEC,Q,[NOT READY] + JRST QREC +] ;END IFN RP10P + +IFN DC10P,[ + +QINT: MOVEM TT,QCST + SKIPL PKIDM ;GETS SPURIOUS DIPE WHEN READING PACK ID + CONSO DC1,7777 ;RUMOR THAT DSSERR DOESN'T ALWAYS SET + TRNE TT,DSSERR + JRST QINTE + TRNE TT,DSSATT + JRST QINTAT +QINTA: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING DATA COMPLETION, FIND NEW TRANSFER + CONSZ DC0,DSSRUN+DSSACT + JRST DSKEX ;ACTIVE OR RUN, TRANSFER IN PROGRESS, DISMISS + AOSN PKIDM ;SKIP IF NOT FINISHED READING PACK ID + JRST QSPKID + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + SKIPL QERS1 + JRST QEROK ;OK ON VERIFY + JRST QINTA1 ;TRANSFER COMPLETE... + +QINTE: CONI DC1,TT + CONO DC0,DCCLR+DCERR+DSKCHN ;CLEAR ERRORS + MOVEM TT,QERST + MOVE Q,QSDU + CONSZ DC0,DSSRUN+DSSACT + JRST .-1 ;ACTIVE OR RUN? + SKIPL QERS1 + JRST QERL1 ;VERIFY ALSO LOST + TRNE TT,DOFFL+DPROT+DDOBSY+DNXM+DCPERR + JRST QINTE1 ;REALLY LOST BIG + TRNE TT,DOVRRN + JRST QOVR + TRNE TT,DWTHER+DFUNSF ;SEEK INC, END DISK, WATCHDOG, OR UNSAFE + JRST QHE ;TRY TO RECALIBRATE + SKIPGE PKIDM + TRZ TT,DRLNER ;IGNORE LENGTH ERROR IF READING PACK # + TRNE TT,DIPE+DRLNER+DRCER+DCKSER + JRST QDE ;TRY AGAIN + SKIPGE PKIDM + TRNE TT,-1 + AOS NQSE ;SPURIOUS ERROR (NOT LENGTH ERROR IN PKIDM) + JRST QINTX ;SPURIOUS ERROR + +QINTE1: TRNE TT,DOFFL + BUG PAUSE,[DSK: UNIT ],DEC,Q,[OFFLINE] + TRNE TT,DPROT + BUG PAUSE,[DSK: UNIT ],DEC,Q,[WRITE PROTECTED] + TRNE TT,DDOBSY + BUG PAUSE,[DSK: DATAO WHEN BUSY] + TRNE TT,DNXM+DCPERR + BUG PAUSE,[DSK: MEM PAR OR NXM ERROR] + JRST QOVR + +QINTAT: CONI DC1,Q + CONO DC0,DCCLR+DCCATT+DSKCHN ;CLEAR ATTENTION + LDB Q,[DSATDN Q] ;ATTENTION DRIVE NUMBER + CAIGE Q,NQS + SKIPL QRCAL(Q) + JRST QINTX + SETZM QRCAL(Q) + CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE + JRST QINTX + +;THIS IS CALLED EVERY HALF SECOND +QRCTMO: MOVEI Q,NQS-1 + SKIPL QRCAL(Q) +QRCTM1: SOJGE Q,.-1 + JUMPL Q,CPOPJ + SOSL QRCTIM(Q) + JRST QRCTM1 + BUG INFO,[DSK: RECAL TIMEOUT UNIT],DEC,Q + SETZM QRCAL(Q) + CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE I GUESS + JRST QRCTM1 +];DC10P + +IFN RH11P,[ + +;;; RHCLRC(Q) Clear controller errors and select drive Q +;;; RHSLCT(Q) Select drive Q +;;; RHCMD(A) Command in A to current drive +;;; RHCLRD Clear current drive +;;; RHCHEK Check for immediate bad news +;;; All return CS1 in A + +RHSLCT: IOWRQ Q,%HRCS2 +RHCHEK: IORDQ A,%HRCS1 + TRNE A,%HXTRE+%HXMCP + BUG HALT,[DSK: MASSBUS ERROR, CS1=],OCT,A + POPJ P, + +RHCLRC: IOWRQ Q,%HRCS2 ; Must select drive before clearing controller + MOVEI A,%HXTRE+%HXIE+%HMNOP +RHCMD: TROA A,%HXIE +RHCLRD: MOVEI A,%HXIE+%HMCLR + IOWRQ A,%HRCS1 + JRST RHCHEK + +EBLK +DSKBRK: 0 +BBLK + JSR UTCSAV +QINT: AOS QGTBZY + MOVE Q,QSDU + IORDQ TT,%HRCS1 + MOVEM TT,QCST + TRNE TT,%HXTRE+%HXMCP + JRST QINTE + TRNN TT,%HXSC ; Perhaps some drive needs attention? + JRST QINT0 ; Not unless SC is set! + IORDQ A,%HRATN + JFFO A,QINTAT +QINT0: SKIPGE Q,QSDU + JRST QINT1 ; Not expecting completion of transfer. + TRNN TT,%HXRDY + JRST DSKEX ; Transfer still in progress. + AOSN QHUNGF + JRST QHE ; Transfer hung, recalibrate and retry. + PUSHJ P,RHSLCT ; Select that drive. + IORDQ A,%HRSTS ; Get its status. + TRNE A,%HSERR ; Just in case %HXTRE didn't get set (by + JRST QINTE ; analogy with RH10)... + JRST QINTA1 ; Transfer complete... + +QINTAT: MOVNI Q,-35.(B) + HRRZS Q + MOVEI A,1 + LSH A,(Q) + IOWRQ A,%HRATN ; Turn off attention bit. + CAIL Q,NQS + JRST QINT0 + CAMN Q,QSDU + JRST [ AOS NQSATN(Q) ; Ignore attention in mid-transfer. + JRST QINTA2 ] + SKIPE QACT(Q) + JRST QINTA2 ; Ignore this drive. + PUSHJ P,RHSLCT + IORDQ B,%HRSTS ; Get status of drive with attention. + TRC B,%HSMOL+%HSDPR+%HSRDY + TRNN B,%HSMOL+%HSDPR+%HSRDY+%HSVV + PUSHJ P,QOFFL ; Went offline and came back online + TRNE B,%HSERR+%HSPIP + JRST [ PUSHJ P,RHCLRD ; Drive barfing not during transfer + AOS NQEATN(Q) ; so clear it + JRST .+1] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS + SETZM QSEEK(Q) ;POSITIONING COMPLETION +IFDEF %HRCCY,[ ;Current Cyl register only on RP disks + IORDQ A,%HRCCY + MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER + CAME A,QPOSGL(Q) + SETOM QSKT1(Q) ;SEEK TO WRONG PLACE +];IFDEF %HRCCY +IFNDEF %HRCCY,[ + MOVE A,QPOSGL(Q) ;On RMxx, jump to conclusion + MOVEM A,QPOS(Q) +];IFNDEF %HRCCY + SETZM QRCAL(Q) ;NO LONGER RECALIBRATING + JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON + ; THIS UNIT NOW + +QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS + JRST DSKEX + +; Went offline and came back online +QOFFL: TRC B,%HSMOL+%HSDPR+%HSRDY ;Recover %HRSTS + IORDQ C,%HRER1 + IORDQ D,%HRER2 +IFDEF %HRER3,[ + IORDQ E,%HRER3 + BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D,[ER3=],OCT,E +] +IFNDEF %HRER3,[ + BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D +] + + AOS NQOFFL(Q) + MOVEI A,%HMCLR ;Clear the drive + PUSHJ P,RHCMD + MOVEI A,%HMRDP ;I said, clear the drive! + PUSHJ P,RHCMD + MOVEI A,0 + IOWRQ A,%HROFS ;No offset, 18 bits, ECC on, HCI off + MOVEI A,%HMACK ;Turn %HSVV back on so drive will work + PUSHJ P,RHCMD + POPJ P, + +QINTE: +IRPS X,,[CS1 CS2 BA WC POS PAT] ; First get status of controller + IORDQ A,%HR!X + MOVEM A,QER!X +TERMIN + IORDQ A,UBAPAG+QUBPG_1 ; Unibus map counts as part of + MOVEM A,QERMAP ; controller status. + IORDQ A,UBAPAG+QUBPG_1+1 + MOVEM A,QERMAP+1 + SKIPGE Q ; Try hard to guess the drive. + LDB Q,[$HYDSK QERCS2] + PUSHJ P,RHCLRC ; Clear controller errors and select drive + ; so that we can read its status too. + TRNN A,%HXRDY ; Why would controller be busy? (RH10 + BUG ; code checks for this...) + +IRPS X,,[STS ER1 ER2] + IORDQ A,%HR!X + MOVEM A,QER!X +TERMIN + MOVE A,QERCS1 ; A: CS1 + MOVE R,QERCS2 ; R: CS2 +IFDEF %HRER3,[ ; Disks with ER2 -and- ER3 + IORDQ A,%HRER3 + MOVEM A,QERER3 + SKIPN QERER2 ; Bad news + SKIPE QERER3 + JRST UNSAFE +] +IFNDEF %HRER3,[ ; Disks with just ER2 + SKIPE QERER2 + JRST UNSAFE +] + TRNN A,%HXMCP ; Real bad news + TRNE R,%HYWCE+%HYPE+%HYNED+%HYNEM+%HYPGE+%HYMXF + BUG HALT,[DSK: UNIT #],DEC,Q,[LOSING. CS1=],OCT,A,[ CS2=],OCT,R + TRNE R,%HYDLT+%HYMDP ; Data bus losing? + JRST QINTE1 + MOVE A,QERSTS ; Check Drive Status + TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ; Better be all on! + TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL + BUG + TRNN A,%HSERR + JRST [ AOS NQSE(Q) ; Spurious? + JRST QINT0] + MOVE B,QERER1 ; Check the main error register + TRNE B,#<%H1ECC+%H1DTE+%H1CRC+%H1HCE+%H1ECH+%H1FER+%H1PAR> + JRST UNSAFE ; Those not listed above are considered "hard" + CAIN B,%H1ECC ; Correct correctable error if that is the + JRST QECC ; only problem. + PUSHJ P,QINTER ; Else print message and reset drive + TRNE B,%H1DTE+%H1CRC+%H1HCE+%H1FER ; These require recalibration + JRST QHE + TRNE B,%H1ECC+%H1ECH+%H1PAR ; These require reread + JRST QDE + JRST QOVR ; No error bits set? (How can this + ; happen?) Go and retry... + +;;; Controller error: +QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CS1=],OCT,QERCS1,[CS2=],OCT,QERCS2 + JRST QOVR + +;;; Drive error: +IFDEF %HRER3,[ +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA +] +IFNDEF %HRER3,[ +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[STARTING DISK ADDR=],OCT,QCHPGA +] + JRST RHCLRD ; Reset error status in drive + +;;; Come here for drive unsafe and similar bad things. May be set to +;;; either halt or attempt retry (via USFHLT variable). Note that when we +;;; get here the state of the drive has not yet been disturbed. +UNSAFE: SKIPE USFHLT + BUG PAUSE,[DSK: TOO MANY ERRORS] + MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND + MOVEM A,USFHLT + PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE + SKIPL QSDU + JRST QHE ;RECALIBRATE AND RETRY + JRST QREC ;Just recalibrate, no transfer to retry + +QECC: PUSHJ P,RHCLRD ; Reset drive + CAME Q,QSDU ; ECC error better be for transfer in + BUG ; progress... + MOVE A,QCHPRG + TRNN A,10 .SEE %HMRED + BUG ; ECC error should only happen during read. + LDB A,[$UPPAG QERMAP] + IORI A,600000 + DPB A,[.PAREP+EXEUMP] ; Point parity error page at buffer. + CLRPT 400000+PAREP_12 ; Get it into our map now. + CLRPT 401000+PAREP_12 ; Both halves... + MOVE J,QERBA + SUBI J,1000+QUBPG_14 ; Correct to relative byte address of start + ; of losing sector. + TRNE J,770777 ; Should always be aligned on sector boundary + BUG ; and within a single block, right? + LSH J,-2 ; J: Address of first word of losing sector + ; within block. + MOVE A,QECPOS ; Get error position + SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE + IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO + CAIL A,177 + JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM + SOJA A,.+1] + ADDI J,400000+PAREP_12(A) ; J: Address of losing word-pair + ; (In parity error page.) + MOVE U,B ;SAVE BIT NUMBER + MOVS B,(J) ;GET FIRST LOSING WORD + MOVS C,1(J) ;GET SECOND LOSING WORD + MOVE D,QECPAT ;GET ERROR PATTERN + SETZ E, ;MAKE INTO DOUBLE-WORD + ROTC D,(U) ;ALIGN IT + XOR B,D ;FIX THE BAD BITS + XOR C,E + MOVSM B,(J) ;PUT CORRECTED DATA BACK + MOVSM C,1(J) + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP + CLRPT 400000+PAREP_12 + CLRPT 401000+PAREP_12 ; Both halves... + + AOS QECCS(Q) ;LOG THE LOSS + LDB E,[111000,,QERBA] ; E: Number of sectors transferred (including + SUBI E,QUBPG_3 ; ECC sector) + MOVE A,QCHPGA + LDB B,[$HASEC A] ;Compute disk address of failing sector: + ADDI B,-1(E) + IDIVI B,NSECS ; C: sector + DPB C,[$HASEC A] + LDB D,[$HATRK A] + ADD B,D ; B: track + DPB B,[$HATRK A] + MOVEM A,QECCAD(Q) + HLRZ A,A ; A: cylinder + MOVE D,QSDCH ; D: chnl + BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT #],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D) + CAIL E,SECBLK + JRST QINTA1 ;XFER COMPLETE + + LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER + ADD B,E + IDIVI B,NSECS + DPB C,[$HASEC QCHPGA] + LDB C,[$HATRK QCHPGA] + ADD C,B + DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS + ; CYLINDERS + + HRL E,QERWC ; Reassemble "iowd" from + HRR E,QERBA ; saved parts. (Don't trust stuff saved + MOVEM E,QIOWD ; in controller more than we have to.) + HRRZ C,QSDCH ;FOR QECCX + JRST QECCX ;MORE TO DO, CONTINUE XFER + +] ;RH11P + +IFN RH10P,[ + +QINT: AOS QGTBZY + MOVE Q,QSDU + MOVEM TT,QCST + TRNE TT,%HIERR + JRST QINTE + TRNN TT,%HIATN + JRST QINT0 + MOVSI A,%HRATN ;FIND DRIVES NEEDING ATTENTION + PUSHJ P,RHGET + JFFO A,QINTAT +QINT0: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING COMPLETION OF TRANSFER + TRNN TT,%HIDON + JRST DSKEX ;NO COMPLETED TRANSFER + CONSZ DSK,%HIBSY + JRST 4,.-1 ;TRANSFER STILL IN PROGRESS?? + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + MOVSI A,%HRSTS(Q) ;SOMETIMES %HSERR SETS AND %HIERR DOESN'T! + PUSHJ P,RHGET + TRNE A,%HSERR + JRST QINTE + JRST QINTA1 ;XFER COMPLETE... + +QINTAT: MOVNI Q,-35.(B) ;LOW BIT IS DRIVE 0 + HRRZS Q + MOVEI A,1 ;TURN OFF ATTENTION (DRIVE MAY BE LOSING + LSH A,(Q) ;IN SUCH A WAY THAT READING %HRSTS DOESN'T CLEAR ATTN) + HRLI A,%HRATN + PUSHJ P,RHSET + CAMN Q,QSDU + JRST [ AOS NQSATN(Q) ;IGNORE ATTN IN MID-TRANSFER + JRST QINTA2 ] + MOVSI A,%HRSTS(Q) ;GET STATUS OF DRIVE WITH ATTENTION + PUSHJ P,RHGET ;THIS ALSO CLEARS THE ATTENTION BIT + SKIPE QACT(Q) + JRST QINTA2 ;IGNORE THIS DRIVE + TRNE A,%HSERR+%HSPIP + JRST [ MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR ;DRIVE REPORTING ERROR NOT DURING TRANSFER + PUSHJ P,RHSET ;SO CLEAR THE DRIVE + AOS NQEATN(Q) + JRST .+1 ] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS + SETZM QSEEK(Q) ;POSITIONING COMPLETION + MOVSI A,%HRCCY(Q) + PUSHJ P,RHGET + MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER + CAME A,QPOSGL(Q) + SETOM QSKT1(Q) ;SEEK TO WRONG PLACE + SETZM QRCAL(Q) ;NO LONGER RECALIBRATING + JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON THIS UNIT NOW + +QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS + JRST DSKEX + +;INPUT FROM MASSBUS - ADDRESS IN LH(A), RETURNS DATA IN A + +RHGET: TLZA A,%HRLOD + +;OUTPUT TO MASSBUS - ADDRESS IN LH(A), DATA IN RH(A) + +RHSET: TLO A,%HRLOD + DATAO DSK,A + MOVEM A,RHDATO ;SAVE FOR REBUGGING + MOVEI A,5 ;WAIT 3 USEC FOR BUS CYCLE + SOJG A,. + DATAI DSK,A + TLNE A,%HDERR + BUG HALT,[DSK: MASSBUS ERROR, DATAO=],OCT,RHDATO,[DATAI=],OCT,A + ANDI A,177777 ;RETURN 16-BIT REGISTER CONTENTS + POPJ P, + +QINTE: CONI DSK,TT + DATAI DSK,R + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN ;RESET CONTROLLER SO DRIVE STATUS MAY BE READ + CONSZ DSK,%HIBSY + JRST .-1 ;SOMETIMES CONTROLLER IS BUSY?? + MOVEM TT,QERST + MOVEM R,QERST+1 + SKIPGE Q ;TRY HARD TO GUESS THE RIGHT DRIVE! + LDB Q,[$HCDRV R] ;CURRENTLY SELECTED DRIVE + IRPS X,,[%HRSTS %HRER1 %HRER2 %HRER3 %HRDCL %HRPOS %HRPAT] + MOVSI A,X(Q) ;GET STATUS OF DRIVE + PUSHJ P,RHGET + MOVEM A,QERST+.IRPCNT+2 + TERMIN + SKIPN QERER2 ;FILE UNSAFE + SKIPE QERER3 + JRST UNSAFE + TRZE TT,%HIDRE + AOS NQDRE(Q) ;THIS BIT SUSPECTED OF BEING SET RANDOMLY. + ;;CHECK FOR IRRECOV (?) HARDWARE LOSSAGE. EVEN MORE SO THAN 'UNSAFE' + TDNE TT,[%HIILF+%HISDE+%HINXM+%HIDRE+%HIILC+%HIPWR] + BUG HALT,[DSK: UNIT ],DEC,Q,[ LOSING. RH10 CONI= ],OCT,QERST +IFN KS10P, .ERR So whats this all about? +IFN KL10P,[ + TLNN TT,(%HIDPE+%HICPE) ;IF CHANNEL DETECTS PARITY ERROR, CAUSE + JRST QINTE0 ;PROCESSOR PARITY SWEEP WHICH WILL PROBABLY + MOVSI A,SCLPAR ;CRASH THE SYSTEM ANYWAY. BEATS LOOPING! + TDNN A,SUPCOR ;BUT DON'T CAUSE CLKB1E+7 HALT + CONO 10407 + BUG CHECK,[DSK: MEM PAR ERR, QICWA/],OCT,QICWA,OCT,QICWA+1,[QIOWD/],OCT,QIOWD +QINTE0: +];KL10P + TDNE TT,[%HIOVR+%HICOV+%HIDPE+%HICPE+%HIBPE] + JRST QINTE1 ;OVERRUN OR PARITY ON CONTROL BUS OR CHANNEL BUS - RETRY + MOVE A,QERSTS ;DRIVE EXCEPTION, CHECK DRIVE STATUS + TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ;THESE BITS BETTER ALL BE ON + TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL + BUG ;DRIVE TURNED OFF? MAYBE 11 HACKING THIS DRIVE? + TRNN A,%HSERR + JRST [ AOS NQSE(Q) ;SPURIOUS? + JRST QINT0 ] + MOVE B,QERER1 ;CHECK THE MAIN ERROR REGISTER + TRNE B,#%H1SOF ;ANY HARD ERRORS? + JRST UNSAFE + CAIN B,%H1ECC ;IF JUST A CORRECTABLE ERROR, + JRST QECC ;GO CORRECT IT + PUSHJ P,QINTER ;OTHER SOFT ERROR, PRINT MESSAGE AND RESET DRIVE + TRNE B,010620 ;SEARCH ERROR, OR HEADER READ OR FORMAT ERROR OR DRIVE TIMING + JRST QHE ;REQUIRES RECALIBRATE + TRNE B,100110 ;BUS PARITY OR ECC "HARD" + JRST QDE ;REQUIRES RE-READ, GIVE UP AFTER N + JRST QOVR ;NO ERROR BITS, PRINT MESSAGE AND RETRY + +;CONTROLLER ERROR +QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CONI=],OCT,QERST,[DCL=],OCT,QERDCL + JRST QOVR + +;DRIVE ERROR +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA + MOVSI A,%HRDCL(Q) ;NOW RESET ERROR STATUS IN DRIVE + HRRI A,%HMCLR + JRST RHSET + +;COME HERE FOR DRIVE UNSAFE AND SIMILAR BAD THINGS. MAY BE SET TO +;EITHER HALT OR ATTEMPT RETRY (VIA USFHLT VARIABLE). NOTE THAT WHEN +;WE GET HERE THE STATE OF THE DRIVE HAS NOT YET BEEN DISTURBED. +UNSAFE: SKIPE USFHLT + BUG PAUSE,[DSK: TOO MANY ERRORS] + MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND + MOVEM A,USFHLT + PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE + JRST QHE ;RECALIBRATE AND RETRY + +QECC: MOVSI A,%HRDCL(Q) ;RESET ERROR STATUS IN DRIVE + HRRI A,%HMCLR + PUSHJ P,RHSET + CAME Q,QSDU ;CORRECT AN ECC ERROR + BUG ;BARF ... NO TRANSFER IN PROGRESS + MOVE A,QCHPRG + TRNN A,10 + BUG ;BARF ... SHOULDN'T HAPPEN DURING WRITE + SKIPN A,QICWA+1 ;GET ADDRESS OF LAST WORD READ + JRST 4,.-1 ;CHANNEL OUGHT TO HAVE STORED CONTROL WORD BY NOW + SOS J,A + TDZ J,[177+.BM $DFCWA] ;J := ADDRESS OF FIRST WORD IN LOSING SECTOR + LDB A,[$DFCAD QIOWD] + SUBM J,A + SOS H,A ;# WORDS SUCCESSFULLY XFERED. + CAIL H,0 ;CHECK IF CHANNEL STORED BAD ADDRESS + CAILE H,2000-200 + JRST QDE ;THIS SHOULD NEVER HAPPEN, BUT IT DOES, FREQUENTLY + MOVE A,QECPOS ;GET ERROR POSITION + SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE + IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO + CAIL A,177 + JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM + SOJA A,.+1] + ADD J,A ;J := ADDRESS OF LOSING WORD-PAIR + LDB A,[121400,,J] + ANDI J,1777 ;GET ADDR OF PAR ERR PAG + ADDI J,400000+2000*PAREP ;IN EXEC ADDRESS SPACE + IORI A,600000 ;MAKE THAT PAGE POINT TO THE DISK BUFFER + DPB A,[.PAREP+EXEUMP] + SPM ECCPAG ;GET IT INTO OUR MAP. + LPMR ECCPAG + MOVE U,B ;SAVE BIT NUMBER + MOVS B,(J) ;GET FIRST LOSING WORD + MOVS C,1(J) ;GET SECOND LOSING WORD + MOVE D,QECPAT ;GET ERROR PATTERN + SETZ E, ;MAKE INTO DOUBLE-WORD + ROTC D,(U) ;ALIGN IT + XOR B,D ;FIX THE BAD BITS + XOR C,E + MOVSM B,(J) ;PUT CORRECTED DATA BACK + MOVSM C,1(J) + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP + LPMR ECCPAG + + AOS QECCS(Q) ;LOG THE LOSS + MOVE A,QCHPGA + MOVEI E,200(H) + LSH E,-7 ;NUMBER OF SECTORS TRANSFERRED (INCLUDING ECC SECTOR) + LDB B,[$HASEC A] ;GET DISK ADDR OF FAILING SECTOR + ADDI B,-1(E) + IDIVI B,NSECS + DPB C,[$HASEC A] + LDB D,[$HATRK A] + ADD B,D + DPB B,[$HATRK A] ;NO NEED TO DIVIDE BY NHEDS SINCE NEVER CROSS CYLINDERS + MOVEM A,QECCAD(Q) + HLRZ A,A + MOVE D,QSDCH + BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT ],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D) + LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER + ADD B,E + IDIVI B,NSECS + DPB C,[$HASEC QCHPGA] + LDB C,[$HATRK QCHPGA] + ADD C,B + DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS CYLINDERS + HRRZ C,QSDCH ;FOR QECCX + LDB A,[$DFCWA QICWA+1] ;LAST CONTROL WORD PROCESSED + SUBI A,1 ;CRETINOUS DF10 + CAIE A,QIOWD + BUG ;CHANNEL STORED BAD ADDRESS? + HRRZM A,QICWA + MOVEI A,200(H) ;# WORDS ALREADY DONE. + DPB A,[$DFWC A] ;PUT IT IN BOTH FIELDS. + ADDB A,@QICWA ;ADVANCE C.W. TO REMAINING STUFF + TLNE A,(.BM $DFWC) + JRST QECCX ;MORE TO DO, CONTINUE XFER + AOS QICWA ;ELSE ADVANCE TO NEXT C.W. + SKIPE @QICWA + JRST QECCX ;MORE TO DO, CONTINUE XFER + JRST QINTA1 ;XFER COMPLETE +] + +IFN T300P,[ +T3INT: SETZM DSCDON ;CLEAR DONE FLAG THAT GOT US HERE + SKIPGE QSDU1 ;OPERATION COMPLETE? + JRST QINT1 ;NO, GO FIND SOMETHING TO DO + HRRZ Q,DSCDRV ;YES, GET DRIVE OPERATION WAS ON + ADDI Q,T300P + CAIGE Q,NQS + CAME Q,QSDU1 ;TERMINATION ON DRIVE WE EXPECTED? + BUG ;DRIVE NUMBER CLOBBERED? + SETZM QRCAL(Q) ;PRESUMABLY NOT RECALIBRATING ANY MORE. + MOVE A,DSCCMD ;COMMAND THAT JUST COMPLETED + CAIN A,%DMREC ;WAS IT A RECALIBRATE? + JRST QINT1E ;IF SO, CONTROLLER IS IDLE NOW + MOVE C,QSDCH1 ;CHANNEL + HRLZ E,DSCFLT ;CHECK FOR ERRORS + HRR E,DSCSTS + JUMPE E,QINTI ;OPERATION COMPLETED UNEVENTFULLY + MOVE D,DSCHED ;GET DISK ADDRESS AS CYL,,HEAD_9+SECTOR + LSH D,9 + IOR D,DSCSEC + HRL D,DSCCYL + SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES + BUG INFO,[DSK: T-300 ERR UNIT ],DEC,Q,[FAULT=],OCT,DSCFLT,[STATUS=],OCT,DSCSTS,[CMD=],OCT,DSCCMD,[CYL-SURF-SEC=],OCT,D + TRZE E,%DSRTR+%DSECC ;THESE ARE NOT ERRORS + AOS QECCS(Q) + JUMPE E,QINTI ;OPERATION COMPLETED SUCCESSFULLY (WITH INTERVENTION OF 2561) + MOVE T,E + TRZ T,%DSECH+%DSIDE+%DSHCE + JUMPN T,T3INT2 ;CONSIDER USING ERROR RECOVERY FEATURES + TRNE A,%DMRED ;IF COMMAND IS A READ + TRNE A,10 ;AND WE HAVEN'T TRIED THEM ALL + JRST T3INT2 + AOS NQSE(Q) ;COUNT "SOFT ERRORS" (NOT "SPURIOUS" IN T-300 CASE) + AOJA A,T3IO1 ;GO RETRY OPERATION USING NEXT FEATURE + +T3INT2: TLNN E,-1 ;ANY FAULT? PROBABLY UNRECOVERABLE BUT TRY RECALIBRATE + TRNE E,%DSIDE+%DSHCE+%DSSKE+%DSOFL+%DSFLT ;DISK CONDITION THAT CALLS FOR RECAL + JRST T3HE + JRST T3DE ;TRY OPERATION AGAIN. PROBABLY WILL LOSE BUT TRY. +];T300P + +OVHMTR QSC ;DISK SCHEDULER (AND HIGHER-LEVEL INTERRUPT STUFF) + +QINTA1: SKIPL C,QSDCH ;XFER COMPLETE +QINTI: SKIPGE A,QSCABN(C) ;CHANNEL IN C + BUG ;MEMBLT INDEX IN A + MOVE R,A ;BUFFER ADDRESS IN R +IFN KL10P,[ ;QSRAC IN D, QSK# IN Q + SKIPL QSCRW(C) ;IF READ, FLUSH CACHE AGAIN + JRST [ PUSHJ P,CSHSWP ;SINCE USER MIGHT HAVE TOUCHED ABS PAGE + CAIA + MOVE A,R ;A WAS CLOBBERED + JRST .+1 ] +] +IFN KS10P,[ + SKIPL QSCRW(C) ;ON KS, CAN ONLY CLEAR THE WHOLE CACHE + CLRCSH +] + LSH R,10. + MOVE D,QSRAC(C) +IFN RP10P,[ + HRRZ TT,QICWA+1 + CAIE TT,1777(R) + TLNE D,%QAPAR ;IGNORE IF LOSING ANYWAY (E.G. SEARCH ERR) + CAIA + JRST QDFLOS +];RP10P +IFN QRDCMP,[ + SKIPE TT,RDCPHS ;NEED TO READ-COMPARE? + JRST QRC1 ;READ-COMPARE STARTING OR FINISHED +QRC0: +];QRDCMP + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE COMPLETION HANDLER + OFFSET -. +%QMIDL::JRST 4,QINT1 ;IDLE - SHOULDN'T BE ACTIVE +%QMRD:: JRST QRDFIN ;READ +%QMWRT::JRST QWRFIN ;WRITE +%QMWOV::JRST QWOVFN ;WRITE-OVER MODE +%QMRD1::JRST QRD1FN ;READ BLOCK AT A TIME MODE + JRST 4,QINT1 ;ILL CODE +%QMUDR::JRST QUDRIN ;USER DIR IN +%QMMDR::JRST QMDRIN ;MASTER DIR IN +%QMTTR::JRST QTUTIN ;TUT IN +%QMUDW::JRST QUFDWF ;USER DIR WRITE +%QMMDW::JRST QMFDWF ;MASTER DIR WRITE +%QMTTW::JRST QTUTWF ;TUT WRITE +%QMSWP::JRST QSWPFN ;SWAP FINISHED + JRST 4,QINT1 ;ILL CODE + JRST 4,QINT1 ;ILL CODE + JRST 4,QINT1 ;ILL CODE +%QMMAX::OFFSET 0 +IFN %QMMAX-20, .ERR %QMMAX MUST BE A POWER OF 2 + +IFN RP10P,[ +;CHANNEL DIDN'T TRANSFER EXACTLY 2000 WORDS +QDFLOS: MOVEI D,1777(R) ;EXPECTED TERMINATION ADDRESS + HRRZ B,QICWA+1 ;ACTUAL TERMINATION ADDRESS + CAIL B,(D) + SKIPL QSCRW(C) + JRST QDFLZ1 + BUG HALT,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D,[DISK IS CLOBBERED NOW.] + +QDFLZ1: BUG PAUSE,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D + JRST QOVR +];RP10P + +;;; SOFTWARE READ-COMPARE ROUTINES + +IFN QRDCMP,[ +IFE RP10P+RH10P, .ERR READ-COMPARE ONLY CODED FOR RP-10 AND RH10 +;IFE KA10P, .ERR READ-COMPARE ONLY CODED FOR KA-10 + +;;; REGULAR OPERATION COMPLETE, DO A READ-COMPARE TO BE SURE +QRC1: +IFN T300P, CAIGE Q,T300P ;NO READ/COMPARE IF THIS IS T-300 CONTROLLER + TLNE D,%QAPAR ;GIVING UP WITH FATAL ERR? + JRST QRC0 ;NO READ-COMPARE THEN + JUMPG TT,QRC2 ;JUMP IF READ-COMPARE COMPLETED + MOVE E,QSGL(C) ;DISK BLOCK + PUSHJ P,QPOSR ;E GETS DATAO WORD +IFN RP10P,[ + IOR E,[DREADC+7000+RCICWA] ;MAKE READ COMMAND + CONO DPC,175700+DSKCHN + MOVE T,[-2000,,QRCBUF-1] ;STORE CHANNEL PROGRAM + MOVEM T,RCIOWD + SETZM RCIOWD+1 + MOVEI T,RCIOWD + MOVEM T,RCICWA + SETZM RCICWA+1 + DATAO DPC,E ;START DISK +];RP10P +IFN RH10P,[ + MOVE T,[-2000_4,,QRCBUF-1] ;DF10-C CHANNEL PROGRAM + MOVEM T,RCIOWD + SETZM RCIOWD+1 + MOVEI T,RCIOWD + MOVEM T,RCICWA + SETZM RCICWA+1 + SWPUA ;DUMP CACHE + CONSZ 200000 ;IT'S INEFFICIENT, BUT WHAT THE HELL + JRST .-1 + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN + MOVSI A,%HRADR(Q) + HRR A,E ;HEAD AND SECTOR (CYL DOESN'T CHANGE) + PUSHJ P,RHSET + MOVEI A,%HMRED+ + TLO A,%HRCTL(Q) + PUSHJ P,RHSET ;START DISK +];RH10P + MOVEM T,RDCPHS ;RDCPHS POSITIVE MEANS DOING RD/CMP NOW + JRST DSKEX ;AWAIT COMPLETION + +;;; READ-COMPARE COMPLETED. CHECK IT. +QRC2: SPM PARPG ;SET UP MAP TO PAGE BEING READ/WRITTEN + MOVEI T,600000+PMCSHM(A) + DPB T,[.PAREP+EXEUMP] + LPMR PARPG + MOVEI H,0 ;H DIFFERENCE COUNT +IFN KA10P,[ + PUSH P,A ;WILL DO COMPARE LOOP IN ACS + PUSH P,C + PUSH P,D + MOVSI E,-2000 ;E ADDRESS WITHIN PAGE + MOVSI D,[ MOVE T,400000+PAREP*2000(E) ;A + CAMN T,QRCBUF(E) ;B + AOBJN E,A ;C + JRST QRC3 ] ;D + HRRI D,A + BLT D,D + JRST A +];KA10P +.ELSE [ + MOVSI E,-2000 ;E ADDRESS WITHIN PAGE + MOVE T,400000+PAREP*2000(E) + CAMN T,QRCBUF(E) +QRC2A: AOBJN E,.-2 +];NOT KA10P +QRC3: JUMPGE E,QRC5 ;JUMP IF DONE + JUMPG H,QRC4 ;COMPARE ERROR, REPORT IT + AOS NQCMPE(Q) +IFN KA10P,[ + MOVE T,-1(P) ;SAVED C + BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(T) +];KA10P +.ELSE BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(C) +QRC4: ADDI H,1 + HRRZ T,E + CAIG H,4 ;ONLY REPORT FIRST 4 BAD WORDS + BUG INFO,[DSK: READ-COMPARE DIFFERENCE ],OCT,T,OCT,400000+PAREP*2000(E),OCT,QRCBUF(E) +IFN KA10P,JRST C +.ELSE JRST QRC2A + +QRC5: +IFN KA10P,[ + POP P,D + POP P,C + POP P,A +];KA10P + MOVEI T,0 ;CLEAR MAP + DPB T,[.PAREP+EXEUMP] + LPMR PARPG + JUMPE H,QRC0 ;NO DIFFERENCE, I/O OPERATION IS DONE + CAILE H,4 ;FAILED, DO IT ALL OVER AGAIN + BUG INFO,[DSK: READ-COMPARE DIFFERENCES TOTAL],DEC,H + JRST QOVR +];QRDCMP + +QUFDWF: MOVE TT,QDWIP + CAMN Q,MDSK ;WRITTEN TO MASTER DISK? + SKIPN E,QSFBT(TT) ;AND HAVE SOME BLOCKS TO FREE? + JRST QUDWF1 + SETZM QSFBT(TT) ;YES, TRANSFER THEM TO QFBTS LIST + MOVE T,E ;E FINDS LAST OF LIST, T RPLACD'D IN THERE + EXCH T,QFBTS ;NCONC QSFBT ONTO FRONT OF QFBTS + SKIPE 1(E) + JRST [ MOVE E,1(E) + JRST .-1 ] + MOVEM T,1(E) + SKIPN T + AOS NCORRQ ;WAKE UP CORE JOB IF QFBTS HAD BEEN EMPTY +QUDWF1: JSP D,QDWF + QSNLCN(TT) + +QMFDWF: JSP D,QDWF + QMDRO + +QTUTWF: AOS T,QSGL(C) ;NEXT BLOCK TO GO OUT + AOS QSCABN(C) ;FROM NEXT CORE PAGE + CAIGE T,MFDBLK ;SKIP IF DONE + JRST QINT1E ;WRITE MORE + JSP D,QDWF + QTUTO(TT) + +QDWF: MOVSI E,(SETZ) ;UNLOCK DIR THAT WAS WRITTEN + IOR E,DCHBT(Q) ;COPY ON THIS DISK IS NOW UP TO DATE + MOVE TT,QDWIP + ANDCAM E,@(D) + HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL + SETOM DWUSR + JRST QINT1A ;DON'T COUNT THIS AS DISK ACTIVITY + +QUDRIN: MOVE TT,QUDPR(C) ;USER DIR IN OK + MOVE D,UDNAME(R) + CAME D,QSNUD(TT) ;COMPARE UNAME IN DIR WITH RQ'ED + JRST QUDER1 + TLO R,40000 ;NOT PAWED OVER + MOVEM R,QSNLCN(TT) + MOVE R,QSLGL(C) + MOVEM R,QSNMI(TT) + MOVEI R,MU23UD ;USER DIRECTORY + PUSH P,A + PUSH P,C + MOVE C,TT + PUSHJ P,QDIRCK ;VERIFY NOT TOTALLY BASHED TO BEGIN WITH + POP P,C ;CLOBBERS A,B,I + POP P,A +QINTU4: DPB R,[MUR,,MEMBLT(A)] + DPB TT,[MNUMB,,MEMBLT(A)] +QTUTI1: SETOM QUSR(C) ;FREE THE DISK CHANNEL + AOS QFCHN + JRST QINT1A + +QMDRIN: TLO R,2 ;NOT RECONCILED + MOVEM R,QMDRO ;MASTER DIRECTORY IN + MOVE TT,MDCHK(R) + CAME TT,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] + MOVE TT,MDNUDS(R) + CAIE TT,NUDSL + BUG HALT,[MFD HAS WRONG NUMBER OF DIRECTORIES] + MOVE TT,(R) ;ASCENDING DIR # + SKIPGE QAMDNO + MOVEM TT,QAMDNO ;FIRST DISK IN STORE ASCENDING # + MOVEI R,MU23MD ;MASTER DIRECTORY + MOVE TT,Q ;DISK NO + JRST QINTU4 + +QTUTIN: AOS T,QSGL(C) ;NEXT BLOCK TO COME IN + AOS QSCABN(C) ;INTO NEXT CORE PAGE + CAIGE T,MFDBLK ;SKIP IF DONE + JRST QINT1E ;READ MORE + HRRZS QTUTO(Q) ;UNLOCK TUT, BUT QDPWF IS STILL SET + JRST QTUTI1 + +QSWPFN: MOVE Q,QDSKN(C) + TLNE D,%QAPAR + JRST QSWPF2 ;SWAP READ ERROR (I HOPE) + MOVSI E,MMPTMP ;PAGE NO LONGER IN TRANSIT + TDNN E,@QSMMP(Q) + BUG ;ALREADY WASN'T? + ANDCAM E,@QSMMP(Q) + SKIPL QSCRW(C) + JRST QSWPIF + PUSHJ P,IMEMR ;SWAP-OUT COMPLETE, RETURN MEMORY + MOVSI E,MMPPGB + ANDCAM E,@QSMMP(Q) + MOVSI E,MMPWOD ;PAGE HAS BEEN WRITTEN ON DISK. AND NO LONGER + IORB E,@QSMMP(Q) ;BEING PAGED BEHIND. + TLNN E,MMPGON + JRST QSWPF2 + MOVE A,QSMMP(Q) ;WE'RE SUPPOSED TO RETURN THE MMP ENTRY + PUSHJ P,RETMMP +QSWPF2: SETOM SWUSR(Q) ;SWAPPING IDLE + JRST QINT1B + +QSWPIF: +;SOME ERROR CHECKING + MOVE E,QSMMP(Q) + HLLZ TT,1(E) + JUMPE TT,QSWPF3 ;ON INITIAL-SWAP-IN, ADDRESS IN MMP IS SUPPOSED TO BE ZERO + LDB TT,[$MMPUN,,(E)] + CAME TT,Q + BUG + HLRZ TT,1(E) + CAME TT,QSGL(C) + BUG +QSWPF3: LDB TT,[MMMPX,,MEMBLT(A)] + CAIE TT,-MMP(E) + BUG +;END ERROR CHECKING + MOVEI TT,MURUSR ;SWAP IN OF PAGE COMPLETED + DPB TT,[MUR,,MEMBLT(A)] + SETZM MMSWP(A) + MOVE D,(E) + SKIPL CIRPSW + JRST QSWPF2 ;CAN'T PUT IN MAPS IF CIRPSW NOT AVAILABLE. + MOVSI D,(TDNE T,) ;SET UP CHECK USED BY PRIVELEGED USER FEATURE + HRR D,QSMMP(Q) + PUSH P,C + PUSH P,Q + MOVE C,[2200,,MEMPNT(A)] + PUSHJ P,PPIUM ;PUT PAGE INTO USERS' MAPS + POP P,Q + POP P,C + JRST QSWPF2 + +QWOVFN: CLEARM QSCRW(C) ;WRITE OVER SWITCH TO READ MODE + HRRI D,%QMRD1 + TLZE D,%QAEFW + HRRI D,%QMIDL ;TRYING TO CLOSE, STOP CHANNEL + MOVEM D,QSRAC(C) + AOS QWBUFS ;COMPENSATE FOR EXTRA SOS BELOW + +QWRFIN: TLNN D,%QACTH ;WRITE COMPLETE, RETURN BUFFER + PUSHJ P,IMEMR + TLNE D,%QACTH + PUSHJ P,CIMEMR + SOS QSBFS(C) + SOS QWBUFS + MOVE TT,QSGL(C) + MOVEM TT,QSLBLK(C) + JRST QINT1B + +QRD1FN: HLLZS QSRAC(C) .SEE %QMIDL ;BLOCK-AT-A-TIME READ COMPLETE, IDLE THE CHANNEL + +QRDFIN: MOVEI B,.BM MLO ;NORMAL READ COMPLETED + ANDCAM B,MEMBLT(A) ;THREAD ONTO CHANNEL LIST + HLRZ B,QBFP(C) + SKIPE B + DPB A,[MLO,,MEMBLT(B)] + SKIPN B + MOVEM A,QBFP(C) + HRLM A,QBFP(C) + SKIPL B,QPIBSZ(C) ;GET BYTE COUNT OF BLOCK + JRST QRDFN1 + HRRZ B,1777(R) ;FUNNY BLOCK, GET FROM LAST WORD + ; 8/20/90 No more funny blocks + HRRZ TT,QSBYTE(C) ;AND MAKE SURE IT'S NOT TOO BIG + IMULI TT,2000 + CAMLE B,TT + MOVE B,TT +QRDFN1: HRRZM B,MEMPNT(A) ;PASS TO MAIN PROGRAM + AOS QSBFS(C) +IFE DMDSK, LDB B,[XWBLK QXWDS] + .ALSO MOVEM B,QSLBLK(C) + +;XFER COMPLETE, DEACTIVATE CHANNEL + +QINT1B: SETOM QACTTM +QINT1A: SETOM QSGL(C) + SETOM QSCABN(C) +QINT1E: +IFE DC10P, SETOM QSKT1(Q) +IFN DC10P,[ + MOVE TT,QTRAN(Q) + SETOM QSKT1(TT) +] ;DC10P +IFN T300P,[ + CAIL Q,T300P + SETOM QSDU1 + CAIGE Q,T300P + SETOM QSDU +];T300P +.ELSE SETOM QSDU +;DROPS THROUGH + ;DROPS IN + +;ACTIVATE CHANNELS, LOOK FOR SEEKS AND TRANSFERS TO BE DONE + +QINT1: SETZM QHUNGF + SETOM QTUNT ;NO UNIT SELECTED YET +IFN T300P, SETOM QTUNT1 + MOVE C,QTCHN ;START SCAN IN SUITABLE PLACE + MOVEM C,QLCHN + JRST QINT2D + +QINT2L: CAIGE C,NQCHN ;IF DIR-WRITE OR SWAP CHANNEL, DON'T CHECK QUSR + SKIPL QUSR(C) + SKIPGE D,QSRAC(C) .SEE %QALOK + JRST QINT2C ;CHANNEL LOCKED OR NOT OPEN, SKIP IT + MOVE Q,QDSKN(C) + SKIPL E,QSGL(C) + JRST QINT4 ;JUMP IF CHANNEL ACTIVE ALREADY + TLNE D,%QACTH+%QAOUT + JRST QINT2C ;CHANNEL BLOCKED BY CORE JOB, DON'T ACTIVATE + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE ACTIVATE HANDLER + OFFSET -. +%QMIDL::JRST QINT2C ;IDLE - DON'T ACTIVATE +%QMRD:: JRST QRDACT ;READ +%QMWRT::JRST QWRACT ;WRITE +%QMWOV::JRST QWRACT ;WRITE OVER +%QMRD1::JRST QRDACT ;READ 1 BLOCK + JRST 4,QINT2C ;ILL CODE +%QMUDR::JRST QDRACT ;UFD READ +%QMMDR::JRST QDRACT ;MFD READ +%QMTTR::JRST QDRACT ;TUT READ +%QMUDW::JRST 4,QINT2C ;UFD WRITE - SHOULDN'T LEAVE THIS MODE AROUND +%QMMDW::JRST 4,QINT2C ;MFD WRITE - .. +%QMTTW::JRST QINT5 ;TUT WRITE - MAY BE WRITING SECOND PAGE +%QMSWP::JRST SWPACT ;SWAP + JRST 4,QINT2C ;ILL CODE + JRST 4,QINT2C ;ILL CODE + JRST 4,QINT2C ;ILL CODE +%QMMAX::OFFSET 0 + +; ACTIVATION ROUTINES + +SWPACT: SKIPL SWUSR(Q) + BUG ;SWAPPING ALREADY ACTIVE ON THIS DISK + MOVE A,MEMFR + SUB A,NCBCOM + MOVEI B,0 ;CHECK FIRST FOR SWAP IN OR OUT + CAIGE A,6 ;ACCORDING TO AVAIL MEM + MOVEI B,1 + SKIPN @SWAPL(B) ;IF NO TRAFFIC THAT DIRECTION, CHECK THE OTHER. + TRC B,1 + HRRZ E,@SWAPL(B) + JUMPE E,QINT2C ;NO SWAPPING TRAFFIC THIS DISK. + LDB A,[MLO,,MEMBLT(E)] ;TAKE BLOCK OFF LIST + SKIPN A + SETZM @SWAPL(B) ;LAST BLOCK, LIST IS NOW EMPTY + HRRM A,@SWAPL(B) ;SET NEW FIRST BLOCK + LDB D,[MMMPX,,MEMBLT(E)] + ADD D,MMPEAD ;GET MMP ADDRESS + LDB TT,[410200,,(D)] + TRNN TT,1 + BUG ;THIS PAGE SHOULD BE MARKED IN TRANSIT + HRRZM D,QSMMP(Q) + SOS SILNG(B) + CAIGE E,TSYSM + CAIGE E,SYSB + BUG + HRRZM E,QSCABN+NQCHN+1(Q) + CLEARM SWUSR(Q) ;CHNL ACTIVE + HLRZ E,MEMPNT(E) + MOVEM E,QSGL+NQCHN+1(Q) ;DISK BLOCK + HRRZS QSRAC+NQCHN+1(Q) .SEE %QMSWP + MOVNM B,QSCRW+NQCHN+1(Q) ;DIRECTION + CLEARM QERRS+NQCHN+1(Q) ;NO ERRORS (YET) + JRST QINT4 ;CHANNEL SUCCESSFULLY ACTIVATED + + +; MORE ACTIVATION ROUTINES + +QRDACT: TLNE D,%QAACC ;ACTIVATE READ CHANNEL + JRST QINT2C ;NOT IF USER HACKING RANDOM ACCESS NOW + SETZM QERRS(C) + MOVE J,QUDPR(C) + SKIPGE QSNLCN(J) + JRST QINT2C ;USER DIRECTORY OUT OR LOCKED + MOVE A,QSBFS(C) + SKIPL QSMDN(C) + AOS A ;A := TOTAL NUMBER OF BUFFERS + CAMLE A,QRDAHD ;HOW MUCH SHOULD BE READ AHEAD + JRST QINT2C ;BLOATED, DON'T ACTIVATE + SKIPE QSBI(C) + JRST QINT4A ;BLOCKS LEFT FROM LAST TIME +QINT4B: PUSHJ P,QIDRCH ;GET NEXT DESC BYTE IN A, ALSO RET BYTE PNTR IN TT + CAIN A,UDWPH + JRST QINT4B + JUMPE A,QEOF ;REACHED READ EOF + TRZE A,40 + JRST QINT4C + CAILE A,UDTKMX + JRST QINT4D ;SKIP AND TAKE + MOVEM A,QSBI(C) ;TAKE NEXT N +QINT4A: SOS QSBI(C) + AOS E,QSLGL(C) +QINT4G: MOVEM E,QSGL(C) + MOVSI B,%QALBK + ANDCAM B,QSRAC(C) ;CLEAR PROCESSING LAST BLOCK IN FILE BIT + HRRZ A,QSBYTE(C) + IMULI A,2000 ;NUMBER OF BYTES IN A FULL BLOCK +IFN DMDSK,[ + MOVSI D,%QAFNY ;FUNNY FILE + TDNE D,QSRAC(C) + SETO A, +] + MOVEM A,QPIBSZ(C) ;SET FUNNY BIT + SKIPE QSBI(C) + JRST QINT4 ;IF MORE BLOCKS FOLLOW DON'T CHECK EOF + PUSHJ P,QIDRCH ;GET NEXT DESCR BYTE + SOS QDIRP(C) ;CORRECT PNTR + JUMPN A,QINT4 + MOVE A,QUDFPR(C) ;THIS IS LAST BLOCK + ADD A,QSNLCN(J) + LDB D,[UNBYTE+UNREF(A)] + PUSHJ P,QBDCD + IMUL D,E ;NUMBER OF UNUSED BITS IN LAST WORD + LDB E,[QSBSIZ(C)] ;(DEPEND ON DIVIDE ROUNDING DOWN) + IDIV D,E ;NUMBER OF UNUSED BYTES (IN SIZE OPEN) + LDB E,[UNWRDC+UNRNDM(A)];NUMBER OF USED WORDS IN LAST BLOCK + SKIPN E + MOVEI E,2000 + IMULI E,@QSBYTE(C) ;CONVERT TO NUMBER OF BYTES + SUB E,D ;NUMBER OF VALID BYTES IN BLOCK + HRRM E,QPIBSZ(C) ;STORE BYTE COUNT OF LAST BLOCK + IORM B,QSRAC(C) .SEE %QALBK + MOVE E,QSGL(C) + JRST QINT4 + +QINT4D: MOVEI E,1-UDTKMX(A) ;SKIP N AND TAKE 1 + ADDB E,QSLGL(C) + JRST QINT4G + +QWRACT: SKIPN I,QBFP(C) ;ACTIVATE WRITE CHANNEL + JRST QINT2C ;END OF WRITE LIST FOR NOW + HRRZM I,QSCABN(C) + LDB H,[MLO,,MEMBLT(I)] + HRRM H,QBFP(C) + SKIPN H + SETZM QBFP(C) ;LAST BLOCK, LIST NOW EMPTY + HLRZ E,MEMPNT(I) + MOVEM E,QSGL(C) + JRST QINT4 + +QDRACT: MOVE E,QSLGL(C) ;ACTIVATE DIRECTORY-READ CHANNEL + MOVEM E,QSGL(C) +; JRST QINT4 ;DROPS THROUGH + ;DROPS IN +QINT4: SKIPL QSCABN(C) ;SKIP IF NEED MEMORY + JRST QINT5 + PUSHJ P,IOMQ ;GET MEMORY FOR READ BUFFER + JRST QINT2C ;CAN'T +QINT5A: MOVEM A,QSCABN(C) + MOVEI D,MU23B + DPB D,[MUR,,MEMBLT(A)] + DPB C,[MNUMB,,MEMBLT(A)] + +QINT5: +IFN DC10P, MOVE TT,QTRAN(Q) +.ELSE MOVE TT,Q + SKIPN QSEEK(TT) ;IGNORE SEEKING DRIVE + SKIPGE QRCAL(TT) ;IGNORE RECALIBRATING DRIVE + JRST QINT2C +IFN T300P,[ ;IGNORE IF FOR CONTROLLER THAT IS NOT READY + CAIL TT,T300P + JRST [ SKIPGE QSDU1 + SKIPL QTUNT1 ;NOTE CODE HERE IS SIMILAR TO THAT AT QINT2F + JRST QINT2C ;T-300 CONTROLLER BUSY OR ALREADY COMMITTED + HRRZM Q,QTUNT1 ;WILL TRANSFER ON THIS UNIT + HRRZM C,QTCHN1 ;FOR THIS CHANNEL + JRST QINT2C ] ;T-300 CODE IS SIMPLIFIED SINCE NO SEEK OVERLAPS + SKIPL QSDU + JRST QINT2C +];T300P + HRRZ B,QSKT1(TT) + CAIN B,(C) + JRST QINT2F ;ALREADY SET FOR ME + SKIPL QSKT1(TT) + JRST QINT2C ;SET FOR SOME OTHER CHNL + HRRZM C,QSKT1(TT) ;AVAILABLE, SET IT FOR ME + PUSHJ P,QPOSR ;CONVERT DISK ADDRESS TO PHYSICAL +IFN DC10P,[ ;AND INITIATE SEEK + ADD E,[DSEEK] + CONSZ DC0,DSSRUN+DSSACT + JRST .-1 + DATAO DC0,E + LDB B,[DCYL E] + MOVE TT,QTRAN(Q) ;PRETEND SEEK ALREADY COMPLETE + MOVEM B,QPOSGL(TT) + MOVEM B,QPOS(TT) + JRST QINT2F ;DON'T WAIT FOR SEEK, START TRANSFER RIGHT AWAY +] ;DC10P +IFN RP10P,[ + TLO E,(DSEEKC) ;DSK SEEK + CONSZ DPC,20 + JRST 4,.-1 + LDB TT,[DCYL E] + TRNE E,.BM DCYLXB + ADDI TT,400 + CAMN TT,QPOS(Q) + JRST QINT2F ;IF WE'RE THERE, DON'T SEEK + MOVEM TT,QPOSGL(Q) + DATAO DPC,E + MOVEM E,QSEEK(Q) + JRST QINT2C ;THIS ONE SEEKING, GO GET ANOTHER +] ;RP10P +IFN RH11P,[ + PUSHJ P,RHSLCT ; Select drive + HRRZ A,E + IOWRQ A,%HRADR ; Set track and sector + HLRZ A,E + IOWRQ A,%HRCYL ; Set cylinder + CAMN A,QPOS(Q) + JRST QINT2F ; On cylinder, don't seek + MOVEM A,QPOSGL(Q) + MOVEI A,%HMSEK + PUSHJ P,RHCMD ; Start seeking + SETOM QSEEK(Q) + JRST QINT2C ; Start other drives now? +] ;RH11P +IFN RH10P,[ + MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE + HLR A,E + PUSHJ P,RHSET + MOVSI A,%HRADR(Q) + HRR A,E + PUSHJ P,RHSET + HLRZ TT,E ;GET CYLINDER PART OF ADDRESS + CAMN TT,QPOS(Q) + JRST QINT2F ;ON CYLINDER, DON'T SEEK + MOVEM TT,QPOSGL(Q) + MOVSI A,%HRDCL(Q) ;START SEEK + HRRI A,%HMSEK + PUSHJ P,RHSET + SETOM QSEEK(Q) + JRST QINT2C ;THIS ONE SEEKING, START OTHER DRIVES +] ;RH10P + +IFN KL10P,[ +;CALL HERE TO SWEEP THE CACHE. CORE PAGE # IN R. +;INSTRUCTION AT CALL+1 SHOULD SKIP IF READING INTO CORE. +;CLOBBERS A,B,D,E,TT. + +CSHSWP: SETZB A,B ;A COUNTS WAIT TIME, B IS SWEEP INSTRUCTION + XCT @(P) + TLOA B,(SWPUO (R)) ;WRITE - UNLOAD PAGE FROM CACHE + MOVSI B,(SWPIO (R)) ;READ - CLEAR PAGE FROM CACHE + LSH R,1 ;HARDWARE PAGES ARE 1/2 K + XCT B ;SWEEP FIRST HALF-PAGE + MOVE D,[CONSZ 200000] + MOVE E,[AOJA A,D] + MOVSI TT,(POPJ P,) + PUSHJ P,D ;WAIT IN ACS TO MINIMIZE MBOX INTERFERENCE + AOS R ;SWEEP SECOND HALF-PAGE + XCT B + PUSHJ P,D + XCT @(P) + AOSA NCSHU ;COUNT NUMBER OF TIMES THIS DONE + AOSA NCSHI + JRST [ ADDM A,NCSHUL ? JRST .+2 ] + ADDM A,NCSHIL ;AND COUNT NUMBER OF LOOPS IN ACS + LSH R,-1 + JRST POPJ1 +] + +;VARIOUS EXITS FROM CHANNEL-CHECKING ROUTINES + +QINT2F: SKIPL QTUNT ;THIS CHANNEL IS READY TO TRANSFER + JRST QINT2C ;ALREADY FOUND A TRANSFER + HRRZM Q,QTUNT ;WILL TRANSFER ON THIS UNIT + HRRZM C,QTCHN ;FOR THIS CHANNEL +QINT2C: CAMN C,QLCHN ;CONTINUE CHANNEL SCAN + JRST QINT2E ;UNLESS CHECKED ALL CHANNELS +QINT2D: CAIL C,NQCHN+1+NQS-1 ;SKIP IF NOT TIME TO WRAP AROUND + SETO C, + AOJA C,QINT2L ;CHECK ANOTHER + +QINT2E: +IFN T300P,[ + MOVE C,QTCHN1 + SKIPL Q,QTUNT1 ;FOUND XFER FOR T-300? + JRST QDE1 ;YES +];T300P + SKIPGE Q,QTUNT ;FOUND XFER? + JRST QINT3 ;IDLE + MOVE C,QTCHN +;Q DISK TO TRANSFER ON, C CHANNEL. START (OR RESTART) TRANSFER ON THEM. +QDE1: MOVE R,QSCABN(C) +IFN KL10P,[ + PUSHJ P,CSHSWP + SKIPGE QSCRW(C) +];KL10P +IFN KS10P,[ + SKIPL QSCRW(C) + CLRCSH +];KS10P +IFE T300P, MOVEM C,QSDCH +IFN T300P,[ + CAIL Q,T300P + JRST T3IO + CAIGE Q,T300P + MOVEM C,QSDCH +];T300P + SKIPGE B,QSCRW(C) ;LOAD R/W STATUS IN B + JRST QINT6W + ;READ - DROPS IN +IFN RP10P,[ + MOVSI T,(DREADC) +QINT6A: IORI T,7000+QICWA ;DON'T STOP FOR PARITY ERRORS (PLUS INITIAL CHNL ADR) + MOVEM T,QCHPRG + DPB Q,[DUNFLD+QCHPRG] + HLLZS QIOWD + DPB R,[121000,,QIOWD] + LDB E,[100300,,R] ;MA15-17 + TRC E,7 + DPB E,[410300,,QIOWD] ;SET UP HIGH ADDR BITS. + MOVE TT,QIOWD + SOS TT + HRRM TT,QIOWD + SETZM QIOWD+1 + MOVEM Q,QSDU + MOVE E,QSGL(C) + PUSHJ P,QPOSR + IORM E,QCHPRG +QOVR: CONSZ DPC,20 + JRST QOVR + SKIPGE Q,QSDU + BUG + CONO DPC,175700+DSKCHN +IFN QRDCMP,[ + SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED + SKIPE QRCSW + SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER +];QRDCMP + MOVEI TT,QIOWD + HRRZM TT,QICWA + MOVE E,QCHPRG + LDB TT,[DCYL E] + TRNE E,.BM DCYLXB + ADDI TT,400 + CAME TT,QPOS(Q) + BUG ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE + SETZM QICWA+1 + DATAO DPC,QCHPRG ;ENTRY ON OVERRUN + MOVE A,TIME + MOVEM A,LQTM + MOVEM Q,QSDU + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: CONO DPC,DCLEAR+20+DSKCHN ;DISK NOTICED TO BE HUNG, RESET IT + SETOM QHUNGF ;TELL P.I. LEVEL TO RETRY OPERATION + MOVE Q,QSDU + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG + POPJ P, +] + ;READ - DROPS IN + +IFN RH11P,[ + MOVEI T,%HMRED +QINT6A: MOVEM T,QCHPRG + MOVEM Q,QSDU + LSH R,1 ; Set up Unibus map for RH11 to point at + TRO R,%UQVAL+%UQFST ; the block in question. + IOWRQ R,UBAPAG+QUBPG_1 + ADDI R,1 + IOWRQ R,UBAPAG+QUBPG_1+1 + MOVE E,[-4000,,QUBPG_14] + MOVEM E,QIOWD + MOVE E,QSGL(C) + PUSHJ P,QPOSR + MOVEM E,QCHPGA +QOVR: IORDQ TT,%HRCS1 ; Enter here to recover from PI level lossage + TRNN TT,%HXRDY + JRST QOVR + SKIPGE Q,QSDU + BUG +QECCX: ;; Enter here from ECC correction code + PUSHJ P,RHCLRC ; Clear controller errors and select drive + HLRZ TT,QCHPGA + CAME TT,QPOS(Q) + JRST DSKEX ; Punt if not positioned in right place + IOWRQ TT,%HRCYL ; Store cylinder in drive + HRRZ TT,QCHPGA + IOWRQ TT,%HRADR ; Store track and sector + HLRZ TT,QIOWD + IOWRQ TT,%HRWC ; Store halfword count + HRRZ TT,QIOWD + IOWRQ TT,%HRBA ; Store Unibus base address + MOVE A,QCHPRG + PUSHJ P,RHCMD ; Go! + MOVE A,TIME + MOVEM A,LQTM + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: MOVEI A,%HYCLR ; Sock controller in jaw + IOWRQ A,%HRCS2 + MOVE Q,QSDU + PUSHJ P,RHSLCT ; Select drive + PUSHJ P,RHCLRD ; Redundantly clear drive + SETOM QHUNGF + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT #],DEC,QSDU,[ADDR=],OCT,QCHPGA + POPJ P, + +] ;RH11P + ;READ - DROPS IN + +IFN RH10P,[ + MOVEI T,%HMRED +QINT6A: IORI T,QICWA_6 .SEE $HCICWA + TLO T,%HRCTL(Q) + MOVEM T,QCHPRG + MOVEM Q,QSDU + LSH R,10. ;ASSEMBLE DF10-C CONTROL WORD + SUBI R,1 + MOVNI E,2000 + DPB E,[$DFWC R] + MOVEM R,QIOWD + SETZM QIOWD+1 + MOVE E,QSGL(C) + PUSHJ P,QPOSR + MOVEM E,QCHPGA +QOVR: CONSZ DSK,20 ;ENTER HERE FOR RECOVER FROM PI HALT, OVERRUN + JRST QOVR + SKIPGE Q,QSDU + BUG + MOVEI TT,QIOWD + HRRZM TT,QICWA +QECCX: SETZM QICWA+1 ;ENTER HERE FROM ECC CORRECTION CODE + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN + HLRZ TT,QCHPGA + CAME TT,QPOS(Q) + JRST DSKEX ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE + MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE + HLR A,QCHPGA + PUSHJ P,RHSET + MOVSI A,%HRADR(Q) + HRR A,QCHPGA + PUSHJ P,RHSET + MOVE A,QCHPRG + PUSHJ P,RHSET +IFN QRDCMP,[ + SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED + SKIPE QRCSW + SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER +];QRDCMP + MOVE A,TIME + MOVEM A,LQTM + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: CONO DSK,%HOCLR+%HORST+%HOSTP+DSKCHN ;HUNG, CLEAR CONTROLLER + SETOM QHUNGF + MOVE Q,QSDU + AOS NTQHNG(Q) + MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR ;CLEAR DRIVE + PUSHJ P,RHSET + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[ADDR=],OCT,QCHPGA + POPJ P, +] + ;READ - DROPS IN +IFN DC10P,[ + MOVSI T,(DREAD) +QINT6A: MOVEM T,QCHPRG + MOVEM Q,QSDU + DPB R,[DCBN+QCHPR2] ;MEM BLOCK # + DPB R,[DCBN+QCHPR3] ;FOR POSSIBLE READ COMPARE + MOVE E,QSGL(C) + PUSHJ P,QPOSR ;QPOSR ALSO STORES MAPPED UNIT IN QCHPRG + IORB E,QCHPRG + CLEARM QCHPR4 ;STORE DHALT FOR NO RCC + CAILE C,NQCHN + JRST QINT6S ;SWAPPING CHNL + SKIPL B + AOSA NRXFR + AOS NWXFR + CAIE C,NQCHN ;ALWAYS R COMPARE DIR WRITES + SKIPLE QRCSW ;SKIP ON NOT READ COMP EVERYTHING + JRST QINT6B ;RCC + SKIPL QRCSW + JUMPL B,QINT6B ;RCC WRITES + HRRZ D,QSRAC(C) + CAIL D,%QMUDR + CAILE D,%QMTTR + JRST QINT6C ;NOT DIR READ +QINT6B: TLZ E,340000 ;CHANGE TO READ COMPARE + MOVEM E,QCHPR4 +QINT6C: SETOM QERS1 ;ERR VERIFY IND +QOVR: CONSZ DC0,DSSRUN+DSSACT + JRST QOVR + DATAO DC0,[DJMP QCHPRG] ;ENTRY ON OVERRUN +QOVR1: CONO DC0,DCSET+DCIENB+DSKCHN ;INTERRUPT WHEN DONE + MOVE A,TIME + MOVEM A,LQTM +QINTX: JRST DSKEX + +QINT6S: SKIPL B + AOSA NSRXFR + AOS NSWXFR + JUMPL B,QINT6B ;RCC WRITES + JRST QINT6C ;NOT READS + +QHUNG: CONO DC0,DCCSET+DSKCHN ;HUNG, CLEAR CONTROLLER + SETOM QHUNGF + MOVE Q,QSDU + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG + POPJ P, +] + +QINT6W:IFE DMDSK,[ + MOVE T,[QXWDS-1,,QXWDS] + BLT T,QXWDS+3 + CAIL C,NQCHN + JRST QNT6W2 ;SWAP OR DIR WRITE + MOVE A,QUDPR(C) + MOVE T,QSNUD(A) + MOVEM T,QXWDS+XWSYSN + HRRZ A,QSNLCN(A) + ADD A,QUDFPR(C) + MOVE T,UNFN1(A) + MOVEM T,QXWDS+XWFN1 + MOVE T,UNFN2(A) + MOVEM T,QXWDS+XWFN2 + MOVE T,QSLBLK(C) + DPB T,[XWBLK+QXWDS] + LDB T,[MWC,,MEMBLT(R)] + DPB T,[XWAWC+QXWDS] +QNT6W2: +] +IFN DC10P, MOVSI T,(DWRITE) +IFN RP10P, MOVSI T,(DWRITC) +IFN RH10P, MOVEI T,%HMWRT +IFN RH11P, MOVEI T,%HMWRT + JRST QINT6A + +IFN T300P,[ +T3IO: MOVEM C,QSDCH1 ;THIS IS MORE OR LESS QINT6A FOR T-300 + MOVEM Q,QSDU1 + MOVEI A,%DMRED + SKIPGE B,QSCRW(C) + MOVEI A,%DMWRT +T3IO1: MOVE R,QSCABN(C) ;RE-ENTER HERE TO RETRY WITH COMMAND IN A + LSH R,10. ;FIRST ADDRESS IN TRANSFER + TLO R,730000 ;12-BIT BYTES, START WITH FIRST BYTE IN WORD + MOVSI E,-4 ;SET UP BYTE POINTERS + MOVEM R,DSCPNT(E) + ADDI R,400 + AOBJN E,.-2 + MOVE D,QSGL(C) ;DO LIKE QPOSR + CAIL D,NBLKS1 + BUG + IDIVI D,NBLKC1 + MOVEM D,DSCCYL + IMULI E,SECBL1 + IDIVI E,NSECS1 + MOVEM E,DSCHED + MOVEM TT,DSCSEC + PUSHJ P,T3CMD + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR1 + AOS NWXFR1 + JRST QINTX + SKIPL B + AOSA NSRXF1 + AOS NSWXF1 + JRST QINTX + +;START T-300, COMMAND IN A, DRIVE IN Q +T3CMD: MOVEI TT,2561 + MOVEM TT,DSCCHK + MOVE TT,TIME + MOVEM TT,LQTM1 + MOVEI TT,-T300P(Q) + MOVEM TT,DSCDRV + HRRZM A,DSCCMD + SETZM DSCDON + MOVEI T,1 + MOVEM T,DSCREQ + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, + +QHUNG1: MOVE Q,QSDU1 + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON T-300 UNIT ],DEC,QSDU + MOVEI TT,5*60.*30. ;SHUT UP FOR FIVE MINUTES + ADDM TT,LQTM1 + POPJ P, +];T300P + +QDE: MOVE C,QSDCH +IFN RP10P, PUSHJ P,QERSOFT +IFN DC10P, AOSE PKIDM + SKIPGE Q,QSDU + BUG +IFN DC10P,[ + TRNE TT,DCKSER + JRST .+3 ;GET CKS ERR + TRNE TT,DRCER + AOS NQCMPE(Q) ;# COMPARE ERRORS [WITH NO OTHER ERROR] +];DC10P +IFN T300P,T3DE: ;ENTER HERE FOR ERROR ON T-300 + AOS NQDE(Q) + SKIPL R,QSCRW(C) + AOSA NQRDE(Q) + AOS NQWDE(Q) +IFN DC10P, JUMPL R,QERV1 ;DO ANOTHER RD/COMP TO SEE IF OK ON DSK (IF WRITE) +QERV2: AOS R,QERRS(C) + TRNN R,10 ;TRY 8 TIMES BEFORE AND AFTER REPOSITION + JRST QDE1 + TRNN R,1000 + JRST QDE2 ;TRY REPOSITION ONCE +QERV3: MOVE D,QSRAC(C) + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE IRRECOV ERROR HANDLER +QERV: OFFSET -. +%QMIDL::JRST 4,QERV+. ;IDLE CHANNELS SHOULDN'T GET HERE +%QMRD:: JRST QPE2D ;USER DATA +%QMWRT::JRST QDE1 ;WRITE KEEP TRYING +%QMWOV::JRST QDE1 ;.. +%QMRD1::JRST QPE2D + JRST 4,QERV+. ;ILL CODE +%QMUDR::JRST QUDER1 +%QMMDR::JRST QDE1 +%QMTTR::JRST QDE1 +%QMUDW::JRST QDE1 +%QMMDW::JRST QDE1 +%QMTTW::JRST QDE1 +%QMSWP::JRST QSWPER + JRST 4,QERV+. ;ILL CODE + JRST 4,QERV+. ;ILL CODE + JRST 4,QERV+. ;ILL CODE +%QMMAX::OFFSET 0 + +QSWPER: SKIPGE CIRPSW ;TRY XFER AGAIN IF CIRPSW NOT AVAILABLE + SKIPGE QSCRW(C) + JRST QDE1 ;DON'T TRY TO DO ANYTHING ABOUT WRITE ERRORS + MOVE A,QSCABN(C) ;READ - GIVE ALL USERS OF PAGE PARITY ERR + PUSH P,C + PUSH P,Q + MOVE C,[2200,,MEMPNT(A)] + PUSHJ P,UCPRL + 400000,,QSWER1 + LDB Q,[2200,,MEMPNT(A)] + DPB Q,C ;REMOVE MEM FROM LOOP + PUSHJ P,IMEMR ;AND GIVE BACK MEM + POP P,Q ;ALTERNATIVELY, COULD LEAVE THE MEM BUT SET MMPBAD + POP P,C ;TO INDICATE THAT THAT MEM COPY OF THE PAGE IS NO GOOD. + MOVEI D,2 + DPB D,[410200,,@QSMMP(Q)] ;PAGE IS OUT + JRST QPE2D + +QSWER1: PUSH P,T + MOVSI T,%PJPAR + IORM T,PIRQC(U) + JRST POPTJ + +IFN DC10P,[ +QERV1: SKIPN QCHPR4 + JRST QERV2 ;NOT SET FOR RCC + CLEARM QERS1 +QERL2: CONSZ DC0,DSSRUN+DSSACT + JRST .-1 + DATAO DC0,[DJMP QCHPR4] + JRST QOVR1 + +QERL1: AOS Q,QERS1 + CAIGE Q,50. + JRST QERL2 + AOSA NQWIRE +QEROK: AOS NQWRE + MOVE C,QSDCH + MOVE Q,QSDU + SETOM QERS1 + JRST QERV2 +] +QDE2: MOVEI R,1000 + MOVEM R,QERRS(C) ;CLOBBER QERRS + JRST QREC ;AND TRY REPOSITIONING + +IFN RP10P,[ +QERSOFT:LDB A,[DCYL+QCHPRG] ;PARSE STARTING DISK ADDRESS + LDB B,[DCYLXB+QCHPRG] + LSH B,8 + IOR A,B + LDB B,[DSURF+QCHPRG] + LDB D,[DSECT+QCHPRG] + SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES + BUG INFO,[DSK: SOFT ERR UNIT ],DEC,Q,[CYL ],DEC,A,[STARTING HEAD ],DEC,B,[SEC ],DEC,D,[CONI=],OCT,QERST,[DATAI=],OCT,QERDTI + POPJ P, + +QRECAT: CONI DPC,A + BUG INFO,[DSK: SEEK ERR DATAO=],OCT,QSEEK(Q),[CONI=],OCT,A,[DATAI=],OCT,E + SETZM QSEEK(Q) + JRST QREC +];RP10P + +QHE: MOVE C,QSDCH +IFN RP10P, PUSHJ P,QERSOFT + SKIPGE Q,QSDU + BUG +IFN T300P,T3HE: ;ENTER HERE FOR ID ERROR ON T-300 + AOS NQHE(Q) + AOS E,QERRS(C) + CAIL E,5. + JRST QHE2 +QREC: +IFN T300P,[ + CAIL Q,T300P + JRST [ SETOM QRCAL(Q) + MOVEI A,%DMREC + PUSHJ P,T3CMD + MOVEM Q,QSDU1 ;CONTROLLER IS TIED UP BY RECAL BECAUSE + JRST QINT1 ] ;IT'S TOO DAMNED PSEUDO-INTELLIGENT +];T300P +IFN DC10P,[ + MOVE TT,QTRAN(Q) +QREC0: DPB TT,[DUNFLD+QRECAL] + SETOM QRCAL(TT) + SETOM QSKT1(TT) + CLEARM QSPPS(TT) + CLEARM QPOSGL(TT) + SETOM QPOS(TT) + MOVEI T,10. ;5-SECOND RECALIBRATE TIMEOUT + MOVEM T,QRCTIM(TT) + DATAO DC0,QRECAL + CONO DC0,DCSET+DCATEB+DSKCHN ;ENABLE ATTENTION +] +IFN RP10P,[ + DPB Q,[DUNFLD+QRECAL] + SETOM QPOS(Q) + DATAO DPC,QRECAL + CLEARM QSPPS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) ;INDICATE RECALIBRATING THIS DISK + CLEARM QPOSGL(Q) +] +IFN RH11P,[ + PUSHJ P,RHSLCT ; Select drive + PUSHJ P,RHCLRD ; Clear errors + MOVEI A,%HMREC + PUSHJ P,RHCMD ; Recalibrate + CLEARM QSPPS(Q) + CLEARM QPOSGL(Q) + SETOM QPOS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) +] ;RH11P +IFN RH10P,[ + MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR + PUSHJ P,RHSET ;CLEAR ERROR OUT OF DRIVE. + MOVSI A,%HRDCL(Q) + HRRI A,%HMREC ;RECALIBRATE + PUSHJ P,RHSET ;MAYBE SHOULD TRY OFFSET FIRST? + CLEARM QSPPS(Q) + CLEARM QPOSGL(Q) + SETOM QPOS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) +] + SETOM QSDU + JRST QINT1 ;LOOK FOR SOME OTHER TRANSFER + +QHE2: SKIPL QSCRW(C) ;HANG UP OR POSITIONING ERR (AFTER 5 TRIES) + JRST QERV3 ;IF READ, PERFORM RECOVERY + +QPE2D: MOVSI R,%QAPAR ;IRRECOVERABLE ERROR + IORM R,QSRAC(C) + AOS QIRRCV + MOVE D,QSGL(C) + MOVEM D,QIRCBK ;BLOCK # AT IRRCV ERR + MOVEM Q,QIRUNT ;SAVE UNIT TOO + CAILE C,NQCHN + AOS NIRSWE ;# IRRCV SWAPPING ERRS + MOVE I,Q + SKIPGE QTUTO(I) + JRST QPE2E ;DON'T MESS WITH LOCKED TUT + PUSHJ P,TUTPNT + CAIN B,TUTLK ;PRINT MESSAGE IF NOT YET LOCKED OUT + JRST QINTI + MOVEI B,TUTLK + DPB B,D +QPE2E: BUG INFO,[DSK: IRREC DATA ERR #],DEC,QIRRCV,[UNIT=],DEC,QIRUNT,[BLK=],OCT,QIRCBK + JRST QINTI + +QUDER1: MOVEI R,1(Q) ;TRY TO READ DIR FROM OTHER DISKS +QUDER2: CAIL R,NQS + MOVEI R,0 + CAME R,QDSKN(C) + JRST QUDER4 + JRST QDE1 ;NO OTHER DISK AVAIL TO READ FROM, TRY AGAIN + +QUDER4: SKIPGE QACT(R) + AOJA R,QUDER2 + HRRZM R,QDSKN(C) ;TRY THIS DISK +IFN T300P,[ + CAIL Q,T300P + JRST [ SETOM QSDU1 ;FREE DRIVE FORMERLY HACKING + SETOM QTUNT1 + JRST T3UDE4 ] +];T300P +IFE DC10P, SETOM QSKT1(Q) ;FREE DRIVE FORMERLY HACKING +IFN DC10P,[ + MOVE TT,QTRAN(Q) + SETOM QSKT1(TT) +] + SETOM QSDU + SETOM QTUNT +IFN T300P,T3UDE4: + MOVE E,QSGL(C) + MOVE Q,QDSKN(C) + SETZM QERRS(C) + JRST QINT5 + +QIDRCH: MOVE TT,QDIRP(C) ;CHNL IN C PNTR TO QSNUD IN J LOAD NEXT CHR INTO A + AOS QDIRP(C) ;ALSO RET BYTE PNTR IN TT + IDIVI TT,UFDBPW + HLL TT,QBTBL(I) + HRRZ I,QSNLCN(J) + ADDI TT,UDDESC(I) + LDB A,TT + POPJ P, + +QMPDCH: MOVE TT,QDIRP(A) ;CHNL IN A PNTR TO QSNUD IN H LOADS NEXT CHR IN R + AOS QDIRP(A) ;USED AT M.P. LEVEL +QMPDC1: IDIVI TT,UFDBPW ;ALSO RETN BYTE PNTR IN TT + HLL TT,QBTBL(I) + HRRZ I,QSNLCN(H) + ADDI TT,UDDESC(I) + LDB R,TT + POPJ P, + +;REACHED EOF ON READ +QEOF: SOS QDIRP(C) ;AVOID GC UNHAPPINESS + MOVSI I,%QAEFR + IORM I,QSRAC(C) + HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL + AOS QSBFS(C) ;TO UNHANG M.P. WHICH IS WAITING FOR BUF TO APPEAR + JRST QINT2C + +QINT4C: +; 8/20/90 DM "funny" bit no longer supported. Allows for huge RP07 block +; numbers. Commenting this out means that %QAFNY can no longer get set +; under any circumstances, so I am leaving a certain amount of dead code in +; other places. +; IFN DMDSK,[ +; MOVSI E,%QAFNY +; ANDCAM E,QSRAC(C) +; TRZE A,20 ; FUNNY FILE BLOCK +; IORM E,QSRAC(C); INDICATE SO +; ] + MOVEI E,0 + DPB A,[140500,,E] + PUSHJ P,QIDRCH + DPB A,[060600,,E] + PUSHJ P,QIDRCH + DPB A,[0600,,E] + MOVEM E,QSLGL(C) + JRST QINT4G + +;DECODE UNBYTE SPEC IN D. +;RETURNS BYTE SIZE IN D, NUMBER OF UNUSED BYTES IN LAST WORD IN E. +QBDCD: TRZE D,400 + JRST [ IDIVI D,100 ? POPJ P, ] + TRZE D,200 + JRST [ IDIVI D,20 ? POPJ P, ] + SUBI D,44 + JUMPGE D,[ IDIVI D,4 ? POPJ P, ] + MOVNS D + SETZ E, + POPJ P, + +;ENCODE BYTE SIZE IN Q AND RESIDUE IN R INTO UNBYTE SPEC IN RH(Q) +QBENC: CAIG Q,3 + JRST [ IMULI Q,100 ? ADDI Q,400(R) ? POPJ P, ] + CAIG Q,7 + JRST [ IMULI Q,20 ? ADDI Q,200(R) ? POPJ P, ] + CAIG Q,18. + JRST [ IMULI Q,4 ? ADDI Q,44(R) ? POPJ P, ] + MOVNI Q,-44(Q) + POPJ P, + +QINT3: SKIPL DWUSR + JRST QINT3X ;DIR CHNL IN USE +IFN T300P,[ + SKIPGE QSDU ;DON'T GET PAST HERE UNLESS BOTH CONTROLLERS ARE IDLE + SKIPL QSDU1 + JRST QINT3X +];T300P + AOSL QDWFAR + JRST [ MOVNI H,10. + MOVEM H,QDWFAR + JRST .+3 ] + SKIPG QACTTM ;LAST ACTIVITY TOO RECENT + JRST QUDW + SKIPGE H,QMDRO + JRST QTDW + MOVE J,QACTB + TDNN J,H + JRST QTDW + MOVSI Q,-NQS +QMDW: SKIPGE QACT(Q) + JRST QMDWA ;UNIT NOT ACTIVE + MOVE J,DCHBT(Q) + TDNN J,QMDRO + JRST QMDWA + HRLI Q,(SETZ) ;INDICATE MFD WRITE IN PROGRESS + MOVEM Q,QDWIP + HRRZM Q,DWSKN + MOVEI TT,%QMMDW + HRRZM TT,QSRAC+NQCHN + MOVSI TT,(SETZ) + IORB TT,QMDRO + MOVE C,MDCHK(TT) + CAME C,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] + HRRZ C,Q + CAMN C,MDSK + AOSA C,QAMDNO + MOVE C,QAMDNO + MOVEM C,MDNUM(TT) + SETZM DWUSR + MOVEI TT,MFDBLK + MOVEM TT,QSGL+NQCHN + HRRZ TT,QMDRO + LSH TT,-10. + MOVEM TT,QSCABN+NQCHN + JRST QINT1 + +QMDWA: AOBJN Q,QMDW +QTDW: SKIPG QACTTM + JRST QUDW + MOVSI Q,-NQS +QTDW1: SKIPGE QACT(Q) + JRST QTDWA + MOVE J,DCHBT(Q) + SKIPL QTUTO(Q) + TDNN J,QTUTO(Q) + JRST QTDWA + MOVSI H,240000 + TDNE H,QTUTO(Q) + JRST QTDWA1 + MOVE TT,TIME ;DON'T WRITE TUTS TOO OFTEN + SUB TT,QTWRTM(Q) ;BECAUSE THE TUT IS LOCKED WHILE IT'S BEING WRITTEN + CAIGE TT,100. + JRST QTDWA + ADDM TT,QTWRTM(Q) + HRLI Q,200000 + MOVEM Q,QDWIP + HRRZM Q,DWSKN + MOVEI TT,%QMTTW + HRRZM TT,QSRAC+NQCHN + MOVSI TT,(SETZ) + IORB TT,QTUTO(Q) + MOVE H,QPKNM(Q) ;VERIFY THAT TUT IS NOT BEING CLOBBERED + MOVE C,QPKID(Q) + CAMN H,QPAKID(TT) + CAME C,QPKNUM(TT) + BUG HALT,[TUT ],DEC,Q,[CLOBBERED] + SETZM DWUSR + MOVEI TT,MFDBLK ;INITIATE WRITING OF FIRST BLOCK OF TUT + SUB TT,NTBL(Q) + MOVEM TT,QSGL+NQCHN + LDB TT,[121000,,QTUTO(Q)] + MOVEM TT,QSCABN+NQCHN + JRST QINT1 + +QTDWA1: ANDCAM J,QTUTO(Q) +QTDWA: AOBJN Q,QTDW1 +QUDW: MOVSI C,-QNUD +QDW4A: MOVE J,QACTB ;BITS CORRESP TO ACTIVE DISKS +QDW4: SKIPE TT,QSNUD(C) + SKIPGE QSNLCN(C) + JRST QDW3 ;SLOT VACANT OR LOCKED + TDNE J,QSNLCN(C) + JRST QUDW1 ;NEEDS TO BE WRITTEN ON SOME UNIT +QDW3: AOBJN C,QDW4A +QINT3X: ;HERE IF DISK GOING IDLE. CLEAR DONE FLAG. + ;IN 2-CONTROLLER CASE, MAKE SURE WE ONLY DO IT TO THE RIGHT CONTROLLER. +IFN T300P,[ + SKIPL QSDU + JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW +] ;T300P +IFN DC10P, CONO DC0,DCCLR+DCIENB+DSKCHN +IFN RP10P, CONO DPC,177710+DSKCHN ;MUST CLEAR "DONE" +IFN RH10P, CONO DSK,%HOCLR+%HOATN+%HORAE+DSKCHN +IFN RH11P, ;; RH11 doesn't need this? + JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW + +QUDW1: MOVSI J,%QUDWM ;WRITE RIGHT AWAY IF %QUDWM IS ON + TDNN J,QSNLCN(C) + SKIPE QSFBT(C) ;OR DISK BLOCKS (AND CORE) WAITING TO BE FREED + JRST QUDW6 + SKIPG QACTTM ; ACTIVITY TOO RECENT + SKIPN QSNNR(C) ; THEN ONLY WRITE IF NOTHING POINTING TO DIRECTORY + SKIPA + JRST QDW3 + MOVSI Q,-NQS +QUDW4: SKIPGE QACT(Q) + JRST QUDW3 + MOVE J,DCHBT(Q) + TDNE J,QSNLCN(C) + JRST QUDW2 +QUDW3: AOBJN Q,QUDW4 + JRST QDW3 + +QUDW6: ANDCAM J,QSNLCN(C) ;TURN OFF %QUDWM + MOVE Q,MDSK ;AND WRITE ON MASTER DISK (ASSUME MDSK IS ACTIVE AND BIT IN QSNLCN IS SET) + +QUDW2: MOVE I,QMDRO + TLNE I,40000 ;IS THIS CODE OBSOLETE? LEFT FROM DAYS OF 1 MFD PER DRIVE? + JRST QUDW2B ;MASTER DIR NOT IN + HRRZS Q + CAMN Q,MDSK ;SKIP IF NOT WRITING ON MASTER DISK + PUSHJ P,QDIRCK ;BLESS THIS UFD!!! + MOVSI TT,(SETZ) + IORB TT,QSNLCN(C) ;LOCK USER DIRECTORY + MOVEI J,%QMUDW + HRRZM J,QSRAC+NQCHN + MOVE A,1(TT) ;NAME AREA PTR + MOVE J,QSNUD(C) + CAMN J,UDNAME(TT) ;MAKE SURE NOT ABOUT TO WRITE BAD DIRECTORY + CAILE A,2000 + JSP TT,QUDCLB + SUBI A,11. + IMULI A,6 + SKIPL J,(TT) + CAMLE J,A ;FS PTR BAD? + JSP TT,QUDCLB + CLEARM DWUSR + MOVEM Q,DWSKN + MOVE TT,QSNMI(C) + MOVEM TT,QSGL+NQCHN + HRRZ TT,QSNLCN(C) + LSH TT,-10. + MOVEM TT,QSCABN+NQCHN + HRRZM C,QDWIP + CLEARM QERRS+NQCHN + JRST QINT1 + +QUDW2B: ANDCAM J,QSNLCN(C) ;CLEAR BIT + GO AWAY + JRST QUDW3 + +;GENERALLY GET HERE BY JSP TT, +QUDCLB: BUG HALT,[DIR ],OCT,C,SIXBIT,QSNUD(C),[CLOBBERED] + +QDIRCK: PUSH P,TT ;CHECKS FILES FOR REASONABLE DESCRIPTORS - + ; PRECEDING BYTE =0, FIRST BYTE NOT=0 + HRRZ A,QSNLCN(C) + MOVEI B,1777(A) ;END OF NAMES + ADD A,1(A) ;BEGIN NAMES +QDIRC1: CAMG B,A + JRST POPTTJ ;DONE + SKIPN (A) + JRST QDIRC2 ;0 NAME=NO FILE + LDB TT,[1500,,UNRNDM(A)] ;DESC PTR + SOS TT ;TRICK - IF DESC PTR = 0 LDB BELOW GETS 0 BECAUSE P FIELD = 44 + IDIVI TT,6 + HLL TT,SBTBL(I) ;BYTE POINTER + ADDI TT,UDDESC-1777(B) + LDB I,TT + JUMPN I,QUDCLB + ILDB I,TT + JUMPE I,QUDCLB +QDIRC2: ADDI A,LUNBLK + JRST QDIRC1 + +IFN RP10P,[ +QPOSR: CAIL E,MBLKS + BUG ;TOO BIG EVEN FOR RP03 +IFN DMDSK,[ + IMULI E,SECBLK + IDIVI E,NSECS + SETZM D + DPB TT,[DSECT+D] + IDIVI E,NHEDS + DPB TT,[DSURF+D] + DPB E,[DCYL+D] + MOVEM E,QSPPS(Q) + LSH E,-8 + DPB E,[DCYLXB+D] + DPB Q,[DUNFLD+D] +] +IFE DMDSK,[ + MOVEI D,0 + IDIVI E,NBLKSC + DPB E,[DCYL+D] + MOVEM E,QSPPS(Q) + LSH E,-8 + DPB E,[DCYLXB+D] + MOVE E,TT + IMULI E,NSSECS + IDIVI E,NHSECS + DPB E,[DSURF+D] + DPB TT,[DSECT+D] + DPB Q,[DUNFLD+D] +] + MOVE E,D + POPJ P, +] +IFN RH10P+RH11P,[ +IFE DMDSK, .ERR CHANGE QPOSR FOR 9-SECTOR BLOCKS! +QPOSR: CAIL E,NBLKS + BUG + IDIVI E,NBLKSC + HRLZ D,E ;CYLINDER IN LH + MOVEM E,QSPPS(Q) + MOVE E,TT + IMULI E,SECBLK + IDIVI E,NSECS + LSH E,8 + IOR E,D ;SURFACE IN 1.9-2.4 + IOR E,TT ;SECTOR IN 1.1-1.5 + POPJ P, +] ;RH10P+RH11P + +IFN DC10P,[ +QPOSR: CAIL E,NBLKS + BUG + IDIVI E,NSECS + MOVSI D,(DUNENB) + DPB TT,[DSECT+D] + IDIVI E,NHEDS + DPB TT,[DSURF+D] + SKIPGE TT,QTRAN(Q) + ADDI E,NCYLS+XCYLS + DPB E,[DCYL+D] + MOVEM E,QSPPS(TT) + MOVE E,D + DPB TT,[DUNFLD+E] + DPB TT,[DUNFLD+QCHPRG] + SKIPGE TT,QPKID(Q) + JRST QPOSRI + DPB TT,[DPKID+E] + POPJ P, + +QPOSRI: MOVE TT,QTRAN(Q) ;NEED PACK ID BEFORE PROCEEDING + DPB TT,[DUNFLD+GPKID] + SETOM QSKT1(TT) + MOVEI A,TUTCYL + SKIPGE QTRAN(Q) + ADDI A,NCYLS+XCYLS + DPB A,[DCYL+GPKID] + MOVEM A,QPOS(TT) ;WILL SEEK TO HERE AUTOMATICALLY + MOVEM A,QPOSGL(TT) + DATAO DC0,[DJMP GPKID] + MOVEM Q,QSDU + SETOM PKIDM + JRST QINTX + +QSPKID: CONSZ DC1,1777 + BUG ;ERRORS + LDB TT,[DPKID+RPKID] + MOVEM TT,QPKID(Q) + SETOM QSDU + JRST QINT1 +] + +SUBTTL DISK IOT ROUTINES + +OVHMTR UUO ;MORE RANDOM UUOS + +;BECAUSE .ACCESS MERELY DROPS ITS ARG IN A VARIABLE AND SETS %QAACC, +;ALL IOT ROUTINES MUST TEST %QAACC AND DO THE REAL WORK OF CHANGING +;THE ACCESS POINTER IF NECESSARY. + +QBO: MOVEI T,BLKT + JRST QUO1 + + SKIPA T,[SIOKT] +QUIO: +QUAO: MOVEI T,CHRKT +QUO1: PUSH P,T + PUSH P,TT + PUSH P,D + MOVE T,QSRAC(A) + TLNE T,%QAACC+%QALNK + PUSHJ P,QBWRA1 ;RANDOM ACCESS MODE HACK + POP P,D + POP P,TT + MOVE E,QSBYTE(A) + JSP B,CPOPJ ;TRANSFER TO CHRKT, SIOKT, OR BLKT +QBOV: SETZ QSMPRP(A) + QSMPRC(A) + QSBWG + SETZ QSBWW + JRST QOCL + TRNA + +QBI: MOVEI T,BLKT + JRST QUI1 + + SKIPA T,[SIOKT] +QUII: +QUAI: MOVEI T,CHRKTI +QUI1: PUSH P,T + PUSH P,TT + MOVE T,QSRAC(A) + TLNE T,%QAACC+%QALNK + PUSHJ P,QBRRA1 + POP P,TT + MOVE E,QSBYTE(A) + JSP B,CPOPJ ;TRANSFER TO CHRKTI, SIOKT, OR BLKT +QBIV: QSMPRP(A) + QSMPRC(A) + QSBGB + QSBRB + JRST QICL + SKIPG QSBFS(A) + +QBWRA1: TLNE T,%QALNK + JRST IOCR10 + LDB T,[$QAMOD,,QSRAC(A)] ;SET RANDOM ACCESS PNTRS ON WRITE + SOJN T,QBWRA2 ;IN ORDINARY WRITE MODE + SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO BECOME IDLE OR HANG UP IN READ + PUSHJ P,UFLS ; WAITING FOR %QAACC TO TURN OFF + SKIPL QSGL(A) + PUSHJ P,UFLS + SKIPGE QSMDN(A) + JRST QBWRA2 + MOVE T,QRADAD(A) ;DESIRED ADDRESS + SUB T,QFBLNO(A) ;ACTUAL ADDRESS OF BEG OF CURRENT BUFFER + JUMPL T,QBWRA2 ;XFER ON BEFORE CURRENT BLOCK + MOVE Q,T + SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER IN BYTES + JUMPL T,QBWRA3 ;SAME BLOCK AS NOW +QBWRA2: PUSH P,R + PUSH P,I + PUSH P,C + PUSHJ P,QSOCL5 ;CLEAR ANY CURRENT BUFFERS ETC + PUSHJ P,QUDULK + MOVE Q,QRADAD(A) + PUSHJ P,QFNTR ;LOCKS DIR IF SKIPS + JRST QBWRA4 ;OFF END OF FILE +QBWRA5: PUSHJ P,QUDULK +QBWRA9: POP P,C + POP P,I + POP P,R + CLEARM QSCRW(A) ;SWITCH TO WRITE OVER MODE + MOVSI Q,%QAMPU+%QAMWO ;SET UPDATE ADR AND WRITE OVER + IORM Q,QSRAC(A) + CLEARM QSMPRC(A) + MOVSI Q,%QAEFR+%QAEFW+%QAACC ;CLEAR EOF, WRITE EOF, AND ACCESS FLAGS + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMRD1 ;AND READ IN THE CURRENT BLOCK + HRRM Q,QSRAC(A) + POPJ P, + +QBWRA4: JUMPE Q,QBWRA0 + CAME J,Q ;MIGHT BE ADDING TO END OF FULL BLOCK + JRST IOCER2 + JRST QBWRA9 + +QBWRA0: PUSHJ P,QLWO ;OFF END OF FILE AND WAS ACCESSING WD 0 + MOVSI C,%QAACC ;SO SWITCH TO NORMAL WRITE MODE AND + ANDCAM C,QSRAC(A) ;TURN OFF RANDOM ACCESS BIT + POP P,C + POP P,I + POP P,R + POPJ P, + +QBWRA3: SKIPGE TT,QSMDN(A) + BUG ;NO BUFFER REALLY ACTIVE AT M.P. + MOVSI J,%QAWOV + TDNN J,QSRAC(A) + JRST QBWRA7 + ANDCAM J,QSRAC(A) ;WAS WRITING IN LAST BLK PAST EOF, + MOVN D,QSMPRC(A) ; UPDATE ACTIVE BYTE COUNT + ADDM D,QMPBSZ(A) ;DECREASE SIZE OF BUFFER TO AMT ACTUALLY WRITTEN +QBWRA7: LSH TT,10. ;ADDRESS OF BUFFER + MOVE T,Q ;SAVE RELATIVE BYTE ADDR WITHIN BUFFER + IDIVI Q,@QSBYTE(A) ;Q = WDS, J = BYTES + ADD TT,Q ;ADDRESS OF DESIRED WORD + HLL TT,QSBYTE(A) ;BYTE POINTER TO FIRST BYTE IN THAT WORD + JUMPE J,.+3 ;ADVANCE TO APPROPRIATE BYTE + IBP TT + SOJG J,.-1 + MOVEM TT,QSMPRP(A) + SUB T,QMPBSZ(A) ;MINUS # BYTES LEFT IN BLOCK + MOVNM T,QSMPRC(A) +QBRRA4: MOVSI Q,%QAACC + ANDCAM Q,QSRAC(A) + POPJ P, + +QSKFRC: MOVN B,QSMPRC(A) + ADD B,QMPBSZ(A) ;NUMBER OF BYTES WRITTEN IN BLOCK + MOVE C,QSRAC(A) + TLNE C,%QAMWO + TLNE C,%QAWOV + JRST [MOVEM B,QMPBSZ(A) ;IS LAST BLOCK, CHANGE LENGTH + PUSHJ P,QOCLPD ;AND PAD IT (GUARANTEED NO-OP IF WORD MODE CHNL) + JRST .+1 ] + SETZM QSMPRC(A) ;BUFFER WILL BE DISPOSED OF + MOVSI E,%QUDWM + SKIPGE QSMDN(A) + SETZB B,E ;NO BUFFER AFTER ALL + ADD B,QFBLNO(A) ;CURRENT POSITION IN FILE + MOVSI C,%QAACC + TDNN C,QSRAC(A) + MOVEM B,QRADAD(A) ;ACCESS BACK ON NEXT IOT + IORB C,QSRAC(A) + PUSHJ P,[TLNE C,%QAWOV ;WRITE OUT THE BUFFER + JUMPN E,QSBWO2 + JRST QSBWW ] + SKIPE QMPTC(A) + MOVSI E,%QUDWM + PUSHJ P,QOCL2 ;STORE QMPTC IF NECESSARY + IORM E,QSNLCN(H) ;WRITE OUT DIR FAST IF CHANGED + PUSHJ P,QUDULK + JRST POPJ1 + +;.CALL FINISH ON DISK OUTPUT CHANNEL +QSKFIN: HRRZ T,QSRAC(A) + CAIN T,%QMWOV ;IF WRITE-OVER MODE + JRST [ SKIPE QSCRW(A) ;THEN WAIT FOR IT TO SWITCH TO READ MODE + PUSHJ P,UFLS + JRST QSKFIN ] + CAIN T,%QMWRT ;IF WRITE MODE + JRST [ SKIPE QSBFS(A) ;THEN WAIT FOR ALL BUFFERS TO GET WRITTEN + PUSHJ P,UFLS + JRST .+1 ] + MOVE H,QUDPR(A) + MOVE T,MDSK ;HAS THE DIR BEEN CHANGED AND NOT WRITTEN + MOVE T,DCHBT(T) ;YET TO THE MASTER DISK? + TDNN T,QSNLCN(H) + JRST POPJ1 + MOVSI TT,%QUDWM ;YES, WRITE IT OUT IMMEDIATELY + IORM TT,QSNLCN(H) ;AND DON'T RETURN UNTIL IT IS WRITTEN + TDNE T,QSNLCN(H) + PUSHJ P,UFLS + JRST POPJ1 + +QBRRA1: TLNE T,%QALNK + JRST IOCR10 + SKIPGE QSMDN(A) + JRST QBRRA2 ;NO MAIN PRGM BUFFER + MOVE T,QRADAD(A) + SUB T,QFBLNO(A) + JUMPL T,QBRRA2 + MOVE Q,T + SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER + JUMPL T,QBRRA3 ;SAME BLOCK AS NOW +QBRRA2: PUSH P,R + PUSH P,I + PUSH P,C + PUSHJ P,QICLW1 ;STOP THE CHANNEL AND FLUSH CURRENT BUFFERS + MOVE A,D + CLEARM QSBFS(A) ;FLUSH POSSIBLE EXTRA AOSES WHEN PI HIT EOF + MOVE Q,QRADAD(A) + PUSHJ P,QFNTR + JRST QBRRA5 ;OFF END OF FILE (DIR ALREADY UNLOCKED) + POP P,C + POP P,I + POP P,R + CLEARM QSMPRC(A) + MOVSI Q,%QAMPU + IORM Q,QSRAC(A) ;SET FLAG TO SET QSMPRP AND QSMPRC ON NEXT BUFFER LOAD + MOVSI Q,%QAEFR+%QAACC ;CLEAR EOF AND .ACCESS FLAGS + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMRD ;START READING AGAIN + HRRM Q,QSRAC(A) + JRST QUDULK + +QBRRA5: POP P,C + POP P,I + POP P,R + CAME J,Q + JRST IOCER2 ;ACCESS OFF END OF FILE IS ERROR + MOVSI TT,%QAEFR ;BUT ACCESS TO EXACTLY EOF IS OK + IORM TT,QSRAC(A) ;IMITATES WHAT QEOF DOES + AOS QSBFS(A) + SETZM QSMPRC(A) ;AND READS ZERO WORDS + JRST QBRRA4 + +QBRRA3: SKIPGE TT,QSMDN(A) + JRST QBRRA2 + JRST QBWRA7 + +;BLKT-SIOKT-CHRKT GET BUFFER ROUTINE FOR WRITE-OVER MODE. +QWOG1: SKIPGE QSCRW(A) ;FETCH BLOCK WRITEOVER MODE + JRST QWOG2 ;STILL WRITING PREVIOUS ONE, WAIT + MOVEI Q,%QMRD1 ;SWITCH INTO READ MODE + SKIPG QSBFS(A) ;IF A BUFFER HAS TO BE READ + HRRM Q,QSRAC(A) + SKIPG QSBFS(A) + PUSHJ P,UFLS + POP P,A +;BLKT-SIOKT-CHRKT GET-BUFFER ROUTINE FOR DISK INPUT. +QSBGB: MOVSI Q,%QAPAR + TDNE Q,QSRAC(A) + JRST QSBGB2 + CONO PI,UTCOFF + HRRZ Q,QBFP(A) + JUMPE Q,[MOVSI J,%QAEFR ;SAID TO BE BUFFERS, BUT NONE THERE + TDNN J,QSRAC(A) + BUG ;SHOULDN'T HAPPEN EXCEPT AT EOF + JRST QSBGB5 ] + LDB J,[MLO,,MEMBLT(Q)] + HRRM J,QBFP(A) + SKIPN J + SETZM QBFP(A) ;LAST BLOCK, LIST NOW EMPTY + HRRZ J,MEMPNT(Q) ;GET SIZE OF BUFFER IN BYTES + MOVEM J,QMPBSZ(A) + LDB TT,[$QAMOD,,QSRAC(A)] + SKIPN TT ;DONT SOS IF IN WRITE OVER MODE + SOS QSBFS(A) +QSBWG4: MOVE TT,Q + LSH TT,10. ;RETURN ADDR OF BUFFER + MOVEM Q,QSMDN(A) + CONO PI,UTCON + HLL TT,QSBYTE(A) + MOVSI Q,%QAMPU + TDNN Q,QSRAC(A) + JRST SIOBG2 + MOVE Q,QRADAD(A) ;DIDDLE PNTRS TO TAKE CARE OF RANDOM ACCESS WITHIN BLOCK + SUB Q,QFBLNO(A) ;DESIRED OFFSET WITHIN BLOCK + SUB J,Q + JUMPL J,IOCER2 ;OFF END OF FILE + JUMPL Q,IOCER2 ;OFF FRONT OF FILE (NEGATIVE .ACCESS PNTR) + PUSH P,J + IDIVI Q,@QSBYTE(A) + ADD TT,Q ;ADJUST BYTE POINTER + JUMPE J,.+3 + IBP TT + SOJG J,.-1 + POP P,J + MOVSI Q,%QAMPU ;NOW IS SAFE TO TURN OFF FLAG + ANDCAM Q,QSRAC(A) + JRST SIOBG2 + +;GET-BUFFER DETECTED EOF ON INPUT OR WRITE-OVER. +QSBGB5: CONO PI,UTCON + MOVE Q,QSRAC(A) + TLNE Q,%QALNK + JRST IOCR10 + LDB Q,[$QAMOD,,QSRAC(A)] + SOJN Q,POPJ2 ;ON INPUT, SKIP TWICE TO SIGNAL EOF. + PUSHJ P,QLWO ;LEAVE WRITE OVER MODE + JRST QSBWG ;START NORMAL WRITE + +QWOG2: SKIPGE QSCRW(A) ;WAIT FOR WRITE TO FINISH + PUSHJ P,UFLS + JRST POPAJ ;NOW RECYCLE AND WAIT FOR READ + +;LEAVE WRITE OVER MODE +QLWO: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + CONO PI,UTCOFF + SETZM QBFP(A) ;WRITEOVER MODE EXTEND FILE (SWITCH TO NORMAL MODE) + CLEARM QSBFS(A) + SETOM QSCRW(A) + MOVE Q,QSLGL(A) + HRRZM Q,QMPTN(A) ;STORE BASE TRACK + MOVSI Q,%QAEFR+%QAMWO ;CLEAR EOF AND WRITEOVER + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMWRT ;NORMAL WRITE MODE + HRRM Q,QSRAC(A) + CLEARM QMPTC(A) ;TRACK COUNT FOR TAKE N + SETOM QMTTR(A) ;NO TRACK RESERVED + SETOM QMFTP(A) ;GET NEW DECADE RESERVATION + CONO PI,UTCON + MOVE TT,QDIRP(A) ;SEE IF GARBAGE COLLECTION NEEDED + PUSH P,R + PUSH P,I + PUSHJ P,QMPDC1 ;CONV CHAR ADR TO BYTE PNTR (AND LDB IN R) + POP P,I + SKIPE R + BUG + MOVE R,QDIRP(A) + ADDI R,NXLBYT+2 + CAMGE R,@QSNLCN(H) + JRST QLWO1 ;DON'T NEED TO EXPAND F.S. + MOVEI R,LUNBLK(TT) + MOVE Q,QSNLCN(H) + SUBI R,(Q) + CAML R,UDNAMP(Q) + JRST QSBWG7 ;DON'T HAVE ROOM. GC + MOVEI R,3*6 ;HAVE ROOM + ADDM R,(Q) +QLWO1: +REPEAT NXLBYT+2,[ + ILDB R,TT + JUMPN R,QSBWG7 +] + JRST QSBWG8 ;OK + +QSBWG7: MOVSI R,%QAFUL ;NO ROOM, GC BEFORE COMMITTING NEXT TRACK + IORM R,QSRAC(A) +QSBWG8: POP P,R + JRST QUDULK + +QSBGB2: ANDCAM Q,QSRAC(A) ;DISK READ ERROR + JRST IOCER3 ;TELL USER + +;DISK OUTPUT GET-BUFFER ROUTINE. PRESERVES D FOR BENEFIT OF PDUMP. +QSBWG: MOVE Q,QSRAC(A) + TLNE Q,%QALNK+%QAACC ;DON'T WRITE TO LINK, DON'T LET PDUMP GET + JRST IOCR10 ; FAKED OUT BY USE FORCE OR ACCESS + PUSH P,A + TLNE Q,%QAMWO + JRST QWOG1 ;JUMP IF WRITE OVER MODE + HRRZ Q,QBFP(A) ;NORMAL MODE + JUMPE Q,QSBWG1 ;CAN ALWAYS HAVE ONE BUFFER + MOVE Q,QWBUFS + CAML Q,QWBFMX + JRST POPAJ ;TOO MANY WRITE BUFFERS QUEUED +QSBWG1: PUSHJ P,QSTWG + PUSHJ P,TCALL + JRST IOMQ + JRST QSBWG5 ;MEM FROZE OR NOT AVAILABLE + MOVE Q,(P) ;DISK CHNL # + DPB Q,[MNUMB,,MEMBLT(A)] + MOVEI Q,MU23B + DPB Q,[MUR,,MEMBLT(A)] + MOVE Q,A + POP P,A + AOS QSBFS(A) + AOS QWBUFS + HRRZ J,QSBYTE(A) + IMULI J,2000 + MOVEM J,QMPBSZ(A) ;FRESH BLOCK SIZE + JRST QSBWG4 + +QSTWG: MOVSI Q,%QAFUL + TDNE Q,QSRAC(A) ;ROUTINE TO COMMIT A TRACK + JRST QSTWG1 ;DIR FULL, NEED GC BEFORE GROWING FILE + MOVE H,QUDPR(A) ;IF THIS DIRECTORY HAS AN ALLOCATION + MOVE Q,QSNLCN(H) ; ENFORCE IT +IFN QRSRVP,[ + HRRZ J,UDALLO(Q) + JUMPE J,QSTWG0 ;NO ALLOCATION + HRRZ H,UDBLKS(Q) ;GET BLOCKS USED + CAML H,J + JRST IOCR13 ;HAS ALLOCATION AND USER IS TRYING TO EXCEED IT +] +QSTWG0: MOVE J,QDSKN(A) + SOSL QSFT(J) ;RESERVE A TRACK + POPJ P, + AOS QSFT(J) ;DISK FULL, GIVE BACK THE TRACK + SKIPE QFBTS ;WAIT FOR ANY PENDING FILE DELETIONS + PUSHJ P,UFLS ; TO COMPLETE AND FREE THEIR BLOCKS + SOSL QSFT(J) ;GOT SPACE NOW? + POPJ P, + AOS QSFT(J) ;NO, GIVE UP AND ERR OUT + JRST IOCER9 + +QSTWG1: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + PUSHJ P,QGC + JRST IOCR12 ;DIR FULL + PUSHJ P,QUDULK + ANDCAM Q,QSRAC(A) .SEE %QAFUL + JRST QSTWG + +QSBWG5: POP P,A ;GET BACK QSK CHANNEL # + MOVE J,QDSKN(A) + AOS QSFT(J) ;NO MEMORY; GIVE EVERYTHING BACK + POPJ P, + +;DISK OUTPUT RELEASE-BUFFER ROUTINE FOR BLKT, SIOKT, CHRKT. +QSBWW: SKIPGE QSMDN(A) ;WRITE BUFFER FROM MN PROG TO CHAIN FOR PI + POPJ P, ;NO WRITE BUFFER ACTIVE + LDB TT,[$QAMOD,,QSRAC(A)] + SOJE TT,QSBWO1 ;WRITE OVER MODE + SKIPL D,QMTTR(A) + JRST QTG1 ;TRACK ALREADY RESERVED + PUSH P,I + MOVE I,QDSKN(A) + PUSHJ P,QGTRK ;GET A TRACK + POP P,I + MOVEM D,QMTTR(A) +QTG1: MOVE H,QUDPR(A) ;TRACK IN D + PUSHJ P,QUDLK + MOVE TT,QSNLCN(H) + AOS UDBLKS(TT) + MOVE TT,QMPTN(A) ;GET PREVIOUS TRACK# + CAIN D,1(TT) + JRST QTG2 ;THIS TRACK IS CONSECUTIVE + SKIPN QMPTC(A) ;THIS TRACK NOT CONSEC CHECK COUNT OF PREV CONSEC BLOCKS + JRST QTG3 + PUSH P,D ;NON-ZERO SO STORE IN USER DIRECTORY + MOVE D,QMPTC(A) + CLEARM QMPTC(A) + PUSHJ P,QUDS + POP P,D +QTG3: MOVE J,QMTTR(A) ;DESCRIPTOR WILL BE STORED + MOVEM J,QMPTN(A) + SUB D,QMPTN(A) ;CAN TRACK BE SKIPPED TO? + SOJL D,QTG4 ;CAN'T BE SKIPPED TO (NOTE QMPTN HAS NOT BEEN AOS'D) + CAILE D,UDWPH-UDTKMX-1 + JRST QTG4 ;ALSO NO + ADDI D,UDTKMX ;NEXT BLOCK WITHIN N + PUSHJ P,QUDS ;STORE APPROPRIATE SKIP +QTG5A: +QTG5: MOVE Q,QSMDN(A) ;CORE BLOCK NUM BEING WRITTEN + MOVE D,QMPTN(A) ;TRACK NUM OF BLOCK ADDING TO FILE + HRLZM D,MEMPNT(Q) ;STORE TRACK NUM + SETOM QMTTR(A) ;INDICATE TRACK USED + MOVE J,QMPBSZ(A) ;LENGTH OF THIS BLOCK + ADDM J,QFBLNO(A) ;INCR BYTE ADR OF START OF CURRENT BLOCK IN FILE + HRRM J,MEMPNT(Q) ;SAVE BYTE COUNT + PUSH P,R + IDIVI J,@QSBYTE(A) ;CONVERT TO WORD COUNT + JUMPE R,QTG7 ;EXACT MULTIPLE OF WORD + AOS J + MOVNS R + ADDI R,@QSBYTE(A) ;# BYTES RESIDUE IN LAST WORD +QTG7: DPB J,[MWC,,MEMBLT(Q)] ;STORE ACTIVE WORD COUNT + MOVE D,QSRAC(A) + LDB TT,[$QAMOD,,QSRAC(A)] + TLNN D,%QALBK ;LAST BLOCK OF WRITE OVER POSSIBLY + SOJE TT,QTG6 ;WRITEOVER MODE AND NOT LAST BLOCK, DONT UPDATE LAST BLOCK WORD COUNT + MOVE H,QUDPR(A) ;SET UP DIRECTORY CHANNEL + MOVE D,QUDFPR(A) + ADD D,QSNLCN(H) + DPB J,[UNWRDC+UNRNDM(D)] ;SET WORD COUNT OF LAST BLOCK + LDB Q,[QSBSIZ(A)] + PUSHJ P,QBENC ;ENCODE BYTE CRUFT + DPB Q,[UNBYTE+UNREF(D)] + MOVE J,QACTB + IORM J,QSNLCN(H) +QTG6: POP P,R + PUSHJ P,QUDULK + MOVE Q,QSMDN(A) + MOVEI J,.BM MLO + ANDCAM J,MEMBLT(Q) ;SET END OF LIST INDICATOR IN MEMORY BLOCK + CONO PI,UTCOFF + HLRZ J,QBFP(A) ;STORE MEMORY BLOCK IN OUTPUT LIST + JUMPE J,QSBWW1 + DPB Q,[MLO,,MEMBLT(J)] +QSBWW2: HRLM Q,QBFP(A) + CONO PI,UTCON + SETOM QSMDN(A) ;MN PROG BUFFER NOW WRITTEN + JRST QSTRTR ;START ACTION IF 2311 IDLE AND RETURN + +QSBWO1: MOVE Q,QSRAC(A) ;PUT BUFFER IN WRITE-OVER MODE + TLNE Q,%QALBK ;IF NOT HACKING LAST BLOCK + TLNE Q,%QAEFW ;OR HACKING CLOSE + JRST QSBWO2 ;THEN JUST WRITE IT + HRRZ D,QSBYTE(A) + IMULI D,2000 + SUB D,QMPBSZ(A) + JUMPE D,QSBWO2 ;BLOCK REALLY FULL + TLNE Q,%QAMPU ;DID WE IOCER2 AT QSBWG4? + JRST IOCER2 ;YES, QSMPRP NOT SET UP, DON'T WRITE ANYTHING + MOVEM D,QSMPRC(A) ;LAST BLOCK NOT REALLY USED UP ("SPRUNG BACK TO LIFE") + ADDM D,QMPBSZ(A) ;EXTRA ROOM IN LAST BLOCK TO FILL UP + MOVSI D,%QAWOV + IORM D,QSRAC(A) ;FILLING LAST BLK PAST ORIG EOF + POPJ P, ;FINISH OUT BLOCK + +QSBWO2: MOVSI D,%QAWOV + ANDCAM D,QSRAC(A) + MOVE D,QSLGL(A) ;WRITE TRACK BACK WHERE IT CAME FROM + MOVEM D,QMPTN(A) ;PUT TRACK NO WHERE QTG5 CAN FIND IT + MOVE H,QUDPR(A) + PUSHJ P,QUDLK + SETOM QSCRW(A) ;SWITCH TO WRITE MODE + MOVEI Q,%QMWOV + HRRM Q,QSRAC(A) + JRST QTG5 + + +QTG4: LDB D,[140500,,QMTTR(A)] ;WRITE LOAD ADDRESS + IORI D,40 + PUSHJ P,QUDS + LDB D,[060600,,QMTTR(A)] + PUSHJ P,QUDS + LDB D,[0600,,QMTTR(A)] + PUSHJ P,QUDS + JRST QTG5A + +QGTRK: PUSHJ P,QTLOCK ;GET TRK CHNL IN A DSK IN I RET IN D CLOBBERS E,TT,Q,J,B +QGTK4: PUSH P,R ;ENTER HERE FROM SWAP OUT WITH UTCOFF + PUSH P,B + PUSH P,E + HRRZ R,QTUTO(I) +QGTK4A: SKIPGE Q,QMFTP(A) + JRST QGTK3A ;FIRST TRACK + IDIVI Q,DECADE + HRREI J,-DECADE(J) ;COMPUTE TRACKS REMAINING IN DECADE + MOVE D,QMFTP(A) + PUSHJ P,TUTPNT + ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER + MOVE TT,QMFTP(A) + EXCH D,TT +QGTK3: CAML D,QLASTB(R) + JRST QGTK3A ;REACHED END OF DISK + ILDB Q,TT + JUMPE Q,QGTK2 + AOJGE J,QGTK3A ;DECADE OUT + AOJA D,QGTK3 + +QGTK3A: CAILE A,NQCHN + JRST QGTK3C ;SWAP CHANNEL +QGTK3D: MOVEI Q,DECADE + ADDB Q,QTUTP(R) +QGTK3B: MOVEM Q,QMFTP(A) + CAMGE Q,QLASTB(R) + JRST QGTK4A + MOVE Q,QSWAPA(R) ;REACHED END OF DSK, RESET TO END OF SWAPPING AREA + ADDI Q,DECADE-1 ;ROUND UP TO A MULTIPLE OF A DECADE + IDIVI Q,DECADE + IMULI Q,DECADE + MOVEM Q,QTUTP(R) + JRST QGTK3B + +QGTK2: MOVEI B,1 + DPB B,TT + MOVEM D,QMFTP(A) + MOVE J,DCHBT(I) + IORM J,QTUTO(I) + POP P,E + POP P,B + POP P,R + CAILE A,NQCHN + POPJ P, ;CALLED FROM SWAP OUT + JRST QTULK + +QGTK3C: CAML D,QSWAPA(R) + JRST QGTK3D ;IN NON-SWAP AREA + AOS D + CAMN D,QSWAPA(R) + MOVEI D,NUDSL + MOVEM D,QMFTP(A) + JRST QGTK4A + ;STORE CHR IN D CHNL IN A USER DIR PNTR IN H +;CANNOT PCLSR NOR GC + +QUDS: PUSH P,I + PUSH P,Q + MOVE I,QDIRP(A) + CAIGE I,2000*UFDBPW + CAML I,@QSNLCN(H) ;UDESCP + BUG ;WRITING ABOVE F.S. PNTR? + AOS QDIRP(A) + IDIVI I,UFDBPW + MOVE Q,QBTBL(Q) + ADD Q,I + SKIPL I,QSNLCN(H) + BUG ;UFD WAS NOT LOCKED + ADDI Q,UDDESC(I) + LDB I,Q + CAIE I,UDWPH ;OK TO CLOBBER UDWPH (NORMALLY DOES AT START OF FILE) + JUMPN I,[JRST 4,.] ;ABOUT TO CLOBBER SOMETHING IN UFD + DPB D,Q + ILDB I,Q ;MAKE SURE FILE DESC WILL ALWAYS BE FOLLOWED BY ZERO + SKIPE I + BUG +REPEAT NXLBYT+2,[ ;MAKE SURE THERE'S ROOM FOR ONE MORE TRACK + ILDB I,Q + JUMPN I,QUDS1 +] + MOVE I,QDIRP(A) + ADDI I,NXLBYT+2 + CAMGE I,@QSNLCN(H) ;UDESCP + JRST QUDSX ;DESC AREA NOT COLLIDING WITH LIM OF DESC SPACE + MOVEI Q,LUNBLK(Q) + MOVE I,QSNLCN(H) + SUBI Q,(I) + CAML Q,UDNAMP(I) + JRST QUDS1 ;NO ROOM. + MOVEI Q,3*UFDBPW ;EXPAND DESC AREA + ADDM Q,UDESCP(I) + JRST QUDSX + +QUDS1: MOVSI Q,%QAFUL ;NEED GC BEFORE STARTING ON NEXT TRACK + IORM Q,QSRAC(A) +QUDSX: MOVE Q,QACTB + IORM Q,QSNLCN(H) ;SET DIRECTORY CHANGED + POP P,Q + POP P,I + POPJ P, + +QSBWW1: HRRM Q,QBFP(A) + JRST QSBWW2 + +QSBRB1: MOVE A,D +QSBRB: PUSH P,A + SKIPGE A,QSMDN(A) + JRST POPAJ + PUSHJ P,MEMR + POP P,A + HRRZ TT,QMPBSZ(A) + ADDM TT,QFBLNO(A) ;INCREMENT BYTE ADR IN FILE OF BEG OF NEXT BLOCK + SETOM QSMDN(A) + JRST QSTRTR + +QTG2: MOVE J,QMTTR(A) ;INDICATE WE WILL STORE DESCRIPTOR FOR NEXT TRACK. + MOVEM J,QMPTN(A) + AOS D,QMPTC(A) ;NEXT BLOCK IS CONSECUTIVE + CAIGE D,UDTKMX + JRST QTG5A + SETZM QMPTC(A) ;MAX # CONSECUTIVE BLOCKS, STORE DESC NOW + PUSHJ P,QUDS + JRST QTG5A + +SUBTTL DIRHNG DEVICE + +;WHENEVER THE DIRECTORY SPECIFIED AS THE SNAME WHEN DIRHNG IS OPENED +;IS MODIFIED, YOU GET AN INTERRUPT ON THE DIRHNG DEVICE CHANNEL. + +;HERE TO OPEN THE DIRHNG DEVICE. IOCHNM ADDR IN R, SNAME IN USYSN1(U). +DIRHO: MOVE C,USYSN1(U) + PUSHJ P,QFL ;LOOK UP THIS DIRECTORY + JRST OPNL20 ;CALL FAILS IF DIRECTORY DOES NOT EXIST. + HRRZM J,IOCHST-IOCHNM(R) ;DIR EXISTS; STORE TRACK NUMBER IN IOCHST. +DIRHP1: CONO PI,CLKOFF + HLLZ A,DIRHNG ;ADD THIS CHANNEL'S IOCHNM TO THE LIST OF DIRHNG CHANNELS. + HRRI A,DNDIRH + MOVEM A,(R) ;SET UP THE IOCHNM WITH IOTTB INDEX AND LIST CHAIN. + HRLZM R,DIRHNG + JRST CLKOJ1 + +;CLOSE A DIRHNG DEVICE CHANNEL. +DIRHCL: PUSHJ P,DIRHPS ;REMOVE IT FROM THE LIST, AND + SETZM (R) ;MARK IT CLOSED. + POPJ P, + +;IOPUSH A DIRHNG DEVICE CHANNEL. REMOVE IT FROM THE LIST OF ALL SUCH. +DIRHPS: MOVEI A,DIRHNG + CONO PI,CLKOFF +;FIND THE PLACE THAT POINTS AT THIS IOCHNM WORD. +DIRHC1: HLRZ B,(A) + CAIN B,(R) + JRST DIRHC2 + SKIPN A,B ;END OF LIST REACHED => + BUG ;THIS IOCHNM ISN'T IN THE LIST. BUT IT IS SUPPOSED TO BE! + JRST DIRHC1 + +;A POINTS AT IOCHNM THAT POINTS AT THIS ONE. PATCH THIS ONE OUT OF LIST. +DIRHC2: HLRZ B,(B) ;THE ONE AFTER THIS ONE + HRLM B,(A) + JRST CLKONJ + +;IOPUSH OR IOPOP THE DIRHNG CHANNEL WITH R -> IOCHNM WORD. I SAYS WHICH OPERATION. +DIRHIP: JUMPE I,DIRHPS ;IOPUSH REMOVES CHANNEL FROM LIST OF ALL DIRHNG CHANNELS. + +;IOPOP A DIRHNG DEVICE CHANNEL. JUST LIKE OPENING IT EXCEPT THAT +;THE DIRECTORY TRACK NUMBER IS ALREADY IN THE IOCHST. +;ALSO, WE SHOULD GIVE AN INTERRUPT NOW, +;IN CASE THE DIRECTORY WAS WRITTEN IN WHILE THE CHANNEL WAS PUSHED. +DIRHPP: PUSHJ P,DIRHP1 ;FIRST, REOPEN THE CHANNEL. LINK IT INTO THE DIRHNG LIST. + BUG + MOVE A,R + SUBI A,IOCHNM(U) ;COMPUTE CHANNEL NUMBER FROM IOCHNM WORD ADDRESS. + MOVE A,CHNBIT(A) ;GET BIT CORRESPONDING TO CHANNEL. + AND A,MSKST2(U) ;GIVE THE INT IF THE INT IS ENABLED. + IORM A,IFPIR(U) + POPJ P, + +;HERE WITH A/ DIRECTORY'S TRACK NUMBER (AS RETURNED BY QFL) +;TO SIGNAL A WRITE IN THAT DIRECTORY TO ALL DIRHNG DEVICES THAT ARE LOOKING. +;CLOBBERS B, C, D. +DIRSIG: CONO PI,CLKOFF + MOVEI B,DIRHNG +DIRSI0: HLRZ B,(B) ;GET IOCHNM ADDR OF NEXT DIRHNG DEVICE. + JUMPE B,CLKONJ + HRRZ C,IOCHST-IOCHNM(B) + CAIE C,(A) ;DOES IT LOOK AT THIS DIRECTORY? + JRST DIRSI0 + MOVEI C,-IOCHNM(B) ;YES => FIGURE OUT USER INDEX OF JOB IT BELONGS TO. + IDIVI C,LUBLK + IMULI C,LUBLK ;C NOW HAS USER INDEX. + MOVNI D,IOCHNM(C) + ADD D,B ;D GETS CHANNEL NUMBER + MOVE D,CHNBIT(D) + AND D,MSKST2(C) ;INTERRUPT THE USER ON THAT CHANNEL, IF IT'S ENABLED. + IORM D,IFPIR(C) + JRST DIRSI0 diff --git a/src/system/dmpcpy.11 b/src/system/dmpcpy.11 new file mode 100755 index 00000000..a099bb6e --- /dev/null +++ b/src/system/dmpcpy.11 @@ -0,0 +1,153 @@ +; -*- MIDAS -*- + + TITLE DMPCPY - COPY DUMPS FROM SWAP AREA TO FILE AREA + +A=1 +B=2 +C=3 +D=4 +E=5 +T=6 +TT=7 +P=17 + +CHDIRI=10 +CHDSKI=11 +CHDSKO=12 + +.INSRT SYSENG;FSDEFS > + +PDL: -20,,. + BLOCK 20 + +;DIRECTORIES WHERE STUFF MIGHT GET DUMPED OUT OF TIMESHARING +DIRLST: SIXBIT/./ + SIXBIT/CRASH/ + SIXBIT/CRASH2/ +NDIRS==.-DIRLST + +DIR: BLOCK 2000 +BUF: BLOCK 2000 + +USRVAR: SIXBIT /OPTION/ ? TLO %OPINT\%OPOPC + SIXBIT /MASK/ ? MOVE [%PIIOC\%PIPDL] +LUSRVAR==:.-USRVAR + +GO: .CLOSE 1, ;RUNS AS DAEMON + MOVE P,PDL + MOVE TT,[-LUSRVAR,,USRVAR] + .CALL [ SETZ ? SIXBIT /USRVAR/ + MOVEI %JSELF + SETZ TT ] + .LOSE %LSSYS +CHKTIM: .CALL [ SETZ ? SIXBIT /RQDATE/ ; don't frob with files + SETZM A ] ; if system doesn't know the time + .LOSE %LSSYS + AOJN A,KNOTIM + MOVEI A,30.*15. ; 15 seconds + .SLEEP A, + JRST CHKTIM + +KNOTIM: MOVSI E,-NDIRS +CHKDIR: .CALL [ SETZ ? SIXBIT/OPEN/ + [.BII,,CHDIRI] + [SIXBIT/DSK/] + [SIXBIT/.FILE./] + [SIXBIT/(DIR)/] + SETZ DIRLST(E)] + JRST NXTDIR ; Hey, there might not -be- such a directory! + MOVE TT,[-2000,,DIR] + .IOT CHDIRI,TT + .CLOSE CHDIRI, + MOVE D,UDNAMP+DIR +CHKFIL: CAIL D,2000 + JRST NXTDIR + MOVE TT,UNRNDM+DIR(D) + SKIPGE UNDATE+DIR(D) + TLNE TT,UNDUMP\UNIGFL\UNREAP\UNLINK ; Don't screw with files + JRST NXTFIL ; you don't understand. + ;HERE WE HAVE FOUND A FILE WRITTEN OUT OF TIMESHARING + ;COPY IT SO AS TO (1) SET THE FILE DATE AND (2) GET IT OUT + ; OF THE SWAPPING AREA. NTS FILES ARE WRITTEN IN THE SWAPPING + ; AREA TO DECREASE THE PROBABILITY OF CLOBBERING SOME OTHER FILE. + .CALL [ SETZ ? SIXBIT/OPEN/ + MOVES TT + [.BII,,CHDSKI] + [SIXBIT/DSK/] + UNFN1+DIR(D) + UNFN2+DIR(D) + SETZ DIRLST(E) ] + JSP T,[ CAIE TT,%ENSFL ; perhaps a hacker deleted it + CAIN TT,%ENAPK ; perhaps that pack had to go offline + JRST NXTFIL + JRST LOSE ] + .CALL [ SETZ ? SIXBIT/OPEN/ + MOVES TT + [.BIO,,CHDSKO] + [SIXBIT/DSK/] + [SIXBIT/_DMPCP/] + [SIXBIT/OUTPUT/] + SETZ DIRLST(E) ] + JSP T,[ CAIE TT,%EFLDR + JRST LOSE + MOVEI TT,30.*60.*5 ; 5 minutes + .SLEEP TT, + JRST .-1 ] +CPYFIL: MOVE TT,[-2000,,BUF] + .IOT CHDSKI,TT + MOVEI T,-BUF(TT) + JUMPE T,ENDFIL + MOVNS T + MOVSS T + HRRI T,BUF + .IOT CHDSKO,T + JRST CPYFIL + +ENDFIL: .CLOSE CHDSKI, + .CALL [ SETZ ? 'RENMWO + MOVEI CHDSKO + UNFN1+DIR(D) + SETZ UNFN2+DIR(D) ] + .LOSE %LSSYS + .CLOSE CHDSKO, +NXTFIL: ADDI D,LUNBLK + JRST CHKFIL + +NXTDIR: AOBJN E,CHKDIR + .LOGOUT 1, + .VALUE + +; JSP T,LOSE is like .LOSE %LSFIL(TT) +LOSE: .CALL [ SETZ ? SIXBIT /LOSE/ + MOVEI %LSFIL(TT) + SETZI -2(T) ] + .LOSE %LSSYS + +TSINT: +LOC 42 + -LTSINT,,TSINT +LOC TSINT + P + %PIIOC ? 0 ? %PIIOC ? 0 ? IOCINT +LTSINT==:.-TSINT + +; If there is a disk or directory full problem, wait for someone to notice. +IOCINT: PUSH P,T + .SUSET [.RBCHN,,T] + CAIE T,CHDSKO + .LOSE + .STATUS CHDSKO,T + LDB T,[330500,,T] + CAIE T,11 ; DEVICE FULL + CAIN T,14 ; DIRECTORY FULL + JRST WAIT + .VALUE + +WAIT: MOVEI T,30.*60.*5 ; 5 minutes + .SLEEP T, + POP P,T + .CALL [ SETZ ? SIXBIT /DISMIS/ + SETZ P ] + .LOSE %LSSYS + +END GO diff --git a/src/system/dskdmp.215 b/src/system/dskdmp.215 new file mode 100755 index 00000000..fa5a92f2 --- /dev/null +++ b/src/system/dskdmp.215 @@ -0,0 +1,1882 @@ +;;; -*-Midas-*- + +TITLE DSKDMP + +.MLLIT==1 + +DEFINE SETF TEXT,FLG +IFDEF FLG,.STOP +.TAG FOOBAR +PRINTC "TEXT +FLG=" +.TTYMAC FLAG +.TTYFLG==.TTYFLG+1 +PRINTX/FLAG +/ +.TTYFLG==.TTYFLG-1 +IFSE FLAG,YES,FLG==1 +IFSE FLAG,NO,FLG==0 +IFSE FLAG,Y,FLG==1 +IFSE FLAG,N,FLG==0 +IFNDEF FLG,FLG==FLAG +TERMIN +IFNDEF FLG,.GO FOOBAR +TERMIN + +IF1,[ +PRINTC "Configuration (KSRP06, KSRP07, KSRM03, KSRM80 or ASK) ? " +.TTYMAC MACH +IFSE MACH,KSRP06,[ + HRIFLG==0 + RP06P==1 + KS10P==1 + NUDSL==500. +] ;KSRP06 +IFSE MACH,KSRP07,[ + HRIFLG==0 + RP06P==0 + RP07P==1 + KS10P==1 + NUDSL==500. +] ;KSRP07 +IFSE MACH,KSRM03,[ + HRIFLG==0 + RP06P==0 + RP07P==0 + RM03P==1 + KS10P==1 + NUDSL==500. +] ;KSRM03 +IFSE MACH,KSRM80,[ + HRIFLG==0 + RP06P==0 + RP07P==0 + RM03P==0 + RM80P==1 + KS10P==1 + NUDSL==500. +] ;KSRM80 +IFSN MACH,ASK,[ +IFNDEF NUDSL,[ PRINTC /No known configuration for "MACH". +/ ]] +TERMIN +] ;IF1 + +SETF [Readin Mode Paper Tape?]HRIFLG +SETF [Assemble BOOT? (If no, full DSKDMP)]BOOTSW + +SETF [RH11/RP06 disk system?]RP06P +IFE RP06P,[ +SETF [RH11/RP07 disk system?]RP07P +IFE RP07P,[ +SETF [RH11/RM03 disk system?]RM03P +IFE RM03P,[ +SETF [RH11/RM80 disk system?]RM80P +IFE RM80P,[ +SETF [RH10 (MC-KL) disk control?]RH10P +IFE RH10P,[ +SETF [AIKA disk control? (no => RP02/RP03)]DC10P +]]]]] +IFN RP06P, RP07P==0 +IFN RP06P+RP07P, RM03P==0 +IFN RP06P+RP07P+RM03P, RM80P==0 +IFN RP06P+RP07P+RM03P+RM80P, RH10P==0 +IFN RP06P+RP07P+RM03P+RM80P+RH10P, DC10P==0 +IFN RP06P+RP07P+RM03P+RM80P+RH10P+DC10P, RP10P==0 +IFE RP06P+RP07P+RM03P+RM80P+RH10P+DC10P, RP10P==1 + +IFE BOOTSW, SETF [Number of dirs? (DM-KA: 200., ML-KA: 250., AI-KA: 440., all others: 500.)]NUDSL + +SETF [KS10 processor?]KS10P +IFE KS10P, SETF [KL10 processor? (no => KA10)]KL10P +IFN KS10P, KL10P==0 +IFN KS10P+KL10P, KA10P==0 +IFE KS10P+KL10P, KA10P==1 + +RH11P==:RP06P+RP07P+RM03P+RM80P + +DEFINE RP +IFN RP10P!TERMIN +DEFINE SC +IFN DC10P!TERMIN +DEFINE RH +IFN RH10P!TERMIN +DEFINE PH +IFN RH11P!TERMIN + +DEFINE KA +IFN KA10P!TERMIN +DEFINE KL +IFN KL10P!TERMIN +DEFINE KS +IFN KS10P!TERMIN + +IFN HRIFLG,[ +NOSYMS ;MAKE PAPER TAPE SHORTER +RIM10 +] + +C=1 ;C-A-B FOR LINKS +A=2 +B=3 +D=4 +BLKIN=5 ;PSEUDO-CORE BLOCK IN CBUF +WRITE=6 ;NEG MEANS DUMP, RH 0 OR WRBIT +DIFF=7 ;DIFF CONO ALSO TEMP +HEAD=10 ;HEAD CONO ALSO TEMP +P=11 ;JSP AC +BLOK=12 +UNIT=13 ;UNIT AND M.A. DATAO +CMD=14 ;COMMAND CHAR +T=15 ;VERY TEMP +TT=16 ;ANOTHER JSP AC, ALSO VERY TEMP +BUFP=17 ;DBUF PNTR--LAST WORD USED + +IF1,[ ;DON'T TAKE A WEEK AND A HALF TO ASSEMBLE. +RP, .INSRT SYSTEM;RP10 > +SC, .INSRT SYSTEM;DC10 > +RH, .INSRT SYSTEM;RH10 > +PH, .INSRT SYSTEM;RH11 > +IFN RP06P, .INSRT SYSTEM;RP06 > +IFN RP07P, .INSRT SYSTEM;RP07 > +IFN RM03P, .INSRT SYSTEM;RM03 > +IFN RM80P, .INSRT SYSTEM;RM80 > +IFE BOOTSW, .INSRT SYSTEM;FSDEFS > +IFE BOOTSW, KL, .INSRT SYSTEM;EPT > +KS, .INSRT SYSTEM;KSDEFS > +KA, TTY==120 +] + +;PARAMETER FILE FOR DSKDMP + +MEMSIZ=1000000 ;ACTUAL SIZE OF MEM +IFNDEF DBGSW,DBGSW==0 ;1 TO DEBUG THIS WITH DDT +DDT==MEMSIZ-4000 +IFN DBGSW,MEMSIZ==MEMSIZ-10000 ;MOVE DOWN UNDER DDT IF DEBUG MODE +CORE==MEMSIZ-10000-<2000*NTUTBL> ;HIGHEST ADR ALWAYS IN CORE+1 +CORES==CORE_<-12> ;BLK # OF ABOVE (FIRST OF BLKS SWAPPED OUT FOR BUFFER AREAS) +NSWBL==4+NTUTBL ;# BLOCKS SWAPPED OUT FOR BUFFER AREAS, +1 FOR DSKDMP ITSELF +HIGH==MEMSIZ-100 ;HIGHEST ADR LOADED/DUMPED+1 + +NDSK==8 ;MAX POSSIBLE. L$n$ DEFINES WHICH ARE REALLY THERE +RP,ICWA=34 +RH,ICWA=34 + +PH, UBPG==:17 ; Use last (usable) page in Unibus map + +KA, LPM=102000,, +KA, LPMR=LPM 2, +KL, PAG=- + +DEFINE INFORM A,B +IF1,[ PRINTX  A = B +] TERMIN + +;COMMANDS ARE: +; L$file LOAD FILE INTO CORE +; T$file LOAD FILE INTO CORE AND GIVE SYMBOLS TO DDT AND START DDT +; M$file LOAD FILE INTO CORE WITHOUT CLEARING CORE FIRST, DOESN'T LOAD SYMBOLS +; K$file DELETE FILE +; D$file DUMP CORE INTO FILE +; I$file VERIFY FILE AGAINST CORE +; G$ START AT STARTING ADDRESS +; U$dir; LIST DIRECTORY +; F$ LIST CURRENT DIRECTORY +; S$ LIST PACK IDS THEN MFD +; nnn$ SET STARTING ADDRESS TO nnn +; L$n$ PUT DISK n ONLINE +; K$n$ TAKE DISK n OFFLINE + +;ERROR MESSAGES ARE: +; CMPERR VERIFY FAILED TO MATCH +; DIRFUL DIRECTORY FULL +; EOF UNEXPECTED EOF +; DIRNF DIRECTORY DOES NOT EXIST +; FNF FILE NOT FOUND +; PKNMTD FILE IS ON PACK THAT IS NOT MOUNTED +; CKSERR CHECKSUM ERROR +; DSKFUL DISK FULL +; NODDT CAN'T ADDRESS DDT SYMBOL TABLE (BUG) +; ?BUG? BUG +; SEEKFL DISK SEEK ERROR +; CLOBRD DISK READ ERROR +; CLOBWR DISK WRITE ERROR +; DIRCLB DIR NAME DIFFERS, TUT DISAGREES WITH DIR +; MFDCLB M.F.D. CLOBBERED +; DSKLUZ DISK LOSSAGE (OFFLINE OR UNSAFE OR MASSBUS ERROR) + +KS, LOC 4000 ; Avoid MTBOOT and KSRIM + +IFE BOOTSW,[ +ZZZ: IFE DBGSW,[ + MOVE T,.... ;THIS CODE BLTS THE FOLLOWING OFFSET CODE + BLT T,MEMSIZ-1-1 ;INTO HIGH MEMORY AND WRITES DSKDMP ON ITS + MOVE T,PROG+MEMSIZ-2-BEG+1 + MOVEM T,BEG+MEMSIZ-2-BEG+1 ;AVOID LOSING DUE TO -1 BLT LOSSAGE +] + MOVSI T,-NDSK+1 ;MAKE ALL BUT DISK 0 BE DEAD (MUST DO L$ TO MAKE THEM ALIVE) + SETOM QDED+1(T) + MOVNS QDED+1(T) + AOBJN T,.-2 + SETZM QDED+0 +RP,[ MOVEI T,ICWA+2 ;SET UP CHANNEL JUMP + MOVEM T,ICWA ;IN INITIAL CHANNEL ADDRESS + SETZM ICWA+1 ;AND CLEAR REMAINING STUFF + SETZM ICWA+3 + DATAO DPC,SUNIT0 + DATAI DPC,B + TRNN B,RP03BT + JRST WBOOT1 + MOVEI B,MBLKS ;UNIT 0 IS AN RP03, ADJUST WORLD + HRRM B,CBLK + MOVE B,RP3ADJ + MOVSI A,-NSWBL + XORM B,SWPSK(A) + AOBJN A,.-1 +WBOOT1: HLLZS BOOT0 + MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ;FIRST BLOCK AFTER CORE BUFFER IS WHERE DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + CONSZ DPC,ALLER +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG +];RP +PH,[ MOVEI T,%HYCLR ; Clear controller + IOWRQ T,%HRCS2 ; (Selects drive 0) +WBOOT0: IORDQ T,%HRCS1 + TRNN T,%HXDVA + JRST WBOOT0 ; Await drive available (well, it is a dual + ; ported drive... perhaps someday?) + MOVEI UNIT,BEG + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ; FIRST BLOCK AFTER CORE BUFFER IS WHERE + ; DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + IORDQ TT,%HRCS1 + TRNE TT,%HXTRE+%HXMCP +IFN DBGSW, JRST DDT +IFE DBGSW, JRST 4,. ; Formerly JRST MEMSIZ-400 (??) + JRST BEG +];PH +RH,[ MOVEI T,ICWA+2 ;SET UP CHANNEL JUMP + MOVEM T,ICWA ;IN INITIAL CHANNEL ADDRESS + SETZM ICWA+1 ;AND CLEAR REMAINING STUFF + SETZM ICWA+3 +WBOOT0: DATAO DSK,[%HRDCL,,] + MOVEI A,20 + SOJG A,. + DATAI DSK,A + TRNN A,%HCDVA + JRST WBOOT0 ;AWAIT DRIVE AVAILABLE + MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ;FIRST BLOCK AFTER CORE BUFFER IS WHERE DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + CONSZ DSK,%HIERR +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG +];RP +SC,[ MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + MOVEI BLOK,NBLKS+NSWBL + MOVEI WRITE,60 + JSP TT,WRD3 + MOVEI BLOK,NBLKS+NSWBL+1 + MOVEI WRITE,60 + JSP TT,WRD3 + DATAO DC0,..... + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG + +.....: DJMP .+1 + DWRITE + DCOPY ......(-LRIBLK_2&37774) + DHLT + +......: DWRITE+DUNENB+DADR ;FOR READIN + DCOPY BEG(-2000_2&37774) + DREAD+DADR1 + DCOPY BEG(-2000_2&37774) + DHLT +];SC + +IFE DBGSW,[ +....: PROG,,BEG + +KA, LOC 2000 ; MAKE OFFSET CONVENIENT +KL, LOC 2000 +KS, LOC 6000 ; Avoid MTBOOT and KSRIM +PROG: OFFSET CORE+<*2000>-. +]IFN DBGSW,LOC MEMSIZ-2000 + +BEG: +KA,[ CONO 635550 ;ENTER HERE, CLEAR WORLD + JRST .+1 + JFCL 1,[JRST 4,.] ;A PDP6?? + LPMR [0]-2 ;TURN OFF EXEC PAGING +] +KL,[ CONO 327740 ;CLEAR APR + CONSZ PAG,660000 ;PAGING AND CACHE BETTER BE OFF + JRST 4,. +] +KS,[ CONO 127760 ; Enable, and Clear all. + RDEBR B + TRNE B,60000 ; Paging and Tops-20 better be off. + JRST 4,. + SETZM 8SWIT0 ; Clear 8080 Communications area to prevent + MOVE B,[8SWIT0,,8SWIT0+1] ; mysterious IO behavior. + BLT B,8RHBAS-1 + ;; If the machine has just been powered on, there is likely to be + ;; bad parity all over the place. I guess that isn't our problem + ;; as long as we don't touch any of it... +] + MOVSI B,-NDSK ;FOR NUMBER OF DISKS + SETOM PKNUM(B) ;SET DISK TO UNKNOWN + AOBJN B,.-1 + MOVE T,[JRST LOADG1] ;SET BOOTSTRAP TO MIDDLE OF WORLD + MOVEM T,BOOT + MOVE D,['DSKDMP] ;ANNOUNCE SELF + JSP TT,PD + JRST READ ;CRLF AND BEGIN READING COMMANDS + +ERROR: 0 + CLEARM MEMSIZ-1 ;DON'T READ ANY MORE COMMANDS FROM MEMORY + SOS T,ERROR ;PICK UP ERROR CODE FROM THE AC FIELD OF + LDB T,[270400+T,,] ;THE JSR ERROR + MOVE D,ERMESS(T) + JSP TT,PD ;PRINT OUT APPROPRIATE COMMENT + CAIL T,EBUG + JRST READ ;BAD ERROR - NO MORE DISKING +LOADG1: +KA, DATAI TTY,C ;FLUSH RANDOM CHARACTER +KS, SETZM 8CTYIN ; ".RESET" + TRO CMD,10 ;MAKE SURE PSEUDO-CORE IN CORE + JRST LOADG ;BY SIMULATING END OF LOADING, NON-GOING COMMAND + +ERMESS: IRP XX,,[ECMP,EDIR,EEOF,ESNF,EFNF,EPNM,ECKS +EDSK,EDDT,EBUG,EC63,ECRD,ECWR,ECDR,EMFC,EDLZ]YY,,[CMPERR,DIRFUL +EOF,DIRNF,FNF,PKNMTD,CKSERR,DSKFUL,NODDT,?BUG?,SEEKFL +CLOBRD,CLOBWR,DIRCLB,MFDCLB,DSKLUZ] +XX==.-ERMESS + SIXBIT \YY\ +TERMIN + +PD: JSP P,CRLF ;TYPE A CR +PD2: MOVEI C,40 + JSP P,TYO ;AND A SPACE + MOVE B,[440600,,D] +PD1: ILDB C,B ;AND THE SIXBIT CONTENTS OF D + ADDI C,40 + JSP P,TYO + TLNE B,770000 + JRST PD1 + JRST (TT) + +PNO: +C12: IDIVI C,10. ;PRINT CONTENTS OF C AS A TWO-DIGIT + DPB C,[60600,,A] ;DECIMAL NUMBER PRECEDED + MOVEI D,(SIXBIT /#00/+A) ;BY # + MOVE B,[300600,,D] + JRST PD1 + +WRCB: MOVEI UNIT,CBUF ;WRITE OUT CONTENTS OF CBUF + LSH BLKIN,-12 ;ON APPROPRIATE BLOCK + HRRZ BLOK,CBLK + ADDI BLOK,-CORES(BLKIN) + JRST WRM + +LODUMP: MOVEI UNIT,CORE ;DEPENDING ON SIGN BIT OF WRITE, LOAD OR DUMP + HRRZ BLOK,CBLK ;PSEUDO-CORE (766000-775777) +LODMP1: JSP TT,WRDM + ADDI UNIT,2000 + CAIGE UNIT,BEG + AOJA BLOK,LODMP1 + MOVEI BLKIN,CORE + JRST (P) + +FD: HRRZ C,B ;SET UP POINTER IN C TO FETCH OR DEPOSIT + ;CONTENTS OF ADDRESS IN RIGHT HALF OF B +IFN DBGSW, SKIPGE WRITE ;LOAD DDT WHEN IN DEBUG MODE + CAIGE C,HIGH + CAIGE C,40 + JRST (P) + CAIGE C,CORE ;IF ADDR IS IN REAL CORE, RETURN IMMEDIATELY + JRST 1(P) +FDX: CAIL C,(BLKIN) ;ADDR IS IN PSEUDO-CORE--CHECK IF RIGHT + CAILE C,1777(BLKIN) ;BLOCK IS IN CBUF + JRST FD3 ;IT'S NOT THERE--READ IT IN +FD4: SUBI C,-CORE(BLKIN) ;IT'S THERE--SET UP RIGHT POINTER IN C + JRST 1(P) ;AND RETURN +FD3: JUMPLE WRITE,FD3A ;IF DUMP OR VERIFY DON'T BOTHER + ;TO WRITE OUT CURRENT BLOCK +FD3B: JSP TT,WRCB ;IF LOAD, WRITE CURRENT BLOCK FIRST +FD3A: MOVEI UNIT,CBUF + MOVE BLKIN,C + ANDI BLKIN,776000 + LDB BLOK,[121000,,BLKIN] + ADD BLOK,CBLK + MOVEI BLOK,-CORES(BLOK) + JSP TT,RDM ;READ IN CORRECT BLOCK + JRST FD4 ;SET UP POINTER AND RETURN + +GBP: IDIVI C,6 ;TURN USER DIRECTORY CHARACTER ADDR IN C + IMULI A,-60000 ;INTO A BYTE POINTER + HRLI C,440600(A) + ADDI C,DIR+UDDESC + JRST (TT) + +WD: AOBJN BUFP,WD1 ;READ, WRITE, OR VERIFY WORD IN D FROM, INTO, + JSP TT,NXTBLK ;OR AGAINST WORD IN DBUF + JSP TT,WRDB ;TIME TO REFILL OR EMPTY DBUF + MOVSI BUFP,-2000 ;RESET BUFFER POINTER +WD1: JUMPG WRITE,WD2 ;JUMP ON LOAD + JUMPL WRITE,WD3 ;JUMP ON WRITE + CAME D,DBUF(BUFP) ;HERE IF VERIFY + JSR ECMP,ERROR ;VERIFY COMPARE LOST + JRST (P) +WD2: SKIPA D,DBUF(BUFP) ;LOAD +WD3: MOVEM D,DBUF(BUFP) ;DUMP + JRST (P) + +NXTTUT: HRRZ B,CU ;SELECT NEXT UNIT AND READ ITS TUT + AOJ B, + CAIN B,NDSK + MOVEI B,0 + HRRM B,CU + CAIN B,@MU + JRST 1(TT) ;SKIP IF NO MORE + SKIPE QDED(B) + JRST NXTTUT ;UNIT NOT ON LINE +RDTUT: MOVEI BLOK,TUTBLK ;READ TUT OF CURRENT UNIT + MOVEI UNIT,TUT + SETOM PKNUM(B) ;ALWAYS READ HEADER FOR TUT +IFG NTUTBL-1,[ ;READ IN MULTI-BLOCK TUT + HRRM TT,RDTUTX ;SAVE RETURN ADDRESS +REPEAT NTUTBL-1,[ + JSP TT,RD + ADDI UNIT,2000 + AOS BLOK +] +RDTUTX: MOVEI TT,. +] + JRST RD + +NXTBW3: 0 + IBP DIRPT ;DO AN IDPB T,DIRPT CHECKING TO SEE IF + LDB DIFF,[1200,,DIRPT] ;RUNNING INTO NAME AREA + CAML DIFF,DIR+UDNAMP + JSR EDIR,ERROR + DPB T,DIRPT + JRST @NXTBW3 + +NXTBW: MOVE BLOK,LBLOCK ;FIND NEXT FREE BLOCK TO WRITE + MOVEI HEAD,1(BLOK) + ILDB T,TUTPT + JUMPN T,NXTBW1 ;JUMP IF VERY NEXT BLOCK NOT FREE + AOSG T,BLKCNT +NXTBW5: SOJA HEAD,NXTBW4 ;GENERATE LOAD ADR IF FIRST TIME (COMPENSATE FOR LBLOCK OFF BY 1) + CAIG T,UDTKMX-1 + JRST NXTBW2 ;NO NEED TO MODIFY DIRECTORY YET + CLEARM BLKCNT ;14 IN A ROW--RESET COUNTER AND +NXTBW6: JSR NXTBW3 ;DPB BYTE INTO DIRECTORY +NXTBW2: MOVE BLOK,HEAD + CAML BLOK,TUT+QLASTB + JSR EDSK,ERROR ;NO MORE DISK LEFT + MOVEI T,1 + DPB T,TUTPT ;MARK BLOCK USED IN TUT + JRST WRDB1 + +NXTBW1: ADDI HEAD,1 ;SEARCH FOR NEXT FREE BLOCK + ILDB T,TUTPT + JUMPN T,NXTBW1 + SUBM HEAD,BLOK + SKIPLE T,BLKCNT ;COME UP WITH DESC BYTE FOR LAST FEW BLOCKS + JSR NXTBW3 + CLEARM BLKCNT + JUMPL T,NXTBW5 ;FIRST TIME + MOVEI T,UDTKMX-1(BLOK) + CAIGE T,UDWPH ;CAN WE SAY SKIP N--TAKE 1? + JRST NXTBW6 ;YES +NXTBW4: MOVEI BLOK,NXLBYT + MOVE T,HEAD + ROT T,-NXLBYT*6 + ADDI T,UDWPH+1 + JSR NXTBW3 + ROT T,6 + SOJG BLOK,.-2 + JRST NXTBW6 + +NXTBLK: JUMPL WRITE,NXTBW ;GET NEXT BLOCK OF FILE--IF DUMP, FIND FREE + MOVE BLOK,LBLOCK ;BLOCK +NXTB6: SOSLE BLKCNT ;HAVE WE RUN OUT OF "TAKE N"? + AOJA BLOK,WRDB1 ;NO--TAKE NEXT BLOCK + ILDB T,DIRPT ;YES--GET NEXT DESC BYTE + CAILE T,UDWPH + JRST NXTB1 ;IT'S A LOAD ADDR + CAIE T,UDWPH + JUMPN T,NXTB2 ;IT'S A TAKE OR SKIP + CAIE CMD,'D ;IT'S 0 OR NULL--IF THIS IS A LOAD, IT'S AN + CAIN CMD,'K ;UNEXPECTED END OF FILE + JRST KILL1 ;IF DUMP OR KILL, O.K. + JSR EEOF,ERROR + +NXTB1: MOVEI BLOK,-UDWPH-1(T) ;LOAD ADR + MOVEI BUFP,NXLBYTS +NXTB1A: MOVEI T,0 + CAIE CMD,'D + CAIN CMD,'K + DPB T,DIRPT ;IF KILLING FILE, ZERO THIS BYTE (OTHERS ZEROED AT KILL) + LSH BLOK,6 + ILDB T,DIRPT + ADD BLOK,T ;GET COMPLETE BLOCK NUMBER + SOJG BUFP,NXTB1A + JRST NXTB3 + +NXTB2: MOVEM T,BLKCNT + CAIG T,UDTKMX + AOJA BLOK,WRDB1 ;TAKE N STARTING WITH NEXT ONE + ADDI BLOK,-UDTKMX+1(T) ;SKIP N- AND TAKE 1 +NXTB3: CLEARM BLKCNT +WRDB1: MOVEM BLOK,LBLOCK + JRST (TT) + ;RP10 IO ROUTINE +RP,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: DPB WRITE,[360600,,DBLK] ;SET OP, UNIT SEL + DPB WRITE,[DUNFLD SEEK] + DPB WRITE,[DUNFLD RECAL] + HRLI UNIT,-2000 ;ADDRESS COMES IN IN `UNIT' + MOVEM UNIT,@ICWA + SOS @ICWA + LDB UNIT,[300,,WRITE] ;ISOLATE FROM GARBAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: HRRZ DIFF,BLOK + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + DPB HEAD,[DSECT DBLK] + IDIVI DIFF,NHEDS + DPB HEAD,[DSURF DBLK] + DPB DIFF,[DCYL DBLK] + DPB DIFF,[DCYL SEEK] + DATAO DPC,CLATT ;CLEAR ATTENTIONS + LSH DIFF,-8 ;EXTRA CYLINDER BIT FOR RP03 + DPB DIFF,[DCYLXB DBLK] + DPB DIFF,[DCYLXB SEEK] + DATAO DPC,SEEK + DATAI DPC,DIFF + TRNN DIFF,ALLATT + JRST .-2 + DATAO DPC,CLATT + TLNN DIFF,(ONCYL) + JRST WRD0 + DATAO DPC,DBLK + CONSO DPC,DONE + JRST .-1 + CONSO DPC,ALLER + JRST WRDX + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD5 ;TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: HRRZ UNIT,@ICWA ;RESTORE ADDR + ADDI UNIT,1 ;COMPENSATE FOR IOWD LOSSAGE + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: AOSLE ERRCT + JSR EC63,ERROR + DATAO DPC,RECAL + DATAI DPC,DIFF + TRNN DIFF,ALLATT + JRST .-2 + JRST WRD5 + +DBLK: ICWA +SEEK: DSEEKC +RECAL: DRCALC +CLATT: DEASEC ALLATT +];RP + ;RH11 IO ROUTINE +PH,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: TRNE UNIT,1777 ; Better be on a page boundary! + JRST 4,. + LDB DIFF,[111100,,UNIT] ; Point Unibus map at page in question + TRO DIFF,%UQFST+%UQVAL + IOWRQ DIFF,UBAPAG+UBPG_1 + ADDI DIFF,1 + IOWRQ DIFF,UBAPAG+UBPG_1+1 + LDB DIFF,[000300,,WRITE] ; Select drive + IOWRQ DIFF,%HRCS2 + JSP HEAD,RHCHEK ; Check for immediate trouble + MOVEI DIFF,%HMRDP ; Init the drive + IOWRQ DIFF,%HRCS1 + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: MOVNI DIFF,4000 + IOWRQ DIFF,%HRWC ; 4000 half words + MOVEI DIFF,UBPG_14 + IOWRQ DIFF,%HRBA ; "Byte" base address + HRRZ DIFF,BLOK + IDIVI DIFF,NBLKSC + IOWRQ DIFF,%HRCYL ; Desire cylinder + MOVE DIFF,HEAD + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + DPB DIFF,[$HATRK HEAD] + IOWRQ HEAD,%HRADR ; Desire track and sector + MOVEI DIFF,%HMRED + TRNE WRITE,10 + MOVEI DIFF,%HMWRT + IOWRQ DIFF,%HRCS1 ; Do it (implied seek) +WRD7: IORDQ DIFF,%HRCS1 + TRNN DIFF,%HXRDY ; Wait for controller to finish + JRST WRD7 + TRNN DIFF,%HXTRE+%HXMCP ; Trouble? + JRST WRDX ; Nope, exit + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD0 ;RECALIBRATE AND TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: MOVEI DIFF,%HYCLR ; Clear controller + IOWRQ DIFF,%HRCS2 + LDB DIFF,[000300,,WRITE] ; Select drive + IOWRQ DIFF,%HRCS2 + MOVEI DIFF,%HMCLR ; Clear drive + IOWRQ DIFF,%HRCS1 + JSP HEAD,RHCHEK ; Immediate lossage? + MOVEI DIFF,%HMREC ; Recalibrate + IOWRQ DIFF,%HRCS1 + MOVEI HEAD,100000. +WRD0A: SOSGE HEAD + JSR EC63,ERROR + IORDQ DIFF,%HRSTS + TRNE DIFF,%HSPIP ; WAIT FOR DRIVE TO FINISH + JRST WRD0A + ANDI DIFF,%HSDPR+%HSMOL+%HSVV+%HSRDY+%HSERR + CAIE DIFF,%HSDPR+%HSMOL+%HSVV+%HSRDY + JSR EDLZ,ERROR + JRST WRD5 + +;;; JSP HEAD,RHCHEK to check for errors. +RHCHEK: IORDQ DIFF,%HRCS1 + TRNE DIFF,%HXTRE+%HXMCP + JSR EDLZ,ERROR + JRST (HEAD) +];PH + ;RH10 IO ROUTINE +RH,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: HRLI UNIT,-2000 ;ADDRESS COMES IN IN `UNIT' + CONI DSK,HEAD ;SET WORD COUNT TO ONE BLOCK + TLNE HEAD,(%HID22) ;ACCORDING TO TYPE OF CHANNEL + HRLI UNIT,-2000_4 + MOVEM UNIT,@ICWA + LDB UNIT,[300,,WRITE] ;ISOLATE FROM GARBAGE + SOS @ICWA ;ADJUST FOR DF10 LOSSAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMRDP ;INIT THE DRIVE + JSP HEAD,RHSET + HRRZ DIFF,BLOK + IDIVI DIFF,NBLKSC + EXCH DIFF,HEAD + MOVEM HEAD,DBLK ;SAVE CYLINDER + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + EXCH DIFF,HEAD + DPB HEAD,[$HATRK DIFF] + TLO DIFF,%HRADR(UNIT) + JSP HEAD,RHSET + MOVE DIFF,DBLK + TLO DIFF,%HRCYL(UNIT) + JSP HEAD,RHSET + MOVSI DIFF,%HRCTL(UNIT) + IORI DIFF,ICWA_6 + TRNE WRITE,10 + TROA DIFF,%HMWRT + TRO DIFF,%HMRED + JSP HEAD,RHSET ;DO IT (USE IMPLIED SEEK) + CONSO DSK,%HIDON + JRST .-1 + CONSO DSK,%HIERR + JRST WRDX + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD0 ;RECALIBRATE AND TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: HRRZ UNIT,@ICWA ;RESTORE ADDR + ADDI UNIT,1 ;COMPENSATE FOR IOWD LOSSAGE + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMCLR + JSP HEAD,RHSET + MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMREC + JSP HEAD,RHSET + MOVEI DIFF,100000. + MOVEM DIFF,DBLK +WRD0A: SOSGE DBLK + JSR EC63,ERROR + MOVSI DIFF,%HRSTS(UNIT) + JSP HEAD,RHGET + TRNE DIFF,%HSPIP + JRST WRD0A + ANDI DIFF,%HSVV+%HSRDY+%HSMOL+%HSERR + CAIE DIFF,%HSVV+%HSRDY+%HSMOL + JSR EDLZ,ERROR + JRST WRD5 + +;RH10 HACKING ROUTINES. CALL BY JSP HEAD,. DIFF HAS REGISTER ADDRESS IN LH, DATA IN RH. +RHSET: TLOA DIFF,%HRLOD +RHGET: TLZ DIFF,%HRLOD + DATAO DSK,DIFF + MOVEI DIFF,20 + SOJG DIFF,. + DATAI DSK,DIFF + TLNE DIFF,%HDERR + JSR EDLZ,ERROR + ANDI DIFF,177777 + JRST (HEAD) + +DBLK: 0 +];RH + ;SC DISK IO ROUTINE +SC,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,60#120 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,60#120 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: TRC WRITE,120 +WRD3: DPB WRITE,[330700,,DBLK] ;SET OP, UNIT SEL + DPB UNIT,[DCCA DBLK+1] ; & CORE ADDR + DPB UNIT,[DCCA DBLK1+1] + LDB UNIT,[400,,WRITE] ;ISOLATE FROM GARBAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: HRRZ DIFF,BLOK + IDIVI DIFF,NSECS + DPB HEAD,[DSECT DBLK] + IDIVI DIFF,NHEDS + DPB HEAD,[DSURF DBLK] + DPB DIFF,[DCYL DBLK] + CONO DC0,DCCSET\DCDENB ;RESET ALL, THEN SET DCDENB + CAIL DIFF,NCYLS + TDZA DIFF,DIFF + SKIPLE DIFF,PKNUM(UNIT) + JRST WRD4 ;PKID IN + MOVE DIFF,QTRAN(UNIT) ;READ PACK ID + DPB DIFF,[DUNFLD GPKID] + MOVEI DIFF,TUTCYL + SKIPGE QTRAN(UNIT) + ADDI DIFF,NCYLS+XCYLS + DPB DIFF,[DCYL GPKID] + DATAO DC0,[DJMP GPKID] + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR + JRST WRD0 + CONO DC0,DCCSET\DCDENB ;RESET POSSIBLE "FUTURE" IP OR RLCERR + LDB DIFF,[DPKID RPKID] + MOVEM DIFF,PKNUM(UNIT) +WRD4: DPB DIFF,[DPKID DBLK] + MOVE DIFF,DBLK + DPB DIFF,[3300,,DBLK1] + MOVE DIFF,QTRAN(UNIT) + DPB DIFF,[DUNFLD DBLK] + JUMPGE DIFF,WRD4A + LDB DIFF,[DCYL DBLK] ;2ND HALF UNIT + ADDI DIFF,NCYLS+XCYLS + DPB DIFF,[DCYL DBLK] +WRD4A: DATAO DC0,[DJMP DBLK] + CONSZ DC0,DSSACT + JRST .-1 + CONSO DC0,DSSERR + JRST WRDX ;XFER OK + MOVE DIFF,ERRCT + TRNN DIFF,2 ;DO RECALIBRATE 2 OUT OF 4 RETRIES + JRST WRD2 +WRD0: AOSLE ERRCT ;POSITIONER ERROR--CHECK ERROR COUNT + JSR EC63,ERROR ;TOO MANY--GIVE UP + DATAO DC0,[DSPC+DSRCAL+DSWINF] + CONSO DC0,DSSATT + JRST .-1 + JRST WRD5 ;TRY AGAIN AFTER RESETTING UNIT + +WRD2: HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD5 ;TRY AGAIN + TRNE WRITE,40 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: DPB BLOK,[XWBLK XWDS] ;PNTR TO PREV BLOCK + LDB UNIT,[DCCA DBLK+1] ;RESTORE ADR + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +DBLK: DREAD+DUNENB + DCOPY .(-2000_2&37774) + DCOPY XWDS(-4_2&37774) +DBLK1: DRC + DCOPY .(-2000_2&37774) + DCOPY XWDS(-4_2&37774) + DHLT + +GPKID: DSPC+DSCRHD+DSWIDX+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +];SC + +;JSP P,TYI RETURNS CHAR IN C. +;JSP P,TYI0 ALSO SKIPS IF NO INPUT AVAILABLE. +TYI: ILDB C,MEMSIZ-1 ;CHECK FOR COMMANDS FROM MEMORY + JUMPN C,(P) ;FOUND ONE--RETURN + CLEARM MEMSIZ-1 +TYI0: ;ENTRY TO SKIP IF NO INPUT AVAILABLE +KA,[ CONSO TTY,40 + JRST TYI1 + DATAI TTY,C +] +KS,[ SKIPN C,8CTYIN + JRST TYI1 + ANDI C,177 + SETZM 8CTYIN +] +KL,[ MOVEI C,3400 ;DDT MODE INPUT + SETZM DTEFLG + MOVEM C,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + MOVE C,DTEF11 + SETZM DTEFLG + JUMPE C,TYI1 +] ANDI C,177 + CAIGE C,175 + CAIN C,33 + JRST (P) ;DON'T ECHO GRITCHES +;DROP INTO TYO + +;JSP P,TYO TYPES OUT CHAR IN C. CLOBBERS A,C. +TYO: ;SKIPE MEMSIZ-1 + ; JRST (P) ;DON'T ECHO COMMANDS FROM MEMORY +KA,[ HRRZ A,C ;COMPUTE PARITY + IMULI A,40201 + AND A,[1111111] + IMUL A,[1111111] + TLNE A,1 + IORI C,200 + CONSZ TTY,20 + JRST .-1 + DATAO TTY,C + ANDCMI C,200 +] +KS,[ MOVE A,C + ANDI A,177 + TRO A,400 + MOVEM A,8CTYOT + CONI A + IORI A,80INT + CONO (A) + SKIPE 8CTYOT + JRST .-1 +] +KL,[ MOVE A,C + ANDI A,177 + SETZM DTEFLG + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SETZM DTEFLG +] + JUMPGE C,(P) ;CHECK FOR CRLF (AS OPPOSED TO ECHOING A CR) + SKIPA C,C12 ;TYPE AN LF +CRLF: HRROI C,15 + JRST TYO + +TYI1: HRRZ C,-1(P) ;NO INPUT AVAILABLE + CAIE C,TYI0 + JRST TYI ;WAIT FOR IT + JRST 1(P) ;CALL WAS TO TYI0, SKIP RETURN + +LINK: CAIE CMD,'D + CAIN CMD,'K + MOVSI WRITE,-1 ;MAKE THIS INFO MORE CONVENIENT + MOVE D,[440600,,C] + MOVEI T,0 +LINKL: ILDB TT,DIRPT + SKIPGE WRITE + DPB T,DIRPT ;CLOBBER CHARS READ FOR DUMP OR KILL + CAIN TT,'; + JRST LINKN + CAIN TT,': + JRST LINKQ + JUMPE TT,LINKN +LINKQ1: IDPB TT,D + TLNE D,770000 + JRST LINKL +LINKN1: CAMGE D,[600,,B] ;THROUGH WITH FN2? + JRST LINKL + JUMPL WRITE,KILL1 + MOVEM A,FN1 + MOVEM B,FN2 + JRST MLOOK2 + +LINKN: TLNN D,770000 + JRST LINKN1 + IDPB T,D ;FILL OUT WITH SPACES + JRST LINKN + +LINKQ: ILDB TT,DIRPT + JUMPGE WRITE,LINKQ1 + DPB T,DIRPT + JRST LINKQ1 + +READ: MOVEI BLKIN,CORE + JSP P,CRLF + MOVEI CMD,0 ;INITIALIZE COMMAND +READ1A: MOVEI WRITE,0 ;INITIALIZE NUMBER + MOVSI B,(SIXBIT \@\) ;INITIALIZE 1ST FILE NAME +READ1: MOVEM B,FN1 +READ3A: MOVSI B,(SIXBIT \@\) ;INITIALIZE CURRENT FILE NAME + MOVE D,[440600,,B] +READ2: JSP P,TYI + CAIN C,177 + JRST READ ;IF RUBOUT START OVER + CAIGE C,175 + CAIN C,33 + JRST ALTMOD ;JUMP IF 33, 175, 176 + ASH WRITE,3 ;DOES NOT CHANGE SIGN OF WRITE + CAIL C,"0 + CAILE C,"7 + TLOA WRITE,400000 ;NON-NUMERIC CHAR--MAKE WRITE NEGATIVE + ADDI WRITE,-"0(C) ;NUMERIC CHAR--ACCUMULATE NUMBER + CAIN C,"; + JRST READ3 ;SET SYSTEM NAME + CAIN C,40 + JRST READ1 ;SET FIRST FILE NAME + CAIN C,^Q + JSP P,TYI ;QUOTED CHARACTER + CAIGE C,140 ;CHECK FOR LOWER CASE + SUBI C,40 + JUMPL C,DOIT ;IF LESS THAN 40 (EXC. ^Q) END OF COMMAND + TLNE D,770000 ;SKIP IF ALREADY SIX CHARS + IDPB C,D + JRST READ2 + +READ3: MOVEM B,SYSN + CAIE CMD,'U + JRST READ3A + JRST DOIT ;IF COMMAND IS U GO LIST DIRECTORY + +ONOFF: CAIGE WRITE,NDSK + DPB CMD,[100,,QDED(WRITE)] ;LOW BIT OF CMD DETERMINES ON/OFF LINE STATUS + JRST READ ; (K=13, L=14) + +ALT1: LDB CMD,D ;PICK UP COMMAND CHAR + CAIE CMD,'K + TRNN CMD,2 + JRST READ1A ;GET FILE NAME + JRST DOIT ;DON'T WANT FILE NAME--GO TO WORK + +ALTMOD: MOVEI C,"$ + JSP P,TYO ;ECHO DOLLAR SIGN + JUMPLE WRITE,ALT2 ;JUMP IF NOT LAST TYPED + JUMPN CMD,ONOFF ;JUMP IF + HRRM WRITE,SADR ;SET STARTING ADDR + JRST READ + +ALT2: TLC D,360000 + TLCN D,360000 ;SKIP IF SINGLE CHARACTER BEFORE + JUMPE CMD,ALT1 ;JUMP IF NO COMMAND ALREADY TYPED +DOIT: MOVEM B,FN2 ;STORE SECOND FILE NAME + HRRZ B,MU + HRRM B,CU ;MAKE MASTER UNIT CURRENT UNIT + MOVNI WRITE,1 + JSP P,LODUMP ;DUMP OUT PSEUDO-CORE + CAIN CMD,'G + JRST LOADG0 ;GO + JSP TT,RDTUT + MOVE C,SYSN +MLOOK2: MOVSI WRITE,1 ;MAKE WRITE INDICATE LOAD + MOVEI BLOK,MFDBLK + MOVEI UNIT,DIR + JSP TT,RD ;READ MASTER DIRECTORY TO FIND WHERE USER DIRECTORY IS + MOVE T,DIR+MDCHK + CAME T,[SIXBIT/M.F.D./] + JSR EMFC,ERROR + MOVE T,DIR+MDNUDS + CAIE T,NUDSL + JSR EMFC,ERROR + CAIN CMD,'S + JRST LISTS ;LIST DISK ID'S AND SYSTEM NAMES + MOVE T,DIR+MDNAMP +MLOOK: CAMN C,DIR+MNUNAM(T) ;LOOK UP SYSTEM NAME + JRST MLOOK1 + ADDI T,LMNBLK + CAIGE T,2000 + JRST MLOOK + JSR ESNF,ERROR ;NOT FOUND + +MLOOK1: MOVEI BLOK,2*NUDSL-2000(T) ;CONVERT USER SLOT TO BLOCK NUMBER + LSH BLOK,-1 + HRRM BLOK,UDBLK ;REMEMBER FOR KILL OR DUMP + MOVEI UNIT,DIR + JSP TT,RDM ;READ USER DIRECTORY +ULOOK: CAME C,DIR+UDNAME + JSR ECDR,ERROR ;WRONG ONE?? + CAIE CMD,'F + CAIN CMD,'U + JRST LISTFC ;LIST USER DIRECTORY + MOVSI TT,UNIGFL + MOVE T,DIR+UDNAMP + MOVE A,FN1 + MOVE B,FN2 +ULOOK1: CAMN A,DIR+UNFN1(T) ;LOOK UP FILE NAME + CAME B,DIR+UNFN2(T) + JRST ULOOK2 + TDNN TT,DIR+UNRNDM(T) ;IS THIS FILE FOR REAL? + JRST ULOOK3 +ULOOK2: ADDI T,LUNBLK + CAIGE T,2000 + JRST ULOOK1 + CAIE CMD,'D ;IF NOT FOUND BETTER BE DUMP + JSR EFNF,ERROR + MOVE T,DIR+UDNAMP +ULOOK4: SKIPN DIR+UNFN1(T) ;FIND FREE SLOT FOR NEW FILE + JRST DUMP + ADDI T,LUNBLK + CAIGE T,2000 + JRST ULOOK4 + MOVNI T,LUNBLK ;NO FREE SLOTS--TRY TO EXTEND NAME AREA DOWN + ADDM T,DIR+UDNAMP + MOVE T,DIR+UDESCP + IDIVI T,6 + ADDI T,UDDESC + CAMGE T,DIR+UDNAMP ;DID WE RUN INTO DESCRIPTOR AREA? + JRST DUMP0 + JSR EDIR,ERROR ;YES + +ULOOK3: HRRM T,DMP4 ;IF FILE FOUND, SAVE SLOT NUMBER FOR DUMP + LDB C,[UNDSCP DIR+UNRNDM(T)] + JSP TT,GBP + MOVEM C,DIRPT ;SET UP DESCRIPTOR AREA BYTE POINTER + MOVSI TT,UNLINK + TDNE TT,DIR+UNRNDM(T) + JRST LINK ;FILE IS A LINK + LDB A,[UNPKN DIR+UNRNDM(T)] +ULOOK5: CAMN A,TUT+QPKNUM ;SEE IF IT'S MOUNTED + JRST LOAD + JSP TT,NXTTUT + JRST ULOOK5 + JSR EPNM,ERROR + +LOAD: CAIE CMD,'D ;GET HERE IF FILE FOUND + CAIN CMD,'K ;IF DUMP OR KILL, DELETE IT + JRST KILL +ZERO: MOVEI TT,CORE-1 + TRNN CMD,20 ;SKIP IF T$ SYMBOL LOADING COMMAND + JRST ZERO1 + MOVEI B,DDT-1 ;ASSUME ALWAYS USING MOBY DDT + JSP P,FD ;GET DDT'S SYMBOL TABLE POINTER + JSR EDDT,ERROR ;CAN'T GET IT?? + HRROS B,(C) ;TELL DDT ITS SYMBOL TABLE WAS BUGGERED + CAME B,[-1,,DDT-2] ;VERIFY THAT IT'S REALLY A MOBY DDT LIKE WE THOUGHT + JSR EDDT,ERROR + SKIPE D,-2(C) ;FLUSH ALL BUT INITIAL SYMBOLS + MOVEM D,-1(C) + MOVE D,-1(C) + MOVEI TT,CORE-1 + CAILE TT,-1(D) + MOVEI TT,-1(D) ;DON'T ZERO SYMBOL TABLE NOR DDT +ZERO1: TRNE CMD,1 + JRST LOAD1 ;NON-ZEROING COMMAND + SETZM 40 ;BEGIN CLEARING CORE + MOVE T,[40,,41] ;SET UP BLT POINTER +;CODE TO SKIP OVER NXM +ZERO2: CAIG TT,10*2000-1(T) ;MORE THAN 8K LEFT TO ZERO? + JRST ZERO4 ;NO, ZERO REMAINING WORDS AND PROCEED + MOVE D,T ;AVOID KA/KL INCOMPAT BY COPYING BLT PNTR + BLT D,10*2000-1(T) ;ZERO NEXT 8K +ZERO3: ADDI T,10*2000 ;MOVE DEST OF BLT PNTR UP 8K + ANDCMI T,1777 ;ROUND DOWN TO 1K BOUNDARY +KA, CONO 10000 ;CLEAR NXM + MOVES (T) ;SET NXM IF HOLE +KA, CONSZ 10000 ;NXM GENERATED? +KA, JRST ZERO3 ;YES, GO TO NEXT 8K + JRST ZERO2 ;NO, CLEAR THIS 8K + +ZERO4: BLT T,(TT) ;AND CLEAR TO TOP BOUNDARY + TRNE CMD,20 + JRST LOAD1 ;IF SYMBOL-LOADING COMMAND, STOP THERE + CLEARM CBUF + MOVE T,[CBUF,,CBUF+1] + BLT T,CBUF+1777 + MOVEI UNIT,CBUF + MOVE BLOK,CBLK ;-NSWBL IN LH + JSP TT,WRM ;CLEAR PSEUDO-CORE + AOBJN BLOK,.-1 +LOAD1: SETZB BUFP,BLKCNT ;SET UP BUFP SO FIRST CALL TO WD WILL READ +LOAD2: JSP P,WD ;FIRST BLOCK OF FILE + CAME D,[JRST 1] ;LOOK FOR END OF SBLK LOADER + JRST LOAD2 + CAIN CMD,'I ;IF VERIFY, START SIMULATING DUMP + JRST DUMP.5 +LOAD3: JSP P,WD ;READ BLOCK HEADER + JUMPGE D,LOADS ;IT'S A JUMP BLOCK + MOVE A,D + MOVE B,D + JSR LOADB ;LOAD LOGICAL BLOCK INTO CORE + JRST LOAD3 + +LOADB: 0 +LOAD4: JSP P,WD ;LOAD A LOGICAL BLOCK--AOBJN POINTER IN B, + ROT A,1 ;BLOCK HEADER IN A (FOR CHECKSUM) + ADD A,D ;ADD NEW WORD INTO CHECKSUM + JSP P,FD ;AND PREPARE TO SMASH IT AWAY + JRST .+2 ;LOCATION CAN'T BE LOADED + MOVEM D,(C) ;SMASH WORD AWAY + AOBJN B,LOAD4 + JSP P,WD + CAMN A,D ;CHECK THE CHECKSUM + JRST @LOADB + JSR ECKS,ERROR ;BAD CHECKSUM + +LOADS: CAIN CMD,'M + JRST LOADG0 ;DON'T LOAD SYMBOLS NOR SADR + MOVEM D,NXTBW3 ;SAVE S.A. + MOVEI B,DDT-1 ;ASSUME IS ALWAYS MOBY DDT. + JSP P,FD ;GET DDT'S SYMBOL TABLE POINTER + JSR EDDT,ERROR ;CAN'T GET IT?? + SKIPN (C) + JRST LOADJ ;AIN'T GOT NO DDT, IGNORE SYMBOLS + HRROS B,(C) ;TELL DDT ITS SYMBOL TABLE WAS BUGGERED + CAMN B,[-1,,DDT-2] ;VERIFY THAT IT'S REALLY A MOBY DDT LIKE WE THOUGHT + JSP P,FD ;FETCH SYMBOL TABLE POINTER + JSR EDDT,ERROR + MOVE D,(C) + MOVEM D,DDTM2 +LOADS1: MOVE B,DDTM2 ;GET LOWEST SYMBOL LOC SO FAR + JSP P,WD ;GET SYMBOL BLOCK HEADER + JUMPGE D,LOADS2 ;JUMP IF END OF SYMBOLS + TRNE D,-1 ;SKIP IF REALLY SYMBOLS AND NOT SOME OTHER BRAIN-DAMAGED CRUFT + JRST LOADBD + MOVSS D + HRLI D,-1(D) + ADD B,D ;EFFECTIVELY SUBTRACTS LENGTH OF BLOCK FROM BOTH HALVES + MOVEM B,DDTM2 ;OF SYMBOL TABLE POINTER + HRL B,D ;SET UP AOBJN POINTER IN B + HRLZ A,D ;AND RECREATE HEADER IN A + JSR LOADB ;LOAD THE SYMBOLS + JRST LOADS1 + +LOADBD: HLRO B,D ;-# WORDS TO SKIP (NOT COUNTING CHECKSUM) + JSP P,WD + AOJLE B,.-1 + JRST LOADS1 ;TRY NEXT SYMBOL BLOCK + +LOADS2: MOVE D,DDTM2 ;GET UPDATED DDT SYMBOL PNTR +LOADS4: MOVEI B,DDT-2 ;WE KNOW WHERE IT ALWAYS GOES + JSP P,FD ;PUT BACK SYMBOL TABLE POINTER + JSR EBUG,ERROR ;CAN'T PUT IT BACK?? + MOVEM D,(C) + MOVEI B,DDT-4 ;GIVE STARTING ADDRESS TO DDT + JSP P,FD + JSR EBUG,ERROR + MOVE D,NXTBW3 + MOVEM D,(C) + MOVEI D,DDT ;AND SET DSKDMP START ADDRESS TO DDT +LOADJ: HRRM D,SADR ;SET STARTING ADDRESS FROM JUMP BLOCK +LOADG0: MOVE T,BOOTNS ;APPROP DISK WAIT FOR NON BUSY INSTR + MOVEM T,BOOT +LOADG: JSP TT,WRCB ;MAKE SURE ALL LOADED CRUFT IN PSEUDO-CORE IS OUT + MOVEI WRITE,0 + JSP P,LODUMP ;AND LOAD IT ALL IN + TRNE CMD,10 + JRST READ ;NON-GOING COMMAND +GO: +PH,[ MOVSI B,-LSWPADR +GO1: IORD DIFF,SWPCS1 + TRNN DIFF,%HXRDY ; Wait for controller + JRST GO1 + HRRZ DIFF,SWPVAL(B) + IOWR DIFF,SWPADR(B) + AOBJN B,GO1 +];PH +RH,[ MOVE B,ERRWD + CONI DSK,HEAD + TLNE HEAD,(%HID22) + HRLI B,-1700_4 + MOVEM B,@ICWA + MOVSI B,-6 +GO1: CONSZ DSK,%HIBSY + JRST .-1 + MOVE DIFF,SWPOU1(B) + JSP HEAD,RHSET + AOBJN B,GO1 +];RH +RP,[ MOVE B,ERRWD + MOVEM B,@ICWA + DATAO DPC,SWPSK + JSP P,SKWAIT + DATAO DPC,SWPOU1 + CONSO DPC,DONE + JRST .-1 + DATAO DPC,SWPOU2 +];RP +SC, DATAO DC0,[DJMP SWPOUT] + JRST WAIT + +LISTS: JSP P,CRLF +LISTS2: JSP P,TYI0 + JRST LOADG1 ;SHUT UP IF KEY HIT + MOVE C,TUT+QPKNUM ;TYPE PACK NUMBER + JSP TT,PNO + MOVE D,TUT+QPAKID ;AND I.D. + JSP TT,PD2 + JSP TT,NXTTUT ;SAME FOR ALL DIRECTORIES + JRST LISTS2 + MOVE T,DIR+MDNAMP +LISTS1: CAIGE T,2000 + JSP P,TYI0 ;STOP TYPING IF TTI FLAG ON + JRST LOADG1 + SKIPE D,DIR+MNUNAM(T) + JSP TT,PD ;TYPE OUT USER NAME + ADDI T,LMNBLK + JRST LISTS1 + +LISTFC: MOVE T,DIR+UDNAMP +LISTF1: +KA, CONSO TTY,40 ;STOP TYPING IF TTI FLAG ON +KS, SKIPN 8CTYIN ; Stop typing if character waiting + CAIL T,2000 + JRST LOADG1 + SKIPN DIR+UNFN1(T) ;SKIP IF FILE IN THIS SLOT + JRST LISTF2 + JSP P,CRLF + LDB C,[UNPKN DIR+UNRNDM(T)] + JSP TT,PNO ;TYPE PACK NUMBER + MOVE D,DIR+UNFN1(T) + JSP TT,PD2 ;TYPE FIRST FILE NAME + MOVE D,DIR+UNFN2(T) + JSP TT,PD2 ;AND SECOND FILE NAME +LISTF2: ADDI T,LUNBLK + JRST LISTF1 + +KILL: JSP TT,NXTB6 ;GET HERE ON KILL OR DUMP OF EXISTING FILE + MOVEI T,0 ;ZERO BYTES IN USER DIRECTORY DESCIPTOR AREA + DPB T,DIRPT ;NXTB6 JUMPS TO KILL1 AT END OF FILE + MOVE C,BLOK + JSP TT,GTP + ILDB T,C + CAIGE T,TUTLK-1 ;SOS USAGE OF THIS BLOCK + SOJL T,[JSR ECDR,ERROR] + DPB T,C + JRST KILL + +KILL1: HRRZ T,DMP4 ;CLEAR OUT USER DIRECTORY SLOT + CLEARM DIR+UNFN1(T) + CLEARM DIR+UNFN2(T) + CLEARM DIR+UNRNDM(T) + MOVSI WRITE,-1 + CAIN CMD,'K + JRST KILDMP ;IF KILL DON'T DUMP + JRST DMP4 ;MUST DUMP ON SAME UNIT + +DUMP0: MOVE T,DIR+UDNAMP ;GET HERE IF SLOT CREATED AT BOTTOM OF NAME AREA +DUMP: HRRM T,DMP4 ;GET HERE IF EMPTY SLOT FOUND IN NAME AREA +DMP0: MOVEI D,0 ;GET HERE IF USING SLOT OF OLD FILE +DMP1: ;MOVE C,TUT+QSWAPA + MOVEI C,0 ;NOTE START AT 0 NOT QSWAPA + MOVE B,C + SUB B,TUT+QLASTB + HRLZ B,B ;LH(B) COUNTS BLOCKS, RH(B) COUNTS FREE BLOCKS + JSP TT,GTP +DMP2: ILDB T,C + SKIPE T +KA, SUBI B,1 ;THIS RELIES ON CARRY PROPAGATING FROM RH TO LH IN AOBJN +KL, HRRI B,-1(B) ;ON KI10, KL10 CHANGE SUBI B,1 TO HRRI B,-1(B) +KS, HRRI B,-1(B) ;KS too... + AOBJN B,DMP2 + CAIG B,(D) ;RH OF D IS HIGHEST SO FAR, LH SAYS WHICH UNIT + JRST DMP5 ;NOT BETTER THAN RECORD + MOVE D,B ;NEW RECORD--RECORD IT + HRL D,CU +DMP5: JSP TT,NXTTUT ;TRY NEXT + JRST DMP1 + ;FALLS THROUGH AT END +DMP3: HLRM D,CU ;SET CURRENT UNIT TO ONE WITH MOST FREE BLOCKS + JSP TT,RDTUT ;GET ITS TUT +DMP4: MOVEI T,. + MOVE A,FN1 + MOVE B,FN2 + MOVEM A,DIR+UNFN1(T) ;PUT CRUFT INTO SLOT + MOVEM B,DIR+UNFN2(T) + SETOM DIR+UNDATE(T) ; Unknown creation date + HRROI C,777000 ; Unknown reference date + MOVEM C,DIR+UNREF(T) ; Unknown author, 36. bit bytes +SC,[ MOVEM A,XWDS+XWFN1 + MOVEM B,XWDS+XWFN2 + MOVE C,SYSN + MOVEM C,XWDS+XWSYSN +] MOVE C,DIR+UDESCP ;PUT DESCRIPTOR CHARACTER ADDRESS + MOVE B,TUT+QPKNUM ;AND PACK NUMBER + DPB B,[UNPKN C] + MOVEM C,DIR+UNRNDM(T) ;INTO USER DIRECTORY SLOT + ;MOVE C,TUT+QSWAPA ;COMMENTED OUT INSN DUMPS INTO FILE AREA + MOVEI C,0 ;DUMP INTO SWAPPING AREA TO AVOID Y FILES + MOVEM C,LBLOCK ;A DAEMON WILL COPY INTO FILE AREA AFTER SALVAGE + JSP TT,GTP + MOVEM C,TUTPT ;INITIALIZE TUT POINTER + MOVE C,DIR+UDESCP + JSP TT,GBP + MOVEM C,DIRPT ;INITIALIZE DESCRIPTOR AREA POINTER + SETOB WRITE,BLKCNT ;FORCE NXTBW TO LOAD ADR +KA, HRLOI BUFP,-2001-1 ;SET UP BUFP SO FIRST WORD GOES IN DBUF+0 +KL, HRLOI BUFP,-2001 +KS, HRLOI BUFP,-2001 + MOVE D,[JRST 1] + JSP P,WD ;END OF SBLK LOADER +;DROPS THROUGH + +;DROPS IN +DUMP.5: MOVSI WRITE,-'I(CMD) ;GET HERE IF VERIFY--SET WRITE NEGATIVE IF + MOVEI B,40 ;DUMP AND ZERO IF VERIFY--FIRST ADDR DUMPED IS 40 + HRRM B,DUMP4 + HLLOS DUMP6 + SETZM DUMP9S + SETZM DUMP9J + SETZM DUMP9K + MOVEI B,DDT-3 ;SET UP TO NOT DUMP SYMBOLS AS PART OF CORE IMAGE + JSP P,FD + JSR EBUG,ERROR + SKIPN A,(C) ;GET PNTR TO BUILT IN SYMBOLS + JRST DUMP4 ;NO DDT, DON'T HACK THIS + HRRM A,DUMP7 ;THIS IS WHERE WE START DUMPING AGAIN + MOVEM A,DUMP9K ;THIS WILL BE INITIAL SYMBOL TABLE PNTR WHEN DDT LOADED + MOVNI A,(A) + ADD A,1(C) ;GET MINUS SIZE OF NON-BUILTIN SYMBOL TABLE IN RH(A) + HRL A,1(C) ;GET PNTR TO SYMBOL TABLE + HLRM A,DUMP6 ;THIS IS WHERE WE STOP DUMPING + MOVSM A,DUMP9S ;SAVE AOBJN PNTR TO NON-BUILTIN SYMBOLS + MOVE A,-1(C) ;PICK UP START ADDRESS + MOVEM A,DUMP9J ;SAVE + MOVE B,-2(C) ;DUMP LOW CORE (ACS) OUT OF PLACE SAVED IN DDT + HLLZ A,B ;HERE B HAS ADDRESS DUMPING FROM + JRST DUMP3B ;AND A AND D HAVE VIRTUAL ADDRESS + +DUMP1: ;SKIP OVER NXM ON DUMPING +KA,[ CONSO 10000 ;NXM SET? + JRST DUMP1A ;NO, CONTINUE IN SEQUENCE + ADDI B,10*2000-1 ;SKIP 8K + TRZ B,1777 ;ROUND DOWN TO 8K BOUDARY + CONO 10000 ;CLEAR NXM +DUMP1A: +];KA +DUMP6: CAIGE B,. ;SKIP IF REACHED SYMBOL TABLE + JRST DUMP8 +DUMP7: MOVEI B,. ;SKIP OVER SYMBOLS, DUMP DDT + HLLOS DUMP6 ;DEFUSE TEST +DUMP8: JSP P,FD + JRST DUMPJ ;TIME TO WRITE JUMP BLOCK AND SYMBOL TABLE + SKIPN (C) ;LOOK FOR NON-ZEROES + AOJA B,DUMP1 + MOVE A,B ;SAVE START OF BLOCK +DUMP2: TLZ A,-1 ;LOOK FOR TWO CONSECUTIVE ZEROES +DUMP2A: CAIL B,200(A) ;BUT DON'T DUMP MORE THAN 200 WORDS AT A TIME + JRST DUMP3 + XCT DUMP6 + JSP P,FD + JRST DUMP3 ;END OF CORE, WRITE OUT LAST BLOCK + SKIPE (C) + AOJA B,DUMP2 ;NONZERO + TLON A,-1 ;ZERO, WAS PREV LOC ZERO ALSO? + AOJA B,DUMP2A ;NO, CHECK FOLLOWING LOC + SOJA B,DUMP3 ;YES, DUMP THE NON-ZERO THAT PRECEDES IT + +DUMP3: HRRM B,DUMP4 ;SAVE ADDRESS TO CONTINUE SEARCH + SUBM A,B ;RH(B) GETS MINUS THE LENGTH OF THE BLOCK + HRL A,B ;SET UP HEADER IN A + MOVE B,A ;AND B +DUMP3B: MOVE D,A ;AND D + JSP P,WD ;WRITE HEADER +DUMP3A: JSP P,FD + JSR EBUG,ERROR ;CAN'T FETCH WORD WE FETCHED BEFORE?? + MOVE D,(C) + ROT A,1 + ADD A,D ;COMPUTE CHECKSUM + JSP P,WD ;WRITE DATA WORD + AOBJN B,DUMP3A + MOVE D,A + JSP P,WD ;WRITE OUT CHECKSUM +DUMP4: MOVEI B,. ;AND CONTINUE SEARCHING + JUMPN B,DUMP1 ;IF MRC EVER SEES THIS --SELFMODIFYING CODE-- .... + JRST DUMP9 ;FINISHED DUMPING SYMBOLS + +DUMPJ: SKIPN DUMP9K + JRST DMP9J1 + HRROI D,DDT-2 ;BUGGER THE SYMBOL TABLE + MOVE A,D + JSP P,WD + MOVE D,DUMP9K + ROT A,1 + JSP P,WD + ADD D,A + JSP P,WD +DMP9J1: SKIPN D,DUMP9J + MOVE D,SADR + JSP P,WD ;WRITE OUT JUMP BLOCK + SKIPN B,DUMP9S ;WRITE SYMBOLS + JRST DUMP9 ;NO SYMBOLS + HLLZ A,B + HLLZS DUMP4 ;DUMP SYMBOL BLOCK, RETURN TO DUMP9 + JRST DUMP3B + +DUMP9: JUMPE WRITE,LOADG1 ;IF VERIFY, THAT'S ALL + SKIPN D,DUMP9J + MOVE D,SADR + JSP P,WD ;SECOND JUMP BLOCK + HRRZ T,DMP4 ; GET POINTER TO NAME AREA + AOS BUFP + DPB BUFP,[UNWRDC+DIR+UNRNDM(T)] + JSP TT,NXTBLK + JSP TT,WRDB ;WRITE OUT LAST BLOCK + SKIPE T,BLKCNT + JSR NXTBW3 ;STORE LAST DESCRIPTOR BYTE + MOVEI T,0 + JSR NXTBW3 ;AND INDICATE END OF FILE + LDB T,[360600,,DIRPT] + IDIVI T,6 + HRRZ TT,DIRPT + IMULI TT,6 + SUBI TT,6*-5-1(T) + HRRZM TT,DIR+UDESCP ;INDICATE NEW END OF DESCRIPTOR AREA +KILDMP: MOVEI UNIT,TUT + MOVEI BLOK,TUTBLK + JSP TT,WRD ;WRITE OUT TUT ON THIS UNIT +REPEAT NTUTBL-1,[ + ADDI UNIT,2000 + ADDI BLOK,1 + JSP TT,WRD +] + HRRZ B,CU + HRRM B,KD2 ;WRITE OUT USER DIRECTORY ON ALL UNITS +KD1: ADDI B,1 + CAIN B,NDSK + MOVEI B,0 + HRRM B,CU + SKIPE QDED(B) + JRST KD2 + MOVEI UNIT,DIR +UDBLK: MOVEI BLOK,. + MOVE TT,DIR+UDNAME + CAME TT,SYSN + JSR EBUG,ERROR + JSP TT,WR +KD2: CAIN B,. + JRST LOADG1 + JRST KD1 + +GTP: SKIPGE TUT+QPKNUM + JSR EBUG,ERROR ;MUST BE OLD-STYLE TUT? + SUB C,TUT+QFRSTB + JUMPL C,[JSR EBUG,ERROR] + IDIVI C,TUTEPW + IMULI A,-10000*TUTBYT + HRLI C,440000+TUTBYT_6(A) + ADDI C,TUT+LTIBLK + JRST (TT) + +SC,[ ;LOGICAL TO PHYSICAL DISK MAPPING +QTRAN: 0 ;INDEX BY LOG DSK # + 1 ;4.9 => USE HIGH HALF OF DRIVE, RH = PHYS DRIVE # + 2 ;(NO LONGER DOES ANYTHING, NOW THAT MEMOWRECKS ARE GONE, + 3 ; BUT KEEP AROUND JUST IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +IFL .-QTRAN-NDSK,.ERR QTRAN LOSES!! +];SC + +ERRCT: 0 ;ERROR COUNTER +DDTM2: 0 ;DDT SYMBOL TABLE POINTER +DUMP9J: 0 ;START INSTRUCTION (AT DUMP9) +DUMP9S: 0 ;SYMBOL TABLE POINTER (AT DUMP9) +DUMP9K: 0 ;INITIAL SYMBOL TABLE PNTR (AT DUMP9) +LBLOCK: 0 ;LAST BLOCK WRITTEN OR READ +BLKCNT: 0 ;NUMBER OF BLOCKS READ OR WRITTEN CONSECUTIVELY +DIRPT: 0 ;DESCRIPTOR AREA BYTE POINTER +TUTPT: 0 ;TUT BYTE POINTER +FN1: 0 ;FILE NAME 1 +FN2: 0 ;FILE NAME 2 +PKNUM: REPEAT NDSK,-1 ;PACK NUMBER INDEXED BY DRIVE NUMBER +QDED: BLOCK NDSK ;-1 IF DRIVE NOT TO BE USED +XWDS: BLOCK 4 +RPKID: 0 +BOOTNS: RP, CONSZ DPC,BUSY + SC, CONSZ DC0,DSSACT + RH, CONSZ DSK,%HIBSY + PH, IORD B,SWPCS1 ; UGH! + + CONSTANTS + +IFL BEG+1677-., .ERR BLOAT +INFORM SPACE LEFT,\BEG+1677-. +BLOCK BEG+1677-. + +BADBLK: 0 ;BLOCK WITH HDWE ERROR +INFORM BADBLK,\.-1-BEG+ + +];END IFE BOOTSW +IFN BOOTSW,[ +BEG=MEMSIZ-2000 +LOC MEMSIZ-100 +] + +CBOOT: CLEARM MEMSIZ-1 ;BOOTSTRAP +RP,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DPC,BUSY OR JRST LOADG1 +IFN BOOTSW, CONSZ DPC,BUSY + JRST .-1 + MOVEI B,ICWA+2 ;SET UP CHANNEL PROG + MOVEM B,ICWA + SETZM ICWA+1 + SETZM ICWA+3 + DATAO DPC,CLATT1 + DATAO DPC,SUNIT0 + DATAI DPC,B +BOOT0: TRNN B,RP03BT + JRST BOOT1 + MOVEI B,MBLKS ;UNIT 0 IS AN RP03, ADJUST WORLD + HRRM B,CBLK + MOVE B,RP3ADJ + MOVSI A,-NSWBL + XORM B,SWPSK(A) + AOBJN A,.-1 +BOOT1: HLLZS BOOT0 ;PREVENT TRNN FROM SKIPPING AGAIN + MOVE B,ERRWD + MOVEM B,@ICWA + DATAO DPC,SWPSK + JSP P,SKWAIT + DATAO DPC,SWPIN1 + CONSO DPC,DONE + JRST .-1 + DATAO DPC,SWPIN2 + CONSO DPC,DONE + JRST .-1 + JRST BEG + +ERRWD: -1700,,BEG-1 +CLATT1: DEASEC ALLATT +SWPSK: DSEEKC+200._22. +SWPIN1: DWRITC+200._22.+3_17.+2._12.+ICWA ;NBLKS 4 +SWPIN2: DREADC+200._22.+4_17.+8._12.+ICWA +SWPOU1: DWRITC+200._22.+4_17.+8._12.+ICWA +SWPOU2: DREADC+200._22.+3_17.+2_12.+ICWA +IFN NSWBL-5, .ERR THE PRECEDING 4 CONSTANTS ARE WRONG! +CBLK: -NSWBL,,NBLKS ;DISK ADDR OF CORE BUFFER, - # BLOCKS IN LH +RP3ADJ: <&377>_22.+<.BM DCYLXB> +SUNIT0: DNOOPC + +SKWAIT: DATAI DPC,A ;AWAIT SEEK DONE UNIT 0 + TRNN A,ALLATT + JRST SKWAIT + DATAO DPC,CLATT1 + MOVEI A,30. + SOJG A,. + DATAI DPC,A + TLNN A,(ONCYL) + JRST SKWAIT + JRST (P) + +WAIT: CONSO DPC,DONE + JRST .-1 +];RP + +PH,[ ;; Initially we could not use IORDQ or IOWRQ because they were + ;; macros that used a literal. There is nothing to stop us now, + ;; except the fact that this code works fine and is as small as you + ;; could possibly want. + +BOOT: +IFE BOOTSW, JRST BEG ; or IORD B,SWPCS1 or JRST LOADG1 +IFN BOOTSW, IORD B,SWPCS1 + TRNN B,%HXRDY + JRST BOOT +KS, WREBR 0 ; No paging or caching + MOVEI A,0 + IOWR A,SWPCS2 ; Select drive +BOOT0: IORD A,SWPCS1 + TRNN A,%HXDVA + JRST BOOT0 ; Await drive available + MOVSI B,-LSWPADR +BOOT1: HLRZ A,SWPVAL(B) + IOWR A,SWPADR(B) +BOOT2: IORD A,SWPCS1 + TRNN A,%HXRDY ; Wait for controller + JRST BOOT2 + TRNE A,%HXTRE+%HXMCP ; Lossage? + JRST 4,. ; Foo! + AOBJN B,BOOT1 + JRST BEG + +ZZ1==*SECBLK ;BLOCK CONTAINING CORE SWAPPED OUT TO BRING DSKDMP IN +ZZ2==*SECBLK ;DSKDMP RESIDENCE BLOCK +ZZ3==ZZ1/NSECS +ZZ4==ZZ2/NSECS +ZZ1==ZZ3*400+ ;CONVERT ADDR TO DISK FORMAT +ZZ2==ZZ4*400+ + +SWPADR: UBAQ,,UBAPAG+UBPG_1 ; Set up Unibus map + UBAQ,,UBAPAG+UBPG_1+1 + UBAQ,,%HRCS2 ; Clear controller +SWPCS2: UBAQ,,%HRCS2 ; Select drive +SWPCS1: UBAQ,,%HRCS1 ; Initialize + UBAQ,,%HRCYL ; Desire cylinder + UBAQ,,%HRWC ; Set (half) word count + UBAQ,,%HRBA ; Set Unibus address + UBAQ,,%HRADR ; Desire track and sector + UBAQ,,%HRCS1 ; Write + UBAQ,,%HRWC ; Reset (half) word count + UBAQ,,%HRBA ; Reset Unibus address + UBAQ,,%HRADR ; Desire track and sector + UBAQ,,%HRCS1 ; Read +LSWPADR==:.-SWPADR + +IFN BEG&1777, .ERR BEG does not lie on a page boundary? + +;;; LH FOR SWAP IN, RH FOR SWAP OUT +SWPVAL: %UQVAL+%UQFST+BEG_-9,,%UQVAL+%UQFST+BEG_-9 ; Set up Unibus map + %UQVAL+%UQFST+BEG_-9+1,,%UQVAL+%UQFST+BEG_-9+1 + %HYCLR,,%HYCLR ; Clear controller + 0,,0 ; Select drive + %HMRDP,,%HMRDP ; Initialize + NCYLS,,NCYLS ; Desire cylinder + -1700*2,,-1700*2 ; Set (half) word count + UBPG_14,,UBPG_14 ; Set Unibus address + ZZ1,,ZZ2 ; Desire track and sector + %HMWRT,,%HMWRT ; Write + -1700*2,,-1700*2 ; Reset (half) word count + UBPG_14,,UBPG_14 ; Reset Unibus address + ZZ2,,ZZ1 ; Desire track and sector + %HMRED,,%HMRED ; Read +IFN .-SWPVAL-LSWPADR, .ERR SWPVAL wrong length. + +CBLK: -NSWBL,,NBLKS + +WAIT: IORD B,SWPCS1 + TRNN B,%HXRDY + JRST WAIT +];PH + +RH,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DSK,%HIBSY OR JRST LOADG1 +IFN BOOTSW, CONSZ DSK,%HIBSY + JRST .-1 +KL, CONSZ PAG,660000 ;PAGING AND CACHE MUST BE DISABLED +KL, JRST 4,. + MOVEI B,ICWA+2 ;SET UP CHANNEL PROG + MOVEM B,ICWA + SETZM ICWA+1 + SETZM ICWA+3 +BOOT0: DATAO DSK,[%HRDCL,,] + MOVEI A,20 + SOJG A,. + DATAI DSK,A + TRNN A,%HCDVA + JRST BOOT0 ;AWAIT DRIVE AVAILABLE + MOVE B,ERRWD + CONI DSK,A + TLNE A,(%HID22) + HRLI B,-1700_4 + MOVEM B,@ICWA + MOVSI B,-6 +BOOT1: DATAO DSK,SWPIN1(B) + MOVEI A,20 + SOJG A,. + CONSZ DSK,%HIBSY + JRST .-1 + AOBJN B,BOOT1 + CONSZ DSK,%HIERR + JRST 4,. + JRST BEG + +ZZ1==*SECBLK ;BLOCK CONTAINING CORE SWAPPED OUT TO BRING DSKDMP IN +ZZ2==*SECBLK ;DSKDMP RESIDENCE BLOCK +ZZ3==ZZ1/NSECS +ZZ4==ZZ2/NSECS +ZZ1==ZZ3*400+ ;CONVERT ADDR TO DISK FORMAT +ZZ2==ZZ4*400+ + +ERRWD: -1700,,BEG-1 +SWPIN1: %HRLOD+%HRDCL,,%HMRDP +SWPIN2: %HRLOD+%HRCYL,,NCYLS+1 ;AVOID CYLINDER 406 WHICH KLDCP USES +SWPIN3: %HRLOD+%HRADR,,ZZ1 +SWPIN4: %HRLOD+%HRCTL,,%HMWRT+ICWA_6 +SWPIN5: %HRLOD+%HRADR,,ZZ2 +SWPIN6: %HRLOD+%HRCTL,,%HMRED+ICWA_6 + +SWPOU1: %HRLOD+%HRDCL,,%HMRDP +SWPOU2: %HRLOD+%HRCYL,,NCYLS+1 ;AVOID CYLINDER 406 WHICH KLDCP USES +SWPOU3: %HRLOD+%HRADR,,ZZ2 +SWPOU4: %HRLOD+%HRCTL,,%HMWRT+ICWA_6 +SWPOU5: %HRLOD+%HRADR,,ZZ1 +SWPOU6: %HRLOD+%HRCTL,,%HMRED+ICWA_6 + +CBLK: -NSWBL,,NBLKS+NBLKSC ;AVOID CYLINDER 406 WHICH KLDCP USES + +WAIT: CONSO DSK,%HIDON + JRST .-1 +];RH + +SC,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DC0,DSSACT OR JRST LOADG1 +IFN BOOTSW, CONSZ DC0,DSSACT + JRST .-1 + DATAO DC0,SWPINJ + CONSZ DC0,DSSACT + JRST .-1 + JRST BEG + +SWPINJ: DJMP SWPIN + +DADR==NCYLS_13+</2>_6+<&1> ;ADDR OF LAST BLOCK IN CORE BUFFER +DADR1==NCYLS_13+_6+ ;ADDR OF NEXT BLOCK (CONTAINS +SWPIN: DWRITE+DUNENB+DADR ; WORKING COPY OF DSKDMP) + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DRC+DADR + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DREAD+DADR1 + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DRC+DADR1 + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DHLT + +SWPOUT: DWRITE+DUNENB+DADR1 + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DRC+DADR1 + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DREAD+DADR + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DRC+DADR + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DHLT + +CBLK: -NSWBL,,NBLKS ;DISK ADDR OF CORE BUFFER, - # BLOCKS IN LH +WAIT: CONSZ DC0,DSSACT + JRST .-1 +];SC +SADR: JRST BOOT ;AND GO TO PROGRAM TO BE STARTED +SYSN: SIXBIT /./ ;CURRENT DIRECTORY +IFG .+1-MEMSIZ,.ERR BOOT BLOAT + +IFE BOOTSW,{ ;CURLY BRACKETS TO AVOID ERROR MESSAGE + OFFSET 0 + LOC CORE + +;THESE ARE THE BLOCKS THAT GET WRITTEN ON DISK +; STARTING AT THE BEGINNING OF THE FIRST EXTRA CYLINDER + +CBUF: BLOCK 2000 ;PSEUDO-CORE BUFFER +DBUF: BLOCK 2000 ;DISK BUFFER +DIR: BLOCK 2000 ;DIRECTORY BUFFER +TUT: BLOCK 2000*NTUTBL ;TUT BUFFER +IFN .-BEG,.ERR BLOCKS LOST +; BLOCK 2000 ;CORE OVERLAYED BY DSKDMP +; BLOCK 2000 ;COPY OF DSKDMP +; BLOCK 2000 ;SPARE COPY OF DSKDMP + +END ZZZ +};END IFE BOOTSW +IFN BOOTSW, END CBOOT diff --git a/src/system/dz11.10 b/src/system/dz11.10 new file mode 100755 index 00000000..b44c5ad0 --- /dev/null +++ b/src/system/dz11.10 @@ -0,0 +1,56 @@ +;-*-MIDAS-*- +; DZ11 definitions + +DZLNLN==3 +DZNLN==1_DZLNLN ;Number of DZ terminal lines per board +DZLNM==DZNLN-1 ;Line number mask given DZ number of TTY + +%DZLM==3400 ;Line Number Mask +%DZLS==8. ;Line number shift + +%DZRCS==0 ;Control & Status register +; CSR Bits and fields +%DZCMN==10 ;Maintenance +%DZCCL==20 ;Clear +%DZCMS==40 ;Master Scan Enable +%DZCRE==100 ;Receiver Interrupt Enable +%DZCRD==200 ;Receiver Done +%DZCSE==10000 ;Silo Alarm Enable +%DZCSA==20000 ;Silo Alarm +%DZCTE==40000 ;Transmitter Interrupt Enable +%DZCTR==100000 ;Transmitter Ready + +%DZRLP==2 ;Line Parameter register +; LPR Bits and fields +%DZLLM==7 ;Line number mask +%DZLCL==10 ;Character Length position +%DZLSC==40 ;Stop code bit +%DZLPY==100 ;Parity bit +%DZLOP==200 ;Odd parity +%DZLSP==400 ;Speed code position +%DZLSS==8. ;Speed code shift +%DZLRO==10000 ;Receiver on + +%DZRDR==2 ;Read Data register +; RDR Bits and fields +%DZDCM==377 ;Character mask +%DZDPE==10000 ;Parity Error +%DZDFE==20000 ;Frame Error (break key) +%DZDOR==40000 ;Overrun +%DZDDV==100000 ;Data valid + +%DZRTC==4 ;Transmitter Control & Data Terminal registers + +%DZRTD==6 ;Transmitter Buffer & Break registers +; TDR and BR fields +%DZTCM==377 ;Character mask +%DZTBM==177400 ;Break mask + +%DZRMS==6 ;Modem status +; MSR fields +%DZMRI==377 ;Ring detect +%DZMCD==177400 ;Carrier detect + +; To do: +; - Add modem control. + diff --git a/src/system/ept.defs16 b/src/system/ept.defs16 new file mode 100755 index 00000000..f8024ba4 --- /dev/null +++ b/src/system/ept.defs16 @@ -0,0 +1,160 @@ +IFN 0,[ +.AUXIL +] + +IF1,[ +.TYO6 .IFNM1 +.TYO 40 +.TYO6 .IFNM2 +PRINTX / included in this assembly. +/ +];IF1 + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + + +IFNDEF EPT, EPT=1000 ;ABSOLUTE LOCATION OF EPT + ;LOCS 0-1777 UNCACHED + ;BUT THE HARDWARE CACHES EPT REFERENCES ANYWAY + +DEFSYM PI0LOC=EPT+40 ;PI0LOC+2*PICHN = ADDRESS OF INSTR PAIR FOR PICHN + +DEFSYM DTEBPO=EPT+140 ;DTE20 OUTPUT (BYTE TRANSFER) BYTE POINTER +DEFSYM DTEBPI=EPT+141 ;DTE20 INPUT (BYTE TRANSFER) BYTE POINTER +DEFSYM DTELOC=EPT+142 ;DTE20 INTERRUPT INSTRUCTION +DEFSYM DTEPRO=EPT+144 ;DTE20 OUTPUT (EXAMINE) PROTECTION WORD +DEFSYM DTERLO=EPT+145 ;DTE20 OUTPUT (EXAMINE) RELOCATION WORD +DEFSYM DTEPRI=EPT+146 ;DTE20 INPUT (DEPOSIT) PROTECTION WORD +DEFSYM DTERLI=EPT+147 ;DTE20 INPUT (DEPOSIT) RELOCATION WORD + +DEFSYM EPTCLK=EPT+510 ;DOUBLE WORD FOR CALENDAR CLOCK (TIME BASE) +DEFSYM EPTPRF=EPT+512 ;DOUBLE WORD FOR PERFORMANCE COUNTER +DEFSYM EPTEBC==EPT+504 ;DOUBLE WORD EBOX COUNT WHEN UPT=EPT +DEFSYM EPTMBC==EPT+506 ;DOUBLE WORD MBOX COUNT WHEN UPT=EPT +DEFSYM TIMLOC=EPT+514 ;INTERRUPT INSTRUCTION FOR INTERVAL TIMER + +DEFSYM EPTTR1=EPT+421 ;EXEC MODE ARITH OVFL TRAP +DEFSYM EPTTR2=EPT+422 ;EXEC MODE PDL OV TRAP +DEFSYM EPTTR3=EPT+423 ;EXEC MODE TRAP 3 (1 PROCEED) + +;UPT LOCATIONS - IN NON-TIME SHARING AND AT CLOCK LEVEL IN ITS UPT=EPT + +;424 MUUO STORED HERE +;425 MUUO PC STORED HERE +;426 MUUO DATAI PAG, HERE +;430 MUUO NEW PC KERNEL NO TRAP +;431 . . K T +;432 . . S N T +;433 . . S T +;434 . . C N T +;435 . . C T +;436 . . P N T +;437 . . P T +;500 PAGE FAIL WORD STORED HERE IN DEC PAGING MODE +;501 PAGE FAIL PC STORED HERE IN DEC PAGING MODE +;502 PAGE FAIL NEW PC FROM HERE IN DEC PAGING MODE +;504-5 EBOX COUNT +;506-7 MBOX COUNT + +DEFSYM EPTPFW=EPT+500 ;PAGE FAIL WORD STORED HERE IN ITS PAGING MODE +DEFSYM PFOPC=EPT+501 ;PAGE FAIL OLD PC STORED HERE IN ITS PAGING MODE +DEFSYM PFNPC=EPT+502 ;PAGE FAIL NEW PC OBTAINED FROM HERE IN ITS PAGING MODE + +;LOW CORE +;0-200 DF10S CHANNEL PROGRAMS, INTERRUPT LOCATIONS FOR IMP INTERFACE +;400-500 DTE20 COMMUNICATION AREA (COMMUNICATE WITH KLDCP AND IOELEV) +;500-1000 DL10 COMMUNICATION AREA AND BUFFERS (COMMUNICATE WITH IOELEV) + +DEFSYM QICWA=32 ;ITS DISK ICWA +DEFSYM QIOWD=160 ;ITS DISK IOWD AREA +DEFSYM RCIOWD=162 ;.. FOR READ COMPARE + +DEFSYM MICWA=30 ;ITS TAPE ICWA +DEFSYM MIOWD=170 ;ITS TAPE IOWD AREA + +;LUUO IN EXEC MODE LOCATIONS 40,41 + +DEFSYM SLVICW=60 ;SALVAGER ICWA +DEFSYM SLVIOW=62 ;SALVAGER IOWD AREA + +;EXEC DDT'S DISK ROUTINES USE LOCATIONS 20 AND 21, BUT THEY SAVE AND RESTORE THEM + +DEFSYM IMPILC=70 ;IMPTERFACE INPUT INTERRUPT INSTRUCTION PAIR +DEFSYM IMPOLC=72 ;IMPTERFACE OUTPUT INTERRUPT INSTRUCTION PAIR + +;DTE20 STUFF AS DEFINED BY KLDCP, ETC. +;THE DOCUMENTATION CLAIMS THIS STUFF IS IN THE EPT, BUT ACTUALLY +;IT'S IN FIXED LOCATIONS IN LOW CORE. + +DEFSYM EPTDIA=440 ;DIAGNOSTIC (SALV) START ADDRESS +DEFSYM EPTDDT=441 ;DDT START ADDRESS +DEFSYM EPTSTL=442 ;LOADER (DSKDMP) START ADDRESS +DEFSYM EPTITS=443 ;MONITOR (ITS) START ADDRESS + +DEFSYM DTEFLG=444 ;DTE20 OPERATION COMPLETE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTECLK=445 ;DTE20 CLOCK INTERRUPT FLAG (SET BY 11, CLEARED BY 10) +;DEFSYM DTECI=446 ;DTE20 CLOCK INTERRUPT INSTRUCTION (USED BY 10 SOFTWARE) +DEFSYM DTET11=447 ;DTE20 10->11 ARGUMENT (SET BY 10) (NOT USED?) +DEFSYM DTEF11=450 ;DTE20 11->10 ARGUMENT (SET BY 11) +DEFSYM DTECMD=451 ;DTE20 10->11 COMMAND WORD (SET BY 10) +DEFSYM DTESEQ=452 ;DTE20 OPERATION SEQUENCE NUMBER (AOS BY 10) +DEFSYM DTEOPR=453 ;DTE20 OPERATION IN PROGRESS FLAG (SET/CLEARED BY 10) +DEFSYM DTECHR=454 ;DTE20 LAST TYPED CHARACTER (SET BY 11, CLEARED BY 10) +DEFSYM DTEMTO=455 ;DTE20 MONITOR-MODE TYPEOUT DONE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTEMTI=456 ;DTE20 MONITOR-MODE TYPEIN DONE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTESWR=457 ;DTE20 SIMULATED SWITCH REGISTER (SET BY 11 ON START) + +DEFSYM DTE==200 ;DTE20 #0 DEVICE CODE +DEFSYM %DBL11==20000 ;CONO BIT TO "DOORBELL" 11 +DEFSYM %DBL10==1000 ;CONI BIT FOR DOORBEL FROM 11. CONO BIT TO CLEAR. +;1.1-1.3 DTE20 PIA + +;WORDS STORED IN DTECMD + +DEFSYM %DTTTI==2400 ;BUFFERED INPUT. CHAR RETURNED IN DTEF11 AFTER LINE TYPED. +;NUMBER 0-377 IS CHAR TO BE TYPED OUT (FLUSHES INPUT. BUFFER NOT PRINTED UNTIL LF/^G/^@) +DEFSYM %DTTTO==2000 ;THIS + CHAR ALSO = TTY OUTPUT +DEFSYM %DTTYI==3400 ;"DDT" INPUT, CHAR RETURNED IN DTEF11, ZERO IF NO CHAR TYPED +DEFSYM %DTTYO==4000 ;THIS + CHAR = ITS (MONITOR) TTY OUTPUT. + ;WHEN TYPEOUT DONE, INTERRUPT WITH DTEMTO SET. + ;TYPEIN CAUSES INTERRUPT WITH DTEMTI SET, CHAR IN DTEF11. +DEFSYM %DTMMN==4400 ;MONITOR MODE ON (DEFAULT WHEN START) +DEFSYM %DTMMF==5000 ;MONITOR MODE OFF (TYPEIN OF A ^X DOES THIS ALSO) +DEFSYM %DTMMS==5400 ;RETURN MONITOR MODE STATE IN DTEF11 +;DEFSYM %DTNRM==3000 ;NORMAL PRINT MODE +;DEFSYM %DTFRC==3001 ;FORCED PRINT MODE +DEFSYM %DTCLN==1001 ;CLOCK ON (60 CYCLE SIMULATED CLOCK) +DEFSYM %DTCLF==1000 ;CLOCK OFF +;DEFSYM %DTCLW==1002 ;"CLOCK WAIT" DTET11 HAS COUNT (? WHAT THE HECK IS THIS?) +;DEFSYM %DTCLR==1003 ;RETURN "CLOCK COUNT" IN DTEF11 (? WHAT THE HECK IS THIS?) +DEFSYM %DTHLT==400 ;HALT +;DEFSYM %DTFTL==401 ;DIAG FATAL ERROR (ACTUALLY JUST TURNS OFF CLOCK) +;DEFSYM %DTERR==402 ;DIAG ERROR HALT (ACTUALLY JUST TURNS OFF CLOCK) +;DEFSYM %DTEPG==403 ;END OF DIAGNOSTIC PROGRAM +;DEFSYM %DTEOP==404 ;END OF DIAGNOSTIC PASS +;DEFSYM %DTCLK==405 ;GET "CLOCK DEFAULT WORD" +;DEFSYM %DTFSL==406 ;DIAMON FILE SELECT (NAME.EXT MUST HAVE BEEN %DTTTO'ED) +;DEFSYM %DTFRD==407 ;DIAMON FILE READ (5 CHARS OR -1 (EOF) RETURNED IN DTEF11) +;DEFSYM %DTCMD==410 ;KLDCP COMMAND EXECUTED FROM OUTPUT BUFFER (%DTTTO IT) +;DEFSYM %DTRSW==1400 ;RETURN SIMULATED SWITCHES IN DTEF11. 10 SHOULD THEN STORE IN DTESWR + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/evsyms.21 b/src/system/evsyms.21 new file mode 100755 index 00000000..e6687ccb --- /dev/null +++ b/src/system/evsyms.21 @@ -0,0 +1,278 @@ +;This purports to be a table of all ITS symbols +;referenced by user programs, not counting sys$j in DDT. +;to sort in TECO, do J6FXA 12U0 <:S0; -DK> CS;$:LL :FWLFWLL J<50L .-Z; 12I 13I 10I> JGA +;The "5" is chosen to count these 4 comment lines, and the blank line. +;Commented-out symbols are those for obsolete devices, used from PEEK/FIDO but not essential. + +%QAACC ;used by PEEK +%QACTH ;used by PEEK +%QADEL ;used by PEEK +%QAEFR ;used by PEEK +%QAEFW ;used by PEEK +%QAFUL ;used by PEEK +%QAPAR ;used by PEEK +%QAWOV ;used by PEEK +%QMMDR ;used by PEEK +%QMMDW ;used by PEEK +%QMTTR ;used by PEEK +%QMTTW ;used by PEEK +%QMUDR ;used by PEEK +%QMUDW ;used by PEEK +AC0S ;used by PEEK +APRC ;used by PEEK +AUSOPG ;used by PEEK +BADBTS ;used by DDT +CALSXB ;used by PEEK +CLSTB ;used by PEEK +CUSER ;used by PEEK +DCHSTB ;used by FIDO (.EVAL and core mapping) +DCHSTB ;used by PEEK +DEDTIM ;used by PFTHMG DRAGON +DEVTAB ;used by PEEK +;DG2 ;used by PEEK +DIRCHN ;used by PEEK +;DISUSR ;used by FIDO (.EVAL and core mapping) +;DISUSR ;used by PEEK +DMNBC ;used by PFTHMG DRAGON +DMNBD ;used by NAMDRG +DMNBD ;used by PFTHMG DRAGON +DMNBEL ;used by NAMDRG +DMNBEL ;used by PFTHMG DRAGON +DMNBF ;used by NAMDRG +DMNBF ;used by PFTHMG DRAGON +DMNBFE ;used by PFTHMG DRAGON +DMNSZ ;used by NAMDRG +DPKBAS ;used by LOCK +;DRTM ;used by PEEK +EDEVS ;used by PEEK +;EUPOS ;used by PEEK +FLSINS ;used by PEEK +HUSRAD ;used by PEEK +IDF1 ;used by PEEK +IDF2 ;used by PEEK +IDLRCE ;used by PEEK +IFPIR ;used by PEEK +IMPBPQ ;used by PEEK +IMPSTL ;used by PEEK +IMPUP ;used by FIDO (.EVAL and core mapping) +IMPUP ;used by PEEK +IMPUP ;used by TELNET (and by other network programs I think - MRC) +IMPUS ;used by COMSAT (.EVAL) +IMPUS ;used by DDT +IMPUS ;used by NAMDRG +IMPUS ;used by NAME +IMPUS ;used by QMAIL (.EVAL) +IMSOC1 ;used by PEEK +IMSOC2 ;used by PEEK +IMSOC3 ;used by PEEK +IMSOC4 ;used by PEEK +IMSOC4 ;used by NAME and NAMDRG +IMSOC5 ;used by PEEK +IMSOC6 ;used by PEEK +IMSOC7 ;used by PEEK +IMSOC8 ;used by PEEK +IOCHNM ;used by FIDO (.EVAL and core mapping) +IOCHNM ;used by PEEK +IOCHNM ;used by NAME and NAMDRG +IOCHST ;used by FIDO (.EVAL and core mapping) +IOCHST ;used by PEEK +IOTLSR ;used by PEEK +IOTTB ;used by PEEK +JBDEV ;used by PEEK +JNAME ;used by FIDO (.EVAL and core mapping) +JNAME ;used by NAMDRG +JNAME ;used by NAME +JNAME ;used by PEEK +JNAME ;used by PFTHMG DRAGON +JTMU ;used by PEEK +LIOBLK ;used by PFTHMG DRAGON +LOSRCE ;used by PEEK +LOUTIM ;used by PEEK +LPTUSR ;used by FIDO (.EVAL and core mapping) +LPTUSR ;used by PEEK +LSCALL ;used by PEEK +LUBLK ;used by COMSAT +LUBLK ;used by FIDO (.EVAL) +LUBLK ;used by NAMDRG +LUBLK ;used by NAME +LUBLK ;used by PEEK +LUBLK ;used by PFTHMG DRAGON +LUBLK ;used by CLU +LUIOP ;used by PEEK +MAXJ ;used by COMSAT +MEMBLT ;used by PEEK +MEMFR ;used by PEEK +MEMPNT ;used by PEEK +MMMPG ;used by PEEK +MMPNP ;used by PEEK +MMSWP ;used by PEEK +;MPXBUF ;used by PEEK +MSKST ;used by PEEK +MSKST2 ;used by PEEK +MTUSR ;used by PEEK +MUR ;used by PEEK +MURUSR ;used by PEEK +N11TYS ;used by FIDO (.EVAL) +N11TYS ;used by NAMDRG +N11TYS ;used by NAME +NCBCOM ;used by PEEK +NCT ;used by FIDO (.EVAL) +NCT ;used by LOCK +NCT ;used by NAMDRG +NCT ;used by NAME +NCT ;used by PEEK +NDPTYS ;used by LOCK +NETDBO ;used by NAME and NAMDRG +NETDUI ;used by NAME and NAMDRG +NETP ;used by COMSAT (.EVAL) +NETP ;used by QMAIL (.EVAL) +NF11TY ;used by FIDO (.EVAL) +NF11TY ;used by NAMDRG +NF11TY ;used by NAME +NFDPTY ;used by LOCK +NFSTTY ;used by NAMDRG +NFSTTY ;used by NAME +NFSTTY ;used by PEEK +NIOCHN ;used by NAME and NAMDRG +NMPGS ;used by PEEK +NNTYS ;used by LOCK +NPGSWO ;used by PEEK +NQCHN ;used by PEEK +NQMFWR ;used by COMSAT (.EVAL and core mapping) +NQS ;used by PEEK +NSTTYS ;used by NAMDRG +NSTTYS ;used by NAME +NSTTYS ;used by PEEK +NSWPGS ;used by PEEK +NULTIM ;used by PEEK +NUNITS ;used by PEEK +NUTIC ;used by PEEK +NUTOC ;used by PEEK +;NVDUSR ;used by PEEK +NXGPFW ;used by XGPSPL +OIPBIT ;used by DDT +OPRSXB ;used by PEEK +PARERR ;used by PEEK +;PDPUSR ;used by FIDO (.EVAL and core mapping) +;PDPUSR ;used by PEEK +PICLR ;used by PEEK +PIRQC ;used by PEEK +PLTUSR ;used by PEEK +PRVUSR ;used by PEEK +PSWOUS ;used by PEEK +PTPUSR ;used by PEEK +PTRUSR ;used by PEEK +QFBLNO ;used by PEEK +QIRRCV ;used by PEEK +QSCRW ;used by PEEK +QSMDN ;used by PEEK +QSMPRP ;used by PEEK +QSNLCN ;used by PEEK +QSNUD ;used by PEEK +QSRAC ;used by PEEK +QUDFPR ;used by PEEK +QUDPR ;used by PEEK +QUSR ;used by PEEK +RNABLU ;used by PEEK +RPCL ;used by PEEK +SCHHB ;used by PEEK +SCLNET ;used by LOCK +SHUTDN ;used by NAMDRG +SHUTDN ;used by NAME +SILNG ;used by PEEK +SLOADU ;used by DDT +SLOADU ;used by PEEK +SOLNG ;used by PEEK +SSCHDB ;used by PEEK +STYSTS ;used by NAMDRG +STYSTS ;used by NAME +STYSTS ;used by PEEK +SUEXIT ;used by PEEK +SUPCOR ;used by LOCK +SUPPRO ;used by COMSAT +SUPPRO ;used by FIDO (.EVAL and core mapping) +SUPPRO ;used by NAMDRG +SUPPRO ;used by NAME +SUPPRO ;used by PEEK +SUPPRO ;used by PFTHMG DRAGON +SUUOH ;used by PEEK +SV40 ;used by PEEK +SWPOPR ;used by PEEK +SWRCE ;used by PEEK +SYSUSB ;used by DDT +SYSUSE ;used by DDT +SYSYMB ;used by DDT +SYSYME ;used by DDT +;TABUSR ;used by PEEK +TCTYP ;used by FIDO (.EVAL and core mapping) +TIME ;used by NAMDRG +TIME ;used by NAME +TIME ;used by PEEK +TIME ;used by PFTHMG DRAGON +TRNLS1 ;used by PEEK +TRNLST ;used by PEEK +TRUMM ;used by PEEK +TRUNTM ;used by PEEK +TRUNTM ;used by PFTHMG DRAGON +TSIPRQ ;used by PFTHMG DRAGON +TSYSM ;used by PEEK +TT11P ;used by NAMDRG +TT11P ;used by NAME +TTITM ;used by NAMDRG +TTITM ;used by NAME +TTYCHN ;used by LOCK +TTYSTS ;used by FIDO (.EVAL and core mapping) +TTYSTS ;used by NAMDRG +TTYSTS ;used by NAME +TTYTBL ;used by FIDO (.EVAL and core mapping) +TTYTBL ;used by NAMDRG +TTYTBL ;used by NAME +TTYTBL ;used by PEEK +TTYTYP ;used by FIDO (.EVAL and core mapping) +TTYTYP ;used by LOCK +TTYTYP ;used by NAMDRG +TTYTYP ;used by NAME +;UDIR ;used by PEEK +;UDIRO ;used by PEEK +;UGOAL ;used by PEEK +;ULCTM ;used by PEEK +UMASTER ;used by FIDO (.EVAL and core mapping) +UMASTER ;used by PEEK +UMNTR ;used by PEEK +UNAME ;used by COMSAT +UNAME ;used by FIDO (.EVAL and core mapping) +UNAME ;used by NAMDRG +UNAME ;used by NAME +UNAME ;used by PEEK +UNAME ;used by PFTHMG DRAGON +UPC ;used by PEEK +UPGCP ;used by PEEK +UPGSEC ;used by PEEK +UREALT ;used by PEEK +USRSTG ;used by COMSAT +USIPRQ ;used by PEEK +USIPRQ ;used by PFTHMG DRAGON +USIPRQ ;used by CLU +USRHI ;used by COMSAT +USRHI ;used by FIDO (.EVAL and core mapping) +USRHI ;used by PEEK +USRHI ;used by PFTHMG DRAGON +USRRCE ;used by PEEK +USTP ;used by PEEK +USWPRI ;used by PEEK +USWSCD ;used by PEEK +USWST ;used by PEEK +USYSN1 ;used by PEEK +USYSNM ;used by PEEK +;UTASS ;used by PEEK +;UTBFS ;used by PEEK +UTMPTR ;used by NAMDRG +UTMPTR ;used by NAME +UTMPTR ;used by PEEK +UTRNTM ;used by PEEK +UTRNTM ;used by PFTHMG DRAGON +;UTTNO ;used by PEEK +;UTUSR ;used by PEEK +UUAC ;used by PEEK +XJNAME ;used by COMSAT +XUNAME ;used by COMSAT diff --git a/src/system/fsdefs.43 b/src/system/fsdefs.43 new file mode 100755 index 00000000..3c9853be --- /dev/null +++ b/src/system/fsdefs.43 @@ -0,0 +1,216 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +;FILE SYSTEM PARAMETERS - APPLIES TO ALL ITS MACHINES + +;9/5/79 - tut format changed! +;8/19/90 - DM "funny" bit flushed + +;MFD INFO + +IFDEF NBLKS,[ ;MFDBLK KNOWN ONLY IF .INSRT APPROPRIATE PHYSICAL PARAMS FILE +DEFSYM MFDBLK==NBLKS/2-1 ;LOC ON DISK +DEFSYM MFDCYL==MFDBLK/NBLKSC +DEFSYM MFDSRF==*SECBLK/NSECS +DEFSYM MFDSEC==*SECBLK-MFDSRF*NSECS +] + ;RANDOM INFO IN MFD +DEFSYM MDNUM==0 ;ASCENDING DIR NUM +DEFSYM MDNAMP==1 ;PNTR TO ORG OF USER NAME BLOCK AREA +DEFSYM MDYEAR==2 ;CURRENT YEAR +DEFSYM MPDOFF==3 ;DE-CORIOLIS CLOCK OFFSET +DEFSYM MPDWDK==4 ;PREFERRED WRITING DISK (PHYSICAL DRIVE #) +DEFSYM MDCHK==5 ;THIS WORD MUST BE M.F.D. (FOR CHECKING) +DEFSYM MDNUDS==6 ;NUMBER USER DIRECTORIES (FOR CHECKING ONLY) +DEFSYM LMIBLK==7 ;TOTAL STG USED BY HACKS LIKE THIS + ;USER NAME BLKS FROM C(MDNAMP) TO END +DEFSYM LMNBLK==2 ;# WDS/BLK +DEFSYM MNUNAM==0 ;6BIT USER NAME + ;SECOND WORD OF A USER-NAME BLOCK IS ZERO. + ;DECUUO CONTAINS A KLUDGE WHICH DEPENDS ON THIS, + ;PLEASE NOTIFY BUG-DECUUO BEFORE CHANGING IT. + +;TUT INFO + +IFDEF NBLKS,[ +DEFSYM TUTBLK==MFDBLK-NTUTBL ;LOC ON DISK +DEFSYM TUTCYL==TUTBLK/NBLKSC +DEFSYM TUTSRF==*SECBLK/NSECS +DEFSYM TUTSEC==*SECBLK-TUTSRF*NSECS +] +DEFSYM TUTBYT==3 ;SIZE OF BYTES (USED TO BE 4) +DEFSYM TUTBP==<440000+TUTBYT_6>,, +DEFSYM TUTEPW==36./TUTBYT ;NUMBER OF ENTRIES PER WORD +DEFSYM TUTMAX==1_TUTBYT +DEFSYM TUTLK==TUTMAX-1 ;HIGHEST CODE MEANS LOCKED OUT +DEFSYM TUTMNY==TUTLK-1 ;TUT MANY OR MORE REFS + +;RANDOM INFO IN TUT (AT THE FRONT) +DEFSYM QPKNUM==0 ;PACK # +DEFSYM QPAKID==1 ;PACK ID +DEFSYM QTUTP==2 ;FREE SPACE POINTER TO TRACK AREA. ADVANCE BY CYLINDERS +DEFSYM QSWAPA==3 ;SWAPPING AREA. FIRST TRACK OF NON-SWAPPING AREA + ;NEW FILES WILL NOT BE WRITTEN LOWER THAN THIS. +DEFSYM QFRSTB==4 ;FIRST BLOCK TUT'ED +DEFSYM QLASTB==5 ;LAST BLOCK TUT'ED +DEFSYM QTRSRV==6 ;-1 IF ONLY ALLOCATED DIRS CAN HAVE FILES ON THIS PACK + ;IF NOT 0 AND NOT -1, SIXBIT NAME OF "SECONDARY" PACK + ;STG FOR RANDOM INFO ^ +DEFSYM LTIBLK==20 ;BYTES MAPPING THE DISK START HERE + +;UFD INFO +;IF A IS RELATIVE LOCATION OF MFD ENTRY, USER DIR IS LOCATED IN +;TRACK NUMBERED /2 (SEE QFL2) + +DEFSYM UFDBYT==6 ;SIZE OF BYTES (Do not change!) +DEFSYM UFDBPW==36./UFDBYT ;NUMBER OF BYTES PER WORD + + ;RANDOM INFO IN UFD +DEFSYM UDESCP==0 ;FS PNTR TO DESC AREA +DEFSYM UDNAMP==1 ;PNTR TO ORG OF NAME AREA +DEFSYM UDNAME==2 ;USER NAME (FOR CHECKING) +DEFSYM UDBLKS==3 ;LEFT HALF HAS AMOUNT OF SPACE ALLOCATED (NOT USED + ; CURRENTLY BY SYSTEM), RIGHT HALF HAS NUMBER OF BLOCKS USED. +DEFSYM UDALLO==4 ;IF NONZERO, LEFT HALF HAS DISK NUMBER, RIGHT + ; HALF HAS AMOUNT OF SPACE ALLOCATED +DEFSYM UDDESC==11. ;FIRST LOC AVAIL FOR DESC + +; 8/19/90 Due to the larger size of RP07s it was necessary to officially +; flush the DM "funny" bit. This change only changes the comments in this +; file, but any program that interprets UFD descriptors needs to be fixed +; to not mask that bit out (as most of them currently do). Fortunately all +; the known ITS filesystems have zeros in all their "funny" bits, so the +; change is upward compatible. + +; UFD descriptor format described: +; +; Each 6-bit byte is taken in turn and used to compute a sequence of block +; numbers. If N is the current descriptor byte, and B is the current block +; number (initially undefined), then N is interpreted as follows: +; +; 0 Marks the end of the file description. +; +; 1 to UDTKMX (1 to 14) "Take" N blocks. +; Blocks B through B + N - 1 are the next N blocks of the file. +; Set B := B + N . +; +; UDTKMX+1 to UDWPH-1 (15 to 36) "Skip" B - UDTKMX blocks. +; Set N := N + B - UDTKMX . +; (ITS has been broken for years such that it never uses this +; UFD descriptor code!) +; +; UDWPH (37) Write Place Holder +; A noop. Used to reserve space in directories for files that are +; being written. Just skip over it and read the next byte. +; +; 40 - 77 Load address and take 1. +; Read the next NXLBYT descriptor bytes (NXLBYT=2), N2 and N3. +; Set B := LSH(AND(N, 37), 12.) + LSH(N2, 6) + N3 . +; Block B is the next block in the file. +; Set B := B + 1 . +; +; A zero length file is described as two bytes: UDWPH then 0. UDWPH does +; not otherwise normally appear in UFD descriptions for closed files. +; Note that a legal description must use codes 40 - 77 before it can use +; any code other than UDWPH. + +; Links are described as a sequence of SIXBIT characters terminated with a +; 0 byte. The directory, first and second name are stored in order. +; The first two components are terminated with a ";" if they are less than +; 6 characters long. ";" (73), ":" (72) and " " (0) are quoted by +; preceding them with a ":". Some examples: +; +; Link target names: Bytes stored in directory: +; +; 123456 123456 123456 "123456123456123456 " +; ALAN FOO BAR "ALAN;FOO;BAR " +; .MAIL. NAMES > ".MAIL.NAMES;> " +; .MAIL. LISTS MSGS ".MAIL.: LISTS: : MSGS " +; MOON LUNAR :EJ "MOON;LUNAR;::EJ " +; +; There are a lot of illegal or wasteful possibilities for link descriptors +; ("A;B ", "A;B;C;D ", ":A;:B;:C ", etc.), which is suprising since +; somebody was clearly trying to compress them into as few bytes as +; possible. + +; Here is the pre 8/19/90 comment describing UFD descriptors: +; +; ;UFD DESCRIPTORS +; ;0 => FREE 1-UDTKMX => TAKE NEXT N +; ;UDTKMX+1 THRU UDWPH-1 => SKIP N-UDTKMX AND TAKE ONE +; ;UDWPH => WRITE-PLACE-HOLDER +; ;40 BIT SET => LOAD ADDRESS. LOWER 5 BITS PLUS NEXT NXLBYT (2) +; ; CHARS (17 BITS IN ALL) +; ;40 BIT & 20 BIT => "FUNNY" BLOCK IF DMDSK. WHAT IS THIS, ANYWAY? +; ;END BY 0 +; +; ;IF LINK DESCR +; ;6 CHAR OR UNTIL ; = SYS NAME. MUST HAVE NO CHAR = 0 IN THIS OR +; ; NEXT 2 NAMES +; ;NEXT CHAR QUOTED BY : (FOR NAMES WITH : OR ;) +; ;NEXT CHAR N1 +; ;NEXT CHAR N2 +; ;END BY 0 + +DEFSYM UDTKMX==12. ;HIGHEST "TAKE N" CODE +DEFSYM UDWPH==31. ;PLACE HOLDER ON WRITE (OR NULL FILE) +DEFSYM UDSKMX==UDWPH-UDTKMX-1 ;# BLOCKS THAT CAN BE SKIPPED +DEFSYM NXLBYT==2 ;# ADDITIONAL BYTES FOR LOAD ADDR + ;IN SYSTEM THIS IS DEFINED AT FRONT OF FILE + + ;NAME AREA DATA + +DEFSYM LUNBLK==5 ;WDS/NAME BLK +DEFSYM UNFN1==0 ;FIRST FN +DEFSYM UNFN2==1 ;SECOND FN +DEFSYM UNRNDM==2 ;ALL KINDS OF RANDOM INFO +DEFSYM UNDSCP==1500,, ;PNTR TO DESC +DEFSYM UNPKN==150500,, ;PACK # +DEFSYM UNLINK==1 ;LINK BIT +DEFSYM UNLNKB==220100,, +DEFSYM UNREAP==2 ;IF 1, DONT REAP FILE +DEFSYM UNWRIT==4 ;OPEN FOR WRITING +DEFSYM UNMARK==10 ;GC MARK BIT +DEFSYM UNCDEL==20 ;DEL WHEN CLOSED +DEFSYM DELBTS==20 ;DELETED -- IGNORE +DEFSYM UNIGFL==24 ;BITS TO IGNORE FILE +DEFSYM UNWRDC==301200,, ;WORD COUNT OF LAST BLOCK MOD 2000 +DEFSYM UNDUMP==400000 ;HAS BEEN DUMPED +DEFSYM UNDATE==3 ;DATE ETC. +DEFSYM UNTIM==2200,, ;COMPACTED TIME OF CREATION +DEFSYM UNYMD==222000,, ;Y,M,D OF CREATION +DEFSYM UNMON==270400,, ;MONTH +DEFSYM UNDAY==220500,, ;DAY +DEFSYM UNYRB==330700,, ;YEAR +DEFSYM UNREF==4 ;REFERENCE DATE SAME AS LEFT HALF OF UNDATE +DEFSYM UNREFD==222000,, ;REFERENCE DATE BYTE POINTER +DEFSYM UNAUTH==111100,, ;MFD INDEX OF AUTHOR, ALL 1=> NO DIRECTORY +DEFSYM UNBYTE==001100,, ;FILE BYTE SIZE AND LENGTH INFO. + ;LET S=BITS PER BYTE, C=COUNT OF UNUSED BYTES IN LAST WD + ;400+100xS+C S=1 TO 3 C=0 TO 35. + ;200+20xS+C S=4 TO 7 C=0 TO 8 + ;44+4xS+C S=8 TO 18. C=0 TO 3 + ;44-S S=19. TO 36. C=0 + ;NOTE THAT OLD FILES HAVE UNBYTE=0 => S=36. + +IF1 IFDEF NUDSL, IFG NUDSL*LMNBLK+LMIBLK-2000,.ERR MFD LOSES + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/imp.365 b/src/system/imp.365 new file mode 100755 index 00000000..30b687e1 --- /dev/null +++ b/src/system/imp.365 @@ -0,0 +1,931 @@ +;;; -*- Mode:MIDAS -*- + +IMPVRS==.IFNM2 ; Version of IMP code + +IFN NCPP,.FATAL IMP Code doesn't support NCP any more! +IFE KSIMP,.FATAL Wrong IMP driver file included! + +OVHMTR IMP ;Charge all this stuff to the IMP + +$INSRT LHDH + +; IMP 1822 PROTOCOL INFORMATION (EXTENDED-LEADER VERSION) + +; The IMP leader is 96 bits long, usually organized as 3 words of 32 bits. +; For further details, these documents are available from the Network +; Information Center: +; IMP-HOST protocol: BBN Report No. 1822 +; NCP protocol: NIC 8246, Host-to-Host Protocol for the ARPANET +; IP, TCP: Internet Protocol Transition Workbook, and +; Internet Protocol Implementor's Guide +; +; Here is the leader format used by the IMP code. This format uses +; no IMP padding, assumes IP only, and expects all IMP<->HOST data +; transfers in 32-bit mode. +; +; Previous versions of this code which supported NCP used a much more +; complicated leader formatting scheme based on 36 bit transfers and +; IMP padding. That scheme is dead, see SYSTEM;IMPOLD WTHNCP for details. +; +; All data from the IMP interface ends up in the -10 as left-justified +; 32-bit words. Objects of less than 32 bits length, such as IP octets, +; are stored in PDP10 ILDB byte order. +; +;------------------------------------------------------------------------ +;1: 4.9-4.6 not used (0) +; 4.5-4.2 all 1's for new format, else old msg type (4=old nop) +; 4.1-3.3 network number (0) +; 3.2-2.8 not used (0) +; 2.7 trace (ignored) +; 2.6-2.4 leader flags (2.6 is to be ignored, 2.5-2.4 are not used!) +; 2.3-1.5 message type +; +;2: 4.9-4.2 Handling type (7 for big buffers, 4 for small buffers, +; 0 for the control link) +; 4.1-3.3 Host number on IMP +; 3.2-1.5 IMP number +; +;3: 4.9-4.2 Link Number (High 8 bits of Message ID) +; 4.1-3.7 Low 4 bits of Message ID (0) +; 3.6-3.3 Sub-type +; 3.2-1.5 Message length +;------------------------------------------------------------------------ +;4: 4.9-1.5 First word of IP datagram +; .... +;------------------------------------------------------------------------ +; +;In message types 2 and 6, the going-down status 16-bit word is +;in word 3 bits 4.9-3.3. + +;3.6-3.3 of word 3 are the padding count for type 4 (nop) from host. +;This is currently 0 (none). Padding is only put on type-0 messages. + +IMPLDS==3 ;IMP local leader size + + ;Byte pointers to fields of input leader +IMOTBP: 340400,,IMPILB+0 ;Message format type +IMTBP: 041000,,IMPILB+0 ;Message type field +IMSABP: 043000,,IMPILB+1 ;Source address field (host+IMP) +IMSHBP: 241000,,IMPILB+1 ;Source host field +IMSIBP: 042000,,IMPILB+1 ;Source IMP field +IMLNBP: 341000,,IMPILB+2 ;Link number field +IMSTBP: 240400,,IMPILB+2 ;Subtype field +IMMLBP: 042000,,IMPILB+2 ;Message length field + + + +SUBTTL ARPANET VARIABLES AND TABLES + +EBLK + +%IMXLN==:<<8159.-96.>+31.>/32. ; Max # of 32-bit words in IMP regular msg, + ; exclusive of leader and leader padding. = 252. + +%IMMTU==:251.*4 ; Used by IP/TCP. Driver currently rounds to PDP10 words, + ; forcing this to be 1004 instead of 1007. + +; ACTIVE HOST TABLE. Entries herein are allocated as needed, using garbage +; collection. Most "host number" fields are really indices into this table. +; +LIMPHT== ; TCP conns plus a few extra + +IMPHTF: -1 ;Host table free list, threaded through IMPHTB, end with -1 + +IMPHTS: ;Start of table area +IMPHTN: BLOCK LIMPHT ; Host number. 1.1-1.8 HOST, 2.1-3.7 IMP +IMPHTB: BLOCK LIMPHT ;Bits: + ;4.9 UNUSED + ;4.8 GC MARK BIT + ;4.7-4.3 UNUSED + ;4.2-4.1 STATUS OF HOST 0 DOWN, 1 RST SENT, 2 UP + ;3.9-3.1 UNUSED + .SEE IMPHDS ;RH Last message from IMP about "host dead status" +IMPHTC: BLOCK LIMPHT ; # active messages outstanding for host (8 max) +IMPHTT: BLOCK LIMPHT ; Time of last RFNM received +IMPHTE==.-1 ;Last location in table + +;Status variables +; +IMPUP: -1 ;0 => IMP up ;-1 => down ;-2 => coming up, PI still off + ;1 => down for good, until next time IMP ready line changes +IMPTCU: 0 ;0 IMP up/down status not changing + ;>0 Trying to reinitialize, SYSJOB hasn't done so yet + ;-1 Has been reinitialized, haven't exchanged NOPs yet +IMPUCT: 0 ;IMP coming up timeout, if 4 NOPs don't go through promptly. +IMPDWN: BLOCK 3 ;Last message from IMP that it is going down + ;WD0: "Reason" claimed by IMP (see ch 3 of BBN report 1822) + ;WD1: Time when expected down + ;WD2: Time when expected up (SYS time=1/30 sec since up) + +IMERCN: -1 ;CONI into here when net goes down + +BBLK + +EBLK + +;Input side variables +; +IMPILB: BLOCK IMPLDS ;Input leader buffer +IMPCSH: -1 ;Current source host (IMPHTB index). -1 when idle. +IMPCLN: 0 ;Current link number +IMIFLS: 0 ;Flushing output at interrupt handler +IMPIEC: 0 ;Count of input errors while down. +IMPIBC: 0 ;Count of words available in DMA input buffer +IMPIBP: 0 ;Pointer into DMA input buffer + +;Output side variables +; + ;Output leader buffer +IMOLDR: <17_10.>,,0 ;Regular new-format message +IMOLAD: 0 ;Filled in with destination IMP address + <233_10.>,,0 ;IP link field + +IMNOPC: 0 ;< 0 => Send NOPs +IMPOAC: -1 ;>= 0 => Output active, don't restart +IMPBZY: 0 ;-1 == Waiting for output interrupt +IMPODP: 0 ;Pointer to IP datagram being output at PI level +IMPOS: 0 ;Output state + %ISODL==:0 ; Not expecting output done (i.e. between messages) + %ISONP==:1 ; Sending NOP + %ISOID==:2 ; Sending IP Datagram + +;Meters + +;IP meters +IMNIPI: 0 ; # of IP datagrams input (rcvd) +IMNIPF: 0 ; # of IP datagrams flushed (input threw away) +IMNIPO: 0 ; # of IP datagrams output (sent) +IMNIPR: 0 ; # of IP RFNMs received +IMNIP7: 0 ; # of IP Type 7 (Dest Host Dead) messages received +IMNIP8: 0 ; # of IP Type 8 (Error) msgs rcvd +IMNIP9: 0 ; # of IP Type 9 (Incomplete Transmission) msgs rcvd +IMNWIG: 0 ; # words ignored by "Ignore" state (%ISIGN) +IMNWIF: 0 ; # words flushed by IMPRM5 + +;IMP meters +IMNSRF: 0 ;Number of spurious RFNMs on non-IP links +IMNBLK: 0 ;Number of times blockage avoided (output held up by ITS) + +IMPMSR: BLOCK 20;Count of IMP messages rcvd +IMPM1S: BLOCK 4 ; # Type 1 (Error in Leader) subtype msgs +IMPM9S: BLOCK 2 ; # Type 9 (Incomplete Transmission) subtype msgs +IMPMSS: BLOCK 1 ;Count of IMP msg sent (we only send regular msgs) +IMCT1: 0 ;# Unvectored interrupts +IMCT2: 0 ;# Valid input interrupts +IMCT3: 0 ;# Valid output interrupts +BBLK + +SUBTTL ARPANET MAIN-PROGRAM LEVEL +;IMPIBF, IMPOBF defined as low-memory buffer page in ITS +IF2,IFN IMPIBF&777,.FATAL IMPIBF not on DEC page boundary + +;(Re)Start IMP. Called from SYSJOB to start IMP, or on error or +; user requested cycle through LOCK +; +IMPINI: SETOM IMPUP ;Not up yet, + SETOM IMPTCU ; but thinking about it. + MOVEI A,IMPIBF_-9. ;DEC page # of IMP buffer page + TRO A,%UQ16B\%UQVAL ;Valid mapping, 16 bit device + IOWRI A,UBAPAG+IUIMPG_1 ;Set up 1 DEC page of UBA mapping. Note that + ; the second half of IUIMPG isn't mapped at all + CONO PI,NETOFF ;Freeze things while IMP bashing occurs + MOVEI A,%LHRST + IOWRI A,%LHOCS ;Reset output side + IOWRI A,%LHICS ;Reset Input side + + ;IMP now shut down. Reset variables + SKIPE A,IMPODP ;Have an output datagram ? + PUSHJ P,IPIODN ;Yep, release it. + SETZM IMPODP ;No output datagram + SETZM IMPOS ;Output idle + SETOM IMPOAC ;Output interrupt level inactive + SETZM IMPBZY ;No pending output interrupt + + SETZM IMPIBC ;No input available + SETZM IMPIEC ;No input errors yet + SETZM IMIFLS ;Not flushing input at interrupt level + SETOM IMPCSH ;No current host table index + SETOM IMPDWN+1 ;Time for IMP to go down, not known + CONO PI,NETON ;Allow interrupts again + + ;Wait one sec for IMP to notice rdy line drop + MOVE T,TIME + ADDI T,30. + CAMLE T,TIME + PUSHJ P,UFLS + + MOVNI A,30. ;Allow 15 seconds to come up + MOVEM A,IMPUCT + MOVE T,TIME ;Note when we last started IMP + MOVEM T,LNETIM + PUSHJ P,IMPHRS ;Set host ready + PUSHJ P,IMPIST ;Start input + + MOVE T,TIME + ADDI T,15. ;Wait 1/2 sec before we try to output + CAMLE T,TIME + PUSHJ P,UFLS + MOVNI A,4 + MOVEM A,IMNOPC ;Send 4 NOPs to start + ;Falls through to start output + +;Start IMP output +; +IMPOST: +IMPIOS: CONO PI,PIOFF ;Freeze. + AOSE IMPOAC ;Do nothing if output already active. + JRST PIONJ + SETOM IMPBZY ;Note we want an IMP interrupt + CONO PI,NETRQ ;Force nonvectored IMP interrupt + JRST PIONJ + +;Check if IMP ready line is set +; Called from SYSJOB. +; Return +1 if IMP not ready, +2 if so +; +IMPCKR: IORDI A,%LHICS ;Get input CSR + TRNN A,%LHINR ;Skip if IMP not ready + AOS (P) ;Return +2 if ready + POPJ P, ;That's all + +;Set HOST READY. From SYS job only, please, loops waiting. +; +IMPHRS: IORDI T,%LHICS + TRNN T,%LHRDY ;Can we mung? + BUG + IORI T,%LHHRC\%LHSE ;Turn on HR. SE prevents dropping messages + IOWRI T,%LHICS + MOVEI A,777777 ;I don't know why this takes so long. +IMPHR1: IORDI T,%LHICS ;Get the bits back + TRNE T,%LHHR ;LHDH thinks host ready is ready + RET ;HR line set + SOJG A,IMPHR1 ;Timed out yet? + BUG CHECK,[IMP: Timed out setting Host Ready] + RET + +SUBTTL HOST-TABLE MANAGEMENT + +;IMPHTI - Initialize host table +; Performed whenever IMP announces that it has been reset +; +IMPHTI: SETOM IMPHTF ;Force GC of IMPHTB on first reference + SETZM IMPHTS ;Clear table of old information + MOVE A,[IMPHTS,,IMPHTS+1] + BLT A,IMPHTE + POPJ P, + +; FNDHST - Look up host-table index for a given IMP host address. +; Call with NETOFF or NETCHN PI in progress. +; T/ IMP host address (maybe someday other nets?) +; Returns .+1 if failed (no room in table) +; Returns .+2 +; H/ host-table index +; Smashes W. + +FNDHST: MOVEI H,LIMPHT-1 ;Search for an entry for this host + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,POPJ1 ;Found + SKIPGE H,IMPHTF ;Not found, cons one off free list + JRST FNDHS1 ;Oops, must garbage collect + MOVE W,IMPHTB(H) + CAIGE H,LIMPHT ;Make sure H is valid idx + CAIL W,LIMPHT ;ditto W + BUG HALT,[NET: FNDHST idx clobbered!!!] + MOVEM W,IMPHTF + MOVEM T,IMPHTN(H) + SETZM IMPHTB(H) ;Nothing is known about this host + SETZM IMPHTC(H) ;Assume no RFNMs outstanding + SETZM IMPHTT(H) ;Clear out time of last RFNM. + JRST POPJ1 + +; Host-Table full, attempt to GC it and flush unused entries, by +; scanning all possible pointers into table. +; IMP pointers are IMPCSH and IMPHTC(H) +; TCP pointers are XBNADR(I) + +; GC mark phase - mark entries in use +FNDHS1: PUSH P,I + MOVSI W,200000 ;Mark bit + MOVEI H,LIMPHT-1 ;Clear all mark bits + ANDCAM W,IMPHTB(H) + SOJGE H,.-1 + SKIPL H,IMPCSH ;Mark from IMPCSH + IORM W,IMPHTB(H) +IFN TCPP,[ + MOVEI I,XBL-1 + SKIPL H,XBNADR(I) ; See if TCP conn has a net addr specified + IORM W,IMPHTB(H) ; Yes, set the mark bit. + SOJGE I,.-2 +] ;IFN TCPP + +; GC sweep phase - free all unmarked entries + SETO I, ;Free pointer + MOVEI H,LIMPHT-1 + MOVSI W,601000 ;Protect if RFNM-WAIT, RST-WAIT, or marked +FNDHS4: + SKIPG IMPHTC(H) ;Also protect if any outstanding RFNMs + TDNE W,IMPHTB(H) + SOJGE H,FNDHS4 + JUMPL H,FNDHS5 + SETZM IMPHTN(H) ;Don't belong to any host + MOVEM I,IMPHTB(H) ;Cons onto free list + MOVE I,H + SOJGE H,FNDHS4 +FNDHS5: MOVEM I,IMPHTF ;Free list + POP P,I + SKIPGE IMPHTF + POPJ P, ;GC-overflow + JRST FNDHST ;Try again, should win + +;See if IMP code is willing to handle a particular datagram right now. +; A/ IP DGM pointer +; C/ Immediate destination address +; Returns +1, can't send right now, +2, OK to send +; +IMPCTS: MOVE T,C ;Set up for FNDHST + AND T,[<377_16.>+377] ;Mask out all but host and IMP field + CALL FNDHST ;Get host index in H + POPJ P, ;No host entry, don't send + JSP T,IMPBLI ;See if OK to send + POPJ P, ;IMP wants to block, no send + JRST POPJ1 ;Skip return if OK to send. + + +;;; IMP Blockage avoidance +; The current IMP software will not accept more than 8 active +; messages to a single host; attempting to send a 9th message will block +; ALL output to the interface, until the first message has been ack'd +; by means of one of the following message types: +; Type 5, RFNM - Message delivered OK +; Type 7, Host dead - transmit failed ("permanent") +; Type 8, Error in data - interface spazzed +; Type 9, Incomplete Transmission - temporary failure +; If for some reason the first message simply becomes lost, the IMP timeout +; (and blockage) can last for up to 30-45 seconds. +; More details in BBN Report 1822. +; ITS attempts to fix this by keeping a count of active un-ACKed +; messages for each host it is communicating with. A timeout is also +; associated with each host; if output to a given host is blocked by ITS +; because there are 8 active messages, trying to send a 9th message +; will check the last-RFNM-received time and if this was more than +; 30 or so seconds then the IMP is probably not giving us what it should +; and we should reset things for that host. + +%IMPMA==:8. ; # of maximum active IMP messages allowed + +; IMPBLI, IMPBLD - routines to hack active-message counts, called via JSP T, +; IMPBLD decrements count. +; IMPBLI increments count and skips if successful (else failed, +; and must NOT output another message to this host!) +; Also clobbers Q. +; +IMPBLI: AOS Q,IMPHTC(H) + CAIGE Q,%IMPMA ;Trying to send max or more messages? + JRST 1(T) ;No, can return safely. + CAIG Q,%IMPMA ;Is this the maximum # allowed? + JRST [ MOVE Q,TIME ;Yes, set up blockage timeout + ADDI Q,60.*30. ; for one minute. + MOVEM Q,IMPHTT(H) + JRST 1(T)] ;And allow this one to be sent + + ; Trying to send too many messages, block it (check for timeout though) + SOS IMPHTC(H) ;Restore original count + AOS IMNBLK ;Increment # of times softwarily blocked. + MOVE Q,IMPHTT(H) + CAML Q,TIME ;See if timeout still in the future + JRST (T) ;Yes, just take failure-return to block. + BUG INFO,[IMP: RFNM-wait timeout! Hst=],OCT,IMPHTN(H) + SETZM IMPHTC(H) ;This may be dangerous... oh well. + SETZM IMPHTT(H) + JRST (T) ;Block one last time, next try will win. + +;Decrement block count on receipt of any kind of ACK +; +IMPBLD: SOSL Q,IMPHTC(H) + JRST IMPBL2 + BUG INFO,[IMP: negative RFNM-wait cnt, Hst=],OCT,IMPHTN(H) + SETZB Q,IMPHTC(H) +IMPBL2: CAIL Q,%IMPMA-1 ;If we were blocking on this host, + PUSHJ P,IMPIOS ;Ensure IMP output started up so blocked stuff + JRST (T) ; gets sent promptly. + + +SUBTTL ARPANET INPUT INTERRUPT LEVEL + +;First level interrupt handling for input side. Here from UBA vector hardware. + +IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPIBK + + EBLK +IMPIBK: 0 + BBLK + JSR UTCSAV ;Save AC's, get a stack + AOS IMCT2 ;Count input interrupts + IORDI TT,%LHICS ;Get CS register + TRNE TT,%LHERR\%LHNXM + JRST IMPRST ;Try resetting the IMP + TRNE TT,%LHMRE ;Ready line flapped + JRST IMPIER ;Go directly to error routine + TRNN TT,%LHRDY ;Device ready for new operation? + JRST IMPRST ;Try resetting. + TRNN TT,%LHEOM ;Saw EOM from IMP? + JRST IMPIB1 ;No, word count ran out before message + SKIPGE IMIFLS ;Flushing output? + JRST [ SETZM IMIFLS ;Not any more! + JRST IMPIRT ] ;But flush last piece by queueing new request + IORDI A,%LHIWC ;End of message. Get remaining UB word count + SKIPE A ;This would be a surprise, really + TDO A,[-1,,600000] ;36bit number of UBA words remaining in bfr + IDIVI A,2 ;Number of PDP10 words (cleverly rounded) + ADDI A,IMPBFS ;Number of PDP10 words of message + MOVEM A,IMPIBC ;Set current count of available data words + MOVEI A,IMPIBF + MOVEM A,IMPIBP ;Set pointer to available data words + JRST IMPLDD ;Go process input message + +;Here when finished processing current message. +IMPIRT: SETOM IMPCSH ;Note no current host + PUSHJ P,IMPIST ;Restart input listener + JRST IMPEX + +;Message didn't fit in input buffer. Shouldn't ever get here, but +;might if messages concatenated due to ready line randomness +; +IMPIB1: BUG INFO,[IMP: Huge message] + SETOM IMIFLS ;Say we are flushing output + JRST IMPIRT ;And go queue up another read + +;Here if error during IMP message transfer +; Currently the only error handled is the IMP going non-ready + +IMPIER: SKIPE IMPUP ;Is the IMP supposed to be up? + JRST IMPIE1 ;No, handle errors differently + BUG INFO,[IMP: Input Ready Error] + JRST IMPRST ;Ready line flapped while up, cycle interface + +IMPIE1: AOS T,IMPIEC + CAIG T,10. ;Huge number of errors while down? + JRST IMPIRT ;No, just ignore this input and start another + SETZM IMPIEC ;Reset + BUG INFO,[IMP: Excessive input errors while down] + JRST IMPRST ;Cycle the interface + +IMPRST: IORDI T,%LHICS ;Record IMP status for sysjob + HRLZM T,IMERCN + IORDI T,%LHOCS + HRRM T,IMERCN + MOVEI A,%LHRST ;Avoid randomness by resetting HW now. + IOWRI A,%LHOCS ;Reset output side + IOWRI A,%LHICS ;Reset Input side + SETOM IMPUP ;IMP is down + MOVEI T,1 + MOVEM T,IMPTCU ;But trying to come up (sysjob poked) + MOVSI J,SCLNET ;Ask SYSJOB to cycle the IMP + IORM J,SUPCOR + JRST IMPEX + + SUBTTL IMP leader dispatch handling + +IMPLDD: SKIPG B,IMPIBC ;Get count of available data + POPJ P, ;None, nothing to do. + CAILE B,IMPLDS ;More than a leader worth? + MOVEI B,IMPLDS ;Yep, only want leader now + MOVS A,IMPIBP ;Copy and reformat leader to IMPILB + HRRI A,IMPILB + BLTUB A,IMPILB-1(B) + ADDM B,IMPIBP ;Increment buffer pointer, + MOVN C,B + ADDM C,IMPIBC ; and decrement count + + LDB T,IMOTBP ;Examine new-format flag bits of leader + CAIL B,IMPLDS ;Large enough to be a valid leader? + CAIE T,17 ;Verify that leader is "new" 96-bit fmt. + JRST IMPLDE ;Go process error in leader + + LDB T,IMLNBP ;Extract link number (high 8 bits of msg-id) + MOVEM T,IMPCLN ;Save link message arrived on + LDB T,IMSABP ;Get arpanet address (source host+imp) +IFN 0,[ + LDB T,IMSHBP ;Source host + LDB A,IMSIBP ;Source imp + DPB A,[112000,,T] ;Form host address +];IFN 0 + PUSHJ P,FNDHST ;H gets host table index + JRST IMPLHE ;Host table full + MOVEM H,IMPCSH ;Save current host + LDB A,IMTBP ;Get message type in A + CAIL A,IMTDTS + JRST IMPUN ;Unknown type? + AOS IMPMSR(A) ;Count IMP msgs rcvd + JRST @IMTDT(A) ;Dispatch + +IMTDT: IMPRM ; 0 Regular Message + IMPBE1 ; 1 Error in Leader (no msg-id) + IMPGD ; 2 IMP Going Down + IMPUN ; 3 - + IMPIN ; 4 NOP + IMPRFN ; 5 RFNM - Ready For Next Message (transmit succeeded) + IMPHDS ; 6 Host Dead Status (general info) + IMPDHD ; 7 Destination Host Dead (transmit failed) + IMPBE8 ; 8 Error in Data (has msg-id) + IMPINC ; 9 Incomplete Transmission (transmit failed temporarily) + IMPIRS ;10 Interface Reset - IMP dropped its ready line +IMTDTS==.-IMTDT + +IMPLHE: BUG INFO,[IMP: Message discarded due to host table full],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +;Here if leader is too short or of wrong format. +; B/ Leader length +IMPLDE: SKIPE IMPUP ;If IMP is not up, we'll take anything. + JRST IMPIRT + CAIGE B,IMPLDS ;Announce short leader if so. + BUG INFO,[IMP: Short leader, ],DEC,B,[wds. WD1=],OCT,IMPILB,[WD2=],OCT,IMPILB+1 + LDB A,IMOTBP ;Get message format type + CAIN A,4 ;Old-type NOP? + JRST IMPIRT ; Just ignore it. +IFN 0,[ ;;For the moment this is a problem because the IMP is marked + ;;up too soon, before all incoming NOPS are received. + CAIN A,16 ;Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE A,17 ;Is it not the long-leader format? + BUG INFO,[IMP: Old-type leader],OCT,IMPILB +] + JRST IMPIRT ;Ignore rest of message, if any + +;;; IMP->Host Type X (e.g. 3, 11-255) - bad type + +IMPUN: BUG INFO,[IMP: Unknown msg type ],OCT,A,[ leader ],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +;;; IMP->Host Type 1 - Error in leader (msg-id not given) +;;; IMP->Host Type 8 - Error in data (msg-id given) + +IMPBE1: LDB T,IMSTBP ;Get subtype (4 bits) + ANDI T,3 ;Only 2 bits should be used + AOS IMPM1S(T) ;Increment count of Type 1 subtype messages +IMPBE8: SKIPN IMPUP ;Ignore error during initial syncronization + BUG INFO,[IMP: Type ],DEC,A,[err msg, leader],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + MOVE B,IMPCLN ;Get link msg came in on + CAIN B,233 ;Internet link? + AOS IMNIP8 ;Yes, count IP meter + CAIN A,8. ;Error identified with a particular message? + JSP T,IMPBLD ;Decrement count of active messages + JRST IMPIRT + +;;; IMP->Host Type 2 - IMP going down + +IMPGD: LDB B,[420200,,IMPILB+2] ;Reason (see 1822) + MOVEM B,IMPDWN + LDB B,[360400,,IMPILB+2] ;How soon going down * 5 mins + MOVE H,B + IMULI B,5*60.*30. ;Ticks in 5 mins + ADD B,TIME + MOVEM B,IMPDWN+1 + LDB C,[241200,,IMPILB+2] ;How long to be down * 5 minutes + MOVE Q,C + IMULI C,5*60.*30. ;Downtime in ticks + ADD C,B ;Add to time down + MOVEM C,IMPDWN+2 ;Store time when will be up + IMULI H,5 ;Minutes + IMULI Q,5 + BUG INFO,[IMP: Going down in ],DEC,H,[mins for ],DEC,Q,[mins, reason],DEC,IMPDWN + JRST IMPIRT + +;;; IMP->Host Type 4 - NOP + +IMPIN: JRST IMPIRT ;One more NOP from IMP + +;;; IMP->Host Type 5 - RFNM (Ready For Next Message) + +IMPRFN: JSP T,IMPBLD ;Decrement outstanding message count for host + MOVE A,IMPCLN ;Get link # + CAIE A,233 ;IP link number? + JRST IMRFNX ;No, skip IP code + AOS IMNIPR ;Bump count of IP RFNMs received + JRST IMPIRT ; and do nothing else about it, ugh. + +IMRFNX: BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN + AOS IMNSRF + JRST IMPIRT + +;;; IMP->Host Type 6 - Host Down Status +; H/ host index + +IMPHDS: LDB A,[301400,,IMPILB+2];Bits 65-76 of leader, 4.9-3.7 3rd word + HRRM A,IMPHTB(H) ;Store, hope user read RFC 611 + JRST IMPIRT + +;;; IMP->Host Type 7 - Destination Host Dead + +IMPDHD: MOVEI E,%NCDED + JRST IMPHNR + +;;; IMP->Host Type 9 - Incomplete Transmission + +IMPINC: LDB T,IMSTBP ;Get subtype field (4 bit reason for failure) + AOS IMPM9S(T) ;Bump count of subtypes + MOVEI E,%NCINC ;This is an incomplete msg response + +IMPHNR: JSP T,IMPBLD ;Decrement active IMP msg count for this host + MOVE A,IMPCLN ;Link for this message? + CAIE A,233 ;IP Link? + JRST IMPHN1 + CAIN E,%NCINC ;Yes, count IP meters + AOS IMNIP9 + CAIN E,%NCDED + AOS IMNIP7 + JRST IMPIRT + +IMPHN1: BUG INFO,[IMP: DHD or IT msg rcvd on non-IP link] + JRST IMPIRT + +;;; IMP->Host Type 10 - Interface Reset + +IMPIRS: PUSHJ P,IMPHTI ;Initialize host table + BUG INFO,[IMP: Interface reset] + JRST IMPIRT + + +;;; IMP->Host Type 0 - Regular Host-Host message +; Unless the source host screwed up and sent a dataless message, +; there is at least one word waiting to be read in the buffer. +; +IMPRM: SKIPG A,IMPIBC ;Get available input word count + JRST IMPIRT ;None left, just ignore message + MOVE B,IMPCLN ;Is link number the magic cookie for IP? + CAIE B,233 + JRST IMPIRT ;No, ignore it + +;IP datagram. Copy into IP buffer and pass it up. +; + AOS IMNIPI ;Bump count of IP datagrams received + PUSHJ P,IPGIPT ;Ask IP for buffer of size (A) + JRST [ AOS IMNIPF ;Punted, bump cnt of datagrams lost + JRST IMPIRT ] ;Flush this message (err msg already printed) + MOVE B,PK.BUF(A) ;Destination + HRL B,IMPIBP ;Source + MOVE C,IMPIBC ;Input words available + ADDI C,-1(B) ;Last destination address + BLTUB B,(C) ;Copy and reformat data to IP buffer + MOVE B,IMPIBC ;Get word count back to B + SETZB C,IMPIBC ;Say zero offset to IP header, and clear count. + MOVE J,IMPCSH ;Set idx to host-table entry dgm received from. + PUSHJ P,IPRDGM ;Hand off rcvd datagram to IP + JRST IMPIRT ;Return from PI level, setting up for next msg + +;Start listening for new input from IMP +; +IMPIST: HRREI T,-IMPBFS*2 + IOWRI T,%LHIWC ;Read up to a buffer full of data + MOVEI T,+<4*> + IOWRI T,%LHICA ;Read data to here + MOVEI T,%LHIE\%LHHRC\%LHSE\%LHGO ;Interrupt, store data, go + IOWRI T,%LHICS ;Start read + RET + + +SUBTTL ARPANET OUTPUT INTERRUPT LEVEL + +;Here on unvectored interrupt caused by call to IMPIOS + +IMPINT: AOS IMCT1 ;Count unvectored interrupts + JRST IMPOBZ ;Go try to start output + ;Returns directly to interrupt dispatcher + +;First-level interrupt handling, from hardware dispatch. +; Crash on severe interface errors +; Restart IMP on ready line flappage. +; Else, go look for more output to send. + +IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPOBK + + EBLK +IMPOBK: 0 + BBLK + JSR UTCSAV ;Save AC's, get a stack + AOS IMCT3 ;Count output interrupts + IORDI TT,%LHOCS ;Get CS register + TRNE TT,%LHERR\%LHNXM ;Interface lost? + JRST IMPOEC ;Try cycling + TRNE TT,%LHMRE ;Somebody bounce a ready line? + JRST IMPOER +IMPOBE: TRNN TT,%LHRDY ;Device ready for new operation? + JRST IMPOEC ;Try cycling + PUSHJ P,IMPOBZ ;No IMP error. Perform planned action. + JRST IMPEX ;Dismiss interrupt. + +;Error while outputting datagram. Currently, just means ready line flapped. +; If IMP was up, finish up IP output if necessary to free buffer, then +; cycle the interface. +; If trying to send NOPS to come up, just send a few more to resynch. +; +IMPOER: SKIPE IMPUP ;IMP up? + JRST IMPOE1 ;Not running normally, maybe OK. + BUG INFO,[IMP: Output RDY error] +IMPOEC: SKIPE A,IMPODP ;Have an output datagram ? + PUSHJ P,IPIODN ;Yep, release it. + SETZM IMPOS ;Doing nothing useful + JRST IMPRST ;Go poke SYSJOB to cycle the IMP + +;Here if interface wasn't fully up. +IMPOE1: MOVE T,IMPOS + CAIE T,%ISONP ;Were we sending a NOP? + BUG CHECK,[IMP: Confusing output error] + SOS IMNOPC ;Add another NOP to make up for this one + SETZM IMPOS ;NOt doing anything anymore + JRST IMPOBE ;Go continue processing. + +;IMPOBZ - Toplevel output processing routing. +; Called from output done interrupt handler or from MP/CLOCK level with +; NETOFF to start output. + +IMPOBZ: SKIPL B,IMPOS + CAIL B,IMPODL + BUG HALT,[IMP: Bad output state] + JRST @IMPODT(B) + +IMPODT: OFFSET -. +%ISODL:: IMPOB0 ; 0 Idle, look for something to send +%ISONP:: IMPOB1 ; 1 Finished NOP +%ISOID:: IMPOB2 ; 2 Finished IP datagram messge +IMPODL::OFFSET 0 + +;Here when interrupt has finished processing a complete message. +; Attempt to find something else to do. +; +IMORET: + ;JRST IMPOB0 ;Fall through to try for more + +; Idle - Look for output to send. First ensure we can send stuff, +; then try things in the order: +; (1) Send NOP if net coming up +; (2) Check IP datagram queue +; +IMPOB0: HRRZ T,IMPUP ;Get current IMP state. + CAIE T,-2 ;Don't say it's up when it's still going down + CAIN T,1 ;or when it is broken + JRST IMPOBN + + ; First check to see if NOP needs to be sent. + AOSG IMNOPC ;Check to see if sending NOPs + JRST IMONOP ;Output a NOP + SETZM IMPUP ;Say IMP is up + SETZM IMPTCU ;Say no longer trying to come up + + ; Now see if there is any real traffic to send + PUSHJ P,IPGIOQ ;Check IP. Get IP IMP output queue entry if any + JRST IMPOBN ;Nothing there, we're done. + + ; Returns A/ ptr to IP dgm struct + ; B/ BLKO pointer to 32-bit words (unused) + ; C/ Arpanet address + ; + ;Build an IMP-format datagram at IMPOBF. + ; Set correct address in prototype leader. + ; BLT and reformat leader to IMPOBF. + ; BLT and reformat datagram to IMPOBF + leader size. + + MOVEM A,IMPODP ;Save ptr to datagram being output + AOS IMNIPO ;# of IP datagrams sent + + ;Put together the IMP leader in IMOLDR. +IFN 0,[ ;First and third word initialized at assembly time + MOVE B,[17_10.,,0] ;Regular message + MOVEM B,IMOLDR + MOVSI B,233_10. ;IP link # in left 8 bits + MOVEM B,IMOLDR+2 ;Set up third word +] + AND C,[<377_16.>+377] ;Mask out all but host and IMP field + LSH C,4. ;Move net address to correct field + MOVEM C,IMOLAD ;set up second word of leader + + ;Copy leader and datagram to IMPOBF + MOVE B,[IMOLDR,,IMPOBF] + BLTBU B,IMPOBF+IMPLDS-1 ;Move IMP leader into place + MOVS B,PK.BUF(A) ;SOURCE,,COUNT + MOVEI A,IMPLDS(B) ;Size including leader to A + HRRI B,IMPOBF+IMPLDS ;Put d'gram immediately after leader. + BLTBU B,IMPOBF-1(A) + PUSHJ P,IMPSOH ;Go start hardware + MOVEI C,%ISOID ;Remember we are outputting IP leader + MOVEM C,IMPOS + POPJ P, + + + +;Here if nothing to output. +; Flag output inactive and disable interface +; +IMPOBN: SETOM IMPOAC ;No more output + IORDI TT,%LHOCS + TRZ TT,%LHIE\%LHGO ;Deactivate interface for a bit + IOWRI TT,%LHOCS + POPJ P, + +;IMONOP - Send a NOP, here from IMPOBZ only. +; +IMONOP: MOVEI A,IMPNOS ;Length of NOP message + MOVE B,[IMPNOP,,IMPOBF] ;BLT (and reformat) NOP to output buffer + BLTBU B,IMPOBF-1(A) + PUSHJ P,IMPSOH ;Start output of (A) words from IMPOBF to IMP + MOVEI C,%ISONP ;Set correct output FSM state + MOVEM C,IMPOS + POPJ P, + +;Prefabricated NOP Host-IMP leader +IMPNOP: 17_10.,,4_4 ;New format, type 4 = NOP + 0 + 0 ;No padding required on regular messages +IMPNOS==.-IMPNOP + +;Finished sending NOP, from IMPOBZ +; +IMPOB1: SETZM IMPOS ;Reset state + JRST IMORET ;Go look for something else to do. + +;Was sending IP datagram, from IMPOBZ +; +IMPOB2: SETZB A,IMPOS ;Reset output state. + EXCH A,IMPODP ;Get active datagram and reset pointer + PUSHJ P,IPIODN ;Tell IP level that datagram was output + JRST IMORET ;Go see if there is anything else to do. + +;Start output hardware. +; A/ Count of PDP10 words to write to net. +; Data to output in IMPOBF. +; Must be NETOFF or at NETCHN interrupt level. Bashes A only. + +IMPSOH: ASH A,1 ;Convert PDP10 word count to... + MOVNS A ; negative unibus word count. + IOWRI A,%LHOWC ;Tell the interface + MOVEI A,+<4*> + IOWRI A,%LHOCA ;Unibus address of output buffer + MOVEI A,%LHIE\%LHELB\%LHGO ;Enable interrupts, send EOM, GO + IOWRI A,%LHOCS ;Start DMA transfer + POPJ P, ;And forget it. + +SUBTTL ARPANET CLOCK LEVEL + +IMRSTO: RET ;Nothing to do any more? + +OVHMTR UUO + +;NETHST (HOST INFO) +; ARG 1 - HOST => VAL 1 - STATUS, VAL 2 - HOST NUMBER +; ARG 1 - -1 => VAL 1 - (STATUS), VAL 2 - OUR HOST NUMBER +;NOT CURRENTLY IMPLEMENTED- ARG 1 - -1, ARG 2 - OUR GOING-DOWN REASON +; +ANETHST:HRRE T,A ;Let immediate -1 win (777777 not a valid host) + AOJE T,ANETH2 ;Jump if want local status and host number + MOVE T,A + JSP J,STDHST ;Standardize and error-check host number + MOVE B,T ;Return new format + TLO B,(NW%ARP) + MOVEI H,LIMPHT-1 + CONO PI,NETOFF ;Do we have status for this host? + CAME T,IMPHTN(H) ;Scan table + SOJGE H,.-1 + JUMPGE H,ANETH1 ;Yes, return it + CONO PI,NETON ;No, have to go get it + MOVEM T,SRN3(U) + POPJ P, ;Oh, too bad + +;Here to return status of foreign ARPAnet host +ANETH1: MOVE A,IMPHTB(H) ;Get status + CONO PI,NETON + EXCH A,B + CALL CVH2NA ;Convert to HOSTS2 for compat + EXCH A,B + JRST LSWCJ1 ;Return IMSOC, NETLST if not done already + +;Here to return our status, host +ANETH2: +REPEAT 0,[ + CAIL W,2 ;(This is a crock) + MOVEM B,NTHDSW ;If 2 args, set our reason for going down. +] + SKIPE IMPUP ;Fake up our status + TDZA A,A ;We're down + MOVSI A,2000 ;We are up + MOVEI B,IMPUS ;And our host umber + JRST POPJ1 + + +;NETIMP (REASON,TIMEDOWN,TIMEUP) READ/SET +; +ANETIM: JUMPLE W,ANETM1 ;No args, return current data + CAIGE W,3 ;Must have 3 args if any + JRST OPNL30 + MOVEM A,IMPDWN ;Set data + MOVEM B,IMPDWN+1 + MOVEM C,IMPDWN+2 + JRST POPJ1 + +ANETM1: MOVE A,IMPDWN ;Get data to return + MOVE B,IMPDWN+1 + MOVE C,IMPDWN+2 + SKIPE IMPUP ;Note current condition of IMP, too + TLO A,400000 + JRST POPJ1 diff --git a/src/system/impold.wthncp b/src/system/impold.wthncp new file mode 100755 index 00000000..bcc9905a --- /dev/null +++ b/src/system/impold.wthncp @@ -0,0 +1,1974 @@ +;;; -*- Mode:MIDAS -*- +SUBTTL ARPANET HARDWARE DEFINITIONS + +IFNDEF BLIMPP,BLIMPP==INETP ; Use IMP blockage avoidance code +IMPVRS==.IFNM2 ; Version of IMP/NCP code + +IFN KAIMP,[ +; Hardware description of AI-KA/ML/MC IMP interface, device "IMP". +; For a more detailed description, see AI Hardware Memo #10, +; "ARPA Network Interface". +; In particular, the "channel 1 multiplexing" feature of the ITS KA's +; is used, so that: +; When PI level 2 (NETCHN) is assigned, the IMP interface takes +; all interrupts on the normal channel (goes to IMPINT). +; When PI level 1 (IMPCHN) is assigned, +; IMPID+(-IMPLIW) => Pseudo channel 4, location 70 (IMPILC)-> various +; IMPOD => Pseudo channel 5, location 72 (IMPOLC)-> various +; else normal PI channel 1 (PI0LOC+2)-> IMPBRK + +; CONI bits - starred items cause interrupt on PIA channel + ; 1.1-1.3 => PIA +IMPID==10 ;* INPUT DONE - Turned on when interface has word for DATAI +IMPI32==20 ; Input in 32 bit mode +;IMPIB==40 ; Input Busy +IMPOD==100 ;* OUTPUT DONE - Interface has finished giving word to IMP +;IMPO32==200 ; Output in 32 bit mode +;IMPOB==400 ; Output Busy +IMPERR==1000 ;* Imp Error (interrupt if IMPIC zero) +IMPR==2000 ;* Imp Ready (interrupt if IMPIC set) +;IMPIC==4000 ; Imp interrupt condition (0 = int on IMPERR, 1= int on IMPR) +IMPHER==10000 ;* Host Error (interrupt if IMPIHE zero) +;IMPHR==20000 ; Host Ready +;IMPIHE==40000 ; Inhibit interrupt on Host Error (IMPHER) +IMPLW==100000 ;* Last Imp Word + +; CONO bits - starred flags are always copied directly to set states + ;* 1.1-1.3 => PIA set from these bits +IMPIDC==10 ; Clear Input Done +IMI32S==20 ; Set input to 32 bit mode +IMI32C==40 ; Clear input in 32 bit mode +IMPODC==100 ; Clear Output Done +IMO32S==200 ; Set output to 32 bit mode +IMO32C==400 ; Clear output in 32 bit mode +IMPODS==1000 ; Set Output Done +IMPIR==4000 ;* Copied to IMPIC; 1= Enable int on imp ready +IMPHEC==10000 ; Clear Host Error +;IMIIHE==40000 ;* Copied to IMPIHE; 1= Inhibit int on host error +IMPLHW==200000 ; Set Last Host Word (do this before last DATAO of msg) + +];DMIMP + IFN DMIMP,[ ;HARDWARE DESCRIPTION OF DM IMP INTERFACE (PER RMM) + +; Note that all PI level 2 interrupts go to normal ITS location +; and thence vectored to IMPINT. +; However, PI 1 interrupts go to different places: +; Input Done -> loc 70 (IMPILC) +; Output Done -> loc 72 (IMPOLC) +; Control -> Should never get control interrupt at PI 1. +; Thus for example "Last Imp Word" interrupts go to +; IMPINT even though input side PIA is 1, because LIW is +; a control interrupt and control ints are always kept at PI 2. + + ;IMP INTERFACE CONO FLAG DESCRIPTION + +;COMMON FLAG BITS TO CONTROLLER + + ;18-> 0 FOR INPUT SIDE, 1 FOR OUTPUT SIDE + ;19->CLEAR TEST MODE (200000) + ;20->SET TEST MODE (100000) + + ;21->CLEAR HOST READY + ;22->SET HOST READY (20000) + ;23->CLEAR IMP-WAS-DOWN (10000) + + ;24->FI DEVICE RESET (CLEAR ALL INPUT AND OUTPUT FLAGS) (4000) + +;CONO FI (424) TO OUTPUT SIDE + ;BIT ;18->IS '1' INDICATING TO OUTPUT + ;25->CLEAR OUTPUT 32-BIT MODE + ;26->SET OUTPUT 32-BIT MODE + + ;27->SET OUTPUT EOT (CLEAR DONE, SET BUSY) (400) + ;28->SET OUTPUT DONE (200) + ;29->RESET OUTPUT (CLEAR ALL OUTPUT FLAGS) (100) + + ;30-32->CONTROL PI ASSIGNMENT + + ;33-35->OUTPUT DONE PI ASSIGNMENT + +;CONO FI (424) TO INPUT SIDE + ;BIT ;18->IS '0' INDICATING TO INPUT + ;25->CLEAR 32-BIT MODE (2000) + ;26->SET 32-BIT MODE (1000) + + ;27->SUSPEND INPUT (400) DATAI WONT SET BUSY NOW + ;28->SET INPUT BUSY (LISTENING TO NETWORK) (200) + ;29->RESET INPUT (CLEAR ALL INPUT FLAGS!) (100) + + ;30-32->CONTROL PI ASSIGNMENT + + ;33-35->INPUT DONE PI ASSIGNMENT + + ;FI CONI FLAG DESCRIPTION + + ;BIT ;00->TEST MODE IS ENABLED + ;08->OUTPUT IS IN 32-BIT MODE + ;17->INPUT IS IN 32-BIT MODE + + ;18->IMP IS DOWN + ;19->IMP WAS DOWN + ;20->HOST READY (?) + + ;21->OUTPUT EOT ON + ;22->OUTPUT BUSY + ;23->OUTPUT DONE + ;24-26->OUTPUT-DONE PI ASSIGNMENT + + ;27->INPUT EOT ON + ;28->INPUT BUSY + ;29->INPUT DONE + + ;30-32->CONTROL INTERRUPT PI ASSIGNMENT + + ;33-35->INPUT DONE PI ASSIGNMENT + +; SYMBOL ASSIGNMENTS FOR DM HARDWARE + +; CONO BITS + +FIIN==000000 ;(SIC) SPECIFY CONO FOR INPUT +FIOUT==400000 ;SPECIFY CONO FOR OUTPUT SIDE +;FITSTC==200000 ;CLEAR TEST MODE +;FITSTS==100000 ;SET TEST MODE + +;FIHSTC==040000 ;CLEAR HOST READY +FIHSTS==020000 ;SET HOST READY +FIIWDC==010000 ;CLEAR "IMP WAS DOWN" + +FIRSET==004000 ;DO LOCAL IOB RESET FOR FI DEVICE + +;INPUT SIDE ONLY + +FII32C==002000 ;CLEAR 32 BIT MODE, INPUT +FII32S==001000 ;SET 32 BIT MODE, INPUT + +FISUSP==000400 ;"SUSPEND INPUT" CLEAR FLAG, NOT SET BUSY +FIIBSY==000200 ;SET INPUT BUSY, ALLOWS BITS IN FROM IMP +FIIDC==000100 ;CLEAR INPUT DONE + +; 0000X0 ;CONTROL PIA + +; 00000X ;INPUT DONE PIA + +;OUTPUT SIDE ONLY + +FIO32C==402000 ;CLEAR 32 BIT MODE, OUTPUT +FIO32S==401000 ;SET 32 BIT MODE, OUTPUT + +FILHW==400400 ;SET "LAST HOST BIT TO IMP" +FIODS==400200 ;SET OUTPUT DONE +FIODC==400100 ;CLR OUTPUT DONE + +; 0000X0 ;CONTROL PIA + +; 40000X ;OUTPUT DONE PIA + +; CONI BITS + +; LEFT HALF OF CONI WORD FOR FOLLOWING 3 BITS + +;FITSTM==400000 ;TEST MODE IS ON +;FIO32==001000 ;OUTPUT IS IN 32 BIT MODE +FII32==000001 ;INPUT IS IN 32 BIT MODE + +; RIGHT HALF OF CONI + +FIDOWN==400000 ;IMP IS DOWN +FIWASD==200000 ;IMP WAS DOWN (OR IS) SINCE LAST RESET +;FIHSTR==100000 ;HOST READY IS SET ON + +;FIOEOT==040000 ;OUTPUT LAST IMP BIT IS ON +;FIOBSY==020000 ;OUTPUT IS BUSY AFTER DATAO +FIOD==010000 ;OUTPUT IS DONE, (INTERRUPTING) + +; 00X000 ;OUTPUT DONE PIA + +FILW==000400 ;LAST BIT SET FROM IMP +FIIBSY==000200 ;INPUT IS BUSY, WORD BEING ASSEMBLED FROM IMP +FIID==000100 ;INPUT IS DONE (INTERRUPTING) TO DO DATAI + +; 0000X0 ;CONTROL PIA + +; 00000X ;INPUT PIA + +IMPLW==FILW ;USEFUL TO TEST IN AC +IMP==FI ;USEFUL FOR BLKO, DATAO INSTR +] + +; IMP 1822 PROTOCOL INFORMATION (EXTENDED-LEADER VERSION) + +; The IMP leader is 96 bits long, usually organized as 3 words of 32 bits. +; For further details, these documents are available from the Network +; Information Center: +; IMP-HOST protocol: BBN Report No. 1822 +; NCP protocol: NIC 8246, Host-to-Host Protocol for the ARPANET +; IP, TCP: Internet Protocol Transition Workbook, and +; Internet Protocol Implementor's Guide +; +; For the benefit of the NCP code, ITS reads in the leader as 36-bit words +; with sufficient IMP padding (5 16-bit wds) to cause NCP data to be aligned +; on a word boundary. The first 4 words of the leader are read +; in 36-bit mode: +;------------------------------------------------------------------------ +;1: 4.9-4.6 not used (0) +; 4.5-4.2 all 1's for new format, else old msg type (4=old nop) +; 4.1-3.3 network number (0) +; 3.2-2.8 not used (0) +; 2.7 trace (ignored) +; 2.6-2.4 leader flags (2.6 is to be ignored, 2.5-2.4 are not used!) +; 2.3-1.5 message type (as of yore, but more bits) (see IMTDT) +; 1.4-1.1 high 4 bits of handling type (0) +; +;2: 4.9-4.6 Low bits of handling type (7 for big buffers, 4 for small buffers, +; 4.5-3.7 host number and 0 for the control link) +; 3.6-1.9 Imp number +; 1.8-1.1 Link number (high 8 bits of message-id) +; +;3: 4.9-4.6 Low 4 bits of message-id (0) +; 4.5-4.2 Sub-type +; 4.1-2.4 Message length (ignored) +; 2.3-1.1 Padding +;------------------------------------------------------------------------ +; All non-regular messages (ie Host-Imp, not Host-Host) +; stop here, since padding and data only exist for regular +; messages (Type 0). +;------------------------------------------------------------------------ +;4: 4.9-1.1 Padding +;------------------------------------------------------------------------ +; At this point there are still 32 bits of padding left. The +; Internet Protocol messages are vectored off here (they are +; identified by a message-type of 0 and a link-number of 233). +;------------------------------------------------------------------------ +; HOST-HOST REGULAR MESSAGES +; NETWORK CONTROL PROTOCOL (NCP) - read in 36-bit mode +;5: 4.9-1.5 Padding +; 1.4-1.1 M1 Host-host padding +; +;6: 4.9-4.6 M1 Host-host padding ; NCP leader contained in this word. +; 4.5-3.7 S Byte size +; 3.6-1.9 C Byte count +; 1.8-1.1 M2 Host-host padding +;------------------------------------------------------------------------ +; HOST-HOST REGULAR MESSAGES +; INTERNET PROTOCOL (IP) - read in 32-bit mode +;5: 4.9-1.5 Padding +;6: 4.9-1.5 First word of IP datagram +;------------------------------------------------------------------------ + +;In message types 2 and 6, the going-down status 16-bit word is +;in word 2 1.8-1.1 and word 3 4.9-4.2. + +;4.5-4.2 of word 3 are the padding count for type 4 (nop) from host. +;This is 5. Padding is only put on type-0 messages. + +IMTBP: 041000,,IMPILB+0 ;BYTE POINTER FOR MESSAGE TYPE FIELD +IMOTBP: 340400,,IMPILB+0 ; Byte ptr for message format type +IMLNBP: 001000,,IMPILB+1 ;BYTE POINTER FOR LINK NUMBER FIELD +IMSABP: 103000,,IMPILB+1 ; Byte ptr for source address field (host+imp) +IMSHBP: 301000,,IMPILB+1 ;BYTE POINTER FOR SOURCE HOST FIELD +IMSIBP: 102000,,IMPILB+1 ;BYTE POINTER FOR SOURCE IMP FIELD +IMSTBP: 340400,,IMPILB+2 ; Byte ptr for subtype field +IMCBBP: 301000,,IMPILB+5 ;BYTE POINTER FOR CONNECTION BYTE SIZE FIELD +IMBCBP: 102000,,IMPILB+5 ;BYTE POINTER FOR BYTE COUNT FIELD + + +SUBTTL ARPANET VARIABLES AND TABLES + +IFN NCPP,[ +IMPSTL==NNETCH ;SOCKET TABLE LENGTH (MUST BE .LE. 70) +IFG NNETCH-70,.ERR NNETCH SHOULD BE LESS THAN 70 OCTAL, PER BBN SPECS +];NCPP + +IFN INETP,[ +IMPCLP: 0 ; HACK!! # to use for control-link link field. +] +EBLK + +IMPN:: ;IMP DATA AREA CLEARED WHEN IMPUP +IFN INETP,[ +%IMXLN==:<<8159.-96.>+31.>/32. ; Max # of 32-bit words in IMP regular msg, + ; exclusive of leader and leader padding. = 252. +IMPIBS: 0 ; Saved initial BLKI pointer for IP datagram read +IMPIDP: 0 ; Pointer to IP datagram being input at PI level +IMPODP: 0 ; Pointer to IP datagram being output at PI level +IMPPSW: 0 ; Flip-flop to alternate output of IP and NCP msgs +] +IFN KAIMP,[ +IMPI: 0 ;-1 => IMPCHN INPUT INTERRUPT OCCURRED +IMPO: 0 ;-1 => IMPCHN OUTPUT INTERRUPT OCCURRED +IMPB: 0 ;-1 => IMPCHN FLAG INTERRUPT OCCURRED +IMPIH: 0 ;-1 => INPUT WANTS PIA = IMPCHN +IMPOH: 0 ;-1 => OUTPUT WANTS PIA = IMPCHN +] +IMPIS: 0 ;INPUT STATE + %ISIDN==:-1 ; Network shut off + %ISIDL==:0 ; Normal - idle, not expecting input (i.e. between msgs) + %ISIGN==:1 ; Ignore input until end of current message (36 bit mode) + %ISIML==:2 ; Reading IMP initial leader (36 bit mode) + %ISINC==:3 ; Reading NCP control message (32 bit mode) + %ISIND==:4 ; Reading NCP data message (32 or 36 bit mode) + %ISINL==:5 ; Reading NCP-type IMP leader (36 bit mode) + %ISIIL==:6 ; Reading IP-type IMP leader (32 bit mode) + %ISIID==:7 ; Reading IP datagram (32 bit mode) + +IMPOS: 0 ;OUTPUT STATE + %ISODL==:0 ; Not expecting output done (i.e. between messages) + %ISONC==:1 ; Sending NCP control message + %ISOND==:2 ; Sending NCP data message + %ISOID==:3 ; Sending IP Datagram + +IMPHI: 0 ;-1 TO HOLD UP INPUT + ;-2 INPUT IS SUCCESSFULLY HELD UP +IMRFCT: 0 ;NUMBER OF HOST TABLE ENTRIES WITH PENDING + ;TIMEOUTS FOR CONTROL-LINK RFNM OR RST-RRP. + +; ACTIVE HOST TABLE. Entries herein are allocated as needed, using garbage +; collection. Most "host number" fields are really indices into +; this table. +LIMPHT==+ ; NCP conns plus TCP conns plus a few extra +IMPHTN: BLOCK LIMPHT ; Host number. 1.1-1.8 HOST, 2.1-3.7 IMP +IMPHTB: BLOCK LIMPHT ;BITS: + ;4.9 1=RFNM WAIT ON LINK 0 (NCP) + ;4.8 GC MARK BIT + ;4.7-4.3 UNUSED + ;4.2-4.1 STATUS OF HOST 0 DOWN, 1 RST SENT, 2 UP + ;3.9-3.1 TIME (MOD 2**9) LAST RFNM SENT ON LINK 0 (NCP) + .SEE IMPHDS ;RH LAST MESSAGE FROM IMP ABOUT "HOST DEAD STATUS" +IMPHTC: BLOCK LIMPHT ; # active messages outstanding for host (8 max) +IMPHTT: BLOCK LIMPHT ; Time of last RFNM received + +IMNCS: 0 ;NUMBER OF CHANNELS BEING CLOSED +IMNAS: 0 ;NUMBER OF CHANNELS WITH 4.8 IN IMSOC5 SET +LIMPN==.-1 ;LAST LOCATION BLT'ED TO ZERO WHEN INITIALIZED +IMNBLK: 0 ; Number of times blockage avoided (output held up by ITS) +IMPHTF: -1 ;HOST TABLE FREE LIST, THREADED THROUGH IMPHTB, END WITH -1 +IMPUP: -1 ;0 => IMP UP ;-1 => DOWN ;-2 => COMING UP, PI LVL STILL OFF + ;1 => DOWN FOR GOOD, UNTIL NEXT TIME IMP READY LINE CHANGES +IMPTCU: 0 ;0 IMP UP/DOWN STATUS NOT CHANGING + ;>0 TRYING TO REINITIALIZE, SYS JOB HASN'T DONE SO YET + ;-1 HAS BEEN REINITIALIZED, HAVEN'T EXCHANGED NOPS YET +IMPUCT: 0 ;IMP COMING UP TIMEOUT, IF 4 NOOPS DON'T GO THROUGH PROMPTLY. +IMPDWN: BLOCK 3 ;LAST MESSAGE FROM IMP THAT IT IS GOING DOWN + ;WD0 "REASON" CLAIMED BY IMP (SEE CH 3 OF BBN REPORT 1822) + ;WD1 TIME WHEN EXPECTED DOWN + ;WD2 TIME WHEN EXPECTED UP (SYS TIME=1/30 SEC SINCE UP) +IFN KAIMP,IMPPIA: 0 ;CURRENT IMP PIA +IMPCNI: 0 ;CONI INTO HERE AT SLOW CLOCK LEVEL +IMERCN: -1 ;CONI INTO HERE WHEN NET GOES DOWN +IMNOPC: 0 ;< 0 => SEND NOPS +IMPA: 0 ;SAVE A AT IMPCHN PI LEVEL +IMPOAC: -1 ;-1 => OUTPUT INACTIVE +IMPERB: BLOCK 5 ;LAST "ERR" MESSAGE FROM A HOST + ;WD 0 TIME WHEN RCVD, WD 1 HOST, WD2-4 11. 9-BIT BYTES OF DATA +IFN DMIMP,IMPSUS: 0 ;HOLDS INPUT WORD WHILE INPUT IS HELD UP +IMPILB: BLOCK 6 ;INPUT LEADER BUFFER +IMPINB: BLOCK 30.+5 ;30. WORDS @ 32 BITS/WD = 120. 8 BIT BYTES + ;+5 WORDS FOR GOOD MEASURE + ;THIS BUFFER IS FOR CONTROL-LINK MESSAGES +BBLK + +IMHSBT: 330200,,IMPHTB(H) ;RST/RRP STATUS + +EBLK + +IMPCSH: -1 ;CURRENT SOURCE HOST (IMPHTB INDEX). -1 WHEN IDLE. +IMPCLN: 0 ;CURRENT LINK NUMBER +IMPCBS: 0 ;CURRENT BYTE SIZE +IMPCBC: 0 ;CURRENT BYTE COUNT +IMPNIW: 0 ;EXPECTED LAST BLKI ADDRESS +IMNWSI: 0 ;SECOND BLKI POINTER, ZERO IF NONE +IMPSVP: 0 ;SAVE PIA AT IMPRMP +IMPSVQ: 0 ;SAVE CONTROL MESSAGE QUEUE POINTER AT IMPOB2 +IMBLKI: 0 ;PLACE TO STORE BLKI POINTER +IMBLKO: 0 ;PLACE TO STORE BLKO POINTER +IMPNBI: 0 ;AMOUNT TO INCREMENT IMSMPC(I) BY, I.E. # OF DATA BYTES + ; IN MESSAGE CURRENTLY COMING IN AT P.I. LEVEL +IMPNBO: 0 ;AMOUNT TO INCREMENT IMSMPC(I) BY, I.E. # OF DATA BYTES THAT WILL BE + ; MADE FREE IN BUFFER BY MESSAGE CURRENTLY GOING OUT AT P.I. LEVEL +IMPNBT: 0 ;# BITS ACTUALLY BEING SENT, USED TO ADJUST ALLOCATION +IMPNPT: 0 ;NEW VALUE FOR IMSPIP(I) AFTER MSG IS SENT +IMPIPI: -1 ;IMSOC INDEX ACTIVE FOR INPUT AT P.I. LEVEL, OR -1 IF NONE +IMPOPI: -1 ;IMSOC INDEX ACTIVE FOR OUTPUT AT P.I. LEVEL, OR -1 IF NONE +IMOB0Z: 0 ;IMSMPP AT IMOBD1, FOR DEBUGGING + +;IMP OUTPUT LIST. EXECUTED AT PI LEVEL 1. +;NEGATIVE = BLKO POINTER, 0=STOP, 1=SET LAST WORD, 2=32-BIT MODE, 3=NOP +IMOPNT: 0 ;INDEX OF NEXT "INSTRUCTION" IN IMP OUTPUT LIST: +IMOLST: 0 ;BLKO FOR SECOND THROUGH SIXTH LEADER WORDS (FIRST IS DATAO'ED) +IMOMOD: 2 ;SWITCH TO 32-BIT MODE IF NECESSARY +IMOBK1: 0 ;FIRST BLKO POINTER +IMOBK2: 0 ;SECOND BLKO POINTER + 1 ;SET LAST WORD +IMOBK3: 0 ;THIRD BLKO POINTER (SEND LAST WORD, NOT USED WITH DM INTERFACE) + 0 ;STOP +IMOLDR: BLOCK 6 ;BUILD PREAMBLE HERE FOR DATA MESSAGES + +IMPNEA: 0 ;NUMBER OF ECOS IN COMMAND MESSAGE THAT HAVE BEEN ANSWERED +IMPNRA: 0 ;NUMBER OF RSTS ANSWERED + +;METERS +IFN INETP,[ +IMNIPI: 0 ; # of IP datagrams input (rcvd) +IMNIPF: 0 ; # of IP datagrams flushed (input threw away) +IMNIPO: 0 ; # of IP datagrams output (sent) +IMNIPR: 0 ; # of IP RFNMs received +IMNIP7: 0 ; # of IP Type 7 (Dest Host Dead) messages received +IMNIP8: 0 ; # of IP Type 8 (Error) msgs rcvd +IMNIP9: 0 ; # of IP Type 9 (Incomplete Transmission) msgs rcvd +IMNWIG: 0 ; # words ignored by "Ignore" state (%ISIGN) +IMNWIF: 0 ; # words flushed by IMPRM5 +] ;INETP +IFN NCPP,[ +IMNOSH: 0 ;# OF SHUFFLES OF NET OUTPUT BUFFERS +IMNISH: 0 ;# OF SHUFFLES OF NET INPUT BUFFERS +IMNSCM: 0 ;NUMBER OF SHORT CONTROL LINK MESSAGES +IMPNEI: 0 ;NUMBER OF ERPS NOT SENT +IMPNRI: 0 ;NUMBER OF RRPS NOT SENT +IMNRFC: 0 ;NUMBER OF RFCS CLSED +IMNRFI: 0 ;NUMBER OF RFCS IGNORED +IMNCLI: 0 ;NUMBER OF CLS IGNORED +IMNALI: 0 ;NUMBER OF ALLS IGNORED +IMNPIL: 0 ;NUMBER OF TIMES PI CONTROL QUEUE EXCEEDED +IMNCNS: 0 ;NUMBER OF CLS NOT SENT +IMNANS: 0 ;NUMBER OF ALLS NOT SENT +IMNMNC: 0 ;NUMBER OF REGULAR MESSAGES FOR NON-EXISTANT CONNECTIONS +IMNMAE: 0 ;NUMBER OF TIMES MSG ALL EXCEEDED +IMNMSS: 0 ;NUMBER OF TIMES MSG SHORT +IMNBAE: 0 ;NUMBER OF TIMES BIT ALL EXCEEDED +] ;IFN NCPP +IMPNPE: 0 ;NUMBER OF PROTOCOL ERRORS +IMNSRC: 0 ;NUMBER OF SPURIOUS RFNMS ON CONTROL LINK +IMNSRF: 0 ;NUMBER OF SPURIOUS RFNMS ON REG CONNECTIONS +IMNRFN: 0 ;NUMBER OF RFNMS NOT SENT +IMSTAS: 0 ;STATUS OF INPUT AT TIME HELD UP +IMPNIH: 0 ;NUMBER OF TIMES INPUT SUCCESSFULLY HELD UP +IMPNUH: 0 ;NUMBER OF TIMES INPUT HOLDUP UNDONE +IMRFTO==60.*30. ;RFNM WAIT TIME OUT +IFN NCPP,[ +IMNORH: 0 ;NUMBER OF STYNET OUTPUT RESETS DELAYED +;IMPRTO==30.*60. ;RESET TIME OUT (IDENTICALLY = IMRFTO) +IMPCTO==30.*30. ;CLS TIME OUT +IMFCTO==55.*30. ;RFC QUEUE TIME OUT - SHOULD BE LESS THAN 2*IMPCTO +IMPCMR: BLOCK 20 ;COUNT OF CONTROL MESSAGES RCD +IMPCMS: BLOCK 20 ;COUNT OF CTL MSG SENT +] ;IFN NCPP +IMPMSR: BLOCK 20 ;COUNT OF IMP MESSAGES RCD +IMPM1S: BLOCK 4 ; # Type 1 (Error in Leader) subtype msgs +IMPM9S: BLOCK 20 ; # Type 9 (Incomplete Transmission) subtype msgs +IMPMSS: BLOCK 1 ;COUNT OF IMP MSG SENT (WE ONLY SEND REGULAR MSGS) +IMCT1: 0 ;# TIMES AT IMPBKZ +IMCT2: 0 ;# TIMES AT IMPIBZ +IMCT3: 0 ;# TIMES AT IMPOBZ +BBLK + +SUBTTL ARPANET MAIN-PROGRAM LEVEL + +IMPINI: +IFN KAIMP,[ + CONO IMP,IMI32C + DATAI IMP,A + CONO IMP,IMPODC ;CLEAR OUTPUT DONE AND PIA + CONSZ IMP,IMPOD+7 ;CHECK OUTPUT DONE, PIA, CAUSE HOST READY + JRST 4,. ;CONO DIDN'T CLEAR SOME BITS? + CONO IMP,IMPIR+IMPHEC ;CLEAR HOST ERR, ENABLE INT ON IMP READY +] +IFN DMIMP,[ + CONO FI,FIRSET ;RESET IMP INTERFACE, SET HOST READY + CONO FI,FIHSTS +] + SETOM IMPIPI + SETOM IMPOPI + MOVE T,TIME + ADDI T,15. + CAMLE T,TIME + PUSHJ P,UFLS ;WAIT FOR HALF SECOND +IFN KAIMP,[ + CONO IMP,0 ;CLEAR "ENABLE IMP READY" INT (TURNS OFF IMP ERROR) + MOVEI A,NETCHN ;IDLE PIA + MOVEM A,IMPPIA + MOVE A,[JSR IMPIBK] + MOVEM A,IMPILC + MOVE A,[JSR IMPOBK] + MOVEM A,IMPOLC +] +IFN DMIMP,CONO FI,FIIWDC ;CLEAR "IMP WAS DOWN" +IFN NCPP,[ + MOVSI I,-IMPSTL +IMPINA: SKIPE IMSOC6(I) + JRST 4,. + SETZM IMSOC1(I) + AOBJN I,IMPINA +] ;IFN NCPP + SETZM IMPILC+1 + SETZM IMPOLC+1 + SETOM IMPOAC + SETOM IMPUP ;NOT UP YET + MOVNI A,20. ;ALLOW 10 SECONDS TO COME UP + MOVEM A,IMPUCT + SETOM IMPTCU ;TRYING TO COME UP + SETOM IMPHTF ;WILL GC IMPHTB ON FIRST REFERENCE +IFN NCPP,[ + SETOM IMPMPU + SETOM IMPMPL + SETOM IMPNCQ + SETOM IMPLCQ + MOVEI I,IMNPIC + MOVEM I,IMFCQL + MOVEI A,IMPCQ + MOVEM A,IMFFCQ + JRST IMPIN1 + +IMPIN2: ADDI A,IMPMQS+1 + MOVEM A,-IMPMQS-1(A) +IMPIN1: SOJG I,IMPIN2 + SETOM (A) + SETOM IMPBPQ + SETOM IMPEPQ + MOVEI A,IMPPQ + MOVEM A,IMFFPQ + MOVEI I,IMNPQ + JRST IMPIN4 + +IMPIN3: ADDI A,4 + MOVEM A,-4(A) +IMPIN4: SOJG I,IMPIN3 + SETOM (A) + MOVEI A,NETSRS + MOVEM A,NRSOC +];NCPP + MOVE A,[IMPN,,IMPN+1] + SETZM IMPN + BLT A,LIMPN + SETOM IMPIS ; Say IMP shut off + MOVE T,TIME + MOVEM T,LNETIM +IFN KAIMP,CONO IMP,NETCHN +IFN DMIMP,[ + CONSZ FI,FIDOWN+FIWASD ;SKIP IF STILL UP + POPJ P, ;LOSE IF NOT IMP UP + CONO FI,FIIN\FIIBSY+NETCHN*11 + CONO FI,FIOUT+NETCHN*11 +] + SETOM IMPDWN+1 ;TIME FOR IMP TO GO DOWN, NOT KNOWN + ;MOVE T,TIME + ADDI T,15. + CAMLE T,TIME + PUSHJ P,UFLS + SETZM IMPIS ; Say up but idle + MOVNI A,4 + MOVEM A,IMNOPC ;SEND 4 NOPS +IMPOST: CONO PI,NETOFF +IFN DMIMP,[ + CONSO FI,70 ;SKIP IF PIA NON-ZERO + JRST NETONJ ;IF NO PIA, THEN DONT SET INT +] +IFN KAIMP,MOVE TT,IMPPIA ;MAIN PROGRAM OUTPUT START + AOSN IMPOAC ;SKIP IF OUTPUT ALREADY ACTIVE +IFN KAIMP, CONO IMP,IMPODS(TT) ;GENERATE OUTPUT INTERRUPT +IFN DMIMP, CONO FI,FIODS+NETCHN*11 + JRST NETONJ + +IMPIOS: +IFN KAIMP,[ + AOSE IMPOAC ;PI LEVEL OUTPUT START + POPJ P, + PUSH P,TT + CONO PI,400 ;TURN PI OFF, IMP MAY HAVE PIA = 1 + MOVE TT,IMPPIA + CONO IMP,IMPODS(TT) + CONO PI,200 + POP P,TT +]IFN DMIMP,[ + AOSN IMPOAC + CONO FI,FIODS+NETCHN*11 +] + POPJ P, + + + +;Check if IMP ready line is set +; Called from SYSJOB. +; Return +1 if IMP not ready, +2 if so +; +IMPCKR: +IFN DMIMP,[ + .ERR IMPCKR Missing for DMIMP! +] +IFN KAIMP,[ + CONSZ IMP,IMPR ;Skip if IMP not ready + AOS (P) ;Return +2 if ready + POPJ P, +] + + +SUBTTL HOST-TABLE MANAGEMENT + +; FNDHST - Look up host-table index for a given IMP host address. +; Call with NETOFF or NETCHN PI in progress. +; T/ IMP host address (maybe someday other nets?) +; Returns .+1 if failed (no room in table) +; Returns .+2 +; H/ host-table index +; Smashes W. + +FNDHST: MOVEI H,LIMPHT-1 ;SEARCH FOR AN ENTRY FOR THIS HOST + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,POPJ1 ;FOUND + SKIPGE H,IMPHTF ;NOT FOUND, CONS ONE OFF FREE LIST + JRST FNDHS1 ;OOPS, MUST GARBAGE COLLECT + MOVE W,IMPHTB(H) +IFN INETP,[ ; Later make this check standard! + CAIGE H,LIMPHT ; Make sure H is valid idx + CAIL W,LIMPHT ; ditto W + BUG HALT,[NET: FNDHST idx clobbered!!!] +] + MOVEM W,IMPHTF + MOVEM T,IMPHTN(H) + SETZM IMPHTB(H) ;NOTHING IS KNOWN ABOUT THIS HOST + SETZM IMPHTC(H) ; Assume no RFNMs outstanding + SETZM IMPHTT(H) ; Clear out time of last RFNM. + JRST POPJ1 + +; Host-Table full, attempt to GC it and flush unused entries, by +; scanning all possible pointers into table. +; IMP pointers are IMPCSH and IMPHTC(H) +; NCP pointers are IMSOC4<3.9-4.7>, RFC queue, PI ctl msg queue, +; and the RFNM-wait and RST-sent bits in table. +; TCP pointers are XBNADR(I) + + ; GC mark phase - mark entries in use +FNDHS1: PUSH P,I + MOVSI W,200000 ;MARK BIT + MOVEI H,LIMPHT-1 ;CLEAR ALL MARK BITS + ANDCAM W,IMPHTB(H) + SOJGE H,.-1 + SKIPL H,IMPCSH ;MARK FROM IMPCSH + IORM W,IMPHTB(H) + +IFN TCPP,[ + MOVEI I,XBL-1 + SKIPL H,XBNADR(I) ; See if TCP conn has a net addr specified + IORM W,IMPHTB(H) ; Yes, set the mark bit. + SOJGE I,.-2 +] ;IFN TCPP +IFN NCPP,[ + MOVEI I,IMPSTL-1 ;MARK FROM IMSOC4 +FNDHS2: SKIPN IMSOC1(I) ;SKIP IF IMSOC4 IS BEING USED BY ANYONE + SOJGE I,FNDHS2 + JUMPL I,FNDHS3 + LDB H,IMSCFH + CAIE H,377 + IORM W,IMPHTB(H) + SOJGE I,FNDHS2 +FNDHS3: MOVE I,IMPBPQ ;MARK RFC PENDING QUEUE + JUMPGE I,[ LDB H,[101000,,3(I)] + IORM W,IMPHTB(H) + MOVE I,(I) + JRST . ] + MOVE I,IMPNCQ ;MARK CONTROL QUEUE + JUMPGE I,[ HLRZ H,1(I) + IORM W,IMPHTB(H) + MOVE I,(I) + JRST . ] +] ;NCPP + + ; GC sweep phase - free all unmarked entries + SETO I, ;FREE POINTER + MOVEI H,LIMPHT-1 + MOVSI W,601000 ;PROTECT IF RFNM-WAIT, RST-WAIT, OR MARKED +FNDHS4: + SKIPG IMPHTC(H) ; Also protect if any outstanding RFNMs + TDNE W,IMPHTB(H) + SOJGE H,FNDHS4 + JUMPL H,FNDHS5 + SETZM IMPHTN(H) ;DON'T BELONG TO ANY HOST + MOVEM I,IMPHTB(H) ;CONS ONTO FREE LIST + MOVE I,H + SOJGE H,FNDHS4 +FNDHS5: MOVEM I,IMPHTF ;FREE LIST + POP P,I + SKIPGE IMPHTF + POPJ P, ;GC-OVERFLOW + JRST FNDHST ;TRY AGAIN, SHOULD WIN + +SUBTTL ARPANET INPUT INTERRUPT LEVEL + +COMMENT | + The IMP interrupt level structure is fairly complicated and +deserves some explanation. Because the IMP interface is not a DMA +device, all I/O is done "by hand", a word at a time; for this reason +all I/O is done at PI level IMPCHN=1 (the highest) whenever possible. +However, to prevent general IMP processing from taking complete +precedence over everything else, all non-I/O handling is done at +PI level NETCHN=2, which is the same level as disk devices. + The MIT-DMS interface (DMIMP) is much more complicated than the +AI-KA/ML/MC interface and was designed to facilitate this dual-level +interrupt processing by providing different PI channel assignments +for each of 3 possible conditions: + Input Done (must usually read next word) + Output Done (must usually output next word) + Control Int (some unusual condition, including Last-IMP-Word) + +Because the non-DM interface only has one PI assignment available, +the software to switch levels is much more complicated. For either +case, the code will not make sense unless you understand the channel 1 +multiplexing feature (see interface CONI bit descriptions). +| + +; Here when IMP interface is interrupting at PI level 2 (NETCHN) +; TT has CONI bits. Can clobber most ACs + +IMPINT: +IFN KAIMP,[ + AOSN IMPB ; PI 1 control interrupt? + JRST IMPBKZ ; Yes + AOSN IMPI ; PI 1 Input Done interrupt? + JRST IMPIBZ ; Yes + AOSN IMPO ; PI 1 Output Done interrupt? + JRST IMPOBZ ; Yes already + TRNE TT,IMPLW+IMPHER+IMPERR ; No PI 1 ints, check status bits + JRST IMPBKZ ; PI 2 Control interrupt (error or Last Imp Word) + TRNE TT,IMPID + JRST IMPIBZ ; PI 2 Input Done + TRNE TT,IMPOD + JRST IMPOBZ ; PI 2 Output Done +]IFN DMIMP,[ + TRNE TT,FILW+FIWASD+FIDOWN + JRST IMPBKZ ; PI 2 Control interrupt (error or Last Imp Word) + TRNE TT,FIID + JRST IMPIBZ ; PI 2 Input Done + TRNE TT,FIOD + JRST IMPOBZ ; PI 2 Output Done +] + JRST 4,. ; Must be one of above!! + +IFN KAIMP,[ +; IMPIBK - Default PI 1 Input Done routine, called from IMPILC. +; We're idling, switch to PI 2 to handle the input +; (normally 1st word of new IMP message) +EBLK +IMPIBK: 0 +BBLK + SETOM IMPI ; Set flag saying PI 1 Input Int seen + CONO IMP,NETCHN ; Switch PIA to 2 + JRST 12,@IMPIBK ; Go re-interrupt, will get to IMPINT->IMPIBK +] + +IFN KAIMP,[ + +; IMPBRK - PI 1 Control interrupt, called from PI0LOC+2 (= 42 on KA's) +; which is the standard PI 1 vector location. +; Again, switch to PI 2 to handle the condition +; (typically Last Imp Word seen on input) +EBLK +IMPBRK: 0 ; This interrupt is to 42, may not be the IMP +BBLK + CONSO IMP,IMPLW+IMPHER+IMPERR ; This really from the IMP? +IFE NEWDTP,JRST RC1INT +IFN NEWDTP,JRST IMPBR1 + SETOM IMPB ; Yes, re-interrupt and handle at NETCHN level + CONO IMP,NETCHN ; Switch PIA to 2 (NETCHN) + JRST 12,@IMPBRK ; Go re-interrupt, will get to IMPINT->IMPBKZ + +IFN NEWDTP,[ +IMPBR1: CONSZ DTC,70 ; Allow for non-IMP interrupt on PI chan 1 + JRST 12,@IMPBRK +] + +RC1INT: MOVEM 17,R1NTAC+17 + MOVEI 17,R1NTAC + BLT 17,R1NTAC+16 + MOVEI J,1 + JSP E,SPUR + MOVSI 17,R1NTAC + BLT 17,17 + JRST 12,@IMPBRK +];IFN KAIMP + +; IMPRM4 - PI 1 Input-Done handler during readin of IMP data (not leader) +; BLKI has run out but haven't yet gotten Last Imp Word! +; Either read more (if 2nd ptr specifed) or ignore following data. +EBLK +IMPRM4: 0 +BBLK + MOVEM A,IMPA ; Save A + SKIPL A,IMNWSI ; Second BLKI pointer exists? + JRST IMPRM6 ; Nope, none now + MOVEM A,IMBLKI ; Yes, store it! + SETZM IMNWSI ; Clear this flag so don't do it again + MOVE A,IMPA ; Restore A + JRST 12,@IMPRM4 ; Return, continuing BLKI. + +IMPRM6: MOVE A,[JSR IMPRM5] ; Ugh! Ignore additional input + MOVEM A,IMPILC ; Set up new vector to "ignore" routine + MOVE A,IMPA + JRST 12,@IMPRM4 + +; IMPRM5 - PI 1 Input-Done handler while ignoring IMP data, only +; set up by IMPRM6 above. +; Just reads a word and ignores it. This loop is broken +; by a control interrupt when Last-Imp-Word is seen. +EBLK +IMPRM5: 0 ; Hmm? Flush input at PI 1 +BBLK + DATAI IMP,IMPA +IFN INETP,AOS IMNWIF ; See how often we come here. + JRST 12,@IMPRM5 + +; IMPIBZ - PI 2 (NETCHN) "Input Done" interrupt, via IMPINT. +; Note there is one input word waiting in the IMP interface, +; but it is NOT the last IMP word (if it was, we would get a +; control interrupt and go to IMPBKZ instead). This situation +; should only happen while reading the IMP leader and there is +; more input than just the leader, i.e. it is a NCP or IP message. +; This is also where we come after being in idle state. +; TT/ IMP CONI word + +IMPIBZ: AOS IMCT2 +IFN DMIMP,[ + TRC TT,IMPCHN ;FIND IF INPUT PIA=IMPCHN + TRNN TT,7 + JRST IMPRET ;YES, ALREADY HANDLED BY IMPCHN +];DMIMP +IFE INETP,[ ; Note IP datagram is read in 32-bit mode! +IFN DMIMP,TLNE TT,FII32 +IFN KAIMP,TRNE TT,IMPI32 + JRST 4,. ; NCP-only, leader should always be read in 36-bit mode +] ;IFE INETP + MOVE C,IMPHI + SKIPN B,IMPIS ; Skip hold-up check unless at start of msg (idle) + AOJE C,IMPBKW ; Jump if input needs to be held up (can only do at start or end of msg) +IFE INETP,CAILE B,%ISIML +IFN INETP,CAILE B,%ISIID + JRST 4,. ; Unknown input state + JRST @.+2(B) ; Dispatch, note data not read yet + + IMPIGN ;-1 Supposed to be shut off, go ignore message. + OFFSET -. + %ISIDL:: IMSTR1 ; 0 Was idle, this is start of a message! + %ISIGN:: IMPIGN ; 1 Ignoring this message. +IFE INETP,%ISIML:: IMPLD2 ; 2 Reading IMP leader, see what we got. +IFN INETP,[ + %ISIML:: [JRST 4,.] ; 2 Should only see %ISINL or %ISIIL + %ISINC:: [JRST 4,.] ; 3 Was reading control msg! Runout is error. + %ISIND:: [JRST 4,.] ; 4 Was reading NCP data msg! Runout is error. + %ISINL:: IMPLD2 ; 5 Was reading NCP IMP leader + %ISIIL:: IMPLD2 ; 6 Was reading IP IMP leader. + %ISIID:: [JRST 4,.] ; 7 Was reading IP datagram! Runout is error. +] ;INETP + OFFSET 0 + +IMPIGN: DATAI IMP,A ; Ignore input (only come here via table above) +IFN INETP,AOS IMNWIG ; See how often we come here. + ;JRST IMPRET + + ; All routines dispatched to from IMPIBZ should return via IMPRET. +IMPRET: +IFN DMIMP,CONI FI,A + SKIPN IMPIS ; Skip if input not in normal (idle) state +IFN KAIMP, CONSO IMP,IMPI32 ; It is, see if input is in 32-bit mode +IFN DMIMP, TLNN A,FII32 + JRST .+2 + JRST 4,. ; Shouldn't be in 32 bit mode in normal state +IFN KAIMP,CONO IMP,@IMPPIA ; Switch to desired exit PIA + JRST IMPEX + +; IMPBKZ - PI 2 (NETCHN) Control interrupt, via IMPINT. +; Error or Last Imp Word on input. +; TT/ IMP CONI word + +IMPBKZ: AOS IMCT1 ; Bump count of control interrupts +IFN KAIMP,TRNE TT,IMPERR+IMPHER ; See if error or last-imp-word. +IFN DMIMP,TRNE TT,FIWASD+FIDOWN + JRST IMPBER ; Jump if IMP Error or Host Error + + ; Not an error, interface has Last Imp Word ready for DATAI'ing! + MOVE B,IMPHI ; Check here to see if input should be held up + AOJN B,IMPBKX ; Jump if not. + + ; Input must be held up. Also enter here from IMPIBZ if + ; at start of message (only other time input can be held up). +IMPBKW: +IFN KAIMP,CONO IMP,IMPIDC ; Clear Input Done so we don't re-interrupt +IFN DMIMP,[ + CONO FI,FISUSP ; Suspend input, no bits accepted after DATAI + DATAI FI,IMPSUS ; Have to read word now + CONO FI,FIIDC+NETCHN_3 ; Have to do this to clear IMP Last Word +] ; (also to clear Input-Done PIA) + SOS IMPHI ; Set -2 to indicate successfully held up + MOVEM TT,IMSTAS ; Save status (CONI bits) + AOS IMPNIH ; Bump meter - count of times input was held up. + JRST IMPRET + +; IMPBKX - Auxiliary to IMPBKZ, PI 2 Control Interrupt +; Have got Last Imp Word and not holding up input, so go +; handle end of IMP message. + +IMPBKX: +IFN KAIMP,[ + MOVE A,[JSR IMPIBK] ; Get rid of input BLKI + MOVEM A,IMPILC ; Replace with default switch-PIA vector + SETZM IMPIH ; Say don't need PI 1 for input any more. + MOVEI A,NETCHN ; And change exit PIA to 2 + SKIPL IMPOH ; Unless output side still needs PI 1. + MOVEM A,IMPPIA ; Set value of PI level desired on exit. + CONO IMP,IMI32C ; Put back in 36 bit mode to start next msg + DATAI IMP,A ; Get the last input word for processing +]IFN DMIMP,[ + CONO FI,FII32C+FISUSP ; Hold up bits for following clear + DATAI FI,A ; Get last input word + CONO FI,FIIDC+FIIBSY+NETCHN*11 ; Now clear Last-Imp-Word +] + ; Enter here from IMOB6 if input had been held up. +IMPBKV: SKIPGE B,IMPIS ; Unless network has been shut off + JRST IMPRET ; (in which case ignore input) + JRST @IMSDT2(B) ; then go process end of IMP message. + +IMSDT2: OFFSET -. + %ISIDL:: IMPBKN ; 0 Was idle - leader only 1 word long?? + %ISIGN:: IMPIRT ; 1 Ignore input + %ISIML:: IMPLD1 ; 2 End of IMP leader - can't be regular msg + %ISINC:: IMPBK3 ; 3 End of NCP control message + %ISIND:: IMPRMB ; 4 End of NCP data input +IFN INETP,[ + %ISINL:: IMPLD1 ; 5 End of NCP IMP leader?? Probably error. + %ISIIL:: IMPLD1 ; 6 End of IP IMP leader?? Probably error. + %ISIID:: IMPRMI ; 7 End of IP datagram +] ;INETP + OFFSET 0 + +; Here from table above for old-type leader (1 word) +; IMPBN1 is used by IMPLD2 if long leader has wrong format. + +IMPBKN: MOVEM A,IMPILB ; Store first (and only) word of leader +IMPBN1: LDB A,IMOTBP ; Get message format type + CAIN A,4 ; Old-type NOP? + JRST IMPIRT ; Just ignore it. + CAIN A,16 ; Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE A,17 ; Is it not the long-leader format? + BUG INFO,[IMP: Old-type leader],OCT,IMPILB + JRST IMPIRT ; Ignore rest of message, if any + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; IMP LEADER READING/DISPATCH ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Code on this page handles the initial processing of +;;; IMP messages and dispatches to the appropriate +;;; routines for each message type. Only Type 0 ("Regular") +;;; messages carry Host-Host traffic. + +; Here from IMPIBZ only, to handle first word of an IMP message. +; (It's not the last word or IMPBKZ would complain about it) +; Set up a BLKI to get the rest of the leader. + +IMSTR1: DATAI IMP,A ; Get 1st word from interface + ; Entry point from IMPOB6 only to restart input from "held-up" state + ; First word already in A +IMSTRT: MOVEM A,IMPILB ; Store first word of leader + MOVEI C,%ISIML ; Set new state = reading rest of IMP leader +IFE INETP,MOVE B,[-4,,IMPILB] ; If not diverting IP, ask for it all. +IFN INETP,MOVE B,[-2,,IMPILB] ; Must vector IP, ask for max 36-bit wds + JRST IMPRM9 ; Go read the leader. + +; The code at IMPLD5 will switch to 32-bit mode at right place if +; the message turns out to be an IP datagram. Otherwise the message +; is either a NCP Host-Host message, or an IMP-to-Host note of some kind; +; both stay in 36-bit mode. + +; Here from IMPBKX only for a leader not followed by any data. +; Last word in A, IMPLW flag in TT. +IMPLD1: AOS B,IMBLKI ; Update pointer to buffer + MOVEM A,(B) ; and store last word in right place. + ; Fall through to handle what should be an IMP-Host note. + ; The IMPLW flag distinguishes this entry point from IMPLD2, + ; so we know there isn't a data word in the interface. + +; Here from IMPIBZ only, for an IMP leader with more data following; +; almost certainly a "Regular" host-host message. The 2 possible +; states are: +; %ISINL - NCP, in 36-bit mode, have read 5 wds and 6th awaits. +; %ISIIL - IP, in 32-bit mode, have read 4 wds and 5th awaits. +; We can't DATAI the current word from the interface until we know +; what mode the remaining data should be read in. + +IMPLD2: +IFN KAIMP,TRNE TT,IMPI32 +IFN DMIMP,TLNE TT,FII32 +IFE INETP, JRST 4,. ; Input was in 32 bit mode when shouldn't! +IFN INETP,[JRST [MOVE B,IMPIS ; If reading IP IMP leader then 32 bit OK. + CAIE B,%ISIIL ; Leader read in 32-bit mode, must be IP. + JRST 4,. ; It isn't??? + JRST .+1] +] ;INETP + LDB T,IMOTBP ; Examine new-format flag bits of leader + CAIN A,16 ; Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE T,17 ; to verify that leader is "new" 96-bit fmt. + JRST IMPBN1 ; Something else?? Go discard. + HRRZ B,IMBLKI ;-> LAST WORD READ + CAIGE B,IMPILB+2 ;MUST BE AT LEAST 3 WORDS TO BE VALID + JRST IMPLD3 + LDB T,IMLNBP ; Extract link number (high 8 bits of msg-id) +IFN INETP,[ + CAMN T,IMPCLP ; HACK! If it matches our specified ctl link + SETZ T, ; number, then make it look like ctl link! +] + MOVEM T,IMPCLN + LDB T,IMSABP ; Get arpanet address (source host+imp) +IFN 0,[ LDB T,IMSHBP ;SOURCE HOST + LDB A,IMSIBP ;SOURCE IMP + DPB A,[112000,,T] ;FORM HOST ADDRESS +] ;ifn 0 + PUSHJ P,FNDHST ;H GETS HOST TABLE INDEX + JRST IMPLD9 ;HOST TABLE FULL + MOVEM H,IMPCSH ;SAVE CURRENT HOST + LDB A,IMTBP ;GET MESSAGE TYPE IN A + CAILE A,10. + JRST IMPUN ;UNKNOWN TYPE + AOS IMPMSR(A) ;COUNT IMP MSGS RCD + JRST @IMTDT(A) ;DISPATCH + +IMTDT: IMPRM ; 0 Regular Message + IMPBE1 ; 1 Error in Leader (no msg-id) + IMPGD ; 2 IMP Going Down + IMPUN ; 3 - + IMPIN ; 4 NOP + IMPRFN ; 5 RFNM - Ready For Next Message (transmit succeeded) + IMPHDS ; 6 Host Dead Status (general info) + IMPDHD ; 7 Destination Host Dead (transmit failed) + IMPBE8 ; 8 Error in Data (has msg-id) + IMPINC ; 9 Incomplete Transmission (transmit failed temporarily) + IMPIRS ;10 Interface Reset - IMP dropped its ready line + +IMPLD9: BUG INFO,[IMP: Message discarded due to host table full],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +; Here from IMPLD2 if leader is too short +IMPLD3: SUBI B,IMPILB-1 ;# WDS READ + BUG INFO,[IMP: Short leader, ],DEC,B,[wds. WD1=],OCT,IMPILB,[WD2=],OCT,IMPILB+1 + ;JRST IMPIRT ;FLUSH REST OF MESSAGE + +;;; IMP->Host Type 4 - NOP + +IMPIN: JRST IMPIRT ; One more nop from IMP + +;;; IMP->Host Type 10 - Interface Reset + +IMPIRS: BUG INFO,[IMP: Interface-reset msg] + JRST IMPIRT ; Probably nothing useful to do about it. + +;;; IMP->Host Type X (e.g. 3, 11-255) - bad type + +IMPUN: BUG INFO,[IMP: Unknown msg type ],OCT,A,[ leader ],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + ;JRST IMPIRT + +IFE NCPP,[ +IMPBK3:: ;Ignore NCP messages +IMPRMB:: +];NCPP + +; Here from all over, to flush rest of this message. +; All non-regular messages (not type 0) return here, as well as some +; errors with regular msgs. +; TT says whether there is any more data to read from this message. +IMPIRT: SETZM IMPIS ; Assume end of message, reset to normal state + TRNN TT,IMPLW ; But if we haven't yet read the last word, + AOSA IMPIS ; then change state to "Ignore" and flush input. + ; Note skip over following SETZM. + +; Regular messages (type 0) return here, when we already know this message +; was completely read. TT isn't valid. +IMPIR1: SETZM IMPIS ; Reset to normal idle state + SETOM IMPCSH ; Say no current host +IFN KAIMP,CONO IMP,IMI32C ; Put world back in 36 bit input mode +IFN DMIMP,CONO FI,FII32C+NETCHN*11 + JRST IMPRET + +;;; IMP->Host Type 0 - Regular Host-Host message +; Unless the source host screwed up and sent a dataless message, +; there is a word waiting to be read from the interface. +; For IP this is the 5th word and we are in 32-bit mode. +; For NCP it's the 6th (the NCP leader) and we're in 36-bit mode. +; TT/ IMP CONI bits, +; B/ addr of last wd input (counted-out BLKI pointer) + +IMPRM: TRNE TT,IMPLW + JRST IMPRM3 ; Foo, message shouldn't end so soon. Go barf. +IFE INETP,[ + CAIE B,IMPILB+4 ; Check that host-host leader word is next in + JRST IMPLD3 ; Barf + SKIPE IMPCLN ; Skip if link 0 - NCP control msg + JRST IMPRMD ; Data message, go read into user buffer. +] +IFN INETP,[ + SKIPN A,IMPCLN ; Skip unless NCP control link message + JRST IMPRM1 ; NCP control message, go handle it. + CAIE A,233 ; Is link number the magic cookie for IP? +IFN NCPP, JRST IMPRMD ; No, go handle as NCP data message. +IFE NCPP, JRST IMPIRT ; No, ignore it if we don't have NCP + + ; This is an Internet Protocol datagram. Make sure we are + ; in right mode for reading. + AOS IMNIPI ; Bump count of IP datagrams received +IFN KAIMP,TRNN TT,IMPI32 ; Should already be in 32-bit mode +IFN DMIMP,TLNN TT,FII32 + BUG PAUSE,[IMP: Reading IP dgm in 36-bit mode] + DATAI IMP,IMPILB+4 ; Okay, read in the padding and get going. + MOVEI A,%IMXLN ; Specify max size of IMP message + ; (we can't trust msg-len leader field) + PUSHJ P,IPGIPT ; Call IP module - get input buffer pointer + JRST [ AOS IMNIPF ; Punted, bump cnt of datagrams lost + JRST IMPIRT] ; Flush this message (err msg already printed) + MOVEM A,IMPIDP ; Save datagram pointer + MOVEM B,IMPIBS ; Save input BLKI pointer for later check + MOVEI C,%ISIID ; Set state = reading IP datagram + JRST IMPRM9 ; Go do it. + +IMPRM1: CAIE B,IMPILB+4 ; NCP control message, check that NCP leader is next + JRST IMPLD3 ; Barf, short message?? +] ;INETP +IFN KAIMP,CONO IMP,IMI32S ; NCP control message, set 32-bit mode +IFN DMIMP,CONO FI,FII32S+NETCHN*11 + DATAI IMP,IMPILB+5 ; Get NCP leader word + LDB A,IMCBBP + MOVEM A,IMPCBS ; Byte size + LDB B,IMBCBP + MOVEM B,IMPCBC ; Byte count + CAIN A,8 ; Byte size should be 8 for control link + CAILE B,120. ; Byte count shouldn't be > 120. + JRST IMPBCM + ADDI B,3 + LSH B,-2 ; Number of words necessary + MOVEM B,IMPNIW ; Number of input words expected + HRLOI B,-1(B) + EQVI B,IMPINB-1 ; BLKI pointer + MOVEI C,%ISINC ; New state = reading NCP control message + +; Set up BLKI. Pointer in B, state in C. +; This place is jumped to by several things that initiate IMP input, +; specifically IMSTRT, IMPRMT, and IMPRM. + +IMPRM9: MOVEM C,IMPIS + MOVEM B,IMBLKI + MOVE B,[BLKI IMP,IMBLKI] + MOVEM B,IMPILC + MOVE B,IMPBRO(C) ; Get BLKI runout instruction and set vector; + MOVEM B,IMPILC+1 ; will execute when ptr counts out. +IFN KAIMP,[ + SETOM IMPIH ; Say that input wants high pri + MOVEI B,IMPCHN ; And set our exit PIA to it (IMP) + MOVEM B,IMPPIA +] +IFN DMIMP,CONO FI,NETCHN_3+IMPCHN ; Set control PIA = NET, input done = IMP + + JRST IMPRET + + ; This table holds the instruction to execute after the input + ; BLKI has counted out the ptr and stored the current input word. + ; Note that if the IMP message ends during the BLKI, a control + ; interrupt will happen instead and control goes to IMPBKZ->IMPBKX + ; where there is another state dispatch table. + ; Normally only %ISIML and %ISINL actually use these instructions; + ; the other states are impossible or expect to read the entire + ; remaining message. +IMPBRO: OFFSET -. + %ISIDL:: JRST 4,IMPBRO ; 0 Idle - shouldn't be BLKI'ing. + %ISIGN:: JRST 4,IMPBRO+1 ; 1 Ignore - shouldn't be BLKI'ing. + %ISIML:: + IFE INETP,JSR IMPLD4 ; 2 Reading IMP leader (5 wds partial msg) + IFN INETP,JSR IMPLD5 ; 2 Reading IMP leader (4 wds partial msg) + %ISINC:: JSR IMPRM4 ; 3 Reading NCP control message (get all) + %ISIND:: JSR IMPRM4 ; 4 Reading NCP data (get all) +IFN INETP,[ + %ISINL:: JSR IMPLD4 ; 5 Reading NCP IMP leader (partial msg) + %ISIIL:: JSR IMPLD4 ; 6 Reading IP IMP leader (partial msg) + %ISIID:: JSR IMPRM4 ; 7 Reading IP datagram (get all) +] ;INETP + OFFSET 0 + +IMPRM3: LDB B,IMBCBP ;BYTE COUNT OF EMPTY CONTROL LINK MESSAGE + JUMPE B,IMPIRT + AOS IMPNPE ;NO TEXT BUT BYTE COUNT NOT ZERO + BUG INFO,[NCP: CTL MSG NO TXT, BC NOT 0. HST ],OCT,IMPHTN(H),[BC],DEC,B + JRST IMPIRT + +IFN INETP,[ +EBLK ; PI 1 Input Done interrupt (from IMPILC+1, runout) +IMPLD5: 0 ; JSR here on BLKI runout after reading 3rd wd of IMP leader. +BBLK ; Input Done is not set, because BLKI just turned it off. + MOVEM A,IMPILC ; Save A + MOVE A,[JSR IMPLD6] ; Make very next input word interrupt to IMPLD6 + EXCH A,IMPILC ; Do it, restore A + JRST 12,@IMPLD5 + +EBLK ; PI 1 Input Done interrupt (from IMPILC) +IMPLD6: 0 ; JSR here with 4th wd of leader in interface. +BBLK ; Must decide whether to continue reading leader in + ; 36-bit mode (NCP) or 32-bit mode (IP). + MOVEM A,IMPILC ; Save A + MOVE A,IMPILB+1 ; Get word with link number in it + ANDI A,377 ; Mask off + CAIN A,233 ; Internet Protocol "link"? + JRST IMPLI3 ; Yes! Go handle it. + + ; NCP read will immediately store current 36-bit word (4th), + ; store another 36-bit word (5th), and then run out to IMPLD4. + MOVE A,[-2,,IMPILB+2] ; Reading NCP message. + MOVEM A,IMBLKI + MOVEI A,%ISINL ; Reading NCP leader, set state thereto. + MOVEM A,IMPIS + MOVE A,[JSR IMPLD4] ; And change dispatch vector. + MOVEM A,IMPILC+1 + MOVE A,[BLKI IMP,IMBLKI] + EXCH A,IMPILC ; Set up BLKI and restore A + JRST 12,@IMPLD6 ; Return. Note current input word is still waiting. + + ; IP read will immediately store current 36-bit word (4th), + ; then set up so next input-done interrupt (on 5th, 32-bit word) + ; goes directly to IMPIBZ->IMPLD2 with NETCHN PI. + ; (For AI-KA/MC/ML, perhaps by way of IMPIBK if output is active) +IMPLI3: MOVEI A,%ISIIL ; Say reading IP type leader. + MOVEM A,IMPIS +IFN KAIMP,CONO IMP,IMI32S+IMPCHN ; Set further input to 32-bit mode +IFN DMIMP,CONO FI,FII32S+NETCHN_3+IMPCHN + DATAI IMP,IMPILB+3 ; Store the 4th 36-bit word immediately; this + ; also starts interface reading the 5th word. +IFN KAIMP,[ + MOVE A,IMPLD6 ; Now must set up for next interrupt. + MOVEM A,IMPLD4 ; Fake out the common code below + JRST IMPLI4 ; Set up for next Input-Done interrupt +] +IFN DMIMP,[ + MOVE A,[JSR IMPLD4] ; Shouldn't need this, but just in case... + EXCH A,IMPILC ; Restore A, set int vector to safe rtn + CONO FI,NETCHN*11 ; DM interface can simply set Input-Done PIA! + JRST 12,@IMPLD6 +] ;DMIMP +] ;INETP + +EBLK ; PI 1 Input Done interrupt (from IMPILC+1, runout) +IMPLD4: 0 ; JSR here on BLKI runout after reading IMP leader +BBLK ; There is still one word to go, to be gotten at NETCHN level +IFN KAIMP,[ + MOVEM A,IMPILC ; Save A + ; Drop through to common code + +IMPLI4: SETZM IMPIH ; Say input no longer needs PI 1 + MOVEI A,NETCHN ; Make PI 2 (NETCHN) the exit PIA, + SKIPL IMPOH ; unless output side needs PI 1. + MOVEM A,IMPPIA ; Set desired PIA channel on exit + CONO IMP,@IMPPIA ; Set PIA to whatever it was! + MOVE A,[JSR IMPIBK] ; Reset PI 1 Input-Done vector back to std. + EXCH A,IMPILC ; and restore A. +];DMIMP +IFN DMIMP, CONO FI,NETCHN*11 ; DM interface can simply set Input-Done PIA! + JRST 12,@IMPLD4 + +IMPBCM: BUG INFO,[NCP: CTL MSG BS NOT 8 OR CT>120. HST ],OCT,IMPHTN(H),[BS ],DEC,IMPCBS,[BC ],DEC,IMPCBC + JRST IMPIRT + +;;; IMP->Host Type 6 - Host Down Status +; H/ host index + +IMPHDS: MOVE A,IMPILB+1 ;1.8-1.1 AND 4.9-4.2 ARE THE INFO + MOVE B,IMPILB+2 + LSHC A,8 + ANDI A,177777 + HRRM A,IMPHTB(H) ;STORE, HOPE USER READ RFC 611 + JRST IMPIRT + +;;; IMP->Host Type 1 - Error in leader (msg-id not given) +;;; IMP->Host Type 8 - Error in data (msg-id given) + +IMPBE1: LDB T,IMSTBP ; Get subtype (4 bits) + ANDI T,3 ; Only 2 bits should be used + AOS IMPM1S(T) ; Increment count of Type 1 subtype messages +IMPBE8: MOVE T,TIME + SUB T,LNETIM + CAIL T,60. ;IGNORE ERROR DURING INITIAL SYNCHRONIZATION + BUG INFO,[IMP: Type ],DEC,A,[err msg, leader],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 +IFN INETP,[ + MOVE B,IMPCLN + CAIN B,233 + AOS IMNIP8 +] + CAIN A,8. + JRST IMPBEB ; Process "Error in data" (decrement RFNM wait cnt) + JRST IMPIRT + +IMPBER: SKIPGE IMPUP ;SKIP IF UP, OR THOUGHT TO BE BROKEN + JRST IMPBE2 ;ALREADY DOWN, LET IT COME UP IN PEACE + MOVSI J,SCLNET ;THINKS IT'S UP, RESET IT + IORM J,SUPCOR + CONI IMP,IMERCN ;RECORD IF IMP ERROR FLIP/FLOP SET + SETOM IMPUP ;IMP IS DOWN + SETZM IMPTCU ;AND NOT TRYING TO COME UP +IFN INETP,.ERR IP/TCP code needs handling for IMP crashing. +IFN NCPP,[ + MOVSI T,200000 ;CLEAR ALL BUFFERS ACTIVE AT PI LEVEL + MOVSI I,-IMPSTL ;SINCE CORE JOB MAY BE WAITING ON THIS + ANDCAM T,IMSOC6(I) + AOBJN I,.-1 +] ;NCPP +IMPBE2: +IFN KAIMP,[ + SETZM IMPPIA + CONO IMP,0 +] +IFN DMIMP,CONO FI,FIRSET + JRST IMPEX + +;;; IMP->Host Type 2 - IMP going down + +IMPGD: LDB B,[060200,,IMPILB+1] ;WHY + MOVEM B,IMPDWN + LDB B,[020400,,IMPILB+1] ;HOW SOON GOING DOWN * 5 MINS + MOVE H,B + IMULI B,5*60.*30. ;TICKS IN 5 MINS + ADD B,TIME + MOVEM B,IMPDWN+1 + MOVE C,IMPILB+1 ;HOW LONG TO BE DOWN, SPANS WORD BOUNDARY + MOVE D,IMPILB+2 + LSHC C,8 + ANDI C,1777 + MOVE Q,C + IMULI C,5*60.*30. + ADD C,B ;ADD TO TIME DOWN + MOVEM C,IMPDWN+2 ;STORE TIME WHEN WILL BE UP + IMULI H,5 ;MINUTES + IMULI Q,5 + BUG INFO,[IMP: Going down in ],DEC,H,[mins for ],DEC,Q,[mins, reason],DEC,IMPDWN + JRST IMPIRT + +;;; IMP Blockage avoidance +; The current IMP software will not accept more than 8 active +; messages to a single host; attempting to send a 9th message will block +; ALL output to the interface, until the first message has been ack'd +; by means of one of the following message types: +; Type 5, RFNM - Message delivered OK +; Type 7, Host dead - transmit failed ("permanent") +; Type 8, Error in data - interface spazzed +; Type 9, Incomplete Transmission - temporary failure +; If for some reason the first message simply becomes lost, the IMP timeout +; (and blockage) can last for up to 30-45 seconds. +; More details in BBN Report 1822. +; ITS attempts to fix this by keeping a count of active un-ACKed +; messages for each host it is communicating with. A timeout is also +; associated with each host; if output to a given host is blocked by ITS +; because there are 8 active messages, trying to send a 9th message +; will check the last-RFNM-received time and if this was more than +; 30 or so seconds then the IMP is probably not giving us what it should +; and we should reset things for that host. + +%IMPMA==:8. ; # of maximum active IMP messages allowed + +; IMPBLI, IMPBLD - routines to hack active-message counts, called via JSP T, +; IMPBLD decrements count. +; IMPBLI increments count and skips if successful (else failed, +; and must NOT output another message to this host!) +; Also clobbers Q. +IMPBLI: AOS Q,IMPHTC(H) + CAIGE Q,%IMPMA ; Trying to send max or more messages? + JRST 1(T) ; No, can return safely. + CAIG Q,8. ; Is this the maximum # allowed? + JRST [ MOVE Q,TIME ; Yes, set up blockage timeout + ADDI Q,60.*30. ; for one minute. + MOVEM Q,IMPHTT(H) + JRST 1(T)] + + ; Trying to send too many messages, block it (check for timeout though) + SOS IMPHTC(H) ; Restore original count + AOS IMNBLK ; Increment # of times softwarily blocked. + MOVE Q,IMPHTT(H) + CAML Q,TIME ; See if timeout still in the future + JRST (T) ; Yes, just take failure-return to block. + BUG INFO,[IMP: RFNM-wait timeout! Hst=],OCT,IMPHTN(H) + SETZM IMPHTC(H) ; This may be dangerous... oh well. + SETZM IMPHTT(H) + JRST (T) ; Block one last time, next try will win. + +IMPBLD: SOSL Q,IMPHTC(H) + JRST IMPBL2 + BUG INFO,[IMP: neg RFNM-wait cnt, Hst=],OCT,IMPHTN(H) + SETZB Q,IMPHTC(H) +IMPBL2: CAIL Q,8.-1 ; If we were blocking on this host, + CALL IMPIOS ; Ensure IMP output started up so blocked stuff + JRST (T) ; gets sent promptly. + +;;; IMP->Host Type 8 - Error in Data +; Actually this is secondary routine that IMPBE1 jumps to. + +IMPBEB: JSP T,IMPBLD ; Decrement count of active messages + JRST IMPIRT + + + +;;; IMP->Host Type 5 - RFNM (Ready For Next Message) + +IFN INETP,.ERR INETP needs handling for RFNM on link 233 +IMPRFN: +IFN BLIMPP,JSP T,IMPBLD ; Decrement count of active IMP messages for this host + SKIPE IMPCLN ;LINK NUMBER + JRST IMRFN1 ;DATA LINK +IMRFN6: SKIPL IMPHTB(H) + JRST IMRFN7 + SKIPN IMPHTN(H) + BUG HALT,[IMP: IMRFN6 sees free IMPHTB entry ],OCT,H + MOVSI D,400000 + ANDCAM D,IMPHTB(H) ;SET RFNM RECEIVED + SOS IMRFCT +IFN NCPP,[ + SKIPL IMPNCQ ;SKIP IF NO PENDING CONTROL-LINK OUTPUT + PUSHJ P,IMPIOS ;START OUTPUT +];NCPP + JRST IMPIRT + +IMRFN7: AOS IMNSRC + BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[LNK 0] + JRST IMPIRT + +; RFNM on non-zero link message +IMRFN1: +IFN INETP,[ + MOVE A,IMPCLN ; Get link # + CAIE A,233 ; IP link number? + JRST IMRFNX ; No, skip IP code + AOS IMNIPR ; Bump count of IP RFNMs received + JRST IMPIRT ; and do nothing else about it, ugh. +IMRFNX: +];INETP +IFN NCPP,[ + MOVE A,IMPCSH + LSH A,8 + IOR A,IMPCLN ;HEADER + MOVSI I,-IMPSTL + MOVEI W,1 +IMRFN2: LDB D,IMSCHL ;HEADER + SKIPGE IMSOC1(I) ;SKIP IF SLOT NOT IN USE + CAME A,D ;SKIP IF HEADER AGREES + JRST IMRFN3 + HRRZ J,IMSOC4(I) ;STATE + MOVEI W,0 + CAIN J,%NSRFN + SOJA J,IMRFN4 ;RFNM WAIT + MOVSI J,20000 ;MIGHT BE EXPECTING RFNM AFTER CLOSE + TDNE J,IMSOC5(I) + JRST [ ANDCAM J,IMSOC5(I) + JRST IMPIRT ] +IMRFN3: AOBJN I,IMRFN2 + BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN,SIXBIT,[(W)[SIXBIT/NOWAITNOLINK/]] +];NCPP +.ELSE BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN + AOS IMNSRF + JRST IMPIRT + +IFN NCPP,[ +IMRFN4: HRRM J,IMSOC4(I) ;CONNECTION OPEN + MOVSI J,30000 ;TURN OFF CLOSE-AWAITING-RFNM BIT, AND + ANDCAM J,IMSOC5(I) ; RFNM-TIMEOUT-DURING-CLOSE BIT + MOVE T,IMSPIP(I) + CAME T,IMSMPP(I) ;SKIP IF OUTPUT BUFFER EMPTY + PUSHJ P,IMPIOS ;START OUTPUT + JRST IMPIRT +];NCPP + + +;;; IMP->Host Type 9 - Incomplete Transmission + +IMPINC: LDB T,IMSTBP ; Get subtype field (4 bit reason for failure) + AOS IMPM9S(T) ; Bump count of subtypes + SKIPA E,[%NCINC] + +;;; IMP->Host Type 7 - Destination Host Dead + +IMPDHD: MOVEI E,%NCDED +IFN BLIMPP,JSP T,IMPBLD ; Decrement count of active IMP messages for this host +IFN INETP,[ + MOVE A,IMPCLN + CAIN A,233 + JRST [ CAIN E,%NCINC + AOS IMNIP9 + CAIN E,%NCDED + AOS IMNIP7 + JRST IMPIRT] ; Don't bother with NCP stuff or anything. +] + MOVSI C,1000 ;RST SENT? + TDNE C,IMPHTB(H) + SOS IMRFCT ;GOING TO CLEAR IT, DECREASE TIMEOUT RQ + MOVSI C,3000 + ANDCAM C,IMPHTB(H) ;CLEAR RST STATUS, RFNM SIMULATED LATER +IFN NCPP,[ + MOVSI I,-IMPSTL +IMDHD: LDB T,IMSCFH + SKIPGE C,IMSOC1(I) ;SKIP IF NOT IN USE + CAME T,IMPCSH + JRST IMDHDA + HRRZ T,IMSOC4(I) + TLNN C,200000 ;THIS GUY IS CLOSING ANYWAY + CAIG T,%NSLSN + JRST IMDHDA ;THIS SOCKET'S HOST NUMBER FIELD IS MEANINGLESS + CAIGE T,%NSCLI .SEE %NSINP + TDZA T,T .SEE %NSCLS + MOVEI T,%NSCLI + HRRM T,IMSOC4(I) + DPB E,IMSCLS ;CLS REASON + PUSHJ P,IMPUIN +IMDHDA: AOBJN I,IMDHD +];NCPP + JRST IMRFN6 ;CONTROL LINK, TAKE AS RFNM SO AS NOT TO HANG THINGS + +IFN INETP,[ +; IMPRMI - End of IP datagram, PI in progress on NETCHN, here from IMPBKX +; A/ Last IMP word (32-bit) +; TT/ CONI bits as of interrupt (note already returned to 36-bit mode) + +IMPRMI: AOS B,IMBLKI ; Get address to store last word in + MOVEM A,(B) ; Store it away + SUB B,IMPIBS ; Get # words read into datagram buffer + MOVEI B,(B) + MOVE A,IMPIDP ; Get pointer to IP datagram buffer we were using + SETZ C, ; Say zero offset to IP header. + MOVE J,IMPCSH ; Set index to host-table entry dgm received from. + PUSHJ P,IPRDGM ; Call IP module to process received datagram at PI lvl + SETZM IMPIDP ; Clear PI level pointer + JRST IMPIR1 ; Return from PI level, setting up for next msg + +] ;INETP + +SUBTTL ARPANET OUTPUT INTERRUPT LEVEL + +; See comments at IMPINT for a description of the overall IMP interrupt +; structure. Output is simpler than input, however. +; Each IMP message is output at PI level 1 except for the initial DATAO; +; the setup and takedown for each message is done at PI level 2. +; The code on this page is not referenced by anything outside the page +; except interrupt vector setup at IMPINI (to IMPOBK) and IMOB9 (to IMPCH1). + +; IMPCH1 - PI 1 Output-Done interrupt, from IMPOLC. +; Comes here when last word DATAO'd has been sent to IMP. +EBLK +IMPCH1: 0 +BBLK + MOVEM A,IMPOLC ; Save A + MOVE A,IMOPNT +IMCH1A: SKIPGE A,IMOLST(A) ; Get next "instruction" + JRST IMCH1B ; Jump if it's a BLKO pointer + CAILE A,3 ; Ensure valid operation + JRST 4,. + XCT IMCH1I(A) ; Do it + AOS A,IMOPNT ; Still here? Point to next operation + JRST IMCH1A ; and loop to do it. + +IMCH1I: JRST IMCH1C ;0 Stop - end of output list +IFN KAIMP,CONO IMP,IMPLHW+IMPCHN ;1 Set Last Word +IFN DMIMP,CONO FI,FILHW+11*NETCHN +IFN KAIMP,CONO IMP,IMO32S+IMPCHN ;2 Set 32-bit mode +IFN DMIMP,CONO FI,FIO32S+10*NETCHN+IMPCHN + JFCL ;3 NOP + +IMCH1B: MOVEM A,IMBLKO ; Set up BLKO - store the pointer + MOVE A,[JSR IMCH1D] ; Set dispatch for BLKO runout + MOVEM A,IMPOLC+1 + MOVE A,[BLKO IMP,IMBLKO] + EXCH A,IMPOLC ; Store the BLKO and restore A + AOS IMOPNT ; Increment output list ptr past this op. + JRST 12,@IMPCH1 ; Will interrupt immediately for first BLKO + ; word, since Output-Done wasn't cleared. + +; PI 1 Output-Done, from IMPOLC+1 (BLKO runout) +; Final word of the BLKO pointer is now in interface, being sent +; to IMP, and Output-Done flag is off. +EBLK +IMCH1D: 0 +BBLK + MOVEM A,IMPOLC + MOVE A,[JSR IMPCH1] ; Interrupt back when output of final word done + EXCH A,IMPOLC + JRST 12,@IMCH1D + +; Here from IMPCH1, PI 1 Output-Done interrupt +; Output list has hit "stop" operation (previous op had better be +; 1 to set Last-Host-Word!) +; This code reverts control back to PI level 2 (IMPOBK). +IMCH1C: +IFN DMIMP,[ + CONO FI,FIOUT+11*NETCHN ; Reset PIA to normal 2 + MOVE A,[JSR RINT1] ; and ensure any further output PI 1 ints +] ; are classified as spurious. + +IFN KAIMP,[ ; Non-DM interface needs more hair. + SETZM IMPOH ; Say output side doesn't need PI 1 anymore + MOVEI A,NETCHN ; And set exit PIA to 2, + SKIPL IMPIH ; unless input side still needs PI 1 + MOVEM A,IMPPIA ; Set it. + CONO IMP,NETCHN ; Shouldn't this be CONO IMP,@IMPPIA?? + SETOM IMPO ; Tell IMPINT we have output-done interrupt. + MOVE A,[JSR IMPOBK] ; Point PI 1 channel at switch-PIA routine, +] ; in case we interrupt on PI 1 again anyway. + EXCH A,IMPOLC + JRST 12,@IMPCH1 + +IFN KAIMP,[ + +; PI 1 Output Done interrupt, when we should really be interrupting +; at IMPINT on PI 2. +EBLK +IMPOBK: 0 +BBLK + SETOM IMPO ; Tell IMPINT what kind of interrupt + CONO IMP,NETCHN ; Reset PIA to 2 + JRST 12,@IMPOBK +] + +; IMPOBZ - PI 2 (NETCHN) "Output Done" interrupt, via IMPINT. +; Come here when we have finished sending stuff out at PI 1, +; also when something wants output to start and tickled the "Done" +; flag. +; TT/ IMP CONI word. + +IMPOBZ: AOS IMCT3 +IFN DMIMP,[ + TRC TT,IMPCHN_9 ;CHECK IF OUTPUT PIA=IMPCHN + TRNN TT,7_9 + JRST IMPRET ;IGNORE, ALREADY HANDLED BY IMPCHN +] + SKIPL B,IMPOS + CAIL B,IMPODL + JRST 4,. + JRST @IMPODT(B) + +IMPODT: OFFSET -. +%ISODL:: IMPOB1 ; 0 Idle, look for something to send +%ISONC:: IMPOB6 ; 1 Finished NCP control message +%ISOND:: IMPOBG ; 2 Finished NCP data message +IFN INETP,%ISOID::IMPOBI ; 3 Finished IP datagram messge +IMPODL::OFFSET 0 + +IFE NCPP,[ +IMPOB6: SETZM IMPOS + SKIPN A,IMPSVQ + JRST IMPRET ;THAT WAS A NOP +IMPOBG: JRST 4,. ;Can't get here +];not NCPP + +; Idle - Look for output to send. First ensure we can send stuff, +; then try things in the order: +; (1) Send NOP if net coming up +; (2) Check NCP control queue, then (3) NCP data output queue +; OR +; (2) Check IP datagram queue +; +; Note that we alternate between checking the NCP and IP queues first, +; so that neither protocol can totally wedge the other up even if +; going at full blst. + +IMPOB1: HRRZ T,IMPUP + CAIE T,-2 ; Don't say it's up when it's still going down + CAIN T,1 ; or when it is broken + JRST IMPOB9 + + ; First check to see if NOP needs to be sent. + AOSG IMNOPC ; Check to see if sending NOPs + JRST IMONOP ; Output a NOP + SETZM IMPUP ; Say IMP is up + SETZM IMPTCU ; Say no longer trying to come up + + ; Now see whether to check NCP or IP. +IFN INETP,[ + SETCMB T,IMPPSW ; Complement IMP output protocol switch + JUMPN T,IMOBNN ; Jump for NCP + PUSHJ P,IPGIOQ ; Check IP! Get IP IMP output queue entry if any + JRST IMOBN ; Nothing there, go check NCP. + ; Returns A/ ptr to IP dgm struct + ; B/ BLKO pointer to 32-bit words + ; C/ Arpanet address + ; The output list should be set up as: + ;IMOLST: -3,,IMOLDR + ;IMOMOD: 2 ; switch to 32-bit mode + ;IMOBK1: -1,,IMOLDR+3 ; Send 5th word of padding + ;IMOBK2:output BLKO ; Send datagram minus last word + ; 1 + ;IMOBK3: -1,,lstwd-1 ; BLKO to last word of datagram + ; 0 +IMOBI1: + MOVEM A,IMPODP ; Save ptr to datagram being output + AOS IMNIPO ; # of IP datagrams sent + ADD B,[1,,] ; Reduce BLKO count by one + MOVEM B,IMOBK2 ; Store in output list + HLRO D,B ; Get -<# wds-1> + MOVN D,D ; Get <#wds-1> + ADDI D,(B) ; Get addr for last-word BLKO + HRROM D,IMOBK3 ; Store -1,,lastwd-1 + MOVE B,[-3,,IMOLDR] + MOVEM B,IMOLST + MOVE B,[-1,,IMOLDR+3] + MOVEM B,IMOBK1 + + ; Output list set up, now must put together the IMP leader + ; in IMOLDR. + MOVE B,[17_10.,,0] ; Regular message + MOVEM B,IMOLDR + LSH C,8. ; Move net address over + IORI C,233 ; Get link # for IP + MOVEM C,IMOLDR+1 ; Store 2nd word + SETZM IMOLDR+2 ; 3rd word can be zero + SETZM IMOLDR+3 ; rest is padding + SETZM IMOLDR+4 ; ditto + +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;SET 36 BIT MODE FOR LEADER, CLEAR PIA + DATAO IMP,IMOLDR ; Start it going! + + MOVEI C,%ISOID ; State = outputting IP datagram. + JRST IMOB9 + +IMOBN: SKIPE IMPPSW ; If no IP, check NCP only if havent already + JRST IMOBI9 ; Skip NCP check, just return. +IMOBNN: +] ;INETP + +IFN NCPP,[ + ; Check NCP control message queue. +IFN BLIMPP,[ + MOVEI C,IMPNCQ +IMPOBV: SKIPGE A,(C) + JRST IMPOBW + HLRZ H,1(A) ; Got one! Go send NCP control msg, + SKIPL IMPHTB(H) ; unless control link waiting for RFNM + JSP T,IMPBLI ; or too many msgs active for that host. + CAIA + JRST [MOVEI T,(C) ? JRST IMPOB2] ; Compat hack + MOVEI C,(A) + JRST IMPOBV +] ;BLIMPP +.ELSE [ + MOVEI T,IMPNCQ +IMPOBV: SKIPGE A,(T) + JRST IMPOBW + HLRZ B,1(A) ;HOST TABLE INDEX + SKIPL IMPHTB(B) ;SKIP IF WAITING FOR RFNM + JRST IMPOB2 ; Got one! Go send NCP control message. + MOVE T,A + JRST IMPOBV +] ;IFE BLIMPP + + ; Check NCP data output queue. This simply runs through + ; all the sockets to see if any want to output something. +IMPOBW: MOVSI I,-IMPSTL + MOVEI W,1 +IMPOBB: SKIPGE IMSOC1(I) ;SKIP IF NOT IN USE + TDNN W,IMSOC2(I) ;SKIP IF SEND + JRST IMOBA9 + HRRZ A,IMSOC4(I) + CAIN A,%NSOPN ;SKIP IF WRONG STATE + SKIPGE IMSOC6(I) ;SKIP IF NOT LOCKED BY CORE JOB +IMOBA9: +IFE BLIMPP,IMPOBA: + AOBJN I,IMPOBB +IFN BLIMPP,[ + JUMPGE I,IMPOB9 + LDB H,IMSCFH ; Get fgn host index for this NCP conn + JSP T,IMPBLI ; Make sure not too many active msgs + JRST IMOBA9 ; Sigh, too many, keep looking. + JRST IMPOBD ; OK, can send! +IMPOBA: JSP T,IMPBLD ; Couldn't send data msg after all, decr cnt + JRST IMOBA9 +] +.ELSE JUMPL I,IMPOBD ; Got one! Go send NCP data message. +];NCPP + + ; No more NCP output for IMP. +IMPOB9: +IFN INETP,[ + SKIPN IMPPSW ; If we didnt check IP queue yet, + JRST IMOBI9 + PUSHJ P,IPGIOQ ; then do it now, after NCP check. + JRST IMOBI9 ; Nothing, really no more output. + JRST IMOBI1 ; Aha, have stuff! Go get it. +IMOBI9: +] + SETOM IMPOAC ; No more output, couldn't find anything to send. +IFN KAIMP,CONO IMP,IMPODC ; Clear Output-Done interrupt bit +IFN DMIMP,CONO FI,FIODC+NETCHN*11 + JRST IMPRET + + +; IMONOP - Send a NOP, here from IMPOBZ only. + +IMONOP: MOVEI A,IMPNOP-2 + SETZM IMPSVQ ; Set flag => this msg not really from control queue + MOVEI B,1 ; No text, but one extra wd (needed to make BLKO win) + JRST IMPOB3 + + ; NOP Host-IMP leader +IMPNOP: 17_10.,,4_4 ; New format, type 4 = NOP + 0 + 5_10.,,0 ; 5 16-bit words of padding desired + +; IMPOB2 - Send a NCP control message, from IMPOBZ only + +IMPOB2: HRL A,T + MOVEM A,IMPSVQ ;SAVE CTL MSG QUEUE PNTR + HRRE B,1(A) ;GET COUNT + JUMPG B,IMPOB3 + JRST 4,. ;ERROR, COUNT NOT > 0 +IMPOB3: ; Entry pt from NOP sending code +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;SET 36 BIT MODE FOR LEADER, CLEAR PIA + DATAO IMP,2(A) ;OUTPUT FIRST LEADER WORD + MOVEI C,2(A) ;SET UP BLKO POINTER FOR REST OF LEADER + SKIPN IMPSVQ + JRST [ HRLI C,-2 ;KLUDGE, SENDING NOP + JRST IMPOB4 ] + HRLI C,-5 + AOS IMPMSS+0 ;COUNT REGULAR MSGS SENT +IFN INETP,[ + MOVE T,IMPCLP ; HACK! Get specified # to use for ctl link + DPB T,[001000,,3(A)] ; Deposit in link field of leader. +];INETP +IFN NCPP,[ + LDB T,[341000,,10(A)] ;FIRST BYTE OF CONTROL MESSAGE + CAIGE T,20 + AOS IMPCMS(T) +];NCPP +IMPOB4: MOVEM C,IMOLST ;STORE BLKO POINTER THAT SENDS LEADER + MOVEI C,2 ;DO TEXT WORDS IN 32-BIT MODE + MOVEM C,IMOMOD +IFN DMIMP,MOVNI B,(B) ;GET MINUS WORD COUNT +IFN KAIMP,MOVNI B,-1(B) ;ALSO -1 FOR LAST WORD SENT SEPARATELY. + HRLI B,7(A) ;ADDR-1 FOR BLKO + MOVSM B,IMOBK1 ;STORE FOR PI 1 +IFN KAIMP,[ + MOVNI B,(B) + ADD B,IMOBK1 ;LAST WORD SENT SEPARATELY + HRROM B,IMOBK3 + MOVEI B,3 ;CHECK FOR SCREW CASE, ONLY SENDING ONE WORD, IT'S THE + SKIPL IMOBK1 ; LAST, SO NOP OUT THE MAIN BLKO + MOVEM B,IMOBK1 +] +.ELSE MOVEI B,3 + MOVEM B,IMOBK2 ;NO 2ND BLKO + MOVEI C,%ISONC ;STATE FOR CONTROL RETURN TO NETCHN +IMOB9: MOVEM C,IMPOS + SETZM IMOPNT + MOVE C,[JSR IMPCH1] + MOVEM C,IMPOLC +IFN KAIMP,[ + SETOM IMPOH ;OUTPUT SIDE WANTS IMP TO RUN ON CHANNEL 1 + MOVEI A,IMPCHN + MOVEM A,IMPPIA +] +IFN DMIMP,CONO FI,FIOUT+NETCHN_3+IMPCHN ;SET PIA FOR OUTPUT + JRST IMPRET + +IFN INETP,[ +; Here when IP datagram transmission completed + +IMPOBI: SETZM IMPOS ; Reset output state + MOVE A,IMPODP + PUSHJ P,IPIODN ; Tell IP level that datagram was output + SETZM IMPODP + JRST IMPRET +] ;INETP + +SUBTTL ARPANET CLOCK LEVEL + +OVHMTR IMP ;NETWORK INTERRUPT LEVEL (NOT STYNET STUFF) + +IMRSTO: SKIPN IMRFCT ;CALLED AT 15 SEC CLK LEVEL TO UNHANG RFNM WAITS +IFE NCPP,POPJ P, +IFN NCPP,JRST IMFCT1 + MOVEI H,LIMPHT-1 ;SOME CONTROL LINKS WAITING FOR RFNM, CHECK FOR TIME OUT + MOVSI TT,401000 ;4.9 AND 4.1 - RFNM AND RRP TIMEOUTS + TDNN TT,IMPHTB(H) +IMRS4: SOJGE H,.-1 +IFN NCPP,JUMPL H,IMFCT1 +IFE NCPP,JUMPL H,CPOPJ + CONO PI,NETOFF + SKIPE IMPHTN(H) ;MAKE SURE IT'S A REAL HOST, NOT A FREE ENTRY + TDNN TT,IMPHTB(H) ;AND THAT THE BITS DIDN'T TURN OFF DUE TO INTERRUPT + JRST IMRS1 + LDB E,[221100,,IMPHTB(H)] + LDB D,[051100,,TIME] ;GET TIME IN SECONDS (APPROX) + CAMLE E,D + ADDI D,1_9 + SUB D,E + CAIGE D,IMRFTO_<-5> + JRST IMRS1 ;HASN'T TIMED OUT YET. + LDB D,IMHSBT ;TIMED OUT. CHECK RST/RRP STATUS. + SOJE D,IMRS2 + MOVSI D,400000 + ANDCAM D,IMPHTB(H) ;RFNM SENT, CLEAR IT + AOS IMNRFN + SOS IMRFCT + BUG INFO,[NET: CTL LNK RFNM TIMEOUT HST],OCT,IMPHTN(H) +IMRS1: CONO PI,NETON + JRST IMRS4 + +IMRS2: DPB D,IMHSBT ;RST SENT, SET STATE TO DOWN + BUG INFO,[NET: RST TIMEOUT HST=],OCT,IMPHTN(H) + SOS IMRFCT + JRST IMRS1 + +;NETHST (HOST INFO) +; ARG 1 - HOST => VAL 1 - STATUS, VAL 2 - HOST NUMBER +; ARG 1 - -1 => VAL 1 - (STATUS), VAL 2 - OUR HOST NUMBER +;NOT CURRENTLY IMPLEMENTED- ARG 1 - -1, ARG 2 - OUR GOING-DOWN REASON + +ANETHST:HRRE T,A ;LET IMMEDIATE -1 WIN (777777 NOT A VALID HOST) + AOJE T,ANETH2 ;JUMP IF WANT LOCAL STATUS AND HOST NUMBER + MOVE T,A + JSP J,STDHST ;STANDARDIZE AND ERROR-CHECK HOST NUMBER + MOVE B,T ;RETURN NEW FORMAT ******* + TLO B,(NW%ARP) + MOVEI H,LIMPHT-1 + CONO PI,NETOFF ;DO WE HAVE STATUS? + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,ANETH1 ;YES, RETURN IT + CONO PI,NETON ;NO, HAVE TO GO GET IT + MOVEM T,SRN3(U) +IFN NCPP,[ + PUSHJ P,NETO00 ;GET IMSOC, RETURN WITH NETLST, IMSOC LOCKED + POPJ P, ;DEVICE FULL OR SOMETHING + PUSHJ P,NETOR ;OPEN COMMUNICATIONS WITH HOST + JFCL ;IT'S DOWN, THAT'S OK +];NCPP +.ELSE POPJ P, ;OH, TOO BAD +ANETH1: MOVE A,IMPHTB(H) ;GET STATUS + CONO PI,NETON + EXCH A,B + CALL CVH2NA ; Convert to HOSTS2 for compat + EXCH A,B + JRST LSWCJ1 ;RETURN IMSOC, NETLST IF NOT DONE ALREADY + +ANETH2: ;CAIL W,2 ;(THIS IS A CROCK) + ;MOVEM B,NTHDSW ;IF 2 ARGS, SET OUR REASON FOR GOING DOWN. + SKIPE IMPUP ;FAKE UP OUR STATUS + TDZA A,A ;WE'RE DOWN + MOVSI A,2000 ;WE ARE UP + MOVEI B,IMPUS ;AND OUR HOST #. + JRST POPJ1 + + +;NETIMP (REASON,TIMEDOWN,TIMEUP) READ/SET + +ANETIMP:JUMPLE W,ANETM1 ;NO ARGS, RETURN + CAIGE W,3 ;MUST HAVE 3 ARGS IF ANY + JRST OPNL30 + MOVEM A,IMPDWN + MOVEM B,IMPDWN+1 + MOVEM C,IMPDWN+2 + JRST POPJ1 + +ANETM1: MOVE A,IMPDWN + MOVE B,IMPDWN+1 + MOVE C,IMPDWN+2 + SKIPE IMPUP + TLO A,400000 + JRST POPJ1 diff --git a/src/system/inet.138 b/src/system/inet.138 new file mode 100755 index 00000000..026a7017 --- /dev/null +++ b/src/system/inet.138 @@ -0,0 +1,1430 @@ +;:;; -*- Mode:MIDAS -*- +; Insert new buffer stuff... +$INSRT TCPBUF + +IP%VER==740000,, ; 0 IP Version # (= 4) +IP%IHL==036000,, ; 0 IP Header Length in 32-bit wds - at least 5 +IP%TOS==001774,, ; 0 Type Of Service +IP%TOL==000003,,777760 ; 0 Total Length in octets (including header) +IP%ID== 777774,, ; 1 Identification +IP%FLG== 3,,400000 ; 1 Flags + IP%FDF== 1,,0 ; Don't-Fragment flag + IP%FMF== 400000 ; More-Fragments flag +IP%FRG== 0,,377760 ; 1 Fragment Offset +IP%TTL==776000,, ; 2 Time To Live +IP%PTC== 1774,, ; 2 Protocol +IP%CKS== 3,,777760 ; 2 Header Checksum +IP%SRC==777777,,777760 ; 3 Source Address +IP%DST==777777,,777760 ; 4 Destination Address + ; 5 Start of options +IP$VER==<.BP IP%VER,0> +IP$IHL==<.BP IP%IHL,0> +IP$TOS==<.BP IP%TOS,0> +IP$TOL==<.BP IP%TOL,0> +IP$ID== <.BP IP%ID, 1> +IP$FLG==<.BP IP%FLG,1> +IP$FRG==<.BP IP%FRG,1> +IP$TTL==<.BP IP%TTL,2> +IP$PTC==<.BP IP%PTC,2> + %PTCIC==:1 ; Protocol ICMP + %PTCTC==:6. ; Protocol TCP + %PTCUD==:17. ; Protocol UDP +IP$CKS==<.BP IP%CKS,2> +IP$SRC==<.BP IP%SRC,3> +IP$DST==<.BP IP%DST,4> + + ; UDP fields +UD$SRC==<242000,,0> ; 0 wd 1 Source port +UD$DST==<042000,,0> ; 0 wd 2 Dest port +UD$LEN==<242000,,1> ; 1 wd 1 # octets in data +UD$CKS==<042000,,1> ; 1 wd 2 UDP checksum +UD$DAT==<441000,,2> ; 2 Data - actually an ILDB pointer! + + ; ICMP fields +IC$TYP==<341000,,0> ; 0 Type of message +IC$COD==<241000,,0> ; 0 Code (subtype) +IC$CKS==<042000,,0> ; 0 ICMP Checksum +IC$GWA==<044000,,1> ; 1 Random arg, usually Gateway Addr +IC$IPH==2 ; 2 Random data, usually an IP header + +; Hack metering macro, since we'll want lots of 'em to start with. +; You know, MR% used to be MTR%, except that when %NMTRS is over 100 +; you get duplicated symbols, and since they used to be defined with +; == instead of ==: you didn't hear about it, either. + +%NMTRS==:140 ; Allow this many meters +DEFINE MTRCOD ; Put this macro someplace after last meter. +EBLK +MTRCNT: BLOCK %NMTRS ; Holds actual meter AOS'd +BBLK +MTRNAM: BLOCK %NMTRS ; Holds ,, + LOC MTRNAM + REPEAT %%%MTR,CONC MR%,\.RPCNT +IF2, REPEAT %%%MTR,CONC EXPUNGE MR%,\.RPCNT + LOC MTRNAM+%NMTRS + +TERMIN + +; METER - Must be used as in following example: +; METER("IP: # of bad cksums") +%%%MTR==0 +DEFINE METER &(NAME) +IFGE %%%MTR-%NMTRS,.ERR Too many meters! +AOS MTRCNT+%%%MTR +CONC MR%,\%%%MTR,==:<.,,[ASCIZ NAME]> +;CONC MR%,\%%%MTR,==:<.,,> +;IF1 SHOMTR %%%MTR,NAME +%%%MTR==%%%MTR+1 +TERMIN + +DEFINE SHOMTR #OFF#,&STR& +PRINTX /;;;;;;;; METER :::: MTRCNT+!OFF! => / +PRINTX STR +PRINTX / +/ +TERMIN + +EBLK +IPMDFL: 0 ; # of flushed input datagrams +IPMCKF: 0 ; # of input datagrams with bad checksum +IPMFRG: 0 ; # of fragments received +IPMFRD: 0 ; # of sucessfully reassembled datagrams +BBLK + +SUBTTL IP Input Interrupt Level + +; IPGIPT - Get datagram input buffer +; Clobbers Q,T +; A/ Max size of buffer in words +; Returns .+1 if failure (error message already printed) +; Returns .+2 +; A/ Pointer to datagram structure associated with buffer +; B/ Input BLKI pointer to buffer, -<# wds>,, + +IPGIPT: CAILE A,PKBSIZ ; Make sure size needed will fit in a packet buffer + JRST IPGIP9 + CALL PKTGFI ; Get a packet at int level + RET ; Failed, none available. + TRCPKT A,"IPGIPT Net input alloc" + MOVE T,PK.BUF(A) ; Get addr of buffer + HRLOI B,-PKBSIZ ; -<#wds>,,-1 + ADDI B,(T) ; Now get BLKI pointer into buffer + JRST POPJ1 ; Win! +IPGIP9: BUG CHECK,[IP: Too-big buff reqd =],OCT,A + RET ; Fail. + + +; IPRDGM - Process a received datagram at PI level +; Must put datagram into one of the following lists: +; User IP input queue (IPQ) +; IP reassembly table +; ICMP processing +; TCP connection queue +; A/ Pointer to datagram structure +; B/ # words read in datagram +; C/ # wds offset to start of IP header +;;; J is not used, and not supplied by all callers +;;; J/ host-table index of address datagram came from +; Returns .+1 always +; Can clobber all ACs except P +; Sets up +; R/ addr of packet entry +; W/ addr of IP header +; H/ addr of IP data + +IPRDGM: METER("IP: IDs rcvd") + MOVEI R,(A) ; Set up packet entry ptr in canonical place + TRCPKT R,"IPRDGM Input from net" + CAIGE B,5(C) ; Make sure it's big enough + JRST IPRDG9 + HRLM B,PK.BUF(R) ; Store # words read + ADD C,PK.BUF(R) ; Find addr of start of IP header + HRLZM C,PK.IP(R) ; and set it. + MOVEI W,(C) + LDB H,[IP$IHL (W)] ; Find claimed length of IP header + ADDI H,(W) ; Get addr of start of IP data + HRLZM H,PK.TCP(R) ; Set that too. + + ; Do initial vectoring test. + SKIPE IPUQUS ; Check Queue 0 (SysIn) + JRST IPRDG2 ; It exists!! Always vector for it. + + ; Perform initial checking for address, checksum, and so forth + ; to verify datagram is good; also dispatch to handle fragments. + ; This is entry point for re-vectors from SysIn IP queue. +IPRDGV: CALL IPCKSM ; Compute checksum for IP header + LDB B,[IP$CKS (W)] ; and get what the datagram had, + CAIE A,(B) ; in order to compare them... + JRST [ METER("IP: Ifl bad cksm") + AOS IPMCKF ; Bump two meters + JRST IPRD90] ; Go flush it forthwith. + MOVE B,IP$DST(W) ; Get destination host, should be us +IFE IPUNCP, CAME B,[IMPUS3_4] + CAMN B,[IMPUS4_4] + JRST IPRD10 + ; Packet is to be forwarded + METER("IP: Packets forwarded") + LDB B,[IP$TTL(W)] ; Decrement time to live + SOJLE B,[ METER("IP: Packets expired") + JRST IPRD90 ] +ICMEK1: DPB B,[IP$TTL(W)] + CALL IPCKSM ; Update the checksum + DPB A,[IP$CKS(W)] + MOVEI A,(R) ; Transmit it + CALRET IPKSNQ + +IPRD10: HRRE B,IP$FRG(W) ; HACK! Get both IP%FMF and IP%FRG! + JUMPN B,IPRD50 ; Jump if this is a fragment. + + ; Do datagram vectoring. This code is temporarily (?) crude, + ; it just scans the whole Internet Queue table. + ; This is entry point for re-vectoring. W must point to IP + ; header, and H to IP data. I should point at 1st queue entry + ; to start checking at. +IPRD20: MOVEI I,2 ; If drop in, start at 2 (leave 0+1 alone) + LDB B,[IP$PTC (W)] ; Get protocol number + CAIN B,%PTCTC ; Is it TCP? + JRST TCPIS ; Yes, go process TCP input segment. + CAIN B,%PTCUD ; Well, is it UDP? + JRST IPRD30 ; Yeah, can handle that one. + CAIN B,%PTCIC ; Maybe ICMP? + JRST ICMP ; Yup, hack it. +IPRD90: MOVEI A,(R) + CALL PKTRT ; Bah, nothing we handle, flush it. + AOS IPMDFL ; Bump count of flushed dgms. + RET + + ; Here to dispatch a UDP datagram +IPRD30: LDB A,[IP$TOL (W)] ; Make sure it's long enough! Find dgm length + LDB B,[IP$IHL (W)] ; and get IP header length + IMULI B,4 ; in octets + SUBI A,(B) ; to subtract from dgm length. + CAIGE A,2*4 ; Must have enough data for UDP header! + JRST [ METER("IP: Ifl bad UDP len") + JRST IPRD90] ; Flush this dgm. +IPRD31: CAIL I,NIPUQ + JRST [ METER("IP: Ifl no UDP port") ; Didn't find any queues, + JRST IPRD90] ; so flush it. + SKIPN IPUQUS(I) ; Check each active UDP queue + AOJA I,IPRD31 + LDB B,[UD$DST (H)] ; Get UDP dest port number + HRRZ T,IPUQCT(I) ; and port # we're watching for + CAIE B,(T) + AOJA I,IPRD31 ; No match, try another. + METER("IP: # UDP dgms queued") + CAIA +IPRDG2: SETZ I, ; Entry point for SysIn queueing + MOVEI Q,IPUQHD(I) ; Hurray, got it! Add to queue + MOVE B,(Q) ; Save prev contents of header + MOVEI A,(R) + CALL PKQPL(PK.IP) ; Put at end of input IP queue + JUMPE B,IPQUSI ; If nothing previously there, give user int. + RET + +IPRDG9: BUG INFO,[IP: Netin dgm too small, size ],OCT,B,[ offset ],OCT,C + JRST IPRD90 ; Try flushing the packet buffer. + +; IP Datagram Reassembly - Handle received fragment. + +IPRD50: AOS IPMFRG ; Bump count of fragments received + + LDB D,[IP$ID (W)] ; Get datagram ID field + LDB C,[IP$PTC (W)] ; Then protocol field + HRLI D,(C) ; Make ,, + MOVE E,IP$SRC(W) ; Then source address + MOVEI I,NIPF-1 +IPRD51: CAME D,IPFDID(I) +IPRD52: SOJGE I,.-1 + JUMPL I,IPRD70 ; If no more, must add to table. + MOVE B,IPFDPE(I) ; Matching ID! Get buffer ptr + HLRZ T,PK.IP(B) ; Get IP header ptr for existing fragment + CAME E,IP$SRC(T) ; Ensure same source host + JRST IPRD52 ; Nope, go check next entry. + HLRZ H,PK.TCP(B) ; Get ptr to start of data in reassembly buff + + ; OK, we matched up a fragment! Now start reassembly procedure. + ; If fragment is first one (offset 0) then must copy IP header, + ; unless already done. Safe to BLT since we always reserve + ; enough room for a full 15-word IP header. + ; If fragment is last one (IP%FMF 0) then must set IP$TOL to + ; the total # octets in full datagram. This gets fixed + ; to include the IP header length when datagram is complete. + ; I/ idx of reassembly entry + ; T/ ptr to IP header in reassembly buff + ; H/ ptr to data in reassembly buff + ; R, W as for entry to IPRD50 +IPRD55: LDB A,[IP$IHL (W)] ; Get IP header length in 4-octet wds + LDB E,[IP$TOL (W)] ; Get total length of this dgm in octets + HRRE D,IP$FRG(W) ; Hack - get frag offset and more-frag flag + TRNN D,IP%FRG ; Is frag offset 0 - 1st part of dgm? + JRST [ LDB C,[IP$FRG (T)] ; Yeah. Already copied header? + JUMPE C,.+1 ; Jump if so, don't do again. + MOVEI B,(T) + HRLI B,(W) ; Set up BLT from,,to + MOVEI C,(T) + ADDI C,(A) ; Get to+IHL + MOVE Q,IP$CKS(T) ; Save ptr to hole list + LDB TT,[IP$TOL (T)] ; Save TOL, might already be set. + BLT B,-1(C) ; Copy the IP header + HRRM Q,IP$CKS(T) ; Restore hole list head + DPB TT,[IP$TOL (T)] + JRST .+1] + ASH D,-3 ; Get frag.first in terms of 4-octet words + JUMPGE D,[ ; Jump for special processing if last frag + MOVNI B,(A) + ASH B,2 ; Get -<# octets in header> + ADDI B,(E) ; Find # octets of data in this fragment + MOVEI C,(D) + LSH C,2 ; Get # octets data is offset + ADDI B,(C) ; Finally get total # data octets of full dgm + DPB B,[IP$TOL (T)] + ADDI E,3 ; Okay, round UP to full word + LSH E,-2 ; Get rounded-up length in terms of 4-octet wds + SUBI E,1(A) ; Get # whole wds of data (minus 1) + JRST IPRD56] ; Go rejoin normal processing + + ; Not last frag. Only special check is to ensure length of data + ; is rounded down to a fragment boundary (frags are 8-octet chunks). + TRZ D,-1# ; Not last frag, clean up RH of frag.first + LSH E,-2 ; Get rounded length in terms of 4-octet words + SUBI E,1(A) ; Get # whole words of data, minus 1 + TRNN E,1 ; Paranoia: ensure # wds of data was EVEN + SUBI E,1 ; If not, round DOWN to ensure 8-octet boundary + +IPRD56: JUMPL E,IPRD80 ; Flush if bad length + ADDI E,(D) ; Get frag.last + CAIL E, ; Make sure datagram won't be too big. + JRST [ METER("IP: Ifl huge dgm") + CALL IPFDFL ; Ugh, must flush whole datagram entry! + JRST IPRD90] ; Would it be better instead to just + ; truncate it, and accept anyway since TCP + ; can ACK up to that much? Probably not. + + ; Each hole descriptor is 1 word of format + ; hole.first: ,, + ; + ; During re-configuration of the hole descriptor list, following + ; ACs are used + ; A/ scratch + ; B/ hole.first (wd offset) + ; C/ hole.last + ; D/ ,,frag.first ; lastflg is 0 if last fragment. + ; E/ frag.last + ; Q/ ptr to current hole descriptor + ; TT/ ptr to previous hole descriptor + ; H/ ptr to start of data in reassembly buffer (base for offsets) + ; W/ ptr to IP header of just-arrived fragment + ; T/ ptr to IP header of reassembly buffer + ; R/ ptr to packet entry of just-arrived fragment + MOVEI Q,IP$CKS(T) ; Get ptr to 1st hole descriptor +IPRD61: MOVEI TT,(Q) ; Save old ptr + HRRE Q,(Q) ; Get next descriptor + JUMPL Q,IPRD68 ; Jump if end of list + MOVEI B,(Q) ; Set hole.first + ADDI Q,(H) ; Make ptr to hole descriptor + HLRZ C,(Q) ; Get hole.last + CAIGE C,(D) ; If hole.last < frag.first, + JRST IPRD61 ; back to try next hole farther on. + CAIGE E,(B) ; If frag.last < hole.first, + JRST IPRD68 ; passed affected area, so can stop now. + + ; New fragment interacts with current hole in some way! + ; Remove current hole from the list, but keep Q pointing to + ; start of hole. TT points to the last valid hole descriptor. + MOVE A,(Q) ; Get hole.first of next hole + HRRM A,(TT) ; Store in prev hole, so current is skipped. + CAIL B,(D) ; If hole.first < frag.first, skip. + JRST IPRD66 + + ; Create new hole descriptor at start of old hole + ; with new.first = hole.first and new.last = frag.first-1 + ; i.e. hole.first: ,, + ; First get ptr to new hole and put it on list. + HRRM B,(TT) ; Point prev hole to new hole. + HRLI A,-1(D) ; Make ,, + MOVEM A,(Q) ; Store new hole descriptor. + MOVEI TT,(Q) ; Make prev be current, in case test below wins + ; Drop thru to check high bound of old hole + +IPRD66: CAIL E,(C) ; If frag.last < hole.last then hole not all filled + JRST IPRD61 ; (hole all filled, so go check further holes) + CAIL D, ; Some hole left; is this the last fragment? + JRST [ HLLOS (TT) ; Yes! Zap prev hole to ensure list ends. + JRST IPRD68] ; and get out of loop now. + + ; Fragment didn't fill last part of hole, so need to create + ; new hole descriptor for it, + ; with new.first = frag.last+1 and new.last = hole.last + ; i.e. frag.last+1: ,, + MOVEI Q,1(E) ; Get frag.last+1 + HRRM Q,(TT) ; Point previous to new hole + ADDI Q,(H) ; Make abs ptr to new hole + HRLI A,(C) ; Make ,, + MOVEM A,(Q) ; Store new hole descriptor. + ; Can drop through to end loop, since no further holes + ; are affected. + + ; No more holes on list, we can copy the data now! +IPRD68: HLL D,PK.TCP(R) ; Get ,, + ADDI D,(H) ; Now have BLT pointer + ADDI E,(H) ; and now have terminating address + CAIN E,(D) ; But if only moving 1 word, + JRST [ HLRZ D,D ; Can't use BLT? + MOVE A,(D) ; So just move by hand + MOVEM A,(E) + JRST .+2] ; Skip over it. + BLT D,(E) ; Here we go! + + ; Now see if any holes left... + MOVEI W,(T) ; Save ptr to reassembly IP hdr (H already set) + MOVEI A,(R) ; No need for arrived dgm any more, + CALL PKTRTA ; so flush it now. + HRRE A,IP$CKS(W) ; See if any holes left + JUMPGE A,CPOPJ ; Jump if some left, nothing else to do. + + HRRZ R,IPFDPE(I) ; Win!!! Get back packet-entry ptr + LDB A,[IP$IHL (W)] ; Must perform final TOL fixup. Get IHL + LSH A,2+4 ; in octets, shifted to TOL field + ADDM A,IP$TOL(W) ; Now have proper length! + SETZM IPFDPE(I) + SETOM IPFDID(I) + HRLOI A,377777 + MOVEM A,IPFTTL(I) + AOS IPMFRD ; Bump cnt of # datagrams reassembled! + JRST IPRD20 ; Go dispatch the datagram! + + + ; Create entry in table to store 1st fragment in. +IPRD70: MOVEI I,NIPF-1 + SKIPE IPFDPE(I) + SOJGE I,.-1 + JUMPL I,[METER("IP: Ifls Fragtab full") ; Barf, fragment table full. + JRST IPRD90] + LDB A,[IP$TTL (W)] ; Get time-to-live + JUMPE A,IPRD90 ; Might as well hack zero case + IMULI A,30. ; Turn into 30ths + ADD A,TIME + MOVEM A,IPFTTL(I) ; Store timeout value + MOVEM D,IPFDID(I) ; Store ptcl,,ID + HRRZM R,IPFDPE(I) ; Store PE ptr + + ; Messy stuff, must get data set up into right place in buffer. + ; If this is the 1st fragment we are OK, and can use original + ; datagram buffer, else we have to shuffle data. Simplest way + ; to handle latter case is to just get a new buffer and copy + ; it over. + LDB A,[IP$FRG (W)] ; Get fragment offset field + JUMPN A,IPRD75 ; If not zero, jump to do copy. + LDB A,[IP$TOL (W)] ; Hurray, 1st fragment! Get total length + LSH A,-2 ; Round down to # words + LDB B,[IP$IHL (W)] + SUBI A,(B) ; Find # words that fragment uses + TRZ A,1 ; Ensure # wds is rounded down to 8-octet chunk + JUMPLE A,[CALL IPFDFL ; Sigh, flush entry. + RET] ; Just return, only flushing one PE. + HRRM A,IP$CKS(W) ; Store first hole.next in header. + MOVEI B,(A) + ADDI B,(H) ; Get addr of start of hole + SETOM (B) ; Make it an infinite hole. + RET + + ; Fragment entry must be stored, but it isn't the 1st thing in + ; the datagram. We must cons up a fake initial fragment and + ; then copy normally into that fragment. + ; Note that this fake fragment must be carefully initiallized + ; since certain IP fields are referred to in the reassembly code + ; (via pointer in T) +IPRD75: CALL PKTGFI ; Get a PE ptr at PI lvl + JRST IPFDFL ; Failed, must flush entry + TRCPKT A,"Reassembly alloc" + MOVEM A,IPFDPE(I) ; Store it + HRRZ T,PK.BUF(A) + HRLM T,PK.IP(A) ; Say IP header at start of buffer. + MOVEI H,15. ; Use maximum IHL for offset + HRRZM H,IP$CKS(T) ; Store this offset as ptr to 1st hole desc + ADDI H,(T) ; and make data start at end of max IP hdr. + HRLM H,PK.TCP(A) + SETOM (H) ; Make 1st hole descriptor be infinite + SETOM IP$FRG(T) ; Put crap in frag offset field + MOVE B,IP$SRC(W) ; and ensure source host copied too. + MOVEM B,IP$SRC(T) + JRST IPRD55 ; Now go do the copy... + +IPRD80: METER("IP: Ifl bad len") ; Bad IP length field + JRST IPRD90 ; Go flush the dgm. + +; IPFCLK - Called every few seconds at clock level to check +; reassembly tables and flush any partially filled datagrams +; which have timed out. + +IPFCLK: MOVEI I,NIPF-1 + MOVE B,TIME + CONO PI,NETOFF ; Hack with net ints deferred. + CAML B,IPFTTL(I) + CALL IPFDFL ; Flush the partial dgm + SOJGE I,.-2 + CONO PI,NETON ; Done, re-enable net ints. + RET + +; IPFDFL - Flush reassembly entry in I +; Clobbers A, Q, T + +IPFDFL: SKIPE A,IPFDPE(I) + CALL PKTRTA ; Flush the packet buffer + SETZM IPFDPE(I) + SETOM IPFDID(I) ; Clear out other table stuffs. + HRLOI A,377777 + MOVEM A,IPFTTL(I) + RET + + +; Datagram Fragment table. +; Free entries have IPFDPE 0, IPFDID -1, and IPFTTL SETZ-1 (max pos time) +EBLK +NIPF==:30 ; Max # of outstanding IP datagram reassembly buffers +IPFDPE: BLOCK NIPF ; +IPFDID: REPEAT NIPF,-1 ; ,, +IPFTTL: REPEAT NIPF,SETZ-1 ; Sys time after which entry flushed. +BBLK + +SUBTTL IP Output Interrupt Level + +IFE IPUNCP,[ + +EBLK +IPOUTQ: 0 +IPOBLQ: 0 +BBLK + +; IPGIOQ - Get IP Output Queue entry for IMP +; Returns .+1 if nothing in queue +; Returns .+2 +; A/ Pointer to datagram structure +; B/ Output BLKO pointer to buffer, -<# wds>,, +; C/ Arpanet host address +; H/ host-table index +; Clobbers Q,T,W,D,E + +IPGOQ1: METER("IP: ODs flushed") + CALL PKTRT ; Internal looping point + +IPGIOQ: MOVEI Q,IPOUTQ + CALL PKQGF(PK.IP) ; Get first thing off IP output list + JUMPE A,IPGOQ9 ; Jump and return if nothing there. + MOVE T,PK.FLG(A) ; Get packet flags + TLNE T,(%PKFLS) ; Should we flush this one? + JRST IPGOQ1 ; Yes, down the drain it goes. + TLO T,(%PKPIL) + IORM T,PK.FLG(A) ; Say packet locked at PI level. + + SKIPLE C,PK.BUF(A) + CAMG C,[2,,0] + BUG HALT,[IP: Null dgm on queue] +IFE KS10P,[ + ;KS doesn't care, save 2 usec.. + MOVN B,C ; Straightforward way to put together AOBJN ptr. + HRRI B,-1(C) ; Now have BLKO +] + MOVE C,PK.DST(A) ; Get destination address + + ; IMP-specific!!! + ; Ask interface if it wants this particular datagram right now. + ; + CALL IMPCTS + JRST IPGOQ5 ; Can't send, requeue + + ; Got valid dgm, must ensure that block queue is merged back + ; onto beginning of output queue. +IPGOQ6: METER("IP: ODs sent") + SKIPN D,IPOBLQ ; See if anything was blocked + JRST POPJ1 ; Nope, just take win return. + SETZM IPOBLQ ; Yes, block queue exists! + SKIPN T,IPOUTQ ; Get ptr to 1st node on output queue + JRST [ MOVEM D,IPOUTQ ; If nothing was left on output queue, + JRST POPJ1] ; can simply move the list. + HLRZ E,D ; Get ptr to last node on blocked queue + HRRM T,PK.IP(E) ; Point end of blocked Q to start of output Q + HRRM D,IPOUTQ ; and point start of output Q to start of block Q + JRST POPJ1 ; and return with nice winning dgm. + + ; Come here to handle blockage of IP datagram. +IPGOQ5: MOVSI T,(%PKPIL) + ANDCAM T,PK.FLG(A) ; Say not locked at PI after all + MOVEI Q,IPOBLQ + CALL PKQPL(PK.IP) ; Put blocked dgm onto block queue + JRST IPGIOQ ; Now go try next dgm. + + ; Output queue empty, just shift block queue back. +IPGOQ9: SKIPN A,IPOBLQ ; See if anything was put on block queue + RET ; Nope, all's clear. + MOVEM A,IPOUTQ ; Aha, move it to standard output queue + SETZM IPOBLQ ; and clear the block-queue ptr. + RET ; Nothing to send from IP at moment. + +] ;IFE IPUNCP + +; IPIODN - Output of IP datagram complete, wrap up. +; Called by all device drivers. +; A/ pointer to datagram structure +; Clobbers T,Q +; Returns .+1 always + +IPIODN: TRCPKT A,"IPIODN Packet output complete" + MOVE T,PK.FLG(A) ; Get flags for packet + TLO T,(%PKODN) ; Say output done, + TLZ T,(%PKPIL) ; and unlock PI level output flag. + MOVEM T,PK.FLG(A) ; Store flags back. + CALRET PKTRT ; Return to freelist if not otherwise queued + + +SUBTTL ICMP - Internet Control Message Protocol + +; ICMP called at NET interrupt level to process just-received ICMP +; datagram. + +ICMP: + + ; First compute and verify checksum for ICMP data. + + ; Then dispatch on type for processing. + LDB E,[IP$SRC (W)] ; Load up source addr (commonly needed) + LDB A,[IC$TYP (H)] ; Get ICMP type field + CAIL A,NICMPT + JRST ICMP19 + AOS ICMPCT(A) ; Bump count of types + JRST @ICMPTB(A) ; Dispatch on type + + ; Bad type +ICMP19: BUG INFO,[ICMP: Bad type ],DEC,A,[from ],OCT,E +ICMP90: MOVEI A,(R) + CALL PKTRTA + RET + +ICMPTB: ICMP90 ; 0 Echo Reply (ignored) + ICMP19 ; 1 - + ICMP19 ; 2 - + ICMP90 ; 3 Destination Unreachable (ignored) + ICMP90 ; 4 Source Quench (ignored) + ICMRD ; 5 Re-direct + ICMP19 ; 6 - + ICMP19 ; 7 - + ICMEK ; 8 Echo + ICMP19 ; 9 - + ICMP19 ; 10 - + ICMP90 ; 11 Time Exceeded (ignored) + ICMPP ; 12 Parameter Problem + ICMP90 ; 13 TimeStamp (ignored) + ICMP90 ; 14 TimeStamp Reply (ignored) + ICMP90 ; 15 Information Request (ignored) + ICMP90 ; 16 Information Reply (ignored) +NICMPT==.-ICMPTB +EBLK +IPMICM: 0 ; # of ICMP datagrams +ICMPCT: BLOCK NICMPT ; # of ICMP datagrams, by type +BBLK + +; Type 8 - Echo + +ICMEK: MOVEI A,0 ; Set type to Echo Reply + DPB A,[IC$TYP (H)] + LDB A,[IC$CKS (H)] ; Fix checksum for change of 8 to 0 + ADDI A,8_8 + TRNE A,1_16. + ADDI A,1 + DPB A,[IC$CKS (H)] + MOVE A,IP$SRC(W) ; Exchange source and destination + EXCH A,IP$DST(W) + MOVEM A,IP$SRC(W) + MOVEI B,60. ; Reset time to live + JRST ICMEK1 ; Go send packet + +; Type 12 - Parameter Problem. + +ICMPP: LDB B,[IC$COD (H)] ; Get code field + JUMPE B,ICMPP2 + BUG INFO,[ICMP: Param err, code ],OCT,B,[from ],OCT,E + JRST ICMP90 +ICMPP2: LDB A,[341000,,1(H)] ; Get pointer into bad IP header + MOVEI B,(A) + LSH B,-2 ; Find word # error is in + ADDI B,IC$IPH(H) ; Make addr to word + BUG INFO,[ICMP: Param err, ptr ],OCT,A,[wd ],OCT,(B),[from ],OCT,E + JRST ICMP90 + +; ICMP type 5 - Redirect + +ICMRD: MOVEI D,IC$IPH(H) + MOVE A,IP$SRC(D) ; Get source addr of alleged IP header + CAME A,[IMPUS4_4] ; Must be a datagram WE sent. +IFE IPUNCP,[ + CAMN A,[IMPUS3_4] + CAIA + ] + JRST ICMP90 ; Bah, flush. Probably should log it. + LDB A,[IP$DST (D)] ; Get dest addr we used + GETNET A ; Derive net number + LDB B,[IC$GWA (H)] ; Get gateway addr recommended for this net + MOVEI C,NIPGW-1 ; Scan backwards thru gateway table + SETOB T,TT ; Index of free slot, index of oldest slot +ICMRD2: CAMN A,IPGWTN(C) + JRST [ SKIPN IPGWTG(C) ; Don't change a direct-route entry! + JRST ICMP90 + JRST ICMRD3 ] + CAIL C,NIPPGW ; Skip if prime gateway, not replaceable + JRST [ SKIPN IPGWTN(C) + MOVEI T,(C) ; Save index of last free slot found + SKIPL TT + CAML D,IPGWTM(C) + MOVEI TT,(C) ; Save index of least recently used slot + MOVE D,IPGWTM(TT) + SOJA C,ICMRD2 ] + SOJGE C,ICMRD2 + + ; Network not found in gateway table, must make new entry. + SKIPL C,T ; If there was one free, + JRST ICMRD3 ; go use that one. + MOVE C,TT ; Otherwise use least recently used entry + MOVE T,TIME + SUB T,IPGWTM(C) + CAIGE T,60.*60.*30. ; Flushing entry less than 1 hour old? + BUG INFO,[ICMP: GW table full, net/gw ],OCT,IPGWTN(C),OCT,IPGWTG(C),[=>],OCT,A,OCT,B +ICMRD3: GETNET D,B ; Figure out which interface this gateway is on + MOVEI T,NIPPGW-1 + SKIPN IPGWTG(T) + CAME D,IPGWTN(T) + SOJGE T,.-2 + JUMPL T,ICMP90 ; I can't figure out how to get to this gateway anyway + MOVEM A,IPGWTN(C) ; Set network number + MOVEM B,IPGWTG(C) ; and its corresponding gateway addr + MOVE T,IPGWTI(T) ; and its interface + MOVEM T,IPGWTI(C) + MOVE T,TIME ; Pretend it was used so it + MOVEM T,IPGWTM(C) ; stays around for a while + JRST ICMP90 ; Done! + +SUBTTL IPQ Device - Internet Protocol Queues + +; Internet Protocol User Datagram Queue stuff, manipulated with +; IPKIOT system call. +; Queue 0 is special: +; Must be asked for explicitly +; All Input datagrams are vectored through it. +; No limit on input queue length +; Can put datagrams back into system for further processing +; Can send datagrams (like ordinary queue actually in this respect) +; Queue 1 is also special: +; Must be asked for explicitly +; All output datagrams are vectored through it. +; No limit on queue length +; Can put datagrams back onto device output queue. + +IFNDEF NIPUQ,NIPUQ==10 ; # User queues allowed +EBLK +IPUQUS: BLOCK NIPUQ ; ,, + IQ%CH==<77,,> ; Field for channel # + IQ$CH==<.BP IQ%CH,IPUQUS> ; BP to channel # +IPUQHD: BLOCK NIPUQ ; Input queue header +IPUQCT: BLOCK NIPUQ ; # datagrams on input queue,,vector args + +IPQOSW: -1 ? 0 ; IP Queue assignment lock + BBLK + +; IPQO - IPQ OPEN routine +; Control bits currently defined are + %IQSYS==100 ; Set up System Queue (0 or 1) + %IQSOU==200 ; System Queue 1 if set, otherwise 0 + %IQUDP==400 ; Set up random queue for UDP (port # in FN1) + +IPQO: CALL SWTL ; Only one job at a time hacking IQ allocation. + IPQOSW + SETZB E,I ; Set up convenient zeros + TLNE C,%IQSYS ; Asking for system queue? + JRST [ TLNE C,%IQSOU ; Yes, want input or output? + MOVEI I,1 ; Output, use queue 1 + SKIPE IPUQUS(I) ; Skip if it's free + JRST OPNL23 ; Nope, say "file locked". + JRST IPQO2] ; Can grab it, do so! + MOVE I,[-,,2] ; Scan tables, skipping 0'th entry + SKIPE IPUQUS(I) ; Look for free slot + AOBJN I,.-1 + JUMPGE I,OPNL6 ; If none available, claim "device full" + TLNN C,%IQUDP ; Got it. If will use UDP vectoring, + JRST OPNL33 ; No, complain "meaningless args" + ; since nothing else understood yet. + TLO E,%IQUDP ; then set flag for IPUQUS. + HRRZM A,IPUQCT(I) ; Store FN1 as UDP port number + CAIA +IPQO2: SETZM IPUQCT(I) + SETZM IPUQHD(I) ; Clear input queue + MOVEI A,IPQDN ; IOCHNM device index to use + HRLI A,(I) ; Save IQ index in LH + MOVEM A,(R) + MOVEI A,-IOCHNM(R) ; Start putting together the IPUQUS entry. + SUBI A,(U) ; Get channel # + DPB A,[.BP IQ%CH,E] ; Remember it in IPUQUS word + HRRI E,(U) ; Put user index in RH + MOVEM E,IPUQUS(I) ; Store, queue is now activated! + ; Note this must be last thing, to avoid + ; timing errors. + CALRET LSWPJ1 ; Unlock switch and return! + +; IPQCLS - IPQ CLOSE routine + +IPQCLS: HLRZ I,(R) ; Get IQ idx + CAILE I,1 ; Is it the Sys In or Out queue? + JRST IPQCL5 ; Nope, can handle normal case. + CONO PI,NETOFF ; Keep anything from being added meanwhile + SETZM IPUQUS(I) ; Mark queue not active, to avoid revector loops. + SETZM IPUQCT(I) ; Be tidy and clear other stuff too. + JUMPE I,IPQCL3 + + ; Close down System Output queue. This means all output + ; on this queue gets moved directly onto the real output + ; queue. +IPQCL1: MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Get first thing queued up + JUMPE A,[CONO PI,NETON ; Exit if no more. + CALRET IPOGO] ; Ensure output fired up. + MOVEI Q,IPOUTQ + CALL PKQPL(PK.IP) ; Put at end of real output queue + JRST IPQCL1 + + ; Close down System Input queue. This means all currently + ; queued input gets processed immediately. Note I gets + ; clobbered, but isn't necessary since we know this is queue 0. +IPQCL3: MOVEI Q,IPUQHD ; Get header for queue 0 + CALL PKQGF(PK.IP) ; Get A/ packet ptr + JUMPE A,NETONJ + HLRZ B,PK.BUF(A) ; Get B/ # words in packet + SETZ C, ; Get C/ # wds offset to IP header + CALL IPRDGM ; Process and vector it. + JRST IPQCL3 ; Get next + + + ; Normal datagram input queue. Doesn't need NETOFF since + ; PI level ignores the queue entry if it's inactive. Just + ; need to keep another job from assigning it... +IPQCL5: CONO PI,CLKOFF + SETZM IPUQUS(I) ; Clear its "active" entry word to stop queueing + CALL IPQRS2 ; Flush its input queue (clears IPUQHD) + SETZM IPUQCT(I) + CONO PI,CLKON + RET + +; IPQRST - IPQ RESET routine. Clears queue for channel. +; This is pretty drastic for the System I/O queues. + +IPQRST: HLRZ I,(R) ; Get IQ idx + CONO PI,NETOFF ; Prevent new dgms from arriving meanwhile. + CALL IPQRS2 ; Flush the queue + JRST NETONJ + +IPQRS2: MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Pull off 1st thing + JUMPE A,CPOPJ ; Return when no more + MOVE T,PK.FLG(A) + CAIN I,1 ; If queue is the Sys Output queue + JRST [ TLNE T,(%PKFLS) ; Then do special stuff. + JRST IPQRS3 ; Flush only if explicitly requested + TLZ T,(%PKPIL) ; Otherwise clear PI-Locked bit + TLO T,(%PKODN) ; and claim "output done" (ha ha) + MOVEM T,PK.FLG(A) + JRST IPQRS2] +IPQRS3: CALL PKTRT ; Put all stuff on freelist. + JRST IPQRS2 + +; IPQIO - IPQ I/O routine (if anything actually tries using this) + +IPQIO: JRST OPNL34 ; Say "Wrong Type Device" + POPJ P, + +; IPQSTA - IPQ STATUS routine + +IPQSTA: + POPJ P, + +; IPQWHY - IPQ WHYINT routine + +IPQWHY: + JRST POPJ1 + +; IPQRCH - IPQ RFNAME/RCHST routine + +IPQRCH: + POPJ P, + +; IPQRFP - IPQ RFPNTR routine + +IPQRFP: JRST OPNL34 + +; IPQIOP - IPQ IOPUSH/IOPOP routine + +IPQIOP: MOVEI T,(R) + SUBI T,IOCHNM(U) + CAIN I, + MOVEI T,77 ; IOPUSH, use 77 + HLRZ I,(R) ; Get IPQ index + DPB T,[IQ$CH (I)] ; Deposit channel # + POPJ P, + +; IPQFRC - IPQ FORCE routine + +IPQFRC: + JRST POPJ1 + +; IPQFIN - IPQ FINISH routine + +IPQFIN: + JRST POPJ1 + +; IPQUSI - Give User Interrupt on I/O channel. Not a system call, +; but called by PI level routines when input arrives for +; a previously empty queue. +; Clobbers T,Q +; I/ index to IP Queue + +IPQUSI: LDB Q,[IQ$CH (I)] ; Get channel # + CAIN Q,77 ; If IOPUSHed, no interrupt. + RET + PUSH P,U + HRRZ U,IPUQUS(I) ; Get user index + CAIN U, + BUG +; MOVSI T,(SETZ) ; Needn't force PCLSR'ing. +; IORM T,PIRQC(U) + MOVE T,CHNBIT(Q) + AND T,MSKST2(U) + IORM T,IFPIR(U) + POP P,U + RET + + + +SUBTTL .CALL IPKIOT - IPQ data transfer + +; .CALL IPKIOT - Internet Protocol Packet Transfer. +; Arg 1 is channel (must be open on IPQ:, specifies queue #) +; Arg 2 is address of buffer +; Arg 3 is count of words +; Val 1 is count of words read into user space (if any) +; Control bits specify function. If none, "read" is assumed. +; Get datagram from: + %IPIUS==100 ; 1 = Get datagram from user space, not from a queue + %IPNOC==200 ; Global input no-check flag, suppresses normal check. + ; For User Space, "check" means verify, set cksum. + ; For Input Queue, "check" means verify IP header. + ; For SysIn Queue, "check" means verify IP hdr. + ; For SysOut Queue, means nothing. + %IPNOH==400 ; Don't Hang waiting for datagram (Queues only) + %IPIQK==1000 ; Keep on queue, don't remove (only for %IPOUS) +; Put datagram to: + %IPOUS==0 ; User space + %IPOUT==1 ; Output to network (bypasses SysOut queue) + %IPOFL==2 ; Flush it + %IPORV==3 ; Re-vector to input queues past this one + +IPKIOT: + HRRZ A,(R) + CAIE A,IPQDN ; Must be right type device (IPQ) + JRST OPNL34 ; Wrong device + HLRZ I,(R) ; Get IP input queue index + CAIL I,NIPUQ ; Ensure it's valid. + BUG HALT,[Bad IPUQ idx in IOCHNM] + MOVE E,CTLBTS(U) ; Get control bits for this call + MOVEI J,(E) + ANDI J,3 ; Get output type in J + + TRNN E,%IPIUS ; Getting datagram from user? + JRST [ CAIN J,%IPOUS ; Giving datagram to user? + CAIL W,3 ; Yes, ensure at least 3 args. + JRST IPKIO2 ; All's OK, go check input queue. + JRST OPNL30] ; Will write to user, but too few args! + CAIGE W,3 ; Must have at least 3 args for this one. + JRST OPNL30 ; Too few args. + + ; Get datagram from user. + ; B/ user addr of buffer + ; C/ # of 32-bit words in buffer + TRZ E,%IPIQK ; Flush "keep" bit since won't be on any list! + CAIL C,5 ; Must have at least 5 words for IP + CAIL C,%IMXLN ; Must be less or eq to maximum datagram size + JRST OPNL33 ; Too big, say meaningless args. + CAIN J,%IPOUS ; Outputting back to self? + JRST POPJ1 ; Yeah, just turn into a NOP. + CALL PKTGF ; Get a free packet buffer (hangs until got it) + PUSHJ P,LOSSET ; Must put back on freelist if we PCLSR on BLT fault + PKTPCL ; Standard routine expects ptr in A + TRCPKT A,"IPKIOT Alloc" + MOVSI B,(B) + HRR B,PK.BUF(A) + MOVEI D,(C) + ADDI D,-1(B) ; Find last address copying into + XCTR XBR,[BLT B,(D)] ; Gobble up user's buffer! May fault. + PUSHJ P,LSWDEL ; Made it through, can flush PCLSR protection + HRLM C,PK.BUF(A) ; Set # words used in buffer + MOVE B,PK.BUF(A) ; Find addr of start of buffer + HRLZM B,PK.IP(A) ; and set start of IP header. + LDB D,[IP$IHL (B)] ; Find claimed length of IP header + ADDI D,(B) ; Get addr of start of IP data + HRLZM D,PK.TCP(A) ; Set that too. + JRST IPKIO3 ; Now decide about checking datagram! + + ; Get datagram from input queue. +IPKIO2: CONO PI,NETOFF + SKIPN A,IPUQHD(I) ; Anything in the queue? + JRST [ CONO PI,NETON + TRNE E,%IPNOH ; No, see if ok to hang. + JRST POPJ1 ; Don't hang, win-return zero wds-read in A. + SKIPN IPUQHD(I) ; Hang, here we go. + CALL UFLS + JRST IPKIO2] + TRNN A,-1 ; Make sure something was there! + BUG + CAIN I,1 ; Is this SysOut queue? + JRST [ MOVE T,PK.FLG(A) ; Yes, get flags + TLNN T,(%PKFLS) ; Actually wants to flush now? + JRST .+1 ; No, let's go with it. + MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Remove from queue + CAIN A, + BUG + CALL PKTRT ; Flush it. + JRST IPKIO2] + CONO PI,NETON + MOVE T,PK.BUF(A) ; Verify that something exists + TLNE T,-1 ; in both <# wds> field + TRNN T,-1 ; and field. + BUG HALT,[IPQ: Null dgm found on queue] + HLRZ T,PK.IP(A) ; Should also be an IP pointer + CAIN T, + BUG HALT,[IPQ: IP-less dgm on queue] + + ; Now have pointer in A to a datagram. It is still linked + ; on the input queue, unless %IPIUS is set. +IPKIO3: TRNE E,%IPNOC ; Should we check the contents at all? + JRST IPKIO5 ; Nope, just go straight ahead. + JFCL ; Here we should verify/set checksum, but... + + ; Now figure out where datagram wants to go! +IPKIO5: JRST @.+1(J) ; Only have 4 possibilities so far. + IQIO70 ; %IPOUS Output to user + IQIO60 ; %IPOUT Output to network + IQIO55 ; %IPOFL Flush it + IQIO80 ; %IPORV Re-vector through input queues + + ; %IPOFL Flush datagram. +IQIO55: TRNN E,%IPIUS ; Is it from input queue list? + CALL IPIQGF ; Yes, take it off input queue list + CALL PKTRT ; Now can return to packet freelist! + JRST POPJ1 ; Win return. + + ; %IPOUT Output datagram to network. +IQIO60: TRNN E,%IPIUS ; Is it still on an input list? + CALL IPIQGF ; Yes, take it off input queue list + CAILE I,1 ; If not from Sys I/O queue, + JRST [ CALL IPKSNQ ; Possibly send onto SysOut queue. + JRST POPJ1] + CALL IPKSNI ; Dgm from Sys queue, never goes back to SysOut + JRST POPJ1 + + + ; %IPOUS Output datagram to user (a "read" from user viewpoint) + ; This is the only place where we can PCLSR on "output". Note + ; that we cannot get here if datagram came from user, so the + ; datagram we point to is always still on input queue, and + ; we can safely PCLSR without any special backup. +IQIO70: HLRZ D,PK.BUF(A) ; Find # words available + JUMPLE C,OPNL33 ; Neg or zero count -> meaningless arg error + CAILE C,(D) ; If asking for more wds than exist, + MOVEI C,(D) ; only furnish what we've got. + MOVEI D,(B) + ADDI D,-1(C) ; Find last user word to write + HRL B,PK.BUF(A) + XCTR XBW,[BLT B,(D)] ; Shove it at him; can PCLSR here. + TRNE E,%IPIQK ; Done! Should we keep datagram around? + JRST IQIO75 ; Yes, don't flush it. + CALL IPIQGF ; Take datagram off the input queue. + CALL PKTRT ; Return entry/buffer to freelist. +IQIO75: MOVEI A,(C) ; Return count as 1st val! + JRST POPJ1 + + ; Must re-vector through stuff... + ; Note that it is illegal to re-vector a datagram from the SysOut + ; queue, because it still shares pointers and stuff with + ; (for example) TCP retransmit queues. Later, could add code to + ; get another packet buffer and copy it over, but this is better + ; done at the device driver level probably. +IQIO80: TRNN E,%IPIUS ; Came from user? + JRST [ CAIN I,1 ; No, from a queue; is it the SysOut queue? + JRST OPNL2 ; Yes, illegal. Say "Wrong direction". + CALL IPIQGF ; No, is OK. Take it off input list. + JRST .+1] + MOVEI R,(A) + HLRZ W,PK.IP(R) ; Get pointer to IP header + HLRZ H,PK.TCP(R) ; and to IP data. + SETZ J, + CONO PI,NETOFF + CALL IPRDGV ; Go vector and process the datagram. + CONO PI,NETON + JRST POPJ1 + + ; Auxiliary, clobbers D to do checking. +IPIQGF: MOVEI D,(A) + MOVEI Q,IPUQHD(I) ; Is from list, must take it off. + CALL PKQGF(PK.IP) ; Remove from IP queue list + CAME A,D + BUG ; Something added in meantime??? + RET + +SUBTTL IP TCP Interface Routines + +; IPMTU - Size of largest datagram we want to send to a given destination +; A/ Destination address +; Returns T/ MTU + +SUBN27==: ; Damn macro generates an error inside literal +NW%CHW==: ; Old CHAOS-wrapping scheme, probably unused + +IPMTU: +IFE IPUNCP,[ + PUSH P,A ; Save address for a bit + MOVEI T,576. ; Default value + GETNET A ; Network part only + CAMN A,[NW%ARP] ; Arpanet? + MOVEI T,%IMMTU ; MTU of IMP + CAMN A,[NW%AI] + MOVEI T,%IMMTU ; AI net. We know we have a good path + CAMN A,[NW%CHW] ; Wrapped chaos packets + MOVEI T,488. ; Smaller MTU + CAME A,[NW%LCS] ; Net 18 is ugly, must check subnets + JRST IPMTU1 + MOVE A,(P) ; Get full address back + TRZ A,177777 ; Mask off all but 18. + CAMN A,[SUBN27] ; Subnet 27 is fed by chaos-wrapping. + SKIPA T,[488.-40.] ; Giving it a very small MTU + MOVEI T,%IMMTU ; Good path to all others +IPMTU1: POP P,A +] ;IFE IPUNCP +IFN IPUNCP, MOVEI T,488.-40. ; This should be small enough... + RET + +IF1,.ERR Amazing MIT-Specific crocks near IPMTU... + +; IPBSLA - Best Local Address for a given destination +; A/ Destination IP Address +; Return A/ Local Address to use + +IPBSLA: +IFE IPUNCP,[ + GETNET A + CAMN A,NW%CHW + SKIPA A,[IMPUS4] ; Local Address on wrapped-chaos net + MOVE A,[IMPUS3] ; Default local host address to IMP +] ;IFE IPUNCP +IFN IPUNCP, MOVE A,[IMPUS4] + RET + +; IPLCLH - Skip return if address in A is one of us. +; Called with JSP T,IPLCLH + +IPLCLH: +IFE IPUNCP, CAME A,[IMPUS3] + CAMN A,[IMPUS4] + JRST 1(T) + JRST (T) + +; IPKSND - Invoked by TCP to send off a segment. +; Fills in the IP header fields, checksums, and puts on output queue. +; R, W, H set up pointing to segment +; The out-of-TCP information is contained in the "IP header" that +; W points to: +; IP$SRC - Source addr +; IP$DST - Dest Addr +; IP$TOL - Length of segment in bytes (must add IP header length) +; Clobbers A,B,C,D,E,Q,T +EBLK +IPIDCT: 0 ; IP identification #, incremented for each datagram +BBLK + +IPKHDR: MOVE A,IP$VER(W) ; Get first word + ADDI A,<5*4>_4 ; Add length of IP header (5 wds for now) + HRLI A,212000 ; Fill in Ver, IHL, TOS + MOVEM A,IP$VER(W) ; Set 1st wd + ADDI A,3_4 ; Now, to get # of words, round up + LSH A,-<4+2> ; (note flush 4 spare bits then divide by 4) + ANDI A,37777 ; 14 bit field now + HRLM A,PK.BUF(R) ; Store # of words, for device driver. + MOVSI A,170030 ; TTL and PTC (TCP) + MOVEM A,IP$TTL(W) ; Set 3rd wd + +IPKHD2: AOS A,IPIDCT ; Get new ID number + LSH A,<16.+4> ; Left justify it + MOVEM A,IP$ID(W) ; Use to set up 2nd wd (no flags/frags) + CALL IPCKSM ; Get IP header checksum + DPB A,[IP$CKS (W)] ; In it goes! + RET + +IPKSND: TRCPKT R,"IPKSND output call" + CALL IPKHDR + MOVEI A,(R) ; Set up PE ptr arg for following stuff. + +; IPKSNQ - entry point from IPKIOT, to send a datagram. +; A/ PE ptr to datagram - PK.BUF must be set up. +; Clobbers A,B,T,Q + +IPKSNQ: MOVSI T,(%PKODN) ; Clear the "output-done" flag. + ANDCAM T,PK.FLG(A) + TRCPKT A,"IPKSNQ output call" + SKIPE IPUQUS+1 ; Check - have System Output queue? + JRST IPKSN5 ; Yes, put on that queue. + ; No, drop into IPKSNI + +; IPKSNI - Route packet to appropriate gateway and interface +; A/ PE ptr to datagram - PK.BUF must be set up. +; Clobbers A,B,T,Q +IPKSNI: PUSH P,C + SKIPLE C,PK.BUF(A) ; Get the packet buffer from the PE + CAMG C,[2,,0] + BUG HALT,[IP: Null dgm being sent] + LDB C,[IP$DST(C)] ; Get destination address + + ;; This is where to apply final gateway routing code, based on Internet address in C. + GETNET T,C ; Get network # into T + MOVSI Q,-NIPGW ; Search table of gateways and direct routes + CAME T,IPGWTN(Q) ; Skip if network # matches + AOBJN Q,.-1 + JUMPL Q,IPSNI1 ; Jump if found entry in table + AOS Q,IPGWPG ; No gateway known for this network, so try a + CAIL Q,NIPMGW ; prime gateway and hope for an ICMP redirect! + SETZB Q,IPGWPG ; Try a different prime gateway each time +IPSNI1: MOVE T,TIME ; Remember that this gateway entry was used + MOVEM T,IPGWTM(Q) + SKIPE IPGWTG(Q) ; Skip if this is a direct route + MOVE C,IPGWTG(Q) ; Get gateway address + MOVEM C,PK.DST(A) ; Save gateway address for interface to use + CALL @IPGWTI(Q) ; Dispatch to interface + POP P,C + RET + +EBLK +IPGWPG: 0 ; Index of current prime gateway + + ; Network number +IPGWTN: + NW%LCS ; LCS net + NW%AI ; MIT-AI-NET +NIPMGW==<.-IPGWTN> ; Number of prime gateways +IFE IPUNCP, NW%ARP ; ARPA Net + HOSTN 128,31,0,0 ; MIT Chaosnet +NIPPGW==<.-IPGWTN> ; Number of permanent gateways + BLOCK 64. ; Extra stuff to patch in and for redirects +NIPGW==<.-IPGWTN> + +; Internet address of gateway servicing given net number +IPGWTG: +IFE IPUNCP,[ + HOSTN 10,0,0,77 ; MIT-GW + HOSTN 10,3,0,6 ; MIT-AI-GW +] ;IFE IPUNCP +IFN IPUNCP,[ + HOSTN 128,31,6,1 ; ??? + HOSTN 128,31,6,2 ; ??? +] ;IFN IPUNCP +IFE IPUNCP, 0 ; Send direct to Arpanet + 0 ; Send direct to Chaosnet +IFN .-IPGWTG-NIPPGW, .ERR Permanent gateway table at IPGWTG wrong size +LOC IPGWTG+NIPGW + +IPGWTI: +IFE IPUNCP,[ + IPKSNA ; MIT-GW + IPKSNA ; MIT-AI-GW +] ;IFE IPUNCP +IFN IPUNCP,[ + IPKSNC ; ??? + IPKSNC ; ??? +] ;IFN IPUNCP +IFE IPUNCP, IPKSNA ; direct to Arpanet + IPKSNC ; direct to Chaosnet +IFN .-IPGWTI-NIPPGW, .ERR Permanent gateway table at IPGWTI wrong size +REPEAT NIPGW-NIPPGW,IPKSNA + +IPGWTM: BLOCK NIPGW ; TIME entry last used + +BBLK + +IFE IPUNCP,[ + +; Queue packet for Arpanet interface +IPKSNA: MOVEI Q,IPOUTQ ; Otherwise use direct IP output queue. + MOVE B,(Q) ; Save previous contents of queue header + CALL PKQPL(PK.IP) ; Put on IP output queue + CAIE B,0 ; Kick off IP output if necessary. + RET ; Not necessary, queue was not empty +IPOGO: CALRET IMPIOS ; Just means kicking IMP for now. + +] ;IFE IPUNCP + +; Queue packet for Chaosnet interface +; A has the pe +; PK.DST(A) has the Internet address to send to, 128.31.subnet.host +; The low 16 bits are Chaosnet address to send an UNC to +IPKSNC: PUSH P,H + PUSH P,J + PUSH P,E + PUSH P,W + MOVE J,A ;J has address of PE + MOVE H,PK.BUF(A) ;H has address of IP header + MOVEI E,0 ;E has number of bytes sent so far +IPKSC1: CALL CHABGI ;Get a Chaosnet buffer in A + JRST IPKSC9 ;Give up if can't get one + MOVSI T,-%CPKDT ;Zero out the Chaosnet header + HRRI T,(A) + SETZM (T) + AOBJN T,.-1 + MOVEI T,%COUNC + DPB T,[$CPKOP(A)] + MOVE C,PK.DST(J) + DPB C,[$CPKDA(A)] + MOVEI T,MYCHAD + DPB T,[$CPKSA(A)] + MOVEI T,8_8 ;DOD Internet #x0800 + DPB T,[$CPKAN(A)] ;Protocol number + AOS CHNIPO ;Meter Internet packets out to Chaosnet + LDB Q,[IP$IHL(H)] ;Internet header length in words + MOVE T,Q ;Save header length for later + MOVSI B,(H) ;BLT IP header into Chaos packet + HRRI B,%CPKDT(A) + ADDI Q,(B) + BLT B,-1(Q) ;Q saves address of first data word + LDB B,[IP$TOL(H)] ;Total length in octets including header + SUB B,E ;Number of bytes remaining to be sent + MOVEI C,IPKSC9 ;Continuation if no more fragments needed + CAIG B,%CPMXC ;Skip if need to fragment + JRST IPKSC2 + MOVEI B,%CPMXC/4 ;Compute number of 32-bit data words in fragment + SUB B,T + TRZ B,1 ;Round down to even multiple of 8 octets + ADD B,T + LSH B,2 ;Number of bytes in this fragment including header + MOVEI W,IP%FMF ;Set more-fragments flag + IORM W,IP$FLG+%CPKDT(A) + MOVEI C,IPKSC1 ;Continuation sends another fragment +IPKSC2: DPB B,[IP$TOL+%CPKDT(A)] ;Total length of this fragment + DPB B,[$CPKNB(A)] + PUSH P,C ;Save continuation address + MOVE W,E ;Get fragment offset + LSH W,-3 ;8-octet units + LSH T,2 ;Number of bytes in header + SUB B,T ;Number of data bytes + LDB C,[IP$FRG+%CPKDT(A)];Set fragment offset + ADD C,W + DPB C,[IP$FRG+%CPKDT(A)] + ADD T,E ;Byte offset of start of data to send + LSH T,-2 ;Word offset + ADD T,H ;Word address + HRL Q,T ;BLT pointer to copy data + MOVEI T,3(B) + LSH T,-2 ;Number of words to copy + ADDI T,-1(Q) ;Address of last word to store + BLT Q,(T) ;Copy the data + ADD E,B ;Offset for next fragment + MOVEI W,%CPKDT(A) + CALL IPCKSM ;Compute header checksum + DPB A,[IP$CKS (W)] ;Store header checksum + MOVEI A,-%CPKDT(W) ;Restore address of chaos packet + SETOM -2(A) ;Not on any packet lists + PUSH P,J ;Save registers clobbered by CHAXMT + PUSH P,D + PUSH P,E + PUSH P,TT + CALL CHAXMT ;Launch packet into Chaosnet + POP P,TT + POP P,E + POP P,D + POP P,J + POPJ P, ;Take continuation + +IPKSC9: MOVE A,J ; The PE + CALL IPIODN ; Say we're done transmitting this packet, + POP P,W ; although it's still in Chaos NCP somewhere + POP P,E + POP P,J + POP P,H + POPJ P, + +IPKSN5: MOVEI Q,IPUQHD+1 ; Put on System Output queue + MOVE B,(Q) ; Save prev contents of header + CALL PKQPL(PK.IP) + CAIE B, ; If stuff already there, + RET ; Just return, else + PUSH P,I ; Nothing there before, give user interrupt. + MOVEI I,1 ; On IPQ SysOut queue. + CALL IPQUSI + POP P,I + RET + +; IPCKSM - Computes checksum for IP header. +; W/ points to IP header. +; Clobbers B,C +; Returns A/ checksum + +IFNDEF JCRY0,JCRY0==: ; Jump on Carry from bit 0 (and clear flag) + +IPCKSM: SETZ A, + LDB C,[IP$IHL (W)] ; Get IP header length + MOVE B,IP$CKS(W) ; Get 3rd word + ANDCM B,[IP%CKS] ; Mask out the checksum field + JFCL 17,.+1 ; Clear flags + ADD B,IP$VER(W) ; Add 1st wd + JCRY0 [AOJA A,.+1] + ADD B,IP$ID(W) ; Add 2nd + JCRY0 [AOJA A,.+1] + ADD B,IP$SRC(W) ; Add 4th + JCRY0 [AOJA A,.+1] + ADD B,IP$DST(W) ; Add 5th + JCRY0 [AOJA A,.+1] + CAILE C,5 + JRST IPCKS4 ; Longer than 5 words, must hack options. +IPCKS2: LSHC A,16. ; Get high 2 bytes (plus carries) in A + LSH B,-<16.+4> ; Get low 2 bytes in B +IPCKS3: ADDI A,(B) ; Get total sum + CAILE A,177777 ; Fits? + JRST [ LDB B,[202400,,A] ; No, must get overflow bits + ANDI A,177777 ; then clear them + JRST IPCKS3] ; and add in at low end. + ANDCAI A,177777 ; Return ones complement + RET + +IPCKS4: SUBI C,5 ; C has a 4 bit value. + MOVN C,C ; Get neg of # words left + LSH C,1 ; Double it + JUMPL C,IPCKS5(C) + RET ; Something is wrong, so just return bad val. + +REPEAT 10.,[ + ADD B,5+<10.-.RPCNT>(W) + JCRY0 [AOJA A,.+1] +] +IPCKS5: JRST IPCKS2 ; Options all added, now go fold sum. + +IFN 0,[ ; Old version +IPCKSM: MOVEI C,(W) + HRLI C,442000 ; Gobble 16-bit bytes + ILDB A,C ; wd 0 byte 1 + ILDB B,C + ADDI A,(B) ; Add 2nd byte of 1st wd + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 1 ID,frag + ILDB B,C ? ADDI A,(B) ? IBP C ; 2 Skip chksum field + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 3 source addr + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 4 dest addr +IPCKS8: CAIG A,177777 + JRST IPCKS9 + LDB B,[202400,,A] ; Get any overflow + ANDI A,177777 + ADDI A,(B) + JRST IPCKS8 +IPCKS9: ANDCAI A,177777 + RET + +] ;IFN 0 diff --git a/src/system/ioelev.432 b/src/system/ioelev.432 new file mode 100755 index 00000000..059311bd --- /dev/null +++ b/src/system/ioelev.432 @@ -0,0 +1,4944 @@ +;;; -*-PALX-*- + .TITLE IOELEVEN + + .SBTTL DEFINITIONS + +;;; note that the .IFM macro must be used only at toplevel +;;; (non-conditionalized) in PALX because it doesn't do the expansion of .IFM +;;; when conditionalized out, therefore it doesn't match it with the +;;; following .ENDC and the .ENDC will be seen at toplevel and end the +;;; conditionalization one is in. This will screw the code running on +;;; another one of the machines even if it doesn't signal an error in your +;;; assembly. --PGS + +.LIF NZ 0 + .FATAL USE PALX DUMMY!! + +;NOTE THAT THIS PROGRAM IS DESIGNED FOR 11/40'S. TO RUN ON AN +;11/10, MACRO OUT THE SOB INSTRUCTIONS. DOES NOT USE EIS NOR FIS. + +A=%0 ;TEMP/ARG/CHAR +B=%1 ;TEMP/ARG +C=%2 ;TEMP/ARG +D=%3 ;TEMP/ARG +H=%4 ;USUALLY INDEX IN HARDWARE UNIT TABLES +I=%5 ;USUALLY LINE NUMBER TIMES 2 +SP=%6 ;STACK POINTER +PC=%7 ;PROGRAM POINTER +PS=177776 ;PROGRAM STATUS +SWR=177570 ;SWITCHES + +.MACRO RTI +.ENDM ;FUCKING PALX! + +RTI=RTT ;11/40 HARDWARE MISFEATURE + +.IF P1 +.PRINT /MACHINE NAME = / +.TTYMAC MNAM +%TTYFLG==%TTYFLG+1 +.PRINT /MNAM +/ +%TTYFLG==%TTYFLG-1 +.MACRO .IFM MCHN ;REFERS TO PDP11 NAME +.IF IDN MCHN,MNAM +.ENDM .IFM +.MACRO MCONDX MCHN ;REFERS TO ITS SYSTEM NAME, USUALLY THE SAME +.IF IDN MCHN,MNAM +.ENDM MCONDX +.MACRO FUBAR +.ENDC +.ENDC +.ENDM FUBAR +.MACRO MNAME BODY ;INSERT ITS SYSTEM NAME INTO BODY IN PLACE OF "MCHN" +.IRP MCHN, +BODY +.ENDM +.ENDM MNAME +.ENDM ;TTYMAC +.ENDC ;P1 + +VERSION==%FNAM2 + +.IFM MX-DL ;MX'S DL-10 PDP11 +.MACRO MCONDX MCHN +.IF IDN MCHN,MX +.ENDM MCONDX +.MACRO FUBAR +.ENDC +.ENDM FUBAR +.MACRO MNAME BODY +.IRP MCHN, +BODY +.ENDM +.ENDM MNAME + +DL10P==1 ;HAS DL10 +DTE20P==0 ;DOES NOT HAVE DTE20 +NODDT==0 ;HAS DDT +NFTTY==102 ;2 * # OF FIRST TTY THIS 11 +NDHS==1 ;NUMBER OF DH11'S +NDHUN==15 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==320 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==1 ;NUMBER OF DL11'S +CTYP==0 ;FIRST DL11 NOT T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS ON MULTIPLEXED LINE (REST IN PEACE) +;MPXIDX==2*27 ;TTY INDEX OF LINE THAT MULTIPLEXED TTYS RUN OVER +NDMS==0 ;HAS DM11BB MODEM SCANNER (BUT IT'S NOT CONNECTED TO ANYTHING) +GOULDP==0 ;DOESN'T HAVE GOULD LPT (ANYMORE) +T300P==1 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==2 ;HAS TWO CHAOS NET INTERFACES +CHSBTB=0 ;CHAOSNET INTERFACE IS NEW, DOESN'T GET HUNG ANY MORE +CHAD0==440 ;CHAOSNET ADDRESS OF THIS PDP11 ITSELF +DLCADR==1440 ;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA DL10 (MX) +CHAD1==3040 ;SECOND INTERFACE +TEN11P==0 ;NO TEN-11 INTERFACE +ETHERP==0 ;NO ETHERNET +FTPULS==0 ;INITIALLY, MX DOES NOT GENERATE TEST PACKETS +FTGARB==1 ;SAVE LAST GARBAGE PACKET RECEIVED +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE +.MACRO ASPIRP BODY ;DEFINE LINE NUMBERS WITH AUTOSPEED +.ENDM ASPIRP +.ENDC ;MX-DL + +.IFM MX ;MX CONSOLE 11 +DL10P==0 ;DOES NOT HAVE DL10 +DTE20P==1 ;HAS DTE20 +NODDT==0 ;HAS DDT AND KLDCP +NFTTY==0 ;2 * # OF FIRST TTY THIS 11 +NDHS==2 ;NUMBER OF DH11'S +NDHUN==0 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==310 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==1 ;NUMBER OF DL11'S +CTYP==1 ;FIRST DL11 IS T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS THAT GO THROUGH MULTIPLEXED LINE (NONE) +NDMS==2 ;has 2 DM11BB modem scanners (really DH11AD) +GOULDP==0 ;DOESN'T HAVE GOULD LPT +T300P==0 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==0 ;NO CHAOS NET INTERFACE +TEN11P==0 ;NO TEN-11 CHAOS INTERFACE +ETHERP==0 ;NO ETHERNET +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE + +.MACRO ASPIRP BODY ;DEFINE LINE #S WITH AUTOSPEED +.IRP N,<1,3,4,5,6,7,10,11,12,13,14,15,16,17> + BODY +.ENDM +.ENDM ASPIRP + +TKS==177560 +TKB==177562 +TPS==177564 +TPB==177566 +.ENDC ;MX + +.IFM AI ;AI'S CHAOS-ETHER-GATEWAY PDP11 + +;THIS IS A PDP11/10, WE HAVE TO REDEFINE A FEW THINGS +.MACRO RTT +.ENDM +RTI==2 +RTT==2 +.MACRO SOB REG,TAG + DEC REG + BNE TAG +.ENDM SOB + +DL10P==0 ;HAS NO DL10 +DTE20P==0 ;DOES NOT HAVE DTE20 +NODDT==1 ;DOESN'T HAVE DDT (USE CARPET) +NFTTY==0 ;2 * # OF FIRST TTY THIS 11 +NDHS==0 ;NUMBER OF DH11'S +NDHUN==0 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==320 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==0 ;NUMBER OF DL11'S (ACTUALLY HAS ONE, BUT WE'RE NOT USING IT NOW) +CTYP==0 ;FIRST DL11 NOT T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS ON MULTIPLEXED LINE +NDMS==0 ;HAS NO DM11BB MODEM SCANNERS +GOULDP==0 ;DOESN'T HAVE GOULD LPT +T300P==0 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==2 ;HAS TWO CHAOS NET INTERFACES +CHSBTB==0 ;CHAOSNET INTERFACE IS NEW-STYLE, DOES NOT GET HUNG +CHAD0==426 ;CHAOSNET ADDRESS OF THIS PDP11 ITSELF (AI-MC-CROSS-STREET SUBNET) +CHAD1==3072 ;SECOND INTERFACE (9TH FLOOR LISP MACHINE SUBNET) +CHADD==426 ;The DOVER protocol translator only works for this address +TEN11P==0 ;USES TEN-11 INTERFACE FOR CHAOS NET TO AI-10 (NOT ANY MORE!) +T11ADR==2026 ;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA TEN-11 INTERFACE (AI) +NT11BF==3 ;THREE BUFFERS IN EACH DIRECTION FOR TEN-11 INTERFACE +ETHERP==1 ;ETHERNET +ETHHSN==6 ;MY HOST NUMBER BYTE, JNC SAYS I SHOULD USE 6 +NDVRBF==6 ;6 DOVER BUFFERS +DVRADR==1002 ;PUP ADDRESS OF DOVER +FTPULS==0 ;INITIALLY, AI DOES NOT GENERATE TEST PACKETS +FTGARB==1 ;DON'T SAVE LAST GARBAGE PACKET RECEIVED (LOW ON CORE) (not that low) +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE +.MACRO ASPIRP BODY ;DEFINE LINE NUMBERS WITH AUTOSPEED +.ENDM ASPIRP +.ENDC ;AI + +.IIF NDF NDHS, .ERROR MACHINE NAME NOT RECOGNIZED + +.IIF NZ DL10P, .IIF Z NFTTY, .ERROR TTY # 0 DOESN'T WORK WITH DL10 PROTOCOL + +;ASSIGN TTY INDICES, HARDWARE INDICES, ETC. + +TX==NFTTY ;TTY INDEX +HX==0 ;HARDWARE INDEX +NCT==0 ;NUMBER OF TTYS + +;SYSTEM CONSOLE (OUT OF ORDER) +.IFNZ CTYP + TX==TX+2 + NCT==NCT+1 +.ENDC + +;DH11 LINES + NFDHTY==TX + TX==TX+<32.*NDHS> + NCT==NCT+<16.*NDHS> + HX==HX+<2*NDHS> + NLDHHX==HX-2 ;UNITS 0-NLDHHX INCLUSIVE ARE DH11S + + TX==TX-<2*NDHUN> ;COMPENSATE FOR UNUSED LINES + NLDHTY==TX-2 ;LAST DH11 LINE INCLUSIVE + NCT==NCT-NDHUN + +;DL11 LINES + NFDLTY==TX + NFDLHX==HX + TX==TX+<2*NDLS>-<2*CTYP> + HX==HX+<2*NDLS> + NLDLHX==HX-2 + NCT==NCT+NDLS-CTYP + +;MULTIPLEXOR LINES + NFMPTY==TX + MPKHWR==HX + TX==TX+<2*NMPTYS> + HX==HX+2 + NCT==NCT+NMPTYS + +NLTTY==NFTTY+<2*NCT> ;2 * # OF FIRST TTY NOT THIS 11 +LASTTY==NLTTY-2 ;LAST VALID TTY INDEX + +.IFNZ NDMS ;DM11-BB MODEM SCANNER + + ;1.1-1.4 MODEM CHANNEL # + DMBSY==20 ;1.5 SCAN BUSY (R.O.) + DMSCN==40 ;1.6 SCANNER ON + DMIEN==100 ;1.7 INTERRUPT ENABLE + DMDON==200 ;1.8 DONE - SCANNER HAS FOUND SOMETHING + DMSTP==400 ;1.9 STEP SCANNER TO NEXT LINE (W.O.) 1.2 USEC. + ;2.1 MAINTENANCE MODE + DMCLR==2000 ;2.2 CLEAR RTS, DTR, SEC TX, LINE EN FOR ALL LINES (W.O.) + DMCSN==4000 ;2.3 CLEAR SCAN - CLEAR CSR AND MODEM STATUS MEMORY (W.O.) 19 USEC + DM2RX==10000 ;2.4 SECONDARY RECIEVE CHANGED ON SELECTED MODEM (R.O.) + DMCTS==20000 ;2.5 CLEAR TO SEND CHANGED ON SELECTED MODEM (R.O.) + DMCAR==40000 ;2.6 CARRIER DETECT CHANGED ON SELECTED MODEM (R.O.) + DMRNG==100000 ;2.7 RING CHANGED ON SELECTED MODEM (R.O.) + + LINENB==1 ;1.1 ENABLE SCANNING OF LINE + LINDTR==2 ;1.2 DATA TERMINAL READY + LINRQS==4 ;1.3 REQUEST TO SEND (FORCE BUSY ON 103E) + LIN2TX==10 ;1.4 SECONDARY TRANSMIT + LIN2RX==20 ;1.5 SECONDARY RECEIVE (R.O.) + LINCTS==40 ;1.6 CLEAR TO SEND (R.O.) + LINCAR==100 ;1.7 CARRIER DETECT (R.O.) + LINRNG==200 ;1.8 RING (R.O.) +.ENDC ;NDMS + +; KW11-L LINE FREQ CLOCK + +LKS=177546 ;1.8 CLOCK FLAG + ;1.7 INTER ENB +HNGDLY==3*60. ;CLEAR TO SEND OFF FOR 3 SECONDS => HANGUP + +.IFNZ GOULDP +;DEFINITIONS FOR GOULD LPT + +GLPCSR=166000 ;COMMAND STATUS REGISTER (NONSTANDARD) + ;COMMAND CODES + %GCFF==0 ;TOP-OF-FORM COMMAND + %GCGRF==1 ;GRAPHIC MODE COMMAND + %GCCUT==2 ;CUT COMMAND (NO CUTTER ON THIS MACHINE, THOUGH) + %GCON==3 ;TURN PRINTER ON + %GCOFF==4 ;TURN PRINTER OFF + %GCLSL==5 ;LAST LINE (GRAPHIC MODE). => 2 MORE SCAN LINES. + %GCION==6 ;INTERRUPT ON + %GCIOF==7 ;INTERRUPT OFF + %GCADV==201 ;ADVANCE ONE LINE + ;STATUS BITS + %GSNRD==400 ;NOT READY + %GSDON==2000 ;TRANSFER COMPLETE + %GSBSY==4000 ;BUSY + %GSVAC==10000 ;VACUUM FAULT + %GSPAP==20000 ;PAPER LOW + %GSTIM==40000 ;TIMEOUT + %GSERR==50400 ;ALL ERROR BITS + +GLPWC=166002 ;NEGATIVE WORD COUNT REG + +GLPCA=166004 ;CURRENT ADDRESS REG + +GLPBSZ==132. ;BUFFER SIZE (# CHARS PER LINE) + +NGLPBF==7 ;NUMBER OF BUFFERS + GB.STA==0 ;BUFFER STATE - DON'T CHANGE ORDER OF %GB CODES + %GBIDL==0 ;0 IDLE + %GBMP==2 ;2 ACTIVE AT M.P. LEVEL + %GBWRT==4 ;4 IN WRITE QUEUE + %GBPI==6 ;6 ACTIVE AT P.I. LEVEL + %GBDMA==8 ;8 ACTIVE AT D.M.A. LEVEL + GB.NXT==2 ;CIRC POINTER TO NEXT BUFFER + GB.FF==4 ;IF NON-ZERO, FF BEFORE THIS BUFFER + GB.NL==6 ;NUMBER OF BLANK LINES BEFORE THIS BUFFER + GB.PNT==10 ;-> NEXT BYTE TO INSERT + GB.DAT==12 ;DATA BEGINS HERE + GB.LEN==GB.DAT+GLPBSZ ;TOTAL NUMBER OF BYTES PER BUFFER + +.ENDC ;GOULDP + +.IFNZ CHAOSP +;DEFINITIONS OF CHAOS NET HARDWARE + +;USUAL ADDRESS IS 764140 . USUAL INTERRUPT VECTOR IS 270 . + +CAICSR=164140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN=164142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=164142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=164144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=164146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=164152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. + +;PACKET DEFINITIONS +;THESE ARE FOR 4K PACKET BUFFERS AND FOR THE ORIGINAL CHAOSNET PROTOCOL + +PKMAX==256. ;MAXIMUM LENGTH OF PACKET (INCLUDING ALL HARDWARE WORDS) +DATMAX==488. ;MAXIMUM NUMBER OF DATA BYTES +PKHDW==8 ;NUMBER OF HEADER WORDS +PKTMXW==+PKHDW ;MAX WORDS THROUGH PACKET SWITCH (SEE MOVDH ETC.) + +PKOP==1 ;BYTE INDEX OF THE OPCODE OF THE PACKET + %CORFC==1 + %COOPN==2 + %COCLS==3 + %COANS==5 + %COSNS==6 + %COSTS==7 + %CORUT==10 + %COLOS==11 + %COEOF==14 + %COUNC==15 +PKNBYT==2 ;WORD INDEX OF NUMBER OF BYTES IN PACKET +PKNBMS==170000 ;MASK FOR THE NUMBER OF BYTES +PKFC==2 ;WORD INDEX FOR THE FORWARD COUNT +PKFCMS==7777 ;IT IS THE TOP 4 BITS +PKDHST==4 ;DESTINATION HOST +PKDIND==6 ; " " " INDEX +PKSHST==10 ;SOURCE HOST +PKSIND==12 ;SOURCE INDEX +PKPKN==14 ;THE PACKET NUMBER +PKACN==16 ;THE ACK PACKET NUMBER +PKDAT==20 ;THE START OF THE DATA +.ENDC ;CHAOSP + +;STANDARD MACROS + +.MACRO PUSH X +.IRP Y, + MOV Y,-(SP) +.ENDM +.ENDM + +.MACRO POP X +.IRP Y, + MOV (SP)+,Y +.ENDM +.ENDM + +.MACRO CALL X + JSR PC,X +.ENDM + +.MACRO RET + RTS PC +.ENDM + +.MACRO SETOM LOC + ZZ===%COMPAT ;DON'T CARE WHETHER .+2 OR .+4 GETS STORED + %COMPAT===0 + MOV PC,LOC + %COMPAT===ZZ +.ENDM + +.MACRO MASK LEVEL + PUSH PS + MOV #_5,PS +.ENDM + +.MACRO UNMASK + POP PS +.ENDM + +.MACRO W +.=.+2 +.ENDM + +.MACRO T TAG ;usage is T TAG: STMNT +.=.-NFTTY +TAG +.=.+NFTTY +.ENDM + +.MACRO CONC A,B,C,D,E,F,G +A'B'C'D'E'F'G +.ENDM + +.MACRO INFORM A,B,C,D,E,F,G +.IF P1 +.PRINT /A'B'C'D'E'F'G +/ +.ENDC +.ENDM + +.MACRO MSG X +.NCHR ZZ,^\X\ + .WORD ZZ + .ASCII \X\ + .EVEN +.ENDM + +.MACRO .IREPT N,BOD +.REPT N +BOD +.ENDR +.ENDM + .IFNZ DL10P + .SBTTL DL10 CONTROL AREA + +ZZ==. +.=100000 + +DLXCSR: W ;DL10 11-SIDE CONTROL & STATUS REG + ;1.1-1.2 PIA + DLXIEN==4 ;1.3 ENABLE DLX11I TO INTERRUPT + DLXEEN==10 ;1.4 ENABLE ERRORS TO INTERRUPT + ;1.5 UNUSED + DLXPRT==40 ;1.6 PORT ENABLE (R.O.) + DLXZWC==100 ;1.7 CLEAR DLXWCO (W.O.) + DLXWCO==200 ;1.8 WORD COUNT OVERFLOW + DLXZPA==400 ;1.9 CLEAR DLXPAR (W.O.) + DLXPAR==1000 ;2.1 PAR ERR IN 10 MEM + DLXZNX==2000 ;2.2 CLEAR DLXNXM (W.O.) + DLXNXM==4000 ;2.3 NXM IN 10 MEM + DLXZ10==10000 ;2.4 CLEAR DLX10I (W.O.) + DLX10I==20000 ;2.5 INTERRUPT PDP10 + DLXZ11==40000 ;2.6 CLEAR DLX11I (W.O.) + DLX11I==100000 ;2.7 INTERRUPT PDP11 + +VERS: W ;.BYTE FIRST LINE, # OF LINES + ;SET BY -10. USED TO CHECK CONSISTENCY. + +DLXUP: W ;CHECK FOR UP-NESS IN BOTH DIRECTIONS + ;INCREMENTED BY 11 EVERY 1/60 SECOND, SETOM'ED BY 10 EVERY 1/2 SEC. + +TTYST: W ;LINE# TO START OUTPUT ON (I.E. SET OUTPUT DONE) + ;SET BY 10, CLEARED BY 11 + +TYILIN: W ;TYPEIN STATUS WORD - LINE NUMBER + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 +TYICHR: W ;TYPEIN CHARACTER - GOES WITH PRECEDING WORD + +TYOSTS: W ;STATUS WORD (OUTPUT DONE LINE #) + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 +TYOBSZ: W ;BUFFER SIZE FOR LINE WITH OUTPUT DINE (SET BY 11) + +TYOPNT: W ;BUFFER POINTER FOR TTY OUTPUT + ;SET BY 10 +TYOCNT: W ;BUFFER LENGTH FOR TTY OUTPUT + ;SET BY 10 +TYOLIN: W ;LINE NUMBER FOR TTY OUTPUT + ;SET BY 10, CLEARED BY 11 + +HNGLIN: W ;0000NN - LINE # NN HUNG UP + ;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES) + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 + +LPRLIN: W ;LINE NUMBER FOR SETTING LINE PARAMETERS + ;SET BY 10, CLEARED BY 11 +LPRLPR: W ;DH11 LPR REGISTER FOR SETTING LINE PARAMETERS + ;SET BY 10 +LPRBSZ: W ;BUFFER SIZE FOR SETTING LINE PARAMETERS + ;SET BY 10 + +EXDSTS: W ;STATUS WORD (EXAMINE/DEPOSIT 11 CORE) + ;1 = EXAMINE, 2 = DEPOSIT + ;SET BY 10, CLEARED BY 11 +EXDADR: W ;ADDRESS FOR ABOVE + ;SET BY 10 +EXDDAT: W ;DATA WORD FOR ABOVE + ;SET BY 10 (DEPOSIT) OR 11 (EXAMINE) + +GLPPTR: W ;BUFFER POINTER FOR GOULD OUTPUT +GLPCTR: W ;NUMBER OF BYTES YET TO BE GOBBLED +GLPTER: W ;ERROR STATUS, SET BY 11 +GLPGRF: W ;GRAPHIC MODE IF NON-ZERO, SET BY 10 + +;CHAOS NET SHARED VARIABLES +DLCINI: W ;WHEN THIS IS NON-ZERO, 11 RESETS ITS POINTERS AND CLEARS IT +DLCSP1: W ;SEND PACKET 1 (ILDB POINTER) +DLCSP2: W ;SEND PACKET 2 +DLCSS1: W ;SEND STATE 1 (0 IDLE, 1 TO 11, 2 OUTPUT DONE) +DLCSS2: W ;SEND STATE 2 +DLCRP1: W ;RECEIVE PACKET 1 (ILDB POINTER) +DLCRP2: W ;RECEIVE PACKET 2 +DLCRS1: W ;RECEIVE STATE 1 (0 IDLE, 1 READY FOR INPUT FROM 11, 2 INPUT DONE) +DLCRS2: W ;RECEIVE STATE 2 + +;^ ADD MORE HERE, E.G. IMP + +.IFNZ T300P +;DISK AREA. 14. WORDS 48. WORDS INTO THE DL-10 AREA. +.=100000+<60*2> + +DSCCHK: W ;MUST BE 2561 OCTAL TO MAKE SURE WE HAVE CORRECT PDP-10 PROGRAM +DSCREQ: W ;0 MEANS NO REQUEST. NON-ZERO MEANS 10 HAS PENDING REQUEST TO 11. +DSCDON: W ;0 MEANS NOT DONE, NON-ZERO MEANS 11 IS TELLING 10 IT'S DONE. +;NEXT 2 WORDS WRITTEN BY 11 TO TELL STATUS OF OPERATION +DSCFLT: W ;0 NO FAULT + %DFRST==100000 ; BIT 15=POWER CYCLED OR UNIBUS HUNG, SO CONTROLLER WAS RESET + ; BIT 12=Q ERROR, BIT 11=CMD NXM, BIT 10=CMD PAR + ; IF ONE OF THESE BITS IS ON, BITS 1-0 AND DSCSTS ARE THE ERROR ADDRESS + ; BITS 7-0 SYSTEM FAULT CODE IF LEFT BYTE IS ZERO + ; SEE THE 2561 OEM MANUAL FOR MEANING OF FAULT CODES +DSCSTS: W ;STATUS FROM 2561: + %DSRTR==100000 ;COMMAND WAS RETRIED + %DSECH==40000 ;UNCORRECTABLE DATA ERROR (ECC HARD) + %DSECC==20000 ;CORRECTED DATA ERROR + %DSIDE==10000 ;ID ERROR + %DSHCE==4000 ;ADDRESS ERROR (HEADER COMPARE ERROR) + %DSPRT==2000 ;WRITE-PROTECT STATUS OF SECTOR (ABORTS WRITE COMMAND) + %DSALT==1000 ;ALTERNATE-SECTOR STATUS (ABORTS READ, WRITE, AND CHECK) + %DSOVR==400 ;FIFO OVER-RUN, NOT CORRECTED BY 1 RETRY + %DSSKE==200 ;SEEK ERROR FROM DRIVE + %DSOFL==100 ;DRIVE OFF-LINE OR FAULT + %DSFLT==20 ;DRIVE FAULT + %DSNXM==10 ;NXM ON PDP11 MEMORY + %DSPAR==4 ;PARITY ERROR IN PDP11 MEMORY + %DSSFL==2 ;SYSTEM FAULT, SEE LOW BYTE OF DSCFLT + %DSWLK==1 ;DRIVE WRITE-LOCKED, WRITE ABORTED + +;FOLLOWING WORDS ARE WRITTEN BY 10 TO TELL WHAT TO DO +DSCCMD: W ;COMMAND OPCODE: + ;%DMNOP==0 ;DO NOTHING + ;%DMCST==1 ;READ OUT CONTROLLER STATE (NOT USEFUL SINCE NOT RETURNED TO 10) + %DMSNS==2 ;SENSE DRIVE STATE. DSCSTS GETS CODE FOR DRIVE TYPE IN + ; BITS 14-8 (10 FOR T-300), AND %DSWLK, %DSFLT, %DSOFL, %DSSKE + %DMTST==3 ;TEST SPECIFIED DRIVE (RUNS DIAGNOSTICS) + %DMREC==4 ;RECALIBRATE + %DMSEK==5 ;SEEK + %DMWRT==6 ;WRITE DATA + ;%DMFMT==7 ;WRITE FORMAT + ;%DMPWT==10 ;WRITE AND SET WRITE-PROTECT BIT + ;%DMAWT==11 ;WRITE AND SET ALTERNATE-SECTOR BIT + ;%DMCHK==12 ;READ AND CHECK ECC BUT DON'T STORE DATA + ;%DMLWT==14 ;LONG WRITE, WILL WRITE ECC AS WELL AS DATA + %DMRED==20 ;READ DATA. ADD 1-10 FOR VARIOUS RECOVERY FEATURES AS + ; DOCUMENTED IN THE 2561 OEM MANUAL. + ;%DMRID==40 ;READ IF FIELD, NOT USEFUL SINCE NOT RETURNED TO 10 +DSCDRV: W ;UNIT NUMBER +DSCCYL: W ;CYLINDER ADDRESS (THESE ARE COPIED BACK BY THE 11 IN CASE OF ERROR) +DSCHED: W ;HEAD ADDRESS +DSCSEC: W ;SECTOR ADDRESS +;WORD COUNT IS ALWAYS 12.*256. +;IF WE PUT IN SEEK-OVERLAP AN ATTENTION FEATURE WILL BE NEEDED +;THAT WOULD ALSO BE USED FOR DISK POWER-UP SIGNALLING +;THESE WORDS ARE SET UP BY THE 10 AS BYTE-POINTERS TO THE DATA +;TO BE TRANSFERRED. EACH BYTE POINTER CAN TRANSFER AT MOST 256 PDP10 WORDS +;DUE TO BRAIN-DAMAGE IN THE DL10, SO THERE ARE 4 OF THEM +DSCPNT: .BLKW 4 +.ENDC ;T300P + +DLXHGH:: +.=ZZ +.ENDC ;DL10P + .IFNZ DTE20P + .SBTTL DTE20 CONTROL AREA + +;LOCATIONS 400-437 ARE JUST BETWEEN US AND ITS +;LOCATIONS 440-457 ARE KNOWN ABOUT BY KLDCP ALSO + +;EPTDDT==441 ;START ADDRESS OF PDP10 NON TIME SHARING DDT +DTEFLG==444 ;NON TIME SHARING TYPEIN/TYPEOUT DONE FLAG (SET BY 11, CLEARED BY 10) +DTEF11==450 ;USED BY NON TIMESHARING TYPEIN COMMAND TO RETURN THE CHAR (SET BY 11) +DTECMD==451 ;NON TIME SHARING COMMAND (SET BY 10) +;COMMANDS THAT CAN GO IN DTECMD: + ;0-377 CHAR TO BE TYPED OUT + %DTTYI==3400 ;TYPE IN, CHAR RETURNED IN DTEF11 + %DTCLN==1001 ;60 CYCLE CLOCK ON + %DTCLF==1000 ;60 CYCLE CLOCK OFF + ;THERE ARE MILLIONS OF OTHERS, BUT WHO NEEDS 'EM? +DTECLK==445 ;60 CYCLE CLOCK FLAG (SET BY 11, CLEARED BY 10) +;DTESWR==457 ;SIMULATED SWITCH REGISTER (SET BY 11) + +;THE FOLLOWING LOCATIONS ARE ONLY USED IN TIME SHARING AND NOT KNOWN ABOUT BY KLDCP + +DTEVER==400 ;I/O VERSION NUMBER. .BYTE FIRST LINE, NUMBER OF LINES. + ;SET BY 10, CHECKED BY 11 + +DTECHK==401 ;INCREMENTED BY 11 60 TIMES PER SECOND, SETOMED BY 10 EVERY 1/2 SECOND + ;USED TO CHECK THAT 10 IS GETTING INTERRUPTS OK + +DTEINP==402 ;CONTROLS "BYTE TRANSFERS" FROM 11 TO 10 (INPUT DIRECTION). + ;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN XFER COMPLETE. + ;10 SHOULD SET UP DTEBPI IN EPT AND DO DATAO DTE, BEFORE SETTING DTEINP. + ;SEE COMMENTS BELOW DTEOUT FOR WHAT GOES IN DTEINP. +DTEOUT==403 ;CONTROLS "BYTE TRANSFERS" FROM 10 TO 11 (OUTPUT DIRECTION). + ;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN TRANSFER STARTS. + ;EACH SIDE KNOWS WHEN TRANSFER IS IN PROGRESS, DOESN'T TRY TO START + ; ANOTHER UNTIL IT HAS RECEIVED HARDWARE TRANSFER-DONE INTERRUPT. + ;10 SHOULD SET UP DTEBPO IN EPT BEFORE SETTING DTEOUT. + ;RH IS #BYTES EXPECTED, LH IS COMMAND+LINE#. COMMANDS ARE: + %DTTYO==1000 ;TELETYPE OUTPUT + ;%DTETI==2000 ;ETHERNET INPUT + ;%DTETO==3000 ;ETHERNET OUTPUT + ;^ ADD MORE COMMANDS HERE. NOTE: THE 4.1 BIT IS 1 FOR OUTPUT, 0 FOR INPUT. + +DTELSP==404 ;LINE# TO SET SPEED OF (SET BY 10, SETOMED BY 11) +DTELPR==405 ;DH11 LINE-PARAMETER-REGISTER,,BUFFER SIZE + +DTEOST==406 ;LINE# TO START OUTPUT ON (SET OUTPUT DONE). (SET BY 10, SETOMED BY 11) + + ;407 NOT USED + +DTETYI==410 ;TELETYPE INPUT + ;LH=LINE#, RH=CHAR RECEIVED. (SET BY 11, SETOM'ED BY 10) + +DTEODN==411 ;TELETYPE OUTPUT DONE + ;LH=LINE#, RH=BUFFER SIZE. (SET BY 11, SETOM'ED BY 10) + +DTEHNG==412 ;HANGUP/DIALIN WORD (SET BY 11, SETOM'ED BY 10) + ;0000NN - LINE # NN HUNG UP + ;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES) + +;^ ADD MORE HERE, NOT TO EXCEED LOCATION 437 + ;.IFNZ DTE20P + +;IOELEVEN RESIDES IN THE BOTTOM 14K OF THE CONSOLE PDP11, ALONG WITH 11DDT. +;I.E. LOCATIONS 0-70000. BE SURE TO USE .;11DDT 14K VERSION OF DDT. +;THE UPPER 14K CONTAIN KLDCP. THE FOLLOWING CALLS TO KLDCP ARE USED. +;THEY RETURN WITH C-BIT SET IF THEY LOSE (MICROCODE HUNG). + +;NOTE: KLDCP ENJOYS CLOBBERING REGISTER 0 (A). I DON'T +;KNOW IF ALL THESE CALLS DO, BUT WE'LL ASSUME THAT THEY DO. + +TENSW=EMT!145 ;UPDATE LOCATION DTESWR FROM THE SWITCHES + +EXAM=EMT!103 ;EXAMINE PDP10 MEMORY + ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 BYTES CONTAINING PDP10 ADDRESS (LOW BITS FIRST) + ;AFTER CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS (LOW BITS FIRST) + +EXAMT=EMT!104 ;EXAMINE PDP10 MEMORY + ;.WORD PDP10-ADDRESS + ;.WORD ADDRESS OF 3-WORD DATA BLOCK + +DPOS=EMT!105 ;DEPOSIT PDP10 MEMORY + ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS + ;AND REGISTER B HAS ADDRESS OF 3 BYTES CONTAINING ADDRESS + +DPOST=EMT!106 ;DEPOSIT PDP10 MEMORY + ;.WORD PDP10-ADDRESS + ;.WORD ADDRESS OF 3-WORD DATA BLOCK + +D10MON=EMT!111 ;DEPOSIT PDP10 MEMORY, -1 + ;.WORD PDP10-ADDRESS + +$PMSG=EMT!25 ;PRINT MESSAGE ON TTY + ;.WORD ADDRESS OF ASCIZ MESSAGE + +$CNTLC=100004 ;JUMP HERE TO "CONTROL C" BACK TO KLDCP + +;WHEN KLDCP IS IDLE, AND IN "ITS MODE", IT DOES JSR PC,3000 +;WHICH CALLS IOELEVEN'S MAIN PROGRAM. RETURN WITH "C" SET +;TO READ AND EXECUTE ONE KLDCP COMMAND LINE. RETURN WITH "C" +;CLEAR TO PRINT KL10 HALTED OR CLOCK ERROR STOP MESSAGE. +;LOCATIONS 3004, 3006 MUST CONTAIN .RAD50/IOELEV/ +;IOELEV WILL RUN ON KLDCP'S STACK. + ;.IFNZ DTE20P +;INFORMATION ABOUT THE DTE20. +;EXCEPT FOR BYTE TRANSFER, WE USE THE TIME-TESTED SUBROUTINES PROVIDED BY KLDCP. + +;THE INTERRUPT VECTOR IS AT 774, BUT WE CAN'T USE IT BECAUSE WOULD HAVE +;TO COORDINATE THINGS WITH KLDCP, WHICH IS OBVIOUSLY IMPOSSIBLE. + +DLYCNT=174400 ;2.6-2.7 UNIBUS ADDRESS EXTENSION FOR BYTE TRANSFER DMA + ;1.1-2.5 14-BIT 2'S COMPLEMENT OF NUMBER OF HALF-MICROSECONDS + ; TO DELAY BETWEEN PI0 INTERRUPTS IN BYTE TRANSFER + +TO10AD=174420 ;ADDRESS (WORD OR BYTE) OF TO-10 BYTE TRANSFER DATA + +TO10BC=174414 ;1.1-2.3 NEGATIVE BYTE COUNT, 2.7 LAST XFER + ;NORMALLY SET BY 10 WITH DATAO DTE, + ;TO10 XFER STARTS WHEN BOTH TO10AD AND TO10BC HAVE BEEN LOADED + +TO11AD=174422 ;ADDRESS (WORD OR BYTE) OF TO-11 BYTE TRANSFER DATA + +TO11BC=174416 ;1.1-2.3 NEGATIVE BYTE COUNT FOR TO-11 BYTE TRANSFER + ;2.5=1 => TO-11 TRANSFER IS 8-BIT BYTES, =0 => 16-BIT WORDS + ;2.6=1 => "ASCIZ" MODE (WHICH WE DON'T USE, OF COURSE) + ;2.7=1 => LAST XFER, UPON COMPLETION INTERRUPT BOTH 10 AND 11 + ; =0 => ONLY INTERRUPT 11. 11 CAN CHANGE TO11AD, TO11BC, CONTINUE. + ;TO11 XFER STARTS WHEN BOTH TO11AD AND TO11BC HAVE BEEN LOADED + ;THE TRANSFER HAPPENS USING DMA (NPR) IN 11, PI LEVEL 0 IN 10. + +STATUS=174434 ;DTE20 STATUS REGISTER + ;READS: + %STDNI==100000 ;2.7 TO10 XFER DONE WITHOUT ERROR + %STERI==20000 ;2.5 TO10 XFER ABORTED BY ERROR + ;2.4 DATA OUT OF DTE RAM IS ALL ZERO (MAINT) + %STINV==4000 ;2.3 PDP10 IS INTERRUPTING PDP11 + ;2.2 DEPOST OR EXAMINE WORD ONE (MAINT) + ;2.1 PDP11 MEMORY PARITY ERROR IN TO10 XFER + ;1.9 PDP11 IS INTERRUPTING PDP10 + %STDNO==200 ;1.8 TO11 XFER DONE WITHOUT ERROR + ;1.7 E BUFFER SELECT (MAINT) + ;1.6 TO11 XFER STOPPED DUE TO ZERO BYTE (IN ASCIZ MODE) + ;1.5 TO11 XFER OR PDP10 EXAMINE ENCOUNTERED EBUS PARITY ERROR + ;1.4 1 => RESTRICTED MODE + ;1.3 0 => EXAMINE/DEPOSIT IN PROGRESS, 1 => DONE + %STERO==2 ;1.2 TO11 XFER ABORTED BY ERROR + ;1.1 1 => DTE ENABLED TO INTERRUPT PDP11 + ;WRITES: + %STCLI==51000 ;2.6+2.4+2.1 CLEAR TO10 XFER DONE AND ERROR FLAGS + %STUNV==2000 ;2.2 CLEAR PDP10 INTERRUPTING PDP11 + %STINX==400 ;1.9 SET PDP11 INTERRUPTING PDP10 + %STCLO==121 ;1.7+1.5+1.1 CLEAR TO11 XFER DONE AND ERROR FLAGS + ;1.6 ENABLE INTERRUPTS + ;1.4 DISABLE INTERRUPTS + +DIAG1=174430 ;DIAGNOSTIC WORD 1, INCLUDES FLAGS + %D1ERR==4000 ;2.3 KL10 CLOCK ERROR STOP + %D1RUN==2000 ;2.2 KL10 RUN INDICATOR (1 IF 11 WANTS 10 TO RUN) + %D1HLT==1000 ;2.1 KL10 HALT INDICATOR (1 IF 10 DOES A JRST 4) + +DIAG3=174436 ;DIAGNOSTIC WORD 3, INCLUDES FLAGS + %D3BYT==1 ;1.1 WRITING 0 SETS TO10 XFER IN WORD MODE, 1 BYTE MODE + ;THERE'S NOTHING ELSE OF THE SLIGHTEST USE IN THIS REGISTER, + ;SO IT'S OK TO WRITE IT AT ANY TIME. +.ENDC ;DTE20P + + .SBTTL LOW CORE + +.IFZ DTE20P ;IF USING DTE20, THESE ARE SET UP BY KLDCP +.=4 + TRAP4 + 340 + TRAP10 + 340 +; TRAP14 ;SET UP BY 11DDT +; 340 +.=20 + TRAP10 ;IOT + 340 + PWRFAL + 340 + TRAP10 ;EMT + 340 + TRAP10 ;TRAP + 340 +.ENDC ;DTE20P + +;CHAOS NET INTERRUPT VECTORS ARE UNFORTUNATELY NOT IN A REASONABLE ARRAY +.IFGE CHAOSP-1 +.=270 + .WORD CHS0BK,5_5 + ;274 IS INTERVAL TIMER +.ENDC ;CHAOSP-1 +.IFGE CHAOSP-2 +.=230 + .WORD CHS1BK,5_5 + ;234 IS INTERVAL TIMER +.ENDC ;CHAOSP-2 +.IFGE CHAOSP-3 +.=240 + .WORD CHS2BK,5_5 + ;244 IS INTERVAL TIMER +.ENDC ;CHAOSP-3 +.IFGE CHAOSP-4 + .ERROR WHERE DOES THE FOURTH CHAOSNET INTERRUPT VECTOR GO? +.ENDC ;CHAOSP-4 + +.IFNZ ETHERP +.=400 + ETHOBK + 5_5 + ETHIBK + 5_5 + ETHOBK ;COLLISION + 5_5 +.ENDC ;ETHERP + +.IFNZ T300P +.=254 + DSKBRK + 240 ;BR5 +.ENDC ;T300P + +.=300 +.REPT NDMS ;DM11s go in floating vectors +CONC DM,\.RPCNT+1,BRK + 240 ;INTERRUPTS ON BR4 BUT WE MASK TO BR5 ANYWAY +.ENDR ;NDMS + +.IFNZ NDLS +.=60 + DL1IBK ;FIRST DL11 LINE IS PDP11'S CONSOLE TTY, DIFFERENT ADDRESS + 240 ;AGAIN INTERRUPTS ON BR4 BUT MASK TO BR5 SO CAN USE DH11 ROUTINES W/O FEAR + DL1OBK + 240 +.ENDC ;NDLS +.=310 +.REPT NDLS-1 ;DL11S AFTER THE FIRST ARE IN FLOATING VECTORS +CONC DL,\.RPCNT+2,IBK + 240 +CONC DL,\.RPCNT+2,OBK + 240 +.ENDR + +.=DHIBAS ;DON'T RELY ON RANDOM FLOATING VECTOR TO + ;COME OUT RIGHT, E.G. IF THERE IS A DL11 + ;THERE WHICH WE AREN'T USING. +.REPT NDHS ;DH11S ARE IN FLOATING VECTOR AFTER DL11[E]S +CONC DH,\.RPCNT+1,IBK ;DH11 #n RECEIVE + 240 +CONC DH,\.RPCNT+1,OBK ;DH11 #n TRANSMIT & ERROR + 240 +.ENDR ;NDHS +.=100 + CLKBRK ;KW11-L 60-CYCLE CLOCK + 300 ;ON BR6 + +.IFNZ GOULDP +.=174 + GLPBRK + 300 ;BR5 BUT NEED TO LOCK OUT CLOCK SO MASK 6 +.ENDC ;GOULDP + +.IFG NMPTYS +.=56 +MPXENB::0 ;NONZERO TO ENABLE MULTISCHLUNKER +.ENDC + +.IFZ DTE20P ;IF DTE20, KLDCP SUPPLIES THE STACK +.=1000 +STKBAS:: + JMP INIT ;START AT 1000 IS CONVENTIONAL +.IFF ;DTE20P +.=3000 ;ENTRY VECTOR + JMP @#INIT +SADR=.-2 ;ARG OF THE JMP@# IS CHANGED AFTER INITIALIZATION + .RAD50 /IOELEV/ +.ENDC ;DTE20P + + .SBTTL TEN-11 CHAOSNET COMMUNICATION AREA + +.IFNZ TEN11P +T11BFL==8+<2*PKTMXW> ;BYTE LENGTH OF A PACKET BUFFER + ;FIRST 8 BYTES ARE BUFFER-FULL FLAG AND CKSM +.IIF NE T11BFL-<*4>, .ERROR T11BFL NOT MULTIPLE OF 4 + +.IIF NE .-1004, .ERROR CHAOSNET TEN-11 COMMUNICATION AREA NOT AT RIGHT ADDRESS + +;THIS AREA IS SHARED WITH THE PDP10 VIA TEN-11 INTERFACE. + + .WORD "CH,1 ;ERROR CHECK AND VERSION NUMBER +T11I10: .WORD 0,0 ;SET NON-ZERO BY 11 TO REINITIALIZE 10 +T11I11: .WORD 0,0 ;SET NON-ZERO BY 10 TO REINITIALIZE 11 + .WORD T11BFL,NT11BF ;BUFFER SIZE, NUMBER OF BUFFERS + .BLKW 8 ;SPARE WORDS +T11OBF: .BLKB T11BFL*NT11BF ;TO-10 BUFFERS + T11OBE==. ;END OF TO-10 BUFFERS +T11IBF: .BLKB T11BFL*NT11BF ;FROM-10 BUFFERS + T11IBE==. ;END OF FROM-10 BUFFERS +;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR +;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE. +;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS +;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW, +; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED +; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT. +;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0. +.ENDC ;TEN11P + + .SBTTL CONFIGURATION + +; TABLES INDEXED BY H (PER HARDWARE UNIT) + +.MACRO DHTE AD ;DH11 REGISTER ADDRESS GENERATOR +.REPT NDHS + +<20*.RPCNT> +.ENDR +.ENDM + +.MACRO DLTE AD ;DL11 REGISTER ADDRESS GENERATOR, FIRST IS WIERD +.IFNZ NDLS + 177560+<&7> +.REPT NDLS-1 + +<10*.RPCNT> +.ENDR +.ENDC ;NDLS +.ENDM + +.MACRO DMTE AD ;DM11 register address generator + .REPT NDMS + +<10*.RPCNT> ;a DM11 eats 8 locations + .ENDR +.ENDM + +DMCSR: DMTE 170500 ;first DM11 is at 170500 + +DMLSR: DMTE 170502 ;selected line status at 170502 + +DHSCR: DHTE DHCBAS ;SYSTEM CONTROL REGISTER + ;1.1-1.4 LINE NUMBER + ;1.5-1.6 MEMORY ADDRESS EXTENSION + DHRENB==100 ;1.7 RECEIVER INTERRUPT ENABLE + ;1.8 RECEIVER INTERRUPT + ;1.9 CLEAR NXM FLAG + ;2.1 MAINTENANCE MODE + DHSNXM==2000 ;2.2 NXM FLAG (GENERATES XMT INTERRUPT) + ;2.3 MASTER CLEAR + DHSENB==10000 ;2.4 STORAGE SILO FULL INTERRUPT ENABLE + DHTENB==20000 ;2.5 TRANSMITTER & NXM INTERRUPT ENABLE + ;2.6 STOARGE FULL INTERRUPT + DHTDON==100000 ;2.7 TRANSMITTER DONE INTERRUPT + +DLKS==DHSCR + DLTE 175610 ;KEYBOARD STATUS REGISTER + ;1.1 PAPER TAPE READER ENABLE (WO) + ;1.2 DATA TERMINAL READY (RW) + ;1.3 REQUEST TO SEND (RW) + ;1.4 SECONDARY TRANSMIT DATA [OR MAKE BUSY] (RW) + ;1.5 UNUSED + ;1.6 DATASET INTERRUPT ENABLE (RW) + ;1.7 RECEIVE INTERRUPT ENABLE (RW) + ;1.8 RECEIVE DATA READY (RO) + ;1.9 UNUSED + ;2.1 UNUSED + ;2.2 SECONDARY RECEIVE DATA (RO) + ;2.3 RECEIVE ACTIVE (RO) + ;2.4 CARRIER DETECT (RO) + ;2.5 CLEAR TO SEND (RO) + ;2.6 RING INDICATOR (RO) + ;2.7 DATASET STATUS CHANGE (RO) + +DHNRC: DHTE DHCBAS+2 ;NEXT RECEIVED CHARACTER + ;1.1-1.8 THE CHARACTER + ;1.9-2.3 LINE NUMBER + %DXPAR==10000 ;2.4 CHAR HAS WRONG PARITY + %DXBRK==20000 ;2.5 FRAMING ERROR (BREAK) + %DXOVR==40000 ;2.6 OVERRUN, PREVIOUS CHARS LOST + ;2.7 1 => THIS WORD VALID +DLKB==DHNRC + DLTE 175612 ;KEYBOARD INPUT REGISTER + ;1.1-1.8 RECEIVED DATA + ;2.4 PARITY ERROR (RO) + ;2.5 FRAMING ERROR (RO) + ;2.6 OVERRUN (RO) + ;2.7 OR OF ERROR BITS (RO) + +DHLPR: DHTE DHCBAS+4 ;LINE PARAMETER REGISTER + ;1.1-1.2 CHARACTER LENGTH 0=5, 1=6, 2=7, 3=8 (PARITY BIT EXTRA) + ;1.3 1 => EXTRA STOP BIT + ;1.5 ENABLE PARITY + ;1.6 0 -> EVEN PARITY, 1 => ODD + ;1.7-2.1 RECEIVER SPEED + ; 0 OFF, 1 50, 2 75, 3 110, 4 134.5, 5 150, 6 200, 7 300 + ; 10 600, 11 1200, 12 1800, 13 2400, 14 4800, 15 9600, 16 A, 17 B + ;2.2-2.5 TRANSMITTER SPEED, SAME CODES AS RECEIVER + ;2.6 HALF DUPLEX + ;2.7 ECHOPLEX + +DHCA: DHTE DHCBAS+6 ;CURRENT ADDRESS +DLCA==DHCA + .IREPT NDLS,0 + +DHBC: DHTE DHCBAS+10 ;BYTE COUNT (MINUS) +DLBC==DHBC + .IREPT NDLS,0 ;POSITIVE FOR DLS + +DHBAR: DHTE DHCBAS+12 ;BUFFER ACTIVE REGISTER + ;BIT = 1 IF XMT ACTIVE ON CORRESP LINE, NUMBERED RIGHT TO LEFT +DLPS==DHBAR + DLTE 175614 ;PRINTER STATUS + ;1.1 SEND BREAK (RW) + ;1.3 LOOP BACK (RW) + ;1.6 INTERRUPT ENABLE (RW) + ;1.7 TRANSMITTER READY (RO) + +DHBCR: DHTE DHCBAS+14 ;BREAK CONTROL REGISTER + ;BIT = 1 => SEND BREAK ON CORRESP LINE, NUMBERED RIGHT TO LEFT +DLPB==DHBCR + DLTE 175616 ;PRINTER BUFFER + ;1.1-1.8 DATA TO TRANSMIT + +DHSSR: DHTE DHCBAS+16 ;SILO STATUS REGISTER + ;1.1-1.6 SILO ALARM LEVEL + ;1.7-1.8 READ EXTENDED ADDRESS (R.O.) + ;1.9-2.5 SILO FILL LEVEL (R.O.) + ;2.7 MAINTENANCE PATTERN (W.O.) + +DHOAC: .IREPT NDHS,0 ;BIT ON IF SOFTWARE THINKS LINE'S TRANSMITTER IS ACTIVE +DLOAC==DHOAC + .IREPT NDLS,0 ;NON-ZERO IF LINE'S TRANSMITTER IS ACTIVE + +DHTYNO: .IREPT NDHS, NFDHTY+<32.*.RPCNT> ;TTY INDEX OF FIRST LINE ON THIS DH11 +DLTYNO==DHTYNO +.IIF NZ CTYP,0 ;TTY INDEX OF LINE ON THIS DL11 +.IREPT NDLS-CTYP,NFDLTY+<2*.RPCNT> + +STROUT: .IREPT NDHS, STRDH ;OUTPUT-START ROUTINES + .IREPT NDLS, STRDL +.IIF NZ NMPTYS, STRMPK + + .BLKB NFTTY ;AVOID LABEL OVERLAPPAGE + +;TABLES INDEXED BY I (PER LINE) + +T HDWR: ;HARDWARE UNIT INDEX, GOES IN H +.IIF NZ CTYP, NFDLHX + .REPT NDHS + ZZ==.RPCNT*2 + .REPT 16. + ZZ ;16 LINES ON EACH DH-11 + .ENDR + .ENDR + .=.-<2*NDHUN> +.IREPT NDLS-CTYP,NFDLHX+<2*.RPCNT>+<2*CTYP> +.IREPT NMPTYS, MPKHWR ;MULTIPLEXOR-KLUDGE TTYS + +T DHLSEL: ;DH11 LINE SELECT WORDS +.IIF NZ CTYP, 0 ;NONE FOR CTY + .REPT NDHS + .REPT 16. + DHTENB+DHRENB+.RPCNT + .ENDR + .ENDR + +T DHLBIT: ;BIT CORRESPONDING TO THIS LINE IN DHBAR, ETC. +.IIF NZ CTYP, 0 ;NONE FOR CTY + .REPT NDHS + .REPT 16. + 1_.RPCNT + .ENDR + .ENDR + +T BUFPNT: ;BUFFER POINTERS + .IREPT NCT, BUFFRS+<.RPCNT*MAXBSZ> + +T BUFSIZ: ;BUFFER SIZES (I.E. AMOUNT TO USE AT CURRENT SPEED) + .REPT NCT + 0 ;SET DURING INITIALIZATION + .ENDR + +T NRMIPC: ;NORMAL INPUT CHARACTER PROCESSING ROUTINES +.IIF NZ CTYP, RCV ;CTY NORMAL INPUT + .REPT 16.*NDHS + DHNRMI ;DH11 TTY NORMAL INPUT + .ENDR + .=.-<2*NDHUN> +.IREPT NDLS-CTYP,RCV ;DL11 NORMAL INPUT +.IREPT NMPTYS, RCV ;NORMAL INPUT FOR TTYS ON MULTIPLEXOR-KLUDGE +.IIF NE .-NRMIPC-NLTTY, .ERROR BARF AT NRMIPC +.IFNZ NMPTYS + .=NRMIPC+MPXIDX + MPXINP ;INPUT FROM THE MULTIPLEXED LINE IS SPECIAL + .=NRMIPC+NLTTY +.ENDC + +T TTYIPC: ;CURRENT INPUT CHAR PROCESSING ROUTINES + .BLKW NCT ;SET UP AT INIT TIME +.IIF NE .-TTYIPC-NLTTY, .ERROR BARF AT TTYIPC + +T AUTOSP: ;IF NON-ZERO, LINE GOES INTO AUTOSPEED WHEN DIALED UP + .REPT NCT ;IF MINUS ALSO WHEN BREAK SEEN + ZZ===. + ASPIRP ^\ + .IIF EQ .RPCNT+-N,+1 ;THIS LINE AUTOSPEED ON DIALUP + .IIF EQ .RPCNT++N,-1 ;ALSO ON BREAK + \ + .IIF EQ .-ZZ, 0 ;THIS LINE NOT AUTOSPEED + .ENDR +.IIF NE .-AUTOSP-NLTTY, .ERROR BARF AT AUTOSP + +.IFM MX +M2LMAP: ;MAP FROM DM11-BB CHANNEL NUMBERS TO TTY INDICES + 2*1 ;0 T01 + 0 ;1 NONE + 0 ;2 NONE + 2*4 ;3 T04 + 2*5 ;4 T05 + 2*6 ;5 T06 + 2*7 ;6 T07 + 2*10 ;7 T10 + 2*11 ;10 T11 + 2*12 ;11 T12 + 2*13 ;12 T13 + 2*14 ;13 T14 + 2*15 ;14 T15 + 2*16 ;15 T16 + 2*17 ;16 T17 + 0 ;17 NONE + 2*21 ;20 T21 + 2*22 ;21 T22 + 2*23 ;22 T23 + 2*24 ;23 T24 + 2*25 ;24 T25 + 2*26 ;25 T26 + 2*27 ;26 T27 + 2*30 ;27 T30 + 2*31 ;30 T31 + 2*32 ;31 T32 + 2*33 ;32 T33 + 2*34 ;33 T34 + 2*35 ;34 T35 + 2*36 ;35 T36 + 2*37 ;36 T37 + 2*40 ;37 T40 +.ENDC ;MX + +.IIF NE NDMS, .IIF NE .-M2LMAP-<40*NDMS>, .ERROR Too few M2LMAP entries for DM11s. + +.IFNZ NDMS + +T DIALED: ;0 IF LINE NOT DIALED UP (OR NO MODEM CONTROL ON THIS LINE) + .REPT NCT ;+ IF DIALED UP (CLEAR TO SEND IS ON) + 0 ;- IF CLEAR TO SEND DROPPED, INC EACH TICK, REACHES 0 => HUNG UP + .ENDR + +.ENDC ;NDMS + +T TTYHNG: ;DIALUP/HANGUP STATUS WAITING TO BE SENT TO 10 (0 IF NONE) + .REPT NCT + 0 + .ENDR + +T TYPING: ;POSITIVE IF LINE IS TYPING OUT FOR 10 + .REPT NCT ; WHICH MEANS -10 SHOULD BE INFORMED WHEN TYPEOUT IS FINISHED + 0 ;0 FOR NO -10 TYPEOUT, MINUS TO SEND AFTER TYPEOUT + .ENDR + +;MISC VARIABLES + +DLXOFF: -1 ;NON-ZERO IF DL10 PORT TURNED OFF BY 10 +NO.ITS: -1 ;NON-ZERO IF HAVEN'T ESTABLISHED COMMUNICATION WITH ITS YET +VERSN: .BYTE NFTTY/2,NCT ;I/O VERSION NUMBER +DMINI: 0 ;NON-ZERO => MODEM SCANNER JUST TURNED ON, GETTING INITIAL STS +WAKE: 0 ;CLOCK INTERRUPT WAKE UP MAIN PROGRAM FLAG +HNGSIG: 0 ;NUMBER OF NON-ZERO TTYHNG WORDS +10RQ: 0 ;LIGHT HACKS +LITHSE: 7 +.IFNZ DTE20P +CLKENB: 0 ;KL10 WANTS 11 TO RELAY CLOCK INTERRUPTS +KLDCPF: 0 ;NON-ZERO => USER WANTS TO GIVE A COMMAND TO KLDCP +DDTMOD: 0 ;NON-ZERO => DDT MODE TTY INPUT +DDTCHR: -1 ;NON-NEGATIVE => CHAR TYPED FOR DDT +CURSWR: 52525 ;LAST SWITCHES SENT TO -10 +OUTCMD: 0 ;0 IF OUTPUT TRANSFER IDLE + ;ELSE CURRENT COMMAND / 400 +OUTSVI: -1 ;LINE# OF CURRENT OUTPUT TRANSFER +OUTSVC: -1 ;#BYTES OF CURRENT OUTPUT TRANSFER +INPCMD: 0 ;0 IF INPUT TRANSFER IDLE + ;ELSE CURRENT COMMAND / 400 +INPSVI: -1 ;LINE# OF CURRENT INPUT TRANSFER +INPSVC: -1 ;#BYTES OF CURRENT INPUT TRANSFER +.ENDC ;DTE20P +.IFNZ NMPTYS +MPXOAC: 0 ;0 IDLE, -1 SENDING HEADER, 1 SENDING DATA +MPXOLN: 0 ;2 x MPXK# OUTPUTTING FOR +MPXSEL: NFMPTY ;TTY INDEX SELECTED FOR MPX INPUT +MPXPNT: .IREPT NMPTYS,0 ;POINTER TO CRUFT TO SEND TO EACH MPXED LINE +MPXNBT: .IREPT NMPTYS,0 ;# BYTES TO SEND, 0 IF IDLE +MPXHED: .BYTE 0,0 ;MPX OUTPUT HEADER: 200+MPXK#, BYTE COUNT +.ENDC ;NMPTYS + + .SBTTL CHAOSNET VARIABLES & TABLES + +.IFNZ CHAOSP + +NSUBNT==80. ;MAXIMUM CAPACITY 80. SUBNETS + +.IFNZ DL10P ;DL10 UNSHARED +DLCRBN: 0 ;CURRENT RECEIVE (11 to 10) BUFFER (0 OR 2) +DLCNXT: .WORD 2,0 ;FOR SWITCHING BUFFERS +DLCIBF: .BLKW PKMAX ;DL10 INPUT BUFFER +.ENDC ;DL10P + +.IFNZ TEN11P ;TEN11 UNSHARED +T11OBP: T11OBF ;NEXT BUFFER TO 10 +T11IBP: T11IBF ;NEXT BUFFER FROM 10 +T11IBA: 0 ;NON-ZERO MEANS INPUT BUFFER ACTIVE, T11IBP NEEDS ADVANCING + ;THIS IS SEPARATE FROM CHISTS+CHXT11 FOR GOOD REASONS +T11CKE: 0 ;COUNT OF TEN-11 CHECKSUM ERRORS +T11TIM: 0 ;TIMEOUT ON TRANSMISSION OF PACKET TO 10 +.ENDC ;TEN11P + +.IFNZ ETHERP +ETHSBN==2 ;SUBNET WHICH IS THE ETHERNET +.SEE ETHHSN ;MY HOST NUMBER BYTE (DEFINED IN MACHINE CONFIGURATION AREA) +ETHMXH==15.-1 ;MAXIMUM NUMBER OF HOPS (-1 => BUG IN XEROX PROGRAMS) +ETHIBF: .BLKW PKTMXW+1 ;INPUT FROM ETHERNET BUFFERED HERE (+1 HARDWARE BUG?) +ETHHDW==PKHDW-2 ;ALLOW FOR OVERLAP OF CHAOSNET HEADER AND 2-WORD ETHERNET HEADER + ;THIS IS THE OFFSET (IN WORDS) WHERE THE ETHERNET PACKET STARTS + +;HERE IS A PACKET USED TO BUILD THE ETHERNET BROADCAST GATEWAY INFO. WHAT A CROCK. +EGTBUF: .BLKW PKHDW ;SPACE FOR CHAOSNET HEADER +EGTPLN: 0 ;PUP LENGTH + 201 ;PUP TYPE 201 +EGTPID: .WORD 0,0 ;PUP IDENTIFIER + 0 ;DESTINATION (BROADCAST) + .WORD 0,2 ;DEST SOCKET 2 +EGTSRC: .BYTE ETHHSN,ETHSBN ;SOURCE (ME) + .WORD 0,2 ;SOURCE SOCKET 2 +EGTSBN: ;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST + .BLKW 2*NSUBNT + 0 ;PUP CHECKSUM + +.IF DF NDVRBF +DVRHST: 0 ;ZERO IF IDLE, OR FOREIGN HOST USING +DVRIDX: 0 ;FOREIGN INDEX +DVRLIX: 0 ;LOCAL INDEX (AOS EACH TIME) +DVRTIM: 0 ;COUNTS UP TO IDLE THE FOREIGN HOST +DVRRTR: 0 ;COUNTS UP FOR RETRANSMISSION + +DVRBFL==2*+1> ;NUMBER OF BYTES IN A DOVER BUFFER (HOLDS PUP IN CHAOSNET PACKET) +DVRBUF: .BLKB DVRBFL*NDVRBF ;RING OF BUFFERS HERE +DVRBF2: .BLKW PKHDW+2 ;BUFFER FOR SENDING STS/OPN/CLS BACK (ALSO END OF RING) +DVRBFP: DVRBUF ;POINTER TO NEXT BUFFER TO GO OUT TO DOVER +DVRMSK: 0 ;MASK OF WHICH BUFFERS CONTAIN PACKETS (MSB = DVRBFP PKT) + .IIF GT NDVRBF-16., .ERROR NDVRBF MAXIMUM OF 16. ALLOWED +DVRPKP: 0 ;IF NON-ZERO, POINTER TO SPECIAL PACKET TO SEND +DVRID: 0 ;ID FOR NEXT PACKET EXPECTED BY DOVER, THIS PACKET IS OR + ; WILL BE IN THE BUFFER DVRBFP POINTS AT +DVROFS: 0 ;ID OFFSET, SUBTRACT FROM CHAOS ID TO GET PUP ID +NDVRFK: 0 ;*** TEMPORARY KLUDGE *** +.ENDC ;NDVRBF +.ENDC ;ETHERP + +PULSAR: 0 ;COUNTS DOWN TO 0 THEN TRIGGERS TRANSMISSION OF A "TEST MESSAGE" +PULSON: FTPULS ;IF THIS IS NON-ZERO, FEATURE IS ENABLED, VALUE IS TICKS BETWEEN PULSES +USECBL: 0 ;IF NON-ZERO, 10 TALKING TO SELF STILL GOES THROUGH CABLE + +NCHX==DL10P+TEN11P+CHAOSP+<2*ETHERP> ;NUMBER OF ENTRIES IN SOURCE AND SINK TABLES +.IIF DF NDVRBF, NCHX==NCHX+1 + +;METERS ETC. +.IFNZ FTGARB +CHSGBF: .BLKW PKMAX ;HOLDS LAST PACKET THAT CAME IN WITH A CHECKSUM ERROR +CHSGBH: 0 ;UNIBUS ADDRESS OF INTERFACE THAT ABOVE CAME IN ON +CHSGBS: 0 ;STATUS REGISTER THAT GOES WITH ABOVE +CHSGBC: 0 ;BIT COUNT THAT GOES WITH ABOVE +.ENDC ;FTGARB + +;FOLLOWING HAVE SEPARATE ENTRIES FOR EACH CABLE +NPKSGB: .IREPT CHAOSP+ETHERP,0 ;COUNTS THE NUMBER OF PACKETS RECEIVED WITH CHECKSUM ERRORS +HPKSGB: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSRL: .IREPT CHAOSP+ETHERP,0 ;COUNTS THE NUMBER OF PACKETS RAM LOST, + ; I.E. DIDN'T COME IN WITH A CHECKSUM ERROR BUT AFTER + ; READING IT OUT HAD ONE. EITHER THE PACKET WAS THE + ; WRONG LENGTH, OR THE RAM IS LOSING, OR HARDWARE + ; CLOBBERAGE. FOR ETHERNET IS PUP CKSM ERR COUNT + ;THIS WORD ALSO IS WHERE BIT COUNT ERRORS WOULD END UP +HPKSRL: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +CHSRLH: 0 ;UNIBUS ADDRESS OF INTERFACE THAT ABOVE LAST HAPPENED ON. +CHSRLC: 0 ;RESIDUAL BIT COUNT FOR ABOVE +NPKSLS: .IREPT CHAOSP,0 ;NUMBER OF PACKETS LOST ACCORDING TO LOSS COUNT IN HARDWARE +HPKSLS: .IREPT CHAOSP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSAB: .IREPT CHAOSP+ETHERP,0 ;NUMBER OF TRANSMISSIONS ABORTED (BY COLLISION OR RECEIVE-BUSY) +HPKSAB: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSI: .IREPT NCHX,0 ;TOTAL NUMBER OF PACKETS IN ON EACH SOURCE +HPKSI: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSO: .IREPT NCHX,0 ;TOTAL NUMBER OF PACKETS OUT ON EACH SINK +HPKSO: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSIG: 0 ;NUMBER OF PACKETS IGNORED AT CHIFLS +NPKSBD: .IREPT NCHX,0 ;NUMBER OF PACKETS BAD AT CHSIHB +HPKSBD: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSRF: 0 ;NUMBER OF PACKETS FOR WHICH ROUTING FAILED +RFSBNT: -1 ;2* SUBNET# OF LAST ROUTING FAILURE + +;"INTERFACE ADDRESSES" +; A NEGATIVE INTERFACE ADDRESS IS THE UNIBUS ADDRESS OF A CHAOS INTERFACE. +; A ZERO INTERFACE ADDRESS MEANS THE DL10 +; A POSITIVE INTERFACE ADDRESS MEANS THE TEN-11, VALUE BETTER BE OCTAL 1011. + +CHSIBF: .BLKW PKMAX*CHAOSP ;INPUT BUFFER FOR PACKETS IN FROM CHAOS HDWR + +;THIS IS WHAT IS SENT BACK IN RESPONSE TO RFC TO "STATUS". +;FOR NOW, JUST THE NAME OF THE MACHINE. +HSTNAM: +.ENDC ;CHAOSP ;FUCK A DOG, PALX! +.IFM MX-DL + .ASCII \MX-IO/11\ +.ENDC +.IFM AI + .ASCII \AI-CHAOS-11\ +.ENDC +.IFNZ CHAOSP ;FUCK A DOG, PALX! +.IIF GE .-HSTNAM-32., .ERROR HSTNAM TOO LONG +.IREPT 32.-<.-HSTNAM>, .BYTE 0 ;PAD ON THE RIGHT WITH 0'S + +;CHAOSNET INPUT SOURCE AND OUTPUT SINK TABLES + + ;NOTE WELL, THE CODE RELIES ON THE ORDER OF THESE INDICES +.IIF NZ DL10P, CHXDLC==0 ;DL10 INDEX +.IIF NZ TEN11P, CHXT11==2*DL10P ;TEN11 INDEX +CHXCHS==2* ;FIRST CHAOS INDEX +.IIF NZ ETHERP, CHXETH==CHXCHS+<2*CHAOSP> ;ETHERNET INDEX +.IIF NZ ETHERP, CHXEGT==CHXETH+2 ;ETHERNET GATEWAY-INFO-BROADCAST KLUDGE INDEX +.IIF DF NDVRBF, CHXDVR==CHXEGT+2 ;DOVER PROTOCOL TRANSLATOR +.MACRO CHXCHK TAG +.IIF NE .-TAG-NCHX-NCHX, .ERROR TAG WRONG LENGTH TABLE +.ENDM CHXCHK + +;CHAOSNET INPUT SOURCE TABLES + +CHIBFP: ;BUFFER POINTER +.IIF NZ DL10P, DLCIBF ;DL10 INPUT BUFFER +.IIF NZ TEN11P, 0 ;CURRENT TEN11 INPUT BUFFER (SET FROM T11IBP+8) +.IREPT CHAOSP, CHSIBF+ ;CHAOS INPUT BUFFER +.IIF NZ ETHERP, ETHIBF ;ETHERNET +.IALSO EGTBUF ;.. +.IIF DF NDVRBF, 0 ;CURRENT DOVER BUFFER, COULD BE CHAOS OR PUP +CHXCHK CHIBFP + +CHIHDL: .IREPT NCHX, 0 ;LENGTH OF HEADER IN WORDS, PACKET CURRENTLY IN BFR + +CHISTS: .IREPT NCHX, 0 ;STATUS (0 IDLE, +1 HAS INPUT, -1 BEING OUTPUT) + +CHILNG: .IREPT NCHX, 0 ;LENGTH OF CONTAINED PACKET IN WORDS + +CHIOUX: .IREPT NCHX, 1 ;DESTINATION OUTPUT SINK INDEX (-1 IF DIRECTED TO PDP11 ITSELF) + +CHICBA: .IREPT NCHX, 0 ;DESTINATION CABLE ADDRESS + +CHIRFL: ;ADDRESS OF REFILL ROUTINE +.IIF NZ DL10P, DLCRFL +.IIF NZ TEN11P, T11RFL +.IREPT CHAOSP, CHSRFL +.IIF NZ ETHERP, ETHRFL ;ETHERNET +.IALSO CPOPJ ;.. +.IIF DF NDVRBF, DVRRFL +CHXCHK CHIRFL + +CHIHWR: ;POINTER TO HARDWARE +.IIF NZ DL10P, 1 ;NOT USED +.IIF NZ TEN11P, 3 ;NOT USED +.IREPT CHAOSP, CAICSR+<400*.RPCNT> ;QUAD-CHAOS INTERFACES HAVE TO BE 200 APART +.IIF NZ ETHERP, 164200 ;AND WE MAKE IT 400 BECAUSE ETHERNET GETS IN WAY +.IALSO 5 ;NOT USED +.IIF DF NDVRBF, 7 ;NOT USED + +;CHAOSNET OUTPUT SINK TABLES + +CHOHWR==CHIHWR ;POINTER TO HARDWARE + +CHOSTS: .IREPT NCHX, 0 ;STATUS (0 IDLE, +1 TRANSMITTING, -1 RETRANSMITTING + ; AFTER TRANS ABORT, +2 DELAYING AFTER TRANSMIT ABORT BEFORE RETRANSM) +CHOINX: .IREPT NCHX, 1 ;CURRENTLY-ACTIVE CHIxxx INDEX + +CHOXMT: ;START TRANSMISSION ROUTINE +.IIF NZ DL10P, DLCXMT +.IIF NZ TEN11P, T11XMT +.IREPT CHAOSP, CHSXMT +.IIF NZ ETHERP, ETHXMT ;ETHERNET +.IALSO 1 ;NOT USED (CHXEGT) +.IIF DF NDVRBF, DVRPKT ;DOVER +CHXCHK CHOXMT + +CHXSBN: ;SUBNET NUMBER +400 FOR STATUS SERVER +.IIF NZ DL10P, DLCADR/400+400 +.IIF NZ TEN11P, T11ADR/400+400 +.REPT CHAOSP + CONC CHAD,\.RPCNT,/400+400 +.ENDR ;CHAOSP +.IIF NZ ETHERP, ETHSBN+400 ;ETHERNET +.IALSO 776 ;NOT REAL (ETHERNET GATEWAY) +.IIF DF NDVRBF, 777 ;NOT REAL (DOVER) +CHXCHK CHXSBN + +CHXRTF: .IREPT NCHX, 0 ;NON-ZERO MEANS BROADCAST ROUTING INFO TO THIS GUY + +.IFNZ CHSBTB +CHSIDL: .IREPT NCHX, 0 ;NUMBER OF TICKS WAITING FOR TRANSMIT-DONE +CHSRST: .IREPT NCHX, 0 ;NUMBER OF TIMES HAD TO RESET HUNG INTERFACE +.ENDC ;CHSBTB + +;;; SUBNET/ROUTING TABLES + +;INDEX BY TWICE SUBNET NUMBER +SBNTYP: .IREPT NSUBNT, 0 ;TYPE OF CONNECTION TO THIS SUBNET: + ; 0 VIA GATEWAY, WITH AUTOMATIC ROUTING + ; -1 VIA GATEWAY, PATCHED IN BY HUMAN, DON'T CHANGE + ; 1 HARDWARE CONNECTION + +SBNADR: ;ADDRESS OF CONNECTION TO THIS SUBNET + ;NETWORK ADDRESS IF SBNTYP NEGATIVE OR ZERO + ;INDEX IN SOURCE/SINK TABLES IF SBNTYP GREATER THAN ZERO + 0 ;0 USED FOR UNKNOWN SUBNETS. WHEN IN DOUBT, BROADCAST. + 0 ;1 9TH FLOOR CABLE + 0 ;2 (NOT CURRENTLY USED) + 440 ;3 MX, ASSUME VIA MX-IO-11 + 426 ;4 AI, ASSUME VIA AI-CHAOS-11 + .IREPT NSUBNT-5, 0 ; WHEN IN DOUBT, BROADCAST + +SBNCST: .IREPT NSUBNT, 1000 ;COST OF ROUTING VIA CURRENT GATEWAY, SEE CHAORD + +;NOW FILL IN TABLES FOR HARDWARE CONNECTIONS THAT EXIST ON THIS MACHINE +;INCLUDING TRANSFINITE HAIR FOR ETHERNET GATEWAY INFO PACKET +ZZ==. +.IFNZ DL10P +DLCSBN==DLCADR/400 ;SUBNET PDP10 ON OTHER END OF DL10 IS ON +.=SBNTYP+ + 1 +.=SBNADR+ + CHXDLC +.=SBNCST+ + 10. ;DIRECT 10/11 CONNECTION COSTS 10. +.ENDC ;DL10P +.IFNZ TEN11P +T11SBN==T11ADR/400 ;SUBNET PDP10 ON OTHER END OF TEN11 IS ON +.=SBNTYP+ + 1 +.=SBNADR+ + CHXT11 +.=SBNCST+ + 10. ;DIRECT 10/11 CONNECTION COSTS 10. +.ENDC ;TEN11P +.ENDC ;CHAOSP + +.IFM MX-DL + CBLCST=11. ;CABLE CONNECTION COSTS 11. +.ENDC +.IFM AI + CBLCST=22. ;AI COSTS MORE 'CAUSE IT'S SICK +.ENDC + +.IFNZ CHAOSP ;sweet fucking jesus, palx +;HAIR FOR MULTIPLE CABLE INTERFACES +.REPT CHAOSP + CONC IZZZ==CHAD,\.RPCNT + IZZ==*2 + .=SBNTYP+IZZ + 1 + .=SBNADR+IZZ + CHXCHS+<.RPCNT*2> + .=SBNCST+IZZ + CBLCST ;THE CABLE COST +.ENDR ;CHAOSP + +.IFNZ ETHERP +.=SBNTYP+ + 1 +.=SBNADR+ + CHXETH +.=SBNCST+ + 11. +.ENDC ;ETHERP + +.=ZZ + +;;; CLOCKS +4SEC: 0 ;4-SECOND CLOCK COUNTER +15SEC: 0 ;15-SECOND CLOCK COUNTER + +.ENDC ;CHAOSP + +;PATCH AREA + +PAT: PATCH: .BLKW 100 + + .SBTTL RING BUFFERS + +.MACRO RING SIZE + 99$ ;IN-POINTER + 99$ ;OUT-POINTER + 0 ;NUMBER OF WORDS IN RING + ;MAX NUMBER ALLOWED + <2*>+99$ ;MAX ADDRESS ALLOWED + 99$ ;MIN ADDRESS ALLOWED +99$: .BLKW ;BUFFER +.ENDM + +RINGIN==0 +RINGOT==2 +RINGCT==4 +RINGSZ==6 +RINGTP==10 +RINGBT==12 +RINGBF==14 + +; DEFINE THE RING BUFFERS + +TYORNG: RING ;OUTPUT-DONE RING, CONTENTS = LINE NUMBER PDP10 STYLE + ;HAS TO BE EXTRA BIG BECAUSE THE OUTPUT DONES PUT IN ON + ;STARTUP FILL IT UP, THEN SOMETIMES ITS PUTS ONE IN + ;BEFORE IT TAKES ANY OUT. + +TYIRSZ==NCT*20 ;8 CHARS PER TTY (2 WORDS PER CHAR) +TYIRNG: RING TYIRSZ ;TTY INPUT RING, FIRST WORD IS CHARACTER, SECOND LINE NUMBER + + + +;MOV #RING,B +;MOV WORD,A +;CALL PUT + +PUT: CMP RINGCT(B),RINGSZ(B) + BLT 1$ + BPT ;BLOATED +1$: PUSH C + MOV RINGIN(B),C + MOV A,(C)+ + CMP C,RINGTP(B) + BLO 2$ + MOV RINGBT(B),C +2$: MOV C,RINGIN(B) + POP C + INC RINGCT(B) + RET + +;MOV #RING,B +;CALL GET +;WORD RETURNED IN A +; IT IS AN ERROR TO CALL THIS IF RING IS EMPTY + +GET: TST RINGCT(B) + BGT 1$ + BPT ;EMPTY +1$: PUSH C + MOV RINGOT(B),C + MOV (C)+,A + CMP C,RINGTP(B) + BLO 2$ + MOV RINGBT(B),C +2$: MOV C,RINGOT(B) + POP C + DEC RINGCT(B) + RET + +CLRING: CLR RINGCT(B) ;CLEAR A RING + MOV RINGBT(B),RINGIN(B) + MOV RINGBT(B),RINGOT(B) + RET + .IFNZ DTE20P + .SBTTL DTE20 SUBROUTINES + +;THE DTE20 MUST NOT BE HACKED AT INTERRUPT LEVEL, BECAUSE KLDCP USES IT TOO. +;THE FOLLOWING THREE LOCATIONS ARE ARGS TO/FROM THE FOLLOWING TWO SUBROUTINES. + +LH: 0 ;LOW 16 BITS OF LEFT HALF +RH: 0 ;LOW 16 BITS OF RIGHT HALF +SNB: 0 ;SIGN BIT (0 IF +, NON-0 IF -) + +;JSR B,HWEXAM +; .WORD ADDR +;EXAMINE PDP10 LOC, SPLIT INTO HALFWORDS, SET LH, RH, SNB +;RETURNS WITH "Z" SET IF LOCATION HAS POSITIVE SIGN, "Z" CLEAR IF MINUS SIGN + +HWEXAM: PUSH ;SAVE REGS + PUSH <#0,(B)+> ;PUT PDP10 ADDRESS ONTO PDL + MOV SP,A ;SET UP POINTER TO ADDRESS + EXAM ;EXAMINE LOCATION, SET A TO POINT TO 3-WORD RESULT BUFFER + BCS UHUNG ;BRANCH IF UCODE HUNG + MOV (A)+,RH ;LOW 16 BITS => RH + MOV (A)+,C ;PICK UP MIDDLE 16 BITS + MOV (A)+,A ;PICK UP HIGH 4 BITS + ROR A ;LSHC ,-2 TO GET PDP10 LH INTO C + ROR C + ROR A + ROR C + MOV C,LH + BIC #177775,A ;LEAVE SIGN BIT IN 1.2 OF A + MOV A,SNB + ADD #4,SP ;POP ADDRESS OFF PDL + POP ;RESTORE REGS + TST SNB + RTS B ;RETURN SKIPPING IN-LINE PARAMETER + +;JSR B,HWDEP +; .WORD ADDR +;ASSEMBLE LH, RH, SNB INTO PDP10 AND DEPOSIT IN ADDR + +HWDEP: PUSH + MOV LH,C + CLR A + TST SNB + BEQ 1$ + MOV #2,A +1$: ASL C + ROL A + ASL C + ROL A + PUSH ;PUSH HIGH, MIDDLE, AND LOW BITS + MOV SP,A ;POINTER TO DATA + PUSH <#0,(B)> ;PUSH HIGH AND LOW ADDRESS + MOV SP,B ;POINTER TO ADDRESS + DPOS ;DO THE DEPOSIT + BCS UHUNG ;BRANCH IF UCODE HUNG + ADD #10.,SP ;POP ADDRESS AND DATA OFF PDL + POP + TST (B)+ ;SKIP TRAILING PARAMETER + RTS B + +UHUNG: $PMSG + .WORD 1$ + SETOM NO.ITS ;GIVING UP + JMP $CNTLC + +1$: .ASCIZ/?MICROCODE HUNG/ + +.ENDC ;DTE20P + .IFNZ DL10P + .SBTTL MAIN LOOP FOR DL10 + +MAIN: +.IIF NZ TEN11P, CALL T11WAK ;CHECK UP ON TEN-11 INTERFACE +.IFNZ ETHERP + TST CHXRTF+CHXETH ;NEED TO BROADCAST ROUTING INFO TO ETHERNET? + BEQ 666$ + CALL ETHRUT +666$: +.ENDC ;ETHERP + BIT #DLXPRT,DLXCSR ;PORT TO 10 ENABLED? + BNE 1$ ;YES + SETOM NO.ITS ;NO, FLAG THERE IS NO ITS + SETOM DLXOFF ;AND THAT WE THINK DL10 PORT IS OFF + BR MAIN ;AND WAIT FOR IT TO TURN ON + +1$: TST DLXOFF ;DID DL10 JUST TURN ON? + BEQ 4$ ;NO, IT WAS ON BEFORE + CLR DLXOFF ;YES, SO REMEMBER THAT + MOV VERS,A ;CHECK VERSION SUPPLIED BY -10 + BEQ 2$ ;ZERO OK (MUST BE SALVAGER) + CMP A,VERSN + BEQ 2$ + BPT ;-10 AND -11 PROGRAMS NOT SAME CONFIG +2$: + +4$: BIT #DLXPAR+DLXNXM,DLXCSR ;ERROR ACCESSING MEMORY? + BEQ 5$ ;NO + BPT ;DON'T GO OFF DESTROYING PEOPLE'S FILES + +;WAIT FOR -10 TO REQUEST SERVICE, OR CLOCK TO TICK + +5$: CLR 10RQ + BIT #DLX11I,DLXCSR ;10 REQUESTING SERVICE? + BEQ 10$ + SETOM 10RQ + BIS #DLXZ11,DLXCSR ;YES, CLEAR FLAG + BR CHKOST ;AND GO CHECK FOR THINGS TO DO + +10$: TST WAKE ;NO, CHECK ANYWAY IF 60 CYCLE CLOCK HAS TICKED + BEQ MAIN ;NEITHER, JUST WAIT + CLR WAKE ;CLOCK HAS TICKED, CLEAR FLAG + INC DLXUP ;AND INCREMENT COUNTER 10 IS SUPPOSED + BEQ 11$ ; TO SETOM EVERY 1/2 SEC + CMP DLXUP,#15.*60. ;IF IT DOESN'T TOUCH IT FOR 15 SECONDS, + BLE 12$ ; CONSIDER IT DOWN. NOTE THAT PARITY SWEEPS + SETOM NO.ITS ; THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS + MOV #15.*60.,DLXUP ;DON'T LET COUNTER OVERFLOW + BR 12$ ;BUT CHECK FOR COMMANDS ANYWAY (SALVAGER DISK) + +11$: CLR NO.ITS ;-10 HAS SETOMED COUNTER, IT'S UP +12$: ;FALL INTO CHKOST + +; CHECK FOR OUTPUT-START FROM -10 + +CHKOST: MOV TTYST,A ;LINE# TO START OUTPUT + BEQ CHKOUT ;NONE. + CLR TTYST ;TELL -10 IT'S BEEN PICKED UP + MOV #TYORNG,B + MASK 5 ;DON'T INTERFERE WITH P.I. LEVEL + CALL PUT ;PUT IN RING, LATER WILL SEND IT BACK TO 10 + UNMASK + +; CHECK FOR TTY OUTPUT SENT BY -10 + +CHKOUT: MOV TYOLIN,I ;OUTPUT TO BE DONE? + BEQ CHKIN ;NO. + MOV TYOCNT,C ;YES, GET NUMBER OF CHARS + CALL TYOSER ;CALL OUTPUT HANDLER + CLR TYOLIN ;TELL 10 WE'VE GOBBLED THE OUTPUT + BIS #DLX10I,DLXCSR ;GIVE TRANSFER-COMPLETE INTERRUPT + +; CHECK FOR TTY INPUT TO BE SENT TO -10 + +CHKIN: TST TYIRNG+RINGCT + BEQ CHKDON ;NO STATUS TO BE STORED + TST TYILIN + BNE CHKDON ;PREVIOUS STATUS NOT PICKED UP + MOV #TYIRNG,B + CALL GET + MOV A,TYICHR ;GIVE INPUT CHARACTER TO 10 + CALL GET + MOV A,TYILIN ;GIVE LINE NUMBER TO 10 + BIS #DLX10I,DLXCSR ;SEND INTERRUPT TO 10 + +; CHECK FOR OUTPUT-DONE TO BE SENT TO -10 + +CHKDON: TST TYORNG+RINGCT + BEQ CHKHNG ;NO STATUS TO BE STORED + TST TYOSTS + BNE CHKHNG ;PREVIOUS STATUS NOT PICKED UP + MOV #TYORNG,B + CALL GET + MOV A,I + ASL I + MOV BUFSIZ(I),TYOBSZ ;TELL -10 HOW MANY CHARS TO GIVE + MOV A,TYOSTS ;GIVE OUTPUT DONE TO 10 + BIS #DLX10I,DLXCSR ;WITH INTERRUPT + +; CHECK FOR HANGUPS TO BE SENT TO -10 + +CHKHNG: TST HNGSIG ;ANY HANGUPS TO BE REPORTED? + BEQ CHKLPR ;NO + TST HNGLIN + BNE CHKLPR ;PREVIOUS STATUS NOT PICKED UP + MOV #LASTTY,I ;SCAN OVER ALL LINES +1$: MASK 5 + MOV TTYHNG(I),A ;GET HANG-UP STATUS + BNE 2$ ;BRANCH IF FOUND SOMETHING TO REPORT + UNMASK + TST -(I) + CMP I,#NFTTY + BHIS 1$ + BPT ;HNGSIG OUT OF PHASE WITH TTYHNG + +2$: CLR TTYHNG(I) ;GOT STATUS, CLEAR IT + DEC HNGSIG ;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED + UNMASK ;NOW IT'S OK TO INTERRUPT AND SET TTYHNG + MOV A,HNGLIN ;GIVE LINE NUMBER AND OTHER DATA TO 10 + BIS #DLX10I,DLXCSR ;WITH INTERRUPT + +; CHECK FOR REQUEST FROM -10 TO SET LINE PARAMETERS + +CHKLPR: MOV LPRLIN,I ;LINE PARAMETERS TO BE SET? + BEQ CHKCHS ;NO. + ASL I ;YES, GET LINE INDEX + MOV LPRLPR,A ;AND DH11 PARAMETER REGISTER VALUE + MOV LPRBSZ,B ;AND BUFFER SIZE + CALL SPARAM ;CALL PARAMETER SETTER + CLR LPRLIN ;TELL 10 IT IS DONE + +; CHECK FOR CHAOS NET ACTIVITY + +CHKCHS: +.IFNZ CHAOSP + CALL DLCWAK ;WAKEUP DL10-CHAOSNET STUFF +.ENDC ;CHAOSP +.IFNZ T300P + CALL DSKSTR ;CHECK FOR DISK REQUEST +.ENDC ;T300P + +; CHECK FOR EXAMINE/DEPOSIT REQUEST FROM -10 + +CHKEXD: TST EXDSTS ;EXAMINE/DEPOSIT? + BEQ CHKGLD ;NO. + MOV EXDADR,A ;GET ADDRESS + CMP EXDSTS,#2 + BNE 21$ + MOV EXDDAT,(A) ;DEPOSIT +21$: MOV (A),EXDDAT ;EXAMINE + CLR EXDSTS ;IT IS DONE + +;CHECK FOR GOULD LPT OUTPUT + +CHKGLD: +.IF EQ GOULDP +; CLR GLPCTR ;IF NO GOULD, FLUSH OUTPUT FOR IT +; SETOM GLPTER ;AND SAY "NOT READY" + TST 10RQ + BEQ 20$ + ;10 WANTED US TO DO SOMETHING, PLAY WITH THE LIGHTS + MOV LITHSE,A + ROL A + ROL LITHSE +20$: MOV LITHSE,GLPTER +.IFF + TST GLPCTR ;ANY BYTES IN BUFFER? + BEQ 1$ + CALL GLPTYO ;YES, OUTPUT THEM +1$: MOV GLPERR,GLPTER ;COPY ERROR STATUS FROM P.I. LEVEL TO -10 +.ENDC ;DONE HERE SO NO USE OF DL10 AT P.I. LEVEL +; BR MAINX + +MAINX: JMP MAIN ;THAT'S IT +MAINE:: +.ENDC ;DL10P + .IFNZ DTE20P + .SBTTL MAIN LOOP FOR DTE20 + +MAIN: BIT #%D1RUN,DIAG1 ;IS KL10 RUNNING? + BEQ TENDED ;NO, LOSE! + BIT #%D1ERR+%D1HLT,DIAG1 ;HAS KL10 CLOCK STOPPED FOR HARDWARE ERROR? OR JRST 4 + BNE TENDED ;YES, LOSE! + TST KLDCPF ;MAYBE USER WANTS TO GIVE A KLDCP COMMAND? + BNE KLDCPR ;YES, RETURN TO KLDCP + TSTB @DLKS+NFDLHX ;CTY INPUT? + BPL 10$ ;TEST KBD BEFORE CLK SINCE MIGHT BE MORE THAN + ; 1/60'TH SECOND PER TRIP AROUND THE LOOP. + MASK 5 ;YES, SIMULATE INTERRUPT + CALL DL1IBK ;CAN'T USE REAL INTS BECAUSE WOULD INTERFERE WITH KLDCP +10$: TSTB LKS ;60 CYCLE CLOCK TICK? + BMI CLKSER ;YES + BIT #%STINV,STATUS ;REQUEST FROM 10? + BNE TENSER ;YES, SERVICE IT. + BIT #%STDNI,STATUS ;TO10 XFER COMPLETE? + BNE INPDON ;YES, SERVICE IT. + BIT #%STDNO,STATUS ;TO11 XFER COMPLETE? + BNE OUTDON ;YES, SERVICE IT. + BIT #%STERI+%STERO,STATUS + BNE LOSSAG ;BYTE TRANSFER LOST + BR MAIN ;CLOSE LOOP + +;60-CYCLE CLOCK SERVICE + +CLKSER: CLR LKS ;CLEAR CLOCK FLAG + TST CLKENB ;DOES 10 WANT CLOCK INTERRUPTS? + BEQ 1$ + D10MON ;YES, GIVE ONE + DTECLK ;SET CLOCK FLAG IN LOW CORE + BCS UHUNG + MOV #%STINX,STATUS ;AND SEND INTERRUPT +1$: CMP SWR,CURSWR ;MAYBE NEED TO UPDATE 10'S SWITCHES + BEQ 2$ + MOV SWR,CURSWR + TENSW ;LET KLDCP DO IT + BCS UHUNG +2$: JSR B,HWEXAM ;INCREMENT COUNTER -10 IS SUPPOSED + DTECHK ; TO SETOM EVERY HALF-SECOND + CLR LH + CLR SNB + INC RH + BEQ 3$ + CMP RH,#15.*60. ;IF IT DOESN'T SETOM IT FOR 15 SECONDS + BLE 4$ ;THEN IT IS DOWN. NOTE THAT PARITY SWEEPS + SETOM NO.ITS ;THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS. + MOV #15.*60.,RH ;DON'T LET COUNTER OVERFLOW + BR 4$ + +3$: CLR NO.ITS ;IT SETOMED COUNTER, IT'S UP. +4$: JSR B,HWDEP ;PUT COUNTER BACK + DTECHK + MASK 6 ;NOW SIMULATE BR6 CLOCK INTERRUPT + CALL CLKBRK + BR TENSER ;AND GO SERVICE 10 (IN CASE LOST INTERRUPT) + +; HERE IF KL10 HALTS + +TENDED: SETOM NO.ITS + CLC + RET ;LET KLDCP PRINT THE MESSAGE + +; BYTE TRANSFER ENCOUNTERED HARDWARE LOSSAGE + +LOSSAG: BPT + BR LOSSAG + +; USER WANTS TO GIVE A KLDCP COMMAND + +KLDCPR: CLR KLDCPF + SEC + RET + +TENSER: JMP TENSR0 + +; HERE WHEN TO10 BYTE TRANSFER COMPLETE + +INPDON: MOV #%STCLI,STATUS ;CLEAR FLAGS IN DTE20 + MOV INPCMD,A ;GET COMMAND FOR XFER THAT JUST FINISHED + BNE 1$ + BPT ;WOOPS, NO XFER IN PROGRESS +1$: CLR INPCMD ;NO XFER IN PROGRESS NOW + MOV INPSVI,I + MOV INPSVC,C + CALL @FINAL-2(A) ;CALL APPROPRIATE FINISHER ROUTINE + BR MAIN + +; HERE WHEN TO11 BYTE TRANSFER COMPLETE + +OUTDON: MOV #%STCLO,STATUS ;CLEAR FLAG + MOV OUTCMD,A ;GET COMMAND FOR XFER THAT JUST FINISHED + BNE 1$ + BPT ;WHOOPS, NO XFER IN PROGRESS +1$: CLR OUTCMD ;NO XFER IN PROGRESS NOW + MOV OUTSVI,I + MOV OUTSVC,C + CALL @FINAL-2(A) ;CALL APPROPRIATE FINISHER ROUTINE + BR MAINJ + +; HERE TO START TO10 BYTE TRANSFER. HWEXAM OF DTEINP HAS BEEN DONE. + +INPSER: D10MON ;VALUE HAS BEEN PICKED UP, SETOM IT + DTEINP + BIT #1000,LH ;RIGHT GENDER OF COMMAND? + BEQ OUTSR1 ;YES + BR MAINJ ;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED + +; HERE TO START TO11 BYTE TRANSFER. HWEXAM OF DTEOUT HAS BEEN DONE. + +OUTSER: D10MON ;VALUE HAS BEEN PICKED UP, SETOM IT + DTEOUT + BIT #1000,LH ;RIGHT GENDER OF COMMAND? + BNE OUTSR1 ;YES + BR MAINJ ;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED + +OUTSR1: MOV RH,C ;GET BYTE COUNT + MOVB LH,I ;GET LINE# + MOVB LH+1,A ;GET COMMAND TIMES 2 + BEQ MAINJ ;CLEARING CORE? IGNORE ZERO COMMAND + BLE OUTSR2 + CMP A,#LBEGIN + BGT OUTSR2 + CALL @BEGIN-2(A) ;CALL APPROPRIATE BEGIN-XFER ROUTINE + BIT #2,A + BNE 1$ + MOV A,INPCMD ;REMEMBER CRUFT FOR XFER IN PROGRESS + MOV I,INPSVI + MOV C,INPSVC + BR MAINJ + +1$: MOV A,OUTCMD ;REMEMBER CRUFT FOR XFER IN PROGRESS + MOV I,OUTSVI + MOV C,OUTSVC +MAINJ: JMP MAIN + +OUTSR2: BR MAINJ ;BAD COMMAND FROM 10 (USED TO BE BPT) JUST IGNORE IT + +;TABLE OF ROUTINES TO PROCESS DATA TRANSFER COMMANDS FROM -10 + +BEGIN: TYOSER ;%DTTYO + ;ETHISR ;%DTETI + ;ETHOSR ;%DTETO +LBEGIN==.-BEGIN + +;TABLE OF ROUTINES TO FINISH UP DATA TRANSFERS + +FINAL: TYOFIN ;%DTTYO + ;ETHIFN ;%DTETI + ;ETHOFN ;%DTETO + +;CHECK FOR COMMANDS FROM 10, STORE STATUS IN ANY STATUS WORDS +;THAT 10 HAS SET BACK TO -1 + +TENSR0: MOV #%STUNV,STATUS ;CLEAR 10 INTERRUPTING 11 FLAG + JSR B,HWEXAM ;CHECK FOR A NON-TIMESHARING COMMAND + DTECMD + MOV RH,A ;IS THERE ONE? + BEQ TENSR1 ;NO, GO CHECK FOR TIMESHARING STUFF + CLR LH + CLR SNB + CMP A,#377 + BHI 2$ +1$: TSTB TPS ;CHAR TO BE TYPED, WAIT FOR READY + BPL 1$ + MOVB A,TPB ;TYPE IT OUT +9$: CLR RH ;CLEAR OUT THE COMMAND + JSR B,HWDEP + DTECMD + D10MON ;TELL 10 IT'S DONE + DTEFLG + JMP MAIN + +2$: CMP A,#%DTTYI + BNE 5$ + CLR RH ;SNB,LH,RH NOW HAS ZERO + SETOM DDTMOD ;KEYBOARD INPUT WANTED + TST DDTCHR ;TEST IF READY + BMI 3$ ;IF NO INPUT, GIVE ZERO + MASK 5 + MOV DDTCHR,RH ;GIVE THE CHAR + COM DDTCHR ;MAKE NEGATIVE + UNMASK +3$: JSR B,HWDEP + DTEF11 + BR 9$ + +5$: CMP A,#%DTCLN + BNE 6$ + SETOM CLKENB + BR 9$ + +6$: CMP A,#%DTCLF + BNE 7$ + CLR CLKENB + BR 9$ + +7$: BPT ;SOME COMMAND WE DON'T IMPLEMENT + BR 9$ ;IF CONTINUED, IGNORE IT + +;CHECK FOR ITS UP/DOWN + +TENSR1: TST NO.ITS ;IF SYSTEM ISN'T UP, + BNE MAINJ ;DON'T TRY TO HACK TS STUFF + INC DLXOFF ;OTHERWISE, FIRST TIME THROUGH HERE + BNE CHKOST ;WE CHECK THE VERSION + JSR B,HWEXAM + DTEVER + TST RH ;STORED? + BNE 1$ + DEC DLXOFF ;NO, DON'T LOOK AT IT + BR MAINJ ;PROBABLY CORE BEING CLEARED + +1$: CMP RH,VERSN + BEQ CHKOST + BPT ;-10 AND -11 PROGRAMS NOT SAME VERSION + +CHKOST: JSR B,HWEXAM ;CHECK FOR 10 WANTING OUTPUT START + DTEOST + BNE CHKTRN ;BRANCH IF LOCATION DTEOST IS -1 + D10MON ;HAVING PICKED IT UP, SET BACK TO -1 + DTEOST + MOV RH,A + MOV #TYORNG,B + MASK 5 ;DON'T INTERFERE WITH P.I. LEVEL + CALL PUT + UNMASK + CLR DDTMOD ;SYSTEM UP, TURN OFF DDT MODE + MOV #-1,DDTCHR ;.. + +CHKTRN: TST INPCMD + BNE 1$ ;INPUT IN PROGRESS, DON'T START AGAIN + JSR B,HWEXAM ;CHECK FOR DATA TRANSFER COMMAND + DTEINP + BNE 1$ ;DTEINP -1, NO REQUEST + JMP INPSER + +1$: TST OUTCMD + BNE CHKLSP ;OUTPUT IN PROGRESS, DON'T START AGAIN + JSR B,HWEXAM ;CHECK FOR DATA TRANSFER COMMAND + DTEOUT + BNE CHKLSP ;DTEOUT -1, NO REQUEST + JMP OUTSER + +CHKLSP: JSR B,HWEXAM ;CHECK FOR SET LINE SPEED COMMAND + DTELSP + BNE CHKTYI + MOV RH,I ;GET LINE# + ASL I + CMP I,#NFTTY ;VALIDATE IT + BLO 1$ ;IGNORE IF BAD + CMP I,#LASTTY + BHI 1$ + JSR B,HWEXAM ;GET LPR,,BUFFERSIZE + DTELPR + MOV LH,A + MOV RH,B + CALL SPARAM ;DO IT +1$: D10MON ;DONE, SETOM + DTELSP + +CHKTYI: TST TYIRNG+RINGCT + BEQ CHKODN ;NO TTY INPUT WAITING + JSR B,HWEXAM + DTETYI + BEQ CHKODN ;PREVIOUS CHAR NOT PICKED UP + MOV #TYIRNG,B + CALL GET + MOV A,RH ;CHAR + CALL GET + MOV A,LH ;LINE# + CLR SNB + JSR B,HWDEP ;GIVE 10 LINE#,,CHAR + DTETYI + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +CHKODN: TST TYORNG+RINGCT + BEQ CHKHNG ;NO OUTPUT DONES WAITING + JSR B,HWEXAM + DTEODN + BEQ CHKHNG ;PREVIOUS STATUS NOT PICKED UP + MOV #TYORNG,B + CALL GET ;GET LINE# WITH OUTPUT DONE + MOV A,LH + ASL A + MOV BUFSIZ(A),RH + CLR SNB + JSR B,HWDEP ;GIVE 10 LINE#,,BUFFERSIZE + DTEODN + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +CHKHNG: TST HNGSIG + BEQ MAINX ;NO HANGUPS/DIALINS WAITING + JSR B,HWEXAM + DTEHNG + BEQ MAINX ;PREVIOUS STATUS NOT PICKED UP + MOV #LASTTY,I ;SCAN OVER ALL LINES +1$: MASK 5 + MOV TTYHNG(I),A ;GET HANG-UP STATUS + BNE 2$ ;BRANCH IF FOUND SOMETHING TO REPORT + UNMASK + TST -(I) + CMP I,#NFTTY + BHIS 1$ + BPT ;HNGSIG OUT OF PHASE WITH TTYHNG + +2$: CLR TTYHNG(I) ;GOT STATUS, CLEAR IT + DEC HNGSIG ;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED + UNMASK ;NOW IT'S OK TO INTERRUPT AND SET TTYHNG + MOV A,RH ;GIVE LINE NUMBER AND OTHER DATA TO 10 + CLR LH + CLR SNB + JSR B,HWDEP + DTEHNG + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +MAINX: JMP MAIN +.ENDC ;DTE20P + +.IFZ DL10P+DTE20P + .SBTTL MAIN LOOP FOR AI + +MAIN: +.IIF NZ TEN11P, CALL T11WAK ;CHECK UP ON TEN-11 INTERFACE +.IIF Z TEN11P, CALL CHSRUN ;DAMNED THING GETS WEDGED +.IFNZ ETHERP + TST CHXRTF+CHXETH ;NEED TO BROADCAST ROUTING INFO TO ETHERNET? + BEQ 666$ + CALL ETHRUT +666$: +.ENDC ;ETHERP + TST WAKE ;CLOCK TICK? + BEQ MAIN ;NO, JUST WAIT + CLR WAKE ;CLOCK HAS TICKED, CLEAR FLAG + BR MAIN ;NOT MUCH TO DO, NO TTYS +.ENDC ;DL10P+DTE20P + + .SBTTL OUTPUT HANDLERS + +TYOSER: ASL I ;CONVERT -10 LINE# TO -11 TTY INDEX + CMP I,#NFTTY + BLO 11$ + CMP I,#LASTTY + BLOS 12$ +11$: BPT ;10 GAVE BAD LINE# +12$: MOV HDWR(I),H ;GET HARDWARE INDEX + MOV BUFPNT(I),D ;AND ADDRESS OF TYPEOUT BUFFER + CMP BUFSIZ(I),C ;MAKE SURE THERE IS ROOM IN BUFFER + BHIS 2$ + BPT ;THERE ISN'T +2$: MOV C,B ;MUSTN'T CLOBBER BYTE COUNT IN C +.IFNZ DL10P + MOV #TYOPNT,A ;GET CRUFT FROM DL10 +3$: MOVB @A,(D)+ ;COPY BUFFER + SOB B,3$ +.ENDC ;DL10P +.IFNZ DTE20P + MOV D,TO11AD ;SET UP BYTE TRANSFER + NEG B + BIC #050000,B ;SET LAST, BYTE; CLEAR ASCIZ, 2.4 + MOV B,TO11BC ;START XFER + RET + +TYOFIN: MOV HDWR(I),H ;COMES BACK WHEN XFER COMPLETE +.ENDC ;DTE20P + +;BUFFER HAS BEEN LOADED, START DEVICE + + MASK 5 ;DON'T LET DEVICE INTERRUPT + MOV BUFPNT(I),D + CALL @STROUT(H) ;CALL DEVICE-DEPENDENT ROUTINE + MOV #40000,TYPING(I) ;TELL 10 WHEN OUTPUT FINISHES (LARGE POSITIVE NUMBER) + UNMASK + RET + +;GIVE MESSAGE. A -> .WORD LENGTH,MSG. I HAS LINE NUMBER. + +GIVMSG: PUSH + MOV (A)+,C ;C HAS BYTE COUNT, A HAS ADDRESS + MOV A,D ;PUT ADDRESS IN D + MOV HDWR(I),H + MASK 5 + CALL @STROUT(H) ;START OUTPUT TO LINE + UNMASK + POP + RET + +ASPACK: MNAME ^% + MSG ^\ +‡Connected to MCHN'.\% +DWNMSG: MSG ^\ +‡ITS is down.\ +IBOMSG: MSG ^\IBO\ + +;DEVICE-DEPENDENT OUTPUT START ROUTINES (CALL AT PI LEVEL 5) +;H HDWR IDX, I TTY IDX, D BUFFER POINTER, C NUMBER OF BYTES + +STRDH: BIC DHLBIT(I),@DHBAR(H) ;IF LINE ALREADY TRANSMITTING, STOP IT + ;IT SHOULDN'T OUGHT TO BE... + MOV DHLSEL(I),@DHSCR(H) ;HARDWARILY SELECT THIS LINE + MOV D,@DHCA(H) ;SET XMT ADDRESS + NEG C ;HARDWARE LIKES NEGATIVE BYTE COUNTS + MOV C,@DHBC(H) ;SET XMT COUNT + BIS DHLBIT(I),@DHBAR(H) ;START TRANSMISSION HARDWARILY + BIS DHLBIT(I),DHOAC(H) ;SOFTWARILY ALSO + RET + +STRDL: MOV D,DLCA(H) + MOV C,DLBC(H) + CLR @DLPS(H) + MOV #300,@DLPS(H) ;CAUSE INTERRUPT + SETOM DLOAC(H) +CPOPJ: RET + +.IFNZ NMPTYS +STRMPK: TST MPXENB + BEQ CPOPJ + MOV D,MPXPNT-NFMPTY(I) ;QUEUE OUTPUT + MOV C,MPXNBT-NFMPTY(I) +STRMPX: PUSH I + TST MPXOAC ;START THE MPXR + BNE 10$ ;ALREADY BUSY + CLR I + MOV #NMPTYS,D +2$: MOV MPXNBT(I),C ;FIND MPX KLUDGE LINE WANTS TO OUTPUT + BNE 15$ + TST (I)+ + SOB D,2$ +10$: POP I + RET + +15$: MOV I,MPXOLN ;SAVE LINE# OUTPUT ON + ASR I ;SET UP HEADER + ADD #200,I + MOVB I,MPXHED + MOVB C,MPXHED+1 + MOV #-1,MPXOAC ;SEND HEADER + MOV #MPXIDX,I + MOV HDWR(I),H + MOV #MPXHED,D + MOV #2,C + CALL @STROUT(H) + BR 10$ +.ENDC ;NMPTYS + +.IFNZ GOULDP +.SBTTL GOULD LPT OUTPUT (M.P. LEVEL) +.IIF Z DL10P, .ERROR GOULD LPT ONLY CODED FOR DL10 +.ERR BY THE WAY, THESE ROUTINES DON'T WORK WORTH GUBBISH + +GLPTYO: MOV GLPOIP,H ;GET NEXT BUFFER + CMP GB.STA(H),#%GBMP + BEQ 2$ ;BRANCH IF M.P. ACTIVE + BLT 1$ ;BRANCH IF IDLE BUFFER AVAIL + RET ;NO FREE BUFFERS + +1$: CALL GLPBGB ;GOBBLE A BUFFER +2$: MOV GB.PNT(H),D + MOV GLPCTR,C ;SET UP BYTE COUNTER + MOV GLPGRF,GLPGF1 ;COPY ARG FROM 0 FOR SPEED + TST GLIMBF ;CHAR SAVED FROM LAST TIME? + BEQ GLPNCL + CLR GLIMBF ;YES, PRINT IT + MOVB GLIMBO,A + CALL GLPPUT + MOVB GLIMBO+1,A ;SECOND CHAR? + BEQ GLPNCL + CLR GLIMBO + CALL GLPPUT + +;CHARACTER PROCESSING LOOP +;C HAS # CHARS YET TO GO, D HAS WHERE TO PUT THEM, H -> BUFFER +;A WILL HAVE CHAR + +GLPNCL: MOV GLPPTR,A ;GET NEXT CHAR + TST GLPGF1 + BNE GLPNRM ;GRAPHIC MODE, NO CHARACTER PROCESSING + CMP A,#177 ;ESCAPE? + BEQ GLPESC + CMP A,#40 ;CONTROL? + BGE GLPNRM ;NO, NORMAL PRINTING + CMP A,#14 ;CHECK FOR SPECIAL CONTROLS + BNE 10$ +8$: CLR GLPROW ;START NEW PAGE + TST GLPCOL ;IN MIDDLE OF LINE? + BEQ 9$ ;NO, OK + CALL GLPBWW ;OTHERWISE, HAIR + CLR GLPFIL ;HACK HACK MAKE FF NEXT LINE + BR GLPNB1 + +9$: SETOM GB.FF(H) + BR GLPNXC + +10$: CMP A,#12 + BNE 12$ + INC GLPROW + CMP GLPROW,#GLPRMX + BHIS 8$ ;SKIP OVER PERFORATION + TST GLPCOL + BNE GLPNBF ;IF NOT A BLANK LINE, FINISH BUFFER + INC GB.NL(H) + BR GLPNXC + +12$: CMP A,#11 + BNE 15$ +13$: MOV #40,A ;TAB - SPACE OVER + CALL GLPPUT + BIT #7,GLPCOL + BNE 13$ + BR GLPNXC + +15$: CMP A,#15 + BEQ GLPNXC ;IGNORE CR + CMP A,#33 + BNE 16$ + MOV #'$,A ;PRINT ALTMODE AS DOLLAR + BR GLPNRM + +16$: BIS #100,A ;RANDOM CONTROL AS UPARROW, LETTER + MOVB A,GLIMBO+1 + MOV #'^,A + CALL GLPPUT + MOVB GLIMBO+1,A + CLR GLIMBO +GLPNRM: CALL GLPPUT ;HERE FOR NORMAL CHARACTER +GLPNXC: DEC C ;HERE TO GOBBLE CHARACTER + BGT GLPNCL ;BRANCH IF MORE CHARS TO GO + BR GLPEND ;BUFFER EMPTIED + +GLPNBF: CALL GLPBWW ;HERE TO ADVANCE TO NEXT BUFFER +GLPNB1: CMP GB.STA(H),#%GBIDL ;NEXT BUFFER AVAIL? + BNE GLPEN1 ;NO, STOP + CALL GLPBGB ;YES, GOBBLE IT + BR GLPNXC + +GLPESC: DEC C ;HERE FOR TWO CHAR ESC SEQ + BEQ GLPEND ;-10 FORGOT 2ND CHAR, FLUSH + MOV GLPPTR,A ;GET & DECODE 2ND CHAR + CMP A,#105 ;EOF + BEQ GLPEOF + BR GLPNXC ;OTHER CHARS ARE IGNORED + +GLPEOF: CLR GLPFIL + CLR GLPROW + CALL GLPBWW ;EOF, WRITE LAST BUFFER +GLPEN1: DEC C ;GOBBLE A CHARACTER +GLPEND: MOV C,GLPCTR ;HERE WHEN DONE, RELEASE 10'S BUFFER + CMP GB.STA(H),#%GBMP ;BUFFER ACTIVE AT M.P. LEVEL? + BNE 1$ ;IF NOT, DON'T CLOBBER GB.PNT + MOV D,GB.PNT(H) ;IF SO, REMEMBER AMT OF STUFF IN CURRENT BUFFER +1$: RET ;RETURN TO MAIN LOOP + +;OUTPUT PRINTING CHAR IN A + +GLPPUT: CMP D,GLPLIM ;LINE OVERFLOW? + BLO 5$ ;NO + CALL GLPBWW ;YES, DONE WITH THIS BUFFER + INC GLPROW ;OUGHT TO CHECK FOR PERFORATION, BUT... + CMP GB.STA(H),#%GBIDL ;MORE BUFFERS? + BNE 6$ ;NO + CALL GLPBGB +5$: MOVB A,(D)+ ;DROP CHAR IN BUFFER + INC GLPCOL ;AND ADVANCE COLUMN + RET + +6$: MOVB A,GLIMBO ;NO BUFFERS, SAVE CHAR BEING PRINTED + SETOM GLIMBF ;SET FLAG SO WILL BE PRINTED NEXT TIME + TST (SP)+ ;STOP THE WORLD + BR GLPEN1 + +;GOBBLE IDLE BUFFER H -> FOR M.P. RETURNS GB.PNT(H) IN D. + +GLPBGB: MOV #%GBMP,GB.STA(H) ;ACTIVATE AT M.P. LEVEL + CLR GB.FF(H) ;INIT THE BUFFER + CLR GB.NL(H) + CLR GLPCOL ;START LINE IN COLUMN 0 + MOV H,D ;INIT INSERT POINTER + ADD #GB.DAT,D + MOV D,GB.PNT(H) + MOV H,GLPLIM ;SET UP MAX. VALUE OF GB.PNT + ADD #GB.LEN,GLPLIM + RET + +;GIVE BUFFER H -> TO P.I. LEVEL + +GLPBWW: BIT #1,D ;MUST BE EVEN NUMBER OF BYTES + BEQ 1$ + CLRB (D)+ + +1$: PUSH A ;INTERFACE GETS BYTES IN WRONG ORDER + MOV P,A ;COMPUTE NUMBER OF WORDS IN LINE + SUB H,A + SUB #GB.DAT,A + ASR A + BNE 4$ + CLR (D)+ ;CAN'T HAVE ZERO-LENGTH LINE + INC A +4$: MOV A,GB.PNT(H) ;SAVE WORD COUNT FOR P.I. LEVEL +2$: SWAB -(D) + SOB A,2$ + POP A + TST GLPFIL ;IF STARTING NEW FILE, + BNE 5$ + SETOM GLPFIL + SETOM GB.FF(H) ; BE SURE TO GET NEW PAGE +5$: MOV #%GBWRT,GB.STA(H) ;QUEUE TO P.I. LEVEL + MOV GB.NXT(H),H ;ADVANCE TO NEXT BUFFER + MOV H,GLPOIP + MASK 6 ;STOP P.I. LEVEL (HAVE TO LOCK OUT GLPBRK & CLKBRK) + TST GLPOAC ;PRINTER ON? + BNE 3$ ;YUP + MOV #%GCOFF,@#GLPCSR ;NO, CLEAR OLD STUFF IN INTERFACE + TST GLPGF1 ;AND PUT IN LOW-SPEED GRAPHIC MODE IF NECC + BEQ 6$ + MOV #%GCGRF,@#GLPCSR + MOV #%GCLSL,@#GLPCSR ;LOW SPEED (COME ON, THIS IS ONLY A KL10!) +6$: MOV #%GCON,@#GLPCSR ;TURN IT ON + MOV #%GCION,@#GLPCSR ;TURN ON INTERRUPTS + SETOM GLPOAC +; PUSH @#PS ;FAKE AN INTERRUPT +; CALL GLPBRK ;IS THIS NECESSARY? +3$: UNMASK + RET + +;GOULD LPT VARIABLES + +GLPCOL: 0 ;CURRENT COLUMN NUMBER +GLPROW: 0 ;CURRENT ROW NUMBER + GLPRMX==67. ;NUMBER OF LINES PER PAGE +GLPLIM: 0 ;ADDRESS OF END OF CURRENT BUFFER +GLPOAC: 0 ;NON-ZERO => GOULD LPT P.I. ACTIVE +GLPGF1: 0 ;NON-ZERO => GOULD LPT IN GRAPHIC MODE +GLIMBO: 0 ;SAVE CHAR HERE WHEN RUN OUT OF BUFFERS +GLIMBF: 0 ;NON-ZERO => CHAR IN GLIMBO +GLPFIL: 0 ;NON-ZERO => IN MIDDLE OF A FILE +GLPTIM: 10. ;COUNT DOWN WHEN LOSING +GLPERR: 0 ;NON-ZERO => ERROR STATUS FROM P.I. +.ENDC ;GOULDP + + .SBTTL T-300 DISK + +.IFNZ T300P + +;DISK UNIBUS REGISTERS + +DSKCRA=176700 ;COMPLETION REGISTER A + %DAPON==100000 ;SPONTANEOUS COMPLETION DUE TO POWER-ON. DISK NUMBER + ; IN LOW BITS OF COMMAND-COMPLETION REGISTER B + %DACQE==10000 ;CONSISTENCY ERROR IN COMMAND QUEUE + %DANXM==4000 ;NXM ERROR IN COMMAND QUEUE + %DAPAR==2000 ;PARITY ERROR IN COMMAND QUEUE + ;LOW 2 BITS OF COMMAND COMPLETION REGISTER A AND + ;COMMAND COMPLETION REGISTER B CONTAIN THE ADDRESS + ;OF THE PARITY OR NXM ERROR +DSKCRB=176702 ;COMPLETION REGISTER B +DSKCSR=176704 ;COMMAND/STATUS REGISTER + %DCCPL==100000 ;COMMAND IS COMPLETE, RESET BY %DCACK. READ-ONLY + %DCDER==40000 ;"DMA ERROR", RESET ONLY BY SYSTEM RESET. + ;1=NORMAL, 0=ERROR + ;BITS 30004 ALWAYS ON + %DCMNT==4000 ;HOST-ADAPTOR MAINTENANCE MODE + %DCRST==2000 ;RESET. WRITE-ONLY. + %DCACK==1000 ;ACKNOWLEDGE COMMAND COMPLETION. WRITE-ONLY + %DCCMD==400 ;TAKE COMMAND FROM CTRA/CTRB. WRITE-ONLY + %DCRDY==200 ;READY TO TAKE A COMMAND. READ-ONLY + %DCTIE==100 ;COMMAND TRANSMISSION (%DCRDY) INTERRUPT ENABLE + %DCCIE==40 ;COMMAND COMPLETION (%DCCPL) INTERRUPT ENABLE + %DCPCY==20 ;POWER JUST CYCLED ON OR OFF. READ-ONLY + %DCPON==10 ;POWER ON. READ-ONLY + %DCDMA==2 ;DMA IN PROGRESS. READ-ONLY + %DCBOT==1 ;BOOT (READ DRIVE 0 SECTOR 0 INTO MEMORY 0). WRITE-ONLY +DSKCTA=176706 ;COMMAND TRANSMISSION A (ADDRESS OF RQB HIGH BITS) +DSKCTB=176710 ;COMMAND TRANSMISSION B (ADDRESS OF RQB LOW BITS) +;176714 DUPLICATES DSKCSR FOR UNKNOWN REASONS + +;DISK REQUEST BLOCK. WE ONLY HAVE ONE SINCE NO SEEK OVERLAP. + +RQBACT: 0 ;NON-ZERO IF REQUEST ACTIVE AND EXPECTING COMPLETION + +RQBID: 0 ;RETURNED IN CCRB WHEN COMMAND COMPLETES +RQBSTS: 0 ;STATUS STORED BY 2561, COPIED INTO DSCSTS +RQBFLT: 0 ;FAULT CODE IN HIGH BYTE, BITS 1-0 HIGH BITS OF LINK ADDRESS +RQBLNK: 0 ;LINK ADDRESS TO NEXT RQB (MUST BE ZERO) +RQBCMD: 0 ;COMMAND CODE, COPIED FROM DSCCMD +RQBDRV: 0 ;UNIT NUMBER, COPIED FROM DSCDRV +RQBCYL: 0 ;CYLINDER NUMBER, COPIED FROM DSCCYL +RQBHED: 0 ;HEAD NUMBER, COPIED FROM DSCHED +RQBSEC: 0 ;SECTOR NUMBER, COPIED FROM DSCSEC +RQBWC: 0 ;POSITIVE WORD COUNT (ALWAYS 12.*256.) +RQBMA: 0 ;MEMORY ADDRESS (ALWAYS DSKBUF) +RQBMAH: 0 ;MEMORY ADDRESS HIGH (ALWAYS 0) + ; BITS 1-0 BITS 17-16 OF ADDRESS. BIT 6 MA INCR INH +RQBID1: 0 ;RETURNS RECORD ID 1 +RQBID2: 0 ;RETURNS RECORD ID 2 +RQBMNT: .BLKW 27. ;DIAGNOSTIC DATA MAY BE RETURNED + +;DISK BUFFER. HOLDS ENOUGH 12-BIT BYTES IN 16-BIT WORDS TO MAKE 1024. 36-BIT WORDS +DSKBUF: .BLKW 3.*1024. + +;ROUTINE TO START DISK IF IT IS READY AND THERE IS A REQUEST. +DSKSTR: TST DSCREQ ;ANY REQUEST FROM 10? + BEQ 99$ ;NO, EXIT + CMP DSCCHK,#2561 + BNE 99$ ;CHECK WORD WRONG, DON'T TOUCH DISK + TST RQBACT ;PREVIOUS OPERATION FINISHED? + BEQ 10$ + BPT ;NO, MUST BE BUG IN 10? +10$: TSTB DSKCSR ;TEST IF READY FOR COMMAND TRANSMISSION + BPL 99$ ;NO, WAIT + CLR DSCDON ;YES, CLEAR 10/11 COMMUNICATION FLAGS + CLR DSCREQ + CLR RQBLNK ;SET UP RQB FROM 10'S PARAMETERS + MOV DSCCMD,RQBCMD + MOV DSCDRV,RQBDRV + MOV DSCCYL,RQBCYL + MOV DSCHED,RQBHED + MOV DSCSEC,RQBSEC + MOV #12.*256.,RQBWC + MOV #DSKBUF,RQBMA + CLR RQBMAH + CMP RQBCMD,#%DMWRT ;IF A WRITE COMMAND, MUST COPY DATA BUFFER + BNE 30$ + MOV #DSKBUF,D + .REPT 4 ;TAKES 4 BYTE POINTERS TO DO IT + MOV #DSCPNT+<2*.RPCNT>,H + .REPT 3 ;EACH BYTE POINTER HAS 768 12-BIT BYTES + MOV #256.,C + CALL MOVHD + .ENDR + .ENDR +30$: CLR DSKCTA ;GIVE ADDRESS OF RQB TO 2561 + MOV #RQBID,DSKCTB + SETOM RQBACT ;TELL INTERRUPT LEVEL INTERRUPT EXPECTED + MOV #%DCCMD+%DCCIE,DSKCSR ;GIVE COMMAND, ENABLE COMPLETION INTERRUPT +99$: RET ;DONE + +;CALL HERE WHEN DISK INTERRUPTS +DSKBRK: PUSH ;SAVE ALL REGISTERS + MOV DSKCSR,A + BIT #%DCPCY,A ;POWER CYCLED? + BNE 5$ ;YES, RESET CONTROLLER AND IGNORE INTERRUPT + BIT #%DCMNT,A ;NO, MAINTAINENCE MODE + BEQ 4$ ;OK + BPT ;BLEAH, MUST BE BROKEN + BR 5$ + +4$: BIT #%DCDER,A ;WHAT ABOUT UNIBUS ERROR + BNE 10$ + BPT +5$: MOV #%DCRST,DSKCSR ;RESET THE CONTROLLER AND TURN OFF INTERRUPTS + TST RQBACT ;DID THIS LOSE IN THE MIDDLE OF A DISK OPERATION? + BEQ 99$ ;NO, DISMISS + MOV #%DFRST,A ;YES, GIVE ERROR STATUS + CLR B + BR 20$ + +10$: BIT #%DCCPL,A ;TEST FOR COMMAND COMPLETION + BPL 99$ ;NO, IGNORE INTERRUPT + MOV DSKCRA,A ;GET COMPLETION STATUS + MOV DSKCRB,B + MOV #%DCACK+%DCCIE,DSKCSR ;ACKNOWLEDGE COMPLETION, ENABLE MORE INTERRUPTS + TST RQBACT ;EXPECTED? + BEQ 99$ ;NO, IGNORE + BIT #%DAPON,A ;POWER-UP INDICATION? + BNE 99$ ;FOR NOW, IGNORE IT + BIT #%DACQE+%DANXM+%DAPAR,A + BEQ 30$ ;OK, NO COMMAND-QUEUE ERROR + MOV #%DCRST,DSKCSR ;RESET CONTROLLER (I DON'T KNOW IF IT NEEDS IT) +20$: MOV A,DSCFLT ;COMMAND-QUEUE ERROR, GIVE STATUS TO PDP10 + MOV B,DSCSTS + BR 80$ + +30$: CLR DSCFLT ;CLEAR HIGH BYTE + MOVB RQBFLT+1,DSCFLT ;PICK UP FAULT CODE, PUT IN LOW BYTE + BEQ 35$ ;IF FAULT CODE IS NON-ZERO, THE THING MAY BE FROZEN, + MOV #%DCRST,DSKCSR ;SO RESET IT. OTHERWISE ERROR SEEMS TO HAPPEN OVER AND OVER +35$: MOV RQBSTS,DSCSTS ;GIVE STATUS TO PDP10 + MOV RQBCYL,DSCCYL ;STORE BACK DISK ADDRESS, MAY BE USEFUL TO PDP10 + MOV RQBHED,DSCHED + MOV RQBSEC,DSCSEC + BIT #%DMRED,RQBCMD ;IF COMMAND WAS READ, COPY BUFFER BACK + BEQ 80$ + MOV #DSKBUF,D + .REPT 4 ;TAKES 4 BYTE POINTERS TO DO IT + MOV #DSCPNT+<2*.RPCNT>,H + .REPT 3 ;EACH BYTE POINTER HAS 768 12-BIT BYTES + MOV #256.,C + CALL MOVDH + .ENDR + .ENDR +80$: SETOM DSCDON ;SIGNAL PDP10 OPERATION IS COMPLETE + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + CLR RQBACT ;NO LONGER EXPECTING COMPLETION ON THE RQB +99$: POP ;RESTORE REGISTERS AND EXIT INTERRUPT + RTI +.ENDC ;T300P + + .SBTTL SET LINE PARAMETERS + +;LINE INDEX IN I +;DH11 PARAM REG IN A +;BUFFER SIZE IN B + +SPARAM: CMP I,#NFTTY + BGE 1$ + BPT +1$: CMP I,#LASTTY + BLE 2$ + BPT +2$: CMP B,#1. ;MINIMUM BUFFER SIZE ONE CHARACTER + BGE 3$ + MOV #1.,B +3$: CMP B,#MAXBSZ ;MAXIMUM BUFFER SIZE CHARACTERS + BLE 4$ + MOV #MAXBSZ,B +4$: MOV B,BUFSIZ(I) ;SET AMOUNT OF BUFFER TO BE USED FROM NOW ON + MOV HDWR(I),H ;(BUT NO LONGER DO WE ATTEMPT DYNAMIC BUFFER ALLOCATION) + CMP H,#NLDHHX + BHI 5$ + MASK 5 ;LINE IS A DH11, HAVE TO SET LINE PARAM REG + MOV DHLSEL(I),@DHSCR(H) ;SELECT THE LINE + MOV A,@DHLPR(H) ;GIVE LINE-PARAMETER REG TO DH11 + UNMASK +5$: MOV A,LPRVAL(I) ;STORE LPR IN CASE SOMEONE IS CURIOUS + RET + + .SBTTL DH11 INPUT INTERRUPT + +.REPT NDHS +CONC DH,\.RPCNT+1, + 2*.RPCNT +.ENDR + +DHIBK: MOV (H),H ;PICK UP HARDWARE INDEX + PUSH +1$: MOV @DHNRC(H),A ;RECIEVE A CHARACTER + BPL DHIEX ;EXIT INTERRUPT IF NO MORE CHARS + MOV A,I ;EXTRACT LINE NUMBER + SWAB I + BIC #177760,I + ASL I + ADD DHTYNO(H),I +.IFNZ NDHUN + CMP I,#NLDHTY ;IGNORE NON-EXISTENT LINES + BHI 1$ +.ENDC + CALL @TTYIPC(I) ;CALL LINE HACKER + BR 1$ ;AND CHECK FOR MORE + +DHIEX: POP + RTI + +;NORMAL DH11 INPUT + +DHNRMI: BIT #%DXPAR,A + BEQ 1$ ;IGNORE IF PARITY ERROR +10$: RET +1$: BIT #%DXBRK,A ;IF BREAK, + BEQ RCV + TST AUTOSP(I) ;AND LINE WANTS AUTOSPEED-ON-BREAK FEATURE + BPL 10$ +ASPMD: MOV #DHASP,TTYIPC(I) ;PUT IT IN AUTOSPEED MODE + MOV DHLSEL(I),@DHSCR(H) ;AND SET HARDWARE TO 1200 BAUD + MOV #023103,@DHLPR(H) + RET + +;CHAR IN A RECEIVED FROM LINE IN I +RCV: BIC #177400,A ;8-BIT CHAR RECEIVE +RCV.FW: TST NO.ITS ;ENTER HERE FOR FULL WORD RECEIVE + BEQ 10$ +21$: MOV #DWNMSG,A ;ITS DOWN, GIVE MESSAGE +12$: CALL GIVMSG + RET + +10$: MOV #TYIRNG,B + CMP RINGCT(B),#TYIRSZ-2 + BGT 11$ + CALL PUT ;FIRST PUT THE CHARACTER + MOV I,A + ASR A + CALL PUT ;THEN THE TENNISH LINE NUMBER + RET + +11$: MOV #IBOMSG,A ;INPUT BUFFER OVERFLOW + BR 12$ + +.IFNZ NMPTYS ;HANDLE INPUT FROM THE MULTIPLEXOR LINE +MPXINP: TST MPXENB + BEQ RCV + MOV MPXSEL,I ;CURRENT INPUT LINE + TSTB A ;SPECIAL CHAR? + BMI 1$ + JMP @TTYIPC(I) ;NO, RECEIVE ON APPROP LINE + +1$: MOV A,I ;SPECIAL CHAR, EXTRACT LINE# + BIC #177700,I +;FOLLOWING FEATURE COMMENTED OUT SINCE IT CAUSES 11 TO LOOP +; WHEN NEXT INPUT ARRIVES -- NOT OBVIOUS HOW TO FIX. +; CMP I,#77 ;SELECT NON-MULTIPLEX INPUT? +; BEQ 3$ ;YES, DO SO + ASL I + ADD #NFMPTY,I + CMP I,#LASTTY + BHI 2$ ;OUT OF RANGE, IGNORE + MOV I,MPXSEL ;INPUT SELECT, SAVE LINE# +2$: RET + +3$: MOV #MPXIDX,MPXSEL ;SELECT PASS THROUGH + RET +.ENDC ;NMPTYS + +;AUTOSPEED MODE COMES HERE WHEN CHAR RECIEVED + +DHASP: BIC #177400,A ;CLEAR FRAMING ERR, ETC. + BEQ ASP10 ;11 0'S = 110 BAUD + CMP A,#200 ;7 0'S, 1 = 150 BAUD + BEQ ASP15 + CMP A,#170 ;3 0'S, 4 1'S, 0 = 300 BAUD + BEQ ASP30 + CMP A,#370 ;300/600 IS NOW RUBOUT, NOT I + BEQ ASP36 + CMP A,#146 ;1 0, 2 1'S, 2 0'S, ... = 600 + BEQ ASP60 + CMP A,#340 ;5 0'S, 3 1'S ? MYSTERY TO ME + BEQ ASP60 + CMP A,#015 ;CR = 1200 + BEQ ASP120 + CMP A,#215 ;CR WITH EITHER PARITY + BEQ ASP120 + MOV A,#. ;SAVE GARBAGE FOR DEBUGGING + RET ;SOMETHING ELSE, IGNORE + +ASP10: MOV #006307,A ;110 IN, 110 OUT, NO PARITY, 8 BITS, EXTRA STPBT + MOV #5,B + MOV #12200,-(SP) + BR ASPX + +ASP15: MOV #012503,A ;150 IN, 150 OUT, NO PARITY, 8 BITS + MOV #7,B + MOV #13300,-(SP) + BR ASPX + +ASP30: MOV #016703,A ;300 IN, 300 OUT, NO PARITY, 8 BITS + MOV #15.,B + MOV #14400,-(SP) + BR ASPX + +ASP36: MOV #020703,A ;300 IN, 600 OUT, NO PARITY, 8 BITS + MOV #30.,B + MOV #14100,-(SP) + BR ASPX + +ASP60: MOV #021003,A ;600 BAUD, NO PARITY, 8 BITS + MOV #30.,B + MOV #11100,-(SP) + BR ASPX + +ASP120: MOV #023103,A ;1200 IN, 1200 OUT, NO PAR, 8 BITS + MOV #60.,B + MOV #15500,-(SP) + BR ASPX + +ASPX: CALL SPARAM ;SET BUFFER SIZE AND HARDWARE SPEED + MOV I,A ;SET UP SET-SPEED COMMAND TO -10 + ASR A + BIS (SP)+,A + TST TTYHNG(I) ;IF THIS IS NEW STATUS FOR 10, + BNE 11$ + INC HNGSIG ;INDICATE STATUS WAITING +11$: MOV A,TTYHNG(I) ;SAVE THIS LINE'S LATEST STATUS + MOV #ASPACK,A ;ACKNOWLEDGE TO USER THAT HE WON + CALL GIVMSG + DEC TYPING(I) ;IF NO WAKEUP FOR 10, HIT CALL WHEN TYPING DONE + MOV NRMIPC(I),TTYIPC(I) ;AND TAKE LINE OUT OF AUTOSPEED MODE + RET + + .SBTTL DH11 OUTPUT INTERRUPTS + +.REPT NDHS +CONC DH,\.RPCNT+1, + 2*.RPCNT +.ENDR + +DHOBK: MOV (H),H ;GET HARDWARE UNIT NUMBER + BIT #DHSNXM,@DHSCR(H) ;IS THIS INTERRUPT DUE TO NXM? + BEQ 1$ + BPT ;YES +1$: BIC #DHTDON,@DHSCR(H) ;HARDWARE KLUDGE TO MAKE INTERRUPTS WIN + PUSH + MOV DHOAC(H),C ;SEE WHICH BAR BITS HAVE TURNED OFF + BIC @DHBAR(H),C + BIC C,DHOAC(H) + MOV DHTYNO(H),I + ADD #15.*2,I +2$: BIT DHLBIT(I),C + BEQ 4$ +.IFNZ NMPTYS + CMP I,#MPXIDX + BNE 3$ + CALL MPXDON +.ENDC ;NMPTYS +3$: +.IFNZ NDHUN + CMP I,#NLDHTY ;IGNORE NON-EXISTENT LINES + BHI 4$ +.ENDC + CALL XMTDON +4$: SUB #2,I + CMP I,DHTYNO(H) + BGE 2$ +DHOEX: POP + RTI + +XMTDON: TST TYPING(I) ;HERE WHEN OUTPUT FINISHES + BGT 1$ ;BRANCH IF -10 WANTS TO KNOW ABOUT IT + BEQ 3$ ;BRANCH IF NOTHING TO DO + MOV #32,A ;SEND A CALL + CALL RCV + BR 3$ + +1$: MOV I,A + ASR A ;PUT TENNISH LINE NUMBER INTO RING + MOV #TYORNG,B ;MAIN PROG LEVEL WILL LATER TELL -10 + CALL PUT +3$: CLR TYPING(I) + RET + +.IFNZ NMPTYS ;OUTPUT DONE ON MULTIPLEXED LINE +MPXDON: PUSH + TST MPXOAC + BGE 1$ + NEG MPXOAC ;SENT HEADER, NOW SEND DATA + MOV MPXOLN,A + MOV MPXPNT(A),D + MOV MPXNBT(A),C + CLR MPXNBT(A) + CALL @STROUT(H) + BR 9$ + +1$: MOV MPXOLN,I ;OUTPUT IS DONE ON THAT LINE NOW + ADD #NFMPTY,I + CALL XMTDON + CLR MPXOAC ;MPX IDLE + CALL STRMPX ;LOOK FOR NEW STUFF TO DO +9$: POP + RET +.ENDC ;NMPTYS + + .SBTTL DL11 INTERRUPTS + +.REPT NDLS +CONC DL,\.RPCNT+1, + NFDLHX+<2*.RPCNT> +CONC DL,\.RPCNT+1, + NFDLHX+<2*.RPCNT> +.ENDR + +DLIBK: MOV (H),H ;GET HARDWARE INDEX OF INTERRUPTING UNIT + PUSH + MOV @DLKB(H),A ;GET RECEIVED CHARACTER + MOV DLTYNO(H),I ;GET LINE NUMBER RECEIVED ON +.IFNZ DTE20P + BNE 2$ ;ONLY T00 CAN RETURN TO KLDCP + BIT #20000,A ;IF BREAK KEY IS HIT + BEQ 1$ + SETOM KLDCPF ;USER WANTS TO RETURN TO KLDCP + BR DLBKEX ;FOR ONE COMMAND LINE + +1$: TST DDTMOD ;IF IN DDT MODE, + BEQ 2$ + BIC #-200,A ; HANDLE INPUT DIFFERENTLY + MOV A,DDTCHR + BR DLBKEX + +2$: +.ENDC ;DTE20P + CALL @TTYIPC(I) +DLBKEX: POP + RTI + +DLOBK: MOV (H),H ;GET HARDWARE INDEX OF INTERRUPTING UNIT + TST DLOAC(H) + BEQ DLBKX1 ;NOT SUPPOSED TO BE TYPING OUT, IGNORE INT + DEC DLBC(H) ;GOT ANY MORE CHARACTERS? + BLT DLBKX2 ;NO, GO GIVE OUTPUT DONE + MOV DLCA(H),-(SP) ;YES, GIVE NEXT CHARACTER + MOVB @(SP)+,@DLPB(H) + INC DLCA(H) +DLBKX1: POP H + RTI + +DLBKX2: PUSH ;OUTPUT DONE + MOV DLTYNO(H),I ;GET TTY INDEX OF INTERRUPTING LINE + CLR DLOAC(H) ;OUTPUT NO LONGER ACTIVE ON THIS LINE + CALL XMTDON + BR DLBKEX + + .SBTTL CLOCK INTERRUPT + +;NOTE - IT IS IMPORTANT THAT THIS BE AT A HIGHER INTERRUPT LEVEL THAN THE CHAOS NET +CLKBRK: SETOM WAKE ;WAKE UP MAIN LOOP +.IFNZ GOULDP + PUSH @#PS ;CHECK GOULD LPT + CALL GLPBRK ;(LOSES INTERRUPTS) + DEC GLPTIM ;TIME TO CHECK GOULD LPT? + BGT 13$ ;NOT YET + MOV #10.*60.,GLPTIM + BIT #%GSNRD,@#GLPCSR ;YES, LOSING? + BNE 14$ ;PROBABLY + CLR GLPERR ;PROBABLY NOT + BR 13$ ;(CAN'T TELL FOR SURE IF %GCON NOT DONE) + +14$: MOV @#GLPCSR,GLPERR ;LPT LOSING, TELL 10 + CALL GLPRST ;AND MAKE SURE BUFFERS DON'T CHOKE UP +.ENDC ;GOULDP +13$: PUSH +.IFNZ NDMS ;MODEM SCANNER GETS SHUT OFF SOMEHOW + CLR A ;loop over the DM11s, turning them on + MOV #NDMS,B +259$: BIT #DMSCN,@DMCSR(A) + BEQ 14$ + BIT #DMIEN,@DMCSR(A) + BNE 15$ +14$: MOV #DMSCN+DMIEN,@DMCSR(A) ;ENABLE SCANNER INTERRUPTS +15$: TST (A)+ ;next DM11 + SOB B,259$ ;until all DM11s done + +.ENDC ;NDMS +.IFNZ CHAOSP ;WAKE-UP OUTPUT LINKS IN RE-TRANSMIT DELAY + MOV #CHXCHS,I +50$: MOV CHOHWR(I),A ;ADDRESS OF HARDWARE CSR + TST CHOSTS(I) ;IF ZERO, IS IDLE, DON'T WANT INTERRUPT ENABLE + BEQ 51$ ;NOTE THAT THIS RUNS MASKED HIGHER THAN CHAOS INT LVL + BIS #%CATEN,(A) ;RE-ENABLE INTERRUPT IF OFF +51$: +.IFNZ CHSBTB + BIT #%CATDN,(A) ;TRANSMIT-DONE? + BNE 59$ + INC CHSIDL(I) ;NO, KEEP TIME-OUT + CMP CHSIDL(I),#60. ;IF TRANSMIT-DONE STUCK OFF FOR 1 SECOND, + BLO 59$ + MOV #%CARST,(A) ; THEN RESET THE INTERFACE +; MOV #%CAREN+%CATEN,(A) ;INTERRUPT ENABLES WILL TURN THEMSELVES BACK ON IF NECESSARY! + INC CHSRST(I) ;COUNT NUMBER OF TIMES HAD TO DO THIS +59$: +.ENDC ;CHSBTB +.IFG CHAOSP-1 + TST (I)+ + CMP I,#CHXCHS+CHAOSP+CHAOSP + BLO 50$ +.ENDC ;CHAOSP-1 + DEC PULSAR ;TIME TO GENERATE TEST PACKET TO CHAOS NET? + BGT 66$ ;NOT YET + MOV PULSON,PULSAR ;RE-INITIALIZE COUNTER +.REPT CHAOSP ;YES, AWAKEN ALL TRANSMIT INTERRUPT SIDES + BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT> +.ENDR +.IFNZ TEN11P + TST CHOSTS+CHXT11 ;AWAITING BUFFER FROM 10? + BNE 65$ ;YES, COUNT TIMEOUT + CLR T11TIM ;NO, RESET TIMEOUT +65$: INC T11TIM +.ENDC ;TEN11P +66$: DEC 4SEC ;TIME FOR 4-SECOND CLOCK? + BGT 90$ + MOV #4*60.,4SEC ;YES + MOV #*2,I ;INCREMENT ROUTING COSTS +71$: TST SBNTYP(I) ;THIS GUY'S COSTS SUPPOSED TO INCREMENT? + BNE 72$ ;NOPE + CMP SBNCST(I),#1000 ;DON'T INCREMENT TOO HIGH AND OVERFLOW + BHIS 72$ + INC SBNCST(I) ;YEP +72$: SUB #2,I + BPL 71$ + DEC 15SEC ;TIME FOR 15-SECOND CLOCK? (REALLY 16) + BGT 90$ + MOV #4,15SEC ;YES +.REPT CHAOSP ;TELL CABLES TO BROADCAST %CORUT PACKETS + SETOM CHXRTF+CHXCHS+<2*.RPCNT> + BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT> +.ENDR +.IIF NZ ETHERP, SETOM CHXRTF+CHXETH ;TELL ETHERNET TO BROADCAST ROUTING +90$: ;CAN'T DO IT NOW BECAUSE WRONG INTERRUPT LEVEL +.ENDC ;CHAOSP +.IF DF NDVRBF + INC DVRTIM ;TIME OUT DOVER CONNECTION + CMP DVRTIM,#15.*60. ;IF IDLE FOR 15 SECONDS, FLUSH + BLO 15$ + CLR DVRHST + CLR DVRMSK +15$: INC DVRRTR ;COUNT UP RETRANSMISSION COUNTER +.ENDC ;NDVRBF +.IFNZ NDMS ;GOT ANY TTYS WITH MODEM CONTROL? + MOV #NFTTY,I ;CHECK FOR HANGUPS +16$: TST DIALED(I) ;HANGUP IN PROGRESS ON THIS LINE? + BPL 17$ ;NO + INC DIALED(I) ;YES, TIMED OUT? + BMI 17$ + CLR DIALED(I) ;YUP, LINE IS HUNG UP + MOV I,A ;TELL -10 ABOUT IT + ASR A + TST TTYHNG(I) ;IF THIS IS NEW STATUS FOR 10, + BNE 18$ + INC HNGSIG ;INDICATE STATUS WAITING +18$: MOV A,TTYHNG(I) ;SAVE THIS LINE'S LATEST STATUS +17$: ADD #2,I + CMP I,#LASTTY + BLO 16$ +.ENDC ;NDMS + POP + + ROR SWR ;LOW BIT OF SWITCHES => DDT + BCC CLKEX + BPT +CLKEX: RTI + .IFNZ NDMS + .SBTTL MODEM CONTROL + +;;; hack multiple DM interrupt vectors +.REPT NDMS +CONC DM,\.RPCNT+1, + 2*.RPCNT +.ENDR ;NDMS + + +DMBRK: PUSH + MOV (H),A ;get the device offset in A + MOV @DMCSR(A),I ;GET ASSOCIATED TTY INDEX + BIC #177760,I ;gives us channel (0-17) on this DM11 + ;; now add to get offset into table for any DM + MOV A,B ;device offset in B, is 2*device number + ASL B + ASL B + ASL B ;multiply by 8 for offset in B + ADD B,I ;add to I for offset for this channel + ASL I ;now get word offset in I by shifting + ;; get index into map between DM channels and TTY indices + MOV M2LMAP(I),I + BEQ 90$ ;EXIT IF THIS LINE NOT UNDER MODEM CONTROL +; TST @DMCSR(A) .SEE DMRNG +; BPL 10$ +; TST DIALED(I) ;RINGING. IS LINE DIALED UP ALREADY? +; BNE 10$ ;YES, NOT SUPPOSED TO BE RINGING +; MOV #LINENB+LINDTR,@DMLSR(A) ;ANSWER THE PHONE + +10$: BIT #LINCTS,@DMLSR(A) ;DO WE HAVE CLEAR-TO-SEND? + BEQ 20$ ;NO + TST DIALED(I) ;YES, WHAT WAS PREVIOUS STATE? + BEQ 13$ ;WAS OFF, THIS IS A DIALUP + BPL 90$ ;WAS ON, IGNORE + NEG DIALED(I) ;WAS HANGING UP, ABORT IT + BR 90$ + +13$: INC DIALED(I) ;LINE IS NOW DIALED UP + TST DMINI ;IF GETTING INITIAL STATE, + BNE 90$ ;DON'T HACK AUTOSPEED + TST AUTOSP(I) ;IF IT HAS AUTOSPEED, + BEQ 90$ + MOV HDWR(I),H ;HACK THAT + CALL ASPMD + BR 90$ + +20$: TST DIALED(I) ;CTS DROPPED + BMI 90$ ;ALREADY KNOWN ABOUT, IGNORE + MOV #-HNGDLY,DIALED(I) ;OTHERWISE START HANGUP TIMEOUT + +90$: BIC #DMDON,@DMCSR(A) ;RESTART SCANNER + POP + POP H + RTI +.ENDC ;NDMS + +.IFNZ GOULDP +.SBTTL GOULD PRINTER P.I. LEVEL + +GLPBRK: BIT #%GSBSY,@#GLPCSR + BEQ 1$ + RTI ;LPT BUSY, WAIT + +1$: BIT #%GSDON,@#GLPCSR + BNE 2$ + RTI ;LPT BUSY OTHER FLAVOR + +2$: PUSH + BIT #%GSERR,@#GLPCSR ;LPT LOSING? + BEQ GLPBR1 + CALL GLPRST ;YUP, RESET THE BUFFERS + MOV @#GLPCSR,GLPERR ;AND TELL 10 + +GLPOFF: CLR GLPOAC ;HERE TO STOP P.I. + MOV #%GCIOF,@#GLPCSR + MOV #5000.,A ;LPT SOMETIMES BUSY FOR A WHILE +1$: BIT #%GSBSY,@#GLPCSR ;HAVE TO WAIT SO TONER PUMPS WILL + BEQ 2$ ;REALLY TURN OFF + SOB A,1$ +2$: MOV #%GCOFF,@#GLPCSR +GLPEX: POP + RTI + +GLPFIN: MOV #%GBIDL,GB.STA(H) ;DONE WITH THIS BUFFER + MOV GB.NXT(H),H ;CHECK NEXT + MOV H,GLPOOP + +GLPBR1: MOV GLPOOP,H ;CHECK ON BUFFERS + CMP GB.STA(H),#%GBDMA ;FINISH DMA XFER? + BEQ GLPFIN ;YES + CMP GB.STA(H),#%GBWRT ;QUEUED OR ALREADY ACTIVE AT P.I.? + BLT GLPOFF ;NO, STOP + MOV #%GBPI,GB.STA(H) ;YES, ACTIVATE IT AT P.I. + TST GB.FF(H) ;NEED FF? + BEQ 1$ + MOV #%GCFF,@#GLPCSR ;YES + CLR GB.FF(H) + BR GLPEX + +1$: TST GB.NL(H) ;NEED BLANK LINES? + BEQ 2$ + DEC GB.NL(H) ;YES, GIVE ONE + MOV #%GCADV,@#GLPCSR + BR GLPEX + +2$: MOV H,B ;SET UP TEXT ADDR + ADD #GB.DAT,B + MOV GB.PNT(H),A ;SET UP TEXT WORD COUNT + NEG A + MOV A,@#GLPWC + MOV B,@#GLPCA ;START XFER + MOV #%GBDMA,GB.STA(H) ;FLAG BUFFER ACTIVE AT DMA LEVEL + BR GLPEX + +GLPRST: PUSH H + MOV #GLPBFF,H ;FLUSH ALL BUFFERS + MOV H,GLPOOP + MOV H,GLPOIP +3$: CLR (H)+ + MOV (H),H + CMP H,#GLPBFF + BNE 3$ + MOV #60.*10.,GLPTIM ;SET TIMEOUT + POP H + RET + +.ENDC ;GOULDP + +.IFNZ CHAOSP + + .SBTTL CHAOSNET ROUTINES + +;ALL ROUTINES ON THIS PAGE CALLED WITH INTERRUPTS MASKED, INDEX IN I. + +;REFILL FROM CHAOS INTERFACE +CHSRFL: BIS #%CAREN,@CHIHWR(I) ;TURN ON RECEIVER INTERRUPTS + RET ;WILL NOTICE INPUT LATER + +.IFNZ DL10P +;LOOPS BACK TO HERE WHEN DISCARDING A PACKET +DLCRF1: CMP (SP)+,(SP)+ ;POP + POP A + INC DLCSS1(A) ;2 ;INDICATE BUFFER HAS BEEN COPIED + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + ;DROP INTO DLCRFL +;REFILL FROM DL10 +DLCRFL: CALL DLCCHK ;SEE IF DL10 IS DISABLED + BNE 99$ ;BRANCH IF YES + MOV #2,A ;CHECK BOTH 10 TO 11 BUFFERS SO CAN'T GET OUT OF PHASE WITH 10 +10$: CMP DLCSS1(A),#1 ;10 SAYS BUFFER READY? + BEQ 11$ ;YES + SUB #2,A ;NO, TRY NEXT + BPL 10$ + BR 99$ ;NONE READY + +11$: PUSH A ;SAVE CURRENT 10 TO 11 BUFFER + ADD #DLCSP1,A ;OUTPUT READY, GET IT + MOV #DLCIBF,B ;COPY INTO BUFFER +.REPT PKHDW ;FIRST GET HEADER + MOV (A),(B)+ +.ENDR + PUSH + CALL CHSIHD ;PROCESS HEADER, GET LENGTH, DEST + BVS DLCRF1 ;BRANCH IF PACKET NO GOOD + POP + PUSH C + SUB CHIHDL(I),C ;GET NUMBER OF DATA WORDS TO FOLLOW + CALL MOVHD ;MOVE THOSE WORDS + POP ;RESTORE LENGTH, 10 TO 11 BUFFER NUMBER + INC DLCSS1(A) ;2 ;INDICATE BUFFER HAS BEEN COPIED + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + TST B ;SWAB IF NOT TO 10-COMPATIBLE DEST + CALL SWAB10 + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND +99$: RET + +;TRANSMIT TO DL10 OUTPUT SINK +;REQUIRES I TO BE SET UP, SMASHES ALL REGS. +DLCXMT: CALL DLCCHK ;DL10 DISABLED? + BNE 70$ ;YES, DISCARD PACKET + MOV DLCRBN,A ;GET CURRENT 11 TO 10 BUFFER NUMBER + CMP DLCRS1(A),#1 ;BUFFER READY? + BNE 80$ ;NO, WAIT + MOV CHOINX+CHXDLC,D ;GET ADDRESS OF BUFFER TO BE SENT OVER + MOV CHILNG(D),C ;AND LENGTH + MOV CHIBFP(D),D + MOV A,H ;GET POINTER TO DL10 MAGIC IDPB WORD + ADD #DLCRP1,H + CALL MOVDH ;COPY WORDS INTO PDP10 + INC DLCRS1(A) ;SIGNAL DATA AVAILABLE TO PDP10 + BIS #DLX10I,DLXCSR ;AND INTERRUPT IT + MOV DLCNXT(A),DLCRBN ;SWITCH BUFFERS +70$: JMP CHSODN ;TRANSMISSION IS DONE ALREADY + +80$: MOV #1,CHOSTS+CHXDLC ;TRANSMISSION AWAITING BUFFER FROM 10 + RET + +;CALL HERE WHEN DL10 INTERRUPTS, CLOBBERS ALL. +DLCWAK: MASK 5 + TST CHOSTS+CHXDLC ;DL10 HUNG ON TRANSMIT? + BEQ 10$ + MOV #CHXDLC,I ;YES, WAKE IT UP + CALL DLCXMT +10$: TST CHISTS+CHXDLC ;DL10 INPUT ACTIVE? + BNE 20$ + MOV #CHXDLC,I ;NO, TRY TO GET SOME + CALL DLCRFL + TST CHISTS(I) ;GOT SOME? + BLE 20$ + CALL CHSOUT ;YES, START TRANSMISSION +20$: CALL CHSRUN ;DO ANYTHING ELSE REQUIRED + UNMASK + RET + +;RETURN 'NE' IF DL10 IS DISABLED, BASHES NOTHING. +DLCCHK: TST DLXOFF + BNE 99$ + TST NO.ITS + BNE 99$ + TST DLCINI ;RE-INITIALIZE? + BEQ 99$ ;NO, EVERYTHING IS OK. + CLR DLCRBN ;YES + TST CHOSTS+CHXDLC ;WAS OUTPUT HUNG ON DL10? + BEQ 90$ + PUSH ;YES, SIGNAL OUTPUT DONE ON DL10 + MOV #CHXDLC,I + CALL CHSODN + POP +90$: CLR DLCINI ;SIGNAL INIT DONE, RETURN 'EQ' +99$: RET +.ENDC ;DL10P + +;FAST BLOCK MOVE +;THESE CAN MOVE AT MOST 256. WORDS + +;MOV (H),(D)+ +;SOB C,.-2 +MOVHD: SUB #256.,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO MOVE TABLE + .REPT 256. + MOV (H),(D)+ + .ENDR + RET + +;MOV (D)+,(H) +;SOB C,.-2 +MOVDH: SUB #256.,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO MOVE TABLE + .REPT 256. + MOV (D)+,(H) + .ENDR + RET + +.IFNZ TEN11P +;REFILL FROM TEN-11 INTERFACE +T11RFL: CALL T11CHK ;CHECK FOR DISABLE + BNE 99$ ;BRANCH IF DISABLED + MOV T11IBP,A + TST T11IBA ;WAS INPUT BUFFER IN USE? + BEQ 10$ + CLR (A)+ ;YES, INDICATE BUFFER IS NOW EMPTY + CLR (A) + CLR T11IBA + ADD #T11BFL-2,A ;ADVANCE POINTER + CMP A,#T11IBE + BLO 7$ + MOV #T11IBF,A +7$: MOV A,T11IBP +10$: TST (A) ;INPUT BUFFER CONTAIN A PACKET? + BEQ 99$ ;NO + SETOM T11IBA ;YES, INPUT BUFFER NOW ACTIVE + ADD #8,A ;GET INPUT FROM PDP10 + MOV A,CHIBFP+CHXT11 ;AS CURRENT INPUT BUFFER + CALL CHSIHD ;PROCESS THE HEADER + BVS T11RFL ;BRANCH IF PACKET NO GOOD + PUSH ;COMPUTE CHECKSUM BEFORE SWABBING + INC C ;C GETS NUMBER OF 32-BIT WORDS + ASR C + CLR D ;CLEAR LOW WORD OF CHECKSUM + CLR H ;CLEAR HIGH WORD OF CHECKSUM + SUB #PKFCMS+1,PKFC(A) ;DECREMENT FWD COUNT (IS HIGH END OF WORD) + ;FWD COUNT HAS TO BE PUT BACK FOR CHECKSUM COMPUTATION +21$: ADD (A)+,H ;ADD HIGH HALFWORD TO HIGH SUM + ADD (A)+,D ;ADD LOW HALFWORD TO LOW SUM + ADC H ;CARRY INTO HIGH SUM + MOV D,B ;NOW ROTATE RIGHT DOUBLE + ROR B + ROR H + ROR D + SOB C,21$ + MOV T11IBP,A ;NOW COMPARE CHECKSUM + CMP H,4(A) + BNE 30$ + CMP D,6(A) + BNE 30$ + POP + ADD #PKFCMS+1,PKFC(A) ;INCREMENT FWD COUNT (IS HIGH END OF WORD) + TST B ;SWAB IF NOT TO 10-COMPATIBLE DEST + CALL SWAB10 + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND +99$: RET + +30$: POP ;CHECKSUM ERROR + INC T11CKE ;COUNT CHECKSUM ERRORS + BR T11RFL ;AND IGNORE PACKET + +;TRANSMIT TO TEN11 OUTPUT SINK +;REQUIRES I TO BE SET UP, SMASHES ALL REGS. +T11XMT: CALL T11CHK ;TEN11 DISABLED? + BNE 70$ ;YES, DISCARD PACKET + TST @T11OBP ;OUTPUT BUFFER EMPTY? + BNE 80$ ;NO, WAIT + MOV CHOINX+CHXT11,D ;GET ADDRESS OF BUFFER TO BE SENT OVER + MOV CHIBFP(D),B + MOV CHILNG(D),C ;AND LENGTH + MOV PKNBYT(B),A + BIT #1,A ;IF ODD NUMBER OF BYTES, CLEAR THE EXTRA ONE + BEQ 5$ + BIC #PKNBMS,A + ADD B,A + CLRB PKDAT-1(A) ;NOTE, AT THIS POINT BYTES ARE SWAPPED +5$: MOV T11OBP,A ;COPY INTO TEN11 OUTPUT BUFFER + ADD #8,A + PUSH +10$: MOV (B)+,(A)+ + SOB C,10$ + MOV (SP),C ;NOW COMPUTE CHECKSUM + INC C ;C GETS NUMBER OF 32-BIT WORDS + ASR C + BCS 11$ + CLR (A)+ ;IF ODD NUMBER OF 16-BIT WORDS, CLEAR THE EXTRA ONE +11$: CLR D ;CLEAR LOW WORD OF CHECKSUM + CLR H ;CLEAR HIGH WORD OF CHECKSUM + MOV T11OBP,A + ADD #8,A +21$: ADD (A)+,H ;ADD HIGH HALFWORD TO HIGH SUM + ADD (A)+,D ;ADD LOW HALFWORD TO LOW SUM + ADC H ;CARRY INTO HIGH SUM + MOV D,B ;NOW ROTATE RIGHT DOUBLE + ROR B + ROR H + ROR D + SOB C,21$ + MOV T11OBP,A ;STORE CHECKSUM INTO OUTPUT BUFFER + MOV H,4(A) + MOV D,6(A) + POP + SETOM (A) ;SIGNAL PRESENCE OF PACKET TO PDP10 + ADD #T11BFL,A ;ADVANCE POINTER + CMP A,#T11OBE + BLO 30$ + MOV #T11OBF,A +30$: MOV A,T11OBP +70$: CLR T11TIM ;NO TIMEOUT, 10 IS TAKING PACKETS + JMP CHSODN ;TRANSMISSION IS DONE ALREADY + +80$: MOV #1,CHOSTS+CHXT11 ;TRANSMISSION AWAITING BUFFER FROM 10 + RET + +;WHACK YOUR TEN11 +T11WAK: MASK 5 + MOV #CHXT11,I + CALL T11CHK ;IS 10 UP? + BNE 30$ ;IT'S DOWN, PUNT IT + TST CHOSTS(I) ;TEN11 HUNG ON TRANSMIT? + BEQ 10$ + CALL T11XMT ;YES, WAKE IT UP +10$: TST CHISTS+CHXT11 ;TEN11 INPUT ACTIVE? + BNE 20$ + MOV #CHXT11,I ;NO, TRY TO GET SOME + CALL T11RFL + TST CHISTS(I) ;GOT SOME? + BLE 20$ + CALL CHSOUT ;YES, START TRANSMISSION +20$: CALL CHSRUN ;DO ANYTHING ELSE REQUIRED + UNMASK + RET + +30$: TST CHOSTS(I) ;TRANSMITTING TO DEAD TEN-11? + BEQ 20$ + CLR T11TIM ;YES, FLUSH IT + CALL CHSODN + BR 20$ + +;CHECK TEN-11 INTERFACE, DO RESET IF NECESSARY, RETURN 'NE' IF DISABLED. +;SMASHES NOTHING. +T11CHK: CMP T11TIM,#5*60. ;10 TAKING 5 SECONDS TO RESPOND? + BLO 5$ + SETOM T11I10 ;YES, DECLARE IT DOWN, REINITIALIZE PROTOCOL +5$: TST T11I10 ;IS 10 DONE INITIALIZING? + BNE 99$ ;NO, DO NOTHING + TST T11I11 ;ARE WE SUPPOSED TO INITIALIZE? + BEQ 99$ ;NO, IT'S OK + MOV #T11OBF,T11OBP ;YES, REINITIALIZE POINTERS + MOV #T11IBF,T11IBP + PUSH A + MOV #T11OBF,A ;INITIALIZE INPUT AND OUTPUT BUFFER HEADERS +10$: CLR (A)+ ;CLEAR INTER-MACHINE SIGNAL WORD + CLR (A)+ + ADD #T11BFL-4,A ;SKIP THE REMAINING WORDS + CMP A,#T11IBE + BLO 10$ + CLR T11IBA ;IDLE THE INPUT + POP A + TST CHOSTS+CHXT11 ;WAS OUTPUT HUNG ON TEN11? + BEQ 90$ + PUSH ;YES, SIGNAL OUTPUT DONE ON TEN11 + MOV #CHXT11,I + CALL CHSODN + POP +90$: CLR T11I11 ;SIGNAL INIT DONE, RETURN 'EQ' + CLR T11I11+2 +99$: RET +.ENDC ;TEN11P + +;THIS ROUTINE PROCESSES THE HEADER OF PACKET IN INPUT BUFFER FOR SOURCE I +;RETURN DESTINATION OUTPUT SINK INDEX IN B (-1 IF THIS IS FOR US (PDP11 ITSELF)), +;PACKET BUFFER POINTER IN A, AND LENGTH IN WORDS IN C. +;RETURNS WITH OVERFLOW SET IF PACKET IS DISCARDED BECAUSE OF +;TOO MUCH FORWARDING, BAD ADDRESS, TOO BIG, CRUFTY, ETC. +;OTHERWISE RETURNS WITH MINUS INDICATOR SET IF PACKET DIRECTED TO 11. +CHSIHD: ADD #1,NPKSI(I) ;COUNT PACKETS IN FROM THIS SOURCE + ADC HPKSI(I) + MOV CHIBFP(I),A ;POINTER TO PACKET + TSTB (A) ;CHECK FOR MUPPET + BNE CHSIHB ;DISCARD, WE DON'T SUPPORT THEM + MOV #PKHDW,CHIHDL(I) ;SET HEADER LENGTH + ADD #PKFCMS+1,PKFC(A) ;INCREMENT FWD COUNT (IS HIGH END OF WORD) + BCS CHSIHB ;BRANCH IF FORWARDING LOOP + MOV PKNBYT(A),C ;GET BYTE COUNT + BIC #PKNBMS,C + CMP C,#DATMAX + BHI CHSIHB ;TOO LONG, LOSES + INC C ;MAKE WORD COUNT + ASR C + ADD CHIHDL(I),C ;ADD IN LENGTH OF HEADER + MOV C,CHILNG(I) ;SAVE FOR LATER USE + ;; NOW ROUTE THIS PACKET + MOV #-1,B ;MAGIC INDEX MEANING "MYSELF" + MOV PKDHST(A),D ;GET DESTINATION ADDRESS + ;HERE WE HAVE HAIR FOR MULTIPLE CHAOSNETS +.REPT CHAOSP + CONC ,\.RPCNT ;ADDRESSED TO PDP11 ITSELF? + BEQ 50$ ;YES, LET CHSRUN HANDLE IT LATER +.ENDR ;CHAOSP + CMPB PKOP(A),#%CORUT ;ROUTING INFO PACKET? + BEQ 40$ ;YES, ADDRESS TO PDP11 + TST USECBL ;SUPPOSED TO USE CABLE EVEN TO TALK TO SELF? + BEQ 20$ + CMP I,#CHXCHS ;YES, IS THIS COMING FROM CABLE? + BHIS 20$ ;YES, ROUTE REGULAR WAY + MOV #CHXCHS,B ;NO, SEND TO SELF ON FIRST CABLE + MOV #CHADD,D + BR 39$ + +20$: MOVB PKDHST+1(A),B ;GET SUBNET ADDRESSED TO + CMP B,#NSUBNT + BLO 21$ + CLR B ;OUT OF RANGE, USE 0 +21$: ASL B ;MAKE INDEX INTO SUBNET TABLES + TST SBNTYP(B) ;IS THIS A DIRECT HARDWARE CONNECTION? + BGT 38$ ;YES, SEND TO IT + MOV SBNADR(B),D ;NO, GO VIA GATEWAY + BEQ CHSIRF ;HAVEN'T GOT A GATEWAY, AND BROADCAST CODE NOT WORKING YET + MOVB SBNADR+1(B),B ;GET SUBNET GATEWAY IS ON + ASL B ;MAKE INDEX INTO TABLES + CMP B,#NSUBNT*2 + BHIS CHSIRF ;OUT OF RANGE, CAN'T GET THERE FROM HERE + TST SBNTYP(B) ;IS THIS A DIRECT CONNECTION? + BLE CHSIRF ;NO, CAN'T GET THERE FROM HERE (SHOULDN'T HAPPEN!) +38$: MOV SBNADR(B),B ;GET SINK INDEX +39$: MOV D,CHICBA(I) ;STORE CABLE ADDRESS OF IMMEDIATE DEST (GATEWAY) +.IIF NDF NDVRBF, 50$: ;IF NO DOVER, ALL TO-11 PACKETS COME HERE +40$: MOV B,CHIOUX(I) ;STORE SINK INDEX, SET INDICATORS + RET ;NOTE THAT MOV CLEARS OVERFLOW + +.IF DF NDVRBF +50$: CMP PKDIND(A),DVRLIX ;DIRECTED TO DOVER? + BNE 40$ ;NO, TO 11 + CMP PKSHST(A),DVRHST + BNE 40$ ;NOT DOVER-CONNECTED HOST + CMP PKSIND(A),DVRIDX + BNE 40$ ;RIGHT HOST, WRONG PROCESS + MOV #CHXDVR,B ;ROUTE PACKET TO DOVER GATEWAY + BR 40$ +.ENDC ;NDVRBF + +;HERE FOR ROUTING FAILURE. METER, RETURN WITH OVERFLOW SET. +CHSIRF: INC NPKSRF + MOV B,RFSBNT ;SAVE 2* SUBNET TRYING TO GET TO + ;FALL INTO CHSIHB +;HERE WHEN CHSIHD SEES A GARBAGE PACKET. RETURN WITH OVERFLOW SET. +CHSIHB: ADD #1,NPKSBD(I) ;GOD-DAMN BRAIN-DAMAGE + ADC HPKSBD(I) + SEV + RET + +;SWAB PACKET COMING FROM PDP-10 OR ETHERNET (BYTES LEFT TO RIGHT) +;IF GOING TO INCOMPATIBLE DESTINATION. CALL RIGHT AFTER CHSIHD. +SWAB10: BMI CHSSWB ;SWAB IF TO-11 + CMP CHOXMT(B),#CHSXMT ;CHECK DESTINATION TYPE + BEQ CHSSWB ;PDP11 OR CHAOSNET, SWAB IT OUT +5$: RET ;PDP10 OR ETHERNET, LEAVE ALONE + +;SWAB PACKET COMING FROM PDP-11 OR CHAOSNET (BYTES RIGHT TO LEFT) +;IF GOING TO INCOMPATIBLE DESTINATION. CALL RIGHT AFTER CHSIHD. +SWAB11=. + BMI 5$ ;RETURN IF TO-11 + CMP CHOXMT(B),#CHSXMT ;CHECK DESTINATION TYPE + BEQ 5$ ;PDP11 OR CHAOSNET, LEAVE ALONE + ;PDP10 OR ETHERNET, SWAB IT OUT + ;DROPS THROUGH INTO CHSSWB +;THIS ROUTINE SWABS THE PACKET FOR THE SOURCE IN I. +;CALLED WITH NUMBER OF WORDS IN PACKET IN C. +;CLOBBERS A, C, AND D. +;SUITABLE FOR CALLING RIGHT AFTER CHSIHD RETURNS. +CHSSWB: MOV CHIBFP(I),A ;ADDRESS OF PACKET + SUB CHIHDL(I),C ;GET LENGTH OF DATA AREA IN WORDS + BLE 99$ ;EMPTY + MOVB PKOP(A),D ;GET OPCODE + BPL 5$ ;BRANCH IF NON-DATA + BIT #100,D ;CHECK FOR BINARY DATA + BEQ 10$ ;NO, GO SWAB +99$: RET + +5$: TSTB CHSBIN(D) ;CONTROL, LOOK UP OPCODE + BNE 99$ ;BINARY, NO SWAB +10$: ADD CHIHDL(I),A ;POINT TO DATA AREA OF BUFFER + ADD CHIHDL(I),A ;BYTES, WATSON, BYTES! + SUB #PKTMXW,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO SWAB TABLE + .REPT PKTMXW + SWAB (A)+ + .ENDR + RET + +;BYTE TABLE INDEXED BY OPCODE, NON-ZERO IF BINARY +;BINARY OPERATIONS ARE 2 (%COOPN), 7 (%COSTS), 10 (%CORUT) +CHSBIN: .BYTE 0,0,2,0,0,0,0,7,10,0,0,0,0,0 + .BYTE 0,0 ;SPARES IN CASE MORE OPCODES ADDED + .EVEN + +;TRANSMIT PACKET FROM INPUT SOURCE I TO OUTPUT SINK, IN B. +;SMASHES ALL REGISTERS. CHISTS(I), CHIOUX(I), CHICBA(I) MUST BE ALREADY SET UP. +CHSOUT: TST B ;THIS DESTINED TO PDP11? + BMI CHSOUX ;YES, LET CHSRUN PICK IT UP LATER + TST CHOSTS(B) ;IS SINK BUSY? + BNE CHSOUX ;YES, CAN'T SEND NOW, WILL TRY AGAIN LATER + NEG CHISTS(I) ;NO, SET SOURCE STATUS TO CONNECTED + MOV I,CHOINX(B) ;CONNECT SINK TO SOURCE + MOV B,I ;SET UP SINK INDEX + ADD #1,NPKSO(I) + ADC HPKSO(I) + JMP @CHOXMT(I) ;GO START TRANSMISSION TO SINK + +;CALL HERE WHEN OUTPUT IS DONE ON SINK I. +CHSODN: CLR CHOSTS(I) ;IDLE THE SINK + PUSH I + MOV CHOINX(I),I ;GET CORRESPONDING SOURCE + CLR CHISTS(I) ;IDLE IT + CALL @CHIRFL(I) ;TELL SOURCE IT'S DONE, TRY TO GET MORE INPUT + POP I +CHSOUX: RET + +;CALL HERE AFTER EACH PACKET TRANSFER TO INITIATE AS MANY ADDITIONAL TRANSFERS +;AS POSSIBLE. BASHES ALL REGISTERS. ON DL10 AND TEN11, WE COULD ACTUALLY DO SEVERAL +;TRANSFERS BEFORE RETURNING. +CHSRUN: +.IF DF NDVRBF + CALL DVRRFL ;WAKE UP DOVER, MIGHT BE TIME TO RETRANSMIT +.ENDC ;NDVRBF + MOV #*2,I ;SCAN ALL INPUT SOURCES +CHSRN1: TST WAKE ;GIVE UP IF CLOCK HAS TICKED, LET TTYS RUN + BNE CHSOUX + TST CHISTS(I) ;IS THIS SOURCE LOOKING FOR A SINK? + BLE CHSRN3 +CHSRN2: MOV CHIOUX(I),B ;GET SINK IT WANTS TO SEND TO + BMI FOR11 ;BRANCH IF FOR PDP11 + TST CHOSTS(B) ;SINK AVAILABLE? + BNE CHSRN3 ;NO, LET INPUT SIT + CALL CHSOUT ;YES, ATTEMPT TO TRANSMIT + BR CHSRUN ;LOOK FOR MORE WORK + +CHSRN3: SUB #2,I ;NEXT INPUT SOURCE + BGE CHSRN1 + RET ;NOTHING LEFT TO DO + +FOR11: MOV CHIBFP(I),A ;PACKET FOR PDP11, CHECK IT OUT + MOVB PKOP(A),B ;GET OPCODE + CMP B,#%CORUT ;IF ROUTING INFO, GOBBLE IT + BEQ CHARUT + CMP B,#%CORFC ;ALL WE KNOW IS RFC TO CERTAIN CONTACT NAMES + BNE FOR11J ;BARF AT JUNK PACKETS + CALL SERVE ;RUN THE SERVER + BEQ FOR11X ;IT DIDN'T LIKE IT +FOR11R: PUSH ;INTERCHANGE SOURCE AND DESTINATION + MOV PKSHST(A),PKDHST(A) + MOV PKSIND(A),PKDIND(A) + POP + CALL CHSIHD ;ROUTE + BVS FOR11X ;NO GOOD, FLUSH (SOURCE IN PACKET WAS WRONG) + CALL SWAB11 ;SWAB IF GOING TO 11-INCOMPATIBLE DEST + BR CHSRN2 ;FIRE IT OFF (CHISTS IS ALREADY 1) + +FOR11X: CLR CHISTS(I) ;DISCARD THIS PACKET + CALL @CHIRFL(I) + BR CHSRUN ;LOOK FOR MORE WORK + +;PACKET FROM RANDOM PLACE DIRECTED TO 11, TELL HIM TO GO AWAY +FOR11J: CMP B,#%COLOS ;DON'T BARF AT LOS PACKETS + BEQ FOR11X + MOV #<%COLOS*400>,(A) + MOV #6$-5$-1,PKNBYT(A) + MOV #5$,B + MOV A,C + ADD #PKDAT,C +1$: MOVB (B)+,(C)+ + BNE 1$ + BR FOR11R ;SEND OFF THE LOS +5$: .ASCIZ /Packet unrecognized by gateway-11/ +6$: .EVEN + +;ROUTING PACKET +CHARUT: MOV CHILNG(I),C ;GET NUMBER OF DATA WORDS + SUB #PKHDW,C + ASR C ;MAKE NUMBER OF 2 WORD PAIRS + BEQ FOR11X ;MIGHT BE ZERO-LENGTH + MOV A,D + ADD #PKDAT,D ;POINT TO START OF PACKET'S DATA +61$: MOV (D)+,B ;GET SUBNET BEING TALKED ABOUT + CMP B,#NSUBNT ;ONE WE KNOW ABOUT? + BHIS 62$ ;NO, FORGET IT + ASL B ;MAKE WORD INDEX + TST SBNTYP(B) ;IS THIS AN AUTO ROUTING TYPE SUBNET? + BNE 62$ ;NO, DON'T MUNG OUR FIXED ROUTING INFO + CMP (D),SBNCST(B) ;COMPARE COSTS + BHI 62$ ;NEW ONE WORSE (IF EQUAL, SWITCH TO EQUALIZE LOAD) + MOV (D),SBNCST(B) ;SAVE BEST COST + MOV PKSHST(A),SBNADR(B) ;AND HOST ADDRESS THIS CAME FROM AS BEST BET +62$: TST (D)+ ;SKIP COST + SOB C,61$ + BR FOR11X ;DONE WITH PACKET + + .SBTTL CHAOS NET SERVERS + +;CALLED WITH PACKET IN A. +;MUST PRESERVE A,I. +;RETURN 'EQ' IF NO GOOD, 'NE' IF MODIFIED PACKET TO BE RETURNED TO SOURCE + +;CURRENTLY WE SERVE THE FOLLOWING CONTACT NAMES: +; STATUS - RETURNS ANS WITH THE NAME OF THE MACHINE, LATER WILL HAVE OTHER DATA +; PULSAR - RETURNS ANS WITH DATA OF 1 BYTE, VALUE OF PULSON AS AN ASCII DIGIT, +; I.E. "0" MEANS OFF, "1" MEANS 60 PER SECOND, ETC. +; IF CONTACT NAME IN RFC IS FOLLOWED BY A SPACE AND AN ASCII DIGIT, +; SETS PULSON TO THAT STATUS. +; DOVER - DOVER PROTOCOL TRANSLATOR + +;NOTE THAT WE DON'T USE THE MOST WINNING STRING COMPARE IN THE WORLD, +;THIS CODE ASSUMES IT DOESN'T MATTER WHAT HAPPENS IF AN RFC TO +;AN UNKNOWN CONTACT NAME IS DONE, AS LONG AS THE 11 DOESN'T CRASH. + +SERVE: MOV #SRVTBL,B ;ADDRESS OF SERVER TABLE +10$: MOV (B)+,D ;ADDRESS OF CONTACT NAME FOR THAT SERVER + BEQ 99$ ;EXIT IF TABLE EXHAUSTED, 'EQ' IN COND CODE + MOV A,C + ADD #PKDAT,C ;ADDRESS OF CONTACT NAME IN THIS RFC +11$: TSTB (D) ;END OF STRING? + BEQ 20$ ;YUP, RUN THIS SERVER + CMPB (C)+,(D)+ ;DO STRING COMPARE + BEQ 11$ ;MATCHES + TST (B)+ ;DOESN'T MATCH, TRY NEXT + BR 10$ + +99$: RET + +20$: JMP @(B)+ ;CALL SERVER, IT CAN RETURN EQ OR NE + +SRVTBL: .WORD 1$,STSSRV ;STATUS - RETURN HOST NAME AND METERS + .WORD 2$,PLSSRV ;PULSAR - SET AND GET PULSAR RATE +.IIF DF NDVRBF, .WORD 3$,DVROPN ;DOVER - DOVER PROTOCOL TRANSLATOR + .WORD 0 ;END OF TABLE +1$: .ASCIZ /STATUS/ +2$: .ASCIZ /PULSAR/ +3$: .IIF DF NDVRBF, .ASCIZ /DOVER/ + .EVEN + +;SERVERS MUST PRESERVE A (PACKET), AND I, AND RETURN 'NE' IF TO BE SENT BACK TO SOURCE. +;NOTE THAT C POINTS AT THE NEXT BYTE AFTER THE CONTACT NAME + +STSSRV: MOV A,B ;RFC TO "STATUS", CHANGE INTO ANS CARRYING APPROPRIATE DATA. + MOV #32.+<12.*NCHX>+<24.*CHAOSP>+<12.*ETHERP>,PKNBYT(A) ;SET BYTE LENGTH, CLEAR FORWARDING COUNT + ADD #PKDAT,B + MOV #HSTNAM,D ;SEND NAME OF HOST + MOV #32.,C +45$: MOVB (D)+,(B)+ + SOB C,45$ + CLR D ;NOW STORE METERING INFO FOR EACH SUBNET +50$: MOV CHXSBN(D),(B)+ ;STORE SUBNET NUMBER+400 + MOV #4,(B)+ ;ASSUME NOT A CABLE + MOV NPKSI(D),(B)+ + MOV HPKSI(D),(B)+ + MOV NPKSO(D),(B)+ + MOV HPKSO(D),(B)+ +.IFNZ ETHERP + CMP D,#CHXETH ;ETHERNET HAS SOME OF THESE COUNTERS + BNE 55$ + MOV #12.,-10.(B) ;THERE ARE 4 MORE DOUBLE-WORDS + MOV NPKSAB-CHXCHS(D),(B)+ + MOV HPKSAB-CHXCHS(D),(B)+ + CLR (B)+ + CLR (B)+ + MOV NPKSGB-CHXCHS(D),(B)+ + MOV HPKSGB-CHXCHS(D),(B)+ + MOV NPKSRL-CHXCHS(D),(B)+ + MOV HPKSRL-CHXCHS(D),(B)+ + BR 59$ +.ENDC ;ETHERP +55$: CMP CHIRFL(D),#CHSRFL ;CHAOSNET CABLE? + BNE 59$ ;NO, THAT'S ALL + MOV #16.,-10.(B) ;YES, THERE ARE 6 MORE DOUBLE-WORDS + MOV NPKSAB-CHXCHS(D),(B)+ + MOV HPKSAB-CHXCHS(D),(B)+ + MOV NPKSLS-CHXCHS(D),(B)+ + MOV HPKSLS-CHXCHS(D),(B)+ + MOV NPKSGB-CHXCHS(D),(B)+ + MOV HPKSGB-CHXCHS(D),(B)+ + MOV NPKSRL-CHXCHS(D),(B)+ + MOV HPKSRL-CHXCHS(D),(B)+ + CLR (B)+ ;I DON'T KEEP TRACK OF BIT COUNT ERRS SEPARATELY + CLR (B)+ + MOV NPKSBD(D),(B)+ + MOV HPKSBD(D),(B)+ +59$: TST (D)+ + CMP D,#2*NCHX + BLO 50$ +RETANS: MOVB #%COANS,PKOP(A) ;RETURN THIS PACKET TO SOURCE AS AN 'ANS' + RET ;NOTE CONDITION CODES HAVE 'NE' + +PLSSRV: MOVB PKNBYT(A),C ;GET BYTE COUNT, SHOULD BE SMALL + CMP C,#8 ;6 FOR PULSAR, 1 FOR SPACE, 1 FOR CHARACTER + BLO 20$ ;NOT GIVEN AN ARGUMENT, JUST READ STATUS + MOVB PKDAT+7(A),C ;YES, GET THE ARGUMENT + SUB #'0,C ;CONVERT TO BINARY (CHEAPO!) + MOV C,PULSON ;CHANGE PULSON STATUS +20$: MOV #1,PKNBYT(A) ;SET BYTE LENGTH, CLEAR FORWARDING COUNT + MOV PULSON,C ;RETURN PULSAR STATUS + ADD #'0,C ;IN ASCII + MOVB C,PKDAT(A) + BR RETANS + + .SBTTL CHAOSNET INTERRUPT HANDLER + +;INTERRUPT HANDLER ENTRIES +.REPT CHAOSP +CONC CHS,\.RPCNT,BK: + JSR I,CHSBRK + CHXCHS+<.RPCNT*2> +.ENDR + +;SUBROUTINE TO ENABLE CHAOSNET INTERFACE IN H,I TO RECEIVE NEXT PACKET +CHINXT: MOVB 1(H),A ;GET CSR BITS 9-12 (LOST COUNT) + ASR A + BIC #-20,A + ADD A,NPKSLS-CHXCHS(I) + ADC HPKSLS-CHXCHS(I) + BIS #%CARCL+%CAREN,(H) ;MAKE READY TO RECEIVE ANOTHER MESSAGE + RET + +;COMMON CHAOS INTERRUPT ROUTINE +CHSBRK: MOV (I),I ;GET SOURCE/SINK INDEX + PUSH ;SAVE ALL REGISTERS + MOV CHIHWR(I),H ;GET HARDWARE ADDRESS + MOV (H),A .SEE CH%CSR ;GET CSR + BPL CHSBK1 ;TEST RECEIVE DONE, BRANCH IF NOT + .SEE %CARDN ;PALX SCREWS UP IF THIS IS ON PREVIOUS LINE! + TST CHISTS(I) ;MAKE SURE INPUT BUFFER IS IDLE + BNE CHSBK1 ;BUSY, DON'T LOOK AT RECEIVE DONE NOW + BIT #%CAERR,A ;CRC ERROR? + BNE CHICRC ;JUMP IF YES + MOV CH%RBC(H),C ;BIT COUNT -1 + SUB #47.,C ;ADD 1, THEN SUBTRACT 3*16. FOR HARDWARE WORDS + .IREPT 4, ASR C ;CONVERT TO NUMBER OF WORDS + CMP C,#256. + BHI CHIFLS ;THIS CAN ONLY HAPPEN IF HARDWARE BROKEN + ADD #CH%RBF,H ;POINT H TO RECEIVE DATA REG + MOV CHIBFP(I),D ;COPY PACKET INTO BUFFER + CALL MOVHD + TST (H) ;READ OUT THE 3 HARDWARE LEADER WORDS + CMP (H),(H) + SUB #CH%RBF,H ;RESTORE H + BIT #%CAERR,(H) ;WAS IT READ CORRECTLY OUT OF RAM? + BNE CHIGBG ;NO, GARBAGE + CMP CH%RBC(H),#7777 ;WAS PACKET CORRECT LENGTH? + BNE CHIGBG ;NO, GARBAGE + CALL CHINXT ;DONE WITH HARDWARE, ENABLE FOR NEXT + CALL CHSIHD ;PROCESS HEADER, GET LENGTH, DEST + BVS CHIFL0 ;BRANCH IF NO GOOD + CALL SWAB11 ;SWAB IF NOT GOING TO 11-COMPATIBLE DEST + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + PUSH I + CALL CHSOUT ;SEND IT OUT + POP I + MOV CHIHWR(I),H ;RESTORE H + TST CHISTS(I) ;INPUT BUFFER STILL BUSY? + BEQ CHSBK1 + BIC #%CAREN,(H) ;YES, CLEAR RECEIVE INTERRUPT ENABLE + BR CHSBK1 ;GO CHECK ON OUTPUT SIDE + +;HERE WHEN A PACKET WAS RECEIVED WITHOUT ERROR, BUT AFTER +;READING OUT OF THE RAM, CRC ERROR WAS SET. EITHER THE +;PACKET WAS THE WRONG LENGTH, OR THE RAM FAILED, OR THE +;HARDWARE RANDOMLY CLOBBERED IT. +;WE ALSO GET HERE IF THE BIT COUNT WAS NOT -1 AFTER ALL WORDS WERE READ. +CHIGBG: ADD #1,NPKSRL-CHXCHS(I) ;LOG THE ERROR + ADC HPKSRL-CHXCHS(I) + MOV H,CHSRLH + MOV CH%RBC(H),CHSRLC + BR CHIFLS ;GO RESET RECEIVER AND CHECK OUTPUT STATUS + +;HERE WHEN A PACKET IS RECEIVED WITH A CRC ERROR. DISCARD IT, +;BUT ALSO SAVE IT IN CHSGBF, CHSGBH, CHSGBS, CHSGBC FOR DEBUGGING (IF FTGARB). +CHICRC: ADD #1,NPKSGB-CHXCHS(I) + ADC HPKSGB-CHXCHS(I) +.IFNZ FTGARB + MOV H,CHSGBH + MOV (H),CHSGBS + MOV CH%RBC(H),CHSGBC + ADD #CH%RBF,H + MOV #CHSGBF,D + MOV #PKMAX,C + CALL MOVHD + SUB #CH%RBF,H ;DROP INTO CHIFLS +.ENDC ;FTGARB +;HERE TO IGNORE AN INPUT PACKET AND ENABLE HARDWARE FOR NEXT +CHIFLS: CALL CHINXT +CHIFL0: INC NPKSIG +;HERE TO CHECK ON TRANSMIT SIDE +CHSBK1: TSTB (H) .SEE %CATDN ;TRANSMIT DONE? + BPL CHSBKX ;NO, EXIT +.IFNZ CHSBTB + CLR CHSIDL(I) ;CLEAR TRANSMIT-DONE TIME-OUT +.ENDC ;CHSBTB + MOV CHOSTS(I),A ;WAS OUTPUT IN PROGRESS? + BEQ CHSBK6 ;NO, LOOK FOR OUTPUT + CMP A,#2 ;TRANSMIT ABORT DELAY COMPLETED? + BEQ 10$ + BIT #%CATAB,(H) ;NO, TRANSMIT ABORTED? + BEQ CHSBK4 ;NO + ADD #1,NPKSAB-CHXCHS(I) ;YES, METER IT, AND SET CHOSTS TO + ADC HPKSAB-CHXCHS(I) + INC CHOSTS(I) ;2 IF THIS IS FIRST TIME, OR 0 IF SECOND TIME + BEQ CHSBK4 ;LOST TWICE IN A ROW, GIVE UP + BR CHSBK5 ;TURN OFF INTERRUPT, DELAY FOR A WHILE + +10$: MOV #-1,CHOSTS(I) ;TRANSMIT ABORT DELAY COMPLETED, SET CHOSTS TO -1 + CALL CHSXM0 ;INITIATE RE-TRANSMISSION (CHOSTS ALREADY SET) + BR CHSBKX ;DISMISS + +CHSBK4: CALL CHSODN ;OUTPUT DONE +CHSBK6: PUSH I + CALL CHSRUN ;INITIATE MORE TRANSFERS + POP I + TST CHOSTS(I) ;DID IT INITIATE TRANSMISSION? + BNE CHSBKX ;YES, LEAVE INTERRUPT ENABLED. + MOV CHOHWR(I),H ;RESTORE H + TST CHXRTF(I) ;TIME TO BROADCAST ROUTING INFO? + BNE CHORUT ;YES + TST PULSON ;IS THIS FEATURE TURNED ON? + BEQ CHSBK5 ;NO, FLUSH + CMP PULSAR,PULSON ;NOTHING TO DO. TIME FOR A TEST MESSAGE? + BNE CHSBK5 ;NOPE, GO IDLE + MOV #52525,CH%WBF(H) ;WRITE A PACKET OF 3 HEADER WORDS, 0, 52525 + CLR CH%WBF(H) + MOV #-1,CH%WBF(H) ;TO HOST -1, WHICH IS NON-EXISTENT +CHSBK7: TST CH%XMT(H) ;INITIATE TRANSMISSION, DON'T ENABLE INTERRUPT +CHSBK5: BIC #%CATEN,(H) ;GO IDLE, CLEAR TRANSMIT INTERRUPT ENABLE +;HERE TO EXIT FROM CHAOS INTERRUPT. RESTORE REGS AND RETURN FROM INT +CHSBKX: POP + RTI + +.IIF NZ CH%WBF-CH%MYN, .ERR FOO CODE ASSUMES CH%WBF = CH%MYN + +;BROADCAST A PACKET FULL OF ROUTING INFO, SINCE WE ARE MORE OR LESS A GATEWAY +CHORUT: MASK 6 ;INHIBIT CLOCK INTERRUPTS SO COSTS DON'T CHANGE + ADD #CH%WBF,H ;ADDRESS WRITE BUFFER + MOV #%CORUT*400,(H) ;OPCODE + MOV #2*,A ;COUNT SUBNETS WHICH WE KNOW ANYTHING ABOUT (REASONABLE COST) + CLR B +5$: CMP SBNCST(A),#1000 + BHIS 6$ + ADD #4,B ;THIS ONE WILL GENERATE 2 WORDS +6$: SUB #2,A + BPL 5$ + MOV B,(H) ;BYTE COUNT + CLR (H) ;DESTINATION + CLR (H) ;.. + MOV (H),(H) ;SOURCE = CH%MYN + CLR (H) ;SOURCE INDEX + CLR (H) ;PACKET NUMBER + CLR (H) ;ACK NUMBER + MOV #2*,A ;GO THROUGH SUBNET TABLES + MOVB 1(H),C ;GET SUBNET THIS IS GOING OUT ON + ASL C + MOV SBNCST(C),C ;GET COST OF GETTING TO US FROM GUY WHO RECEIVES THIS +10$: CMP SBNCST(A),#1000 ;WAS THIS ONE INCLUDED IN BYTE COUNT? + BHIS 11$ ;NO, DON'T PUT IT IN PACKET + MOV A,B ;FIRST WORD IS SUBNET NUMBER + ASR B + MOV B,(H) + MOV SBNCST(A),B ;SECOND WORD IS COST + ADD C,B ;WHICH MUST INCLUDE COST OF GETTING TO US + MOV B,(H) +11$: SUB #2,A ;NEXT SUBNET + BPL 10$ + CLR (H) ;BROADCAST THIS PACKET + SUB #CH%WBF,H ;RESTORE H + CLR CHXRTF(I) ;CLEAR REQUEST FOR ROUTING PACKET + UNMASK + BR CHSBK7 ;FIRE IT OFF, DON'T ENABLE TRANSMIT-DONE INTERRUPT + +;INITIATE TRANSMISSION ON CHAOS INTERFACE +;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED. BASHES ALL REGS. +CHSXMT: INC CHOSTS(I) ;SET CHOSTS TO 1, TRANSMIT STARTING +CHSXM0: MOV CHOHWR(I),H ;GET HARDWARE ADDRESS + MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),D ;GET PACKET ADDRESS + ADD #CH%WBF,H ;ADDRESS THE WRITE BUFFER + MOV CHILNG(B),C ;GET WORD COUNT + CALL MOVDH ;COPY INTO HARDWARE + MOV CHICBA(B),(H) ;STORE CABLE DESTINATION + SUB #CH%WBF,H ;RESTORE H + TST CH%XMT(H) ;TRIGGER TRANSMISSION + BIS #%CATEN,(H) ;ENABLE DONE INTERRUPT + RET ;PI LEVEL WILL PICK UP OUTPUT + +.ENDC ;CHAOSP + +.IFNZ ETHERP + .SBTTL ETHERNET SUPPORT + +;ENABLE NEXT ETHERNET PACKET TO COME IN. +;SINCE WE ONLY HAVE ONE BUFFER, THIS SETS UP THE TRANSFER RATHER +;THAN JUST ENABLING THE INTERRUPT AS THE CHAOSNET DOES. +;THAT WOULDN'T WORK ANYWAY, BECAUSE THE HARDWARE IS SO TOTALLY BRAIN-DAMAGED. +ETHRFL: MOV CHIHWR(I),H + ADD #10,H + MOV #-,(H)+ ;- WORD COUNT, +1 FOR HARDWARE BUG + MOV #ETHIBF+,(H)+ ;BUFFER ADDRESS + MOV #101,(H) ;START, INTERRUPT-ENABLE + RET + +;INCOMING PUP TOO BIG. WE DON'T HAVE FRAGMENTATION, SO SEND A PUP ERROR REPORT +ETHBIG: MOV #ETHIBF+PKDAT,A ;COPY PUP HEADER INTO DATA FIELD + MOV A,C + MOV #ETHIBF+PKDAT+20.,B + .IREPT 10.,< MOV (A)+,(B)+ > + MOV #517.,(B)+ ;PACKET TOO LARGE ERROR + MOV #DATMAX,(B)+ ;MAX NUMBER OF BYTES ALLOWED + MOV #50$,A +5$: MOVB (A)+,(B)+ ;ASCII MESSAGE + BNE 5$ + INC B ;MESSAGE LENGTH IS EVEN. INCLUDE CHECKSUM IN COUNT. + SUB #ETHIBF+PKDAT,B ;GET PUP LENGTH + MOV B,(C)+ ;BUILD PUP HEADER NOW + MOV #4,(C)+ ;PUP TYPE = ERROR + CMP (C)+,(C)+ ;PUP ID SAME + .IREPT 3,< MOV 6(C),(C)+ > ;DESTINATION = ORIGINAL SOURCE + MOV #,(C)+ ;SOURCE = ME + .IREPT 2,< CLR (C)+ > ;SOURCE PORT ZERO + CALL ETHOUT ;TRANSMIT + JMP ETHINX ;DISMISS + +;The ascii message. This isn't as destroyed as it looks. +50$: .ASCIZ/UP Pot oalgr eotf tii n ahCoanstep caek.t/ + .EVEN + +;INPUT INTERRUPT +ETHIBK: PUSH + MOV #CHXETH,I + MOV CHIHWR(I),H + MOV 14(H),A ;PICK UP STATUS + CLR 14(H) ;CLEAR RECEIVE INTERRUPT ENABLE + CMP ETHIBF+PKDAT-2,#1000 ;TYPE = PUP? + BNE ETHIIX ;NO, IGNORE PACKET + TST 10(H) ;CHECK RESIDUAL WORD COUNT + BEQ ETHBIG ;PACKET TOO BIG, RESPOND WITH PUP ERROR + TST A ;CHECK COMBINED INPUT ERRORS BIT + BMI 70$ ;ERROR, IGNORE PACKET + MOV ETHIBF+PKDAT+10,A ;GET DESTINATION HOST + BEQ 5$ ;AND SEE IF BROADCAST OR SELF + CMP A,# + BNE 11$ ;NO, ROUTE AS REGULAR MESSAGE +5$: CMPB ETHIBF+PKDAT+2,#1 ;PUP TYPE = ECHO-ME? + BEQ ETHECO ;YES, ECHO IT (MAYBE TAKE THIS OUT AFTER 11 DEBUGGED) + CMPB ETHIBF+PKDAT+2,#200 ;GATEWAY INFORMATION REQUEST? + BNE 10$ + TST ETHIBF+PKDAT+12 ;NOT REALLY UNLESS DESTINATION SOCKET IS 2 + BNE 10$ + CMP ETHIBF+PKDAT+14,#2 + BNE 10$ + TST CHISTS+CHXEGT ;PSEUDO DEVICE AVAILABLE? + BNE ETHIIX + MOV #ETHIBF+PKDAT+4,A ;YES, SEND HIM SOME INFO + MOV #EGTPID,B + .IREPT 2,< MOV (A)+,(B)+ > ;COPY PUP ID + ADD #6,A ;COPY SOURCE HOST AND SOCKET INTO DESTINATION + .IREPT 3,< MOV (A)+,(B)+ > + CALL ETHRT1 + MOV #CHXETH,I ;I CLOBBERED BY ETHRT1 + BR ETHIIX + +10$: TST A ;DON'T HARASS REST OF NET WITH BROADCASTS + BEQ ETHIIX +11$: MOV #ETHIBF+PKDAT,A ;CHECK THE CHECKSUM + CALL PUPCKT + BNE 60$ ;BAD, COUNT AS RAM ERROR +.IF DF NDVRBF + CMP ETHIBF+PKDAT+10,DVRHST ;SEE IF ADDRESSED TO DOVER USER + BNE 12$ + CMP ETHIBF+PKDAT+14,DVRIDX + BNE 12$ + CALL DVRPUP ;YES, PROCESS + MOV #CHXETH,I + BR ETHIIX + +.ENDC ;NDVRBF +;TRANSLATE PUP AND SEND TO CHAOSNET +12$: MOV #ETHIBF,A ;FILL IN CHAOSNET HEADER + MOV #<%COUNC*400>,(A)+ ;PKOP + MOV ETHIBF+PKDAT+0,B ;PKNBYT (TOTAL PUP LENGTH = CHAOS DATA LENGTH) + INC B ;ROUND UP TO AN EVEN NUMBER + ASR B + ASL B + MOV B,(A)+ + MOV ETHIBF+PKDAT+10,(A)+ ;PKDHST + MOV ETHIBF+PKDAT+14,(A)+ ;PKDIND (LOW HALF OF PUP PORT) + MOV ETHIBF+PKDAT+16,(A)+ ;PKSHST + MOV ETHIBF+PKDAT+22,(A)+ ;PKDIND (LOW HALF OF PUP PORT) + MOV ETHIBF+PKDAT+6,(A)+ ;PKPKN (LOW HALF OF PUP ID) + MOV #100001,(A)+ ;PKACN = PROTOCOL NUMBER + CALL CHSIHD ;PROCESS THIS HEADER, GET LENGTH, DEST + BVS ETHIIX ;IGNORE IF NO GOOD + CALL SWAB10 ;SWAB IF NOT GOING TO 10-COMPATIBLE DEST + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + CALL CHSOUT ;SEND IT OUT + BR ETHINX ;ETHRFL WILL BE CALLED WHEN NECESSARY + +60$: ADD #1,NPKSRL-CHXCHS(I) ;COUNT ERRORS (SOFTWARE CHECKSUM) + ADC HPKSRL-CHXCHS(I) + BR ETHIIX + +70$: ADD #1,NPKSGB-CHXCHS(I) ;COUNT ERRORS (HARDWARE CHECKSUM) + ADC HPKSGB-CHXCHS(I) +ETHIIX: CALL ETHRFL ;AND READ ANOTHER PACKET +ETHINX: POP + RTI + +;ETHERNET PUP ECHO PROTOCOL +ETHECO: MOV #ETHIBF+PKDAT+10,A ;INTERCHANGE SOURCE AND DESTINATION + MOV A,B ;I DON'T BOTHER CHECKING CHECKSUM, BUT I DO GENERATE IT + .IREPT 3, PUSH (A)+ + .IREPT 3,< MOV (A)+,(B)+ > + .IREPT 3, POP -(A) + MOV #,(A) ;FIX SOURCE TO BE ME + INCB ETHIBF+PKDAT+2 ;SET PUP TYPE = 2 (I AM AN ECHO) + CALL ETHOUT ;SEND BACK OUT ON THE ETHERNET + BR ETHINX + +;GENERAL PURPOSE ROUTINE FOR TRANSMITTING INTERNALLY-GENERATED PUPS TO +;THE ETHERNET. FIXES THE DESTINATION ADDRESS (THIS IS HOW OTHER +;HOSTS FIGURE OUT WHAT SUBNET THEY ARE ON!), COMPUTES THE PUP CHECKSUM, +;AND INTERFACES TO THE PACKET SWITCH. CALLED WITH SOURCE INDEX IN I. +;CALL THIS WITH A PACKET THAT ALREADY HAS ITS BYTES IN ETHERNET ORDER. +;BASHES ALL REGISTERS. +ETHOUT: MOV CHIBFP(I),A + ADD #PKDAT,A ;ADDRESS OF PUP + TST 10(A) ;ONLY IF NOT BROADCASTING, + BEQ 10$ + TSTB 11(A) ;DESTINATION ADDRESS HAVE NETWORK NUMBER? + BNE 10$ + MOVB #ETHSBN,11(A) ;NO, PUT IT IN +10$: CALL PUPCKS ;INSERT CHECKSUM + MOV #CHXETH,B + MOV B,CHIOUX(I) + INC CHISTS(I) + JMP CHSOUT + +;INITIATE TRANSMISSION ON ETHER INTERFACE +;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED. BASHES ALL REGS. +;PACKET IS ALREADY SWABBED INTO ETHERNET BYTE ORDER (REVERSE OF CHAOSNET). +ETHXMT: INC CHOSTS(I) ;SET CHOSTS TO 1, TRANSMIT STARTING + CLR A ;NO OUTPUT START DELAY +ETHXM0: MOV CHOHWR(I),H ;GET HARDWARE ADDRESS + MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),D ;GET PACKET ADDRESS + ADD #PKDAT,D ;GET PUP ADDRESS + MOV #1000,-(D) ;SMASH LAST 2 WORDS OF CHAOS HEADER. TYPE=PUP + MOV #ETHHSN,-(D) ;STORE SOURCE ADDRESS + MOVB 14(D),1(D) ;STORE DESTINATION ADDRESS + MOV 4(D),B ;GET PUP SIZE IN BYTES + ADD #5,B ;CONVERT TO WORDS, ALLOW FOR ETHERNET HEADER + ASR B + NEG B ;HARDWARE WANTS IT NEGATIVE + MOV B,(H)+ ;OUTPUT WORD COUNT + MOV D,(H)+ ;OUTPUT BUFFER ADDRESS + MOV A,2(H) ;OUTPUT START DELAY + MOV #101,(H) ;START OUTPUT, ENABLE INTERRUPT + RET ;PI LEVEL WILL FINISH + +;OUTPUT DONE/ABORTED INTERRUPT +ETHOBK: PUSH + MOV #CHXETH,I + MOV CHOHWR(I),H + MOV 4(H),A ;PICK UP STATUS BEFORE WRITING IT + CLR 4(H) ;CLEAR INTERRUPT ENABLE + TST A ;CHECK FOR ERROR + BPL 10$ + ADD #1,NPKSAB-CHXCHS(I) + ADC HPKSAB-CHXCHS(I) + NEG CHOSTS(I) ;ERROR, ENTER RETRANSMIT MODE + BPL 10$ ;ALREADY RETRANSMITTED ONCE, PUNT + MOV #25.,A ;WAIT 1 MS (DON'T BOTHER BEING RANDOM) + CALL ETHXM0 ;START TRANSMISSION AGAIN + BR ETHINX ;AND EXIT + +10$: CALL CHSODN ;TRANSMISSION FINISHED + CALL CHSRUN ;FIND MORE WORK TO DO + BR ETHINX ;DISMISS + +;CHECKSUM PUP ADDRESSED BY A. BASHES A,B,C. +PUPCKS: CALL PUPCK1 ;COMPUTE CHECKSUM + MOV B,(A) ;STORE CHECKSUM + RET + +;RETURN 'EQ' IF CHECKSUM MATCHES +PUPCKT: CALL PUPCK1 ;COMPUTE CHECKSUM + CMP (A),#-1 ;PACKET CHECKSUMMED? + BEQ 5$ ;NO, ALWAYS MATCH + CMP B,(A) ;RETURN WITH CC SET FROM NEW AND OLD CKSMS +5$: RET + +;A POINTS AT PACKET, RETURN WITH A -> CHECKSUM AND CHECKSUM IN B. BASH C. +PUPCK1: MOV (A),C ;GET LENGTH + DEC C ;IN WORDS NOT COUNTING CHECKSUM + ASR C + CLR B ;BUILD CHECKSUM IN B +10$: ADD (A)+,B ;ONE'S COMPLEMENT ADD + ADC B + BPL 11$ ;TRANSFER SIGN BIT INTO CARRY + SEC +11$: ROL B ;AND LEFT CYCLE + SOB C,10$ + INC B ;GRONK MINUS ZERO + BEQ 15$ + DEC B +15$: RET + +;BROADCAST ETHERNET GATEWAY INFO +ETHRUT: MASK 5 ;ENTER SUITABLE LEVEL FOR HACKING NET + TST CHISTS+CHXEGT ;IS THE PSEUDO SOURCE THAT EMITS THE + BNE 99$ ; PACKET AVAILABLE? IF NOT, PUNT. + CLR CHXRTF+CHXETH ;CLEAR REQUEST FLAG + MOV #EGTPID,A + CLR (A)+ ;PUP ID ZERO + CLR (A)+ + CLR (A)+ ;BROADCAST DESTINATION + CLR (A)+ ;TO SOCKET 2 + MOV #2,(A)+ + CALL ETHRT1 ;BUILD AND SEND GATEWAY INFO +99$: UNMASK + RET + +BADSBP: .WORD BADSUB ;POINTER INTO BAD SUBNETS +BADSUB: ;SUBNETS THAT SHOULD NOT HAVE INFORMATION SENT + ;ABOUT. THIS LIST MUST BE IN INCREASING ORDER + ;AND MUST END IN 377. + .BYTE 004 ;AI CHAOS 11 pseudo subnet (only AI PDP-10 (RIP) is on this) + .BYTE 010 ;Tech Square LCSnet (unused) + .BYTE 011 ;Tech Square LCS asynchronous line net (IP) + .BYTE 012 ;Tech Square VII LCSnet (IP) + .BYTE 014 ;Symbolics: Los Angeles-Chatsworth land line + .BYTE 020 ;CHAOS MIT IN subnet (ask JNC) + .BYTE 027 ;Experimental asynchronous line net + .BYTE 030 ;Experimental radio broadcast net + .BYTE 040 ;Symbolics: Tech Square-Vassar St. microwave link + .BYTE 041 ;Symbolics: Cambridge-Palo Alto land line + .BYTE 042 ;Symbolics: Palo Alto-Chatsworth land line + .BYTE 047 ;Symbolics: Cambridge-Chatsworth land line + .BYTE 054 ;S-1: 10Mb Ethernet + .BYTE 055 ;S-1: Pronet ring + .BYTE 056 ;S-1: serial line subnet + .BYTE 057 ;S-1: serial line subnet + .BYTE 061 ;Symbolics: Cambridge-Cambridge land line + .BYTE 062 ;Symbolics: Cambridge-Washington land line + .BYTE 064 ;Symbolics: Cambridge-Houston land line + .BYTE 070 ;Symbolics: Chatsworth-Westwood land line + .BYTE 072 ;Atari: Cambridge-MIT land line + .BYTE 073 ;Atari: Cambridge-Sunnyvale land line + .REPT 8 + .BYTE 377 ;SPARES + .ENDR + .BYTE 377 +.EVEN + +ETHRT1: MOV #BADSUB,BADSBP ;INITIAL BAD SUBNET POINTER + MOV #EGTSBN,A ;FILL IN GATEWAY INFORMATION IN THE PUP + CLR I ;I SUBNET*2, A EGTSBN POINTER +10$: ;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST + CLR B ;FOR NON-GATEWAY, USE 0 AS GATEWAY ADDRESS + TST SBNTYP(I) ;HARDWARE CONNECTION? + BGT 11$ + MOV SBNADR(I),B ;NO, GET GATEWAY ADDRESS +11$: cmpb i,#60 + bhi 20$ ;dover, as of 1-Dec-83 can't handle more than 60 + ;; FILTER OUT KNOWN BAD SUBNETS + CMPB I,@BADSBP ;MAYBE UPDATE POINTER + BHI 115$ ; NO UPDATE NEEDED + INC BADSBP +115$: CMPB I,@BADSBP ;THIS TIME, CHECK FOR EQUALITY + BEQ 20$ ;PUNT + ;; END FILTER + MOV SBNCST(I),C ;GET COST + CMP C,#1000 ;IF NOT REACHABLE, DON'T PUT IN PACKET + BHIS 20$ + .IREPT 3, ASR C ;DIVIDE BY 8 TO GET APPROXIMATE HOP COUNT + CMP C,#ETHMXH ;DON'T PUT MORE THAN MAXHOPS + BLOS 12$ + MOV #ETHMXH,C +12$: MOV I,D ;GET TARGET-NET + ASR D + SWAB B + MOVB B,(A)+ ;STORE IN WIERD XEROX BYTE ORDER + MOVB D,(A)+ + MOV B,(A)+ + MOVB C,-2(A) +20$: TST (I)+ ;NEXT SUBNET + CMP I,#NSUBNT*2 + BLO 10$ + SUB #EGTSBN,A ;NUMBER OF DATA BYTES IN PUP + ADD #22.,A ;FOR HEADER AND CHECKSUM + MOV A,EGTPLN ;SET PUP LENGTH + MOV #CHXEGT,I ;SET UP TO TRANSMIT TO ETHERNET + JMP ETHOUT +.ENDC ;ETHERP + +.IF DF NDVRBF + .SBTTL DOVER PROTOCOL TRANSLATOR + +;RFC PACKET IN A. MUST PRESERVE I, AND RETURN 'EQ'. +DVROPN: MOV PKPKN(A),C + MOV PKSIND(A),B + MOV PKSHST(A),A + PUSH I + CALL 5$ + POP I + SEZ + RET + +;SET UP DOVER TO TALK TO HOST IN A, INDEX IN B, PKT# IN C, SENDING BACK AN OPN +;OR SENDING A LOS IF BUSY. MUST WATCH FOR DUPLICATE RFC'S +;MUST BE CALLED WITH CHAOS AND ETHER INTERRUPTS MASKED +5$: TST DVRHST ;BUSY? + BEQ 10$ ;NO + CMP A,DVRHST + BNE DVRBSY ;YES, TALKING TO ANOTHER HOST + CMP B,DVRIDX + BNE DVRBSY ;YES, TALKING TO ANOTHER GUY SAME HOST + BR 11$ ;DUPLICATE RFC + +10$: CLR DVRTIM ;FLUSH TIMEOUT + MOV A,DVRHST + MOV B,DVRIDX + INC DVRLIX ;ESTABLISH UNIQUE LOCAL INDEX + BNE 11$ + INC DVRLIX ;DON'T USE 0 +11$: CLR DVRMSK ;CLEAR THE BUFFER RING + CLR DVRID ;FIRST PACKET TO SEND TO DOVER IS PACKET 0 + INC C ;C := FIRST PACKET ID THAT WILL COME IN FROM CHAOS + MOV C,DVROFS + MOV #%COOPN*400,B ;SEND AN OPN + BR DVRST1 ;REST IS LIKE STS + +DVRBSY: TST DVRPKP ;SPECIAL BUFFER BUSY? + BNE CPOPJ0 ;YES, PUNT + MOV #DVRBF2,C ;SEND A CLS + MOV #%COCLS*400,(C)+ + MOV #4,(C)+ + MOV A,(C)+ + MOV B,(C)+ + MOV #CHADD,(C)+ + CLR (C)+ + CLR (C)+ + CLR (C)+ + MOV #"BU,(C)+ + MOV #"SY,(C)+ + MOV #DVRBF2,DVRPKP + BR DVRRFL + +;HERE TO SEND STS TO GUY CONNECTED TO DOVER +;MUST BE MASKED AGAINST CHAOS INTERRUPTS +DVRSTS: MOV #%COSTS*400,B +DVRST1: MOV #DVRBF2,A ;USE THIS BUFFER + MOV #4,D ;NUMBER OF BYTES +DVRST2: MOV A,C + MOV B,(A)+ ;OPCODE + MOV D,(A)+ ;NUMBER OF BYTES + MOV DVRHST,(A)+ ;DESTINATION HOST + MOV DVRIDX,(A)+ ;DESTINATION INDEX + MOV #CHADD,(A)+ ;SOURCE HOST + MOV DVRLIX,(A)+ ;SOURCE INDEX + CLR (A)+ ;NO PACKET NUMBER + CMP B,#%COLOS*400 ;IF SENDING LOS, PUNT THE REST + BEQ 20$ + MOV DVRID,B + DEC B ;LAST PACKET ACKNOWLEDGED BY DOVER + ADD DVROFS,B ;CONVERT TO CHAOSNET ID + MOV B,(A)+ ;ACKNOWLEDGE PACKET NUMBER + MOV B,(A)+ ;RECEIPT + MOV #NDVRBF,(A)+ ;WINDOW SIZE +20$: MOV C,DVRPKP ;CAUSE PACKET TO GET SENT + ;DROP INTO DVRRFL + +;HERE TO GET ANOTHER PACKET FROM THE DOVER. THIS CAN BE EITHER A CHAOSNET +;PACKET TO BE SENT BACK TO THE APPROPRIATE GUY, OR A PUP TO GO TO THE DOVER +DVRRFL: MOV #CHXDVR,I ;THIS MIGHT NOT BE SET UP WHEN CALLED + TST CHISTS(I) ;PACKET SOURCE ONLY EMANATES ONE AT A TIME + BNE CPOPJ0 + CMP CHIBFP(I),DVRPKP ;FINISHED SENDING SPECIAL PACKET? + BNE 10$ + CLR DVRPKP ;YES, MAKE READY FOR ANOTHER +10$: CLR CHIBFP(I) ;THIS PACKET NO LONGER BEING SENT + MOV DVRPKP,A ;GOT SPECIAL PACKET TO SEND? + BNE 30$ ;YES, SEND IT + TST DVRMSK ;GOT NEXT BUFFER TO SEND TO DOVER? + BPL CPOPJ0 ;NO + CMP DVRRTR,#60. ;1-SECOND RETRANSMISSION INTERVAL ELAPSED? + BLO CPOPJ0 ;NO, DON'T SEND YET + CLR DVRRTR ;SENDING, RESET RETRANSMISSION TIMER + MOV DVRBFP,A + BIC #PKFCMS,PKFC(A) ;CLEAR FORWARDING COUNT SINCE SENDING AGAIN +30$: MOV A,CHIBFP(I) ;SEND THIS PACKET + CALL CHSIHD ;ROUTE HIM + BVS DVRRFL ;BAD, IGNORE + CMP B,#CHXCHS ;SWAB IF SENDING TO 10, BUT NOT ETHERNET + BHIS 35$ + CALL CHSSWB +35$: INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + RET + +;CALLED WITH A PUP IN ETHIBF WHICH IS FROM THE DOVER AND ADDRESSED +;TO THE GUY WHO'S TRYING TO PRINT ON IT. MUST BE MASKED AGAINST ETHER & CHAOS INTERRUPTS. +DVRPUP: MOVB ETHIBF+PKDAT+2,B + CMP B,#31 ;EFTP ACKNOWLEDGE? + BNE DVRPP1 + CMP ETHIBF+PKDAT+6,DVRID ;ACKNOWLEDGING EXPECTED PACKET? + BNE CPOPJ0 ;NO, IGNORE IT + INC DVRID ;YES, ADVANCE ID, POINTER, AND PACKET-PRESENCE MASK + MOV DVRBFP,A + ADD #DVRBFL,A + CMP A,#DVRBF2 + BLO 11$ + MOV #DVRBUF,A +11$: MOV A,DVRBFP + ASL DVRMSK + SETOM DVRRTR ;FAKE RETRANSMIT TIMER TO SEND NEXT PUP RIGHT AWAY + TST CHISTS+CHXDVR ;PACKET SOURCE BUSY? + BEQ DVRSTS ;NO, SEND AN ACKNOWLEDGEMENT TO THE CHAOSNET +CPOPJ0: RET + +DVRPP1: MOV #22.,A ;RELATIVE ADDRESS OF ASCII STRING + CMP B,#33 ;EFTP ABORT? + BEQ DVRERR + MOV #44.,A ;RELATIVE ADDRESS OF ASCII STRING + CMP B,#4 ;PUP ERROR? + BNE CPOPJ0 ;IGNORE ANYTHING ELSE +DVRERR: CLR DVRMSK ;DON'T SEND ANYTHING MORE TO THE DOVER + MOV ETHIBF+PKDAT,C ;PUP LENGTH + SUB A,C + SUB #2,C ;GET LENGTH OF ASCII STRING + ADD #ETHIBF+PKDAT,A ;GET ADDRESS OF ASCII STRING + MOV #DVRBUF+PKDAT,B ;BUILD A LOS PACKET TO SEND BACK + MOV C,D ;SAVE BYTE LENGTH + INC C + ASR C ;WORD COUNT + BEQ 11$ +10$: MOV (A)+,(B) + SWAB (B)+ ;ALTO HAS BYTES IN THE WRONG ORDER + SOB C,10$ +11$: MOV #%COLOS*400,B ;SEND A LOS + MOV #DVRBUF,A + CALL DVRST2 + CLR DVRHST ;KILL CONNECTION + RET + +;HERE IS A PACKET DIRECTED TO THE DOVER. DO GOOD THINGS WITH IT. +;NOTE, IT HAS ALREADY BEEN SWABBED INTO ETHERNET BYTE ORDER. +DVRPKT: MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),A ;GET ADDRESS OF PACKET + CLR DVRTIM ;FOREIGN HOST IS NOT IDLE + MOVB PKOP(A),B ;DATA PACKET? + BMI 50$ ;YES + CMP B,#%COSNS + BNE 11$ + TST CHISTS+CHXDVR + BNE 90$ + CALL DVRSTS ;SNS => STS + BR 90$ + +11$: CMP B,#%COCLS + BEQ 12$ ;CLS OR LOS PUNTS THE CONNECTION + CMP B,#%COLOS + BNE 13$ +12$: CLR DVRHST + BR 90$ + +13$: CMP B,#%COEOF ;NOTE THAT EOF IS TREATED VERY MUCH LIKE DATA! + BNE 90$ ;IGNORE ANYTHING RANDOM +50$: MOV PKPKN(A),B ;GET ID OF DATA PACKET + SUB DVROFS,B + MOV DVRBFP,D ;FIND WHERE IN THE BUFFER IT GOES + MOV #100000,C ;AND GET MASK BIT FOR IT + SUB DVRID,B ;B := ID RELATIVE TO NEXT EXPECTED + BEQ 53$ + CMP B,#NDVRBF + BHIS 90$ ;IGNORE DUPLICATE OR NOT IN WINDOW +51$: ADD #DVRBFL,D + CMP D,#DVRBF2 + BLO 52$ + MOV #DVRBUF,D +52$: CLC + ROR C + SOB B,51$ +53$: BIT C,DVRMSK ;ALREADY HAVE PACKET? + BNE 90$ ;YES, IGNORE + BIS C,DVRMSK ;NO, STORE IT AWAY + MOV D,C + ADD #PKDAT,D ;BUILD PUP + MOV PKNBYT(A),B + BIC #PKNBMS,B + MOV B,(D) + ADD #22.,(D)+ ;PUP LENGTH + MOV #30,(D)+ ;PUP TYPE + TST (A) ;WAS THIS DATA OR EOF? + BMI 54$ ;DATA + SUB (PC),-2(D) ;EOF, SET PUP TYPE TO 32 +54$: CLR (D)+ ;PUP ID HIGH + MOV PKPKN(A),(D) ;PUP ID LOW + SUB DVROFS,(D)+ ; CORRECTED + MOV #DVRADR,(D)+ ;DESTINATION HOST + CLR (D)+ ;DESTINATION SOCKET HIGH + MOV #20,(D)+ ;DESTINATION SOCKET LOW + MOV DVRHST,(D)+ ;SOURCE HOST + CLR (D)+ ;SOURCE SOCKET HIGH + MOV DVRIDX,(D)+ ;SOURCE SOCKET LOW + ADD #PKDAT,A + INC B + ASR B ;NUMBER OF DATA WORDS +;*** TEMPORARY KLUDGE *** + PUSH ;PUSH B LAST!! +;*** END TEMPORARY KLUDGE *** + BEQ 56$ +55$: MOV (A)+,(D)+ ;MOVE THE DATA + SOB B,55$ +56$: MOV C,A + ADD #PKDAT,A + MOV #<%COUNC*400>,(C) ;PKOP + MOV 10(A),PKDHST(C) + MOV (A),PKNBYT(C) ;SHOULD BE ENOUGH TO GET IT ROUTED TO ETHERNET + CALL PUPCKS ;STORE APPROPRIATE CHECKSUM +;*** TEMPORARY KLUDGE *** + POP ;LOOK FOR SOME KIND OF MACHINE FAILURE + TST B + BEQ 79$ +70$: CMP (D)+,(A)+ + BNE 75$ + SOB B,70$ + BR 79$ + +75$: DVRFKT=. + NOP ;PUT A BPT HERE IF YOU LIKE + INC NDVRFK + CLR DVRMSK ;DO IT ALL OVER AGAIN +79$: +;*** END TEMPORARY KLUDGE *** + CALL DVRRFL ;SEND THIS PACKET MAYBE +90$: MOV #CHXDVR,I + JMP CHSODN ;THIS PACKET HANDLED +.ENDC ;NDVRBF + .IFNZ DL10P + .SBTTL TRAP HANDLING + +TRAP14: HALT ;BPT WITH NO RUG IN CORE + +TRAP10: BPT ;ILLEGAL INSTRUCTION + +TRAP4: NOP ;PATCH BPT HERE IF YOU WANT + CMP (SP),#MAIN ;IF TRAP4 IN MAIN LOOP... + BLO CRASH + CMP (SP),#MAINE + BHIS CRASH + BIT #DLXPRT,DLXCSR ;AND DL10 PORT TURNED OFF + BNE CRASH + TST DLXOFF ;AND WE THOUGHT IT WAS ON + BNE CRASH +RESTRT: MOV #STKBAS,SP ;THEN RESTART MAIN LOOP + CLR -(SP) ;WHICH WILL WAIT FOR DL10 PORT TO TURN ON + MOV #MAIN,-(SP) + RTI + +CRASH: BPT ;OTHERWISE, CRASH + +PWRFAL: RESET ;POWER FAIL OR UP - IF FAIL, HALT DURING RESET + MOV #20,B ;WAIT 2 SECONDS TO +1$: CLR A ; MAKE SURE POWER IS REALLY ON + SOB A,. + SOB B,1$ + JMP INIT ;POWER SEEMS UP, RESTART PROGRAM +.ENDC ;DL10P + +.IFNZ NODDT ;IF NO DDT OR OTHER "OPERATING SYSTEM", SET UP TRAP HANDLERS +TRAP4: + .=4 + .WORD TRAP4,340,TRAP10,340,TRAP14,340,TRAP10,340,PWRFAL,340,TRAP10,340,TRAP10,340 + .=TRAP4 + +;ILLEGAL ADDRESS, UNIBUS NXM, STACK OVERFLOW +TRAP4: BPT + 0 + +;ILLEGAL INSTRUCTION, IOT, EMT +TRAP10: BPT + 0 + +;POWER FAILURE OR RESTORE +PWRFAL: HALT + 0 + +;BPT (OR TRACE) +TRAP14: .REPT 7 ;SAVE REGISTERS WHERE CARPET CAN FIND THEM + MOV %0+.RPCNT,BPTACS+<.RPCNT*2> + .ENDR + CLR BPTGO + SETOM BPTFLG +5$: TST BPTGO + BEQ 5$ + CLR BPTFLG + .REPT 7 + MOV BPTACS+<.RPCNT*2>,%0+.RPCNT + .ENDR + RTI + +BPTFLG: 0 ;NON-ZERO IF GOT A BPT +BPTGO: 0 ;NON-ZERO TO PROCEED +BPTACS: .BLKW 7 ;REGS EXCEPT PC + +.ENDC ;NODDT + + .SBTTL INITIALIZATION +GO:: +INIT: CLR PS +.IFNZ DL10P + RESET + MOV #STKBAS,SP + TST 14 + BNE 1$ ;BPT ALREADY SET UP BY RUG + MOV #TRAP14,14 + MOV #340,16 +1$: +.ENDC ;DL10P +.IFNZ NODDT ;NO OPERATING SYSTEM + RESET + MOV #STKBAS,SP +.ENDC ;NODDT + SETOM DLXOFF ;REINITIALIZE VARIOUS VARIABLES + SETOM NO.ITS +.REPT CHAOSP ;IDLE CHAOS NET INTERFACES + CLR CHISTS+CHXCHS+<2*.RPCNT> + CLR CHOSTS+CHXCHS+<2*.RPCNT> +.ENDR +.IIF NZ T300P, CLR RQBACT +.IFNZ NCT + MOV #NFTTY,I +76$: MOV NRMIPC(I),TTYIPC(I) + ADD #2,I + CMP I,#LASTTY + BLE 76$ + MOV #TYORNG,B ;CLEAR THE TYPOUT-DONE RING + CALL CLRING + MOV #,A ;GIVE OUTPUT DONE ON ALL LINES +78$: CALL PUT + INC A + CMP A,#+NCT + BLO 78$ +.ENDC ;NCT +.IFNZ NDMS +;;; Turn on DM11-BBs + CLR B ;iterated over DM11 units + MOV #NDMS,H +5$: MOV #DMCLR+DMCSN,@DMCSR(B) ;CLEAR SCANNER MEMORY +2$: BIT #DMBSY,@DMCSR(B) + BNE 2$ + CLR I ;iterated over modem channels + ;; turn on connected modem channels for one DM11 + CLR A ;counter for channels per unit +3$: TST M2LMAP(I) + BEQ 4$ + MOV A,@DMCSR(B) + MOV #LINENB,@DMLSR(B) +4$: TST (I)+ + INC A + CMP A,#16. + BLT 3$ + TST (B)+ + SOB H,5$ ;next DM11 + ;; treat first-time interrupts differently + SETOM DMINI + CLR B + MOV #NDMS,A +6$: MOV #DMSCN+DMIEN,@DMCSR(B) ;enable scanner interrupts + TST (B)+ + SOB A,6$ ;on all DMs + MOV #20000.,A + SOB A,. ;DELAY 50 MILLISECONDS + CLR DMINI ;WHILE P.I. LEVEL GETS INITIAL STATUS +.ENDC ;NDMS + +.IFG NDHS +;TURN ON DH11'S + MOV #NLDHHX,H +DHINIL: MOV DHSCR(H),A ;DEVICE ADDRESS + MOV #100000,16(A) ;TURN ON SILO MAINTENANCE MODE, SUSPECTED OF + ;LOSING + MOV #4000,(A) ;RESET DH11 + MOV 16(A),B ;CHECK SILO STATUS + BIC #300,B ;THESE BITS ARE IN RAM & DON'T CLEAR + BEQ DHSWIN ;SHOULD HAVE CLEARED MAINTENANCE MODE AND OTHER CRUD +DHSLUZ: BPT ;LOSE +DHSWIN: MOV #DHRENB+DHTENB,(A) ;NOW ENABLE INTERRUPTS ON DH11 + SUB #2,H + BGE DHINIL +.ENDC ;NDHS + +;TURN ON DL11S +.IFG NDLS + MOV #NLDLHX,H + MOV #NDLS-1,A +21$: +.IIF NZ DTE20P, BEQ 22$ ;NO KBD INT ON KL10 CTY DUE TO KLDCP LOSSAGE + MOV #103,@DLKS(H) ;ACTIVATE KEYBOARD INTERRUPT, D.T.R., READER +22$: MOV #100,@DLPS(H) ;ACTIVATE PRINTER INTERRUPT + SUB #2,H + DEC A + BPL 21$ +.ENDC ;NDLS + +;SET LINE PARAMETERS AND ALLOCATE BUFFERS +.IFNZ NCT + MOV #NFTTY,I +10$: MOV LPRVAL(I),A + MOV BUFSIZ(I),B + CALL SPARAM + ADD #2,I + CMP I,#LASTTY + BLE 10$ +.ENDC ;NCT + +;TURN ON CLOCK +.IIF Z DTE20P, MOV #100,@#LKS ;NO CLOCK INTERRUPTS IF KLDCP IS HACKING CLOCK TOO + +.IFNZ DTE20P +;INITIALIZE DTE20 + MOV #37774,DLYCNT ;DMA TO BANK 0, 2 USEC DELAY + MOV #%D3BYT,DIAG3 ;DO TO10 TRANSFERS IN BYTE MODE + MOV #MAIN,SADR ;ONLY DO INIT ONCE +.ENDC ;DTE20P +.IIF NZ TEN11P, SETOM T11I10 ;CAUSE 10 TO REINITIALIZE TEN-11 CHAOS +.REPT CHAOSP + MOV CHIHWR+CHXCHS+<2*.RPCNT>,H ;ADDRESS THE INTERFACE + CONC ,\.RPCNT ;CHECK THE HOST NUMBER SWITCHES AGAINST THE PROGRAM + BEQ .+4 + BPT + BIS #%CAREN,(H) ;ENABLE CHAOS NET INPUT INT +.ENDR ;CHAOSP +.IFNZ ETHERP + MOV CHIHWR+CHXETH,H ;ADDRESS THE INTERFACE + MOV 16(H),A ;GET HOST NUMBER SWITCHES + COMB A ;FIX XEROX MISTAKE + CMPB A,#ETHHSN ;CHECK HOST NUMBER SWITCHES + BEQ .+4 + BPT + MOV #CHXETH,I ;ENABLE TO RECEIVE FIRST ETHERNET PACKET + CALL ETHRFL +.ENDC ;ETHERP +;GO + JMP MAIN + +.IFNZ GOULDP +.SBTTL GOULD PRINTER BUFFERS + +GLPOIP: GLPBFF ;NEXT BUFFER IN AT M.P. LEVEL +GLPOOP: GLPBFF ;NEXT BUFFER OUT AT P.I. LEVEL + + .REPT NGLPBF ;ASSEMBLE THE BUFFERS + 0 .SEE GB.STA + GLPBFF ;DUE TO PALX BUG, LEAVE .SEE ON NEXT LINE + .SEE GB.NXT +GLPBFF==.-4 + 0 .SEE GB.FF + 0 .SEE GB.NL + 0 .SEE GB.PNT + .BLKB GLPBSZ + .ENDR +.ENDC ;GOULDP + + .SBTTL "TTYTYP" PARAMETER FILE + +T LPRVAL: + .BLKW NCT ;DH11 PARAMETER REG + +BUFFRS: ;BEGIN ALLOCATING BUFFERS HERE + +.IIF NZ NCT, INFORM ,\BUFFRS +ZZ===+3777>/4000 ;NUMBER OF K USED +.IRP ZZZZ,<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16> +.LIF EQ ZZ-.IRPCNT ;THIS IS A CRETINOUS CROCK TO GET IT COME OUT IN DECIMAL +INFORM ,\BUFFRS+,< (>,ZZZZ, +.ENDR + +.IFNZ NCT ;TTYTYP FILE ONLY IF WE HAVE TTYS +.IF P2 ;SPEED UP THE ASSEMBLY +OFF==69105 ;KLUDGES SO I DON'T HAVE TO PUT KEYWORD PARAMETERS INTO PALX +40K==40000 +80K==80000 + +.MACRO SPEED BAUD +ZZ==-1 +.IIF EQ BAUD-OFF, ZZ==0 +.IIF EQ BAUD-50, ZZ==1 +.IIF EQ BAUD-75, ZZ==2 +.IIF EQ BAUD-110, ZZ==3 +.IIF EQ BAUD-134, ZZ==4 +.IIF EQ BAUD-150, ZZ==5 +.IIF EQ BAUD-200, ZZ==6 +.IIF EQ BAUD-300, ZZ==7 +.IIF EQ BAUD-600, ZZ==10 +.IIF EQ BAUD-1200, ZZ==11 +.IIF EQ BAUD-1800, ZZ==12 +.IIF EQ BAUD-2400, ZZ==13 +.IIF EQ BAUD-4800, ZZ==14 +.IIF EQ BAUD-9600, ZZ==15 +.IIF EQ BAUD-80K, ZZ==16 +.IIF EQ BAUD-40K, ZZ==17 +.IIF LT ZZ, .ERROR UNRECOGNIZED SPEED "BAUD" +.ENDM SPEED + +.MACRO IPARM N,ODFLT,IDFLT,MUMLST +.IF GE <2*N>-NFTTY +.IF LE <2*N>-LASTTY +%%.ISPEED==-1 +%%.SPEED==-1 +.IRP MUM, +.IF NB + ZZ==0 + .IRPC MUMB, + .IIF GE .IRPCNT-2, .MEXIT + .IIF IDN MUMB,S, .IIF EQ .IRPCNT, ZZ==1 + .IIF IDN MUMB,P, .IIF EQ .IRPCNT-1, ZZ==ZZ+1 + .IIF IDN MUMB,I, .IIF EQ .IRPCNT, ZZ==1 + .IIF IDN MUMB,S, .IIF EQ .IRPCNT-1, ZZ==ZZ+1 + .ENDM + .IIF EQ ZZ-2, %%.'MUM + .ENDC +.ENDM +.IF LT %%.ISPEED + .IIF LT %%.SPEED, %%.ISPEED==IDFLT + .IELSE %%.ISPEED==%%.SPEED +.ENDC +.IIF LT %%.SPEED, %%.SPEED==ODFLT +SPEED %%.ISPEED +IZZ==ZZ +SPEED %%.SPEED +; BUFFER SIZE IS 1/2 SECOND'S TYPING +; BUT WILL BE SUBJECT TO LIMIT OF MAXBSZ +.IIF LT ZZ-7, BZZ==5. +.IIF EQ ZZ-7, BZZ==15. +.IIF EQ ZZ-10, BZZ==30. +.IIF EQ ZZ-11, BZZ==60. +.IIF EQ ZZ-12, BZZ==90. +.IIF EQ ZZ-13, BZZ==120. +.IIF EQ ZZ-14, BZZ==240. +.IIF EQ ZZ-15, BZZ==480. +.IIF GT ZZ-15, BZZ==1000. +.=LPRVAL+<2*N> ;ASSEMBLE LINE PARAMETER WORD +.IIF NE ZZ-3, ++3 ;ISPEED, OSPEED, NO PARITY, 8 BITS, FULL DUPLEX +.IELSE ++3+4 ;110 BAUD EXTRA STOP BIT +.=BUFSIZ+<2*N> +BZZ ;ASSEMBLE BUFFER SIZE +.ENDC +.ENDC +.ENDM IPARM + +;MACROS USED IN THE TTYTYP FILE: + +.MACRO TTDPRT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,300,300, +.ENDM TTDPRT + +.MACRO TTDMRX TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,600,600, +.ENDM TTDMRX + +.MACRO TTDTRM TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,1200,1200, +.ENDM TTDTRM + +.MACRO TTDLPT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDLPT + +.MACRO TTDLA36 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,300,300, +.ENDM TTDLA36 + +.MACRO TTDIML TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,50K,25K, +.ENDM TTDIML + +.MACRO TTDVT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDVT + +.MACRO TTDTEK TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,1200,1200, +.ENDM TTDTEK + +.MACRO TTDLSR TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,2400,2400, +.ENDM TTDLSR + +.MACRO TTDDPT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,2400,2400, +.ENDM TTDDPT + +.MACRO TTDGT40 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,4800,4800, +.ENDM TTDGT40 + +.MACRO TTDRAY TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDRAY + +.MACRO TTDH19 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDRAY + +.MACRO TTD11 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,4800,4800, +.ENDM TTD11 + +.MACRO TTDRAN TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDRAN + +.MACRO TTDTV TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDTV + +.MACRO TTDGRN TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDGRN + +.MACRO TTDSTY TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDSTY + +.MACRO REPEAT N,FOO +FAKOUT: .REPT N +FAKOUT===0 +.ENDM + +NSTTYS==0 ;WE'RE NOT INTERESTED IN PSEUDO-TTYS +N11TYS==0 ;NOR IN PDP11 TVS + +.INSRT SYSTEM;TTYTYP > + +.EXPUNGE ZZ,IZZ,IZZZ,BZZ,OFF,40K,80K,%%.ISPEED,%%.SPEED +.EXPUNGE TT,TY,TO,TP,TCT,HOR,VER,ROL,SPEED,ISPEED + +.ENDC ;P2 + +.ENDC ;NCT + +.END INIT + \ No newline at end of file diff --git a/src/system/its.1644 b/src/system/its.1644 new file mode 100755 index 00000000..a9a0c458 --- /dev/null +++ b/src/system/its.1644 @@ -0,0 +1,21930 @@ +;-*-MIDAS-*- + +.SYMTAB 12003.,5500. +TITLE ITS + +SUBTTL DEFINITIONS + +.NSTGWD .SEE PATB ;NO STORAGE WORDS ALLOWED UNTIL PATB + +IF1 [ PRINTX \MACHINE NAME = \ +;WELL-KNOWN MACHINE NAMES ARE: +; AIKA AI LAB KA10 (R.I.P.) +; MLKA MATHLAB KA10 (R.I.P.) +; DM DYNAMIC MODELING KA10 (R.I.P.) +; MC Mail Computer KS10 +; AI AI Lab KS10 +; MX The ex-MC KL10 +; ML Math Lab KS10 +; MD Mostly Development KS10 +; SI Stacken ITS KS10 +; FU Australian KS10 +; PM PandaMonium KS10 +; DX DigeX KS10 +;THE FILE "CONFIG" HAS ASSEMBLY SWITCHES AS A FUNCTION OF MACHINE. + +.TTYMAC A +IFN ASCII/A/&ASCII/ /,.FATAL USE UPPER CASE! +DEFINE MCOND X ;0 IFF THIS IS MACHINE X. +,TERMIN +DEFINE MNAME X ;USED TO SUBSTITUTE IN THIS MACHINE'S NAME. +X!!A!!TERMIN +FOO==.TTYFLG ;MAKE ERR FILE LOOK NICE +.TTYFLG==1 +PRINTX/A +/ +.TTYFLG==FOO +TERMIN ];IF1 + +IFNDEF PCLSW,PCLSW==1 ;1 => ASSEMBLE PCLSR TEST FEATURE +IFNDEF TT11BY,TT11BY==8 ;PDP11-TV OUTPUT BUFFER BYTE SIZE. +.MLLIT==1 ;MULTI-LINE LITERAL MODE +ASTIME==.OP .OPER+@,0,.RTIME ;GET ASSEMBLY TIME AND DATE IN SIXBIT. +ASDATE==.OP .OPER+@,0,.RDATE ;RH OF INSN MUST BE 0, SO MIDAS WILL PUT IN PROPER AC FLD. + +;AC DEFS + +A=1 +B=2 +C=3 +D=4 +E=5 +TT=6 +I=7 +Q=10 +J=11 +R=12 +W=13 +H=14 +P=15 ;DO NOT CHANGE! ;PDL POINTER +T=16 ;" +U=17 ;" ;USER INDEX + +.XCREF A,B,C,D,E,TT,I,Q,J,R,W,H,P,T,U + +IF1 EXPUNGE APR,OCT,DEC ;FOR NEW CALENDAR HACK + +NULBLK==4 ;NUMBER OF LOCKED SWITCH BLKS IN USR VARIABLES + ;USES 2 WDS OF USER VAR PER + +NPVSEC==30. ;NUMBER OF SECONDS A USER IS ALLOWED TO BE IN THE PRIVILEDGED SWAPPING CLASS +IF2 LIOBLK==_-10. ;LOWEST BLOCK NEVER TO BE SHUFFLED + ;ALSO MAX # OF BLOCKS SYS JOB MAY HAVE +IF2 MAXJ==/LUBLK ;ROUND UP TO ACTUAL MAX #JOBS + +DIRMAP==1 ;ENABLE DIRECT MAPPING OF HIGH HALF + ;I DON'T THINK IT WORKS TO TURN THIS OFF. +NIOCHN==20 ;NUMBER OF I/O CHANNELS PER USER + +DEFINE $INSRT $%$%$% ;PRINTX MESSAGE WHEN FILE GETS INSERTED + .INSRT $%$%$% > + PRINTX \ ==> INSERTED: \ + .TYO6 .IFNM1 + .TYO 40 + .TYO6 .IFNM2 +PRINTX \ +\ +TERMIN + +;;; CONFIG uses this macro... +DEFINE CONC A,B +A!B!TERMIN + +$INSRT CONFIG ;CONFIGURATION SWITCHES FOR ALL KNOWN MACHINES + +$INSRT BITS ;DEFINITIONS OF MANY BIT NAMES + +;IN BADBTS => CLASS 2 OR 1 INTERRUPT ;IN VBDBTS=> CLASS 1 INTERRUPT +VBDBTS==%PIB42\%PIVAL\%PIBRK\%PIC.Z\%PI1PR\%PITRP\%PIDCL +BADBTS==VBDBTS\%PIMPV\%PIIOC\%PIILO\%PIMAR\%PIDIS\%PIOOB\%PILOS\%PIFET\%PIWRO\%PIPAR\%PITTY\%PIPDL\%PINXI + +UUOMIN==40000,, ;SMALLEST NUM THAT COULD BE A SYSTEM CALL +UUOMAX==50000,, ;ONE GREATER THAN LARGEST NUM " +UIOT=UUOMAX ;USE FOR USER I/O INST TRAP + + ;MAX DYN ALLOC ALLOC IO BUFFERS +MXIOB==100 ;MAX POSSIBLE + +SIOMT==50 ;MAX SIZE TRANSLATION TABLE + +LUPDL==50 ;LENGTH USER PDL MUST BE >= 40 FOR 2311 GC +LUIOP==20 ;LENGTH OF USER IO PDL +CPDLL==40 ;LENGTH CLOCK CHANNEL PDL +LUTCP==40 ;LENGTH UTC PDL (NETWORKS AND DISKS) +LSYSP==100 ;SYSTEM JOB PDL +LTTYP==40 ;LENGTH OF TTY (INTERRUPT LEVEL) PDL + +DMNSZ==20 ;# ENTRIES IN DEMON BUFFER (DMNBF) + +MXCZS==5 ;MAX NUMBER ^Z'S PER CLOCK BREAK + +SCLKI==30. ;60'THS PER SLOW CLOCK +VSCLKI==2*60.*60. ;60'THS PER VERY SLOW CLOCK TICK +MXOPT==8. ;SLOW CLOCK MAX UT OP CAN TAKE +NINFP==8. .SEE UFIN ;MAX # OF DIRECT INFERIORS A PROCEDURE MAY HAVE + +SSCHDB==100 ;LENGTH OF SCHEDULER HISTORY BUFFER + +SPD==60.*60.*24. ;# SECS IN A DAY (FITS IN A HALFWORD) + PDUPS==60. ;# PDCLK INCREMENTS/SEC + +OPNCOM==410300 ;COMMAND FIELD IN LH OF FIRST OPEN WORD + +IFN 340P,N340PB==10. ;# EXEC PGS USED FOR 340 DATA MUST BE EVEN +IFN N11TYS,[ + NTTPG==6 ;# EXEC PGS FOR PDP11 TV TTYS. + NTVBP==11 ;THESE PAGES ADDRESS THE WHOLE VIDEO BUFFER MEMORY ADDRESS + ;SPACE OF THE TV 11. THE LAST OF THESE ADDRESSES THE + ;TV CONSOLE REGISTER +] +NUVPG==256. ;NUMBER OF VIRTUAL PAGES PER USER. SIZE OF PAGE TABLE VARS. + ;DON'T TRY TO CHANGE THIS. +;CIRCULAR PAGE LINK FORM +;2.9=0 +;1.1-1.8 PAGE # +;2.8-1.9 USER # +;2.9=1 +;2.8=0 2.7-1.1 LINK TO MMP TABLE +;2.8=1 2.7-1.1 LINK TO MEM PNT TABLE +;EXCEPT 2.9-1.1=777777 => ABSOLUTE PAGE, NOT LINKED + +SUBTTL GOBBLE TTYTYP FILE + +IFN XGP\N11TYS,[IFE TEN11P,[ + .ERR XGP OR N11TYS WITHOUT TEN11P + N11TYS==0 + XGP==0 +] +] +IFNDEF UNSPLP,UNSPLP==*DEMON*<1-TPLP> + ;1 IF THE "UNSPOO" PROGRAM DOES LPT SPOOLING. + +IFNDEF TSYSM,[ +MNAME PRINTX \NO PARAMS KNOWN FOR , MACHINE. +\ +.INSRT TTY: +] + +IF2,[ +;TTY LINES DEFINITIONS + +;MACRO WHICH RETURNS THE %TY BIT FOR THE CONTROLLER ACCORDING TO THE LINE NUMBER + +DEFINE CNTRLR +IRPS F,,[0 NFKSTY NFETY NFNTY NFNVTY NFDZTY NFDPTY NFMTY NFDLTY NFSTTY NF11TY + ]NT,,[NOTYS NKSTYS NETYS NNTYS NNVTTS NDZTYS NDPTYS NMTYS NDLTYS NSTTYS N11TYS + ]FG,,[%TYOTY %TYKST %TYETY %TYNTY %TYNVA %TYDZT %TYDPK %TYMTY %TYDL %TYSTY %TY11T] + IFGE -F,[IFL -,[FG]]TERMIN TERMIN + +;MACRO WHICH RETURNS $TTISP, $TTOSP BITS GIVEN BAUD RATES + +DEFINE SPEEDC +*%TTISP+*%TTOSP!TERMIN + +DEFINE SPEED1 +IRPS BD,,[0 600 110 150 300 1200 1800 2400 4800 9600 25K 40K 50K 80K + ]CD,,[0 1 2 3 4 5 6 7 10 11 12 13 14 15 ] +IFSE BAUD,BD,[CD] TERMIN TERMIN + +;KEYWORD PARAMETERS TO TTY DEFINITION MACROS +; FOR OVER-RIDING DEFAULTS +;SPEED NUMBER OF BAUDS OUTPUT +;ISPEED NUMBER OF BAUDS INPUT IF DIFFERENT +;TT LH(TTTYP) IN ADDITION TO SPEED CODE +;TY RH(TTYTYP) IN ADDITION TO CONTROLLER BIT +;TO LH(TTYOPT) IN ADDITION TO USUAL CODES FOR TERMINAL TYPE +;TP RH(TTYOPT) IN ADDITION TO PAD CODES +;TCT TCTYP +;HOR SCREEN WIDTH +;VER SCREEN HEIGHT +;ROL LINES PER GLITCH WHEN SCROLLING + +;DEFINE TTY AS PRINTING. +;IF SPEED IS 110, ASSUME TTY IS TELETYPE, +;MEANING CAN'T BS, STANDARDIZE ALTMODES. +;IF KA10 CONSOLE TTY OR TK10 TTY, NEED PARITY +DEFINE TTDPRT N,+SPEED=300,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==80.-IFE 110-SPEED,8 +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOALT+IFN 110-SPEED,[%TOMVB+%TOLWR-%TOALT],,<1+IFE 300-SPEED,[IFE TY&<%TYDIL\%TYRLM>,[3]]>*%TPPCR+TP +T!N!$TYP==TT+\\,[%TTPAR]]>,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS MEMOREX +DEFINE TTDMRX N,+SPEED=600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=120.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOMVB+%TOLWR,,4*%TPPLF+6*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNMEM +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS TERMINET. +DEFINE TTDTRM N,+SPEED=1200,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=120.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOMVB+%TOLWR,,5*%TPPLF+TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNTRM +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS A LPT. +DEFINE TTDLPT N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=0,HOR=200.,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOMVB+%TOOVR,,TP +T!N!$TYP==%TTDDI+TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS AN LA36 DECWRITER. +DEFINE TTDLA36 N,+SPEED=300,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=132.,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOMVB+%TOOVR+%TOLWR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS IMLAC. (RUNNING SOFTWARE-TTY PROGRAM) +DEFINE TTDIML N,+SPEED=50K,ISPEED=25K,TT=0,TY=0,TO=0,TP=0,HOR=90.,VER=44.,TCT=%TNSFW,ROL=10.,SMARTS=%TQIM1 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOOVR+%TOLWR+%TOMVB+%TOMVU+%TOERS+%TOLID+%TOCID,,TP +T!N!$TYP==%TTDDI+TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS VT52 +DEFINE TTDVT N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,VER=24.,TCT=%TNESC,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS,,TP+%TPPTB* + ;DIRECT POSITIONING LOSES AT 9600 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS H19 +DEFINE TTDH19 N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,VER=24.,TCT=%TNH19,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*3 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS AAA +DEFINE TTDAAA N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS+%TPMTA,HOR=80.,VER=48.,TCT=%TNAAA,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*2 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS C100 +DEFINE TTDC100 N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=79.,VER=24.,TCT=%TNHDS,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*3+ +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS TEKTRONIX. +DEFINE TTDTEK N,+SPEED=1200,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNTEK,HOR=73.,VER=35.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOOVR+%TOMVB+%TOLWR+%TOMOR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==0 +TERMIN + +;DEFINE TTY AS A LOSING DATAPOINT +DEFINE TTDLSR N,+SPEED=2400,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNODP +T!N!$HOR==71.-IFN MCOND AIKA,1 ;OTHER DATAPOINTS HAVE SHORTER SCREENS. +T!N!$VER==25. +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS,,4*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS DATAPOINT. +DEFINE TTDDPT N,+SPEED=2400,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=[72.-IFN MCOND AIKA,[1]],SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNDP +T!N!$HOR==HOR ;OTHER DATAPOINTS HAVE SHORTER SCREENS. +T!N!$VER==25. +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS,,4*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS A TELERAY 1061 +DEFINE TTDRAY N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNRAY +T!N!$HOR==HOR +T!N!$VER==24. +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOERS+%TOLWR+%TOLID+%TOCID,,3*%TPPTB+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE A TTY THAT IS A GT40. +DEFINE TTDGT40 N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNDP,HOR=72.,VER=32.,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOERS+%TOMVU+%TOOVR+%TOLWR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE A TTY THAT IS A LINE TO A PDP11. +DEFINE TTD11 N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=0,TCT=%TNPRT,HOR=72.,VER=MOVE,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOOVR+%TOALT,,TP +T!N!$TYP==TT+%TTDDI+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE A TTY THAT IS RANDOM. +DEFINE TTDRAN N,+SPEED=FOO.,ISPEED=,TT=0,TY=0,TO=FOO.,TP=FOO.,TCT=FOO.,HOR=FOO.,VER=FOO.,ROL=FOO.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DATAMEDIA +DEFINE TTDDTM N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS+3*%TPPCR,HOR=80.,VER=24. +T!N!$SMT==0 +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOERS+%TOMVU+%TOLWR+%TOLID+%TOCID,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNDTM +T!N!$ROL==1 +TERMIN + +;DEFINE A PDP11 TV COMMUNICATING VIA TEN-11 INTERFACE. NO OPTIONS. +DEFINE TTDTV N +T!N!$SMT==%TQGRF+%TQVIR+%TQREC+%TQXOR+<.DPB 14,<.BP %TQHGT>>+<.DPB 6,<.BP %TQWID>>,,%TRSCN +T!N!$HOR==96. +T!N!$VER==45 +T!N!$OPT==%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI+%TOLID+%TOCID,,%TP11T+%TPRSC +T!N!$TYP==%TTLCL+,,%TY11T +T!N!$TCT==%TNTV +T!N!$ROL==4 +TERMIN + +;DEFINE A PDP11 TV COMMUNICATING AS A SOFTWARE TTY. TYPICALLY A GRINNELL (512x512). +DEFINE TTDGRN N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPCBS+%TPORS,HOR=86.,VER=50.,TCT=%TNSFW,ROL=0,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE AN STY LINE. NO OPTIONS. +DEFINE TTDSTY N +T!N!$SMT==0,, +T!N!$HOR==81. +T!N!$VER==MOVE +T!N!$OPT==%TOMVB+%TOOVR+%TOLWR+%TORAW,,%TPORS +T!N!$TYP==%TYSTY +T!N!$TCT==%TNPRT +T!N!$ROL==1 +TERMIN + +DEFINE MCONDX MCHN +IFE MCOND MCHN,TERMIN + +;;; THE NEXT TWO MACROS CAUSE TTYTYP FILE TO BE INSERTABLE BY BOTH +;;; PDP-10 AND PDP-11 PROGRAMS. + +DEFINE .ENDC +TERMIN + +DEFINE .ENDR +TERMIN + + .CRFOFF +$INSRT TTYTYP + .CRFON +EXPUNGE TTDPRT,TTDTRM,TTDDPT,TTDMRX,TTDGT40,TTD11,TTDRAN,TTDGRN,TTDVT,TTDTEK +EXPUNGE TTDTV,TTD2741,TTDSTY,TTDLPT,TTDIML,TTDLA36,TTDLSR +EXPUNGE SPEEDC,SPEED1,CNTRLR,MCONDX,.ENDC,.ENDR +] ;END OF IF2 + +SUBTTL BUG MACROLOGY + +;Macro for reporting a bug or other interesting condition +;Use this in place of JRST 4, especially when condition is automatically +;recoverable or wants explanation typed out for benefit of loser. +; +;First argument is one of the following symbols: +; INFO - just print on the system console +; CHECK - same as INFO unless SYSDBG non-zero or buffer full, then same as PAUSE +; PAUSE - print message, go to DDT, allow alt-P +; HALT - print message, go to DDT, do not allow alt-P +; DDT - PAUSE but not because of a bug (shorter message), allow alt-P +; AWFUL - same as HALT but usable when there is no pdl in P +; Should there be a combination of AWFUL and PAUSE? +; That would require restoring P upon attempt to continue +;Arguments after the first are either strings to be printed +;(enclose in brackets), or format,value pairs. Value is any +;address; indexing and indirection are allowed, however registers +;P and TT may not be referenced. +;A format is one of the following symbols: +; OCT - octal number, with ,, if bits on in the left halt +; DEC - decimal number +; THOU - decimal number with commas every three digits +; CR - print a carriage return (unfortunately swallows and ignores an arg) +; SIXBIT - sixbit word +; ASCIZ - asciz string +;Undefined formats will be taken as strings to be printed. +;The maximum number of value arguments is 6 +;A space is printed after each formatted value. A space is also +;printed after the last string and before any additional formatted values. +; +;With no arguments, BUG may be used in place of JRST 4,. +;It uses the same amount of storage but has the advantage of going +;straight to DDT. In this case there won't be a specific message +;about what the bug was, of course. +; +;Note that the BUG macro always generates one word of code, and hence +;may be skipped over. +;All registers are preserved. +;P must point at a valid PDL. +; +;Due to Midas inadequacy, the BUG macro may not be used from inside +;a literal. You will get an error (label inside brackets) if you try it. +; +;Example: +; BUG PAUSE,[DSK: DRIVE NUMBER ],OCT,Q,[IS OFF-LINE.] +; +DEFINE BUG FLAVOR,ARGS/ +IFNB [FLAVOR][ + ;Make sure we are not in a literal, since cannot get value of "." +BUGBUG: EXPUNGE BUGBUG + ;Generate call to appropriate flavour of subroutine + ZZ==0 + IRPS FLA,,[INFO,CHECK,PAUSE,HALT,DDT]SUB,,[BUGINF,BUGCHK,BUGPSE,BUGHLT,BUGDDT] + IFSE [FLAVOR]FLA,[ + PUSHJ P,SUB + ZZ==1 ] + TERMIN + IFSE [FLAVOR]AWFUL, JSR BUGAWF + .ELSE IFE ZZ, .ERR "FLAVOR" UNKNOWN FLAVOUR OF BUG + + BUGB==0 ;Initialize formatting bits + + ;Initialize remote macros +DEFINE BUGMC1 *ZZ001*ZZ002*ZZ003* +ZZ001!ZZ002!ZZ003!TERMIN + +DEFINE BUGMC4 ZZ001 +ZZ001 +TERMIN + + BUGN==0 ;number of accumulated arguments + BUGNN==0 ;total number of arguments + BUGF==0 ;next thing not argument + IRP ARG,,[ARGS] + ;; Processing "ARG" + IFN BUGF,[ ;Address of word to print + BUGN==BUGN+1 + BUGNN==BUGNN+1 + BUGMC5 [ARG] + BUGF==0 + ] + .ELSE [ ;Name of format in which to print? + IRPS FMT,,OCT DEC THOU CR UNUSED5 SIXBIT ASCIZ + IFSE [ARG]FMT,[ + BUGF==1 + BUGB==BUGB+<<.IRPCNT+1>_<<5-BUGNN>*3>> + ] + TERMIN + IFE BUGF,[ ;Just a string to be printed + IFN BUGN,[ ;Say to output some arguments before this string + BUGMC3 BUGN + BUGN==0 + ] + BUGMC2 [ARG] + ] ] + TERMIN + IFG BUGNN-6, .ERR MORE THAN 6 WORDS TO BE PRINTED IN BUG MACRO + ;Make bug table entry: length,,pc ? bits,,string ? args + IF1, BUGMC1 'ZZ==[ASCIZ|',,'|]' + IF2,[ + ZZ==. + LOC BUGTAB+LBUGTB + BUGNN+2,,ZZ + BUGMC1 'BUGB,,[ASCIZ|',,'|]' + BUGMC4 + LOC ZZ + ] + LBUGTB==LBUGTB+BUGNN+2 +];end IFNB +.ELSE PUSHJ P,BUGNIL +TERMIN + +LBUGTB==0 ;Initialize length of bug table + +;This support macro appends a string to the middle argument of BUGMC1 +DEFINE BUGMC2 STRING +BUGMC1 //,[DEFINE BUGMC1 *ZZ001*ZZ002*ZZ003* +ZZ001!ZZ002!]//,STRING!!ZZ003!TERMIN +TERMIN + +;This support macro appends a character, given by number, to the middle +;argument of BUGMC1 +;Only for characters 0 through 7 +DEFINE BUGMC3 #N +IRPC C,,.QUOTE// + IFE .IRPCNT-N,{ + BUGMC2 C + .ISTOP } +TERMIN +TERMIN + +;This one is a simple remote macro +DEFINE BUGMC5 STR +BUGMC4 [DEFINE BUGMC4 ZZ001 +ZZ001]STR +TERMIN +TERMIN + +SUBTTL DEFINE PI CHANNELS + +LPTP==OLPTP+NLPTP+GLPTP ;ANY KIND OF LPT EXCEPT A TTY LPT +IFE NMTCS,[ ;IF NO MAG TAPES AT ALL +TM10A==0 ; CAN'T HAVE ANY KIND! +TM10B==0 +TM03S==0 +] ;IFE NMTCS +TM10P==TM10A+TM10B ;SOME KIND OF A TM10 MAGTAPE PRESENT +IFN TABP,TABCLK==0 ;1=>PUT TABLET ON CLOCK CHNL + +;PRIORITY INTERRUPT CHANNEL ASSIGNMENTS + DCCHN==1 ;DC CHANNEL + DCLOC=40+2*DCCHN ;DC INTERRUPT LOCATION +IFN IMPP, IMPCHN==1 ;IMP STUFF +IFN NETP, NETCHN==2 ;SOFTWARE ACTIVATED... + UTCCHN==2 ;UTC CHANNEL + DSKCHN==UTCCHN ;2314 CHANNEL + MTCCHN==UTCCHN ;MAG TAPE CONTROL CHANNEL + LPTCHN==4 ;LINE PRINTER, PAPER TAPE, ETC. CHANNEL + TTYCHN==3 ;TTY CHANNEL +IFN PLTP, PLTCHN==4 ;PLOTTER CHANNEL +IFN PTRP, PCHCHN==4 ;PTP CHANNEL +IFN PTRP, PTRCHN==4 ;PAPER TAPE READER CHANNEL +IFN NTYP, NTYCHN==4 ;NTY 11 KLUDGE +IFN 340P, SDCHN==4 ;DISPLAY SPECIAL CHANNEL +IFN DSDP, DSDCHN==4 ;INTERRUPT FROM OTHER PROCESSOR +IFN ARMP, TIPBCH==5 ;ARM TIP BREAK CHNL +IFN OMXP, OMPCHN==5 ;OUTPUT MULTIPLEXOR +IFN VIDP, NVDCHN==5 ;NEW VIDI +IFN TABP, IFE TABCLK, TABCHN==5 ;TABLET +IFN 340P\E.SP, DISCHN==6 ;DISPLAY DATA CHNL +IFN CH10P, CHXCHN==5 ;CHAOSNET + ;WOULD BE 6 BUT PI 6 BROKEN IN ML-KA TTLIOB +IFN CH11P, CHXCHN==6 ;UNIBUS CHAOSNET PACKET COPYING +IFN TABP, IFN TABCLK, TABCHN==7 ;TABLET + APRCHN==7 ;DO NOT CHANGE + + PIOFF==400 ;TURN OFF PI SYSTEM + PION==200 ;TURN ON PI SYSTEM + PICOFF==1200 ;TURN OFF PI CHANNEL + PICON==2200 ;TURN ON PI CHANNEL + PICIRQ==4200 ;REQUEST INTERRUPT ON PI CHANNEL + CLKON==2201 ;ABSOLUTE + CLKOFF==1201 +IFN OMXP, OMXON==CLKON\<400_-OMPCHN-1> +IFN OMXP, OMXOFF==CLKOFF\<400_-OMPCHN-1> + LPTON==CLKON\<400_-LPTCHN-1> + LPTOFF==CLKOFF\<400_-LPTCHN-1> +IFN PTRP, PTPON==CLKON\<400_-PCHCHN-1> +IFN PTRP, PTROFF==CLKOFF\<400_-PCHCHN-1> +IFN PTRP, PTRON==CLKON\<400_-PTRCHN-1> +IFN PTRP, PTROFF==CLKOFF\<400_-PTRCHN-1> + TTYON==CLKON\<400_-TTYCHN-1> + TTYOFF==CLKOFF\<400_-TTYCHN-1> + UTCON==CLKON\<400_-UTCCHN-1> + UTCOFF==CLKOFF\<400_-UTCCHN-1> +IFN NETP, NETON==UTCON +IFN NETP, NETOFF==UTCOFF +IFN KL10P, DTEON==CLKON +IFN KL10P, DTEOFF==CLKOFF + + DSKRQ==PICIRQ\PICON\<200_-DSKCHN> ;RQ INT + TURN ON FOR SAKE OF KL + MTCRQ==PICIRQ\PICON\<200_-MTCCHN> + UTCRQ==PICIRQ\PICON\<200_-UTCCHN> + TTYRQ==PICIRQ\PICON\<200_-TTYCHN> + CLKRQ==PICIRQ\PICON\<200_-APRCHN> +IFN NETP,NETRQ==PICIRQ\PION\<200_-NETCHN> +IFN CH11P,CHXRQ==PICIRQ\PICON\<200_-CHXCHN> + +IFN TABP,[ +IFN TABCLK,[ +TABON==CLKON +TABOFF==CLKOFF +] +IFE TABCLK,[ +TABON==CLKON\<400_-TABCHN-1> +TABOFF==CLKOFF\<400_-TABCHN-1> +] +] + +IFN NUNITS, IFE NEWDTP, CUINT==5000+UTCCHN ;CONO TO UTC TO ACTIVATE UTAPE INTERRUPT + +PMLCAD==(.BP ) ;BYTE POINTER TO L.H. REAL CORE ADR +PMRCAD==(.BP PMRCM) ;BYTE POINTER TO R.H. REAL CORE ADR + +SUBTTL DEFINE DEVICE CODES, IOBFT CHNL NUMBERS + +IFN STKP, STK==70 ;STANFORD KEYBOARD +IFN OLPTP, OLPT==124 ;LINE PRINTER +IFN NLPTP, NLPT==464 +IFN TM10P, MTC==340 ;MAG TAPE CONTROL +IFN TM10P, MTS==344 ;MAG TAPE STATUS +IFN VIDP, NVDX==620 ;NEW VIDI X +IFN VIDP, NVDY==624 ;NEW VIDI Y +IFN VIDP, NVDT==630 ;NEW VIDI T (DEFLECTION DELAY) +IFN PLTP, PLT==654 ;CAL COMP PLOTTER +IFN HCLKP, CLK1==710 ;HOLLOWAY CLOCK +IFN HCLKP, CLK2==714 ; " +IFN IMXP, MPX==574 ;INPUT MULTIPLEXOR +IFN OMXP, OMPX==570 ;OUTPUT MULTIPLEXOR +IFN TK10P\NTYP, NTY==600 ;KNIGHT TTY KLUDGE +IFN MTYP, MTY==400 +IFN DL10P, DLB==60 ;DL10 BASE +.ALSO DLC==64 ;DL10 CONTROL +IFN PDCLKP, PDCLK==500 ;DE-CORIOLIS CLOCK (FOR ML-KA AND DM, CALENDAR CLOCK) +IFN DSDP, DSDEV==20 ;DE SELECTION AND INTER COM DEVICE +IFN DSDP, DSDEVN==24 ;DE SELECTION DEV (FOR DEVICES YOU DATAO DEV CODE TO DSDEVN) +IFN ARMP, TIPDEV==504 ;TIP BREAK DEVICE +IFN RBTCP, RBTCON==514 ;ROBOT CONSOLE +IFN DPKPP, DPK==604 ;DATA POINT KLUDGE +IFN DC10P, DC0==610 ;2314 DISK CONTROL +IFN DC10P, DC1==614 ;2314 DISK CONTROL +IFN RP10P, DPC==250 ;RP10 DISK CONTROL +IFN RH10P, DSK==270 ;RH10 DISK CONTROL +IFN KAIMP, IMP==460 ; AI-KA/ML-KA/MC-KL IMP interface +IFN DMIMP, FI==424 ; DM IMP hardware +IFN NUNITS,[ +IFN NEWDTP,[ + DTC==320 + DTS==324 +] ;END OF IFN NEWDTP +] ;END OF IFN NUNITS + + +;IOBFT CHANNEL NUMBERS - 77 MEANS "FREE" + +IFN NUNITS, NUTIC==8 ;NUMBER UT IN CHNLS +.ELSE NUTIC==0 +IFN NUNITS, NUTOC==8 ;NUMBER UT OUT CHNLS +.ELSE NUTOC==0 + NFCLC==NUTIC+NUTOC+1 ;# OF FIRST CORE LINK CHNL + NCLCH==14 ;NUMBER CORE LINK CHNLS + NFNETC==NFCLC+NCLCH ;# OF FIRST NCP NET CHNL (if any) + ;NNETCH DEFINED IN CONFIG +IFG NFNETC+NNETCH-77, .ERR TOO MANY IOBFT CHANNELS + +SUBTTL RANDOM DEFINITIONS FOR I/O DEVICES + +IFN DSDP, IFN VIDP, DSNVID==200000,, ;DEASSIGN BIT FOR NVD +IFN DSDP, IFN 340P, DSNDIS==4000,, ;DEASSIGN BIT FOR DIS +IFN DSDP, IFN NMTCS, DSMTC==1,, ;DEASSIGN BIT FOR MAG TAPE + +IFN RBTCP, RLTSWC==17 ;ROBOT CONSOLE SELECT FOR LIGHTS AND SWITCHES +IFN RBTCP, IFN TABP, RTABC==16 ;ROBOT CONSOLE SELECT FOR TABLET + +IFN IMXP, LCHN==177 ;MULTIPLEXOR LIMIT ON READ IN + + NUDCH==14 ;NUMBER DIRECTORY CHNLS +IFN IMXP, NPOTCH==20. ;NUMBER POT CHANNELS +IFG NQCHN+1+NQS-77, .ERR MORE THAN 6 BITS OF DISK CHANNEL NUMBER + +IFN CODP, CODBFL==5 ;CODE BUFFER +IFN PTRP, PUNSIZ==20 ;PTP BUF SIZ +IFN PTRP, REDSIZ==200 ;PTR BUF SIZ +IFN PLTP, LPLBUF==200 ;PLT BUF SIZ +IFN LPTP, LPTBSZ==1000 ;LPT BUF SIZ +IFN VIDP, NVDLNG==340 ;NVD BUF SIZE +IFN TPLP, TPLBSZ==100 ;TPL BUFFER SIZE IN SYS JOB +IFN TABP, LTABBF==100 ;TABLET BUFFER +IFN N11TYS, TT11CR==764044 ;UNIBUS ADR OF TV11 CONSOLE REG + +EOFCH==3 ;SYSTEM END OF FILE CHR +EOFWRD=REPEAT 5,[EOFCH_<.RPCNT*7+1>\]0 ;WORD OF EOFCH'S + +IFN 340P, DVEF==4000 ;DISPLAY VERTICAL EDGE FLAG +IFN 340P, DHEF==1000 ;DISPLAY HOR EDGE FLAG + +IFN 340P, EWRT==400./12. ;EQIV "COST" IN DISPLAY WRDS FOR TRIP THRU RECYC +IFN 340P, MDISWD=70000 ;MAX # WDS SENT TO SCOPE IN 1/2 SEC + +NSWPV==E.SP\340P+VIDP+IMXP ;# OF DEVICES THAT CAN SWAPIN PAGES + +IFN C1MXP,[ +IFN NMTCS, MAGLOC==76 ;INTERRUPT LOCS FOR MAGTAPE +IFN NUNITS, DCMLOC==74 ;" " FOR DC +IFN IMXP, IMXLC==66 ;" " IMX +IFN IMPP,[ + IMPILC==70 ;INPUT FROM IMP + IMPOLC==72 ;OUTPUT TO IMP +] +] + +IFE C1MXP,[ +IFN NMTCS, MAGLOC==42 +IFN NUNITS, DCMLOC==42 +] +IFN PLTP,[ +;PLOTTER CONTROL BITS +SD==4000 +PD==10000 +PUP==200 +PDN==400 +SDC==20000 +PDC==40000 +SDS==1000 +PDS==2000 +] + IFN KA10P,[ + +SUBTTL STUFF PECULIAR TO KA-10 PROCESSOR + +;;;PAGING BOX INSTRUCTIONS + +LPM=102000,, ;LOAD PG MEM STATE VECTOR DONT CLR ASSOC MEM +LPMR= LPM 2, ;CLEAR ASSOC MEM AND LOAD +SPM= LPM 1, ;STORE PG MEM STATE VECTOR +LPMRI=LPM 6, ;LOAD PM, CLEAR ASSOC REG, AND CAUSE INTERRUPT +EXPGNG==4 .SEE UPQUAN ;4 TO TURN ON EXEC PAGING +XCTR=103000,, ;EXECUTE INSTRUCTION WITH MAPPING CONTROLLED BY AC FIELD + ;VIOLATION CAUSES USER MEM PROTECT INTERRUPT UNLESS INHIBITED + ;VIOLATION ALSO SKIPS BUT THIS IS OF NO CONSEQUENCE UNLESS + ;INTERRUPT IS INHIBITED SINCE PC WILL BE RESET FROM OPC +XCTRI= XCTR 4, ;XCTR WITH PAGE FAULT INHIBITED (SKIPS ON FAULT) + ; AC FIELD VALUES FOR XCTR AND XCTRI + XR==1 ;MAP READ MAIN OPERAND OF SIMPLE INSTRUCTION (MOVE, SKIPL, HLL) + XW==2 ;MAP WRITE MAIN OPERAND OF SIMPLE INSTRUCTION (MOVEM) + XRW==3 ;MAP READ/WRITE OPERAND OF SIMPLE INSTRUCTION (E.G. IORM) + XBYTE==3;MAP BYTE DATA AND BYTE POINTER (ILDB, IDPB) + XBR==1 ;MAP BLT READ + XBW==2 ;MAP BLT WRITE + XBRW==3 ;MAP BOTH OPERANDS OF BLT + ;KA10 PAGING BOX GOES BY WHETHER IT'S A READ OR WRITE (OR RW) CYCLE + ;KL10 PAGING BOX WORKS DIFFERENTLY (SEE BELOW) + ;DO NOT USE MULTI-OPERAND INSTRUCTIONS (DMOVE, PUSH, ETC.) WITH XCTR + +DEFINE CLRPGM U ;CLEAR PAGER ASSOCIATIVE MEMORY. ARG IS USUALLY "(U)". + SPM UPGML!U ;STORE SO DON'T LOSE QUANTUM TIMER + LPMR UPGML!U +TERMIN + +;;; MISCELLANEOUS BUILTIN I/O DEVICES + +PI==4 ;INTERRUPT SYSTEM +LIGHTS==PI ;DEVICE CODE FOR DATAO THAT SETS CONSOLE LIGHTS. +CLK==0 ;DEVICE CODE FOR 60 HZ CLOCK INTERRUPT (APR) +CLKINT==1000 ;CONI CLK, BIT FOR INTERRUPT. ALSO CONO BIT TO CLEAR. +PTR==104 ;PAPER TAPE READER +PTP==100 ;PAPER TAPE PUNCH +TTY==120 ;CONSOLE TTY +DTC==320 ;DECTAPE CONTROL +IFN 340P, DIS==130 ;340 DISPLAY + +PI0LOC==40 ;INTERRUPT VECTOR BASE + +OIPBIT==%PC1PR ;PC BITS FOR 1-PROCEED. +BADPC==%PCUIO+%PCSPC+37 ;BITS IN PC USER NOT ALLOWED TO TURN ON + +DEFINE UUOH ;UUO HANDLER LOCATIONMS ARE REFERENCED THROUGH THESE MACROS +XUUOH!TERMIN + +DEFINE FORTY +40!TERMIN + +DEFINE SYSCTX ;SET UUO LEVEL AC BLOCKS +TERMIN + +DEFINE USRCTX ;SET USER-MODE AC BLOCKS +TERMIN + +DEFINE OVHMTR NAME ;OVERHEAD METERING DOESN'T WORK ON KA'S +TERMIN +] ;END OF IFN KA10P + IFN KL10P,[ + +SUBTTL STUFF PECULIAR TO KL-10 PROCESSOR + +;;;PAGING BOX INSTRUCTIONS + +XCTR=074000,, ;EXECUTE INSTRUCTION WITH MAPPING, PAGE FAILS ENABLED +XCTRI=075000,, ;SAME BUT SKIPS IF THERE IS PAGE FAIL (DONE SNEAKILY BY SOFTWARE) +LPMR=076000,, ;LOAD PAGER MEMORY (JPC, DBRS) AND CLEAR PT DIR +SPM=077000,, ;STORE PAGER MEMORY + ;AC FIELD VALUES FOR XCTR AND XCTRI + XR==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR READING) + XW==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR WRITING) + XRW==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR READING AND WRITING) + XBYTE==5;MAP BYTE DATA AND BYTE POINTER + XBR==1 ;MAP BLT SOURCE + XBW==4 ;MAP BLT DESTINATION + XBRW==5 ;MAP BOTH BLT OPERANDS + XEA==16 ;MAP EFFECTIVE ADDRESS COMPUTATION + ;IN KL10 BITS ARE: 14 INDIRECT WORDS + ; 10 XR UNDER SOME RANDOM WIERD CONDITIONS (?) + ; 4 MAIN OPERAND " " " ALSO BYTE WRITE + ; 2 INDEX REGISTER, @ AND XR IN BYTE PTRS + ; 1 2ND OPND - BLT SOURCE, BYTE READ, STACK DATA + +DEFINE CLRPGM U ;CLEAR PT DIR WITHOUT SWITCHING USERS. ARG IS USUALLY "(U)". + CONO PAG,660000+ +TERMIN + +;;; INTERNAL "I/O" DEVICES + +PI==4 ;INTERRUPT SYSTEM +PAG==10 ;CONO, DATAO PAG SET UP PAGING + ..D010==0 ;FOR DDT +CCA==14 ;CACHE OPERATIONS +TIM==20 ;TIMER DEVICE +MTR==24 ;METERS DEVICE + +IFN PDCLKP,[ ;IF THIS KL-10 HAS FREEMAN KL-UDGE BOARD, +LIGHTS==500 ;DATAO LIGHTS, SETS CONSOLE LIGHTS. +CLK==500 ;60 HZ CLOCK INTERRUPT (ON KL-UDGE BOARD) +CLKINT==10 ;CONI CLK, BIT FOR INTERRUPT. ALSO CONO BIT TO CLEAR. + ;ALSO DATAI 500, IS THE DECORIOLIS CLOCK. + ;AND CONO 500,400000 TURNS CLOCK BACK ON AFTER POWER FAIL. +] + +OIPBIT==%PS1PR ;1-PROCEED BITS IN THE PC. +BADPC==%PSUIO+37 ;%PSPUB IS OK? + +;;; SPECIAL INSTRUCTIONS + +SWPIA=DATAI CCA, ;INVALIDATE WHOLE CACHE +SWPIO=CONI CCA, ;INVALIDATE ONE PAGE OF CACHE +SWPUO=CONSO CCA, ;UNLOAD ONE PAGE OF CACHE +SWPUA=DATAO CCA, ;UNLOAD WHOLE CACHE +WRPAE=702100,, ;WRITE PERFORMANCE-COUNTER ENABLES +APRID==BLKI ;READ CPU SERIAL NUMBER AND OPTIONS +RDERA=BLKI PI, ;READ ERROR ADDRESS +RCCL=DATAI TIM, ;READ CALENDAR CLOCK (DOUBLE WORD) +RPERFC=BLKI TIM, ;READ PERFORMANCE COUNTER (DOUBLE WORD) +REBOXC=DATAI MTR, ;READ EBOX CYCLE COUNTER (DOUBLE WORD) +RMBOXC=BLKI MTR, ;READ MBOX CYCLE COUNTER (DOUBLE WORD) + +;;;EPT LOCATIONS + +$INSRT EPT + +;;;PAGE FAIL WORD - UPFW(U) + + %PF==1,,405000 + %PFUSR==400000 ;USER PAGE + %PFCOD==370000 ;FAILURE CODE: + %PFPRO==210000 ;PROPRIETARY VIOLATION + %PFMAR==230000 ;MAR BREAK + %PFILW==240000 ;ILLEGAL WRITE IN READ ONLY + %PFPNA==330000 ;PAGE NO ACCESS + %PFPTP==250000 ;PAGE TABLE PARITY + %PFPAR==360000 ;PARITY ERROR, DATA IN AR + %PFPRX==370000 ;PARITY ERROR, DATA IN ARX + %PFPUB==4000 ;PUBLIC PAGE + %PFCCH==2000 ;CACHED + %PFPAG==1000 ;PAGED + $PFPNO==121000 ;VIRTUAL PAGE NUMBER + ;1.1-3.5 VIRTUAL ADDRESS + +DEFINE UUOH ;UUO HANDLER LOCATIONS REFERENCED THROUGH THESE MACROS +XUUOH(U)TERMIN + +DEFINE FORTY +MUUODP(U)TERMIN + +;SET SPECIAL CONTEXT: CURRENT AC BLOCK CURACS, PREVIOUS BLOCK (FOR XCTR) OLDACS, +; UPT AS SPECIFIED. IF NO ACS SPECIFIED, THEY DON'T CHANGE; SAME FOR UPT. +; DISABLE, IF NONBLANK, CAUSES ACCOUNTING UPDATING NOT TO BE DONE EVEN THOUGH +; UPT IS BEING SET. +DEFINE SPCCTX CURACS,OLDACS,UPT,DISABLE +DATAO PAG,[IFNB CURACS OLDACS,[SETZ]+IFNB UPT,[1^13]+2^13+CURACS_33+OLDACS_30+UPT/1000+400000-IFNB UPT,[IFB DISABLE,[400000]]] +TERMIN + +SYSCTX=SPCCTX 0,1 ;UUO LEVEL CONTEXT: CURRENT AC BLOCK 0, PREVIOUS = 1. +USRCTX=SPCCTX 1,1 ;USERS RUN IN BLOCK 1. +IRPC N,,[234567] + AC!N!CTX=SPCCTX 0,N ;CUR AC 0, PREV N. USE XCTR TO ACCESS SPECIAL ACS +TERMIN + +;AC BLOCK USAGE: +; 0 ACCUMULATORS FOR SYSTEM (AT UUO LEVEL) +; 1 ACCUMULATORS FOR USER +; 2 USED TEMPORARILY BY TTY INPUT INTERRUPTS +; 3-5 NOT USED +; BLOCKS 2 & 3 ARE USED BY THE UNFINISHED MUSIC MICROCODE +; BLOCKS 4 & 5 ARE USED BY THE UNFINISHED JPC RING FEATURE +; 6-7 USED BY MICROCODE +] ;END OF IFN KL10P + IFN KS10P,[ + +SUBTTL STUFF PECULIAR TO THE KS-10 PROCESSOR + +EPT==:0 ; This MUST agree with the Salvager! +HSB==:500 +$INSRT KSDEFS + +DEFINE CLRPGM U ;CLEAR PT DIR WITHOUT SWITCHING USERS. ARG IS USUALLY "(U)". + WREBR 20000+ +TERMIN + +OIPBIT==1000 ;BIT 8 (SYMBOLIC NAME %PSINH) +BADPC==%PSUIO+37 ;BITS IN PC THAT USER CANNOT TURN ON + +DEFINE UUOH ;UUO HANDLER LOCATIONS REFERENCED THROUGH THESE MACROS +XUUOH(U)TERMIN + +DEFINE FORTY +MUUODP(U)TERMIN + +;SET SPECIAL CONTEXT: CURRENT AC BLOCK CURACS, PREVIOUS BLOCK (FOR XCTR) +; OLDACS, UPT AS SPECIFIED. IF NO ACS SPECIFIED, THEY DON'T CHANGE; SAME +; FOR UPT. +DEFINE SPCCTX CURACS,OLDACS,UPT +WRUBR [IFNB CURACS OLDACS,[SETZ]+IFNB UPT,[1^13]+CURACS_33+OLDACS_30+UPT] +TERMIN + +SYSCTX=SPCCTX 0,1 ;UUO LEVEL CONTEXT: CURRENT AC BLOCK 0, PREVIOUS = 1. +USRCTX=SPCCTX 1,1 ;USERS RUN IN BLOCK 1. +IRPC N,,[234567] + AC!N!CTX=SPCCTX 0,N ;CUR AC 0, PREV N. USE XCTR TO ACCESS SPECIAL ACS +TERMIN + +;AC BLOCK USAGE: +; 0 ACCUMULATORS FOR SYSTEM (AT UUO LEVEL) +; 1 ACCUMULATORS FOR USER +; 2 USED TEMPORARILY BY TTY INPUT INTERRUPTS +; 3-6 NOT USED +; 7 USED BY MICROCODE (AC0 GETS BAD DATA WHEN MEMORY ERROR OCCURS, THIS +; COULD BE FIXED IF ANYONE THINKS IT IS WORTH IT...) +] ;END OF IFN KS10P + +IFE KS10P,[ ; For the benefit of processors without UMOVE and UMOVEM. + +DEFINE UMOVE (AC,ADDR) +XCTR XR,[MOVE AC,ADDR] +TERMIN + +DEFINE UMOVEM (AC,ADDR) +XCTR XW,[MOVEM AC,ADDR] +TERMIN + +] ;IFE KS10P + +SUBTTL SYS IOC STATUS WORD FORMAT + +;RIGHT HALF WORD DEVICE STATUS +;1.1-1.6 SYS PHYSICAL DEVICE CODE +;1.7-1.9 OPEN MODE +;2.1 SYS BUFF CAP FULL +;2.2 " " " EMPTY +;2.9-2.3 DEVICE DEPENDANT + +;LEFT HALF WORD CHANNEL STATUS +;3.6-3.1 SET BY OPENS THAT DONT SKIP +;4.5-3.7 SET BY IOC ERRORS (INTERRUPTS) AT IOT OR OPER TIME + ;3.9-3.7 ARE FOR 340 OR E&S ERRORS + ;4.5-4.1 ARE FOR OTHER DEVICES +;A LIST OF ERROR CODES FOR OPEN FAILURES ARE IN THE FILE BITS. + +NDOPL==7 ;NUM OF DIS OPNL + +;4.5-3.7 SET BY IOC ERRORS AT IOT OR OPER TIME + +;3.9-3.7 SET BY 340 ROUTINES +;1 ILLEGAL SCOPE MODE +;2 SCOPE HUNG +;3 MORE THAN 1K SYS SCOPE BUF +;4 MEMORY PROTECT +;5 ILLEGAL SCOPE OP +;6 MEMORY PROTECT ON PDL POINTER +;7 ILLEGAL PARAMETER SET + +;4.5-4.1 +;DECIMAL CODE +;13 DIRECTORY'S ALLOCATION EXHAUSTED +;12 DIRECTORY FULL +;11 ILLEGAL CHR AFTER ^P ON TTY DISPLAY +;10 CHNL IN ILLEGAL MODE WHEN .IOT ATTEMPTED +;9 DEVICE FULL +;8 CHANNEL NOT OPEN +;7 USR OP CHNL DOES NOT HAVE USR OPEN +;6 ATTEMPT TO OVER IOPUSH +;5 ATTEMPT TO OVER IOPOP +;4 NON-EXISTANT SUB DEVICE +;3 NON-RECOVERABLE DATA ERROR ;NON-EX-MEM ON PDP6 REF +;2 END OF FILE +;1 DEVICE HUNG OR REPORTING NON-DATA ERROR + +MIOTER==1 ;LOWEST IOCERR CODE USED +NIOTER==13. ;NUMBER " " + +;4.9-4.5 ALWAYS ZERO (USED BY IOPUSH FOR CHNL NUM) + +;SYS PERIPHERAL DEVICE CODES + +;1.6 INDICATES DIRECTORY DEVICE +;1.5 INDICATES NON PHYSICAL DEVICE + +SNTTY==1 +SNTDS==2 ;TERMINAL DISPLAY +SNLPD==3 ;DATA PRODUCTS LPT +SNVID==4 +SNBAT==5 +SNPLT==6 +SNPTP==7 +SNIMPX==10 +SNOMPX==11 +SNPTR==12 +SN340==13 ;340 AS ASCII DEVICE +;SN340I==14 ;INTERPRETED DISPLAY ON 340 +SNMTC==15 ;MAGTAPE +SNCOD==16 ;CODE DEVICE +SNTAB==17 +SNNUL==21 +SNJOB==22 +SNBOJ==23 +SNSPY==24 +SNSTY==25 +SNNET==26 ; Arpanet NCP +SNLPV==27 ;VOGUE LPT +SNSTK==30 ;STANFORD KEYBOARD +SNMSP==31 ;CROCK "IPC" FOR NOW +IFN CHAOSP,SNCHA==32 ;CHAOS NET +IFN TCPP,SNTCP==33 ; Internet TCP/IP network device +SNTRAP==34 ;TRAP "DEVICE" +IFN INETP,SNIPQ==35 ; Internet Queue +IFN KS10P,SNUBI==36 ; Unibus interrupt +SNUTC==41 +SN2311==43 +SNFUSR==60 +SNUSR==61 +SNCLK==62 ;CLO, CLU, & CLI +SNDIR==63 +SNPDP==64 ;PDP6 +SNDIRH==65 ;DIRHNG "DEVICE" +SNLCK==66 ;LOCK "DEVICE" + +SUBTTL SYSTEM VERSION NUMBER & MISC MACROS + +ITSMCH==: ; Define SIXBIT machine name symbol +ITSVRS==:.FNAM2 ; Preserve SIXBIT symbol value of ITS version # +FNM==ITSVRS ;SRI GETS VERSION NUMBER + ;WORKS FOR DECIMAL IGNORES LOW ORDER NON-NUMERIC CHRS +DEFINE VNAM +.TAG FOO + ZZZQ==FNM&77 + IFGE ZZZQ-'0,IFLE ZZZQ-'9,.GO BAR + FNM==FNM_-6 + .GO FOO +.TAG BAR + ZZZQ==1 + SRI==0 +.TAG MUM + IFE FNM,.GO END + ZCHR==FNM&77-'0 + IFL ZCHR,.GO END + IFG ZCHR-9,.GO END + SRI==SRI+ZZZQ*ZCHR + ZZZQ==ZZZQ*10. + FNM==FNM_-6 + .GO MUM +.TAG END + TERMIN + +IF1 VNAM + +DEFINE SRITYP A +ZZZ==10 ;SAVE OLD RADIX +RADIX 10. + MOVEI I,[MNAME [.ASCII ? +] ITS !SRI A?] +RADIX ZZZ + TERMIN + + ;"MONTHS OF THE YEAR" MACRO + +DEFINE MNIRP A +IRPS M,,[JAN:FEB:MAR:APR: +MAY:JUN:JUL:AUG: +SEP:OCT:NOV:DEC:]L,,[31. 29. 31. 30. +31. 30. 31. 31. +30. 31. 30. 31.] +A +TERMIN +TERMIN + +FOO==-1 ;ACCUMULATED VALUE FOR FOLLOWING DEFINITION: + +MNIRP [M==FOO +FOO==FOO+L] ;JAN=-1, FEB=30., MAR=59., ETC. + +DEFINE INFORM A,B +IF1,[PRINTX \A = B +\]TERMIN + +ZZZ==10 +RADIX 10. +INFORM VERSION,\SRI +RADIX ZZZ + +SSYS==0 ;LENGTH OF SYS CODE + +DEFINE EBLK +IFN CKPAR,.ERR LOSS AT EBLK +CKPAR==1 +IFE .-CKZZ,.STOP ;NO WORDS BETWEEN BBLK AND EBLK +CONC CK,\CKNUM,==CKZZ-.,,CKZZ +CKNUM==CKNUM+1 +SSYS==SSYS+.-CKZZ +TERMIN + +DEFINE BBLK +CKZZ==. +IFE CKPAR,.ERR LOSS AT BBLK +CKPAR==0 +TERMIN + +CKPAR==1 +CKNUM==0 + + +;INSERT CALL TO THIS MACRO AT ANY PLACE IT IS POSSIBLE TO PCLSR +;(IF IT IS DESIRED FOR PCLSR TEST FEATURE TO TEST THAT SECTION) + +DEFINE PCLT +IFN PCLSW,[ + SKIPE PCLDBM + PUSHJ P,PCLTST +] +TERMIN + +DEFINE PCLTH A +IFN PCLSW,[ + SKIPN PCLDBM + JRST .+3 + PUSHJ P,PCLTSH + A +] +TERMIN + +DEFINE PI2SAF + CONSO PI,20000 + CONSO PI,40 + CAIA + JRST 4,. ;PI 2 NOT OFF AND NOT IN PROGRESS +TERMIN + +SUBTTL DEFINE EXEC PAGES + +EXPGN==0 + +DEFINE EXECPG X +X==EXPGN +EXPGN==EXPGN+1 +ZZQ==&1 +ZZQQ==X_-1 +.!X==220000*ZZQ+2200,,ZZQQ +TERMIN + +;EXEC MAP ASSIGNMENTS +IFN 340P,[ +EXECPG 340P1, ;USED TO FETCH + TRACE 340 PNTRS +EXECPG 340P2, +REPEAT N340PB,CONC [EXECPG DPG]\.RPCNT,; ;DATA AREA PNTRS FOR 340 DATA +] +EXECPG CORJF, ;CORE JOB FROM PAGE +EXECPG CORJT, ;CORE JOB TO PAGE +IFN VIDP,[ +EXECPG VSB1, ;.VSCAN B1 +EXECPG VSB2, ;.VSCAN B2 +] +IFN TEN11P,[ +EXECPG T11CP, ;TEN11 CONTROL PAGE +] +EXECPG PAREP, ;USED BY SYSTEM IN ITS DILIGENT EFFORTS TO FIX PARITY ERRORS + +IFN ECCMEM, EXECPG ECCPG, ;PAGE USED TO ACCESS ECC HISTORY + +IFN XGP,[ +EXECPG XGPC, ;LOW 2K OF XGP PDP-11 (USED TO TRACE BUFF POINTERS) +EXECPG XGPB, ;2K BUFFER IN PDP-11 (CHANGES LOCATION) +EXECPG XGPUB, ;XGP USER CORE EXEC PG SETUP TO POINT TO USER CORE DURING XGPIM SYSTEM CALL +] +IFN N11TYS,[ +REPEAT NTTPG,[CONC [EXECPG TTPG]\.RPCNT, +] +REPEAT NTVBP,[CONC [EXECPG TTR]\.RPCNT, +]] +IFN CHAOSP,[ IFN T11CHP,[ +EXECPG CHSPG ;CHAOS NET 10-11 COMMUNICATION PAGE +T11CHS=400000+CHSPG*2000 +]] ;CHAOSP, T11CHP +;^ INSERT NEW EXEC PAGES HERE +;EXEC PAGES BELOW THIS POINT WILL BE COPYABLE BY USERS +REPEAT NMMP,CONC [EXECPG MMP]\.RPCNT,; ;MMP TABLE + MMP=MMP0*2000+400000 ;VIRTUAL ADDRESS OF MMP +EXPUNGE EXECPG +NEXPGS==EXPGN ;# EXEC PGS USED + +SUBTTL LOW CORE + +.YSTGWD ;STORAGE WORDS OKAY NOW + +IFN KL10P, LOC EPT+1000 ;KL needs a full DEC page for EPT +IFN KS10P,[ + IFE KSIMP, LOC EPT+1000 ;KS needs a full DEC page, too, + IFN KSIMP, LOC EPT+2000 ; unless you are losing even worse. +] + +PATB=. +LOC 20 + BBLK + +IFN KS10P,[ +LOC 30 ; 8080 communications area + EBLK +] ;IFN KS10P + +IFN TM10B,[ + LOC 30 + EBLK +MICWA: MIOWD + 0 +IFE RP10P+RH10P,BBLK +] +IFN RP10P+RH10P,[ + LOC 32 +IFE TM10B,EBLK +QICWA: QIOWD + 0 +IFN QRDCMP,[ +RCICWA: 0 + 0 +];QRDCMP + BBLK +] +IFN E.SP,[ + LOC 34 + E.SPM ;POINTER , NEVER CHANGES +] + +IFE KS10P,[ +LOC 37 + EBLK +] ;IFE KS10P + +LOC 41 +IFN KA10P, JSR UUOH ;UUO TRAP +IFE KA10P, JSR LUUOEX ;USER UUO IN EXEC MODE (ERROR) + +LOC PI0LOC+2 + REPEAT 2, JSR RINT1 + REPEAT 6*2, JSR RINT ;INITIALIZE ANY UNUSED PI LOCNS + +LOC 61 +IFN KA10P, JSR 60H ;60 TRAP +IFN C1MXP, REPEAT 2*7., JSR RINT1 ;INITIALIZE C1MPX LOCNS + +LOC PI0LOC+2*APRCHN + JSR CLKBRK ;PROCESSOR OR CLOCK INTERRUPT + JRST 4,. + +LOC PI0LOC+2*LPTCHN + JSR LPTBRK ;LPT,DISPLAY,PTP,PTR,OTHER PROCESSOR +IFN 340P, JSR DRECYC ;HACK HACK + +LOC PI0LOC+2*TTYCHN + JSR TTYBRK ;TTY,DATAPOINT KLUDGE + JRST 4,. + +LOC PI0LOC+2*UTCCHN + JSR UTCBRK ;MICRO TAPE OR DISK (S) + JRST 4,. + +IFN E.SP,[ +LOC PI0LOC+2*DISCHN + JSR ESBRK + JRST 4,. +] +IFN 340P,[ +LOC PI0LOC+2*DISCHN + JSR DIGNOR ;340 DISPLAY BLKO GETS PATCHED IN HERE + CONO PI,4000+200_<-SDCHN> ;HACK HACK +] +IFN CH10P+CH11P,[ +LOC PI0LOC+2*CHXCHN + JSR CHXBRK + JRST 4,. +];CH10P + +IFN VIDP,[ +LOC PI0LOC+2*OMPCHN + JSR OMPXBK ;OUTPUT MPXR, NVID, ETC. + JRST 4,. +] +IFN KAIMP,[ +LOC PI0LOC+2*IMPCHN + JSR IMPBRK +LOC IMPILC + JSR IMPIBK + 0 +LOC IMPOLC + JSR IMPOBK + 0 +] ; IFN KAIMP + +IFN KL10P,[ +LOC PFOPC +PFOPC: 0 ;PAGE FAIL OLD PC STORED HERE +PFNPC: PFAIL ;WHERE TO GO FOR PAGE FAIL + +LOC EPTDIA +EPTDIA: JRST SALV ;STD COMMAND START ADDRESS ("DIAGNOSTIC") +EPTDDT: JRST DDT ;DDT COMMAND START ADDRESS +EPTSTL: JRST DSKDMP ;STL COMMAND START ADDRESS ("LOADER") +EPTITS: JRST BEG ;STM COMMAND START ADDRESS ("MONITOR") + ;SALV THEN GO +LOC EPTTR1 +EPTTR1: CAI ;ARITH OVERFLOW EXEC MODE IGNORED +EPTTR2: JSR ILLTRP ;PDL OVERFLOW EXEC MODE IS AN ERROR +EPTTR3: JSR ILLTRP ;ONE PROC CODE? + +LOC DTEBPO +DTEBPO: 0 ;BYTE TRANSFER NOT USED +DTEBPI: 0 ;BYTE TRANSFER NOT USED +DTELOC: ;INTERRUPT FROM CONSOLE 11 +IFE PDCLKP, JSR DTEBRK ;IF USING 11 FOR CLOCK, FIRST CHECK FOR CLOCK INTR +.ELSE JSR TTYBRK ;OTHERWISE JUST USING 11 FOR TTYS. + 0 ;UNUSED WORD +DTEPRO: 0 ;NO PROTECTED EXAMINES +DTERLO: 0 ;.. +DTEPRI: 0 ;NOR PROTECTED DEPOSITS +DTERLI: 0 ;.. + +LOC EPT+430 +REPEAT 8,MUUOEX ;HALT IF UUO IN PROCESSOR BREAK ROUTINES + +LOC EPTEBC +EPTEBC: 0 ? 0 ;EBOX COUNT FOR PROC BRK ROUTINES AND NULL JOB +EPTMBC: 0 ? 0 ;MBOX DITTO + +LOC TIMLOC + JSR OVHBRK ;INTERVAL TIMER INTERRUPT, EVERY 39 MILLISEC ON CHANNEL 1 + +;OVHMTR MACRO IS USED TO CONSTRUCT TABLE OF AREAS OF EXEC CORE TO BE METERED +;ON KL10 OVHBRK CHECKS WHERE THE PC IS IF IT IS IN EXEC MODE. + +DEFINE OVHMTR NAME ;NAME IS 3 CHARACTERS NAMING THE REGION THAT BEGINS HERE +OVHMT1 NAME,\. ;EVALUATE "." AT THIS POINT IN TIME +TERMIN + +;KLUDGE MACRO +DEFINE OVHMT1 NAME,POINT +OVHTAB [DEFINE OVHTAB FOO +FOO] <(SIXBIT/NAME/)>,,POINT ? 0 +TERMIN +TERMIN + +;THIS IS THE CORRESPONDING REMOTE MACRO +DEFINE OVHTAB FOO +FOO +TERMIN +] ;END OF IFN KL10P + +IFN KS10P,[ + +LOC EPTUIT+UBAQ + UBAQIB ; Pointer to interrupt table for Unibus Q (dsk) + +LOC EPTUIT+UBAI + UBAIIB ; Pointer to interrupt table for Unibus I (other) + +LOC EPTPFW +EPTPFW: 0 ; Page fail word +EPTPFO: 0 ; Page fail old PC +EPTPFN: PFAIL ; Page fail new PC + +IRP I,,[1,2,3,4,5,6,7] +LOC EPTP!I!W +EPTP!I!W: 0 ; Page fail word +EPTP!I!O: 0 ; Page fail old PC +EPTP!I!N: PF!I!AIL ; Page fail new PC at PI level I +TERMIN + +LOC EPTTR1 +EPTTR1: CAI ;ARITH OVERFLOW EXEC MODE IGNORED +EPTTR2: JSR ILLTRP ;PDL OVERFLOW EXEC MODE IS AN ERROR +EPTTR3: JSR ILLTRP ;TRAP 3 SHOULD NOT HAPPEN + +LOC EPT1PO +EPT1PO: 0 ;ONE-PROCEED OLD-PC +EPT1PN: MUUOEX ;ONE-PROCEED SHOULD NOT HAPPEN IN UPT=EPT MODE + +LOC EPTUEN +EPTUEN: MUUOEX ;HALT IF UUO IN PROCESSOR BREAK ROUTINES +EPTUET: MUUOEX +LOC EPTUUN +EPTUUN: MUUOEX +EPTUUT: MUUOEX + +IFN KSIMP,[ +;Here because with EPT at 0, this is the second half of physical +; page 0, which is uncached, which we want, and otherwise unused. +; +LOC EPT+1000 ; IMP data reformatting buffers +IMPIBF: BLOCK 400 +IMPBFS==.-IMPIBF +IMPOBF: BLOCK 400 +] + +;OVHMTR MACRO IS USED TO CONSTRUCT TABLE OF AREAS OF EXEC CORE TO BE METERED +;ON KS10 PC SAMPLING FACILITY IS USED, 60-CYCLE CLOCK COLLECTS THAT DATA +;NOTE THAT THE TABLE FORMAT IS NOT THE SAME AS ON KL10, FOR SPEED REASONS + +DEFINE OVHMTR NAME ;NAME IS 3 CHARACTERS NAMING THE REGION THAT BEGINS HERE +OVHMT1 NAME,\. ;EVALUATE "." AT THIS POINT IN TIME +TERMIN + +;KLUDGE MACRO +DEFINE OVHMT1 NAME,POINT +OVHTAB [DEFINE OVHTAB FOO +FOO] POINT,,<(SIXBIT/NAME/)> +TERMIN +TERMIN + +;THIS IS THE CORRESPONDING REMOTE MACRO +DEFINE OVHTAB FOO +FOO +TERMIN +] ;END OF IFN KS10P + +IFN DL10P,[ ;DL10 COMMUNICATIONS AREA IN NON-ENCACHED LOW CORE +IFN KL10P, LOC 500 ;500-777 RESERVED FOR DL10 AREA AND BUFFERS +IFN KA10P, LOC 100 ;IF KA10, PUT DL10 AREA JUST BELOW START OF SYSTEM +IFN KS10P, .ERR DL10 on KS10 system? + +DL10AR: JSR TTYBRK ;INTERRUPT INSTRUCTION (NOT ACTUALLY USED) + +;FOLLOWING LOCATIONS MUST AGREE WITH IOELEVEN PROGRAM + +DL10VR: NDLTYS_8+NFDLTY ;"I/O VERSION NUMBER" +DL10UP: 0 ;INCREMENTED BY -11 EVERY 1/60 SECOND. + ;SETOM'ED BY 10 EVERY 1/2 SECOND. DETECTS UP/DOWNNESS. + +DL10SO: 0 ;LINE # TO SET OUTPUT DONE FOR, SET BY -10, CLEARED BY -11. + +DL10IL: 0 ;LINE # WITH INPUT AVAILABLE. CLEARED BY -10 AFTER CHAR READ. +DL10IC: 0 ;CHARACTER RECEIVED FROM THAT LINE. + +DL10OD: 0 ;LINE # WITH OUTPUT DONE. CLEARED BY -10 WHEN PROCESSED. +DL10BS: 0 ;BUFFER SIZE FOR THAT LINE. + +DL10BP: 0 ;WIERD DL10 BYTE POINTER TO TTY OUTPUT BUFFER. +DL10CC: 0 ;NUMBER OF CHARACTERS BEING OUTPUT TO TTY. +DL10LN: 0 ;LINE # OUTPUT BEING SENT TO. CLEARED BY -11 WHEN GOBBLED. + +DL10CL: 0 ;DIALUP LINE CONNECT OR DISCONNECT INFO. SET BY 11, 0'D BY 10. + ;0000NN => LINE # NN DISCONNECTED. + ;01RTNN => LINE # NN CONNECTED, %TTISP=R, %TTOSP=T. + +DL10PL: 0 ;LINE # TO SET PARAMETERS OF. CLEARED BY -11 WHEN PROCESSED. +DL10PR: 0 ;VALUE OF DH11 LPR REGISTER. +DL10PS: 0 ;NUMBER OF BYTES OF OUTPUT BUFFERING DESIRED. + +DL10XD: 0 ;1=EXAMINE -11 CORE, 2=DEPOSIT. CLEARED BY -11 WHEN DONE. +DL10XA: 0 ;EXAMINE/DEPOSIT ADDRESS +DL10XW: 0 ;EXAMINE/DEPOSIT WORD + +GLPTBP: 0 ;BYTE POINTER TO BUFFER FOR GOULD LPT +GLPTBC: 0 ;BYTE COUNT " " - IF NONZERO BUFFER IS ACTIVE BY PDP11. +GLPTER: 0 ;NONZERO => PDP11 CLAIMS PRINTER IS BROKEN. +GLPGRF: 0 ;NONZERO => GRAPHICS MODE (SET BY 10). + +;CHAOS NET SHARED VARIABLES +DLCINI: 1 ;THE COMMENTS ARE IN THE CHAOS FILE +DLCSP1: 0 +DLCSP2: 0 +DLCSS1: 0 +DLCSS2: 0 +DLCRP1: 0 +DLCRP2: 0 +DLCRS1: 0 +DLCRS2: 0 + +;^ ADD MORE HERE + +DLXEND:: ;END OF ASSIGNED DL10 AREA + +IFG .-DL10AR-100, .ERR DL-10 AREA TOO BIG, CHANGE CONO IN TSS INITIALIZATION +LOC DL10AR+100 ;SKIP OVER 11-ACCESSIBLE AREA + +DL10BF: BLOCK <261.+3>/4 ;OUTPUT BUFFER, 8-BIT BYTES. HAS TO BE NON-ENCACHED. + +IFN GLPTP,[ +GLPBSZ==255. ;BUFFER SIZE IN WORDS. MAXIMUM POSSIBLE WITHOUT MODIFYING (ELIMINATING) + ;"WORD COUNT" HARDWARE IN DL-10. +GLPMPP: 0 ;MAIN PROGRAM POINTER - IF NONZERO BUFFER IS ACTIVE BY M.P. LEVEL (PDP10) +GLPMPC: 0 ;MAIN PROGRAM COUNTER +GLPTBF: BLOCK GLPBSZ ;ONE BUFFER FOR NOW +] ;END IFN GLPTP + +IFN KL10P, IFG .-1000,.ERR DL10 STORAGE TOO BIG, DOESN'T FIT IN UNENCACHED PAGE +IFN KA10P, PATB=. ;MOVE ORIGIN OF SYSTEM UP +] ;END IFN DL10P + +IFN NETYS,[ ;ASSEMBLE DTE20 CONTROL AREA +IFE KL10P, .ERR DTE20 WITHOUT KL10? +LOC 400 + +DTEVER: NETYS_8+NFETY ;400 I/O VERSION NUMBER, SET BY 10, CHECKED BY 11 + +DTECHK: 0 ;401 INCREMENTED BY 11 60 TIMES PER SECOND + ;SETOMED BY 10 EVERY HALF SECOND. + ;USED TO TELL 11 THAT 10 IS UP. + +DTEINP: -1 ;402 -1 IF IDLE, ELSE INPUT REQUEST FROM 10 TO 11 + ;SETUP DTEBPI IN EPT AND DO DATAO DTE, BEFORE SETTING THIS. + ;SEE COMMENTS BELOW DTEOUT FOR WHAT GOES HERE +DTEOUT: -1 ;403 -1 IF IDLE, ELSE OUTPUT REQUEST FROM 10 TO 11 + ;SETUP DTEBPO IN EPT BEFORE SETTING THIS. + ;CONTENTS OF DTEINP AND DTEOUT ARE DESCRIBED BELOW. + ;THESE ARE SET BY THE 10, SETOMED BY 11 WHEN TRANSFER STARTS. + ;RH # BYTES EXPECTED. LH COMMAND+LINE#. COMMANDS ARE: + %DCTYO==1000 ;TELETYPE OUTPUT (NOTE 4.1=0 INPUT, =1 OUTPUT) + %DCETI==2000 ;ETHERNET INPUT (N.Y.I.) + %DCETO==3000 ;ETHERNET OUTPUT (N.Y.I.) + +DTELSP: -1 ;404 LINE # WHOSE SPEED IS TO BE SET, SET BY 10, SETOMED BY 11 +DTELPR: -1 ;405 CORRESPONDING DH11 LINE PARAMETER REGISTER,,BUFFER SIZE + +DTEOST: -1 ;406 LINE# TO START OUTPUT ON (SET OUTPUT DONE). + ;SET BY 10, SETOMED BY 11 + + BLOCK 1 ;407 NOT USED + +DTETYI: -1 ;410 TELETYPE INPUT. SET BY 11, SETOMED BY 10. + ;LH LINE#,,RH CHAR RCVED. + +DTEODN: -1 ;411 TELETYPE OUTPUT DONE. SET BY 11, SETOMED BY 10. + ;LH LINE#,,RH BUFFER SIZE. + +DTEHNG: -1 ;412 HANGUP/DIALIN WORD. SET BY 11, SETOMED BY 10. + ;0000NN LINE # NN HUNG UP. + ;01RTNN LINE # NN HAS SPEED RCV=R, XMT=T (CODES AS IN TTYTYP) + +;^ ADD MORE LOCATIONS HERE, NOT TO EXCEED 437 + +;LOCATIONS 440-457 ARE KNOWN ABOUT BY BOTH IOELEV AND KLDCP, +;USED MOSTLY FOR NON-TIMESHARING PROGRAMS. +];NETYS + +LOC PATB + + ;FOR VARIABLES (MONITORABLE WITH KEYS) +NSKED: 0 ;# TIMES NON-NULL JOB IS RUN +NNSKED: 0 ;# TIMES NULL JOB IS RUN +NRSKED: 0 ;# OF FULL SCHEDULES (MUST SCAN ALL JOBS) +NSSKED: 0 ;# OF SCHEDULES SAVED BY SCHBLN FEATURE. +NRESKED:0 ;# TIMES A JOB SCHEDULED JUST AFTER IT RAN. +NSCHDU: 0 ;TOTAL NUMBER OF JOBS FOUND RUNNABLE IN FULL SCHEDULES +NNULBK: 0 ;# OF CONSECUTIVE BLOCKS OF NULLTIME. +NUINT: 0 ;# TIMES USER GIVEN INTERRUPT +NAUINT: 0 ;# ATTEMPTED USER INT (POSSIBLY UNSUCCESSFUL DUE TO PG FAULT) +NPCLSR: 0 ;# ATT TO PCLSR +NEPCLS: 0 ;# PCLSRS WHERE JOB WAS IN EXEC MODE +NFPCLS: 0 ;# OF PCLSRS THAT FAILED (JOB WAS IN EXEC MODE AND NOT BLOCKED) +NSOUSR: 0 ;# ATT TO SWAP OUT USR +NSOPGS: 0 ;# TIMES THRU LOOP LOOKING FOR PG TO SWAP OUT +NPGSO: 0 ;# TIMES AT SWOPG +NAGEAB: 0 ;# TIMES SWAP OUT ABORTED BY AGE BITS +NSHRAB: 0 ;# TIMES SWAP OUT ABORTED BY SHARING +NPGFLT: 0 ;# PAGE FAULT (ALL CAUSES) +NCLKI: 0 ;# CHNL 7 INTS (ALL CAUSES) +NPGLD: 0 ;# TIMES AT PGLDU +NUFLS: 0 ;# TIMES AT UFLS +NTUSB: 0 ;# TIMES USER SWAP BLOCKED +NTSBUP: 0 ;# TIMES SWAP BLOCKED USER TOOK PAGE FAULT AND LET IN +NTSBUB: 0 ;# TIMES SWAP BLOCKED USER TOOK PAGE FAULT AND BLOCKED +NTSBUU: 0 ;# TIMES SWAP BLOCKED USER UNBLOCKED BEFORE TIME (MEM APPARENTLY AVAIL) +NAGES: 0 ;# TIMES AROUND PAGE-AGEING LOOP + +;THE FOLLOWING FOUR MUST BE CONSECUTIVE +NRPI: 0 ;# REFS TO PAGE IN (BUT MAP WAS NOT SET UP, ETC) +NRPCI: 0 ;# PAGE FAULTS REFS TO PAGE COMMING IN +NRPO: 0 ;# REFS TO PAGE OUT +NRPGO: 0 ;# TO PAGES GOING OUT +CLKBRS: 0 ;CLKBRK COPIED INTO HERE (SINCE CLKBRK GETS CHANGED) + +PAT: IFG .-PATB-40,.ERR PAT TOO HIGH + +LOC PATB+40 + +BBLK + +PATCH: BLOCK 140 ;PATCH SPACE CODE AND CONSTANTS + +EBLK + +VPATCH: +VPAT: +BLOCK 40 ;PATCH SPACE VARIABLES + +SUBTTL PROCESSOR BREAK ROUTINES + +DEFINE CLKSAV BRK=CLKBRK +IFE KA10P, XCT CLCXSV ;DATAI PAG,CLCX(U) + XCT CLUSAV ;STORE U IN AC17S FOR CURRENT USER (UNLESS NULL JOB) + MOVE U,BRK ;SAVE AWAY BRK + MOVEM U,CLKBRS +IFSN BRK,CLKBRK, MOVEM U,CLKBRK ;SAVE IN CLKBRK IF NOT CLKBRK +TERMIN + +IFE KA10P,[ +DEFINE CLKLEV ;ENTER CLOCK-LEVEL CONTEXT + SPCCTX 0,1,EPT ;UPT = EPT; CLOCK LEVEL CONTEXT. + MOVE U,USER + JRST 2,@.+1 ;MAKE XCTR WORK RIGHT + %PSPCU,,.+1 + MOVE P,CPDLP +TERMIN +] ;IFE KA10P +IFN KA10P,[ +DEFINE CLKLEV + MOVE U,USER + MOVE P,CPDLP +TERMIN +] ;IFN KA10P + +IFN KL10P,[ ;CODE USED IF GETTING 60-CYCLE CLOCK FROM PDP11 (IN CASE MAIN CLOCK DOWN) + +;HACKING THE DTE: + +;THE TTY CODE ASSUMES, SINCE THE DTE20 IS USED BY ITS SOLELY AS +;THE INTERFACE TO THE CONSOLE TTY AND THE LINE-FREQUENCY CLOCK, +;THAT IT MAY FREELY GIVE THE "MONITOR TTY OUTPUT" COMMAND WHEN +;THE "MONITOR TTY OUTPUT DONE" INTERRUPT IS RECEIVED. ANY CODE +;WHICH HACKS THE DTE OTHER THAN AT PI LEVEL OR IN ITS INITIALIZATION +;MUST THEREFORE OBSERVE THE FOLLOWING PROTOCOL: +; CONO PI,DTEOFF +; SKIPN DTEFLG ;WAIT FOR MONITOR TTY OUTPUT TO GO THROUGH +; JRST .-1 +; SETZM DTEFLG +; ;HERE SET DTECMD +; CONO DTE,%DBL11 +; SKIPN DTEFLG ;WAIT FOR THIS COMMAND TO GO THROUGH +; JRST .-1 +; CONO PI,DTEON +; + +DTEBRK: 0 +BBLK + CONSO PI,1_<7-APRCHN> ;TEMPORARY (I HOPE) HARDWARE BUG IN KL10 PI HARDWARE + JRST 4,. ;ALLEGEDLY FIXED + CONO PI,TTYRQ ;REALLY WANTED TO INTERRUPT ON TTY CHANNEL, + JFCL ; BUT HAVE TO DO IT THIS WAY DUE TO + JFCL ; MISFEATURES IN THE PI HARDWARE + SKIPN DTECLK ;DON'T TAKE OUT THE JFCLS!! + JRST 12,@DTEBRK + CLKSAV DTEBRK ;TAKE CLOCK INTERRUPT + JRST CLKB2A +EBLK +];KL10P + +CLKBRK: 0 ;PC SAVED HERE BY JSR FOR CLOCK INT. + +BBLK +IFN KL10P,[ + CONSO PI,1_<7-APRCHN> ;HARDWARE BUG IN KL10 PI SYSTEM + JRST 4,. ;ALLEGEDLY FIXED +] +IFE KA10P, CONO PI,020000+200_<-APRCHN> ;BAG-BITING DEC LOSERS CHANGED + ;FUNCTIONAL SPECIFICATION OF + ;PROGRAMMED REQUESTS +CLKBR2: CLKSAV ;SAVE AC BLK STATUS AND U. +CLKB2A: AOS NCLKI + SKIPGE U,USER ;PICK UP INDEX OF CURRENT USER, SKIP UNLESS NULL JOB + JRST [ SPM UPGML ;JUMP IF NULL JOB WAS RUNNING + JRST CLKBKR ] + SPM UPGML(U) ;STORE PAGE MAP AWAY + AOSN UFLSF ;SKIP UNLESS GOT HERE FROM UFL6 + JRST CLUFLS + MOVEM T,AC16S(U) ;STORE AWAY T + MOVEI T,AC0S(U) + BLT T,AC15S(U) ;STORE REST OF ACS +CLKBKR: CLKLEV ;SET UP CROCK-LEVEL CONTEXT HARDWARE + +;;; CHECK FOR THINGS OTHER THAN CLOCK TICKS (PAR ERR, PG FAULT, NXM, PDLOV, +;;; AROV AND ARFOV ARE POSSIBLE ON ONE MACHINE OR THE OTHER). + +IFN KA10P,[ + CONSZ 270220 ;CHECK PDL OV, MEM PROTECT, NXM, FOV, AR OV + JRST CLKB1 ;JUMP ON LOSSAGE +CLKB1D: CONSZ PI,200000 + JRST CLKB1E ;PARITY +] ;KA10P + +IFN KL10P,[ + AOSG PFAILF + JRST PFA6 ;PAGE FAULT + CONSZ 7740 ;This is all but the cache sweep done bit (=20). + JRST CLKB2 ;APR ERROR INTERRUPT +] ;KL10P + +IFN KS10P,[ + AOSG PFAILF + JRST PFLU2 + CONSZ 7620 ;This is all but the interval timer's bit (=40). + JRST CLKBKS ; (Memory ECC (=100) doesn't interrupt) + CONSO 40 + JRST CLK1F +] ;KS10P + +IFN PDCLKP\KA10P,[ ;IF 60 HZ CLOCK IS IN HARDWARE + CONSO CLK,CLKINT + JRST CLK1F ;INTERRUPT NOT FROM CLOCK, MUST BE SPURIOUS (OR + ;PREEMPT) +] ;PDCLKP\KA10P + +;DROP THROUGH FOR PLAIN CLOCK-TICK. + ; +; 60-CYCLE CLOCK INTERRUPT +; +CLKTIC: +;IFN 340P, DATAI CLK1,LQTIM + SOSG @CLROOT ;COUNT DOWN, SKIP IF NOT YET TO NEXT REQUEST + JRST CLQBRK ;SERVICE CLOCK QUEUE REQUEST +CLQBRT: +IFN KS10P, CONO 020040+APRCHN ;Clear interval flag +IFN PDCLKP\KA10P, CONO CLK,CLKINT+APRCHN ;Clear hardware clock flag +IFE PDCLKP\KA10P\KS10P, SETZM DTECLK ;Clear software clock flag +IFN KA10P,[ + DATAI CLKBSW + SKIPGE CLKBSW +] ;KA10P +IFN KL10P, SKIPGE DTESWR +IFN KS10P, SKIPE 8SWIT0 + BUG DDT,[SWITCH 0 IS UP] +IFN KS10P, SETZM 8SWIT0 ; Allow hacker to P +IFN CHAOSP, IFN T11CHP, PUSHJ P,T11WAK ;RUN TEN-11 CHAOS NET INTERFACE +IFN XGP,[ + SKIPL XGPUSR + PUSHJ P,XGPCLK +] +IFN 340P,[ + AOSGE T,DTIME + JRST DSTPD ;WAIT IF DTIME CLOBERED DUE TO RATE EXCEEDED + CAILE T,2 + MOVEI T,2 + MOVEM T,DTIME + SKIPL CDISOF + SKIPGE DISOFF + JRST DSTPD + AOSG DISON + CONO DIS,1100\SDCHN_3\DISCHN ;RESTART DISPLAY +DSTPD: +] +IFN E.SP,[ + SKIPN T,E.SPGW ; E&S WAITING FOR PAGE + JRST E.SOK + HRRZM T,DISSPG ; SAVE FOR SWPPIN + SKIPL T,DISUSR ; -1 IMPLIES NO USER + MOVEM T,DISSWI ; USER INDEX FOR SWPPIN +E.SOK: +] +IFN N11TYS,[ + SKIPE @TT11HD ;ANY INPUT FROM PDP11? + PUSHJ P,TT11IN ;YES, DO INPUT INT LVL STUFF FOR IT,. +] +IFN DZ11P,[ + PUSHJ P,DZSCAN ;SCAN DZ'S FOR INPUT +] + MOVS T,TTERQS + CAIE T,(MOVE) + PUSHJ P,TTECH ;CHARACTERS TO BE ECHO ED +IFN NETP,[ + SKIPE STYNTA ;IF THERE ARE STY'S CONNECTED TO NETWORK I/O, + PUSHJ P,STYNTC ;XFER BETWEEN THEM. +] +IFN KS10P, PUSHJ P,OVHCLK + SETCMM CLKFL1 + SKIPL CLKFL1 + AOS TIME ;GET HERE EVERY THIRTIETH OF A SECOND +IFN PAGPRE,[ + SKIPE PREEMP ;CHECK FOR PRE-EMPTION INTERRUPT + JRST PRESCD +];PAGPRE + AOSG SCHFLG + JRST CLKB5 ;TIME NOT UP + AOS NLPCLK + JRST SCHED ;SCHEDULE + +CLK1F: +IFN PAGPRE,[ + SKIPE PREEMP ;CHECK FOR PRE-EMPTION INTERRUPT. THIS IS HERE + JRST PRESCD ; BECAUSE OF SCREW CASE WHEREBY DLSRCH PREVENTS + ; PREEMP FROM DOING ANYTHING, AND PREEMP WOULD + ; PREVENT CLOCK FLAG FROM GETTING CLEARED IF IT WAS + ; TESTED BEFORE CLOCK. +];PAGPRE +; MOVEI J,APRCHN ;DO NOT TAKE THESE OUT WITHOUT SEEING RG!!!! +; JSP E,SPUR +; JRST SCHED + AOS CHSPUR+APRCHN ;COUNT SPURIOUS INT + JRST SCHED ;(MIGHT HAVE BEEN RUNNING NULL JOB) + +IFN PAGPRE,[ +PRESCD: AOS NLPPRE + JRST SCHED +];PAGPRE + +IFN KL10P,[ +CLKB2: CONSZ 2000 ;NXM + PUSHJ P,MEMHNG + CONSZ 1040 ;POWER FAIL OR I/O PAGE FAIL + BUG HALT,[KL: POWER FAIL OR I/O PAGE FAIL] + CONSZ 300 ;CACHE DIR OR PT DIR PAR ERR. + BUG HALT,[KL: CACHE OR MAP DIR PAR ERR] + CONSO 4400 ;SBUS ERR OR MB PAR ERR + JRST SCHED ;CALLED MEMHNG, AND NOTHING ELSE => SCHEDULE. + SETOM PARRSN ;TEL PAR ERR SCANNER THIS IS AN INTERRUPT, NOT A PG FAIL. + RDERA PARERA ;STORE ADDR OF PAR ERR. + JRST CLKB1E +] ;IFN KL10P + +IFN KS10P,[ +CLKBKS: CONSZ 7600 ; Any bad guys? (8080 -> KS is 20, Interval is 40, + JRST CLKKS1 ; Memory ECC is 100.) + CONO 020020+APRCHN ; 8080 wants service. Clear the bit. + MOVEI I,NFKSTY ; TTY # (fancy name for 0) + CONO PI,TTYOFF ; Pretend this is TTY interrupt level. + SKIPN A,8CTYIN ; Any input from 8080? + JRST CLKKS2 + SETZM 8CTYIN ; Yes: Make room for more. + PUSHJ P,NTYI1 ; Stuff it into the tty. + MOVEI I,NFKSTY ; Just in case... +CLKKS2: SKIPN 8CTYOT ; Room for output yet? + PUSHJ P,TYPSC ; Yes: Get some now. + CONO PI,TTYON ; No: 8080 will wake us up later. + JRST SCHED ; Null job might have been running. + +CLKKS1: CONSZ 1000 ;Power failure + BUG HALT,[KS: POWER FAIL] + CONSZ 6000 ;KS -> 8080 or Flag 24 + BUG HALT,[KS: KS->8080 FLAG OR FLAG 24 SET] + CONSZ 400 ;NXM + PUSHJ P,MEMHNG + CONSO 200 ;Bad memory data + JRST SCHED + IORD B,[KSECCS] + MOVEM B,PARERA + JRST CLKB1E + +] ;IFN KS10P + +CLUFLS: CONO PI,CLKON ;FROM UFLS + CLKLEV + MOVE T,UPC(U) + MOVEM T,CLKBRK + AOS NUFLS + AOS NLPUFL + JRST SCHED2 + + ;CLOCK QUEUE SERVICE +CLQBRK: SKIPG U,CLROOT ;GET POINTER TO CURRENT BLOCK + BUG ;CLK QUEUE SCREWED + SKIPG T,1(U) ;GET POINTER TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + MOVEM T,CLROOT ;SET UP POINTER FOR NEXT BLOCK + SETOM 1(U) ;INDICATE CURRENT BLOCK IDLE + XCT 2(U) ;EXECUTE REQUEST (PROBABLY A JRST) + ;FALL THROUGH IF SINGLE INST RQ +CLQRET: ;RETURN FROM REQUEST + SKIPN @CLROOT ;SKIP IF TIME TILL NEXT RQ NONZERO + JRST CLQBRK ;ZERO TIME DELTA, DO NEXT RQ + JRST CLQBRT ;RETURN TO CLOCK ROUTINE + +CLQTTR: JUMPE TT,CLQRET ;COMMON RETURN FOR TT IDLE FLAG +CLQREE: MOVEI E,CLQRET ;RE ENTER RQ + +;CLOCK OFF OR IN PROGRESS LEVEL ADD TO CLOCK QUEUE, CALL BY JSP E, + ; T HAS TIME TILL RQ IN 60'THS + ; C POINTS TO THREE WORD BLOCK, RQ'ED INST IS IN THIRD +CLQPUT: MOVEI B,CLROOT-1 +CLQPU2: MOVE A,B ;REPLACE POINTER TO PREV BLOCK WITH CURRENT + SKIPG B,1(B) ;GET LINK TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + SUB T,(B) ;SUBTRACT TIME DELTA FOR NEXT BLOCK + JUMPG T,CLQPU2 ;JUMP IF RQ LATER THAN CURRENT BLOCK + JUMPE T,CLQPU6 ;JUMP IF RQ SAME AS " " (COULD USE PU2 BUT THIS FASTER) + ADD T,(B) ;RQ EARLIER, ADD BACK + MOVEM T,(C) ;SET DELTA OF BLOCK BEING ADDED + SUB T,(B) ;COMPUTE NEG OF DELTA FOR NEXT BLOCK + MOVNM T,(B) ;SET TIME DELTA FOR NEXT BLOCK + MOVEM B,1(C) ;SET LINK OF NEW BLOCK TO NEXT + MOVEM C,1(A) ;SET LINK OF PREV BLOCK TO NEW + JRST (E) + +CLQPU6: SETZM (C) ;SET TIME DELTA OF NEW BLOCK TO ZERO + MOVE A,1(B) ;GET POINTER TO NEXT BLOCK + MOVEM A,1(C) ;SET POINTER OF NEW TO NEXT BLOCK + MOVEM C,1(B) ;SET POINT OF CURRENT TO NEW BLOCK + JRST (E) + +;MAIN PROG LEVEL ADD TO CLOCK QUEUE +;CALL BY PUSHJ P,CLQADD +;WITH POINTER TO BLOCK IN NEXT WORD AND TIME TILL RQ IN T IN 60'THS +;POINTER TO BLOCK SHOULD NOT BE INDEXED BY C + +CLQAD1: MOVEI T,1 ;RQ IN ONE TICK +CLQADD: PUSH P,C + MOVE C,@-1(P) ;GET BLOCK POINTER + MOVEI C,@C + SKIPL 1(C) ;SKIP IF IDLE + JRST POPCJ1 ;IGNORE THIS RQ, BLOCK ALREADY ACTIVE + PUSH P,A + PUSH P,B + PUSH P,E + SKIPN (C) ;DELTA WORD OF IDLE BLOCK SHOULD BE ZERO + SKIPG T ;TIME SHOULD BE NON-ZERO + BUG ;CLK QUEUE SCREWED + CONO PI,CLKOFF + JSP E,CLQPUT ;ADD RQ +CLQDE4: CONO PI,CLKON + POP P,E + POP P,B + POP P,A + JRST POPCJ1 + +;DELETE CLOCK QUEUE ENTRY +;CALL BY PUSHJ P,CLQDEL WITH POINTER TO BLOCK IN NEXT WORD +CLQDEL: PUSH P,C + MOVE C,@-1(P) ;GET BLOCK POINTER + MOVEI C,@C + CONO PI,CLKOFF + SKIPGE 1(C) ;IGNORE RQ TO DELETE IF IDLE + JRST CKOCJ1 + PUSH P,A + PUSH P,B + PUSH P,E + JSP E,CLQCLR + JRST CLQDE4 + +CLQCLR: MOVEI B,CLROOT-1 ;CLOCK OFF OR IN PROGRESS VERSION +CLQDE2: MOVE A,B + SKIPG B,1(B) ;GET POINTER TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + CAME B,C ;SKIP IF FOUND BLOCK TO DELETE + JRST CLQDE2 + SKIPG B,1(B) ;GET POINTER TO BLOCK AFTER ONE TO DELETE + BUG ;CLK QUEUE SCREWED + MOVEM B,1(A) ;PATCH AROUND DELETED BLOCK + MOVE A,(C) + ADDM A,(B) ;ADD DELTA OF DELETED BLOCK TO NEXT + SETZM (C) ;CLEAR DEL + SETOM 1(C) ;MARK IDLE + JRST (E) + +OVHMTR PGF ;PAGE FAULT + +IFN KL10P,[ +EBLK +PFAILU: 0 ;SAVED U AS OF A PAGE FAILURE +PFINST: 0 ;PF INSTRUCTION IF XCT +PFOPC1: 0 ;SAVE PFOPC WHILE SWITCHING TO CLK LEVEL (PROTECT AGAINST XCTRI) +BBLK + +;PAGE FAULTS COME HERE, WITH PC IN PFOPC, AND PI SYSTEM TURNED OFF. + +PFAIL: MOVEM U,PFAILU + HLRZ U,EPTPFW + ANDI U,%PFCOD ;GET THE PFAIL CODE FROM THE PFW + CAIE U,%PFPAR + CAIN U,%PFPRX + JRST PFA2 ;IT'S A PAR ERR; BYPASS XCTR HACKS + MOVE U,PFOPC + TLNE U,%PCUSR + JRST PFA2 + LDB U,[331100,,(U)] ;GET OPCODE OF LOSING INSTRUCTION. + ;ASSUME THAT IN EXEC MODE VIRTUAL + ; AND PHYSICAL ADDRESSES ARE IDENTICAL + ; FOR INSTRUCTION FETCHES. ALSO ASSUME + ; THAT NOBODY DOES XCT OF XCT OF XCTR. +PFA4: CAIE U,XCTRI_-33 ;SKIP IF "XCTR WITH INHIBIT" + JRST PFA1 +REPEAT 2, AOS PFOPC ;ONCE COMPENSATING FOR INSTR ABORT, AND ONCE TO SKIP + MOVE U,PFAILU + JRST 17,@PFOPC ;KL-10 CROCK: JRST 17, TURNS ON PI SYSTEM + +PFA1: CAIE U,XCTR_-33 ;SKIP IF "XCTR WITH NO INHIBIT" + JRST PFA3 +PFA2: CONSO PI,77400 ;PI IN PROGRESS? + CONSO PI,1 ;CHANNEL 7 ENABLED? + BUG AWFUL,[PAGE FAULT WITH PI IN PROGRESS OR CLKOFF] + SKIPGE USER + BUG AWFUL,[PAGE FAULT IN NULL JOB] + MOVE U,PFOPC + MOVEM U,PFOPC1 + MOVE U,PFAILU ;RESTORE U SO CLKSAV CAN RE-SAVE IT +TPFLT1: SETOM PFAILF + CONO PI,CLKRQ ;CAUSE CLK BREAK AND PI SYSTEM ON + JRST . ;TAKES A WHILE TO GO OFF + +;COME BACK HERE PI IN PROGRESS ON CLK CHANNEL +PFA6: MOVE T,PFOPC1 + MOVEM T,CLKBRK ;SAVE PC AS OF PAGE FAULT AS PLACE INTERRUPTED FROM + AOSN PFAILF ;IF INTERRUPTED FROM INTPFL, + JRST PFA9 ; PC DOESN'T POINT TO FAULTING INSTRUCTION + TLNE T,%PSUSR ;MAYBE SPURIOUS MPV ON IOT IN USER MODE? + TLNE T,%PSUIO + JRST PFA9 ;CAN'T BE, I/O IS LEGAL + HLRZ TT,UPFW(U) + ANDI TT,%PFCOD + CAIE TT,%PFPNA ;CAN'T BE IF PAGE FAULT IS REALLY SOME OTHER RANDOM BREAK + CAIN TT,%PFILW ;SUCH AS A PARITY ERROR + JRST PFA11 +PFA9: +; MOVE T,PFOPC +; MOVEM T,UPOPC(U) ;SOLELY FOR THE .OPC USER VARIABLE + LDB E,[$PFPNO,,UPFW(U)] ;FAILING PAGE NO + HLRZ D,UPFW(U) + ANDI D,%PFCOD ;GET THE PAGE-FAULT CODE. + MOVEI A,0 ;INIT USER INT BITS + CAIE D,%PFPNA + CAIN D,%PFILW + JRST PFA5 ;REAL PAGE FAULT OR RWF + CAIN D,%PFMAR + JRST PFA7A + CAIN D,%PFPRO + JRST PFA7 ;OTHER RANDOM BREAKS + CAIE D,%PFPAR + CAIN D,%PFPRX + JRST PFA14 ;PARITY ERROR + MOVSI D,SCLBPF ;UNKNOWN PFW, GET SYSTEM JOB TO BARF ABOUT IT + TDNE D,SUPCOR + BUG PAUSE,[BAD PAGE FAIL WORD ],OCT,BPFPFW ;LOSING IN REAL TIME + IORM D,SUPCOR + AOS BPFERR + MOVEM U,BPFUSR + MOVE D,UPFW(U) + MOVEM D,BPFPFW + MOVE D,CLKBRK + MOVEM D,BPFPC + JRST SCHED ;IGNORE THE FAULT (BUT DO A FULL SCHEDULE SO SYS JOB WAKES) + +PFA14: SETZM PARRSN ;SAY THIS IS PAR ERR TRAP, NOT PAR ERR INTERRUPT. + MOVE D,UPFW(U) + MOVEM D,PARPFW ;SAVE PFW OF PAR ERR FOR ERROR MESSAGE + AC7CTX ;SELECT AC BLOCK 7, USED BY UCODE. + UMOVE D,0 ;SAVE THE AC THAT HOLDS THE BAD WORD + MOVEM D,PARWRD + SYSCTX ;AND RESET THE DATAO PAG TO NORMAL VALUE + JRST CLKB1E ;GO SCAN FOR THE ERROR. + +PFA3: CAIE U,XCT_-33 + BUG HALT,[PAGE FAULT IN SYSTEM AT ],OCT,PFOPC ;BARF! + MOVE U,@PFOPC ;QUUX! LET ONE LEVEL OF XCT WIN + MOVEM U,PFINST + MOVE U,PFAILU + LDB U,[331100,,@PFINST] + JRST PFA4 + +PFA11: XCTRI XR,[MOVE T,(T)] ;GET INSTRUCTION IN WHICH PAGE FAIL OCCURRED + TLCA T,700000 ;AND CHECK HIGH THREE BITS OF OPCODE + JRST PFA9 ;JUMP IF FAULT WAS ON INSTRUCTION FETCH + TLCE T,700000 + JRST PFA12 ;JUMP IF INSTRUCTION NOT AN IOT +PFA13: MOVSI TT,(HRRI T,) + DPB T,[2700,,TT] + XCTRI XEA,TT ;COMPUTE ITS EFFECTIVE ADDRESS + TLZA T,37 ;CLEAR @+XR, BUT LEAVE OPCODE AND AC + JRST PFA9 ;JUMP IF FAULT ON INDIRECT WORD + MOVEM T,MUUODP(U) ;IT WAS A SPURIOUS MPV, SO + MOVE T,CLKBRK ; SIMULATE TRAPPING AS A UUO + HRRI T,1(T) + MOVEM T,XUUOH(U) ;STORE OLD PC + MOVE T,CLCX(U) + MOVEM T,MUUOCX(U) ;AND OLD CONTEXT + MOVE T,MUUOCN(U) + MOVEM T,CLKBRK ;GET NEW PC + JRST CLKB5 ;AND RESTART USER AT UUOH0 + +PFA12: TLNN T,700000 ;MAYBE AN INSTRUCTION OVERLAYED ON AN MUUO, E.G. LPMR + TLNN T,040000 ;OPCODES 040-077 QUALIFY. + TLCA T,(XCT) + JRST PFA13 ;YUP. + TLNE T,777000 ;SKIP IF OPCODE WAS XCT + JRST PFA9 +; TLZ T,777740 +; TLO T,(MOVEI T,) +;Following instruction is suspected of not working (sometimes using wrong AC block) +; XCTRI XEA,T ;COMP EFFECTIVE ADDRESS OF XCT IN USER CONTEXT +;; JRST PFA11 ;AND GO PROCESS INSTRUCTION AT THAT ADDRESS +; JRST [ MOVEM T,TRMNAM(U) ;TEMPORARY FOR DEBUGGING +; JRST PFA11 ] +; JRST PFA9 ;HERE IF FAULT WAS IN INDIRECT CYCLE +;Replacement code: +PFA15: DATAI PAG,TT ;HMM, SEE IF WRONG AC BLOCK SELECTED + TLNN TT,100 + BUG + LDB TT,[220400,,T] ;CHECK FOR NEED TO SIMULATE INDEXING + JUMPE TT,PFA16 + UMOVE TT,(TT) + ADD TT,T + HRR T,TT +PFA16: TLNN T,(@) ;CHECK FOR NEED TO SIMULATE INDIRECT + JRST PFA11 + XCTRI XR,[MOVE T,(T)] + JRST PFA15 ;PROCESS INDIRECT WORD + JRST PFA9 ;TAKE FAULT ON INDIRECT WORD +;End replacement code. +];KL10P + +IFN KS10P,[ + +EBLK + +IRP I,,[1,2,3,4,5,6,7] +PF!I!SVU: 0 ;Saved U at PI level I page fail +PF!I!SVT: 0 ;Saved T at PI level I page fail +PF!I!INS: 0 ;Instruction at PI level I page fail +TERMIN +IFN .-PF1SVU-21., .ERR Wrong length PFXSVU block. + +BBLK + +IRP I,,[1,2,3,4,5,6,7] +PF!I!AIL: ;;PI level I page fail comes here. + MOVEM T,PF!I!SVT ;Save T + MOVEM U,PF!I!SVU ;Save U + JSP U,PIFAIL ;Set up U and join common code +TERMIN +IFN .-PF1AIL-21., .ERR Wrong length PFXAIL block. +PFXSVT==:0,,> +PFXINS==:0,,> +PFXWRD==:0,,> +PFXOPC==:0,,> + +PIFAIL: MOVE T,PFXWRD(U) ;Check page fail word + TLNE T,%PFNXI + BUG AWFUL,[NON-EX IO REG WITH PI IN PROGRESS ],OCT,PFXWRD(U),[PC=],OCT,PFXOPC(U) + TLNE T,%PFNXM\%PFPAR + BUG AWFUL,[NXM OR PARITY ERROR WITH PI IN PROGRESS] + MOVE T,PFXOPC(U) ;Check for user mode. + TLNE T,%PSUSR + BUG AWFUL,[PAGE FAULT IN USER MODE WITH PI IN PROGRESS] + SKIPA T,(T) ;We assume that it wasn't the instruction + ;fetch itself that caused the fault. +PIFL2: MOVEI U,PF7AIL-PF7XCT(U) ;Correct U on return from PFXXCT + MOVEM T,PFXINS(U) ;Save instruction that caused fault + LSH T,-33 ;Look at opcode + CAIE T,XCTRI_-33 ;XCTRI gets special treatment: + JRST PIFL1 +REPEAT 2, AOS PFXOPC(U) ;Arrange for it to skip. + JRST PFXRET(U) ;And return. + +IRP I,,[1,2,3,4,5,6,7] +PF!I!RET: + MOVE T,PF!I!SVT ;Restore T + MOVE U,PF!I!SVU ;Restore U + JRST 2,@EPTP!I!O ;Return +TERMIN +IFN .-PF1RET-21., .ERR Wrong length PFXRET block. +PFXRET==:0,,> + +;;;Let XCT chains that end in XCTRI win. We assume that none of the +;;;fetches along the way to the XCTRI itself caused the fault. +PIFL1: CAIE T,XCT_-33 + BUG AWFUL,[PAGE FAULT WITH PI IN PROGRESS] + MOVE T,PFXSVT(U) ;Restore T + JRST PFXXCT(U) ;Go pick up word XCT'ed + +IRP I,,[1,2,3,4,5,6,7] +PF!I!XCT: + MOVE U,PF!I!SVU ;Restore U + MOVE T,@PF!I!INS ;Pick up XCTed instruction + JSP U,PIFL2 ;Set up U again and rejoin common code +TERMIN +IFN .-PF1XCT-21., .ERR Wrong length PFXXCT block. +PFXXCT==:0,,> + +EBLK + +PFLCLK: 0 ; Did page fault happen with CLKOFF? +PFLSVU: 0 ; Saved U during page fail +PFLSVT: 0 ; Saved T during page fail +PFLINS: 0 ; Faulting instruction + +BBLK + +;;; Note! +;;; If we are swapped out while running with Exec mode PC between PFAIL and +;;; PFAILE inclusive, EPTPFO is saved as our PC. (There are actually only +;;; a few PC's for which this is possible given that we mostly run CLKOFF.) + +PFAIL: SETZM PFLCLK + CONSO PI,1 + SETOM PFLCLK + CONO PI,CLKOFF ; Don't bother me + MOVEM U,PFLSVU ; Save U + MOVEM T,PFLSVT ; Save T + SKIPGE U,USER + BUG AWFUL,[PAGE FAULT IN NULL JOB] + MOVE T,EPTPFW ; Get the explanation + MOVEM T,UPFW(U) ; Save it for others + MOVE U,PFLSVU ; Restore U, only needed it for a moment. + TLNE T,%PFNXM\%PFPAR ; Bad stuff should interrupt us, right? + BUG AWFUL,[NXM OR PARITY ERROR DIDN'T INTERRUPT] + MOVE T,EPTPFO + TLNE T,%PSUSR ; In Exec mode? + JRST PFLUSR + MOVE T,(T) ; We assume that it wasn't the instruction + ; fetch itself that caused the fault. +PFLOOP: MOVEM T,PFLINS ; Save instruction that caused fault. + LSH T,-33 ; Check opcode for XCTRI + CAIN T,XCTRI_-33 ; Should we skip? + JRST PFLSKP + CAIN T,XCTR_-33 ; Touching user address? + JRST PFLUSR + CAIE T,UMOVE_-33 ; These guys are just like XCTR + CAIN T,UMOVEM_-33 + JRST PFLUSR + ;; Let XCT chains win. We assume that none of the fetches along + ;; the way caused the fault. + CAIE T,XCT_-33 + BUG HALT,[PAGE FAULT IN SYSTEM AT],OCT,EPTPFO + MOVE T,PFLSVT ; Restore T for a moment + MOVE T,@PFLINS ; Pick up XCTed instruction + JRST PFLOOP + +;;; Come here to cause faulting instruction to skip. +PFLSKP: MOVE T,PFLSVT ; Restore T +REPEAT 2, AOS EPTPFO + SKIPL PFLCLK ; Unless clock was already off + CONO PI,CLKON ; turn it back on +PFAILE: JRST 2,@EPTPFO + +;;; Come here on NXI error. +PFLNXI: + +;;; We come here when the page fault is "soft" and it happened in user mode +;;; or while using XCTR, UMOVE, or UMOVEM. +PFLUSR: MOVE T,EPTPFW + TLNN T,%PFNXI ; Non-existent IO Register? + JRST PFLU1 ; Nope + MOVE T,EPTPFO + TLNE T,%PSUSR ; NXI in User IOT mode is not fatal. + TLNN T,%PSUIO + BUG AWFUL,[NON-EX IO REG ],OCT,EPTPFW,[PC=],OCT,EPTPFO +PFLU1: MOVE T,PFLSVT ; Restore T + SKIPGE PFLCLK ; Check for lossage + BUG AWFUL,[PAGE FAULT WITH CLKOFF AT],OCT,EPTPFO +TPFLT1: SETOM PFAILF ; Cause CLK level to go to PFLU2 +CCLKRQ: CONO PI,CLKRQ + JRST . ; Takes a while to go off... + +;;;CLKBRK comes back here at CLK level. +PFLU2: MOVE T,EPTPFO + MOVEM T,CLKBRK ;Save PC of page fault as place interrupted + ;from. + LDB E,[$PFPNO,,UPFW(U)] ;E: Virtual page number + HLRZ D,UPFW(U) + ANDI D,%PFNXI\%PFWRT\%PF2.9\%PF2.8 ;D: Page fault code + MOVEI A,0 ;A: User interrupt bits + TRNE D,%PFNXI ;NXI in User IOT mode. + JRST PFA7A + +;Drops through into PFA5 + +] ;KS10P + +IFN KA10P,[ +CLKB1: MOVE T,CLKBRK + CONSZ 200 + JRST CLKFO1 ;FLOATING OVERFLOW ENABLED +CLKFO2: CONSZ 20 ;SKIP IF AR OV INT NOT ENABLED + CONSO 10 ;OV ENABLED, SKIP IF OV + CONSZ 270000 ;NOT OV, CHECK PDL OV, MEM PROTECT, NXM + JRST CLKB1C ;PDL OV, NXM, ETC + JRST CLKB1D ;ONLY CLOCK BREAK, AR OV JUST ENABLED + +CLKFO1: CONSO 100 ;SKIP ON FLOATING OVERFLOW + JRST CLKFO2 ;NOT REALLY FLOATING OVERFLOW +CLKB1C: JUMPL U,CNLJL ;NULL JOB LOST + MOVEI A,0 ;SET UP INTERRUPT BITS FOR USER + CONSZ 20 ;SKIP IF OV NOT ENABLED + CONSO 10 ;OV ENABLED, SKIP ON OV + JRST CLB1A ;NOT AROV + PUSHJ P,AROV +CLB1A: CONSZ 200 ;SKIP IF FL OV NOT ENABLED + CONSO 100 ;FL OV ENABLED, SKIP ON FL OV + JRST CLB1B ;NOT FLOATING OVERFLOW + PUSHJ P,ARFOV +CLB1B: CONSO 270000 ;SKIP IF PDL OV, NXM, OR MEM PROTECT + JRST CLB1X + CONSZ 10000 ;NON EX MEM + PUSHJ P,MEMHNG + CONSO 200000 + JRST CLKB1H + TRO A,%PIPDL ;PDL OVFLO + TLNN T,%PCUSR ;SKIP IF IN USER MODE + BUG HALT,[PDL OVERFLOW IN EXEC MODE] +CLKB1H: CONSO 20000 ;MEM PROTECT + JRST CLKB1G + HLLZ D,UPQUAN(U) ;PICK UP FAULT BITS + TLNE D,1000 + TLNN D,770 ;ALL CONDITIONS WHICH ABORT INSTRUCTION + JRST CLKB1J ;(PLUS PAGE NXM FOR RANDOMNESS) + TRZ A,%PIPDL ;INSTRUCTION ABORTED, DON'T SET PDL OV + HLLZ T,UPOPC(U) + LSH T,5 + HRR T,UPOPC(U) ;FIX UP OPC + MOVEM T,CLKBRK ;RESET PC FROM OPC + AOS NPGFLT + HLRZ E,UPJPC(U) ;GET VIRTUAL PAGE # (LH OF JPC) + TRNN E,400 + JRST CFHFPF + ANDI E,377 ;FLUSH AGE ETC +] ;KA10P + ;DROP THROUGH INTO PFA5 + +IFE KA10P,[ +PFA5: AOS NPGFLT +] ;IFE KA10P + MOVE TT,LUMPS + HRRZ W,USER +IFN KA10P,[ + TLNE D,320 ;SKIP IF REALLY PAGE FAULT + JRST CFH4 ;OTHERWISE WRITE IN READ ONLY OR EXECUTING IMPURE PAGE +] ;KA10P + +;COME HERE WITH +; A BITS FOR USER'S PIRQC +; D PAGE FAULT BITS OR CODE +; E VIRTUAL PAGE NUMBER OF PAGE FAILURE +; TT THE UMAPS SETTING +;THE MYSTERIES OF W: +; RH IS A USER INDEX +; LH 0 => NORMAL PAGE FAULT +; NON0 => SWAP IN REQUEST FOR OTHER REASON. D,TT SHOULD BE 0. +; SPECIFICALLY, +; 4.9 => DMA DEVICE SWAP-IN, SEE SWIRQB, SWPPIN +; 4.8 => FROM SCHEDULER, TO GIVE INTERRUPT (?) THIS IS NO LONGER USED, +; PROBABLY. +; 4.7 => FROM CFHAHD, TO PAGE AHEAD. THIS IS ONE LEVEL OF RECURSIVE +; USE OF CFHSW1. +; FOR A NORMAL PAGE FAULT, THE USER PC IS IN CLKBRK. + +CFHSW1: HRRZM E,CFHUVP ;USER'S VIRTUAL PAGE NUMBER + TRZN E,200 + JRST CFH1 + MOVEI C,UPGCPH(W) ;VIRTUAL ADDRESS IN USER'S HIGH SEG + TLNN TT,%UMMPU ;IS MY UPPER NORMAL? + JRST CFH2 ;YES, USE MY UPPER CPB + MOVEI C,UPGCPH(TT) ;NO, TRY HIS UPPER. + TLNE TT,%UMUTL ;IS MY UPPER GOING TO HIS LOWER? + MOVEI C,UPGCP(TT) ;YES, TRY HIS LOWER. + JRST CFH2 + +CFH1: MOVEI C,UPGCP(W) ;VIRT ADDRESS IN USER'S LOW SEG + TLNN TT,%UMMPL + JRST CFH2 ;MY LOWER DBR NOT HACKED + MOVEI C,UPGCP(TT) + TLNE TT,%UMLTU ;WAS MY LOWER HACKED TO POINT TO UPPER? + MOVEI C,UPGCPH(TT) ;YES. +CFH2: ROT E,-1 + ADD C,E + HRLI C,222200 + SKIPGE E + HRLI C,2200 + MOVE T,C ;CALCULATE MAP ENTRY B.P. FROM CIRC PTR B.P. + ADD T,[(200000-2000)UPGMP-UPGCP] + LDB E,C ;CIRC MEM USE POINTER FOR PAGE FAULT + JUMPE E,CFH4 ;ADDRESS IS IN REAL ILM + CAIN E,-1 + JRST CFH4 ;ON REFERENCE TO ABS PAGE ALSO ILM +IFN KL10P,[ CAIE D,%PFILW + JRST CFHW1 + LDB I,T + JRST .+1(I) + BUG ;? + JRST CFH4 ;WRITE IN READ ONLY? + JRST CFHRWF ;READ WRITE FIRST + BUG ;? +] ;KL10P +IFN KS10P,[ CAIN D,%PFWRT\%PF2.8 ;WRITE IN READ ONLY + JRST CFH4 + CAIN D,%PFWRT\%PF2.9 ;READ WRITE FIRST + JRST CFHRWF + TRNE D,%PF2.8\%PF2.9 ;PAGE NOT IN MAP + BUG HALT,[BOGUS PAGE FAIL CODE] +] ;KS10P +IFN KA10P,[ + TLNE D,40 + JRST CFHRWF +] ;KA10P +;REFERENCE TO PAGE WITH NO ACCESS IN MAP. +CFHW1: SKIPGE RPCL(W) + JUMPGE W,CFF1 ;BEING RPCLSRED? + MOVEM A,CFHAS + AOSE CIRPSW + JRST CFH5 ;CIRPSW NOT AVAILABLE + TRZE E,400000 + TRNE E,200000 + JRST CFHSW3 + CAML E,MMPMX + BUG ;MMP OUT OF RANGE + MOVE C,E ;CIRC PNTR ALREADY POINTS TO MMP + ADD C,MMPEAD + JRST CFHSW4 + +CFHSW3: PUSHJ P,UCPRL ;FIND MMP + 200000,,.+2 + BUG ;NONE? + SUB P,[4,,4] +CFHSW4: LDB D,[410200,,(C)] ;TWO BITS OF MMP ENTRY GIVES DISPOSITION OF PAGE + AOS NRPI(D) + JRST @CFHDT(D) + +CFHDT: CFHPI ;IN + CFHPCI ;COMING IN + CFHPO ;OUT + CFHPGO ;GOING OUT + +;PAGE FAULT IN JOB BEING PCLSR'D. +CFF1: MOVE C,CLKBRK + TLNE C,%PCUSR + BUG ;BEING RPCLSRED IN USER MODE +IFN KA10P,[ + MOVSI D,1770 + ANDCAM D,UPQUAN(W) ;CLR PG FLT + LPMR UPGML(W) + CONO 470000+APRCHN ;CLR PDL OV + QT OV + MPV + NXM +] ;KA10P + MOVE T,[BADBTS] + IOR T,MSKST(W) + AND T,A + IORM T,PIRQC(W) +IFE KA10P,[ + MOVE T,CLCX(W) ;RESTORE UPT BUT NOT ACS + HRLI T,300000 + DATAO PAG,T +] ;IFE KA10P + CONO PI,CLKOFF ;GO ALLOW SELF TO GET RPCLSRED + JRST 10,UFL1 ;GO INTO UFLS WITH CLK OFF RATHER THAN + ;IN PROGRESS + +CFHRWF: ;HANDLE "WRITE IN READ-WRITE-FIRST PAGE" PAGE FAULT. +IFN KA10P,[ + TLNE D,10 + JRST CFHW1 ;SOMETIMES NO ACCESS SEEMS TO BE ON TOO + LDB I,T + CAIE I,2 + BUG ;GOT "WRITE IN R-W-F PAGE" BUT PAGE ISN'T R-W-F. +] ;KA10P + MOVEI I,3 + DPB I,T + MOVEM A,CFHAS + JRST CFHX1 + +;; EXIT FROM PAGE FAULT HANDLING FOR NON-ERROR FAULT. +;; C SHOULD CONTAIN 0 IF CAN CONTINUE NOW, OR A FLSINS TO WAIT WITH. +;; A SHOULD CONTAIN -1 IF FAULT HANDLED SUCCESFULLY (PAGE IN OR ON ITS WAY), ELSE 0. +CFHX: SETOM CIRPSW + TLNN W,200000 + JUMPL W,CPOPJ +CFH5A: JUMPE C,CFHX1 ;IF NOT GOING TO WAIT, SKIP NPGWTU CODE + MOVSI D,%SWPGW + IORM D,USWST(W) ;WAITING FOR PAGE + AOS NPGWTU ;KEEP COUNT OF USERS WAITING FOR A PAGE + SKIPN FLSINS(W) + MOVEM C,FLSINS(W) + SKIPE FLSINS(W) + CLEARM DLSRCH +CFHX1: MOVE A,CFHAS +IFN KA10P, MOVSI D,1770 ;CLEAR FAULT STATUS BITS + MOVE U,USER + JRST CFH6 + +;; WAIT FOR CIRPSW TO BE AVAILABLE. +CFH5: SETZ A, + JUMPL W,CPOPJ + MOVE C,[SKIPL CIRPSW] + AOS NLPPGC + JRST CFH5A + +;PAGE FAULT ON PAGE THAT'S REALLY IN CORE. +CFHPI: PUSHJ P,CFHAHC ;SEE IF WE WANT PAGE-AHEAD OR PAGE-BEHIND. + MOVSI D,MMPPGA + TDNE D,(C) + AOS NPGAHR ;COUNT NUMBER OF PAGED-AHEAD PAGES ACTUALLY USED. + ANDCAB D,(C) + MOVSI D,MMPPGB + TDNE D,(C) + AOS NPGBHR ;COUNT NUMBER OF PAGES AGED BY PAGE-BEHIND WHICH WERE USED AGAIN. + ANDCAB D,(C) + HRLI C,2200 + PUSH P,C ;SAVE MMP ENTRY ADDRESS FOR PPIUM. + PUSHJ P,UCPRL + 100000,,.+2 ;RETURN ON MEMPNT + BUG ;NO MEMORY LINKED IN? + SUB P,[4,,4] ;FIND MEMBLT INDEX + POP P,C + TLNE D,MMPBAD ;WAS THIS PAGE RECENTLY A PAR ERR VICTIM? + JRST CFHPB ;YES; READ IT BACK OFF THE DISK IF POSSIBLE. +IFN E.SP,[ + JUMPGE W,E.SBAR ;IF NOT CALLED FROM SWPPIN + HRRZ H,DISUSR ;CHECK TO SEE IF SERVICING E&S + CAIN H,(W) ;NOT DISPLAY, THEN SKIP + PUSHJ P,E.SPGI ;ELSE TIE DOWN PAGE +E.SBAR: +] + MOVE A,T + HLLZS MMSWP(A) ;CLEAR LENGTH OF CIRC LIST (BUT NOT EXEC PGS COUNT) + MOVE D,C + HRLI D,(TDNE T,) + PUSHJ P,PPIUM ;PUT PAGE INTO USERS' MAPS +IFN E.SP,SETZM E.SPGH ; CLEAR QSWI1 FLAG + MOVEI C,0 + MOVNI A,1 + JRST CFHX + +;COME HERE FOR PAGE WHICH SEEMS TO BE IN CORE, BUT HAD A PAR ERR RECENTLY. +;"SWAP IT OUT", SO IF IT'S PURE IT WILL JUST BE READ BACK FROM DISK. +CFHPB: PUSH P,W + MOVE A,T + SETOM CIRPSW ;UNLOCK, SO SWPOPG CAN RE-LOCK. + MOVE C,USER ;TELL SWPOPG WHICH JOB SHOULDN'T BE PCLSR'ED. + PUSHJ P,SWPOPL ;"SWAP OUT" THE PAGE (EVEN IF LOCKED DOWN) + JRST [ POP P,W ;FAILED TO GO OUT. COULD BE EXEC PAGE POINTING TO IT, + SETZ A, ;OR A JOB THAT CAN'T BE PCLSRED RIGHT NOW. + MOVSI C,(CAIA) ;WAIT A LITTLE AND TRY AGAIN (HOPE FOR THE BEST) + JRST CFHX ] + POP P,W + AOSE CIRPSW ;SWPOPG UNLOCKS; RE-LOCK. + JRST CFH5 ;OR ELSE GO INTO PAGE-WAIT TILL CIRPSW FREE. + MOVE C,SWOMMP + JRST CFHSW4 ;TRY AGAIN TO REFERENCE PAGE, SWAPPING IT BACK IN. + +;ON A RANDOM PAGE FAULT, SEE IF WE WANT PAGE-AHEAD OR PAGE-BEHIND. +;ASSUMES W SET UP AS FOR CFHSW1, AND TT +CFHAHC: MOVE D,CFHUVP ;GET USER'S VIRTUAL PAGE NUMBER. + TLNN W,-1 ;PAGE AHEAD ONLY FOR NORMAL PAGE FAULT (SO PC IS IN CLKBRK). + SKIPN PAGAHD(W) ;IS PAGE-AHEAD WANTED FOR THIS JOB? + POPJ P, + MOVSI T,%UMMPU + TRNN D,200 + MOVSI T,%UMMPL + TDNE TT,T ;NO PAGE-AHEAD ON PAGE NOT MAPPED NORMALLY. + POPJ P, + HLRZ H,PAGRAN(W) + HRRZ T,PAGRAN(W) + CAML D,H ;IS PAGE IN RANGE FOR AUTOMATIC PAGE-AHEAD? + CAML D,T ;IF SO, GO DO IT. + POPJ P, + PUSH P,C + PUSHJ P,CFHAHD + POP P,C + POPJ P, + +;AUTOMATIC PAGE-AHEAD AND PAGE-BEHIND. +;WHEN PAGE N IS PUT INTO THE MAP, PAGE N+1 IS SWAPPED IN +;AND PAGE N-1 IS SWAPPED OUT. +;(ACTUALLY, 1 IS A PARAMETER, IN THE PAGAHD VARIABLE) +CFHAHD: PUSH P,CFHUVP +;LOOP, REQUESTING SWAP-IN FOR THE NEXT N PAGES. E HAS PAGE NUMBER TO SWAP IN. +CFHAH1: MOVE E,CFHUVP + HLRE A,PAGAHD(W) + MOVE T,A + ADD A,(P) + CAMN A,E ;DETECT END OF LOOP. + JRST CFHAH2 + SKIPL T ;ELSE INCREMENT OR DECREMENT PAGE NUMBER. + AOSA E + SOS E + PUSHJ P,CFHRNG ;IS PAGE NUMBER IN RANGE FOR PAGE-AHEAD? + JRST CFHAH2 + PUSH P,W + HRLI W,500000 ;PAGE AHEAD THE PAGE. 100000 MEANS PAGE-AHEAD. + SETZB D,TT + SETOM CIRPSW ;ALLOW CFHSW1 TO LOCK CIRPSW. + PUSH P,CFHAS + PUSHJ P,CFHSW1 + POP P,CFHAS + SETZM CIRPSW ;BUT REALLY IT'S ALREADY LOCKED SO KEEP IT SO. + POP P,W + SKIPN A + AOS NPGAH1 ;COUNT NUMBER OF TIMES AN ATTEMPT FAILS. + JRST CFHAH1 + +;NOW IT'S TIME FOR PAGE-BEHIND. E HAS PAGE NUMBER TO SWAP OUT. +CFHAH2: MOVE E,(P) +;???? IS THERE ANY NEED TO PRESERVE U, EVER, INSIDE CFHSW1? + PUSH P,U + HRRE A,PAGAHD(W) ;GET PAGE-BEHIND DISTANCE. + JUMPE A,CFHAH4 + ADDB A,E ;COMPUTE WHICH PAGE TO PAGE OUT. + PUSHJ P,CFHRNG ;SKIP IF PAGE IS IN RANGE FOR PAGE-BEHIND. + JRST CFHAH4 + MOVE U,W + PUSHJ P,UPLC ;LOOK UP THE PAGE IN THE MAP. + LDB D,Q ;D GETS CIRC PNTR + JUMPE D,CFHAH4 ;NO PAGE THERE + CAIN D,-1 + JRST CFHAH4 ;ABSOLUTE PAGE, DO NOTHING. + LDB D,T + TRO D,PMAGEM ;AGE THE PAGE, IF THE PAGE IS REALLY IN THE MAP, + TRNE D,600000 + DPB D,T + AOS NPGBHA ;COUNT PAGES AHED FOR PAGE-BEHIND. + MOVE D,T ;SAVE B.P. TO PAGE MAP HALFWORD, FOR CFHAH6. + MOVE C,Q ;STARTING FROM CIRC PTR, FIND MMP + PUSHJ P,UCPRL + 200000,,.+2 + BUG ;IF NONE FOUND + SUB P,[4,,4] ;FOUND MMP, C POINTS TO IT + MOVE E,C ;SAVE ADDRESS OF MMP ENTRY + MOVSI T,MMPTMP\MMPOUT ;IF PAGE IS IN TRANSIT OR OUT, DO NOTHING TO IT. + TDNE T,(C) + JRST CFHAH6 + MOVE T,CLKBRK + TLNN T,%PCUSR ;IF JOB IN EXEC MODE, CAN'T SWAP OUT PAGE, SO JUST LEAVE AGED. + JRST CFHAH6 + MOVE T,MEMFR + SUB T,NCBCOM ;IF LOTS OF FREE MEM, DON'T SWAP OUT. + SUB T,SILNG + CAML T,CFHAHS + JRST CFHAH6 + PUSHJ P,UCPRL ;GET CORE PAGE NUMBER IN T. + 100000,,.+2 + BUG + SUB P,[4,,4] + HLRZ A,MMSWP(T) + JUMPN A,CFHAH6 ;POINTED TO BY AN EXEC PAGE, E.G. 340, CAN'T SWAP OUT. + PUSH P,E + PUSH P,D + PUSH P,W + MOVE A,T ;PHYSICAL PAGE # TO SWAP OUT + HRRZ C,W ;DON'T PCLSR ME + SETOM CIRPSW ;SWPOPG WILL WANT TO RE-LOCK CIRPSW. + PUSHJ P,SWPOPG ;SWAP OUT + JRST CFHAH5 ;CAN'T SWAP OUT => LEAVE JUST AGED. + AOS NPGBHD ;COUNT PAGES SWAPPED OUT BY PAGE-BEHIND. +CFHAH5: POP P,W + POP P,D + POP P,E + POP P,U + POP P,CFHUVP + AOS CIRPSW ;SWPOPG UNLOCKS; RE-LOCK. + POPJ P, ;CAN'T GET LOCKED BY SOMEONE ELSE, WE ARE AT CLOCK LEVEL + +;HERE FOR PAGE-BEHIND PAGE WHICH WE CAN'T OR DON'T WANT TO SWAP OUT. +CFHAH6: MOVSI T,MMPPGB ;IT HAS ALREADY BEEN AGED. MARK IT FOR METERING PURPOSES. + IORM T,(E) ;E POINTS TO MMP ENTRY. +CFHAH4: POP P,U + POP P,CFHUVP + POPJ P, + +;SKIP IF PAGE NUMBER IN E IS IN RANGE FOR PAGE-AHEAD OR PAGE-BEHIND. +;ASSUMES USER INDEX IN W. CLOBBERS T. +CFHRNG: CAIL E,400 + POPJ P, + HLRZ T,PAGRAN(W) + CAIGE E,(T) + POPJ P, + HRRZ T,PAGRAN(W) + CAIL E,(T) + POPJ P, + JRST POPJ1 + +EBLK + +CFHAHS: 20 ;IF LESS THAN THIS MUCH FREE MEM, PAGE-BEHIND SHOULD SWAP OUT. + +NPGAHD: 0 ;NUMBER OF PAGES WE ACTUALLY SWAPPED IN FOR PAGE-AHEAD. +NPGAH1: 0 ;NUMBER OF TIMES WE WERE UNABLE TO PAGE AHEAD. +NPGBHD: 0 ;NUMBER OF PAGES WE ACTUALLY SWAPPED OUT FOR PAGE-BEHIND. +NPGBHA: 0 ;NUMBER OF PAGES WE DID PAGE-BEHIND. +NPGAHR: 0 ;NUMBER OF PAGED-AHEAD PAGES ACTUALLY USED. +NPGBHR: 0 ;NUMBER OF PAGES AGED FOR PAGE BEHIND AND USED AGAIN. + +BBLK + +;REFERENCE TO SWAPPED OUT PAGE, MMP ADDRESS IN C. SWAP IN THE PAGE. +;W HAS THE USER INDEX AND FLAGS. +CFHPO: PUSHJ P,CFHPOA + JRST [ SETZ A, ;FAILED. RETURN CODE FOR FAILURE, IF THIS IS FOR DEVICE (W<0). + JRST CFHX] + TLNN W,100000 ;IF THIS IS A PAGE-AHEAD REQUEST, + JRST CFHPOB + MOVSI A,MMPPGA ;MARK THE MMP ENTRY SO, + IORM A,(C) + AOS NPGAHD ;AND COUNT IT AS A SUCCESSFUL ATTEMPT TO PAGE AHEAD. +CFHPOB: TLNN W,200000 + JUMPL W,CFHPO2 + PUSHJ P,CFHAHC ;ORDINARY PG FAULT => MAYBE PAGE AHEAD. + MOVSI D,%SWBEM +IFN SWPWSP,[ ;SWAPPING IN A PAGE FOR THIS GUY + ANDCAM D,USWST(W) ;SO CLEAR BEST EFFORT MADE TO SWAP OUT BIT +];SWPWSP +IFE SWPWSP,[ + TDNN D,USWST(W) ;IF JOB IS BRINGING IN FIRST PAGE + JRST CFHPO2 ; SINCE BEING SWAPPED OUT, + ANDCAM D,USWST(W) ;CLEAR BEST EFFOR MADE TO SWAP OUT BIT + EXCH U,W ;AND MAKE SWAP HISTORY TABLE ENTRY + MOVSI T,0 ;FOR "BEGIN LOADING" + PUSHJ P,SWPKHT + EXCH U,W +];SWPWSP +CFHPCI: +CFHPGO: +CFHPO2: MOVNI A,1 ;SIGNAL "SUCCESS" + TLNN W,200000 + JUMPL W,CFHX + MOVSI D,MMPTMP ;BIT ON IF PAGE "IN TRANSIT" + SKIPN FLSINS(W) + MOVEM D,EPDL2(W) ;HANG USER UNTIL PAGE GETS WHERE IT'S GOING + HRLI C,(TDNE T,) ;COMBINE WITH ADDRESS OF MMP + AOS NLPPAG + JRST CFHX + +;SWAP IN PAGE. W HAS USER INDEX AND FLAGS. C HAS MMP ADDRESS. +;SKIPS IF SUCCESSFUL. OTHERWISE RETURNS FLSINS IN C. +;SIGN BIT IN W IS SET FOR SWAP IN FOR DEVICE OR FOR PAGE-AHEAD +;(THAT IS, NOT ONE WHICH A JOB MUST WAIT FOR) +;SO DON'T INCREMENT SOME COUNTERS AND DON'T BOTHER WITH FLSINS IN C. +CFHPOA: +IFE SWPWSP,[ + SKIPGE USWSCD(W) ;IF SWAP BLOCKED, EITHER UNBLOCK OR GIVE UP. + JRST CFBO1 +CFBO2: +];SWPWSP +IFN SWPWSP,[ + MOVE E,USWST(W) ;IF SWAPPED OUT, WE ARE EITHER GOING TO ENTER + TLNE E,%SWOUT ;THE LOADING STATE OR THE SWAP BLOCKED STATE + JRST CFSB +CFSB1: +];SWPWSP + MOVSI E,MMPISW + AND E,(C) + CONO PI,UTCOFF-1 + JUMPN E,CFHPO5 ;INITIAL SWAPIN; GIVE UP AND WAIT NOW IF TUT IS LOCKED. +CFHPO7: PUSHJ P,HMRQC ;GET PHYS MEM BLOCK, NUMBER IN A. + JRST CFHPO1 ;MEM NOT AVAILABLE + MOVEI B,1 + DPB B,[410200,,(C)] ;INDICATE COMING IN + HRRZ B,(C) ;OLD CP OF MMP + MOVEM B,MEMPNT(A) ;BECOMES LINK OUT OF CORE BLOCK + HLRZ B,1(C) ;B := DISK ADDRESS + LDB I,[$MMPUN,,(C)] ;I := DISK NUMBER + CAIL I,NQS + BUG + HRLM B,MEMPNT(A) ;SET DISK ADDRESS CORE BLOCK COMING FROM +IFN SWPWSP,[ + MOVE D,USWST(W) + TLNN D,%SWLOD + AOSA NPLBNL + AOS NPLBLJ +];SWPWSP + SKIPE E ;IF INITIAL SWAP IN PAGE, SOS THE TUT NOW + PUSHJ P,CFHPO8 ;SINCE WE ARE DISSOCIATING THE PAGE FROM THE DISK BLOCK. + CAIGE A,TSYSM + CAIGE A,SYSB + BUG ;SHOULDN'T HAVE TO SWAP IN THE SYSTEM + CONO PI,UTCON-1 ;LEAVE CLKCHN OFF. + SOS NPGSWO + AOS SWIPRQ ;TOTAL SWAP IN REQUESTS +;; MARK THE PHYSICAL MEMORY BLOCK AS BEING SWAPPED INTO BY THIS PAGE. + MOVEI B,MUSWPG + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,600000(A) + HRRM B,(C) ;MAKE CP OF MMP POINT TO MEMPNT + MOVE TT,C + SUB TT,MMPEAD + DPB TT,[MMMPX,,MEMBLT(A)] ;STORE MMP INDEX IN MEMBLT + MOVEI TT,.BM MLO + ANDCAM TT,MEMBLT(A) ;SET END OF LIST IN THIS BLOCK +;; PUT THE TRANSFER ON THE SWAP IN LIST. + CONO PI,UTCOFF-1 + HLRZ TT,SINLST(I) ;GET PREV BLOCK + SKIPE TT + DPB A,[MLO,,MEMBLT(TT)] ;CHAIN TO PREV BLOCK + SKIPN TT + MOVEM A,SINLST(I) ;OR TO HEADER IF FIRST + HRLM A,SINLST(I) ;AND SET NEW LAST BLOCK + AOS SILNG ;AOS NUMBER OF PENDING SWAP IN RQS. + PUSHJ P,QSTRT1 ;WAKE UP DISK INTERRUPT LEVEL. + CONO PI,UTCON-1 +;; UPDATE SWAP HISTORY TABLE. + HRLZ TT,W + IDIVI TT,LUBLK ;TT 3.1-3.8 GETS USER NUMBER, BASHES I +IFN SWPWSP,[ + MOVSI T,%SWLOD + TDNE T,USWST(W) + TLO TT,(SETZ) +];SWPWSP + MOVE T,CFHUVP + DPB T,[321000,,TT] + HRR TT,TIME + MOVEM TT,@PGIHTP + AOS T,PGIHTP + MOVE TT,UTRNTM(W) + MOVEM TT,PGIHTL-1(T) + MOVEI TT,PGIHTB + CAIL T,PGIHTB+PGIHTL + MOVEM TT,PGIHTP + TLNN W,200000 + JUMPL W,POPJ1 + AOS USIPRQ(W) + JRST POPJ1 ;HANG USER UNTIL PAGE IN + +;IF SWAPPNG IN "INITIAL SWAP IN" PAGE, CHECK TO SEE WHETHER TUT IS AVAILABLE. +;WE CAN'T SWAP THE PAGE IN IF NOT. +CFHPO5: LDB I,[$MMPUN,,(C)] ;GET DSK # + CAIL I,NQS + BUG + SKIPL QTUTO(I) + JRST CFHPO7 ;DISK TUT AVAIL + CONO PI,UTCON-1 + TLNN W,200000 + JUMPL W,CPOPJ ;NO COUNTER AOS IF SWAPIN FOR DEVICE OR PAGE AHEAD. + MOVE C,[SKIPGE QTUTO] ;ALSO MUSTN'T SMASH C + ADD C,I + AOS NLPPGT + POPJ P, + +;LATER ON, COME HERE TO SOS THE TUT, AFTER GETTING THE MEM, WHEN WE CAN NO LONGER BLOCK. +CFHPO8: ANDCAM E,(C) ;CLEAR INITIAL SWAPIN BIT + MOVE D,B ;GET TRK # + PUSHJ P,TUTPNT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] + DPB B,D + HRRZS 1(C) ;CLEAR ASSIGNED TRACK NUMBER SO NEW SPACE ASSIGNED ON SWAPOUT + POPJ P, + +;HERE IF NO MEMORY TO SWAP PAGE INTO. +CFHPO1: CONO PI,UTCON-1 + TLNN W,200000 + JUMPL W,CPOPJ + SKIPGE MEMFRZ ;IF BECAUSE MEMFRZ LOCKED, MAKE JOB WAIT FOR MEMFRZ. + JRST CFHPO4 + MOVE C,[SKIPL MEMFRZ] + AOS NLPPGM + POPJ P, + +CFHPO4: MOVE C,[PUSHJ P,CFHPO3] + MOVN D,SOLNG + SUB D,SWPOPR ;- # PGS GOING OUT + ADDI D,10. ;MAKE SURE AT LEAST 10. GOING OUT + JUMPLE D,.+2 + ADDM D,SWPOPR + MOVEI D,1 + SKIPN FLSINS(W) + MOVEM D,EPDL2(W) + AOS NLPPG3 + POPJ P, + +CFHPO3: PUSH P,A ;FLSINS ROUTINE (NEEDED MEM) + MOVE A,MEMFR + SUB A,NCBCOM + CAIL A,5(T) + JRST POPAJ1 ;NEEDED MEM AVAILABLE + ADD A,SOLNG + ADD A,SWPOPR + SUBI A,10.(T) + JUMPGE A,POPAJ ;WILL EVENTUALLY WIN + MOVNS A + ADDM A,SWPOPR ;LOSING - SWAP SOME MORE STUFF OUT + JRST POPAJ + +IFE SWPWSP,[ +;HERE IF TRYING TO SWAP IN A PAGE BUT SWAP BLOCKED +CFBO1: MOVE E,MEMFR ;GUY SWAPPED BLOCKED + SUB E,NCBCOM + SUB E,AUSOPG + SUB E,SILNG + ADD E,SOLNG + JUMPGE E,CFBO3 ;SEEMS TO BE ROOM SO LET IT COME IN + TLNN W,200000 + JUMPL W,CPOPJ ;HANG GUY UNTIL SWAP BLOCK GOES AWAY + MOVE C,[SKIPGE USWSCD] + ADDI C,(W) + AOS NTSBUB + AOS NLPPGB + POPJ P, + +CFBO3: AOS NTSBUP + JRST CFBO2 +];SWPWSP + +OVHMTR WS ;WORKING-SET COMPUTATIONS + +IFN SWPWSP,[ +;HERE WHEN A SWAPPED OUT OR SWAP BLOCKED JOB TRIES TO SWAP IN A PAGE. +;JOB IN W, C -> MMP, USWST(W) IN E. RETURN TO CFSB1. +;WE DECIDE WHETHER ENOUGH CORE CAN BE GARNERED TO LET HIM IN, AND PUT +;HIM INTO THE LOADING STATE, OR ELSE PUT HIM INTO THE SWAP BLOCKED STATE. + +CFSB: PUSH P,C + TLNN E,%SWSB ;ALREADY SWAP BLOCKED? + PUSHJ P,WSRCM ;NO, RECOMPUTE WORKING SET + POP P,C + MOVE B,USWPRI(W) ;FIND SUM OF WS'S OF SWAPPED IN GUY'S WITH BIGGER USWPRI + PUSHJ P,WSAVL + MOVE D,USVWRK(W) ;COMPUTE AMT OF WS NOT ALREADY IN CORE + SUB D,UWRKST(W) +IFL TSYSM-356.,[ + CAML D,[TSYSM-100.,,] + JRST .+3 ;WS > PHYSICAL MEM, ALLOW IN ANYWAY, FOO! +];TSYSM + CAMGE A,D ;WILL IT FIT IN AVAILABLE MEM? + JRST CFSB2 ;NO, SWAP BLOCK + PUSHJ P,CFELD ;YES, ENTER 'LOADING' STATE + JRST CFSB1 ;AND GO AHEAD AND BRING IN THE PAGE + +CFSB2: TLNN W,200000 ;IF PAGE-AHEAD, JUST RETURN. + JUMPL W,CPOPJ + MOVE T,TIME + MOVSI A,%SWSB ;ALREADY SWAP BLOCKED? + TDNE A,USWST(W) + JRST CFSB3 + IORM A,USWST(W) ;NO, ENTER SWAP BLOCKED STATE + AOS NUSWB + MOVEM T,USWTIM(W) +CFSB3: MOVE U,W + MOVSI T,3_16. ;MAKE SWAP HISTORY TABLE ENTRY FOR SWP BLK + PUSHJ P,SWPKHT + MOVE T,TIME + SUB T,USWTIM(W) ;HOW LONG SWAP BLOCKED + CAIGE T,20.*30. ;IF LESS THAN 20 SECONDS, + SKIPA T,[15.] ; SLEEP FOR 1/2 SECOND, + MOVEI T,5*30. ; OTHERWISE SLEEP FOR 5 SECONDS + ADD T,TIME + SKIPN FLSINS(W) + MOVEM T,EPDL2(W) + MOVEI A,0 ;WILL THEN TAKE FAULT AGAIN AND + MOVE C,[CAMLE T,TIME] ;CHECK AVAILABLE MEMORY AGAIN + AOS NLPPGB + POPJ P, + +;ROUTINE TO FIND MEMORY AVAILABLE TO A JOB WHOSE USWPRI IS IN B +;RETURNS IN LH(A) SUITABLE FOR COMPARING TO UWRKST. SMASHES T,TT,J + +WSAVL: MOVEI J,2*LUBLK ;DON'T LOOK AT SYS NOR CORE JOB + MOVSI T,%SWOUT+%SWLOD ;IF THESE BITS CLEAR, JOB IS SWAPPED IN + MOVE A,MEMFR ;FREE CORE + SUB A,NCBCOM ;FUDGE FOR THINGS IN PROCESS + SUB A,SILNG ;.. + ADD A,SOLNG ;.. + ADD A,NLOOSP ;LOOSE PAGES ARE EVICTABLE + SUB A,SWPOPR ;DON'T COUNT PAGES ALREADY COMMITTED TO EVICT + HRLZI A,-4(A) ;ALIGN AS UWRKST AND ALLOW 4 PAGES OF SLOP + SKIPA TT,TIME ;TO SEE IF PROTECTED AGAINST MEMORY PREEMPTION +WSAVL1: ADDI J,LUBLK + CAML J,USRHI + POPJ P, + SKIPE UNAME(J) + TDNE T,USWST(J) + JRST WSAVL1 ;DOESN'T EXIST, OR NOT SWAPPED IN, OR LOADING + CAMGE B,USWPRI(J) + CAMGE TT,USWTIM(J) + JRST WSAVL1 ;HIGHER PRIORITY OR PROTECTED + ADD A,UWRKST(J) ;THIS GUY'S WORKING SET IS PREEMPTABLE + JRST WSAVL1 + +;Routine to re-compute working set, also re sets up map +;to point to any pages which are swapped in but not mapped in. +;This is necessary in order to get the proper estimate of +;how much core is going to have to be swapped out to make +;this job fit. Called when a job leaves the swapped-out state, +;to enter either Loading or Swap-blocked. +;Job is in W, smashes A,B,C,D,E,T,TT,H,I,U. +;Call with CIRPSW locked and clk in progress. +WSRCM: SETZM UWRKST(W) + MOVEI E,UPGMP(W) ;SET UP SCAN OF USER'S MAP + HRLI E,442200 + MOVEI C,UPGCP(W) ;AND OF CIRCULAR POINTERS + HRLI C,442200 + LDB D,[121100,,HUSRAD(W)] ;# OF USER PAGES +WSRCM1: ILDB A,E ;GET PAGE MAP ENTRY + ILDB B,C ;AND CIRCULAR POINTER + JUMPE A,WSRCM2 ;JUMP IF PAGE DOESN'T EXIST + CAIN B,-1 + JRST WSRCM2 ;ABS PAGE, DON'T COUNT + TRNN A,600000 ;ALREADY SWAPPED IN? + JRST WSRCM3 ;NO, GO PONDER + ANDI A,PMRCM ;GET PAGE MAPPED TO + HRRZ B,MMSWP(A) ;GET # SHARERS + MOVSI A,1 ;COMPUTE WS ADJUSTMENT + IDIV A,B + ADDM A,UWRKST(W) +WSRCM2: SOJG D,WSRCM1 ;LOOP + POPJ P, + +WSRCM3: PUSH P,C ;PAGE NOT MAPPED, SEE IF IT'S IN + PUSHJ P,UCPRL + 100000,,WSRCM4 ;RETURN WITH 4 PUSHES IF MEMORY IN LOOP + POP P,C ;NO MEMORY, LEAVE ALONE + SOJG D,WSRCM1 + POPJ P, + +WSRCM4: SUB P,[4,,4] ;FOUND MEMORY, IN T + TRNE A,2 + MOVEI A,2 ;USE READ/WRITE/FIRST RATHER THAN READ/WRITE + LSH A,20 + IORI A,PMCSHM(T) ;SET UP MAP + DPB A,E + AOS C,MMSWP(T) ;ONE MORE USER POINTING TO PAGE + MOVSI A,1 + MOVEI B,-1(C) + IDIVM A,B ;ADJUST WS AS IF WAS ALREADY POINTING TO PAGE + ADDM B,UWRKST(W) ;ADDM DOES NOTHING IF THERE WAS DIVIDE BY ZERO + IMULI C,-1(C) ;COMPUTE WS DECREASE DUE TO ADDITIONAL SHARING + MOVNI C,(C) + IDIV A,C ;IF DIVIDE BY ZERO, A GETS RIGHT THING! + MOVE C,(P) ;ADJUST ALL SHARER'S WS'S + PUSHJ P,UCPRL + SETZ WSRCM5 + POP P,C + SOJG D,WSRCM1 + POPJ P, + +WSRCM5: ADDM A,UWRKST(U) + POPJ P, + +;LEAVE LOADING STATE IF IN IT. JOB IN U, SMASH C,TT,T,I +LVLOAD: MOVE C,USWST(U) + TLZN C,%SWLOD + POPJ P, ;NOT IN LOADING STATE +LVLOA0: MOVEM C,USWST(U) ;TURN OFF LOADING STATE + MOVE T,TIME + SUB T,USWTIM(U) ;TIME IT TOOK TO LOAD + IMUL T,LODFCT ;COMPUTE PROTECT TIME + HLRZS T + ADD T,TIME + MOVEM T,USWTIM(U) + MOVSI T,1_16. ;MAKE SWAP HISTORY TABLE ENTRY + JRST SWPKHT + +;PUT JOB IN W INTO THE 'LOADING' STATE. CALL WITH D CONTAINING USVWRK-UWRKST. +;WSRCM MUST HAVE BEEN CALLED ALREADY ON THIS JOB. SMASHES A,D,T,TT,I + +CFELD: MOVE T,USWST(W) + TLNE T,%SWSB + SOS NUSWB ;CEASES TO BE SWAP-BLOCKED + TLZ T,%SWOUT+%SWSB+%SWDSO+%SWBEM + TLO T,%SWLOD + MOVEM T,USWST(W) + MOVE T,TIME ;SAVE TIME STARTED TO LOAD + MOVEM T,USWTIM(W) + MOVE U,W + MOVSI T,0 ;MAKE SWAP HISTORY TABLE ENTRY + PUSHJ P,SWPKHT + JUMPLE D,CPOPJ + HLRZ D,D ;NUMBER OF PAGES GOING TO NEED, PROBABLY + MOVE A,MEMFR ;FREE CORE + SUB A,NCBCOM ;FUDGE FOR THINGS IN PROCESS + SUB A,SILNG ;.. + ADD A,SOLNG + SUB D,A ;NUMBER OF PAGES GOING TO HAVE TO SWAP OUT + SKIPLE D + ADDM D,SWPOPR ;START THEM GOING OUT NOW + POPJ P, +];SWPWSP + +OVHMTR FLT ;MISC FAULTS + +CFH4: TLNE W,100000 ;PAGE-AHEAD OF NON-EX PAGE: DO NOTHING. + POPJ P, + JUMPL W,SWIILM ;IF FROM DMA DEVICE, GIVE ERROR +;HERE FOR FAULTS WHICH ABORT THE INSTRUCTION. +PFA7: MOVE T,OPTION(U) ;IF USER WANTS IT, + TLNN T,%OPOPC ;GIVE HIM THE OPC RATHER THAN + AOSA T,CLKBRK ;THE INCREMENTD PC. +PFA7A: MOVE T,CLKBRK ;HERE FOR KL10 MAR BREAK AND KS10 NXI + ;ERROR, ALWAYS GIVE ORIGINAL PC, INST + ;ABORTED + TLNE T,%PCUSR + JRST CLKB1J + MOVEI C,IOADCR ;FROM EXEC MODE SO RESET PC TO IOADCR + EXCH C,CLKBRK + HRRM C,LEXFDR(U) ;AND SAVE FAULT EXEC ADR FOR DEBUGGING + CLEARM DLSRCH ;IN CASE IT WAS SET + CLEARM UMAPS(U) ;RESTORE NORMAL MAP IN CASE RANDOM ONE WAS + ;IN USE + +CLKB1J: HRLM D,LEXFDR(U) ;SAVE PF BITS FOR DEBUGGING PURPOSES + +IFN KS10P,[ TRNE D,%PFNXI ;Non-existent IO register in KS10 Unibus. + TLO A,(%PINXI) +] ;KS10P + +IFN KS10P, TRNN D,%PFNXI\%PF2.9\%PF2.8 +IFN KA10P, TLZE D,210 ;NO ACCESS OR DBL +IFN KL10P, CAIN D,%PFPNA + TRO A,%PIMPV ;ILM + +IFE KS10P,[ +IFN KA10P, TLZE D,20 ;PURE +IFN KL10P, CAIN D,%PFPRO + TLO A,(%PIFET) +] ;IFE KS10P + +IFN KS10P, CAIN D,%PFWRT\%PF2.8 +IFN KA10P, TLZE D,100 ;W IN RD ONLY +IFN KL10P, CAIN D,%PFILW + TLO A,(%PIWRO) + + TDNE A,[%PIMPV\%PIWRO\%PINXI] + PUSHJ P,MPVMAS ;SAVE FAULT PAGE # FOR DEBUGGING + +;;; NO ABORT-TYPE FAULTS, CHECK OTHERS: + +IFE KS10P,[ +IFN KL10P, CAIN D,%PFMAR +IFN KA10P, TLZE D,2 + PUSHJ P,PCMARB +] ;IFE KS10P + +IFN KA10P,[ TLZE D,2000 + PUSHJ P,CPROC1 ;ONE PROCEED + ANDCA D,UPQUAN(U) ;GET BITS FLUSHED BY TLZE'S +] ;KA10P + +CFH6: +IFN KA10P,[ + ANDCMI D,-1 ;DON'T CLOBBER USER'S RUNTIME. + TLZ D,4 ;DON'T CLOBBER EXEC PAGING FLAG. + TLO D,1 ;IGNORE QUANTUM-TIMEOUT INT. + ANDCAM D,UPQUAN(U) +] ;KA10P +CLKB1K: LPMR UPGML(U) +CLKB1G: IFN KA10P, CONO 470000+APRCHN ;RESET +CLB1X: MOVE T,CLKBRK ;PUT USER'S PC WHERE IT BELONGS + MOVEM T,UPC(U) + MOVE B,[BADBTS] + IOR B,MSKST(U) ;GET OR OF ENABLED AND BAD BITS + AND B,A ;GET AND WITH BITS ACTUALLY ON + JUMPE B,CLB1XA ;NOT BAD OR ENABLED, FORGET ABOUT IT + IORM B,PIRQC(U) ;GIVE INTERRUPT + CAIN T,IOADCR ;READY TO BE INTERRUPTED? + JRST CLKB5 ;NOT QUITE, RUN MOMENTARILY AND WILL UFLS +IFN SCHBLN,SETZM SCHMNY ;DO FULL SCHEDULE TO DELIVER THE INTERRUPT + JRST SCHED2 + +CLB1XA: MOVSI T,%SWINT .SEE INTPFL ;IF PAGE FAULT DUE TO USER TRYING TO + TDNN T,USWST(U) ;INTERRUPT, BETTER SCHED SO HE GETS THE INT. + SKIPE FLSINS(U) ;ELSE PROCEED THE USER IF HE HAS GOT WHAT HE WANTED. + JRST SCHED2 ;OR IF HE'S WAITING, GO SCHEDULE. + JRST CLKB5 + +IFN KA10P,[ ;NULL JOB LOST +CNLJL: CONSZ 230220 ;SKIP ON JUST "ADDR BREAK" (QUANTUM OVERFLOW) + BUG PAUSE,[KA: APR ERROR IN NULL JOB] + CONO 470000+APRCHN + JRST SCHED + +CFHFPF: BUG PAUSE,[PAGE FAULT IN SYSTEM, PC=],OCT,CLKBRK,[PAGE=],OCT,E + MOVSI D,1770 ;FALSE PAGE FAULT + MOVEI A,0 + JRST CFH6 +] ;KA10P + +EBLK +RINT: 0 +BBLK + CONI RINTAP ;SAVE STATUS IN CASE SOMEONE DUMPS IT + CONI PI,RINTPI + BUG AWFUL,[RANDOM INTERRUPT, APR ],OCT,RINTAP,[PI ],OCT,RINTPI + JRST 12,@RINT ;YOU CAN TRY PROCEEDING + +EBLK +RINTAP: 0 ;APR STATUS AT RINT +RINTPI: 0 ;PI STATUS AT RINT + +IFN KS10P,[ ; On KS, all random interrupts are created equal. +BBLK +RINT1==:RINT +] ;IFN KS10P + +IFE KS10P,[ +R1NTAC: BLOCK 20 +RINT1: 0 +BBLK + MOVEM 17,R1NTAC+17 + MOVEI 17,R1NTAC + BLT 17,R1NTAC+16 + MOVEI J,1 + JSP E,SPUR + MOVSI 17,R1NTAC + BLT 17,17 + JRST 12,@RINT1 +] ;IFE KS10P + +IFE KS10P,[ ;KS10 HAS NO MAR + +PCMARB: +IFN KA10P,[ + HLLZ B,UPOPC(U) ;FLAGS + LSH B,5 + HRR B,UPOPC(U) ;PC + MOVE T,B + XOR T,CLKBRK ;DID PC CHANGE FROM START OF INST TO PLACE TRAPPED? + TDNE T,[#<%PCFPD,,>] + TLO B,(@) ;YES, INSTRUCTION COMPLETED, FLAG FOR USER +] ;KA10P ;LOSES FOR JSR .-1 WITH MAR AT .-1, BUT OTHERWISE OK +IFN KL10P,[ + MOVE B,CLKBRK ;PC OF FAULTING INST IF USER, OR IOADCR IF EXEC +; MOVEM B,UPOPC(U) ;SOLELY FOR .OPC USER VAR +;NOTE- ON KL10 THE INSTRUCTION IS NEVER COMPLETED, DON'T SET 3.5 +] ;KL10P + TLNE B,%PCUSR + JRST PCMAR1 ;USR MODE, USE PC FROM PAGER + MOVE B,UUOH ;EXEC MODE, USE USER PC (UUO) + HRRI B,-1(B) +IFN KL10P,[ ;ON KL10 AVOID DOING AOS UUOH AT IOADCR + MOVEM U,AC0S+U(U) + MOVEI T,UUOER2 + MOVEM T,CLKBRK +];KL10P +PCMAR1: MOVEM B,UMARPC(U) + TRO A,%PIMAR + MOVEI B,0 +IFN KA10P, DPB B,[220300,,UPMAR(U)] ;DISABLE MAR +IFN KL10P, DPB B,[270400,,UPMAR(U)] ;DISABLE MAR + POPJ P, + +] ;IFE KS10P + +IFN KA10P,[ +CPROC1: MOVE T,CLKBRK + TLNN T,%PCUSR ;SKIP IF FROM USER MODE + JRST CPRUUO + TRO A,%PI1PR ;GIVE USER INTERRUPT + POPJ P, + +CPRUUO: MOVE T,[JRST ONEPROC] ;ONE PROCEED INT. FROM EXEC. MODE + MOVEM T,UEXIT ;CLOBBER EXIT TO RUN SYS CALL TO COMPLETION + POPJ P, + +AROV: TLZE T,400000 + TLNN T,%PCUSR + JRST AROV2 ;NOT REALLY SET OR SET BY SYS + MOVEM T,CLKBRK + SKIPE PICLR(U) ;SKIP IF INTERRUPTS TO USER NOT ENABLED + TRO A,%PIARO ;GIVE USER INTERRUPT + POPJ P, + +AROV2: MOVEM T,CLKBRK + POPJ P, + +ARFOV: TLZE T,40000 + TLNN T,%PCUSR + JRST AROV2 + MOVEM T,CLKBRK + SKIPE PICLR(U) + TLO A,(%PIFOV) + POPJ P, +] ;KA10P + +;;; HANDLE PARITY ERRORS. + +CLKB1E: SETZM PARDIE ;AT FIRST ASSUME THE PAR ERR ISN'T FATAL. + CONO PI,PIOFF ;TURN OFF WORLD +IFN KA10P, CONO PI,240000 ;RESET +IFN KL10P,[ ;CLEAR THE CACHE + SWPUA + CONSZ 200000 + JRST .-1 +] ;KL10P +IFN KS10P,[ + CLRCSH ;Clear the cache +] ;KS10P + MOVSI B,SCLPAR + TDNE B,SUPCOR ;IF PREV ERROR NOT PRINTED, PRINT IT NOW AND PAUSE + BUG PAUSE,[TOO MANY PARITY ERRORS. PREV STATUS=],DEC,PARCNT,OCT,PARAAN,OCT,PARAOR,OCT,PARAND,OCT,PARIOR + IORM B,SUPCOR ;TELL SYS JOB TO PRINT OUR DATA WHEN WE FINISH. + AOS PARERR ;COUNT # OF PAR ERRS SINCE SYSTEM STARTED. + SETOM PARAND ;INIT LOGAND AND LOGOR OF ALL BAD DATA WORDS + SETZM PARIOR + SETOM PARAAN ;AND SIMILAR FOR ADDRESSES OF PAR ERRS. + SETZM PARAOR + MOVE T,CLKBRK + MOVEM T,PARPC + MOVE T,USER + MOVEM T,PARUSR ;REMEMBER WHICH JOB GOT THE PAR ERR. + JUMPL T,PARSCJ ;PAR ERR IN NULL JOB? OR WHAT? +IFN KL10P,[ + SKIPE PARRSN ;PAR ERR IN WORD NOT REFERENCED + JRST PARSCJ ; SHOULDN'T SCREW THE RUNNING JOB +] ;KL10P + CAIG T,LUBLK + SETOM PARDIE ;PAR ERR IN A SUPERVISOR-MODE JOB IS HOPELESS. + MOVSI TT,(%PIPAR) + IORM TT,PIRQC(T) ;GIVE RUNNING USER A PARITY ERROR (CLASS 1 INT) +PARSCJ: SPM PARPG +IFN KL10P,[ + PUSH P,PFNPC ;MAKE SURE THE PAR ERRS WE DETECT WHILE SCANNING DON'T + MOVEI D,PARFX4 ;CALL US RECURSIVELY (ON KA, THAT'S DONE BY HAVING + MOVEM D,PFNPC ;CLKCHN OFF) +] ;KL10P +IFN KS10P,[ + PUSH P,EPTP7N ;Same hack for the KS except page fails trap + MOVEI D,PARFX4 ;as a function of current PI level. + MOVEM D,EPTP7N +] ;KS10P + MOVEI D,0 ;POINTER TO ERROR BUFFER + MOVSI TT,-TSYSM + PUSHJ P,PARSCN ;SCAN MAIN MEM BLOCKS +IFN PDP6P,[ + MOVE TT,[-LPDP6M,,PDP6BM_-10.] ;SCAN PDP6 MEM FOR PARITY ERRORS + SKIPGE PDP6UP ;BUT NOT IF PDP6 IS DOWN. + PUSHJ P,PARSCN +] +IFN KL10P,[ + POP P,PFNPC + CONO 024400+APRCHN ;CLEAR PAR ERR FLAGS. +] ;KL10P +IFN KS10P,[ + POP P,EPTP7N + CONO 020200+APRCHN ;CLEAR FLAG + MOVSI A,%KEHLD+%KEREF ;CLEAR STATUS AND ERROR ADDR + IOWR A,[KSECCS] +] ;KS10P + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] + LPMR PARPG ;SET UP MAP WITH PARPG SET TO MPV. + MOVEM D,PARCNT ;SAVE AWAY COUNT OF ERRORS IN BUFFER + SKIPE PARDIE + BUG HALT,[PARITY ERROR IN SYSTEM MEMORY. CNT=],DEC,PARCNT,[ADR AND ],OCT,PARAAN,CR,0,[ ADR IOR ],OCT,PARAOR,[DATA AND ],OCT,PARAND,[DATA IOR ],OCT,PARIOR + ;FATAL ERROR (DONT ALLOW CONTINUE SINCE ERR IS + ;KNOWN TO BE A LOSER) + CONO PI,PION ;TURN WORLD BACK ON + JRST SCHED + +PARSCN: +PARFX3: HRRZ T,TT ;SCAN AOBJN POINTER IN TT + CAIL T,TSYSM + JRST PARFX7 + LDB T,[MUR,,MEMBLT(TT)] + CAIN T,MUHOLE + JRST PARFX8 ;HOLE THERE +PARFX7: MOVEI T,600000(TT) ;NOTE THAT WE ARE NOT ENABLING THE CACHE. + DPB T,[.PAREP+EXEUMP] ;ON KL10 THIS WILL CAUSE A 1-WORD READ. + LPMR PARPG ;SET UP TO CHECK PAGE # IN TT + MOVEI B,0 ;ADDRESS WITHIN PAGE +PARFX1: +IFN KA10P, CONO PI,200000 ;CLEAR PAR ERR +PARFX5: MOVE C,400000+PAREP*2000(B) ;REFERENCE EVERY MEMORY LOCATION +IFN KA10P,[ + ;;ON KA, MUST CHECK EXPLICITLY. + ;;ON KL AND KS, PAR ERR WILL TRAP RIGHT TO PARFX4. + CONSZ PI,200000 ;PARITY ERR? + JRST PARFX4 ;YES. +] ;KA10P + CAIGE B,1777 ;SKIP ON FINISHED WITH BLOCK + AOJA B,PARFX5 +PARFX8: AOBJN TT,PARFX3 ;CHECK NEXT PAGE + POPJ P, ;DONE + +PARFX4: ;HERE WHEN THE SCAN FINDS A WORD WITH BAD PARITY +IFN KL10P, HRRZ T,PFOPC +IFN KS10P, HRRZ T,EPTP7O +IFE KA10P,[ + ;;DID THIS TRAP COME FROM SCAN LOOP WHERE WE EXPECT THEM? + CAIE T,PARFX5 + JRST 4,. + AC7CTX + UMOVE C,0 ;GET CONTENTS OF LOCATION WITH BAD PARITY + SYSCTX +] ;IFE KA10P + SETO T, ;MAKE SURE T ISN'T ACCIDENTALLY 0 AT PARFX6. + HRRZ E,TT + LSH E,10. + IOR E,B ;MAKE MEM ADR + CAIGE E,20 ;PAR ERR IN SHADOW ACS ISN'T SERIOUS. + JRST PARFX6 + ANDM E,PARAAN ;UPDATE ANDS AND ORS OF DATA AND ADRS + IORM E,PARAOR + ANDM C,PARAND + IORM C,PARIOR + MOVE A,USRHI + CAIGE E,USRSTG(A) + SETOM PARDIE ;PARITY ERROR IN EXEC CORE + HRRZ T,TT + CAIL T,TSYSM + JRST PARFX6 + LDB T,[MUR,,MEMBLT(TT)] + CAIE T,MUFR + CAIN T,MUINP + JRST PARFX6 + CAIE T,MUDISB + CAIN T,MUFRT + JRST PARFX6 + CAIN T,MUDDT + JRST PARFX6 + SOJE T,PARFX6 ;USER + SETOM PARDIE ;ERR IN CRITICAL MEMORY (DISK DIR, ETC) +PARFX6: MOVEM C,400000+PAREP*2000(B) ;FIX UP MEMORY AS BEST WE CAN + MOVEM C,PARCON(D) ;SAVE LOSING CONTENTS + MOVEM E,PARADR(D) ;SAVE LOSING ADDRESS + CAIL D,MXPARS-1 ;OVERFLOWING BUFFER? + SOS D ;JUST DON'T CLOBBER STUFF. AT LEAST PARAND, ETC. WILL BE VALID. + JUMPN T,PARFX9 + PUSH P,D ;PAR. ERR IN USER MEMORY, + HRRZ D,TT + CAIL D,TSYSM + JRST PARFXA + PUSHJ P,UCPRL4 ;HAS ANY JOB WRITTEN IN THIS PAGE? + 400000,,PARFU1 + JUMPL D,PARFXB ;SOMEONE HAS; JUST GIVE EVERYONE AN INTERRUPT. + PUSHJ P,UCPRL4 ;DOES MMP SAY PAGE WAS WRITTEN? IF SO, SET SIGN(D); + 200000,,PARFU2 ;OTHERWISE, SET MMPBAD, CAUSING PAGE TO BE RELOADED FROM DISK. + JUMPGE D,PARFXA +PARFXB: PUSHJ P,UCPRL4 ;PAGE HAS BEEN WRITTEN SINCE LAST ON DISK, SO WE CAN'T ESCAPE + 400000,,PARFU3 ;GIVING EVERY JOB AN INTERRUPT. +PARFXA: POP P,D +PARFX9: AOS B ;INCREMENT B HERE SO YOU DON'T HACK THE SAME + ; WORD AGAIN. IF THAT WORD WAS SOLIDLY BAD, + ; THIS CODE WOULD LOOP + CAIG B,1777 ;MIGHT BE DONE WITH PAGE + AOJA D,PARFX1 + AOJA D,PARFX8 + +PARFU1: CAIG U,LUBLK + SETOM PARDIE ;SYS JOB OR CORE JOB HAS PAGE + PUSH P,Q + MOVE A,I ;FIND PAGE-MAP HALFWORD FOR THIS PAGE + PUSHJ P,UPLC + POP P,Q + LDB A,T + LSH A,-20 + CAIE A,1 ;MAP SET UP TO A PAGE, AND IN READ-ONLY MODE? + JRST PARFU5 + DPB A,T ;YES, UNMAP IT SO THAT NEXT ACCESS WILL TRAP AND GO TO CFHPB + SOS MMSWP(D) ; IN CASE WE WILL SET MMPBAD. + ;NOTE, THIS MAY CRASH THE SYSTEM IF THE JOB WAS RUNNING IN A UUO, + ;HAD CHECKED ACCESS TO THE PAGE, AND WAS ASSUMING IT COULD ACCESS + ;IT AGAIN SAFELY. USUALLY THIS ONLY HAPPENS WHEN WRITING, HOWEVER. +IFN SWPWSP, ;DON'T BOTHER ADJUSTING WORKING SET. WILL BE FIXED ON NEXT SWAPIN. +PARFU5: CAIL A,3 +PARFU4: TLO D,400000 ;IF THIS JOB HAS WRITTEN THE PAGE, SET SIGN (D) + POPJ P, ;TO SIGNAL THAT SETTING MMPBAD IS NO USE. + +PARFU2: MOVE T,(C) ;C HAS ADDR OF MMP ENTRY; HAS PAGE BEEN WRITTEN BY A JOB + TLNN T,MMPWRT ;THAT NO LONGER HAS IT IN MAP? + TLNN T,MMPWOD ;OR HAS IT NEVER BEEN ON DISK? + JRST PARFU4 ;IF SO, AVOID SETTING MMPBAD, AND INTERRUPT EVERYONE. + HLRZ T,1(C) + JUMPE T,PARFU4 ;DITTO IF THERE IS NO DISK SPACE ASSIGNED. + MOVSI T,MMPBAD + IORM T,(C) + POPJ P, + +PARFU3: MOVSI T,(%PIPAR) + IORM T,PIRQC(U) + POPJ P, + +MEMHNG: +IFN PDP6P,[ + LDB B,[221100,,UPJPC(U)] ;FAULT ADDR + TRZN B,400 ;SKIP IF REFERENCE WAS VIA USER MAP + JRST MEMHN1 + MOVEI C,UPGMP(U) + ROT B,-1 + ADDI C,(B) + HRLI C,PMLCAD ;POINTER TO CORE ADR FIELD OF LH PAGE IN MAP WD + SKIPGE B + HRLI C,PMRCAD ;RH MAP WD + LDB C,B ;C GETS PAGE # + CAIGE C,+LPDP6M + CAIGE C,PDP6BM_-10. + JRST MEMHN1 + MOVE B,CLKBRK + TLNE B,%PCUSR + JRST MEMHN3 ;USER MODE PDP6 NXM + MOVEI B,IOCER3 ;PDP6 MEM + HRRM B,CLKBRK + JRST MEMHN2 +] + +MEMHN1: ;NXM + ; JRST 4,.+1 ;COMMENTED OUT SINCE NXM STOP SHOULD ALWAYS BE SET. +MEMHN2: +IFN KA10P,CONO 10000+APRCHN ;CLEAR NON EX MEM AFTER HALT TO RESET MEMORY +IFN KL10P,CONO 22000+APRCHN +IFN KS10P,[ + CONO 20400+APRCHN ;Clear APR flag + MOVSI B,%KEHLD+%KEREF ;Clear saved error address + IOWR B,[KSECCS] +] ;KS10P + MOVSI B,SCLNXM + TDNE B,SUPCOR ;Haven't printed previous error? + BUG PAUSE,[TOO MANY NXM ERRORS.] + IORM B,SUPCOR + MOVE T,CLKBRK + MOVEM T,NXMPC + MOVE T,USER + MOVEM T,NXMUSR + AOS NXMERR + POPJ P, + +IFN PDP6P,[ +MEMHN3: MOVSI B,%PIMPV ;PDP6 NXM GIVE MPV INTERRUPT + IORM B,PIRQC(U) + JRST MEMHN2 +] + SUBTTL SLOW CLOCK SERVICE ROUTINE + +OVHMTR SLW ;SLOW CLOCK + +SSLCK: SKIPGE SHUTDN ;SYSTEM "DEAD" => + PUSHJ P,COFFIN ;GO TO DDT AFTER RIGOR MORTIS SETS IN. + SETCMB A,SCKPHS ;CHECK SYSTEM CHECKSUMS EVERY OTHER SLOW CLOCK TICK + MOVE T,SUPCOP ;WHICH IS ONCE PER SECOND. + SKIPE A + IORM T,SUPCOR +IFN KS10P,[ + CONSO 100 ; Check for memory ECC corrected errors + JRST SSLCK0 + IORD A,[KSECCS] ; A: status and error addr + MOVEM A,ECCERA ; Remember most recent one + AOS ECCERR ; Also count 'em + CONO 20100+APRCHN ; Clear memory ECC APR flag + MOVSI T,%KEHLD+%KEREF ; Clear status and error addr + IOWR T,[KSECCS] + MOVE T,A + AND A,ECCAND ; A: AND of previous errors + IOR T,ECCIOR ; T: IOR of previous errors + CAMN A,ECCAND ; If either changes, this is news. + CAME T,ECCIOR + BUG INFO,[MEMORY: ECC CORRECTED ERROR],OCT,ECCERA + MOVEM A,ECCAND + MOVEM T,ECCIOR +SSLCK0: ] ;IFN KS10P +IFN NETP,PUSHJ P,NETCLK ; Run 1/2 sec clock routines for various net stuff +IFN NETYS, SETOM DTECHK ;TELL 11 WE'RE ALIVE +IFN DPKPP,[ + CONSO DPK,7 + CONO DPK,TTYCHN ;CROCK - IF DPK LOSES ITS PIA, GIVE IT BACK. +] + MOVE A,UTTBF + CAIGE A,30 + JRST SSLCK2 + SETOM UTBFLF ;SIGNAL CORE JOB TO FLUSH UTAPE BUFFERS + AOS NCORRQ +SSLCK2: SKIPE UTTYCT ;SKIP IF NO NEW USERS + SKIPL TREESW ;SKIP UNLESS SOMEBODY'S MUNGING THE TREE STRUCTURE. + CAIA + PUSHJ P,USTART ;NEW USER TO START +IFN 340P,[ + SKIPL T,DWDS + MOVEI T,0 + ADDI T,MDISWD + MOVEM T,DWDS ;RESET DISPLAY RATE COUNTER +] + CONO PI,UTCOFF ;UTC OFF WHILE HACKING UTAPE, MTAPE, DISK, ETC. +IFN RH10P+RH11P,[ + SKIPLE USFHLT + SOS USFHLT +];RH10P+RH11P +IFN NUNITS,[ +IFE NEWDTP,[ + MOVE T,TIME + AOSN UIDLE ;SKIP IF DEC TAPE NOT IDLE + JRST [MOVEM T,LUTOTM ? JRST SSLCK1] ;DEC TAPE IDLE + SUB T,LUTOTM ;SUBTRACT LAST UTC OPERATION TIME + CONSO UTC,4000 + CAIGE T,MXOPT*SCLKI ;SKIP IF DEC TAPE HUNG TOO LONG ON ONE OPERATION + JRST SSLCK3 ;OK + SETOM UTHERR ;SET UTC HUNG ERR FLAG +SSLCK1: CONO UTC,CUINT ;CAUSE DEC TAPE INTERRUPT ROUTINE TO RUN +SSLCK3: +] +IFN NEWDTP,[ + MOVE T,TIME + AOSN UIDLE + JRST [MOVEM T,LUTOTM ? JRST SSLCK1] + SUB T,LUTOTM + CAIGE T,MXOPT*SCLKI + JRST SSLCK3 + SETOM UTHERR +SSLCK1: SETOM CUINT + CONO PI,UTCRQ +SSLCK3: +]] ;END IFN NUNITS + SKIPL QSDU ;IF DISK TRANSFER IN PROGRESS + JRST [ MOVE T,LQTM ;SEE IF IT'S TAKING UNREASONABLY LONG TIME + ADDI T,5*30. + CAMGE T,TIME + PUSHJ P,QHUNG ;YES, UNHANG THE DISK + JRST .+1 ] +IFN T300P,[ + SKIPL QSDU1 ;IF TRANSFER IN PROGRESS ON OTHER CONTROLLER + JRST [ MOVE T,LQTM1 ;SEE IF IT'S TAKING UNREASONABLY LONG TIME + ADDI T,5*30. + CAMGE T,TIME + PUSHJ P,QHUNG1 ;YES, UNHANG THE DISK + JRST .+1 ] +];T300P +IFN DC10P, PUSHJ P,QRCTMO ;RECALIBRATE TIMEOUT + CONO PI,UTCON + PUSHJ P,QSTRTR ;WAKE UP DISK ROUTINES +IFN NMTCS, PUSHJ P,MSTRTR ;WAKE UP MAG TAPE ROUTINES (MUST BE SEPARATE INTR) +;DROPS THROUGH + +;DROPS IN +IFG NMTYS,[ ;TRY TO UNHANG MORTON TTY CARDS + MOVE I,[-NMTYS,,NFMTY] + MOVE T,TIME + SUBI T,60. ;IF HAVEN'T TYPED FOR 2 SECONDS +SSLCM1: SKIPL TTYOAC(I) ;YET SUPPOSED TO BE TYPING + CAMGE T,TTLTM(I) + JRST SSLCM2 + CONO PI,TTYOFF-1 + CONO MTY,@TTYLT(I) ;SELECT THE LINE + DATAO MTY,[0] ;AND BANG ON IT + CONO PI,TTYON-1 ;MAYBE IF WE'RE LUCKY ITS DONE FLAG WILL COME ON +SSLCM2: AOBJN I,SSLCM1 +] ;END IFG NMTYS +IFN IMPP,[ +IFN KAIMP, CONI IMP,IMPCNI ;KEEPS HOST READY ON +IFE KSIMP,[ + ;KS doesn't drop interrupts, I hope + PUSHJ P,IMPOST ;START UP OUTPUT +] +IFN NCPP,[ + SKIPLE IMNCS + PUSHJ P,IMPCCL ;CLOSE NETWORK CHANNELS + SKIPLE IMNAS + PUSHJ P,IMPAAA ;WAKE UP STYS THAT NEED IT +];NCPP + SKIPGE IMPTCU ;IF IMP IS TRYING TO COME UP + AOSE IMPUCT ;AND UP-COMING TIMEOUT EXHAUSTED + JRST SSLCK8 + BUG INFO,[NET: TIMED OUT TRYING TO COME UP] + MOVEI A,1 ;THEN MAKE IT STAY DOWN + MOVEM A,IMPUP ;IF THIS IS ML-KA THE IMP CABLE PROBABLY BROKE AGAIN +SSLCK8: +];IMPP +IFN PDP6P,[ + SKIPL PDPISR + CONO DSDEV,DSDCHN ;ENABLE INTERRUPTS FROM 6 +];PDP6P +IFN NETYS,[ + SKIPE DTEBBY + SOSL DTEBBT + JRST .+3 + BUG CHECK,[TTY: TIMEOUT ON OUTPUT XFER TO DTE, DTEBBY],OCT,DTEBBY + SETZM DTEBBY +];NETYS +IFN N11TYS,[ +;SEE IF THE TV PDP11 WANTS TO GO DOWN. + SKIPN TEN11F ;PROVIDED THE PDP11 IS THERE, + SKIPN TT11P ;AND WE'RE TRYING TO USE IT, + JRST SSLCK5 + LDB A,[061600,,TT11HA] ;DOES 11 WANT WHO LINES UPDATED? + CAIL A,2000*NTTPG ;RANGE CHECK SO CLOBBERED 11 MEMORY DOESN'T CAUSE ILL MEM REF + BUG HALT,[GARBAGE POINTER IN TV-11 MEMORY] + SKIPGE 1+400000+TTPG0*2000(A) + JRST [ MOVEI T,SCRWHO ;YES + IORM T,SUPCOR + CLEARM 1+400000+TTPG0*2000(A) + JRST .+1] + SKIPE TT11DN ;IF IT IS REQUESTING TO GO DOWN, + JRST SSLCK5 + SETZM TT11P ;DON'T USE IT & WAIT FOR IT TO RE-INIT, + MOVSI T,1 + MOVEM T,TT11DN ;GIVE IT OUR PERMISSION TO GO DOWN. + MOVEI T,SCR11D ;CAUSE "11 DOWN" MESSAGE + IORM T,SUPCOR +SSLCK5: SKIPN TEN11F + SKIPG TT11P ;WAITING FOR 11 TO BE UP? + JRST SSLCK6 + SKIPN TT11UP ;SKIP ON 11 UP + JRST SSLCK6 + MOVEI T,SCR11U + IORM T,SUPCOR ;INIT THE TTYS +SSLCK6: +] + SKIPLE T,AGERTE ;IF IT'S ENABLED, AGE SOME PAGES + PUSHJ P,AGE +;DROPS THROUGH + +;DROPS IN +IFN DL10P,[ + SKIPN DL10F + JRST SSLCKA + SETOM DL10UP ;COULD ALSO CHECK WHETHER PDP11 IS INCREMENTING THIS. + DATAI DLC,A + TRNE A,20 ;SEE IF PDP11 HALTED. + JRST SSLCKA + BUG INFO,[I/O PDP11 WENT DOWN] + SETZM DL10F + MOVEI T,%TYDL + MOVSI A,-NCT + TDNE T,TTYTYP(A) + SETOM TTYOAC(A) + AOBJN A,.-2 +SSLCKA: ] + AOS QACTTM ;Bump this for benefit of QSK dir writers. + SKIPN SWPOPR ;If there is a request to swap out pages + SKIPE SOLNG ; or if there are pages now going out + JRST SSKQ2 ; do not bother with LMEMFR, warnings. + MOVN A,LMEMFR ;See how many free low-memory pages. + ADD A,MINCOR + JUMPLE A,SSRCK ;Okay + AOS NCORRQ ;Wake up core job to do some shuffling + SUB A,MEMFR + ADD A,LMEMFR ;Core wanted minus high free + SKIPLE A + ADDM A,SWPOPR ;Swap out to make room. +;Check to see if we are running out of various resources. +;RSWTIM is a timestamp of last warning, initialized by DATIM6 and PDDCHK. +SSRCK: MOVE A,RSWTIM ;Get time we last checked. + ADDI A,2*30. + CAML A,TIMOFF ;If we checked less then 30 secs ago + JRST SSKQ2 ; don't deluge the console. + MOVE A,TIMOFF ;Else remember that we are cheking now. + MOVEM A,RSWTIM + MOVEI A,5 ;There should be at least 5 free low pages. + CAMLE A,LMEMFR ;If there are not, print warning. + BUG INFO,[Warning: Just ],DEC,LMEMFR,[ free pages in low core.] + SKIPN QFCHN ;Check disk channels. + BUG INFO,[Warning: No free qsk channels.] + MOVN A,USRHI ;Check job slots. + IDIVI A,LUBLK + ADDI A,MAXJ + SKIPN A + BUG INFO,[Warning: System full - no job slots.] +SSKQ2: +IFN 340P,[ + SKIPL DISUSR + PUSHJ P,DISCHK ;CHECK FOR 340 DEATH +] + PUSHJ P,PDCCHK ;CHECK ON REAL-TIME HACKS +IFN PTRP,[ + PUSHJ P,PTRCHK ;CHECK ON PAPER TAPE READER + PUSHJ P,PTPCHK ;CHECK ON PAPER TAPE PUNCH +] ;PTRP +IFE KS10P,[ ; Silly KS10 doesn't have devices... + SKIPN CCSDEV + JRST SCDCK3 + SETZM CCSDEV + MOVSI I,-128. +SCDCK1: SKIPGE A,DCHNTC(I) + TLNE A,300000 + JRST SCDCK2 + AOS CCSDEV + SUB A,[1,,] + TLNN A,777 + TLZ A,400000 + MOVEM A,DCHNTC(I) +SCDCK2: AOBJN I,SCDCK1 +SCDCK3:; JSP E,CHECK ;CHECK FOR CLOBBERED DEVICES +] ;IFE KS10P +IFN NLPTP,[ + CONO PI,LPTOFF + MOVE A,NLPTBR ;IF LPT OUTPUT BUFFER NOT EMPTY + CAIN A,LPTBSZ + JRST [ CONSZ NLPT,100 ;AND LPT IS READY + CONSZ NLPT,7 ;BUT HAS NO PIA + JRST .+1 + CONO NLPT,LPTCHN ;THEN IT LOST AGAIN + AOS NTNLPL ;COUNT NUMBER OF TIMES NEW LPT LOST + JRST .+1 ] + CONO PI,LPTON +] +IFN ECCMEM,[ +;THIS ASSUMES THAT THE PDP-10/XBUS ADDRESS OFFSET IS ZERO +ECCLOG: MOVE B,400000+ECCPG*2000+1760 + LSH B,-32. + CAMN B,ECCIDX ;DID ECC HISTORY POINTER ADVANCE? + JRST ECCLG9 + AOS A,ECCIDX ;YES, GET NEXT WORD FROM ECC HISTORY + MOVE B,400000+ECCPG*2000+1760-1(A) + ANDI A,17 ;ADVANCE OUR COPY OF POINTER + MOVEM A,ECCIDX + LDB A,[240700,,B] ;SYNDROME BITS + TLZ B,777774 ;REDUCE B TO ADDRESS BITS + BUG INFO,[MEM: ECC ERROR, ADDRESS ],OCT,B,[SYNDROME],OCT,A + JRST ECCLOG ;LOOK FOR MORE HISTORY + +ECCLG9: +];ECCMEM + PUSHJ P,GPDTIM ;WHAT CALENDAR TIME IS IT? + SETOB A,LPDTIM + EXCH A,LPDTIM ;REMEMBER IT FOR NEXT CLOCK TICK. + JUMPL A,ALCR0 ;TIME NOT KNOWN THIS AND/OR LAST TICK => DO NOTHING + SUB A,LPDTIM ;ELSE HOW LONG HAS IT BEEN SINCE PREVIOUS TICK? + CAML A,[-5*PDUPS] ;MORE THAN 5 SECONDS? SHOULD ONLY BE 1/60 + JRST ALCR0 ;ONLY EXPLANATION IS ITS WAS STOPPED AND CONTINUED. + SKIPL SYSDBG ;SO UNLESS THAT'S NORMALLY EXPECTED + PUSHJ P,DEATHM ;TELL THE WORLD "ITS REVIVED" + MOVE T,TIME ;REMEMBER WHEN THIS LAST HAPPENED + MOVEM T,RVVTIM + +;DROPS THROUGH + +;DROPS IN +;DECAY VARIOUS EXPONENTIAL AVERAGES. ON KA10, RUN IN ACS SINCE IT'S FASTER. +;ON KL10, DON'T, SINCE IT'S SLOWER. ON KS10, DON'T, BECAUSE IT IS +;JUST AS FAST TO RUN IN THE ACS BUT IT WASTES TIME TO MOVE THE CODE +;INTO THEM. +ALCR0: MOVSI U,-NCT + SETZM SLOADU +IFN KA10P,[ + MOVE I,[ALCR1,,A] + BLT I,I + JRST A +] ;KA10P + +ALCR1: MOVN T,USRRCE(U) ;A ;DECAY USRRCE AVERAGES + ASH T,-4 ;B + ADDB T,USRRCE(U) ;C + CAMLE T,SLOADU ;D ;AND SET SLOADU TO HIGHEST USRRCE + MOVEM T,SLOADU ;E +IFN KA10P,[ + AOBJN U,A ;TT + JRST .+1 ;I +] ;KA10P +IFE KA10P, AOBJN U,ALCR1 + + MOVN T,USRRCE+NCT + ASH T,-4-2 ;DISOWNED JOBS (DECAY SLOWER) + ADDB T,USRRCE+NCT + IMULI T,1999. ;MAKE COMMENSURATE WITH REGULAR USRRCE'S + ASH T,-13. ; (You might think that you could just + ; divide by 4, but in fact the ratio + ; between the two decay rates is + ; ln(64/63)/ln(16/15) = .24401474) + ADDM T,SLOADU ;DISOWNED TIME COULD HAVE BEEN USED BY REAL + ; USERS + MOVN T,USRRCE+NCT+1 + ASH T,-4+1 ;SYS, CORE, AND SOME DAEMON JOBS (DECAY FASTER) + ADDM T,USRRCE+NCT+1 + IRPS RCE,,LOSRCE IDLRCE + MOVN T,RCE ;LOST TIME AND IDLE TIME + ASH T,-4 + ADDB T,RCE + TERMIN + ADDM T,SLOADU ;IDLE TIME COULD HAVE BEEN USED BY USERS + +IFE KS10P, MOVE A,[193682794.] ; = 100. * 250000. * .5 / ln(16/15) + ; (100% of 250000. four usec ticks per second, + ; decaying by 16/15 every .5 second.) +IFN KS10P, MOVE A,[198524864.] ; = 100. * 256250. * .5 / ln(16/15) + ; (256250. 3.9 usec ticks per second.) +; Used to be: +; MOVE A,[100.*15.*125000.] ;100% DIVIDED BY MAXIMUM SINGLE TREE % + ADD A,LOSRCE ;WITH FUDGE FACTOR FOR LOST TIME + IDIVM A,SLOADU ;GIVES EFFECTIVE # OF COMPETITORS FOR MACHINE. +; It is possible for SLOADU to drop below 100. (giving a fair share greater +; than 100%). This happens because the decay rate for disowned jobs is +; less than the decay rate for consoles. If the load switches abruptly +; from the disowned jobs to some console, the resource word for the console +; fills up quicker than the disowned resource word decays, causing their +; sum to briefly exceed the maximum. This would be hard to fix without +; introducing additional resource words just for better maintaining SLOADU. +; +; An additional odd effect: If only disowned jobs are running, and a +; network server starts up, the fair share drops almost to zero. This is +; because when such jobs are created, their resource word is zeroed to +; given them an initial priority boost. + + MOVEI T,0 +IFN KA10P,[ + MOVE W,[ALCR4,,A] + BLT W,W + JRST A +] ;KA10P + +ALCR4: MOVN H,JTMU(T) ;A + ASH H,-4 + ADDM H,JTMU(T) + MOVE H,MSKST(T) + ANDI H,%PICLK ;E + SKIPE UNAME(T) ;TT + IORM H,PIRQC(T);I + ADDI T,LUBLK ;Q + CAMGE T,USRHI ;J +IFN KA10P,[ + JRST A ;R + JRST .+1 ;W +] ;KA10P +IFE KA10P, JRST ALCR4 +;DROPS THROUGH + ;DROPS IN +IFN SWPWSP,[ + MOVE U,USRHI + SUBI U,LUBLK ;ACCOUNT FOR I/O WAIT TIME IN USWPRI + MOVSI T,%SWOUT+%SWPGW +IFN KA10P,[ + MOVE J,[ALCR5,,A] + BLT J,J + JRST A +] ;KA10P +ALCR5: SKIPE UNAME(U) ;A ;IGNORE JOBS WHICH DON'T EXIST OR + TDNE T,USWST(U) ;B ;ARE SWAPPED-OUT OR IN PAGE-WAIT +IFN KA10P, JRST I ;C +IFE KA10P, JRST ALCR6 + SKIPN USTP(U) ;D ;CHARGE JOBS WHICH ARE STOPPED + SKIPE FLSINS(U) ;E ;OR BLOCKED + JRST ALCR7 ;TT +ALCR6: SUBI U,LUBLK ;I ;NEXT JOB +IFN KA10P,[ + JUMPG U,A ;Q + JRST .+1 ;J +] ;KA10P +IFE KA10P, JUMPG U,ALCR5 +];SWPWSP + SKIPGE 37 ;CHECK FOR PLANNED SYSTEM DEATH + PUSHJ P,DEATH ;ABOUT TO START DYING + JFCL + IRPS 4US,,[IDLTM1 LOSTM1 USRTM1 NULTM1]SEC,,[IDLTIM LOSTIM USRTIM NULTM3] + MOVE A,4US ;KEEP SYSTEM WIDE USAGES AS TWO WORDS + IDIVI A,250000. ;ONE IN 4.069 USEC UNITS + ADDM A,SEC ;AND ONE IN SECONDS + MOVEM B,4US ;SO NO OVERFLOW + TERMIN + IMULI A,60. ;CONVERT TO 60THS + ADDM A,NULTIM ;ADD TO 60THS USED (OBSOLETE) + MOVEI T,SCLKI + MOVEI C,SSLCKB + JRST CLQREE ;RE-ENTER RQ FOR SLOW CLOCK BREAK + +IFN SWPWSP,[ ;JOB IN U NEEDS TO BE CHARGED FOR MEMORY USED WHILE BLOCKED OR STOPPED +ALCR7: HLLO W,UWRKST(U) + JFFO W,.+1 ;H GETS 19 - LOG(WORKING SET SIZE + 1/2) + SUBI H,19. + IMUL H,[-125000.] ;CHARGE FOR 1/2 SECOND OF MEMORY USAGE + ADDM H,USWPRI(U) +IFN KA10P, JRST I +IFE KA10P, JRST ALCR6 +];SWPWSP + +;SYSTEM IN FINAL THROES OF COMING DOWN, SEE IF IT'S OVER YET + +COFFIN: MOVE T,NLOOSP ;MUST SWAP OUT ALL LOOSE PAGES + ADDB T,SWPOPR + JUMPN T,CPOPJ ;SWAPPAGE OUT STILL GOING ON + MOVEI T,NQCHN+1+NQS-1 + SKIPGE QSGL(T) + SOJG T,.-1 + SKIPL QSGL(T) ;NOT OVER IF ANY DISK CHANNELS ARE ACTIVE + POPJ P, + MOVSI T,040000 + MOVE TT,QACTB ;SEE IF DISK STUFF NOT OUT YET + TDNE TT,QMDRO + POPJ P, ;MFD NOT OUT + MOVSI A,-NQS +COFFI8: TDNE T,QTUTO(A) + JRST COFFI9 ;TUT NEVER CAME IN + TDNE TT,QTUTO(A) + POPJ P, ;TUT NOT OUT +COFFI9: AOBJN A,COFFI8 + MOVSI A,-QNUD +COFFI1: SKIPN QSNUD(A) + JRST COFFI2 + TDNE TT,QSNLCN(A) + POPJ P, ;UFD NOT WRITTEN +COFFI2: AOBJN A,COFFI1 + +IFN NUNITS,[ + MOVSI A,-NUNITS + SKIPGE UFLAPF(A) + POPJ P, ;TAPE STILL FLAPPING + AOBJN A,.-2 +] + MOVE A,DTHTIM + ADDI A,15.*30. ;DON'T WAIT FOR CONSOLES MORE THAN 15 SECONDS + CAMGE A,TIME ;BECAUSE %TCHNG ISN'T NECESSARILY SET + JRST COFFI3 + MOVEI A,NFSTTY-1 ;CHECK FOR REAL CONSOLES STILL TYPING OUT + MOVSI T,%TCHNG ;AND NOT HUNG (NEVER GOING TO FINISH TYPING OUT) + TDNN T,TTYCOM(A) + SKIPGE TTYOAC(A) + SOJGE A,.-2 + JUMPGE A,CPOPJ ;A CONSOLE IS STILL TYPING, DON'T GO DOWN YET +COFFI3: SKIPL A,SYSCN + SKIPGE TTYOAC(A) + CAIA + POPJ P, ;SYSTEM CONSOLE HAS A LOT OF TYPING TO DO + MOVEI A,2*LUBLK +COFFI7: CAML A,USRHI + JRST COFFI4 + SKIPE UNAME(A) + POPJ P, ;JOBS STILL EXIST + ADDI A,LUBLK + JRST COFFI7 + +;SYSTEM FULLY DOWN; GO TO DDT. +COFFI4: BUG DDT,[SHUTDOWN COMPLETE] + SETZM SHUTDN ;IF USER PROCEEDS, BRING SYSTEM BACK UP + SETZM DEDTIM ;ARRANGE TO RELOAD ATSIGN DRAGON + SETZM FLSINS ;BY RESTARTING SYS JOB WHERE IT DOES THAT + MOVEI A,ISYS + MOVEM A,UPC + POPJ P, + +;ROUTINE TO AGE SOME PAGES. THIS ROUTINE SLOWLY CIRCULATES THROUGH +;CORE. IF IT TOUCHES A PAGE TWICE, AND NO USER HAS TOUCHED IT, +;THE PAGE GETS SWAPPED OUT. ALSO FLUSHES PAGES NOT IN ANY USER'S MAP. +;ENTER WITH VALUE OF AGERTE IN T. + +AGE: MOVE TT,MEMFR + CAIL TT,100 + POPJ P, ;NO MEMORY COMPETITION, DON'T BOTHER + ADD T,AGEREQ ;INCREASE NUMBER OF PAGES NEEDING TO BE AGED + CAIGE T,100 ; BUT DON'T LET IT GET INFINITELY HUGE + MOVEM T,AGEREQ ; IF CIRPSW IS LOCKED FOR A LONG TIME + SKIPN DLSRCH ;IF MUSTN'T PCLSR ANYONE, OR + SKIPL CIRPSW ; IF CIRPSW LOCKED, HAVE TO WAIT UNTIL NEXT SLOW CLOCK + POPJ P, + LDB W,[121000,,HUSRAD] ;DON'T AGE SYSTEM JOB (CIRC PNTRS NOT CONNECTED) + MOVE A,AGEPOS ;CONTINUE AGEING FROM WHERE LEFT OFF LAST TIME + SKIPGE U,USER ;CHECK FOR NULJOB + JRST AGE0 + MOVE T,CLKBRK ;PC FOR USER WHO MAY GET PCLSR'D + MOVEM T,UPC(U) .SEE SWOP2 + LPMR UPGML(U) ;DON'T LEAVE SWAPPED OUT PAGES IN ASSOC MEM +AGE0: CAIGE A,TSYSM + CAMGE A,W + MOVE A,W + SOSGE AGEREQ + JRST [ MOVEM A,AGEPOS ? SETZM AGEREQ ? POPJ P, ] + AOS NAGES + LDB T,[MUR,,MEMBLT(A)] + CAIE T,MURUSR + AOJA A,AGE0 + MOVE D,A + PUSHJ P,UCPRL4 + SETZ AGE1 + MOVNI C,1 ;NO USERS ACTIVELY USING THIS PAGE, SWAP IT OUT + PUSHJ P,SWPOPG + JFCL + AOJA A,AGE0 + +AGE1: MOVEI C,UPGMP(U) + MOVE T,I ;DON'T CLOBBER I + ROT T,-1 + ADD C,T + HRLI C,222200 + SKIPGE T + HRLI C,2200 + LDB T,C ;GET PAGE MAP WORD + TRNN T,600000 + POPJ P, ;USER NOT CONNECTED TO THIS PAGE + TROE T,PMAGEM + POPJ P, ;HASN'T TOUCHED THIS PAGE SINCE AGE BITS LAST SET + DPB T,C ;HAS TOUCHED PAGE, TURN AGE BITS BACK ON + SUB P,[4,,4] ;AND BACK OUT OF UCPRL + AOJA A,AGE0 + +IFN 340P,[ + +DISCHK: SKIPGE DISOFF + POPJ P, + AOSLE DISDIE + SKIPGE CDISOFF + POPJ P, + MOVEI T,1 + MOVEM T,DTIME +DISZAP: MOVE T,[JSR DBLKPB] + MOVEM T,40+2*DISCHN + MOVEI T,DIS300-1 ;CAUSE 340 TO STOP AND INTERRUPT SOON + MOVEM T,DBLKOP + CLEARM DISOFF + CONO DIS,5100+SDCHN_3+DISCHN + POPJ P, +] + +DEATH: SKIPL SHUTLK + POPJ P, + SETZM 37 ;CLEAR START DYING FLAG + MOVEI T,60.*5.*60. ;5 MIN + MOVEM T,DEDTIM + LSH T,-1 + ADD T,TIME + MOVEM T,SHUTDN + PUSHJ P,CLQDEL + DEDBLK +DEATHX: SKIPN T,DEDTIM + POPJ P, + AOS (P) + MOVEI TT,0 + CAIGE T,40.*60. + JRST DEATHY + MOVE TT,T + LSH TT,-2 +DEATHY: MOVEM TT,DEDTIM + SUB T,TT + PUSHJ P,CLQADD + DEDBLK +DEATHM: MOVEI A,%PIDWN + PUSHJ P,INTALL ;TELL THE WORLD + MOVSI T,SCLSHD ;CAUSE TYPE OUT ON UNLOGGED-IN CONSOLES +SUPSET: IORM T,SUPCOR + POPJ P, + +VSSLCK: MOVSI T,SCLVSK + IORM T,SUPCOR ;CAUSE VERY SLOW CLOCK TO RUN + MOVEI T,VSCLKI + MOVEI C,VSLCKB + JRST CLQREE + +IFN CCLKP,[ +RCCLK: DATAI 374,T ;HACK CHESS CLOCK + TRNE T,4000 + AOSA CCLK1 + AOS CCLK2 + MOVEI T,6 + MOVEI C,CCLKB + JRST CLQREE +] + +IFN N11TYS,[ +WHOSET: MOVEI T,SCRWHO ;CAUSE SYS TO UPDATE WHO LINES + IORM T,SUPCOR + MOVEI T,5.*60.-5 ;5 SECONDS MINUS A LITTLE SO DOESN'T SYNC WITH OTHER CLOCKS + MOVEI C,WHOCLB + JRST CLQREE +] + +SUBTTL SWAP SCHEDULER + +OVHMTR SWS ;SWAP SCHEDULER + +;15 SECOND CLOCK +15SCLK: +IFN IMPP, PUSHJ P,IMRSTO ;RESET CONTROL LINK RFNM WAIT FOR LOSING IMP. + +;RECOMPUTE SWAP BLOCK DATA. +;DECAY SWAP PRIORITIES (USWPRI AND SWRCE) +;RESET BEST-EFFORT-HAS-BEEN-MADE TO SWAP OUT BITS + + MOVSI B,%SWBEM ;SET UP TO CLEAR "BEST EFFORT TO SWAP OUT BIT" + SETOM SBEFLG ;NOT YET DESPERATE ENOUGH TO TRY USERS WHOSE BEST EFFORT BITS ARE SET +IFE SWPWSP,[ + CLEARB T,NUSWB ;# USERS LOCKED OUT + SETOM BUSR ;SMALLEST SWAPPED BLOCKED USER + MOVE D,[37777,,777777] + MOVEM D,BUSIZ ;SIZE OF SMALLEST SWAP-BLOCKED USER. + CLEARM ASBUM ;REAL MEM OCC BY ACTIVE SWAPPED BLOCKED LOSERS + MOVSI D,400000 ;TO CLEAR SWAPPED BLOCKED BIT +];SWPWSP +.ELSE MOVEI T,LUBLK*2 +15S1: CAML T,USRHI + JRST 15S2 + SKIPN UNAME(T) + JRST 15S3 + MOVN C,USWPRI(T) + ASH C,-2 + ADDM C,USWPRI(T) ;DECAY JOB SWAP PRI'S + MOVE C,NMPGS(T) +IFE SWPWSP,[ + SKIPE ENPZRO + SUBI C,1 ;COMPENSATE FOR PAGE ZERO ALWAYS IN +];SWPWSP + CAMLE C,NSWPGS(T) ;SKIP ON NOT COMPLETELY OUT + ANDCAM B,USWST(T) .SEE %SWBEM +IFE SWPWSP,[ + SKIPGE USWSCD(T) + JRST 15S4 ;CLEAR SWAPPED BLOCK BIT AND MAYBE ADD TO AUSOPG AND TRUMM (IF HE WAS HUNG ON IT) +];SWPWSP +15S3: ADDI T,LUBLK + JRST 15S1 + +15S2: +IFE SWPWSP,[ + SKIPE ENSWSC + PUSHJ P,SWSCD ;SWAP BLOCK LOSERS IF NECESSARY +];SWPWSP + MOVSI T,-NCT-2 +15S5: MOVN C,SWRCE(T) ;DECAY TREE SWAP PRI'S + ASH C,-2 + ADDM C,SWRCE(T) + AOBJN T,15S5 + MOVEI T,15.*60. + MOVEI C,15SCLB + JRST CLQREE + +IFE SWPWSP,[ +15S4: ANDCAM D,USWSCD(T) ;CLEAR SWAP BLOCK BIT + SKIPN TT,FLSINS(T) ;WAS HE HUNG TESTING IT + JRST 15S3 + SUBI TT,(T) + CAME TT,[SKIPGE USWSCD] + JRST 15S3 ;HE WASN'T HUNG ON THIS + CLEARM FLSINS(T) ;HE WAS SO NOW HES ACTIVE + MOVE TT,USWST(T) + TLZE TT,%SWPGW + SOS NPGWTU ;FLSINS WAS SET BY PAGE FAULT, SO CONSIDERED + TLZ TT,%SWBEM ;TO BE WAITING FOR A PAGE + MOVEM TT,USWST(T) + MOVE TT,NMPGS(T) + ADDM TT,TRUMM ;GUY IS NOW RUNNABLE + SUB TT,NSWPGS(T) ;ANY PAGES HE MAY HAVE IN MEM NO LONGER BELONG TO A BLOCKED USER + MOVNS TT + ADDB TT,BUMPGS + SKIPGE TT + CLEARB TT,BUMPGS + MOVE TT,NSWPGS(T) ;ANY SWAPPED OUT PAGES BELONG TO AN ACTIVE USER + ADDM TT,AUSOPG + JRST 15S3 +];SWPWSP + +IFE SWPWSP,[ + +PRVCLK: SKIPN ENPVCL + JRST PRVCK4 + MOVSI B,%SWPRV + SKIPL U,PRVUSR + ANDCAM B,USWST(U) + SETOM PRVUSR ;TURN OFF CURRENT PRIVILEDGED USER + MOVEI J,2*LUBLK +PRVCK1: CAML J,USRHI + JRST PRVCK2 + SKIPN UNAME(J) + JRST PRVCK3 + MOVE B,UTRNTM(J) ;GET USER RUN TIME + SUB B,LTRNTM(J) + MOVE A,USIPRQ(J) + SUB A,LSIPRQ(J) + IMUL A,[NPVSEC*125000.] ;1/2 NUMBER OF 4 MICROSECOND INTERVALS IN THE PRIV INTERVAL + SKIPE B + IDIV A,B + MOVE B,UPGSEC(J) + LSH B,-1 ;DIVIDE LAST VALUE BY TWO + ADD A,B + MOVEM A,UPGSEC(J) ; LAST/2 + CURRENT + MOVE A,UTRNTM(J) + MOVEM A,LTRNTM(J) + MOVE A,USIPRQ(J) + MOVEM A,LSIPRQ(J) ;SAVE OLD VARIABLES +PRVCK3: ADDI J,LUBLK + JRST PRVCK1 + +PRVCK2: PUSHJ P,NPRVUS ;GET NEXT PRIV USR +PRVCK4: MOVEI T,NPVSEC*60. + MOVEI C,PRVCLB + JRST CLQREE + +NPRVUS: MOVEI J,2*LUBLK + SETOM U + MOVNI T,30.*2 ;DON'T LET A BLOCKED OR STOPPED PERSON BE PRIVILEDGED + ADD T,TIME + MOVE B,PRVCUT + HRLOI E,377777 +NPVUS1: CAML J,USRHI + JRST NPVUS2 + CAMGE T,LUBTM(J) ;BLOCKED TOO LONG? + SKIPN UNAME(J) + JRST NPVUS3 + CAMG B,UPGSEC(J) + CAMG E,LPRVTM(J) + JRST NPVUS3 + MOVE U,J + MOVE E,LPRVTM(J) +NPVUS3: ADDI J,LUBLK + JRST NPVUS1 + +NPVUS2: MOVEM U,PRVUSR + SKIPG U + POPJ P, + MOVSI B,%SWPRV + IORM B,USWST(U) + MOVE T,TIME + MOVEM T,LPRVTM(U) + POPJ P, +];SWPWSP + +IFE SWPWSP,[ +IFNDEF MEMSYS,MEMSYS==50 ;GUESS AT AMOUNT OF MEM SYSTEM NEEDS +IFNDEF MEMSY1,MEMSY1==50 ;AMOUNT OF MEM ANY ONE USER MUST LEAVE TO "FIT". + +SWSCD: MOVE E,TRUMM ;SEE IF NECESSARY TO SWAP BLOCK SOMEONE + CAIGE E,TSYSM-SYSB-MEMSYS + POPJ P, ;NO SHOULD FIT + MOVE E,MEMFR + SUB E,NCBCOM + ADD E,SOLNG + SUB E,SILNG + SUB E,AUSOPG + ADD E,BUMPGS ;WILL SWAP OUT BLOCKED USERS FIRST + ADD E,ASBUM + SUBI E,20 ;SLOP + JUMPGE E,CPOPJ ;SHOULD HAVE ROOM FOR EVERYBODY + MOVMM E,SWSCT1 ;SAVE # PGS REQ + MOVNI E,1 ;NEED TO GRONK USER (MAYBE) + CLEARB T,TT ;TT SWP PRI OF PROCESS + MOVEI R,0 ;R SWP PRI OF TREE +SWSCP1: CAML T,USRHI + JRST SWSCP2 + SKIPE UNAME(T) + SKIPE USTP(T) + JRST SWSCP7 + SKIPGE USWSCD(T) + JRST SWSCP7 ;GUY ALREADY LOCKED OUT + SKIPE FLSINS(T) + JRST SWSCP4 ;SEE IF REALLY BLOCKED OR JUST PAGE WAIT +SWSCP5: MOVE B,UTMPTR(T) + CAML R,SWRCE-USRRCE(B) + CAMG TT,USWPRI(T) + JRST SWSCP6 ;THIS GUY A BIGGER LOSER THAT PREV BIGGEST +SWSCP7: ADDI T,LUBLK + JRST SWSCP1 + +SWSCP6: MOVE E,T + MOVE R,SWRCE-USRRCE(B) + MOVE TT,USWPRI(T) + JRST SWSCP7 ;GUY REALLY BLOCKED + +SWSCP4: MOVE B,USWST(T) + TLNE B,%SWPGW + JRST SWSCP5 + JRST SWSCP7 + + +SWSCP2: JUMPL E,CPOPJ ;NO VICTIM + MOVE B,NMPGS(E) + CAIGE B,TSYSM-SYSB-MEMSY1 + JRST SWSCP9 ;"SMALL LOSER" + SUB B,NSWPGS(E) + CAMLE B,SWSCT1 ;SKIP ON WILL STILL NEED TO BLOCK MORE LOSERS + POPJ P, +SWSCP9: MOVSI B,400000 + IORM B,USWSCD(E) ;SWAP BLOCK LOSER + AOS NUSWB + AOS NTUSB + MOVE TT,NMPGS(E) + CAMLE TT,BUSIZ + JRST SWSCP8 + MOVEM TT,BUSIZ + MOVEM E,BUSR +SWSCP8: SUB TT,NSWPGS(E) + SOSGE TT + MOVEI TT,0 + ADDM TT,ASBUM ;THIS GUY SWAPPED BLOCKED + MOVN TT,NMPGS(E) + ADDM TT,TRUMM ;DOESNT COUNT ANY MORE + SKIPGE TRUMM + CLEARM TRUMM + MOVN TT,NSWPGS(E) + ADDM TT,AUSOPG ;NOT REALLY ACTIVE ANY MORE + JRST SWSCD ;SEE IF THATS ENUF +];SWPWSP + +OVHMTR PPI ;PPIUM + +;PUT PAGE INTO USERS' MAPS (OF ALL USERS THAT ARE CONNECTED VIA CIRCULAR POINTERS) +;ALSO UPDATES THE WORKING SETS. +;CALL WITH PAGE NUMBER IN A, STARTING BYTE POINTER IN C, AND TDNE T,MMP IN D. +;SMASHES T,H,I,U,E,TT,C +PPIUM: AOS NPPIUM +IFN SWPWSP,[ + MOVEI E,0 ;COUNT USERS OF THE PAGE + PUSHJ P,UCPRL + 400000,,[AOJA E,CPOPJ] + HRRM E,MMSWP(A) ;ALL THESE SHARERS WILL BE CONNECTED TO THE PAGE + MOVSI T,1 ;COMPUTE WORKING SET ADJUSTMENT + IDIVM T,E ;I.E. 1 OVER NUMBER OF SHARERS +];SWPWSP + PUSHJ P,UCPRL ;GIVE PAGE TO ALL USERS WAITING FOR IT + 400000,,PPIUM1 + POPJ P, + +;SET UP MAP TO MEMBLT INDEX IN A +PPIUM1: AOS NPPIU1 + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB + PUSH P,I + MOVEI C,UPGMP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + JUMPE I,[JRST 4,.] ;DOESN'T REALLY EXIST? + MOVSI T,MMPPGA ;DON'T REALLY PUT IN MAP IF PAGE-AHEAD PAGE. + TDNE T,(D) ;JUST PRE-EMPT. + JRST QSWI2A + TRNE I,600000 ;DO NOTHING IF ALREADY IN MAP. +IFE E.SP,[ + JRST QSWI2 ;ALREADY IN MAP, POSSIBLE AS A RESULT OF RIDICULOUS TIMING ERROR +] +IFN E.SP,[ + JRST E.SPGJ ; CHECK E&S WANTS READ/WRITE FIRST FIX +] + SOS NSWPGS(U) ; NUMBER OF SWAPPED-OUT PAGES + SOS SNSWPG ;DECR CNT OF SWAPPED OUT FOR SYS + SKIPN (P) ;DON'T SET UP PG 0 AS R-W-F. + JRST QSWI3 + TRNE I,2 + MOVEI I,2 ;SET READ/WRITE TO READ/WRITE/FIRST +QSWI3: LSH I,16. + IORI I,PMCSHM(A);BRING IN ADDRESS AND CACHE BITS + DPB I,C +QSWI2: +IFE SWPWSP,[ + AOS MMSWP(A) ;INCREMENT COUNT OF USERS IN RING +];SWPWSP +IFN SWPWSP,[ + ADDM E,UWRKST(U) ;ADJUST WORKING SET +];SWPWSP +QSWI2A: +IFN PAGPRE,[ +;IF THIS USER IS WAITING FOR THIS PAGE, MAKE HIM RUNNABLE BY PUTTING +;HIM ON THE SCHMNY LIST, AND PRE-EMPT THE CURRENTLY-RUNNING USER. +;THE IDEAS ARE TO START THIS USER'S NEXT PAGE READ AS SOON AS POSSIBLE, +;AND TO ELIMINATE THE SCHEDULING THAT WOULD OTHERWISE BE NECESSARY TO RUN THIS GUY. + AOS NPREE1 + CONSZ PI,200_-APRCHN ;CAN'T PREEMPT IF CLKOFF + CONSZ PI,100000_-APRCHN ;OR IN PROGRESS, BECAUSE + JRST POPIJ ;MIGHT ZERO FLSINS WHILE SCHEDULER + ;IS EXECUTING IT & SIMILAR NASTIES + AOS NPREE2 + CAME D,FLSINS(U) ;IF JOB THAT JUST GOT PAGE IS WAITING FOR IT + JRST POPIJ + AOS NPREE3 + SETZM FLSINS(U) ;THEN THAT JOB PREEMPTS CURRENT ONE + MOVSI T,%SWPGW + TDNE T,USWST(U) + SOS NPGWTU ;FLSINS WAS DUE TO PAGE FAULT (MIGHT BE IN .CALL CORBLK) + ANDCAM T,USWST(U) + HRRZ I,U + PUSHJ P,SCHSB + SETOM PREEMP + CONO PI,CLKRQ ;REQUEST INT TO SCHEDULER +];PAGPRE +IFE PAGPRE,[ + SKIPE ENPREE + CAME D,FLSINS(U) + JRST POPIJ + MOVE TT,PRVCUT + CAME U,PRVUSR + CAMLE TT,UPGSEC(U) + SETZM SCHFLG +];PAGPRE +POPIJ: POP P,I + POPJ P, + +IFN E.SP,[ +E.SPGJ: SKIPE E.SPGH ; FLAG FROM E.SPGI + CAME U,DISUSR + JRST QSWI2 ; LEAVE AS IS + TRNN I,400000 + JRST QSWI2 + MOVEI I,3 + JRST QSWI3 ; GO MAKE READ/WRITE + ; DON'T SOS NSWPGS, SINCE PAGE IS ALREADY HERE +];E.SP + +SUBTTL USER SCHEDULER + +OVHMTR SC1 ;SCHEDULER 1 - ENTRY + +IFN KL10P, IFNDEF SCCOST, SCCOST==250. ;CHARGE 1 MILLISEC FOR SCHEDULING +IFN KA10P, IFNDEF SCCOST, SCCOST==1000. ;CHARGE 4 MILLISEC FOR SCHEDULING +IFN KS10P, IFNDEF SCCOST, SCCOST==1000. ;CHARGE 4 MILLISEC FOR SCHEDULING + +SCHED: SKIPGE U,USER + JRST SCHED9 + MOVE T,CLKBRK +IFN KS10P,[ + ;; If user is swapped out while running in the page fail code, then + ;; EPTPFO is used as the PC. Either he is on his way in, in which + ;; case he will come back when restarted, or he is on his way out, + ;; in which case this just pushes him on his way. + TLNE T,%PSUSR + JRST SCHED0 + HRRZ T,T + CAIL T,PFAIL ; First instruction inclusive + CAILE T,PFAILE ; Last instruction inclusive + SKIPA T,CLKBRK + MOVE T,EPTPFO +SCHED0: ] ;IFN KS10P + MOVEM T,UPC(U) +IFN SCHBLN,SETZM SCHMNY ;ENTERED FROM QUANTUM RUNOUT, TIME TO CHECK ALL USERS +SCHED2: ;ENTERED FROM UFLS OR PAGE FAULT, CHECK FOR AUXIL PERSON TO RUN + ;IF SCHMNY IS STILL -1 + AOS NSKED + MOVSI T,UEXIT ;GET HERE FROM CLUFLS + HRRI T,UUO(U) + BLT T,SUEXND-1(U) +IFN KL10P,[ + AC7CTX + XCTR XR,[HRRZ A,13] ;GCSTBR + XCTR XR,[HRL A,14] ;STBR + SYSCTX + MOVEM A,ULSPBR(U) + SKIPL MTRUSR ;SKIP IF PERF COUNTER AVAILABLE + JRST [ DMOVE A,MBOXCT(U) ;COMPUTE EQV CPU TIME FROM MBOX+EBOX ACCT + DSUB A,STMBOX ;AS INCREMENTAL RUNTIME + DMUL A,KLMBCC + DADD B,EBOXCT(U) + DSUB B,STEBOX + DMUL B,KLEBCC + MOVE A,D + JRST SCHD2A ] + RPERFC A + DSUB A,STPERF ;USER RUN TIME IN 80 NS UNITS LEFT 12 + DIVI A,50.*4096. ;CONVERT TO 4 MICROSECOND UNITS IN A +SCHD2A: +] ;KL10P +IFN KS10P, LDB A,[044000,,UPQUAN(U)] ;GET TIME USED IN 3.9 USEC UNITS +IFN KA10P, LDB A,[022100,,UPQUAN(U)] ;GET TIME USED IN 4.069 USEC UNITS + ADDM A,USRTM1 ;SYSTEM TOTAL USER RUN TIME + ADDM A,UTRNTM(U) ;INCREASE RUN TIME + ADDM A,JTMU(U) ;DECREASE PROCEDURE PRIORITY + MOVEI B,SCCOST(A) ;ACCOUNT FOR OVERHEAD IN STARTING UP + ADDM B,@UTMPTR(U) ;DECREASE PROCEDURE TREE PRIORITY +IFE SWPWSP,[ + MOVE T,NMPGS(U) ;USWPRI IS PAGES IN CORE X CPU TIME + SUB T,NSWPGS(U) +];SWPWSP +IFN SWPWSP,[ + HLLO B,UWRKST(U) ;USWPRI IS LOG(WORKING SET SIZE) X (CPU TIME + IO WAIT TIME) + JFFO B,.+1 ;C GETS 19 - LOG(WORKING SET SIZE + 1/2) + MOVEI T,19. + SUB T,C +];SWPWSP + IMUL T,A + MOVE Q,UTMPTR(U) + ADDM T,USWPRI(U) ;CHARGE AGAINST SWAPPINNG PRI + ADDM T,SWRCE-USRRCE(Q) ;AND FOR TREE + MOVE B,A + LSH B,-7 ;GET RUNTIME IN 512 USEC UNITS + CAILE B,777 + MOVEI B,777 ;TO FIT IN SCHEDULER HISTORY TBL + MOVE C,USWST(U) + SKIPE FLSINS(U) + TLNN C,%SWPGW + JRST SCHED8 + TRO B,1000 ;BLOCKAGE DUE TO PAGE FAULT +IFN SWPWSP,[ + CAML A,LODQNT ;CHECK FOR LEAVING LOADING STATE +SCHED8: TLZN C,%SWLOD ;DUE TO RUNNING FOR MORE THAN LODQNT BETWEEN PAGE FAULTS + JRST .+2 ;OR DUE TO BLOCKAGE FOR REASON OTHER THAN A PAGE FAULT + PUSHJ P,LVLOA0 ;LEAVE LOADING STATE +];SWPWSP +.ELSE SCHED8: + DPB B,[311200,,@SCHHP] ;COMPLETE SCHEDULER HISTORY TBL ENTRY + SKIPL Q,RTIMER(U) ;SKIP UNLESS RUNTIME INT ACTIVE + JRST SEARRT +SCHED3: SKIPGE DLSRCH + JRST SEAREP ;DELETE SEARCH, EXIT +IFN PAGPRE,[ + SKIPE PREEMP ;PRE-EMPT? + JRST SCHEDP ;YES, AVOID DOING FULL SCHEDULE +];PAGPRE +IFN SCHBLN,[ + SKIPN SCHMNY ;IF NOT YET TIME TO DO A FULL SCHEDULE, + JRST SEARL0 +SCHED4: HLRZ U,UREALT ;THEN CHECK LIST OF JOBS SCHEDULED BEFORE + JUMPE U,SEARL0 ;ALWAYS SCHEDULE IF HIGH PRIORITY REAL TIME USER ACTIVE + PUSHJ P,SCHGB ;POP NEXT JOB OFF LIST + JUMPL U,SEARL0 ;EMPTY + PUSHJ P,SCHACK + JRST SCHED4 ;JOB CEASED TO BE RUNNABLE + AOS NSSKED ;OK, RUN THIS ONE + JRST SCHED6 +];SCHBLN + +SEARRT: SUB Q,A + MOVEM Q,RTIMER(U) + JUMPGE Q,SCHED3 + MOVSI T,(%PIRUN) ;GIVE RUNTIME INTERRUPT + IORM T,PIRQC(U) + JRST SCHED3 + ; +; HERE TO DO A FULL SCHEDULE (LOOK AT ALL JOBS) +; + +OVHMTR SC2 ;SCHEDULER 2 - SEARCH + +SEARL0: AOS NRSKED ;1 MORE REAL SCHED (ACTUALLY SEARCHES JOBS) + CLEARM TRUMM ;TOTAL RUNNABLE USER MEM + CLEARM AUSOPG ;ACTIVE USER SWAPPED OUT PAGES + CLEARM BUMPGS ;PAGES IN REAL CORE BELONGING TO BLOCKED USERS +IFE SWPWSP, CLEARM ASBUM ;PGS IN REAL MEM OCC BY SWAPPED BLOCKED LOSERS + SKIPN SWPOPB + SKIPE SWPOPR + PUSHJ P,SWPON ;SWAP OUT STUFF +IFN NSWPV,[ + SKIPGE CIRPSW + PUSHJ P,SWPPIN ;SERVICE SWAPPING REQUESTS FROM OTHER PROCESSORS (DISPLAY) +] + SETZB U,J ;JOB BEING SCHEDULED + SETZM RNABLU ;NUM RUNABLE USERS +IFN SCHBLN,[ + SETZM SCHBNJ ;GOT NO RUNNABLE JOBS YET + SETOM SCHMNY ;ALLOW ALL THE RUNNABLES WE FIND TO RUN +];SCHBLN +.ELSE SETOM I ;BEST USER SO FAR + MOVNI T,7 + MOVEM T,SCHFLG ;DONT SCHED AGAIN FOR 1/7.5 SEC + JRST SEARL1 + +;HERE IF NULL JOB HAD BEEN RUNNING + +SCHED9: AOS NNSKED ;1 MORE TIME NULL JOB WAS RUN +IFN KA10P, LDB C,[022100,,UPQUAN] ;GET TIME NULL JOB RAN IN 4.069 USEC UNITS +IFN KS10P, LDB C,[044000,,UPQUAN] ;GET TIME NULL JOB RAN IN 3.9 USEC UNITS +IFN KL10P,[ + CAMN U,MTRJOB ;IF METERING ONLY NULL JOB, STOP METERS NOW + WRPAE PAEOFF + CAMN U,MTRJOB + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 + REBOXC A ;COMPUTE NULL JOB'S EQUIVALENT RUNTIME IN 4 USEC UNITS + DSUB A,NULEBC + RMBOXC C + DSUB C,NULMBC + DMUL C,KLMBCC ;CONVERT MBOX COUNT TO EBOX COUNTER UNITS, + DADD A,D ;ADD TO EBOX COUNT + DMUL A,KLEBCC ;CONVERT TO 4 USEC UNITS. + SKIPGE MTRUSR + JRST [ RPERFC C ;PERFORMANCE METER AVAILABLE, USE IT INSTEAD + DSUB C,NULPRF + DIVI C,50.*4096. ;CONVERT TO 4 MICROSECOND UNITS + JRST .+1 ] +];KL10P + ADDM C,NULTM1 ;ACCUMULATE TOTAL NULL TIME IN 4 USEC UNITS + SKIPE NPGWTU ;IF SOMEONE WOULD HAVE BEEN RUNNING IF THEY + ADDM C,LOSTM1 ; WEREN'T WAITING FOR A PAGE, THIS WAS LOST TIME + SKIPN NPGWTU ;BUT OTHERWISE + ADDM C,IDLTM1 ;IT WAS COMPLETE IDLE TIME + SKIPE NPGWTU ;NOW COMPUTE % TIME IDLE AND LOST + ADDM C,LOSRCE + SKIPN NPGWTU + ADDM C,IDLRCE +IFN PAGPRE,SKIPN PREEMP ;CHECK FOR PRE-EMPT + JRST SEARL0 ;NOW GO DO A FULL SCHEDULE +IFN PAGPRE,[ +SCHEDP: SETZM PREEMP + AOS NPREEL + PUSHJ P,SCHGB ;U GETS USER TO PRE-EMPT THIS ONE (LAST INTO SCHMNY LIST) + JUMPL U,SCHDP1 ;NO ONE TO PRE-EMPT, RUN SAME USER AGAIN + PUSHJ P,SCHACK ;MAKE SURE PRE-EMPTING JOB IS RUNNABLE + JRST SCHEDP ;AFRAID NOT + AOS NPREEM ;OK, RUN THIS ONE + SKIPL I,USER + PUSHJ P,SCHSB ;PRE-EMPTED JOB IS STILL A CANDIDATE FOR RUNNING + JRST SCHED6 + +SCHDP1: SKIPGE U,USER ;TRY TO RUN SAME USER AGAIN + JRST SCHED1 ;RUN NULL JOB AGAIN + PUSHJ P,SCHACK ;MAKE SURE THIS JOB IS STILL RUNNABLE (COULD HAVE UFLSED) + JRST SEARL0 ;FOO, BETTER DO A FULL SCHEDULE + JRST SCHED6 ;OK, RUN THIS GUY +];PAGPRE + +;MAIN SEARCH LOOP, RETURN HERE TO EXAMINE NEXT PROCEDURE +SEARL: MOVEI U,LUBLK ;LENGTH OF USER VAR BLOCK + ADDB U,J ;STEP TO NEXT USER + CAML U,USRHI ;SKIP IF EXISTS + JRST SEAREN ;ALL PROCEDURES HAVE BEEN EXAMINED +SEARL1: SKIPE T,USTP(U) + JRST SEARS1 ;EMPTY OR STOPPED JOB SLOT + SKIPE A,PIRQC(U) + JRST SEAR2A ;FIRST WORD INTERRUPT PENDING +SEARL2: SKIPE B,IFPIR(U) + JRST INTWD2 ;SECOND WORD INTERRUPT PENDING +SEARL3: SKIPN FLSINS(U) + JRST SEARC ;NOT BLOCKED +SEARL4: MOVE T,EPDL2(U) + XCT FLSINS(U) ;TEST BLOCKING CONDITION (MAY SKIP ONCE OR TWICE) + JRST SEARLB ;UNRUNABLE + JRST SEARC ;LOW PRIORITY UNBLOCK + SKIPA Q,[-1] ;HIGH PRIORITY UNBLOCK + MOVEI Q,3 ;EXTRA LOW PRIORITY + JRST SEARC2 + +SEARC: SETZM Q ;SET TO NORMAL PRIORITY + PUSHJ P,UPRIVL ;COMPUTE PRIVELEGE LEVEL (MAY SKIP ONCE OR TWICE) + SOJA Q,SEARC2 ;HIGH-PRIORITY + JRST SEARC2 + SKIPGE APRC(U) + ADDI Q,2 ;DISOWNED JOB IN USER MODE +SEARC2: AOS RNABLU ;ANOTHER RUNABLE USER + MOVE T,TIME + MOVEM T,LUBTM(U) ;RECORD LAST TIME UNBLOCKED +IFE SWPWSP,[ + SKIPGE USWSCD(U) + JRST SEARC7 ;HE'S SWAPPED BLOCKED SO HE DOESNT COUNT +];SWPWSP + JUMPE U,SEARC4 ;DON'T FIGURE SYSTEM JOB. + MOVSI T,%SWDSO + ANDCAM T,USWST(U) ;RUNNABLE SO NOT DESIRED OUT + MOVE T,NMPGS(U) + ADDM T,TRUMM ;TOTAL RUNNABLE USER MEM + MOVE T,NSWPGS(U) + ADDM T,AUSOPG ;TOTAL PAGES OF RUNNABLE USERS SWAPPED OUT +SEARC4: CAMN U,UREALT ;IF THIS IS REAL TIME USER IN HIGH PRIORITY + JRST [ MOVEI A,0 ; PHASE, SCHEDULE WITH INFINITE PRIORITY + JRST SEARP2 ] + SKIPLE T,URTIME(U) ;NON SKIP IF POSSIBLE REAL TIME BLOCK + TLNN T,1 ;SKIP IF REAL TIME BLOCK UNLESS PI IN PROGRESS + JRST SEARC6 + SKIPGE PICLR(U) ;SKIP IF PI IN PROGRESS + JRST SEARL ;REAL TIME BLOCKED +SEARC6: MOVE A,@UTMPTR(U) ;GET AMOUNT OF MACHINE TIME USED RECENTLY BY TREE PROCEDURE IS IN + LSH A,3 ;COMBINE WITH TIME FOR JUST THIS PROCEDURE + ADD A,JTMU(U) ;TO GET PRIORITY FIGURE (SMALLER NUMBER IS HIGHER PRI) + LSH A,(Q) ;ADJUST PRIORITY BY MULTIPLICATIVE FACTOR IN Q +;THE EFFECT OF THIS PRIORITY COMPUTATION IS THAT JOBS IN THE SAME TREE +;ARE COMPARED BY JTMU, WHILE JOBS IN DIFFERENT TREES ARE COMPARED MAINLY +;BY USRRCE, ALTHOUGH A MUCH SMALLER JTMU CAN OVERRIDE A SOMEWHAT LARGER +;USRRCE. THIS IS SOMEWHAT DIFFERENT THAN THE COMPUTATION THAT WAS HERE +;BEFORE MAY 1980, BUT THAT COMPUTATION'S RESULTS EVEN DEPENDED ON THE +;ORDER THAT JOBS HAPPENED TO BE INSPECTED, AND ALLOWED A TREE WITH +;A LARGE NUMBER OF RUNNING JOBS TO GET AN UNFAIR SHARE OF THE MACHINE. +SEARP2: +IFN SCHBLN, PUSHJ P,SCHSJB ;INSERT JOB INTO PRIORITY-SORTED LIST +.ELSE [ JUMPL I,SEARP5 + CAML A,U0P ;SKIP IF IS BETTER THAN BEST SO FAR + JRST SEARL +SEARP5: MOVEM U,I ;I GETS NEW BEST USER SO FAR + MOVEM A,U0P ;U0P GETS PRIORITY OF THAT USER +];SCHBLN + JRST SEARL ;TRY NEXT + +IFE SWPWSP,[ +SEARC7: MOVE T,NMPGS(U) ;RUNNABLE AND SWAPPED BLOCKED + SUB T,NSWPGS(U) + SOSL T + ADDM T,ASBUM + JRST SEARC4 +];SWPWSP + +;JOB IS NOT RUNNABLE +SEARLB: JUMPE U,SEARL ;DON'T FIGURE SYSTEM JOB + MOVE T,USWST(U) +IFE SWPWSP, SKIPL USWSCD(U) ;IF LOCKED OUT, DONT COUNT +IFN SWPWSP, TLNN T,%SWSB + TLNN T,%SWPGW + JRST SEARB1 ;NOT WAITING FOR PAGE + MOVE T,NMPGS(U) ;USER IS WAITING FOR PAGE SO COUNT FOR ACTIVE + ADDM T,TRUMM + MOVE T,NSWPGS(U) + ADDM T,AUSOPG + JRST SEARL + +SEARB1: TLNE T,%SWBEM + JRST SEARL ;HAVE MADE BEST SWAPOUT EFFORT + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) + SOSL T + ADDM T,BUMPGS ;REAL MEM PGS BELONGING TO BLOCKED USERS + JRST SEARL + +SEARS1: SKIPN UNAME(U) + JRST SEARL + MOVE T,USWST(U) ;GUY STOPPED, DOES HE HAVE PAGES IN REAL MEM? + TLNE T,%SWBEM + JRST SEARL ;HAVE TRIED BEST EFFORT TO SWAP OUT + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) + ADDM T,BUMPGS + JRST SEARL + +IFN SCHBLN,[ +;TEST ALL THINGS THAT MAKE A PERSON UNRUNNABLE, OR AT LEAST +;REQUIRE THE ATTENTION OF THE SCHEDULER +;SKIP-RETURN IF JOB IS RUNNABLE, BASHES T, A +SCHACK: CAMGE U,USRHI ;NON-EXISTENT + SKIPE USTP(U) ;STOPPED + POPJ P, + SKIPE T,PIRQC(U) + JRST [ TDNE T,[BADBTS] + JRST SCHACI ;NON-DEFERRABLE + SKIPN PICLR(U) + JRST .+3 ;ALL INTERRUPTS DEFERRED + ANDCM T,IDF1(U) + TDNE T,MSKST(U) + JRST SCHACI + JRST .+1 ] + SKIPE T,IFPIR(U) + JRST [ SKIPN PICLR(U) + JRST .+1 ;ALL INTERRUPTS DEFERRED + ANDCM T,IDF2(U) + TDNE T,MSKST2(U) + JRST SCHACI + JRST .+1 ] + SKIPE FLSINS(U) ;FLUSH INSTRUCTION NOT SATISFIED + JRST [ MOVE T,EPDL2(U) + XCT FLSINS(U) ;IT MAY BE SATISFIED BUT NOT CLEARED YET + POPJ P, ;STILL BLOCKED + JRST .+1 ;CAN SKIP VARIOUS RANDOM NUMBERS OF TIMES + JRST .+1 + JRST .+1 ] +SCHAC1: SKIPLE T,URTIME(U) ;REAL-TIME BLOCKED + TLNN T,1 + SKIPA + SKIPLE PICLR(U) + AOS (P) + POPJ P, + +SCHACI: MOVE T,UPC(U) ;TRYING TO INTERRUPT, NEEDS SCHEDULER + TLNN T,%PCUSR ;ATTENTION UNLESS RUNNING IN EXEC MODE + SKIPE FLSINS(U) ;IN WHICH CASE NEED TO LET IT FINISH + POPJ P, ;SO IT CAN BE PCLSRED + JRST SCHAC1 + +;PUT JOB IN U, PRIORITY IN A, INTO STACK IN PRIORITY ORDER. BASH T,TT,B. +SCHSJB: SKIPG T,SCHBNJ ;FIRST SEARCH FOR SLOT IN WHICH TO INSERT + JRST SCHSJ1 ;BUFFER NOW EMPTY, SKIP SEARCH + MOVE TT,T + CAML A,SCHBPR-1(T) + SOJG T,.-1 ;LOOP TERMINATES WITH T SLOT WHERE IT BELONGS + CAIL TT,SCHBLN + SOJA T,SCHSJ3 ;BUFFER FULL, WORK DIFFERENTLY +SCHSJ0: MOVE B,SCHBTB-1(TT) ;MOVE STUFF UP TO ADD ANOTHER ENTRY + MOVEM B,SCHBTB(TT) + MOVE B,SCHBPR-1(TT) + MOVEM B,SCHBPR(TT) + CAILE TT,1(T) + SOJA TT,SCHSJ0 +SCHSJ1: AOS SCHBNJ +SCHSJ5: MOVEM U,SCHBTB(T) + MOVEM A,SCHBPR(T) + POPJ P, + +SCHSJ3: AOS NSCHOV ;BUFFER NOT BIG ENOUGH FOR ALL RUNNABLE JOBS + JUMPL T,CPOPJ ;THIS JOB IS LOWEST PRIORITY, FORGET IT + JUMPE T,SCHSJ5 ;THIS JOB IS SECOND-LOWEST PRIORITY, FORGET LOWEST + MOVE TT,[SCHBTB+1,,SCHBTB] + BLT TT,SCHBTB-1(T) ;MOVE LOWER PRIORITY JOBS DOWN, FORGET LOWEST + MOVE TT,[SCHBPR+1,,SCHBPR] + BLT TT,SCHBPR-1(T) + JRST SCHSJ5 + +;PUSH JOB IN I ONTO STACK OF RUNNABLE JOBS +SCHSB: AOS T,SCHBNJ + CAILE T,SCHBLN + JRST [ SOS SCHBNJ ;BUFFER OVERFLOW + AOS NSCHOV ;MOVE LOWER PRIORITY JOBS DOWN, FORGET LOWEST + MOVE T,[SCHBTB+1,,SCHBTB] + BLT T,SCHBTB+SCHBLN-2 + MOVEM I,SCHBTB+SCHBLN-1 + POPJ P, ] + MOVEM I,SCHBTB-1(T) + POPJ P, + +;POP STACK OF RUNNABLE JOBS INTO U (RETURNS -1 IF STACK EMPTY) +SCHGB: SOSL U,SCHBNJ + SKIPA U,SCHBTB(U) + SETZM SCHBNJ ;BUFFER EMPTY, U HAS -1 + POPJ P, +];SCHBLN + +.ALSKF==0 +DEFINE ALTSKP A +IFE .ALSKF,[ + DEFINE .ALSKS +A TERMIN +] +IFN .ALSKF,[ + CAME U,.ALSKS + CAMN U,A + POPJ P, +] +.ALSKF==.ALSKF#1 +TERMIN + +;DETERMINES USER PRIVILEGE LEVEL FOR SCHEDULING AND SWAPPING +UPRIVL: SKIPN RPCL(U) ;BEING RPCLSR'ED? + CAMN U,UMASTER ;MASTER? + POPJ P, ;HIGHLY PRIVILEGED + AOS (P) ;SKIP AT LEAST ONCE +IFN 340P\E.SP, ALTSKP DISUSR +IFN VIDP, ALTSKP NVDUSR +IFN TABP, ALTSKP TABUSR +IFN ARMP, ALTSKP ARMUSR +IFN LPTP, ALTSKP LPTUSR +IFG LPTP-1, ALTSKP OLPUSR +IFN PLTP, ALTSKP PLTUSR +IFN .ALSKF,[ + CAMN U,.ALSKS + POPJ P, ;DON'T FIGURE DISOWNED IF USING ABOVE DEVICES +] + MOVE T,UPC(U) + TLNE T,%PCUSR + AOS (P) ;SKIP TWICE + POPJ P, + +OVHMTR SC3 ;SCHEDULER 3 - EXIT + +;SEARCH END (EXIT) +SEAREN: +IFE SWPWSP,[ + SKIPE NUSWB + PUSHJ P,SSWC1 ;SEE IF ENUF CORE TO UNBLOCK A SWAPPED BLOCKED LOSER +];SWPWSP +IFE SCHBLN,[ + SKIPGE U,I ;SKIP IF NON-NULL JOB BEST + JRST SCHED1 + AOS NSCHDU +];SCHBLN +IFN SCHBLN,[ + MOVE T,SCHBNJ + ADDM T,NSCHDU + PUSHJ P,SCHGB ;GET HIGHEST-PRIORITY JOB + JUMPL U,SCHED1 ;NONE, RUN NULL JOB +];SCHBLN +SCHED6: SKIPE FLSINS(U) + JRST SCHED5 +SCHED1: EXCH U,USER + JUMPL U,SCHDN ;JUMP IF SWITCHING FROM NULL JOB + CAMN U,USER ;SKIP UNLESS RUNNING SAME JOB AGAIN + JRST SEAREP ;JUMP ON SAME JOB +IFN KL10P,[ + CAMN U,MTRJOB ;IF LEAVING JOB BEING METERED, STOP METER AND + WRPAE PAEOFF + CAMN U,MTRJOB + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 +] +;SWAP OUT THE OLD JOB'S CONSOLE REGISTER, AND CLEAR ITS BLINKER. +IFN N11TYS,[ + SKIPGE TT11P + SKIPE TEN11F + JRST SSTVR1 ;DONT HACK 11 + SKIPL TVCREG(U) ;DO WE WANT TO SAVE TV CONSOLE REG FOR THIS GUY? + SKIPN T,400000+TTR10*2000 ;0 IS NOT A (VERY) LEGITIMATE CONSOLE REG FCN + JRST SSTVR2 ;SO ASSUME 11 STOPPED, DONT CLOBBER PREV THING + MOVEM T,TVCREG(U) +SSTVR2: SKIPGE T,TVVBN(U) ;DID WE SET RUNNING BLINKER FOR THIS GUY? + JRST SSTVR1 ;NO + MOVEM T,400000+TTR10*2000 ;SET TO VIDEO BUFFER WE SET IT IN + MOVE A,TVBLAD ;ADDR IN VIDEO BUFFER WE FLASHED + CLEARM 400000+TTR0*2000(A) ;CLEAR IT +SSTVR1:] +IFN KA10P,[ + MOVE T,40 + MOVEM T,SV40(U) ;SAVE LAST UUO EXECUTED FOR THIS USER + MOVE T,UPC(U) ;IF USER HAS JUST TRAPPED TO 60, + TLNE T,%PCUSR + JRST SCHDN + ANDI T,-1 + CAIL T,60H0 + CAILE T,60HE + JRST SCHDN + MOVNI T,60H0-UUOH0 + ADDM T,UPC(U) ;THEN MOVE HIM INTO UUOH INSTEAD + MOVE T,60 ;AND MOVE 60H'S VARIABLES INTO UUOH'S VARS + MOVEM T,SV40(U) ;(THAT'S ALL 60H DOES ANYWAY). + MOVE T,60H + MOVEM T,SUUOH(U) +] ;KA10P +;DROPS THROUGH. + ;DROPS IN +;COME HERE TO SET UP A JOB THAT WASN'T ALREADY RUNNING. + +SCHDN: MOVE A,U + SKIPGE U,USER + JRST SCHDN2 ;JUMP IF SWITCHING TO NULL JOB +IFN KA10P,[ + MOVE T,SV40(U) ;LOAD NEW KRUFT + MOVEM T,40 +] ;KA10P +IFN N11TYS,[ + SKIPGE TT11P ;DONT HACK 11 IF ITS DOWN (MOSTLY IN CASE ITS BEING HACKED + ;HARDWARILY + SKIPE TEN11F + JRST SLTVR1 ;DONT HACK 11 + SKIPGE T,TVVBN(U) ;BLINK RUNNING FROB? + JRST SLTVR2 + MOVEM T,400000+TTR10*2000 + MOVE A,TVBLAD + MOVNI T,20 + MOVEM T,400000+TTR0*2000(A) + SKIPA T,TVVBN(U) +SLTVR2: MOVSI T,12_<8+4+16.-18.> ;ALU NOP + SKIPL TVCREG(U) + MOVE T,TVCREG(U) + MOVEM T,400000+TTR10*2000 +SLTVR1:] +IFN KL10P,[ + CAMN U,MTRJOB ;IF THIS JOB'S BEING METERED, TURN ON METER AND TIME BASE. + WRPAE PAEON + CAMN U,MTRJOB + CONO MTR,2001 ;TIME-BASE ON, INTERVAL PIA=1 +];KL10P + SOS NRESKED ;COMPENSATE FOR EXTRA AOS ON NEXT PAGE + +;DROPS THROUGH + ;DROPS IN +;COME HERE TO START UP A JOB EVEN IF IT WAS ALREADY RUNNING BEFORE THIS SCHEDULE. + +SEAREP: AOS NRESKED +IFN KA10P,[ + HRLOI T,1 + ANDCAM T,UPQUAN(U) ;RESET QUANTUM TIMER +] ;KA10P +IFN KL10P,[ + RPERFC STPERF ;SAVE PERF METERS FOR LATER USE + DMOVE A,EBOXCT(U) ;COMPUTING RUN TIME EFFECTIVELY RESETS + DMOVEM A,STEBOX ;QUANTUM TIMER + DMOVE A,MBOXCT(U) + DMOVEM A,STMBOX +] ;KL10P +IFN KS10P, SETZM UPQUAN(U) ;RESET QUANTUM TIMER + PUSHJ P,PGLDU + MOVN A,U + IDIVI A,LUBLK + SKIPE B + BUG +IFE KS10P,[ ; KS has no lights. + MOVSI B,400000 + LSH B,(A) + SKIPN MIPGDS + DATAO LIGHTS,B ;LIGHTS HAVE ONE BIT, SHOWING WHICH JOB IS RUNNING. +] ;IFE KS10P + MOVN B,A ;GET JOB'S NUMBER IN B + MOVE T,UPC(U) ;USER'S PC WORD + MOVEM T,CLKBRK + AOS A,SCHHP ;SET UP SCHEDULER HISTORY TBL + CAIL A,SCHHB+SSCHDB + MOVEI A,SCHHB + MOVEM A,SCHHP + HRRM T,(A) ;STORE PC + TLNN T,%PCUSR + TRO B,400000 + HRLM B,(A) ;STORE USER INDEX AND USER BIT + MOVSI T,UUO(U) + HRRI T,UEXIT + BLT T,UEXND-1 ;BLT IN UEXIT BLOCK +IFN KL10P,[ + MOVE T,ULSPBR(U) + AC7CTX + XCTR XW,[HRRZM T,13] ;GCSTBR + XCTR XW,[HLRZM T,14] ;STBR +] ;KL10P ;CONTEXT WILL BE RESTORED AT CLKB5 BELOW +IFN KA10P, CONO @APRC(U) + +; +; THIS IS THE ONE PLACE WHERE CLOCK LEVEL RETURNS TO THE USER JOB +; +CLKB5: +IFE KA10P, DATAO PAG,@CLCXSV ;RESTORE CONTEXT + MOVE U,USER + MOVSI U,AC0S(U) ;RESTORE AC BLOCK 0 + BLT U,U + JRST 12,@CLKBRK ;RESTORE PC, FLAGS, AND PI + +;HERE WHEN STARTING A USER WHO HAD BEEN FLSING + +SCHED5: MOVE T,USWST(U) +IFN SWPWSP,[ + TLNN T,%SWPGW ;PAGE WAITS DON'T COUNT AS BLOCKING + TLNN T,%SWOUT ;IF SWAPPED-OUT, UNBLOCKING BUMPS SWAP-IN PRIORITY + JRST SCHD5A + MOVE TT,USWPRI(U) ; (A SOMEWHAT QUESTIONABLE FEATURE) + LSH TT,-1 + MOVEM TT,USWPRI(U) +SCHD5A: +];SWPWSP + TLNE T,%SWPCL + JRST SCHED7 ;JUMP IF PAGES SWAPPED OUT WHILE BLOCKED IN EXEC MODE + TLNE T,%SWPGW + SOS NPGWTU ;NOT WAITING FOR A PAGE ANY MORE + MOVSI T,%SWPGW+%SWRUN+%SWINT ;NOT WAITING FOR PAGE,NOT UNBLOCKED SWAPOUT, + ANDCAM T,USWST(U) ;NOT WAITING FOR INTERRUPT PAGE + SETZM FLSINS(U) ;NOT WAITING FOR ANYTHING + JRST SCHED1 + +SCHED7: PUSHJ P,PCLSR ;PAGES WERE SWAPPED OUT WHILE BLOCKED IN EXEC MODE + BUG ;SO PCLSR JOB SINCE IT MIGHT BE COUNTING ON THOSE PAGES + JRST SCHED1 ;PCLSR MUST SUCCEED. JOB WAS BLOCKED WITH EMPTY LSWPR. + + +;COME HERE TO RUN THE NULL JOB. + +SCHDN2: SKIPL A ;WERE RUNNING IT ALREADY? + AOS NNULBK ;NO, INCREMENT # CONSECUTIVE BLOCKS OF NULLTIME. + MOVSI T,(JFCL) + MOVEM T,CLUSAV ;AVOID LOSSAGE AT CLKBRK+1 NEXT CLOCK INT +IFE KA10P, MOVEM T,CLCXSV +IFE KS10P,[ ; KS has no lights. + SKIPN MIPGDS + DATAO LIGHTS,[0] ;LOAD LIGHTS WITH JOB RUNNING (NONE) +] ;IFE KS10P +IFN KA10P,[ + HRLOI T,1 + ANDCAM T,UPQUAN +] ;KA10P +IFN KL10P,[ + CAMN U,MTRJOB + WRPAE PAEON + CAMN U,MTRJOB + CONO MTR,2001 ;TIME-BASE ON, INTERVAL PIA=1 + REBOXC NULEBC + RMBOXC NULMBC + RPERFC NULPRF +] ;KL10P +IFN KS10P, SETZM UPQUAN + CLEARM SCHFLG ;RESCHEDULE ON NEXT CLK INT + LPMR UPGML + JRST 12,@[%PSPCU,,NULJOB] ;DISMISS INT AND GO TO NULL JOB + +NULJOB: MOVSI (JRST 4,) + MOVEI 17,1 ;SET ACS 0 TO 16 TO JRST 4,0 + BLT 17,16 ;TO CATCH SPURIOUS TRANFERS TO ACS + MOVE 17,[AOJA 17] ;RUNS IN ACS TO FREE MEMORY FOR OTHER PROCESSORS + JRST 2,@[%PCUSR,,17] ;RUNS IN USER MODE FOR SAKE OF RANDOMNESS + +IFE SWPWSP,[ +OVHMTR SC4 ;SCHEDULER 4 - UNSWAPBLOCKER + +;SEE IF THERE IS ENOUGH CORE TO UNBLOCK A SWAP-BLOCKED JOB. +SSWC1: SKIPGE U,BUSR + POPJ P, + MOVN T,NSWPGS(U) + ADD T,MEMFR + SUB T,NCBCOM + ADD T,SOLNG + SUB T,SILNG + SUB T,AUSOPG + ADD T,ASBUM + ADD T,BUMPGS + CAIGE T,20 + POPJ P, ;THERE ISN'T ENOUGH ROOM. + MOVSI T,400000 + ANDCAM T,USWSCD(U) ;CLEAR SWAP BLOCKED + SETOM BUSR + MOVE T,[-1_-1] + MOVEM D,BUSIZ ;SIZE OF SMALLEST SWAP-BLOCKED USER. + AOS NTSBUU + SOSN NUSWB + JRST SSWSC3 + MOVEI U,0 + MOVNI R,1 + MOVSI T,200000 +SSWSC4: CAML U,USRHI + JRST SSWSC6 + SKIPGE USWSCD(U) + SKIPN UNAME(U) + JRST SSWSC5 + CAMGE T,NMPGS(U) + JRST SSWSC5 + MOVE R,U + MOVE T,NMPGS(U) +SSWSC5: ADDI U,LUBLK + JRST SSWSC4 + +SSWSC6: MOVEM R,BUSR ;STORE NEW SMALLEST SWAPPED BLOCKED LOSER + SKIPGE R + MOVEI T,0 + MOVEM T,BUSIZ +SSWSC3: JUMPL I,SEARL0 ;MAYBE CAN RUN THIS GUY NOW + POPJ P, +];SWPWSP + +OVHMTR SWU ;SWAP USER + +;SWAP OUT N PAGES (N IS IN SWPOPR) +SWPON: MOVE C,SOLNG + SKIPGE CIRPSW ;CAN'T DO ANYTHING WITHOUT CIRPSW + CAILE C,2*NQS + POPJ P, ;ALREADY STUFF ON WAY OUT + SKIPL U,PSWOUS ;SEE IF CONTINUING TO SWAP OUT A USER + CAML U,USRHI + JRST SWPON1 + MOVE C,PSWCLS + SKIPE LSWPR(U) ;PREFER NOT TO SWAP OUT + JRST SWPON1 ;USER WHO HAS SWITCHES LOCKED + SKIPE UNAME(U) ;SKIP ON USER KILLED + SKIPL USWST(U) .SEE %SWDSO ;OR NOT DESIRED OUT ANY MORE +SWPON1: PUSHJ P,SWPON2 ;FIND NEW USER TO FLUSH + JUMPL U,SWUP8 +SWPON6: MOVSI A,%SWDSO ;THIS USER NOW DESIRED OUT + IORM A,USWST(U) + MOVEM C,PSWCLS + MOVEM U,PSWOUS + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWPU1 ;OK TO SWAP USER + SKIPN LSWPR(U) ;PCLSR IF HAS LOCKS, OR AT JBFLS, + SKIPN FLSINS(U) ;OR IF NOT BLOCKED + JRST SWPON8 + MOVSI T,%SWPCL ;OTHERWISE, DON'T PCLSR NOW, BUT + IORM T,USWST(U) ;WHEN IT UNBLOCKS + JRST SWPU1 ;AND START SWAPPING OUT ITS PAGES + +SWPON8: PUSHJ P,PCLSR ;GET OUT OF SYS BEFORE SWAPPING OUT + POPJ P, + JRST SWPU1 + +;FOUND NO USER TO SWAP OUT +SWUP8: SKIPE NLOOSP + JRST SWOL1 ;SWAP OUT SOME LOOSE PAGES + AOSE SBEFLG ;HAVE WE COME HERE TWICE? + JRST SWUP6 ;YES, GIVE UP + MOVSI B,%SWBEM ;NO, TURN OFF EVERYONE'S BEST EFFORT BIT + MOVEI J,2*LUBLK ;AND LOOK AT EVERYONE AGAIN SINCE WE'RE DESPERATE +SWUP9: CAML J,USRHI ;TO FIND A PAGE TO SWAP OUT + JRST SWUP7 + ANDCAM B,USWST(J) + ADDI J,LUBLK + JRST SWUP9 + +SWUP7: PUSHJ P,SWPON2 ;HAVING TURNED OFF %SWBEM, FIND A USER TO SWAP OUT + JUMPG U,SWPON6 ;GO SOMEONE, GO DO +SWUP6: SETZM SWPOPR ;CAN'T FIND ANYONE TO SWAP OUT, GIVE UP + SETOM PSWOUS + POPJ P, + +SWOL1: SKIPN A,FLOOSP ;SWAP OUT SOME LOOSE PAGES + BUG ;NLOOSP WAS TOO HIGH? + MOVNI C,1 + PUSHJ P,SWPOPG + BUG ;CIRPSW, EXEC PAGE COUNT ALREADY CHECKED + SETOM SBEFLG ;WE FOUND A PAGE TO SWAP OUT, NOT DESPERATE + MOVE C,SOLNG + SOSLE SWPOPR ;ENOUGH + CAIL C,20. ;ENOUGH FOR NOW + POPJ P, + SKIPE NLOOSP ;SWAP OUT MORE PAGES + JRST SWOL1 + JRST SWPON + ;START SWAPPING OUT THIS USER'S PAGES +SWPU1: AOS NSOUSR + MOVSI A,%SWRUN + CAILE C,1 ;CLASS + IORM A,USWST(U) ;INDICATE USER WAS RUNNABLE AT TIME OF SWAP OUT +IFE SWPWSP,[ + SETZM SWUPC + SKIPN ENUPC + JRST SWPU1B + MOVE T,UPC(U) ;CALCULATE WHAT PAGE HIS PC IS ON + LDB C,[121000,,UPC(U)] + ROT C,-1 + ADDI C,UPGMP(U) + MOVE A,[222200,,(C)] + SKIPGE C + IBP A + LDB A,A + TRNN A,600000 + SETZM A + ANDI A,PMRCM ;MASK TO REAL CORE ADR BITS + SKIPN USTP(U) ;ONLY IF RUNNING + TLNN T,%PCUSR ;AND IN USR MODE + CAIA + MOVEM A,SWUPC ;THEN DON'T ALLOW UPC PAGE TO BE SWAPPED OUT +SWPU1B: +];SWPWSP + MOVE B,PSWLC + AOSE PSWSFL + JRST SWPU3A ;PICK UP FROM WHERE LEFT OFF +IFE SWPWSP,[ + SKIPE ENPZRO + SETOM SWPP0F +];SWPWSP + MOVEI C,UPGMP(U) ;ADDRESS OF PAGE MAP (START FROM PG 0) + MOVEI J,UPGCP(U) + HRLI C,442200 ;CNVRT TO BYTE PNTR TO MAP + HRLI J,442200 + MOVEM C,SWPMBP + MOVEM J,SWPCBP + LDB B,[121100,,HUSRAD(U)] ;DO ALL PAGES THAT MIGHT EXIST +SWPU2: ILDB D,SWPCBP ;CIRC PNTR ENTRY + ILDB A,SWPMBP ;PAGE MAP ENTRY + AOS NSOPGS + JUMPE D,SWPU3A ;DOESN'T HAVE PAGE +IFE SWPWSP,[ + AOSN SWPP0F + SKIPE USTP(U) ;DON'T SWAP OUT PAGE 0 IF NOT STOPPED + CAIN D,-1 ;PAGE IS ABSOLUTE + JRST SWPU3A + TRNN A,600000 ;NO ACCESS + JRST SWPU3A + SKIPN ENAGE + JRST SWPU2A + TRON A,PMAGEM ;HAS PAGE BEEN REFERENCED? (AGE MASK) + JRST [ DPB A,SWPMBP + AOS NAGEAB + JRST SWPU3A ] +SWPU2A: ANDI A,PMRCM ;MASK TO REAL CORE PAGE # + CAMN A,SWUPC ;DON'T SWAP OUT PAGE WHERE PC IS IF RUNNING + JRST SWPU3A +];SWPWSP +IFN SWPWSP,[ ;I DOUBT THAT MOST OF THAT NONSENSE DOES ANYTHING + TRNE A,600000 ;NO ACCESS + CAIN D,-1 ;OR PAGE IS ABSOLUTE + JRST SWPU3A ;MEANS DON'T SWAP OUT + ANDI A,PMRCM ;MASK TO REAL CORE PAGE # +];SWPWSP + HRRZ D,MMSWP(A) ;NUMBER OF USERS WHO HAVE THIS PAGE MAPPED + SOJN D,SWPU4 ;PAGE IS SHARED +SWPU6: MOVEM B,PSWLC ;SAVE HOW FAR SWAP-OUT SCAN GOT + MOVE C,PSWOUS + PUSHJ P,SWPOPG ;SWAP OUT THIS PAGE + JRST SWPU3 + SETOM SBEFLG ;FOUND A PAGE TO SWAP OUT, NOT DESPERATE + MOVE C,SOLNG + SOSLE SWPOPR ;ENOUGH + CAIL C,20. ;ENOUGH FOR NOW + POPJ P, +SWPU3: MOVE B,PSWLC + MOVE U,PSWOUS +SWPU3A: SOJG B,SWPU2 + SETOM PSWOUS + MOVSI B,%SWBEM + IORM B,USWST(U) ;SET BEST EFFORT BIT +IFN SWPWSP,[ + SKIPL APRC(U) ;IF DISOWNED, + JRST SWPON + MOVE B,USWPRI(U) ;DECREASE PRIORITY TO COME BACK IN + LSH B,2 + MOVEM B,USWPRI(U) +];SWPWSP + JRST SWPON + ;TRYING TO SWAP OUT A SHARED PAGE +SWPU4: MOVEM B,PSWLC ;SAVE HOW FAR SWAP-OUT SCAN GOT + AOSE CIRPSW + BUG ;CIRPSW LOCKED IN SWAP OUT CODE + MOVE C,[2200,,MEMPNT(A)] + MOVEM A,SWOBK + PUSHJ P,UCPRL + 400000,,SWPU5 ;CONSULT THE OTHER USERS OF THE PAGE + SETOM CIRPSW + MOVE A,SWOBK + JRST SWPU6 ;OK TO SWAP IT OUT + +SWPU5: SKIPGE TT,USWST(U) .SEE %SWDSO + POPJ P, ;USER DESIRED OUT, CAN'T HOLD PAGE IN +IFN SWPWSP, TLNN TT,%SWLOD ;IF USER IS LOADING, HOLDS PAGE IN + SKIPN AGERTE + JRST SWPU5A + MOVE TT,I + LSH TT,-1 + ADDI TT,UPGMP(U) + HRLI TT,2200 + TRNN I,1 + HRLI TT,222200 + LDB TT,TT + TRNE TT,600000 ;SKIP IF NO ACCESS, IGNORE AGE + TRNE TT,PMAGEM ;HAS SHE USED THIS PAGE? + POPJ P, ;NO, CAN'T HOLD PAGE IN +SWPU5A: SUB P,[4,,4] + SETOM CIRPSW ;SHARED W/USER WHO IS WANTED IN CORE + AOS NSHRAB ;SO DON'T SWAP IT OUT + JRST SWPU3 + +;COME HERE WITH BEST USER TO SWAP OUT IN U, CLASS IN C +SWPONX: JUMPL U,CPOPJ ;NO SWAP OUTTABLE LOSER +IFN SWPWSP,[ + CAILE C,1 + SKIPN NLOOSP + JRST SWPNX2 + SETO U, ;WOULD RATHER SWAP OUT LOOSE PAGES + POPJ P, + +SWPNX2: MOVSI T,%SWOUT ;MAKE USER SWAPPED OUT + TDNE T,USWST(U) + JRST SWPNX3 ;ALREADY IS? + IORM T,USWST(U) + MOVE T,UWRKST(U) + MOVEM T,USVWRK(U) + MOVE T,TIME + MOVEM T,USWTIM(U) ;DROPS INTO SWPNX3 +];SWPWSP +IFE SWPWSP,[ + CAILE C,1 + SKIPN NLOOSP + SKIPA B,USWST(U) + JRST [ SETO U, ? POPJ P, ] ;WOULD RATHER SWAP OUT LOOSE PAGES + SKIPGE USWSCD(U) + JRST SWPNX3 ;HE'S ALREADY SWAP BLOCKED + TLNN B,%SWPGW ;IS HE RUNNABLE? + SKIPN FLSINS(U) + SKIPE USTP(U) + JRST SWPNX3 + MOVE B,NMPGS(U) ;HE'S RUNNABLE + CAIGE B,TSYSM-SYSB-MEMSY1 + JRST SWPNX1 ;SMALL, NO THRASH + SUB B,NSWPGS(U) + ADD B,MEMFR + SUB B,NCBCOM + ADD B,SOLNG + SUB B,SILNG + SUB B,AUSOPG + JUMPG B,SWPNX3 ;LET THIS GUY THRASH +SWPNX1: SKIPN ENSWBK + JRST SWPNX3 + MOVSI B,(SETZ) ;SWAP BLOCK THIS LOSER + IORM B,USWSCD(U) + AOS NTUSB + AOS NUSWB + MOVE B,NMPGS(U) ;SMALLEST SWAP BLOCKED LOSER? + CAML B,BUSIZ + JRST SWPNX3 + MOVEM U,BUSR ;YES + MOVEM B,BUSIZ ;DROP INTO SWPNX3 +];SWPWSP +;HAVING DECIDED TO SWAP OUT JOB IN U, MAKE SWAP HISTORY TABLE ENTRY +SWPNX3: MOVSI T,2_16. +;GENERAL SWAP HISTORY TABLE KEEPER. ENTER WITH JOB IN U, EVENT IN T, BASHES TT,I,T +SWPKHT: HRLZ TT,U + IDIVI TT,LUBLK ;TT 3.1-3.8 GETS JOB NUMBER, BASHES I + IOR TT,T + HRR TT,TIME +IFN SWPWSP, HLRZ T,UWRKST(U) +IFE SWPWSP,[ + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) +];SWPWSP + SOSL T + DPB T,[321000,,TT] + MOVEM TT,@SWPHTP + AOS T,SWPHTP + MOVE TT,UTRNTM(U) + MOVEM TT,SWPHTL-1(T) + MOVEI TT,SWPHTB + CAIL T,SWPHTB+SWPHTL + MOVEM TT,SWPHTP + POPJ P, + +OVHMTR SWF ;SWAP FIND USER + +;FIND A USER TO SWAP OUT, RETURN IN U, -1 IF NONE +SWPON2: SETOM PSWSFL ;START FROM BEG OF USER +IFE SWPWSP,[ + SKIPL U,PRVUSR + PUSHJ P,CKPRUS ;MAKE SURE PRIV USER EXISTS AND HAS NOT BEEN BLOCKED FOR A LONG TIME +];SWPWSP + MOVNI T,30.*60. + ADD T,TIME ;A MINUTE AGO + MOVNI U,1 + MOVEI J,2*LUBLK + MOVEI C,NSSCDC ;# SWAP OUT CLASSES +SWPON4: CAML J,USRHI ;C HAS INDEX OF MAX CLASS INTERESTED IN + JRST SWPONX ;LOOKED AT ALL USERS, GO PONDER RESULTS + SKIPE UNAME(J) ;SEE IF FOR REAL + SKIPN NMPGS(J) ;DON'T BOTHER IF HAS NO MEMORY + JRST SWPON3 +IFN SWPWSP,[ + MOVE B,USWST(J) + TLNE B,%SWBEM+%SWLOD ;DON'T SWAP OUT IF BEST EFFORT ALREADY MADE, + JRST SWPON3 ; OR STILL LOADING IN + MOVEI I,7 + MOVE TT,USWTIM(J) + CAMLE TT,TIME ;IF PROTECT TIME HASN'T ELAPSED YET, GETS HIGHER PRIORITY + JRST SWPTK ;TO PREVENT THRASHING +];SWPWSP +IFE SWPWSP,[ + MOVE B,USWST(J) + TLNE B,%SWBEM + JRST SWPON3 ;BEST EFFORT ALREADY MADE +];SWPWSP + SKIPE LSWPR(J) + JRST SWPON7 ;PREFER NOT TO SWAP OUT LOSER WITH SWITCHES LOCKED + MOVEI I,1 + TLNE B,%SWPGW + JRST SWPON5 ;FLSINS IS WAITING FOR A PAGE (NOT REALLY BLOCKED) + CAML T,LUBTM(J) + SOJA I,SWPTK ;BLOCKED FOR A LONG TIME (CLASS 0) + SKIPN FLSINS(J) +SWPON5: SKIPE USTP(J) + JRST SWPTK ;CLASS 1 (BLOCKED) +IFE SWPWSP,[ + TLNE B,%SWPRV + JRST [ MOVEI I,7 ;CLASS 7 (PRIV USER) + JRST SWPTK ] +];SWPWSP + JUMPL B,[AOJA I,SWPTK] .SEE %SWDSO ;DESIRED OUT (CLASS 2) + MOVEI I,4 + SKIPGE APRC(J) + SOJA I,SWPTK ;DISOWNED (CLASS 3) +IFE SWPWSP,[ + SKIPGE USWSCD(J) + JRST SWPTK ;SWAP BLOCKED (CLASS 4) +];SWPWSP + SKIPGE TTYTBL(J) + AOJA I,SWPTK ;DOESNT HAVE TTY (CLASS 5) +SWPON7: MOVEI I,6 ;OTHERWISE.... + +SWPTK: CAMGE C,I + JRST SWPON3 ;THIS GUY IN MORE WINNING CLASS +IFE SWPWSP,[ + MOVE A,NMPGS(J) + SUB A,NSWPGS(J) +];SWPWSP +.ELSE MOVE A,UWRKST(J) + CAME C,I + JRST SWPTK2 + XCT SWPTT(C) ;IN SAME CLASS, COMPARE CLASS-DEPENDENT PRIORITY MEASURES + JRST SWPON3 +SWPTK2: MOVE E,@SWPTT(I) ;MAKE THIS GUY BEST VICTIM + MOVE C,I + MOVE U,J +SWPON3: ADDI J,LUBLK + JRST SWPON4 + +;SKIP IF THIS GUY (J) IS BETTER LOSER TO FLUSH THAN PREV BEST (IN E) +SWPTT: CAMG E,LUBTM(J) ;BLOCKED FOR A LONG TIME (0) - LATER LUBTM WINS + CAMG E,LUBTM(J) ;BLOCKED (1) - LATER LUBTM WINS + CAML E,A ;DESIRED OUT (2) - SMALLER WORKING SET WINS + CAML E,A ;DISOWNED (3) - SMALLER WORKING SET WINS + CAML E,A ;RUNNABLE, SWAP BLOCK SET (4) - SMALLER WORKING SET WINS + CAML E,USWPRI(J) ;RUNNABLE, W/O TTY (5) - GO BY PRIORITY + CAML E,USWPRI(J) ;OTHERWISE (6) - GO BY PRIORITY +IFE SWPWSP, BUG ;PRIVELEGED USER (7) - SHOULD ONLY BE ONE +IFN SWPWSP, CAMG E,USWTIM(J);PROTECTED (7) - LATER UNPROTECT TIME WINS +NSSCDC==.-SWPTT + +IFE SWPWSP,[ +CKPRUS: MOVSI B,%SWPRV + CAMGE U,USRHI + ANDCAM B,USWST(U) ;TURN OFF PRIV USER BIT + MOVNI TT,30.*2 + ADD TT,TIME ;TWO SECONDS AGO + SKIPE UNAME(U) + CAML TT,LUBTM(U) + PUSHJ P,NPRVUSR + SKIPG U,PRVUSR + POPJ P, + MOVSI B,%SWPRV + IORM B,USWST(U) + POPJ P, +];SWPWSP + +OVHMTR UUO ;RANDOM UUOS + +;AC: A.9 =>1 SWAP OUT USER +;4.8 => 1 ALL PAGES +;4.7=1 => LOOP FOR A WHILE +;3.9-3.1 USER # SELF IF 0 +;RH => USER VIRTUAL PG # +;OR 4.9=0, 4.8=0, 4.7=0 SWAP OUT RH # OF PAGES +;IF 4.9=0, 4.8=1 AND 4.7=0, HACK PCLSR TEST FEATURE ON CURRENT USER +;RH =0 LEAVE PCLSR TEST MODE =1 ENTER IN ADVANCE MODE =-1 ENTER IN HOLD MODE +; =2 ENTER IN ADVANCE BUT DON'T ^Z + +ASWAP: SKIPN SYSDBG + JRST ILUUO + UMOVE A,(J) + TLNE A,100000 + JRST ASWAP3 + JUMPL A,ASWAP1 + TLNE A,200000 + JRST ASWPCL ;PC LSR TEST MODE. + HRRZM A,SWPOPR ;CLOBBER CLOBBER + POPJ P, + +ASWAP1: HLRZ B,A + ANDI B,777 .SEE MAXJ ;FIELD SHOULD BE BIG ENOUGH + IMULI B,LUBLK + SKIPE B + MOVE U,B + TLNN A,200000 + JRST ASWAP2 + MOVE D,NMPGS(U) + SUB D,NSWPGS(U) + JUMPL D,[JRST 4,.] + JUMPE D,CPOPJ + CONO PI,CLKOFF + MOVEM U,PSWOUS + SETOM PSWSFL + ADDM D,SWPOPR + MOVSI D,%SWDSO + IORM D,USWST(U) + CONO PI,CLKON + POPJ P, + +ASWAP2: PUSHJ P,CWAIT ;RETURNS WITH CLKOFF AND CIRPSW AVAILABLE + SKIPL CIRPSW + HRRZS A ;A HAS VIRTUAL PAGE # + PUSHJ P,UPLC ;RETURN POINTERS IN T AND Q + LDB A,T ;GET MAP ENTRY + LDB C,Q ;GET CIRC PNTR + CAIE C,-1 ;DON'T SWAP OUT ABS PAGE + TRNN A,600000 + POPJ P, ;ALREADY OUT OR DOESN'T HAVE PAGE + ANDI A,PMRCM ;MASK TO REAL CORE PAGE # + MOVNI C,1 + PUSHJ P,SWPOPG + JFCL + JRST CLKONJ + +ASWAP3: MOVE B,[1250000.] + SOJG B,. + UMOVE A,2000 + JRST ASWAP3 + +ASWPCL: MOVEM U,PCLUSR + CLEARM PCLL + CLEARM PCLHSH + SETOM PCLNXT + HRRES A + MOVEM A,PCLDBM + POPJ P, + +;.CALL PGWRIT +; ARG 1 - A +; ARG 2 - PAGE NUMBER IN 'S ADDRESS SPACE +;IF ONLY ONE ARGUMENT IS GIVEN, IT IS ARG 2, AND ARG 1 DEFAULTS TO CURRENT USER + +;THE PAGE IS SWAPPED OUT. THE CALL DOESN'T RETURN UNTIL THE SWAP IS COMPLETED. +; THIS ALLOWS USER TO BE SURE THAT THE COPY ON DISK IS UP TO DATE. +;CONTROL BIT 1.1 => RETURN IMMEDIATELY, NO WAITING. TO WAIT LATER, JUST DO +; ANOTHER PGWRIT WITHOUT SETTING 1.1. +;CONTROL BIT 1.2 => UNLOCK PAGE. IF YOU CALL THIS ON A LOCKED PAGE, +; WITHOUT SETTING BIT 1.2, THE PAGE WILL BE SWAPPED OUT, BUT THE NEXT +; TIME IT IS SWAPPED IN IT WILL BE LOCKED AGAIN. THIS IS USEFUL FOR +; CONTROLLING EXACTLY WHEN A DATA BASE PAGE GETS WRITTEN TO DISK. + +NPGWRT: CAIGE W,2 + JRST [ MOVE J,U ? JRST NPGWR1 ] + MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC + JRST NPGWR0 + JSP T,NCORWR ;WHICH MUST BE WRITABLE + JRST OPNL31 +NPGWR0: +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;CAN'T HACK PDP6 +];PDP6P + MOVE A,B ;NOTE: SWPOPG TAKES CARE OF THE PCLSR'ING + PUSHJ P,NPGWR1 ;CALL MAIN ROUTINE + POPJ P, ;LOST, OPNL CLEARED LSWPR + JRST LSWPJ1 ;WON, UNLOCK DIELOK + +;USER INDEX IN J, PAGE NUMBER IN A +NPGWR1: TDNE A,[-1,,-400] + JRST OPNL32 ;PAGE NUMBER NOT VALID + PUSHJ P,CWAIT ;DON'T ALLOW PAGE MAPS TO CHANGE, AND TURN CLK OFF + SKIPL CIRPSW ;DON'T NEED UTCOFF BECAUSE UTC LEVEL CAN ONLY PUT PAGES INTO MAPS + EXCH U,J + PUSHJ P,UPLC + EXCH U,J + LDB D,Q ;D GETS CIRC PNTR + JUMPE D,OPNL32 ;NO PAGE THERE + CAIN D,-1 + JRST OPNL12 ;ABSOLUTE PAGE + PUSH P,U + MOVE C,Q ;STARTING FROM UPGCP, FIND MMP + PUSHJ P,UCPRL + 200000,,.+2 + BUG ;IF NONE FOUND + SUB P,[4,,4] ;FOUND MMP, C POINTS TO IT + MOVSI T,MMPTMP ;IF PAGE IS IN TRANSIT + TDNE T,(C) + JRST [ POP P,U + TDNE T,(C) ;AWAIT COMPLETION + PUSHJ P,UFLS + JRST NPGWR1 ] ;THEN TRY AGAIN + MOVE E,C ;SAVE ADDRESS OF MMP ENTRY + PUSHJ P,UCPRL ;SEE IF PAGE IS IN MEMORY + 100000,,NPGWR3 + POP P,U ;NOT SWAPPED IN, BYPASS SWAP-OUT CODE + JRST NPGWR2 + +NPGWR3: SUB P,[4,,4] ;IT'S SWAPPED-IN TO CORE PAGE IN T + POP P,U + HLRZ D,MMSWP(T) + JUMPN D,OPNL12 ;POINTED TO BY AN EXEC PAGE, E.G. 340, SHOULDN'T MESS. + PUSH P,A ;SAVE USER'S VIRTUAL PAGE # + PUSH P,J ;SAVE WHAT JOB THAT IS + PUSH P,E ;SAVE ADDRESS OF MMP ENTRY + MOVE A,T ;PHYSICAL PAGE # TO SWAP OUT + MOVE C,USER ;DON'T PCLSR ME + PUSHJ P,SWPOPL ;SWAP OUT, EVEN IF LOCKED + JRST NPGWR4 ;NO DISK SPACE, OR SOME JOB NOT PCLSRABLE + POP P,E + POP P,J + POP P,A +NPGWR2: MOVE T,CTLBTS(U) + MOVSI D,MMPLOK + TRNE T,2 ;CONTROL BIT 1.2 UNLOCKS + ANDCAM D,(E) + TRNE T,1 ;CONTROL BIT 1.1 INHIBITS WAITING FOR SWAP TO FINISH. + JRST CLKOJ1 + MOVSI T,MMPTMP ;PAGE IN TRANSIT BIT + TDNE T,(E) ;WAIT FOR BIT TO TURN OFF + PUSHJ P,UFLS + JRST CLKOJ1 + +;COULDN'T SWAP OUT, WAIT A WHILE AND TRY AGAIN +NPGWR4: PUSHJ P,UDELAY ;UDELAY TURNS CLKON + POP P,E + POP P,J + POP P,A + JRST NPGWR1 + +EBLK + +;SWAP IN RQ BLOCKS +SWIRQB: +IFN 340P\E.SP, DISSWI: -1 ;USER +IFN VIDP, VIDSWI: -1 +IFN IMXP, POTSWI: -1 +IFN NSWPV-.+SWIRQB,.ERR NSWPV ERR + +SWIVPN: +IFN 340P\E.SP, DISSPG: 0 ;VIRTUAL PAGE NUMBER +IFN VIDP, VIDSPG: 0 +IFN IMXP, POTSPG: 0 + +SWPNTB: ;SIGNAL BITS IN LH OF W TO CFHSW1 +IFN 340P\E.SP, 400000 ;DISPLAY +IFN VIDP, 400000 ;VID +IFN IMXP, 400000 ;POTS + +SWILMT: ;PIRQC BIT TO SET ON ILM +IFN 340P\E.SP, %PIDIS +IFN VIDP, %PIMPV +IFN IMXP, %PIMPV + +PSWOUS: -1 ;INDEX OF PARTIALLY SWAPPED OUT USER +PSWCLS: 0 ;CLASS OF PARTIALLY SWAPPED OUT USER +PSWSFL: 0 ;-1 START FROM BEG OF USER, ELSE PICK UP WHERE LEFT OFF +SWPMBP: 0 ;PNTR TO MAP +SWPCBP: 0 ;PNTR TO CIRC DESC SPACE +PSWLC: 0 ;LOOP COUNT +SBEFLG: -1 ;0 => ALREADY ONCE WANTED TO CLEAR ALL "BEST EFFORT" BITS. +SWPOPR: 0 ;NUMBER OF PAGES DESIRED TO BE SWAPPED OUT +SWPOPB: 0 ;SWAP OUT REQUEST BUT ONLY SWAP OUT NON-RUNNING USERS TO MEET (UNUSED?) +SILNG: 0 ;TOTAL LENGTH OF SWAP IN LISTS +SOLNG: 0 ;TOTAL LENGTH OF SWAP OUT LISTS + ;SINLST AND SOUTLS ARE IN DISK CODE. VARIATION ON QBFP. +SWODSK: NQS-1 ;UNIT TO SWAP OUT ON NEXT +SWOBK: 0 ;MEMBLT BEING SWAPPED OUT +SWOMMP: 0 ;MMP ADDRESS (NOT INDEX) +SPGNMF: 0 ;-1 => PAGE NOT MODIFIED +CFHAS: 0 ;TEMP FOR A AT CFH +SWPIQS: 0 ;SAVE Q AT SWPPIN +CFHUVP: 0 ;USER'S VIRTUAL PAGE NUMBER TOOK FAULT ON +LUMPS: 0 ;UMAPS USED FOR CURRENT USER, MAY DIFFER FROM + ;UMAPS(U) IF TOOK FAULT TRYING TO CAUSE INTERRUPT +TRUMM: 0 ;TOTAL USER MEM ACTIVE USERS +NPGSWO: 0 ;NUMBER OF CURRENTLY SWAPPED OUT PAGES +AUSOPG: 0 ;ACTIVE USER SWAPPED OUT PAGES +BUMPGS: 0 ;REAL CORE PAGES OCC BY BLOCKED + STOPPED LOSERS +NUSWB: 0 ;# LOSERS SWAP BLOCKED +SWPOPU: 0 ;USER PG "BELONGS" TO (IE NOT NECC TO PCLSR THIS GUY, + ;BUT PCLSR ANYONE ELSE LINKED TO PG.) +AGEREQ: 0 ;NUMBER OF PAGES BEING AGED AT SLOW CLOCK +AGEPOS: 0 ;LAST PAGE # AGED + +IFE SWPWSP,[ +PRVUSR: -1 ;PRIV USR +PRVCUT: 1500 ;CUT OFF FOR PRIV USR +SWUPC: 0 ;ABSOLUTE PAGE NUMBER OF USER MODE PC DURNING SWAP OUT +SWPP0F: -1 ;-1 IF CONSIDERING PAGE 0 +ASBUM: 0 ;REAL MEM OCC BY ACTIVE "SWAPPED BLOCKED" LOSERS +SWSCT1: 0 ;TEM AT SWSCD +BUSR: 0 ;INDEX OF SMALLEST SWAP BLOCKED LOSER +BUSIZ: 0 ;SIZE OF BUSR +];SWPWSP + +IFN PAGPRE,[ +PREEMP: 0 ;IF NON-ZERO, A PRE-EMPT IS IN PROGRESS (WHEN WE NEXT GET TO CLK LVL) +NPREEL: 0 ;NUMBER OF LOOPS AT SCHEDP (ATTEMPTED PREEMPTS) +NPREEM: 0 ;NUMBER OF SUCCESSFULL PREEMPTS +NPREE1: 0 ;NUMBER OF TIMES A PAGE CAME IN AND WE STARTED TO THINK ABOUT PREEMPTION +NPREE2: 0 ;NUMBER OF TIMES WE DIDN'T PUNT BECAUSE OF CLKOFF OR IN PROGRESS +NPREE3: 0 ;NUMBER OF TIMES WE DIDN'T PUNT BECAUSE FLSINS WAS WRONG +];PAGPRE + +;COUNTS OF REASONS FOR ENTRY TO SCHED +;THESE METERS MAY BE TEMPORARY - SOME OF THEM ARE REDUNDANT +;REASONS NOT COUNTED - VARIOUS PARITY, NXM, AND OTHER ERROR CASES +NLPPRE: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PREEMPT +NLPCLK: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO CLOCK +NLPUFL: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO UFLS +NLPPAG: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE-IN +NLPPGT: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND TUT LOCKED +NLPPGC: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND CIRPSW LOCKED +NLPPGM: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND MEMFRZ LOCKED +NLPPG3: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND CALLED CFHPO3 (NO MEM) +NLPPGB: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND SWAP-BLOCKED +NPPIUM: 0 ;NUMBER OF TIMES PAGE PUT INTO BUNCHA USERS' MAPS +NPPIU1: 0 ;NUMBER OF USERS PAGES PUT INTO MAPS OF (RATIO OF THESE 2 IS SHARING) + +IFN SWPWSP,[ +LODQNT: ;RUN TIME IN 4-USEC UNITS BETWEEN PG FAULTS TO LEAVE + ;LOADING STATE + IFN KL10P, 3000. ;12 MS + IFN KA10P, 9000. ;36 MS + IFN KS10P, 3000. .ERR Guessed LODQNT on KS10? +LODFCT: 3,,0 ;MULTIPLY LOADING TIME BY THIS TO GET PROTECT TIME (INT,,FRAC) +NUPTAW: 0 .SEE SWOP6 ;NUMBER OF USERS PAGE TAKEN AWAY FROM + +;METERS + +NPLBLJ: 0 ;NUMBER OF PAGE LOADS BY LOADING JOBS +NPLBNL: 0 ;NUMBER OF PAGE LOADS BY NON-LOADING JOBS + +;Still to be done +; 1-, 5-, 15- minute average population of each state, +; also avg of NPGWTU and RNABLU (for load avg) +; avg of core occupied by jobs in each state, +; i.e. UWRKST for load, pro, sw in. +; Relationship of sum of UWRKST's of loading and swapped in +; versus total core occupied by user pages. +; Average time spent in each state before moving on, +; versus size of job. Maybe cpu time as well as +; real time? + +];SWPWSP +BBLK + + +OVHMTR SWP ;SWAP PAGE + +;SWAP OUT PAGE WHOSE MEMBLT INDEX IS IN A +;SKIP IF SUCCESSFUL +;C IS USER WHO DOESN'T NEED TO BE PCLSRED BEFORE HIS PAGES CAN BE SWAPPED. +SWPOPL: TDZA B,B ;THIS ENTRY IGNORES LOCK BIT +SWPOPG: MOVSI B,MMPLOK ;THIS ENTRY RESPECTS LOCK BIT + MOVEM C,SWPOPU + MOVEM A,SWOBK + CAIGE A,TSYSM + CAIGE A,SYSB + BUG ;DON'T SWAP OUT PART OF SYSTEM + AOSE CIRPSW + POPJ P, + LDB C,[MMMPX,,MEMBLT(A)] + ADDI C,MMP + HRRZM C,SWOMMP ;STORE ADDRESS OF FIRST WORD OF MMP ENTRY + TDNE B,(C) .SEE MMPLOK ;LOCKED IN CORE? + JRST [ CAIGE A,256. ;IF SO, DON'T SWAP OUT UNLESS IN "LOW" MEMORY + CAIGE A,LIOBLK ;IN WHICH CASE MUST GO OUT TO AVOID SYSTEM DEADLOCK + JRST SCRPSJ ;SEE CODE AT CIMEMR + CAIGE A,128. + JRST .+1 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES + SKIPN USEMDM + JRST SCRPSJ + JRST .+1 ] + SOS CIRPSW ;RELEASE SWITCH + HLRZ B,1(C) + JUMPN B,SWOP1 ;JUMP IF DISK SPACE ALREADY ASSIGNED +SWODF3: MOVSI B,-NQS +SWODF6: AOS I,SWODSK + CAIL I,NQS + SUBI I,NQS ;WRAP AROUND + MOVEM I,SWODSK ;CURRENT SWAPPING DSK + CONO PI,UTCOFF-1 ;DON'T CHANGE STATE OF CLOCK CHNL. + SKIPGE QTUTO(I) ;TUT LOCKED + JRST SWODF7 + SKIPL QACT(I) + SKIPG QSFTS(I) ;DSK FULL IN SWAPPING AREA + JRST SWODF7 + MOVSI A,(SETZ) + IORM A,QTUTO(I) + CONO PI,UTCON-1 ;DON'T TURN ON CLOCK CHNL. + MOVEI A,NQCHN+1(I) ;QMFTP(A) CONTAINS TRACK TO START FROM + PUSHJ P,QGTK4 ; RETURNS TRACK IN D + SOS QSFTS(I) +SWODF5: MOVSI A,(SETZ) + ANDCAM A,QTUTO(I) + MOVE A,SWOMMP + HRLM D,1(A) ;STORE DISK ADDRESS IN MMP ENTRY + DPB I,[$MMPUN,,(A)] + JRST SWOP1 + +SWODF7: AOBJN B,SWODF6 ;TRY NEXT DSK FOR SWAPPING AREA + CONO PI,UTCON-1 ;NON FOUND FIND FILE SPACE + MOVNI D,1 + MOVNI I,1 + MOVSI E,-NQS +SWODF2: SKIPL QTUTO(E) ;FIND WHICH DISK HAS MOST FREE SPACE + SKIPGE QACT(E) + JRST SWODF4 + CAMGE D,QSFT(E) + HRRZ I,E + CAMGE D,QSFT(E) + MOVE D,QSFT(E) +SWODF4: AOBJN E,SWODF2 + JUMPL I,CPOPJ ;NO DSK SPACE AVAIL + HRRZM I,SWODSK ;LAST DSK HACKED + JUMPLE D,CPOPJ ; NO ROOM ANYWHERE + CONO PI,UTCOFF-1 + SKIPGE QTUTO(I) + JRST UTCNJ ;TUT LOCKED + MOVSI A,(SETZ) + IORM A,QTUTO(I) + CONO PI,UTCON-1 + MOVEI D,NBLKS/2 ;STARTING POINT + MOVEI A,NQCHN+1(I) ;DISK CHANNEL + MOVEM D,QMFTP(A) + PUSHJ P,QGTK4 ;RETURNS TRACK IN D + MOVEI E,NUDSL + MOVEM E,QMFTP(A);DON'T LEAVE SWAPPING CHNL POINTING INTO FILE SPACE + SOS QSFT(I) + JRST SWODF5 + +SCRPSJ: SETOM CIRPSW + POPJ P, + +SWOP1: AOSE CIRPSW + POPJ P, + AOS NPGSO + +;COME HERE FROM SWPOPG AND MMPRTN TO SWAP OUT A PAGE. +;CLOCK OFF OR IN PROGRESS AND ARGUMENTS IN SWOBK AND SWOMMP. +;PUTS BLOCK ON SWAPOUT LIST IF DISK COPY NEEDS TO BE UPDATED, ELSE +;JUST DELETES MEMORY. IF NO USERS ARE USING THE PAGE, +;RETURNS THE MMP ENTRY OR ARRANGES FOR THE DISK ROUTINES TO. + +SWOP1A: CONO PI,UTCOFF-1 ;DON'T CHANGE STATE OF CLOCK CHNL. + MOVE A,SWOBK ;CORE BLOCK # CONTAINING PAGE TO BE SWAPPED OUT + HLRZ C,MMSWP(A) ;NUMBER OF EXEC PAGES POINTING TO THIS PAGE + JUMPN C,SWOP5 ;POINTED TO BY EXEC PAGE, CAN'T SWAP OUT +IFN 340P,[ + MOVSI C,-N340PB-2 +SWOPT2: LDB I,DPEP(C) + TRZN I,600000 + JRST SWOPT1 + ANDI I,PMRCM ;MASK TO REAL CORE PAGE # + CAIN I,(A) + BUG ;DISPLAY STILL SET UP TO PAGE BEING SWAPPED OUT +SWOPT1: AOBJN C,SWOPT2 +] + MOVSI C,MMPPGA + ANDCAM C,@SWOMMP + MOVSI C,(SETZ) + IORM C,MEMBLT(A) ;PREVENT NEW EXEC PAGES FROM BEING SET UP POINTING HERE + CONO PI,UTCON-1 + MOVE C,[2200,,MEMPNT] + ADD C,SWOBK + SETOB B,SPGNMF ;INITIALIZE PAGE NOT MODIFIED FLAG, AND COUNT USERS IN B +IFN SWPWSP,[ + LDB I,C + PUSH P,I + SETZM NUPTAW + MOVSI D,-1 ;COMPUTE WORKING SET CONTRIBUTION TO BE TAKEN AWAY + IDIV D,MMSWP(A) ;LH(MMSWP) KNOWN TO BE ZERO! + PUSHJ P,UCPRL ;CHECK ALL USERS, TAKE PAGE AWAY FROM SOME + 400000,,SWOP6 ;ALSO COUNTS USERS IN B + POP P,I + AOJE B,SWOP7 ;JUMP IF NO USERS USING PAGE, RETURN MMP ENTRY + CAMN B,NUPTAW ;ANY USERS STILL MAPPED TO PAGE? + JRST SWOP8 ;NO, GO SWAP IT OUT + MOVSI D,1 ;YES, COMPUTE WORKING SET ADJUSTMENT + IDIV D,MMSWP(A) ;TO BE ADDED BACK IN TO THEM + PUSHJ P,UCPRL ;GO BACK AND FIX WORKING SETS + 400000,,SWOP6B + JRST SWOP6E ;ABORT SWAP OUT +];SWPWSP +IFE SWPWSP,[ + LDB I,C + PUSH P,I ;NOTE: CAN BACK OUT OF THIS PUSH AT SWOP2B + PUSHJ P,UCPRL + 400000,,SWOP2 ;RETURN ON USERS (CAN BACK OUT AT SWOP2B) + POP P,I + JUMPGE B,SWOP8 +];SWPWSP +SWOP7: MOVSI B,MMPGON ;NO USERS USING PAGE, SO MMP ENTRY WILL BE RETURNED + IORM B,@SWOMMP ;FLAG THAT MMP ENTRY WILL SOON GO AWAY + MOVEI A,0 ;REMOVE FROM LOOSE PAGE LIST + MOVE T,FLOOSP +SWOP7A: MOVE B,A ;B PREDECESSOR + SKIPN A,T ;T SUCCESSOR + BUG ;NOT IN LIST? + LDB T,[MLO,,MEMBLT(A)] + CAME A,SWOBK + JRST SWOP7A + SKIPE B ;FOUND, PATCH OUT OF LIST + DPB T,[MLO,,MEMBLT(B)] + SKIPN B + MOVEM T,FLOOSP + SKIPN T + MOVEM B,LLOOSP + SOSL NLOOSP + JRST SWOP8 + BUG ;NLOOSP TOO LOW. + +IFN SWPWSP,[ + +;THIS UCPRL ROUTINE SCANS ALL USERS, COUNTS THEM IN B, +;USES D TO ADJUST WORKING SETS OF USERS WHICH ARE MAPPED TO +;THE PAGE, AND TAKES THE PAGE AWAY FROM ANY USERS IT CAN, +;COUNTING THEM IN NUPTAW. +SWOP6: AOS B ;COUNT USERS OF THIS PAGE + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB? + PUSH P,I + MOVEI C,UPGMP(U) ;MAKE C POINT TO UPGMP ENTRY (PTW) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNE I,600000 + ADDM D,UWRKST(U) ;IS MAPPED TO PAGE, ADJUST WORKING SET + CAMN U,SWPOPU + JRST SWOP6A ;DON'T CONSIDER PCLSRING SWPOPU + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWOP6A + SKIPN LSWPR(U) ;PCLSR IF HAS SWITCHES LOCKED + SKIPN FLSINS(U) + JRST SWOP6D + MOVSI T,%SWPCL ;DONT PCLSR NOW, BUT WHEN UNBLOCKS + IORM T,USWST(U) + JRST SWOP6A + +SWOP6D: PUSH P,D + PUSH P,C + PUSH P,I + PUSHJ P,PCLSR ;BETTER NOT CLOBBER U OR H OR A + JRST [ SUB P,[2,,2] + POP P,D + JRST SWOP6C ] + POP P,I + POP P,C + POP P,D +;WHEN WE GET HERE, THIS JOB CAN'T HOLD THIS PAGE IN +SWOP6A: TRNN I,600000 + JRST SWOP6C ;NOT SET UP SINCE PREV SWAPPED OUT + AOS NUPTAW ;TAKE IT AWAY + LSH I,-16. ;SAVE ACCESS MODE IN LOW ADR BITS + CAILE I,2 ;SKIP ON READ ONLY OR READ/WRITE/FIRST + CLEARM SPGNMF ;PAGE HAS BEEN MODIFIED + CAIN I,2 ;FLUSH R.W.F. + MOVEI I,3 + DPB I,C ;STORE PROTECTION BITS BACK IN LOWER TWO BITS OF ENTRY + AOS NSWPGS(U) ;INCR COUNT OF SWAPPED OUT PGS OF USER + AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + SOS MMSWP(A) ;DECR COUNT OF PAGE SHARERS +IFN E.SP,[ + CAMN U,DISUSR ;IF USER OF E&S + PUSHJ P,E.SLPM ;LOAD ITS MAP +] +SWOP6C: POP P,I + POPJ P, + +SWOP6F: CAMN U,-4(P) ;DON'T LOOK AT USER TAKING PAGE AWAY FROM + POPJ P, ;ELSE DROP INTO SWOP6B +;THIS UCPRL ROUTINE ADJUSTS WORKING SETS OF JOBS THAT +;ARE MAPPED TO THE PAGE USING D. +SWOP6B: PUSH P,I + MOVEI C,UPGMP(U) ;MAKE C POINT TO UPGMP ENTRY (PTW) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNE I,600000 + ADDM D,UWRKST(U) ;IS MAPPED TO PAGE, ADJUST WORKING SET + POP P,I + POPJ P, +];SWPWSP + +IFE SWPWSP,[ +;COME HERE VIA UCPRL FOR ALL USERS OF PAGE BEING SWAPPED OUT + +SWOP2: AOS B ;COUNT USERS OF THIS PAGE + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB? + PUSH P,I + CAMN U,SWPOPU + JRST SWOP2A + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWOP2A + SKIPN LSWPR(U) ;PCLSR IF HAS SWITCHES LOCKED + SKIPN FLSINS(U) + JRST SWOP2D + MOVSI T,%SWPCL ;DONT PCLSR NOW, BUT WHEN UNBLOCKS + IORM T,USWST(U) + JRST SWOP2A + +SWOP2D: PUSHJ P,PCLSR + JRST SWOP2B +SWOP2A: MOVEI C,UPGMP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNN I,600000 + JRST SWOP2C ;NOT SET UP SINCE PREV SWAPPED OUT + LSH I,-16. ;SAVE ACCESS MODE IN LOW ADR BITS + CAILE I,2 ;SKIP ON READ ONLY OR READ/WRITE/FIRST + CLEARM SPGNMF ;PAGE HAS BEEN MODIFIED + CAIN I,2 ;FLUSH R.W.F. + MOVEI I,3 + DPB I,C ;STORE PROTECTION BITS BACK IN LOWER TWO BITS OF ENTRY + AOS NSWPGS(U) ;INCR COUNT OF SWAPPED OUT PGS OF USER + AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + MOVE I,SWOBK + SOS MMSWP(I) ;KEEP ACCURATE COUNT OF UPGMP'S POINTING AT THIS PAGE +IFN E.SP,[ + CAMN U,DISUSR ;IF USER OF E&S + PUSHJ P,E.SLPM ;LOAD ITS MAP +] +SWOP2C: POP P,I + POPJ P, + +SWOP2B: SUB P,[6,,6] ;2 PUSHES OF I AND 4 FOR UCPRL +];SWPWSP +SWOP6E: MOVE A,SWOBK ;ABORT SWAP-OUT + MOVSI I,(SETZ) + ANDCAM I,MEMBLT(A) + SOS CIRPSW + POPJ P, + +SWOP8: DPB I,C ;DELINK MEMPNT + MOVEI I,3 .SEE MMPOUT .SEE MMPTMP + DPB I,[410200,,@SWOMMP] ;INDICATE ON THE WAY OUT + MOVSI I,MMPBAD + ANDCAM I,@SWOMMP + MOVE A,SWOBK + MOVSI B,(SETZ) + CONO PI,UTCOFF-1 + ANDCAM B,MEMBLT(A) + MOVE C,@SWOMMP + TLNN C,MMPGON ;UNLESS PAGE WILL BE FORGOTTEN AFTER SWAP OUT, + AOS NPGSWO ; KEEP COUNT OF PAGES CURRENTLY SWAPPED OUT + TLNE C,MMPWRT ;IF WAS WRITTEN BY USER WHO LATER DELETED IT, + JRST SWOP3 + SKIPGE SPGNMF ;OR IF PAGE MODIFIED, + TLNN C,MMPWOD + JRST SWOP3 ;OR IF HASN'T BEEN WRITTEN TO DISK, MUST WRITE OUT. + MOVEI I,2 ;NO NEED TO WRITE OUT. INDICATE OUT. + DPB I,[410200,,@SWOMMP] + PUSHJ P,IMEMR ;RETURN THE MEMORY + MOVE A,SWOMMP + TLNE C,MMPGON + PUSHJ P,RETMMP ;ALSO RETURN THE MMP ENTRY IF NECESSARY + JRST SWOP4 + +SWOP5: SOS CIRPSW +UTCNJ: CONO PI,UTCON-1 ;DON'T TURN ON CLOCK CHNL + POPJ P, + +SWOP3: CAIGE A,TSYSM ;HAVE TO WRITE THIS PAGE OUT + CAIGE A,SYSB + BUG + HRRZ B,SWOMMP + LDB I,[$MMPUN,,(B)] + CAIL I,NQS + BUG ;DISK NUMBER NOT LEGITIMATE + MOVEI C,.BM MLO + ANDCAM C,MEMBLT(A) ;SET END OF LIST IN THIS BLOCK + HLRZ C,SOUTLS(I) ;GET PREV BLOCK + SKIPE C + DPB A,[MLO,,MEMBLT(C)] ;CHAIN TO PREV BLOCK + SKIPN C + MOVEM A,SOUTLS(I) ;OR TO HEADER IF FIRST + HRLM A,SOUTLS(I) ;AND SET NEW LAST BLOCK + AOS SOLNG + HLRZ C,1(B) + HRLM C,MEMPNT(A) ;STORE DISK ADDRESS + MOVEI B,MUSWPG + DPB B,[MUR,,MEMBLT(A)] + PUSHJ P,QSTRT1 +SWOP4: SOS CIRPSW +UTCNJ1: CONO PI,UTCON-1 + JRST POPJ1 + +IFN NSWPV,[ +SWPPIN: MOVSI Q,-NSWPV ;# OF DEVICES THAT CAN SWAP IN PAGES +SWPPI4: SKIPGE W,SWIRQB(Q) ;USER INDEX + JRST SWPPI6 + MOVE E,SWIVPN(Q) ;VIRTUAL PAGE NUMBER + HRL W,SWPNTB(Q) + CLEARB TT,D + MOVEM Q,SWPIQS + PUSHJ P,CFHSW1 + MOVE Q,SWPIQS + SETOM SWIRQB(Q) +SWPPI6: AOBJN Q,SWPPI4 + POPJ P, +] + +SWIILM: +IFN E.SP,[ + TRNN Q,-1 ; IS DEVICE DIS? (E&S IS INDEX 0 IN SWIRQB) + SETZM E.SPGW ; IF SO, CLEAR PAGE WAIT. +] + SKIPGE E,SWILMT(Q) + BUG + IORM E,PIRQC(W) + MOVEI A,0 + POPJ P, + +SUBTTL LOAD USER PAGE MAP + +OVHMTR UUO ;RANDOM UUOS (WELL, SOME MINOR SCHED STUFF, TOO) + +;SET PAGE MAP AT M.P. LEVEL, ASSUMING UMAPS HAS BEEN ALTERED. +;UMAPS EXISTS SO SCHEDULER CAN RESTORE THE MAP AFTER OTHER JOBS RUN. +;FORMAT OF A MAP SPECIFICATION IS: +%UM==1,,525252 +%UMMPL==200000 ;1 => MAP LOWER HALF TO SPEC'D JOB'S; 0 => USE LOWER OF JOB IN U. +%UMMPU==100000 ;1 => MAP UPPER HALF TO SPEC'D JOB'S; 0 => USE UPPER OF JOB IN U. +%UMALL==300000 ;SET => SELECT WHOLE MAP OF SPEC'D JOB. +%UMUTL==40000 ;IGNORED IF %UMMPU=0. IF %UMMPU=1, MEANS USE SPEC'D JOB'S LOWER + ;INSTEAD OF ITS UPPER, AS OUR UPPER HALF. READ "%UM UPPER-TO-LOWER". +%UMLTU==20000 ;"%UM-LOWER-TO-UPPER". WITH %UMMPL, MAKES LOWER -> SPEC'D JOB'S UPPER. +%UMSOA==4000 ;1 => USE AC0S AS THE USER'S ACS, INSTEAD OF UUOACS. + ;NOTE IF %UMLTU=1, OR IF LOWER -> PDP6, THE GARBAGS ACS ARE USED. + ;ELSE, THE ACS COME FROM THE JOB WHICH OUR LOWER HALF COMES FROM. +;RH ;JOB INDEX OF THE "SPECIFIED JOB". -1 => PDP6. + ;NOT NEEDED IF %UMMPL=%UMMPU=0. + +PGLDU: MOVE R,UMAPS(U) +;SET PAGE MAP AT INT. LEVEL, NOT CLOBBERING JOB'S UMAPS. ARG IN R. +PGLD: MOVEM R,LUMPS ;LAST UMAPS ACTUALLY USED + AOS NPGLD ;COUNT # CALLS TO PGLD + PUSH P,A ;R HAS UMAPS CODE + PUSH P,B + PUSH P,C + HRRZ C,U +IFN KA10P, MOVSI B,NUVPG/2 ;SET UP NORMAL DBL, MIGHT BE CHANGED IF PDP6 +IFE KA10P, MOVSI B,0 ;ONLY KA10 HAS DBL + TLNN R,%UMMPL + JRST PGLD3A ;USE NORMAL LOW SEG +IFN PDP6P,[ + TRNE R,400000 + JRST PGLD3B ;USE PNTR TO PDP6 +] + HRRZ C,R + TLNE R,%UMLTU ;SKIP ON USE HIS LOWER + JRST PGLD3D ;USE HIS UPPER +PGLD3A: HRRI B,UDBR1A(C) + TLNE R,%UMSOA + JRST PGLD3G ;MAKE AC'S POINT AT SWAP OUT AC'S + MOVEI A,UUOACS(C) +PGLD3F: MOVEM B,UPDBR1(U) +IFN KA10P, DPB A,[2300,,UPACP(U)] ;STORE AC PNTR +IFE KA10P,[ + CAMN A,AC1PTR ;IF CHANGING AC BLOCK 1 + JRST PGLD3H + EXCH A,AC1PTR ;STORE OLD BLOCK 1 + MOVE B,A + XCTR XBR,[BLT B,17(A)] + MOVS A,AC1PTR ;AND LOAD NEW BLOCK 1 + XCTR XBW,[BLT A,17] +PGLD3H: ] ;IFE KA10P +IFN KA10P, MOVSI B,NUVPG/2 ;SET UP DBL FOR DBR2 +IFE KA10P, MOVSI B,0 + HRRI B,UDBR2A(U) + TLNN R,%UMMPU + JRST PGLD6 ;USE NORMAL UPPER SEG + HRRI B,UDBR2A(R) + TLNE R,%UMUTL + HRRI B,UDBR1A(R) +IFN PDP6P,[ + TRNE R,400000 + MOVE B,PDP6MP +] +PGLD6: MOVEM B,UPDBR2(U) +PGLDR1: LPMR UPGML(U) + POP P,C + POP P,B + POP P,A + POPJ P, + +IFN PDP6P, PGLD3B: SKIPA B,PDP6MP +PGLD3D: HRRI B,UDBR2A(R) + MOVEI A,GACS + JRST PGLD3F + +PGLD3G: MOVEI A,AC0S(C) + JRST PGLD3F + +GACS: BLOCK 20 ;GARBAGE AC'S POINTED TO BY ACPNTR WHEN ITS REALLY POINTING + ;AT UPPER PAGES OR PDP6 SHOULD HOPEFULLY NEVER GET REFERENCED + +;MAIN PROGRAM MAP-SETTING ROUTINES. +IFN PDP6P,[ +MP6LD: SKIPA J,[%UMMPU,,-1] ;LOAD UPPER DBR TO PNT TO 6 +];PDP6P +MPLDZ: MOVEI J,0 ;SET NORMAL MAP - OUR OWN CORE. +MPLD1: CAMN J,UMAPS(U) ;SET UMAPS AS SPEC'D + JRST CLKONJ + MOVEM J,UMAPS(U) +MPLD: CONO PI,CLKOFF + PUSHJ P,PLD + JRST CLKONJ + +;SET MAP TO JOB # IN J; MIGHT OR MIGHT NOT BE THE CURRENT JOB. SAVES RH(J) +MPLDJ: CAME J,USER + TLOA J,%UMSOA+%UMALL ;OTHER JOB'S ACS ARE IN ITS AC0S. + TLO J,%UMALL ;THIS JOB => WANT UUOACS. + JRST MPLD1 + +;SIMILAR ROUTINES, BUT FOR USE WHEN CLKCHN IS OFF AND SHOULD STAY OFF. +IFN PDP6P,[ +PLD6: SKIPA J,[%UMMPU,,-1] ;MAKE UPPER DBR POINT TO PDP6. +];PDP6P +PLDZ: MOVEI J,0 ;NORMAL MAP +PLD1: MOVEM J,UMAPS(U) +PLD: SPM UPGML(U) ;IF ANY INHIBITED FAULT PRESENT, CAUSE IT TO GET STORED AWAY + PUSH P,R + PUSHJ P,PGLDU ;CAUSE ACTUAL PG LOAD TO HAPPEN + POP P,R + POPJ P, + +SUBTTL GIVING THE USER INTERRUPTS + +SEAR2E: MOVE A,PIRQC(U) + +;ROUTINE TO HANDLE FIRST WORD (PIRQC) INTS +SEAR2A: JUMPL A,SEAR2B ;REQUEST TO PCLSR + SKIPN PICLR(U) + JRST SEAR2C ;PI IN PROG, ONLY LOOK FOR FATAL INTS. + SETCM Q,IDF1(U) + AND Q,MSKST(U) ;ENABLED UNDEFERRED INTS. + TDNN A,Q ;ANY OF THOSE PENDING, + TDNE A,[BADBTS] ;OR ANY CLASS 1 OR 2 => INTERRUPT. + CAIA + JRST SEARL2 + ANDCA Q,A ;GET DISABLED OR DEFERRED PENDING INTS. + TDNN Q,[BADBTS] ;ANY CLASS 1 OR 2 DISABLED OR DEFERRED + JRST INTWD1 ;NO, INT. THIS JOB. + JRST SEAR2D ;YES, INT. SUPERIOR. + +SEAR2C: TDNN A,[BADBTS] ;PI IN PROG: ANY CLASS 1 OR 2 ? + JRST SEARL2 ;NO, NOTHING TO DO. +SEAR2D: PUSHJ P,PCLSR ;INT. THE SUPERIOR: PCLSR FIRST. + JRST SEARC ;CAN'T STOP THIS JOB IN EXEC MODE. + SETZ B, ;OK, HANDLE FATAL 1ST WORD INTS IN A, AND NO 2ND WORD INTS. + +;HANDLE A FATAL INTERRUPT BY INTERRUPTING THE SUPERIOR. +;FATAL 1ST WORD INTERRUPTS IN A, FATAL 2ND WORD INTS IN B. +INTSUP: MOVEM A,SRN4(U) ;.FTL1 + MOVEM B,SRN5(U) ;.FTL2 ;PUT THE FATAL INTERRUPTS WHERE SUPERIOR CAN READ THEM. + MOVSI T,BUSRC + IORM T,USTP(U) ;STOP INFERIOR +IFN SWPWSP, PUSHJ P,LVLOAD + MOVSI T,BULGOS ;IF LOST TRYING TO LOG OUT, ABORT LOGOUT + ANDCAM T,APRC(U) + MOVE Q,U ;SAVE USER INTERRUPTING + SKIPGE U,SUPPRO(U) ;SKIP UNLESS TOP LEVEL + JRST INTTOP ;REALLY TOP LEVEL + HLLZ T,U ;GET INT BIT + IORM T,IFPIR(U) ;TURN ON INTERRUPT BIT IN SUPERIOR + HRRZS U ;CLEAR LEFT HALF OF U + CAIL J,(U) ;SKIP IF SUPERIOR HAS NOT YET BEEN SCHEDULED + JRST SEARL1 ;RESCHEDULE SUPERIOR + JRST SEARL ;HAVEN'T GOT TO HIM YET SO CONTINUE + +INTTOP: MOVEI T,SCRDET + SKIPL APRC(Q) ;IF JOB ISN'T ALREADY DISOWNED + IORM T,SUPCOR ;SAY SOMEONE WANTS TO BE DETACHED. + JRST SEARL ;LEAVE STOPPED, SYS JOB WILL DETACH SOMEDAY. + +SEAR2B: PUSHJ P,PCLSR ;PCLSR THE JOB, E.G. SO IT CAN GET AN IOC ERROR + JRST SEARC ;RUNNING IN EXEC MODE, GO RUN IT + MOVSI A,(SETZ) ;CLEAR REQUEST + ANDCAM A,PIRQC(U) + JRST SEARL1 ;INSPECT THIS JOB AGAIN + +;IFPIR IS NONZERO BUT PIRQC IS ZERO. +INTWD2: SKIPN PICLR(U) + JRST SEARL3 ;IGNORE 2ND WD INTS IF PI IN PROG. + AND B,MSKST2(U) + ANDCM B,IDF2(U) ;GET ENABLED UNDEFERRED INTS. + JUMPE B,SEARL3 ;ALL DISABLED OR DEFERRED. + JSP T,INTPAG ;MAKE SURE NOT WAITING FOR PAGE NEEDED FOR INT. + PUSHJ P,PCLSR ;DON'T INT. EXCEPT IN USER MODE. + JRST SEARC + SETZ A, ;1ST WD INTS TO GIVE = 0. + JRST INTSRC ;2ND WD INTS TO GIVE ALREADY IN B. + +;PIRQC WAS NONZERO BUT NO FATAL INTS. +INTWD1: JSP T,INTPAG ;IF TRIED BEFORE & WENT TO INTPFL, WAIT FOR PAGE. + PUSHJ P,PCLSR ;CAN INT. ONLY IN USER MODE. + JRST SEARC + MOVE B,IFPIR(U) + AND B,MSKST2(U) ;GET PENDING ENABLED UNDEFERRED 2ND WD INTS IN B. + ANDCM B,IDF2(U) + AND A,MSKST(U) + ANDCM A,IDF1(U) ;PENDING ENABLED UNDEFERRED 1ST WD INTS IN A. +INTSRC: AOS NAUINT ;ELSE 1 MORE ATTEMPT TO INTERRUPT. + MOVSI R,%UMSOA ;LOAD ORDINARY MAP FOR THIS USER. + PUSHJ P,PGLD ;BUT ACS -> SWAP OUT ACS. + HRRZ T,40ADDR(U) ;GET ADDR OF USER'S LOCATION "40" + XCTRI XR,[MOVE T,2(T)] ;TRY TO GET CONTENTS OF "42" (..I SO STOP ON EXEC PG FAULT DOESNT) + SKIPA R,T + JRST INTPFL ;PAGE FAULT IN XCTR, GIVE UP & WAIT FOR PAGE. + ANDI R,-1 + JUMPE R,INTBAD ;42 POINTS TO 0 => BADPI ERROR. + MOVE TT,OPTION(U) + TLNN TT,%OPINT ;NEW STYLE INTERRUPTS? + JRST INTOLD ;NO, OLD STYLE. + XCTRI XR,[MOVE R,(R)] ;GET ADDR OF HIS INT PDL PTR. + CAIA + JRST INTPFL + JUMPGE T,INTBAD + CAMGE T,[-72.*5-1,,] + JRST INTBAD + XCTRI XR,[MOVE H,(R)] ;GET CONTENTS OF INT PDL PTR. + JRST INTSR2 ;ADVANCE T PAST INT PDL PTR ADDR. + JRST INTPFL + +INTSR0: XCTRI XR,[MOVE C,(T)] ;GET THE INTS NEXT INT TABLE ENTRY + SKIPA D,B + JRST INTPFL ;APPLIES TO. + XCTRI XR,[AND D,1(T)] + CAIA + JRST INTPFL + AND C,A ;WHICH OF THEM ARE WE TRYING TO GIVE? + JUMPN C,.+2 + JUMPE D,INTSR1 ;NOT GIVING ANY OF THEM, TRY NEXT ENTRY. + MOVE Q,IDF1(U) ;GET CURRENT SETTINGS OF DEFER WORDS. + XCTRI XW,[MOVEM Q,3(H)] + SKIPA Q,IDF2(U) ;AND PUT INTO NEXT INT PDL FRAME. + JRST INTPFL + XCTRI XW,[MOVEM Q,4(H)] + SKIPA Q,UPC(U) ;ALSO PUT CURRENT PC IN FRAME. + JRST INTPFL + XCTRI XW,[MOVEM Q,5(H)] + CAIA + JRST INTPFL + XCTRI XR,[MOVE E,2(T)] ;NOW SEE WHICH DEFER BITS TO TURN ON NOW. + CAIA + JRST INTPFL + XCTRI XR,[MOVE TT,3(T)] + CAIA + JRST INTPFL + XCTRI XR,[MOVE Q,4(T)] ;AND THE NEW PC. + TLOA Q,%PCUSR + JRST INTPFL + TLZ Q,BADPC + SKIPGE IOTLSR(U) + TLO Q,%PCUIO ;DON'T CHANGE HIS IOTLSR STATUS. + XCTRI XW,[MOVEM C,1(H)] + CAIA ;PUT INTS BEING GIVEN IN + JRST INTPFL ;INT. PDL FRAME. + XCTRI XW,[MOVEM D,2(H)] + TDZA B,D + JRST INTPFL + MOVE W,H ;REMEMBER PDL PTR BEFORE INCREMENT, FOR PDL OV TESTING + ADD H,[5,,5] + LDB J,[220500,,R] ;HOW MANY ACS SHOULD WE SAVE? + JUMPE J,INTSR5 ;NONE? + HRLS J + ADD H,J ;ADVANCE THE PDL PTR OVER WHERE THEY'LL GO. + SUBM H,J ;GET BACK THE OLD UN-ADVANCED PDL PTR IN J. + ROT R,14 + HRLI J,(R) ;PUT 3.7-4.1 OF R INTO LH(J) CIRCUITOUSLY + TLZ J,777760 + ROT R,-14 + AOS J ;MAKE J POINT AT 1ST UNUSED PDL WORD. + XCTRI XBRW,[BLT J,(H)] + CAIA + JRST INTPFL +INTSR5: JUMPGE R,INTSR4 ;SAVE DEBUGGING INFO ON INT PDL IF USER WISHES + HRRZ J,UPJPC(U) + XCTRI XW,[MOVEM J,1(H)] + SKIPA J,SUUOH(U) + JRST INTPFL + XCTRI XW,[MOVEM J,2(H)] + SKIPA J,LSPCL(U) + JRST INTPFL + XCTRI XW,[MOVEM J,3(H)] + CAIA + JRST INTPFL + ADD H,[3,,3] +INTSR4: MOVE J,U ;MAYBE? SCHED LOOP WANTS USER IDX IN J? + XCTRI XW,[MOVEM H,(R)] ;STORE BACK THE PDL POINTER, THUS FINALIZING ALL + TDZA A,C ;INTS HAVE BEEN GIVEN; NOW WE CAN CHANGE THE USER VARS. + JRST INTPFL + ANDCAM C,PIRQC(U) + ANDCAM D,IFPIR(U) + IORM E,IDF1(U) ;SET THE DEFER BITS SPEC'D IN TABLE ENTRY. + IORM TT,IDF2(U) + MOVEM Q,UPC(U) ;START USER AT INT HANDLER. + JUMPL H,INTSR3 ;NOW CHECK FOR INT PDL OVFLO. + JUMPGE W,INTSR3 + MOVEI TT,%PIPDL ;THERE WAS OVFLO, SET PDL OV INT + TDNN TT,MSKST(U) ;IF ENABLED. + JRST INTSR3 + IORM TT,PIRQC(U) + JRST SEAR2E ;RE-TRY THE INTERRUPT. + +INTSR3: JUMPN A,SEAR2E ;MORE INTS TO GIVE => RETRY. + JUMPN B,SEAR2E +INTSRX: AOS NUINT ;1 MORE INT GIVEN SUCESSFULLY. + SPM UPGML(U) + JRST SEARC ;SCHEDULE. + +INTSR1: ADD T,[4,,4] ;NO INTS GIVEN, TRY NEXT ENTRY. +INTSR2: AOBJN T,INTSR0 + JRST INTSUP ;ENABLED INTS BUT NO ENTRIES FOR THEM. + +;GIVE INTS THE OLD WAY. +INTOLD: SKIPN C,A ;GIVE INTS OF 1 WD AT A TIME. + SKIPA C,B ;(NO 1ST WD, GIVE ALL 2ND WD) + TDZA B,B ;(SOME 1ST WD INTS, GIVE NO 2ND WD INTS) + TLO C,4^5 ;(GIVING 2ND WD, SET SIGN TO SAY SO) + XCTRI XW,[MOVEM C,(T)] + SKIPA Q,UPC(U) ;STORE INTS BEING GIVEN, + JRST INTPFL + MOVEI T,2(T) ;ADVANCE -> PLACE TO START USER. + XCTRI XW,[MOVEM Q,-1(T)] + TLOA T,%PCUSR ;OLD PC STORED, SET UP NEW. + JRST INTPFL + ANDCAM A,PIRQC(U) ;SAY THESE INTS NOW GIVEN. + ANDCAM B,IFPIR(U) + SKIPGE IOTLSR(U) + TLO T,%PCUIO + MOVEM T,UPC(U) ;SET HIS PC -> TSINT+2 + SETZM PICLR(U) + JRST INTSRX + +;IF WE ARE WAITING FOR A PAGE NEEDED FOR TAKING AN INTERRUPT, +;GIVE UP ON TRYING TO TAKE TE INT. UNLESS PAGE HAS COME IN SINCE LAST TRY. +INTPAG: MOVSI E,%SWPGW + SKIPE FLSINS(U) + TDNN E,USWST(U) + JRST (T) ;JOB NOT WAITING FOR PAGE + MOVSI E,%SWINT + TDNN E,USWST(U) + JRST (T) ;NOT WAITING FOR INTERRUPT PAGE + MOVE E,T + MOVE T,EPDL2(U) + XCT FLSINS(U) + JRST SEARL ;PAGE NOT IN + MOVSI T,%SWPGW+%SWINT ;PAGE IN + ANDCAM T,USWST(U) + SETZM FLSINS(U) + SOS NPGWTU + JRST (E) + +;COME HERE WHEN AN XCTRI TAKES FAULT WHILE TRYING TO STORE AN INTERRUPT. +INTPFL: MOVE J,U ;MAYBE? SCHED MAIN LOOP WANTS USR IDX IN J. + SPM UPGML(U) ;STORE MAP IN INTERRUPTING STATE +IFN KA10P, LDB T,[221000,,UPJPC(U)] ;FAULT ADDRESS +IFN KL10P, LDB T,[$PFPNO,,UPFW(U)] +IFN KS10P, LDB T,[$PFPNO,,EPTP7W] ; Fault happened at PI level 7. + ROT T,-1 + ADDI T,UPGCP(U) + SKIPL T + TLOA T,222200 + HRLI T,2200 + LDB E,T + JUMPE E,INTBAD ;DON'T HAVE PAGE +IFN KA10P,[ + HLLZ T,UPQUAN(U) + TLNE T,100 + JRST INTBAB ;WRITE IN RD ONLY +INTBAC: HLLZ T,UPC(U) ;SIMULATE SETUP OF OPC + LSH T,-5 + HRR T,UPC(U) + MOVEM T,UPOPC(U) ;FAULT STATUS + MOVSI T,1000 + IORM T,UPQUAN(U) ;BIT NOT SET BY XCTRI + MOVSI T,%SWINT + IORM T,USWST(U) ;PAGE FAULT RESULT OF INTERRUPT ATT + LPMRI UPGML(U) ;SET MPV FLAG, WILL CAUSE INT. LATER LPMR'S WON'T + ; CLEAR IT. + JRST SCHED6 ;"RUN" USER, TAKING PAGE FAULT IMMEDIATELY + +INTBAB: TLNE T,50 ;NO ACCESS OR W IN RWF + JRST INTBAC ;PAGING BOX BUG? IGNORE RD ONLY + JRST INTBAD ;REALLY IS READ-ONLY. +] ;KA10P +IFN KL10P,[ + SUBI T,UPGCP-UPGMP + LDB E,T + TRNE E,600000 + LSH E,-20 + CAIN E,2 ;RWF + JRST INTBAB + MOVS T,UPFW(U) + ANDI T,%PFCOD + CAIE T,%PFPNA + JRST INTBAD ;REAL VIOLATION +;DROPS THROUGH + ;DROPS IN +;KL10P ;PF OR RWF, TAKE THE FAULT, READ IN THE PAGE, THEN TRY TO INTERRUPT AGAIN + +INTBAB: MOVSI T,%SWINT + IORM T,USWST(U) ;PAGE FAULT RESULT OF INTERRUPT ATTEMPT + SETOM DLSRCH ;DON'T INTERRUPT AT INTBA1, SCHEDULE, TRY TO PCLSR + ; WITH WRONG PC + MOVEI T,INTBA1 + EXCH T,UPC(U) ;HACK USER'S PC + MOVEM T,EPDL3(U) + JRST SCHED6 ;RUN USER, RETURNING IMMEDIATELY TO INTBA1 + +INTBA1: CONO PI,PIOFF + SETZM DLSRCH + MOVEM U,PFAILU ;SIMULATE A PAGE FAULT ON THE INTERRUPT WORD + MOVE U,USER + MOVE U,EPDL3(U) + MOVEM U,PFOPC1 ;RESTORE USER'S PC + MOVNI U,2 + MOVEM U,PFAILF ;FLAG FAULT FROM INTPFL + MOVE U,PFAILU ;RESTORE U SO CLKSAV CAN RE-SAVE IT + CONO PI,CLKRQ ;TURN PI SYSTEM ON AND CAUSE CLOCK BREAK + JRST . ;TAKES A WHILE TO GO OFF +] ;KL10P +IFN KS10P,[ + MOVE T,EPTP7W + TLNE T,%PF2.8 ; Write in read only? + JRST INTBAD ; Yes: %PIB42 + MOVEM T,UPFW(U) ; No: Set up for a simulated fault + MOVSI T,%SWINT + IORM T,USWST(U) ; Signal fault as result of interrupt attempt + SETOM PFAILF ; Cause CLK level to go to PFLU2 at + ; first opportunity. + MOVEI T,CCLKRQ ; Make sure that happens real fast + EXCH T,UPC(U) ; by setting his PC thusly. + MOVEM T,EPTPFO ; Save old PC as location of fault. + JRST SCHED6 ; Go run this user. +] ;KS10P + +INTBAD: MOVEI A,%PIB42 ;TURN ON BAD PI LOC INT BIT + IORB A,PIRQC(U) ;GIVE USER INTERRUPT(MUST IORM TO AVOID TIMING ERR) + JRST SEAR2A ;RE-PERFORM ACTIONS FOR NON-ZERO PIRQC + ;WILL CAUSE AN INTERRUPT TO SUPERIOR + +;INTERRUPT ALL USERS THAT WANT IT +; C(A) IS BIT IN PIRQC TO TURN ON +DBGINT: MOVSI A,(%PIDBG) ;"SYS BEING DEBUGGED" INT +INTALL: MOVEI U,0 ;ENTRY INITIALIZE +INTA2: ADDI U,LUBLK ;ADVANCE TO NEXT BLOCK OF USER VARIABLES + CAML U,USRHI ;SKIP UNLESS AT END + POPJ P, ;THROUGH, RETURN + SKIPN UNAME(U) ;SKIP IF BLOCK IN USE + JRST INTA2 ;IDLE, IGNORE + LDB T,[410100,,USTP(U)] ;GET BUCSTP OF USERS STOP WORD + JUMPN T,INTA2 ;IF USER CONTROL STOPPED, JUMP TO IGNORE + MOVE B,MSKST(U) ;PICK UP INTERRUPT MASK + AND B,A ;MASK C(B) TO APPROPRIATE BIT + IORM B,PIRQC(U) ;GIVE INT TO USER + JRST INTA2 ;LOOP + +SUBTTL PCLSR ROUTINES + +; PUT PC OF USER WHOSE INDEX IS IN U IN USER MODE +; (CALL ONLY WITH CLOCK OFF OR CLOCK BREAK IN PROGRESS) +;SKIPS IF SUCCESSFUL, FAILS IF USER RUNNING IN EXEC CODE OR HAS TO BE FINALIZED +; +PCLSR: AOS NPCLSR + CAIG U,L + BUG ;PCLSR'ING NULL, SYS OR CORE JOB? + MOVEI T,L + IDIVM U,T + IMULI T,L + CAMN T,U ;IS U REALLY A MULTIPLE OF LUBLK? + SKIPN UNAME(U) ;SHOULD NOT HAPPEN TO NONEXTANT JOB + BUG + SKIPE USTP(U) + JRST POPJ1 ;USER STOPPED (MUST ALREADY BE IN USER MODE) + AOS NEPCLS + SKIPLE T,RPCL(U) + JRST PCLSR2 ;LOSER IS RPCLSR'ING SOMEONE +PCLSR3: MOVE T,SUEXIT(U) +IFE KA10P,SUB T,U + CAME T,[JRST 2,@XUUOH] + JRST PCLSR5 ;EXIT ALREADY CLOBBERED + MOVE T,UPC(U) ;PICK UP PROGRAM COUNTER (FLAGS IN L.H.) + TLNN T,%PCUSR ;SKIP IF USER MODE ON + JRST PCLSR8 ;JOB CURRENTLY IN EXEC MODE + SOS NEPCLS ;WAS WRONGLY AOS'ED + CLEARM FLSINS(U) ;IN CASE HE WAS WAITING FOR A PAGE OR CIRPSW + MOVE T,USWST(U) + TLNE T,%SWPGW + SOS NPGWTU + MOVSI T,%SWPGW+%SWRUN+%SWINT + ANDCAM T,USWST(U) + AOS (P) + POPJ P, + +PCLSR8: SKIPE FLSINS(U) ;SKIP IF UNBLOCKED + JRST PCLSR1 ;HUNG, TRY TO BACK UP TO UUO +PCLSR4: MOVE T,[JRST ONEFLS] + MOVEM T,SUEXIT(U) ;MUNG EXIT OF UUO, COME BACK LATER +PCLSRF: AOS NFPCLS + POPJ P, + +PCLSR2: SETZM RPCL(U) ;CLEAR OUT POINTERS IN BOTH DIRECTIONS + SETZM RPCL(T) + JRST PCLSR3 + +PCLSR5: SKIPN FLSINS(U) + JRST PCLSRF ;NOT HUNG, LET RUN TO COMPLETION +IFN KA10P,[ ;HUNG, UNCLOBBER EXIT AND BACK UP TO UUO + CAME T,[JRST ONEPROC] ;SKIP IF ONE PROCEEDING A SYS CALL + JRST PCLSR6 + MOVSI T,%PC1PR + IORM T,SUUOH(U) ;RESET SINGLE INSTRUCTION PROCEED +PCLSR6:] ;KA10P +IFN KS10P,[ ;HUNG, UNCLOBBER EXIT AND BACK UP TO UUO + CAME T,[JRST ONEPR4] ;SKIP IF ONE PROCEEDING A SYS CALL + JRST PCLSR6 + MOVSI T,OIPBIT + IORM T,XUUOH(U) ;RESET SINGLE INSTRUCTION PROCEED +PCLSR6:] ;KS10P + MOVE T,UPC(U) + TLNE T,%PCUSR + BUG +IFN KA10P, MOVE T,[JRST 2,@UUOH] +IFE KA10P,[ + MOVSI T,(JRST 2,@) + HRRI T,UUOH +] ;IFE KA10P + MOVEM T,SUEXIT(U) ;UNCLOBBER EXIT +PCLSR1: HLRZ T,LSPCL(U) ;SAVE LAST TWO DISTINCT LOCS PCLSR'ED FROM + CAIN T,@UPC(U) + JRST PCLSR9 + HRL T,UPC(U) + MOVEM T,LSPCL(U) +PCLSR9: SOS T,SUUOH(U) ;GET USER LOCATION OF HIS CURRENT UUO +UFL5: +IFN KL10P,[ + TLC T,%PS1PR-%PSINH + TLCN T,%PS1PR-%PSINH + TLO T,%PSINH ;ONE PROCEEDING AND INSTR NOT COMPLETE +] ;KL10P + MOVEM T,UPC(U) ;SET USERS PROGRAM COUNTER +IFE KA10P,[ + MOVSI T,701100 ;RESTORE PAGE-CONTEXT TO USER MODE + HLLM T,CLCX(U) +] ;IFE KA10P + CLEARM UMAPS(U) ;RESTORE TO NORMAL MAP + SETZM FLSINS(U) ;CLEAR OUT ANY BLOCKING CONDITION + MOVE T,USWST(U) + TLNE T,%SWPGW + SOS NPGWTU + MOVSI T,%SWPGW+%SWRUN+%SWPCL+%SWINT ;NOT BLOCKED ON PAGE, NOT UNBLOCKED SWAPOUT, + ANDCAM T,USWST(U) ; NOT INTERRUPT PAGE, NOT SWAPPED OUT WHILE BLOCKED + SKIPE T,LSWPR(U) + JRST LSWZAP ;REQUIRED TO UNLOCK SWITCHES +PCLSR7: +IFE KA10P,[ + MOVEI T,UUOACS(U) ;IF JOB U'S ACS ARE IN HARDWARE AC BLOCK 1, + CAMN T,AC1PTR ;COPY THEM INTO UUOACS WHERE THEY BELONG. + XCTR XBR,[BLT T,UUOACS+17(U)] +] ;IFE KA10P + MOVEI T,AC0S(U) + HRLI T,UUOACS(U) + BLT T,AC17S(U) + JRST POPJ1 ;EXIT AFTER BACKING UP TO UUO + ; +; AOS USTP OF USER IN A +; +NJRPCL: CAIE A,-1 ;ENTRY TO IGNORE IF NULL JOB +RPCLSR: CAMN A,USER ;NORMAL ENTRY + POPJ P, ;TRYING TO RPCLSR SELF OR NULL JOB + PCLT + PUSH P,U ;SAVE U + MOVE U,A ;GET INDEX OF RPCLSRED JOB IN U + MOVE A,USER ;GET RPCLSRING USER INDEX IN A + CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + PUSHJ P,PCLSR ;PUT USER IN USER MODE + JRST RPCLOS ;JUMP IF CAN'T DO IT RIGHT NOW + AOS USTP(U) ;WIN,STOP USER + CONO PI,CLKON ;RE-ENABLE CLOCK BREAKS +RPCLS1: MOVE A,U ;RESTORE A + POP P,U ;RESTORE U + POPJ P, +; +RPCLOS: SKIPE RPCL(U) ;SKIP IF ZERO RPCL FOR USER BEING RPCLSRED + JRST RPCLS2 ;SOMEONE GOT THERE FIRST + SKIPE RPCL(A) ;SKIP IF ZERO RPCL FOR RPCSRING USER + JRST UDELAY ;YOU ARE BEING RPCLSR'ED, SURRENDER + HRROM A,RPCL(U) ;SET UP RPCL IN VARS OF RPCLSRED USER + HRRM U,RPCL(A) ;" OF RPCLSRING USER + PCLT + SKIPE RPCL(A) ;WILL NOT SKIP AT FIRST + PUSHJ P,UFLS ;WAIT FOR PERSON BEING RPCLSRED TO GET TO ONEFL2 + JRST RPCLS1 +; +RPCLS2: MOVE A,U ;RESTORE A AND U + POP P,U + PCLT + SKIPE RPCL(A) ;WAIT FOR OTHER GUY TO WIN + PUSHJ P,UFLS + JRST RPCLSR ;THEN TRY AGAIN + +; +; UNDO AN RPCLSR +; +NJUPCL: CAIE A,-1 ;ENTRY TO IGNORE IF NULL JOB +UPCLSR: CAMN A,USER ;REGULAR ENTRY + POPJ P, ;TRYING TO UPCLSR SELF OR NULL JOB + SOSGE USTP(A) + BUG + POPJ P, + +IFN KA10P,[ +; +; RETURN FROM SYSTEM CALL IN ONE PROCEED MODE +; +ONEPROC:CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + MOVE U,USER ;BE SURE U HAS RUNNING USER INDEX IN IT + MOVEI T,%PI1PR + IORM T,PIRQC(U) ;GIVE USER INTERRUPT + JRST ONEPR2 +] + +SUBTTL KS-10 ONE-PROCEED + +IFN KS10P,[ +ONEPRO: SYSCTX ;SWITCH TO SYSTEM AC BLOCK + SKIPGE U,USER + BUG AWFUL,[ONE-PROCEED IN NULL JOB] + MOVE T,1PROPC(U) ;PC OF NEXT INSTRUCTION TO EXECUTE + TLNE T,%PSUSR ;NORMALLY USER MODE IS EXPECTED + JRST ONEPR3 + HRRZ T,T ;SEE IF IT'S FIRST INSTRUCTION OF EXEC ENTRY + CAIE T,UUOH0 + CAIN T,MUUOTR + SKIPA TT,[JRST ONEPR4] + BUG AWFUL,[ONE-PROCEED IN EXEC MODE],OCT,1PROPC(U) + MOVEM TT,UEXIT ;CLOBBER EXIT TO RUN SYS CALL TO COMPLETION + CAIE T,UUOH0 ;AND RESUME PROCESSING UUO + JRST [ USRCTX + JRST MUUOTR ] + USRCTX + JRST UUOH0 + +ONEPR3: MOVEM T,UUOH ;PUT USER PC WHERE ONEFLS WANTS IT +ONEPR4: SYSCTX ;COME HERE WHEN ONE-PROC'D UUO FINISHES + MOVE U,USER ;BE SURE U HAS RUNNING USER INDEX IN IT + MOVEI T,%PI1PR + IORM T,PIRQC(U) ;GIVE USER INTERRUPT + JRST ONEFLS +];KS10P + +SUBTTL USER START ROUTINES +; +; CALLED EVERY SLOW CLOCK TICK WHEN TTY WANTING TOP PROCEDURE LOADED +; +USTART: PUSH P,U +USTRT1: SKIPL T,@UTTYO ;GET TTY TO BE STARTED + JRST [ MOVE U,MMPFR ;WHEN STARTING A HACTRN, MAKE SURE CORE IS AVAILABLE + CAIGE U,100 + JRST USTRTL ;IT'S NOT, SAY SYSTEM FULL + JRST .+2 ] ;T HAS INITIAL TTYTBL + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;NOT A REAL TTY, INITIALIZE TTYTBL TO NO TTY + PUSHJ P,USTRA ;CREATE NEW USER SLOT ENTRY + JRST USTSC1 ;LOSE, HAVE TO WAIT + SKIPGE T,@UTTYO ;SKIP IF REALLY A TTY + JRST USTRTS ;DONT LOAD A HACTRN + MOVE T,[SIXBIT /HACTRN/] ;LOAD HACKTRN +USTRT2: MOVEM T,JNAME(U) ;SET JOB NAME + MOVEM T,XJNAME(U) + HRLZI T,%PCUSR + HRRI T,1 + MOVEM T,UPC(U) + MOVEI T,AC0S(U) + HRLI T,NUSTCD + BLT T,AC17S(U) + MOVE T,JNAME(U) + MOVEM T,AC0S+11(U) + SETZM @UTMPTR(U) ;GIVE TEMPORARY HIGH PRIORITY + SETZM USTP(U) ;START UP +USTSC2: AOS T,UTTYO ;AOS RING BUFF + CAIL T,UTTYS+MXCZS + MOVEI T,UTTYS + MOVEM T,UTTYO + SOSE UTTYCT + JRST USTRT1 ;MORE JOBS TO SET UP + JRST POPUJ + +USTRTS: MOVEM U,1(T) ;STORE USER'S INDEX IN SECOND WORD + MOVE T,(T) ;GET JNAME FROM FIRST WORD (POINTED TO BY RH OF @UTTYO) +IFN DEMON,[ + CAME T,[SIXBIT /LDRDEM/] + CAMN T,[SIXBIT /UNSPOO/] + AOS UTMPTR(U) ;LOADER, UNSPOOLER -> SYSTEM TREE +] + JRST USTRT2 + +USTSC1: MOVE U,USRHI ;IF A USER IS ^Z'ING AND THERE IS NO POSSIBILITY + SKIPL T,@UTTYO ;OF GETTING MORE JOB SLOTS, + CAIGE U,LUBLK*MAXJ + JRST POPUJ +USTRTL: MOVSI U,%TANJS ;THEN MARK THE TTY AS IN NEED OF A "SYSTEM FULL" MESSAGE + IORM U,TTYSTA(T) + MOVEI U,SCRCFM ;AND WAKE UP THE SYS JOB. + IORM U,SUPCOR + JRST USTSC2 ;REMOVE THIS TTY FROM LIST OF THOSE NEEDING A ^Z. + +;GOBBLE NEW USER SLOT, RESET VARIABLES (SKIPS IF IT WINS) +;RETURNS INDEX IN U. IF FAILS, CLOBBERS U! +USTRA: MOVEI U,0 +USTR3: CAML U,USRHI + JRST USTR1 ;ASSIGN MORE CORE TO USER STORAGE + SKIPN UNAME(U) + JRST USTR2 ;HAVE FOUND FREE USER SLOT (IN U) + ADDI U,LUBLK + JRST USTR3 + +USTR1: SKIPGE SJCFF + POPJ P, ;SYSTEM JOB FLUSHING CORE, WAIT UNTIL IT STABILIZES + MOVEI U,LUBLK ;MOVE UP USRHI IF SYS HAS ENOUGH CORE + ADD U,USRHI + PUSH P,T + MOVE T,HUSRAD ;LENGTH OF SYS + CAIGE T,USRSTG(U) + JRST MORCOR ;SYS NEEDS MORE CORE FOR USER VARIABLES + POP P,T +USSINI: SETOM USTP-LUBLK(U) ;SYS INITIALIZATION ENTRY + EXCH U,USRHI +USTR2: PUSHJ P,USTR4 ;RESET USER VARIABLES + MOVEI T,SIOCHN-1(U) + MOVEM T,SIOCP(U) + CLEARM IOCHNM(U) + HRLI T,IOCHNM(U) + HRRI T,IOCHNM+1(U) + BLT T,IOCHNM+17(U) ;CLEAR ALL I/O CHANNELS +USRST4: HRLI T,AC0S(U) + HRRI T,AC0S+1(U) + SETZM AC0S(U) + BLT T,AC17S(U) ;CLEAR AC'S & RETURN HAPPY + JRST POPJ1 + +MORCOR: SUB P,[1,,1] + MOVSI T,SCLDEC + ANDCAM T,SUPCOR ;CLEAR ANY SYS CORE DECREASE REQ + MOVSI T,SCLEX + JRST SUPSET ;REQUEST MORE CORE FROM SYS JOB + ; +; INITIALIZE A SET OF USER VARIABLES +; T HAS INITIAL TTYTBL, POSITIVE IT IS TTY # ELSE NO TTY +USTR4: MOVEM T,TTYTBL(U) + JUMPL T,USTR4B + PUSH P,U + HRRM U,TTYSTS(T) ;TELL TTY IT NOW BELONGS TO NEW JOB, + MOVSI U,%TSCNS ;AND IS NOW A CONSOLE. + IORM U,TTYSTS(T) + MOVSI U,%TSFRE + ANDCAM U,TTYSTS(T) ;AND IS NO LONGER FREE + MOVSI U,%TACFM+%TACTZ + ANDCAM U,TTYSTA(T) ;AND WILL NEED CONSOLE FREE MESSAGE + POP P,U + ADDI T,USRRCE +USTR4A: MOVEM T,UTMPTR(U) + HRROI T,'000 + MOVEM T,UNAME(U) + PUSH P,U + MOVE T,U + IDIVI T,LUBLK + POP P,U + DPB T,[000300,,UNAME(U)] + LSH T,-3 + DPB T,[060300,,UNAME(U)] + LSH T,-3 + DPB T,[140300,,UNAME(U)] + MOVE T,UNAME(U) + MOVEM T,XUNAME(U) + MOVEM T,HSNAME(U) + MOVE T,JNAME(U) + MOVEM T,XJNAME(U) + MOVEI T,(U) + HRLI T,%TSCNS + MOVEM T,TTSTSV+2(U) + SETZM USWST(U) +IFN SWPWSP,[ + SETZM UWRKST(U) + SETZM USVWRK(U) + MOVE T,TIME + ADDI T,2*30. ;PROTECT FROM SWAPOUT FOR 2 SECONDS (RANDOMLY) + MOVEM T,USWTIM(U) +];SWPWSP + SETZM NSWPGS(U) + SETZM NMPGS(U) + SETOM JBI(U) ;NOT JOB DEVICE HANDLER (NOT YET, ANYWAY) + SETZM OPTION(U) + SETZM STTYOP(U) + SETOM TRNLST(U) ;INIT TRANSL LISTS TO NIL + SETOM TRNLS1(U) + SETZM HUSRAD(U) + JUMPE U,.+5 ;SYSTEM JOB DOESN'T HAVE A MAP + CLEARM UPGMP(U) + MOVSI T,UPGMP(U) + HRRI T,UPGMP+1(U) + BLT T,UPGCP+NUVPG/2-1(U) + MOVSI T,(MOVEM U,) + HRRI T,AC17S(U) + MOVEM T,SCLUSV(U) +IFE KA10P,[ + MOVSI T,(DATAI PAG,) + HRRI T,CLCX(U) + MOVEM T,SCLCXS(U) + MOVEI T,USRSTG(U) +IFN KL10P, LSH T,-9 + HRLI T,701100 + MOVEM T,CLCX(U) + MOVSI T,(JRST 2,@) + HRRI T,XUUOH(U) + MOVEM T,SUEXIT(U) + MOVSI T,(CAI) ;INITIALLY IGNORE TRAPS 1 AND 2 + MOVEM T,TR1INS(U) + MOVEM T,TR2INS(U) +IFE KS10P,MOVEI T,%PI1PR ;TRAP 3 IS IGNORED TOO ON KS + MOVEM T,TR3INS(U) ;TRAP 3 GIVES ONE-PROCEED INTERRUPT ON KL +] ;IFE KA10P +IFN KL10P,[ + SETZM ULSPBR(U) + MOVSI T,MUUOKN ;UUO NEW PC'S ARE SAME AS SYS JOB'S, + HRRI T,MUUOKN(U) ; EXCEPT THAT UUO IN EXEC MODE IS AN ERROR + BLT T,MUUOPT(U) + MOVEI T,MUUOEX + HRRM T,MUUOKN(U) +] ;KL10P +IFN KS10P,[ + MOVE T,[%PSPCU,,MUUOEX] + MOVEM T,MUUOKN(U) ; UUO in Exec mode is an error + MOVEM T,MUUOKT(U) ; (either case) + HRRI T,UUOH0 + MOVEM T,MUUOCN(U) ; Normal UUO + HRRI T,MUUOTR + MOVEM T,MUUOCT(U) ; UUO as trap instruction + HRRI T,ONEPRO + MOVEM T,1PRNPC(U) ; One-proceed jumps to ONEPRO +] ;KS10P +IFN KA10P,[ + MOVE T,[JRST 2,@UUOH] + MOVEM T,SUEXIT(U) +] ;KA10P + MOVSI T,BUSRC + MOVEM T,USTP(U) + SETOM SUPPRO(U) + SETZM UCLBLK(U) + SETOM UCLBLK+1(U) + MOVE T,[JRST UREALB] + MOVEM T,UCLBLK+2(U) + CLEARM UPGML(U) ;CLEAR USER PG MAP VARIABS + MOVEI T,UPGML+1(U) + HRLI T,-1(T) + BLT T,UPGMLE(U) +IFN KA10P,[ + MOVSI T,1+EXPGNG ;DONT ENABLE QUAN COUNTER FOR NOW (BUT SET + ; EXEC PAGING) + MOVEM T,UPQUAN(U) + MOVE T,EXECMP + MOVEM T,UPDBR3(U) ;SET UP EXEC DBR + MOVSI T,IFN MCOND DM,[1040] .ELSE [0] ;ON DM, B+C MEMORIES DON'T WORK + MOVEM T,UPACP(U) ;SET UP B+C MEMORY PTRS +] ;KA10P +IFN KS10P, SETZM UPQUAN(U) ; Clear quantum counter. + +;DROPS THROUGH + +;DROPS THROUGH, AND .RESET OF USR DEVICE COMES HERE. +USRST2: MOVE T,UNAME(U) + MOVEM T,USYSNM(U) ;CLOCK MUST BE OFF OR PI IN PROG ON 7 + MOVE T,TIME ;DON'T SWAP JOB OUT RIGHT AWAY + MOVEM T,LUBTM(U) + PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,E + MOVEI C,UCLBLK(U) + SKIPL 1(C) + JSP E,CLQCLR + SETOM SERVER(U) + SETZM PAGAHD(U) + SETZM PAGRAN(U) + SETZM UWHO1(U) + SETZM UWHO2(U) + SETZM UWHO3(U) +IFN N11TYS,[ + SETZM NVDBA(U) ;0 VIDEO BUFFERS ASSIGNED BY JOB. + SETOM TVCREG(U) + SKIPL T,TTYTBL(U) + PUSHJ P,USTTV0 + SETOM TVVBN(U) +USTTV1: ];N11TYS + POP P,E + POP P,C + POP P,B + POP P,A + SETZM URTIME(U) + SETZM UTIME(U) + SETOM RTIMER(U) + MOVSI T,%PCUSR + MOVEM T,UPC(U) + HRLI T,-LUPDL + HRRI T,UPDL-1(U) + MOVEM T,USRPDL(U) + SETZM MSKST(U) + SETZM MSKST2(U) + MOVE T,[20,,40] + MOVEM T,40ADDR(U) + MOVEI T,APRCHN+440 + MOVEM T,APRC(U) + SETZM USTYN(U) + SETZM PIRQC(U) + SETZM IFPIR(U) + SETZM IDF1(U) + SETZM IDF2(U) + SETOM PICLR(U) + SETZM FLSINS(U) + SETZM UTRNTM(U) +IFN KL10P,[ + SETZM EBOXCT(U) + SETZM EBOXCT+1(U) + SETZM MBOXCT(U) + SETZM MBOXCT+1(U) +] + SETZM USIPRQ(U) + SETZM TRUNTM(U) + SETZM TSIPRQ(U) +IFE SWPWSP,[ + SETZM LTRNTM(U) + SETZM LSIPRQ(U) + SETZM UPGSEC(U) +];SWPWSP + SETZM IOTLSR(U) + MOVSI T,%OPOJB ;USR RESET DOESN'T CLEAR OJB OPTION BIT + ANDM T,OPTION(U) + SETOM CORRQ(U) + POPJ P, + +USTR4B: MOVEI T,USRRCE+NCT + JRST USTR4A + +IFN N11TYS,[ +;SET UP THE BLINKER FOR THE JOB IN U. +USTTV0: SKIPN TEN11F + SKIPL TT11P + POPJ P, + HRL T,TTYTYP(T) + TLNN T,%TY11T + POPJ P, ;NOT A TV + MOVE A,TT11HD ;11 HEADER ADR + ADDI A,-NF11TY(T) + LDB B,[141000,,1(A)] ;VIDEO BUFFER # + TRO B,17_8 ;CSET ALU FCTN + LSH B,4+16. ;INTO POSITION FOR MOVEMING INTO CONSOLE REG + MOVEM B,TVVBN(U) + JRST POPJ1 +] ;END IFN N11TYS + +; USER START CODE + +NUSTCD: JFCL ;0 + .OPEN 1,7 + .LOGOUT ;2 + .CALL 12 + .LOGOUT + .IOT 1,2 + JRST (2) + .UII,,(SIXBIT/SYS/) ;7 + SIXBIT /ATSIGN/ + SIXBIT /HACTRN/ + SETZ ;12 + SIXBIT /LOAD/ + 16 + SETZ 17 + -1 ;16 + 1 ;17 + +USTCDR: SYSCTX ;GOT HERE FROM ULEAVE WHICH SELECTED THE USER ACS, + MOVE U,USER ; SELECT SYSTEM ACS INSTEAD. + MOVEI A,USTCDR+1 ;COME BACK HERE IN CASE OF PCLSR + MOVEM A,UUOH + MOVE P,USRPDL(U) + PUSHJ P,UBLAM + MOVE U,USER + MOVSI T,NUSTCD + XCTR XBW,[BLT T,17] + MOVE T,JNAME(U) + UMOVEM T,11 + MOVE T,[%PCUSR,,1] + MOVEM T,UUOH + JRST URET + +SUBTTL USER KILL ROUTINES + +; +; CLOSE ALL DEVICES AND INFERIOR PROCEDURES OF A JOB (INDEX IN U) +; +IODCL: MOVNI I,1 ;SET TO STOP + PUSHJ P,IODCL3 ;STOP ALL INFERIOR JOBS (RECURSIVE) + MOVEI I,0 ;THEN KILL. +IODCLA: PUSH P,I + MOVE A,OPTION(U) + TLNE A,%OPLOK ;IF USER HAS ENABLED THE SWITCH-UNLOCK FEATURE, + PUSHJ P,IODCSW ;UNLOCK HIS LOCKED SWITCHES. +IFN 340P\E.SP, PUSHJ P,ADCLOSE ;FLUSH DISPLAY +IFN IMXP, PUSHJ P,POTCLS ;DISCONNECT HIS POTS +IFN VIDP,[ + CAMN U,SCNUSR + PUSHJ P,SCNSTP ;KILL SCANNER IF HIS +] +IFN ARMP, PUSHJ P,AARMOFF ;FLUSH ARM +IFN DEMON, PUSHJ P,DEMOUT ;FLUSH EXISTANCE (CURRENT OR FORMER) AS DAEMON. +IFN N11TYS,[ + SKIPE NVDBA(U) + PUSHJ P,VBDFLS ;DEASSIGN ALL VIDEO BUFFERS. +] +IFN KL10P,[ + CAMN U,MTRUSR ;DEASSIGN THE PERFORMANCE COUNTER + PUSHJ P,PRFOFF +];KL10P + PUSHJ P,CLQDEL ;RELEASE AND STOP CLOCK QUEUE BLOCK + UCLBLK(U) + HRRZ A,UREALT + CAMN A,U + SETOM UREALT ;UN REAL TIME + CAMN U,UMASTER ;UNMASTER + SETOM UMASTER + PUSHJ P,AIOPDL ;POP UP ALL OF IO PDL (CLOSING CHNLS POPPED INTO) + MOVEI R,IOCHNM(U) +IODCL1: PUSHJ P,CCLOSE ;CLOSE ALL CHANNELS + CAIGE R,IOCHNM+NIOCHN-1(U) + AOJA R,IODCL1 + PUSH P,U + SKIPGE T,JBI(U) ;IF THIS JOB IS A JOB-DEVICE, + JRST IODCL2 + HRROS JBCJUI(T) ;TELL THE JOB CHANNEL THAT THE HANDLER IS GONE. + CONO PI,CLKOFF + SKIPGE JBCG(T) ;IF OUR CREATOR STILL HAS A JOB CHANNEL, + JRST IODCL6 + MOVE A,JBCUI(T) ;FLUSH THE CREATOR'S JOB CHANNELS, + CONO PI,CLKON + PUSHJ P,RPCLSR ;STOPPING THE CREATOR IN CASE HE'S USING THEM NOW. + MOVE T,JBI(U) ;RPCLSR CLOBBERS T. + MOVSI C,%CLSJ + PUSHJ P,CHSCAA + PUSHJ P,[HRRZ B,(R) + TDNN C,CLSTB(B) + POPJ P, + HLRZ B,(R) + CAMN B,T + SETZM (R) + POPJ P,] + PUSHJ P,UPCLSR ;ALLOW THE CREATOR TO CONTINUE AND GET IOC ERROR OR RETRY OPEN +IODCL6: CONO PI,CLKON + SETOM JBCUI(T) ;FLUSH THE JOB-DEVICE SLOT. + SETOM JBI(U) ;SAY THIS JOB NO LONGER A JOB-DEVICE. + JRST IODCL2 + +IODCL3: PUSH P,I ;I=0 KILL I=-1 STOP I=1 JUST CLOSE CHANNELS. + PUSH P,U +IODCL2: MOVEI A,0 +IODCL4: HRRZ E,SUPPRO(A) + SKIPE UNAME(A) ;SKIP IF VARIABLES BLOCK IDLE + CAIE E,(U) ;SKIP ONLY IF IT IS A DIRECT INF. + JRST IODCL5 ;TRY NEXT SET OF VARS + PUSH P,A + MOVE U,A + PUSHJ P,1USTOP ;STOP (WITH BUSRC BIT) + MOVE R,P + MOVE P,USRPDL(U) + PUSH P,R + SKIPGE I,-2(R) + JRST IODCL8 ;STOP + PUSHJ P,IODCLA ;KILL OR CLOSE CHNLS, RECURSE +IODCL9: MOVE P,(P) + SKIPE -2(P) ;KILLING? + JRST IODCL7 ;JUST CLOSING CHNLS. + MOVE A,U ;KILLING; WAIT TILL NO OTHER JOB + PUSHJ P,AUCL3 ;IS LOOKING AT THE ONE THAT WE'RE KILLING. + PUSHJ P,UBLST2 ;FLUSH CORE + SETZ R, + PUSHJ P,ZUSLOG ;ACCOUNT FOR USAGE THEN FLUSH LAST VESTIGES + CONO PI,CLKON +IODCL7: POP P,A + HRRZ U,(P) +IODCL5: ADDI A,LUBLK + CAMGE A,USRHI + JRST IODCL4 ;LOOP FOR ALL SETS OF USER VARIABLES + POP P,U + SUB P,[1,,1] + POPJ P, + +IODCL8: PUSHJ P,IODCL3 + JRST IODCL9 + +;SYSTEM CALL UNLOCK. 1 ARG, A JOB SPEC. +;THAT JOB'S LOCKS ARE ALL UNLOCKED. +NUNLOCK: + MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC. + JRST NUNLO1 ;WE'RE CERTAINLY ALLOWED TO WRITE THIS JOB. + JUMPE U,NUNLO1 ;SYSTEM JOB CAN DO IT TO ANYBODY + JSP T,NCORWR ;NOT SURE, SO CHECK. + JRST OPNL31 ;NO, NOT ALLOWED. +NUNLO1: +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 +];PDP6P + ;THE CALL IS ALLOWED, SO UNLOCK THAT JOB'S LOCKS + CAMN J,USER + JRST NUNLO2 + MOVE A,J ; If not self, + PUSHJ P,RPCLSR ; assure a User mode PC + PUSHJ P,SOSSET + USTP(A) + JRST NUNLO3 + +NUNLO2: MOVE A,UUOH ; If we are asked to unlock + SUBI A,1 ; our own locks, put our PC in + MOVEM A,SRN3(U) ; SRN3 where IODCSW will look for it +NUNLO3: MOVE U,J + MOVE A,OPTION(U) + TLNE A,%OPLOK ; Provided it is using locks at all... + PUSHJ P,IODCSW + CAME U,USER + PUSHJ P,LSWPOP ; USTP + JRST LSWPJ1 ; DIELOK + ; Returns with U clobbered, which seems to be OK for .CALL's? + + +;CALL HERE TO UNLOCK THE SWITCHES A JOB HAS LOCKED (USER IDX IN U). +;LOCATION 43 (ACTUALLY, 3+C(40ADDR)) HAS THE LIST POINTER. 0 IS NIL. +;ANYTHING ELSE POINTS TO 2-WORD BLOCK; THE 1ST WORD IS THE SWITCH OR THE +;ADDRESS OF THE SWITCH. THE RH OF THE SECOND IS THE CDR OF THE LIST. +;THE LH OF THE SECOND IS THE UNLOCK INTRUCTION. THE INDEX FIELD IS IGNORED, +;ONE LEVEL OF INDIRECTION IS PERMITTED, AND THE INSN MUST BE EITHER +;AOS OR SOS WITH 0 IN AC FLD, A LOGICAL INSTRUCTION (TOP 3 BITS = 4), +;A HALFWORD INSTRUCTION, OR A MOVE,MOVN,MOVS,MOVN,ADD OR SUB SERIES INSN, +;OR 0 WHICH MEANS SETOM. ONLY INSNS THAT MODIFY MEMORY ARE USEFUL. +;44 IS AN AOBJN POINTER TO THE CRITICAL RTNS TABLE, OF 2-WORDS ENTRIES. +;THE 1ST WORD EACH IS ,,+1. +;THE SECOND IS THE UNLOCK INSTRUCTION, WITH THE ADDRESS OF THE SWITCH +;IN THE RH (AGAIN, 1 LEVEL OF INDIRECTION IS PERMITTED). +;IF THE PC IS IN THAT RANGE, THE UNLOCK INSN IS EXECUTED. +;43 AND 44 ARE UPDATED DURING PROCESSING TO PREVENT PCLSR LOSSAGE. +;SEE .INFO.;ITS LOCKS + + +;MACRO TO DO XCTR, OR POPJ IF THAT WOULD CAUSE INTERRUPT. +DEFINE XCTRIJ + JSP TT,IODCXC + XCTR!TERMIN + +; IODCSW: Unlock locks for user in U +; User should be stopped so that he is in user mode. +; The only exception is if we are unlocking the locks of the running job, +; in which case the contents of SRN3 will be used as our PC. +; Clobbers just about everything except U. +IODCSW: PUSH P,U + PUSHJ P,IODCS0 ; Do actual work, if any... + MOVE U,USER ; But be sure to always + PUSHJ P,MPLDZ ; restore normal page map of running user. + JRST POPUJ ; And U + +IODCS0: HRRZ J,U + MOVE U,USER ;SET UP MAP TO USER BEING HACKED (IDX IN J). + PUSHJ P,MPLDJ ;LH(J) CLOBBERED, RH SAVED. + HRRZ U,J ;U HAS WHAT IT HAD AT CALL (USR BEING HACKED). + MOVEI C,1000 ;COUNT LENGTH OF LIST SO CIRCULAR LISTS DON'T HANG US UP. + HRRZ E,40ADDR(U) + XCTRIJ XRW,[MOVES B,3(E)] ;GET HIS "43" (AND MAKE SURE IT'S WRITABLE) +IODCS1: JUMPE B,IODCS2 ;REACHED END OF LOCKED SWITCH LIST, MAYBE? + XCTRIJ XR,[HLL B,1(B)] ;MERGE LOCK INSN WITH ADDR OF SWITCH. + PUSHJ P,IODCDO ;EXECUTE THE UNLOCK INSN + POPJ P, ;IODCDO DETECTED MPV OR PUR INTERRUPT. + XCTR XR,[HRRZ B,1(B)] ;REPLACE LIST BY ITS CDR. + UMOVEM B,3(E) + SOJG C,IODCS1 + +IODCS2: XCTRIJ XRW,[MOVES E,4(E)] ;GET JOB'S "44", AND MAKE SURE IT'S WRITEABLE. + HRRZ C,UPC(U) ;GET ITS PC, FOR COMPARISON. + CAMN U,USER ; Except if this is us, + HRRZ C,SRN3(U) ; then unlock PC is in SRN3 + JUMPGE E,CPOPJ ;THERE ARE NO PROTECTED RANGES => DONE. +IODCS3: XCTRIJ XR,[MOVS B,(E)] ;GET BOUNDS OF NEXT PROTECTED RANGE. + CAIGE C,(B) ;IS PC ABOVE LOWER BOUND? + JRST IODCS4 + MOVSS B + CAIL C,(B) ;IS IT BELOW UPPER? + JRST IODCS4 + XCTRIJ XR,[MOVE B,1(E)] ;PC IS IN THIS RANGE; GET UNLOCK INSN + PUSHJ P,IODCDO ;EXECUTE IT + POPJ P, ;NO SKIP => MPV OR PUR INTERRUPT DETECTED. +IODCS4: ADD E,[2,,2] ;CHECK ALL ENTRIES IN CRITICAL RTN TABLE, 1 BY 1. + HRRZ B,40ADDR(U) ;UPDATE 44 SO ENTRIES ALREADY PROCESSED ARE + UMOVEM E,4(B) ;ACTUALLY IN THE TABLE. THIS IS IN CASE PCLSR. + JUMPL E,IODCS3 + POPJ P, + +;PRECEDE AN XCTR WITH JSP TT,IODCXC TO POPJ IF THE XCTR WOULD +;CAUSE AN INTERRUPT (MPV OR PUR). CLOBBERS A,T,Q. +IODCXC: MOVEI A,@(TT) ;GET EFFECTIVE ADDR OF XCTR. + MOVEI A,@(A) ;GET EFFECTIVE ADDR OF XCTR'ED INSN. + LSH A,-10. ;GET PAGE # BEING REFERENCED. + PUSHJ P,UPLC ;SET T = B.P. TO PAGE MAP HALFWORD. CLOBBERS Q. + LDB T,T + TRNE T,600000 ;IF PAGE IS SWAPPED IN, PUT ACCESS BITS IN + LSH T,-20 ;SAME PLACE THEY ARE WHEN SWAPPED OUT (LOW 2 BITS). +;FOLLOWING CODE COMMENTED OUT BECAUSE IT DOESN'T WORK ON THE KL10 XCTR +; TRNE T,2 ;CHANGE CODE 2 (READ-WRITE, NOT WRITTEN) TO 3 (READ-WRITE). +; IORI T,1 +; LSH T,27 ;PUT ACCESS CODE IN AC FIELD, AND TEST +; ANDCA T,(TT) ;AGAINST WHAT THE XCTR WILL TRY TO DO. +; TLNN T,(0 3,) ;ALL DESIRED ACCESS AVAILABLE => +; JRST (TT) ;WE WIN. +; POPJ P, ;ELSE QUIT OUT OF CALLING ROUTINE. +; +;FOLLOWING CODE INSERTED INSTEAD. THIS RELIES ON THE FACT +;THAT ONLY THE FOLLOWING INSTRUCTIONS ARE XCTRIJ'ED: +; BOOLE,HWT,MOVXX,ADDX,SUBX,AOSX,SOSX + MOVE A,@(TT) ;GET INSTRUCTION XCTR'ED + TLC A,300000 + TLCE A,300000 ;SKIP IF AOS OR SOS + TLNE A,002000 ;SKIP IF DOESN'T WRITE IN MEMORY + TRNE T,2 ;INSTRUCTION WRITES, SKIP IF RW OR RWF ACCESS NOT PRESENT + TRNN T,3 ;INSTRUCTION READS, SKIP IF ANY ACCESS PRESENT + POPJ P, ;INSUFFICIENT ACCESS, QUIT OUT OF CALLING ROUTINE + JRST (TT) ;WINNING, GO DO THE XCTR + +;PUSHJ P,IODCDO WITH INSN IN B TO XCTRIJ IT, CHECKING FOR LEGALITY +;AND PERFORMING ONE LEVEL OF INDIRECTION IF THE @ BIT IS SET. +;(WE CAN'T AFFORD AN INFINITE LOOP WHILE KILLING A JOB EVEN IF IT IS +;INTERRUPTABLE) +;INDEX FIELD IS IGNORED. IF THE OPCODE IS 0, SETOM IS USED INSTEAD. +;SKIPS IF INSN IS LEGAL AND DOESN'T CAUSE MPV OR PUR INTERRUPT. +;CLOBBERS A,D,J,T,TT,Q +IODCDO: MOVE J,B ;B IS NOT CLOBBERED. + TLZN J,(@) + JRST IODCD1 + XCTRIJ XR,[HRR J,(J)] ;INDIRECTION IS WANTED; DO IT. +IODCD1: TLNN J,-1 ;IF LH IS 0, REPLACE BY (SETOM) + HRLI J,(SETOM) + LDB A,[271500,,J] + CAIE A,AOS_-27 ;AOS AND SOS ARE LEGAL WITH 0 IN AC FIELD. + CAIN A,SOS_-27 + JRST IODCD2 + LDB A,[410300,,J] + CAIE A,4 ;ALL INSNS WITH 4 IN TOP 3 BITS (LOGICAL INSNS) ARE OK. + CAIN A,5 ;HALFWORD INSTRUCTIONS ALSO OK. + JRST IODCD3 + LDB A,[360600,,J] + CAIE A,MOVE_-36 ;ALL FORMS OF MOVE, MOVS, MOVN AND MOVM OK + CAIN A,MOVN_-36 + JRST IODCD3 + CAIE A,ADD_-36 ;ADD & SUB OK. (OF COURSE, ONLY TO-MEMORY INSNS MAKE SENSE) + POPJ P, +IODCD3: LDB A,[270400,,J] ;AC FIELD NEED NOT BE 0, SO GET CONTENTS OF SPEC'D AC, + UMOVE D,(A) + MOVEI A,D + DPB A,[270400,,J] ;AND MAKE THE INSN USE AC D, WHERE THE VALUE IS. +IODCD2: TLZ J,17 + XCTRIJ XRW,J ;EXECUTE INSN, CHECKING FOR INTERRUPTS. + AOS (P) + POPJ P, + +; FLUSH LAST VESTIGES OF USER +; ELIMINATES ALL POINTERS TO USER & FREES USER VARIABLES (CLOBBERS U TO "USER") +; R, IF NON-ZERO, IS ADDRESS OF CHANNEL NOT TO BE CLOSED UNTIL LAST MINUTE +; (IN CASE PCLSR OUT OF .UCLOSE) + +ZUSER: MOVEI A,(U) ;CLEAR BOTH TRANSLATION LISTS + HRLI A,300000 ;FOR THIS JOB. + PUSHJ P,NTRNC + JFCL + MOVEI A,0 ;AND GET RID OF EXISTING FOREIGN-USER CHANNELS. +ZUSER2: SKIPE UNAME(A) + PUSHJ P,ZUSES ;SEE IF THIS USER HAS ANY POINTERS TO BE FLUSHED + CAMN U,SERVER(A) ; If we were a server for this guy, + SETOM SERVER(A) ; clear it out. + ADDI A,LUBLK + CAMGE A,USRHI + JRST ZUSER2 ;LOOP FOR ALL SETS OF USER VARIABLES + SKIPE R + SETZM (R) + CONO PI,CLKOFF + SKIPE NMPGS(U) ;USER SHOULD HAVE NO MEMORY BY NOW + BUG + SETZM UNAME(U) ;ONLY PLACE THAT UNAME IS ZEROED + SETOM USTP(U) ;SET USTP TO SPEED SEARCH + MOVE A,U ;USER FLUSHED + MOVE U,USER + MOVSI T,SCLDEC + IORM T,SUPCOR ;CAUSE USER VARIABLE BLOCKS DECREASE PROGRAM TO RUN + POPJ P, ;RETURN WITH CLOCK OFF + + +;CALLED BY ADISOWN, NATTACH, NDETACH, ETC. +ZUSES: MOVEI D,%CLSU\%CLSFU\%CLSJI\%CLSJO ;CLSTB BITS FOR CHANNELS TO CLOSE +ZUSES1: PUSH P,B + PUSH P,R + PUSH P,C + MOVE C,R + SETZM B ;CLEAR STOPPED PROC FLAG + PUSHJ P,CHSCAA ;EXECUTE FOLLOWING INST FOR EACH CHANNEL AND I/O PDL SLOT + PUSHJ P,ZACHEK + POP P,C + POP P,R + SKIPE B ;SKIP UNLESSS YOU STOPPED THE PROC + PUSHJ P,UPCLSR ;RESTART USER + JRST POPBJ + +ZACHEK: HLRZ T,(R) ;CHECK FOR CHANNEL TO ZAP + CAME T,U + POPJ P, +ZACHK4: HRRZ T,(R) + HLRZ T,CLSTB(T) + TRNN T,(D) + POPJ P, ;IS IT EITHER TYPE OF USER CHANNEL? OR JOB CHNL? + TRON B,-1 ;SET FLAG + PUSHJ P,RPCLSR ;STOP USER + HRRZ T,(R) + HLRZ T,CLSTB(T) + TRNN T,%CLSFU ;IS IT A FOREIGN USR CHNL? + JRST ZACHK2 ;NO, SUPERIOR OR JOB CHNL. + JUMPG R,ZACHK1 ;IOPDL CHANNEL + MOVEI T,LUBLK ;SEE IF A HAS BEEN CLOBBERED + IDIVM A,T ;(AT LEAST MAKE SURE IT'S A VALID USER INDEX) + IMULI T,LUBLK + CAMN T,A + CAML A,USRHI + BUG + HRRZ T,R ;NORMAL CHANNEL, INTERRUPT ON IT. + SUBI T,IOCHNM(A) + MOVE T,CHNBIT(T) + AND T,MSKST2(A) + IORM T,IFPIR(A) +ZACHK2: CAIE C,(R) ;UNLESS THE ONE NOT TO BE CLOSED UNTIL LAST MINUTE, + SETZM (R) ;FOR ANY KIND OF CHANNEL, CLEAR IT OUT. + POPJ P, + +ZACHK1: MOVEI T,IIOPOP ;FOREIGN USR IN IOPDL SLOT: INTERRUPT WHEN IOPOPPED. + MOVEM T,(R) + POPJ P, + +ZUSLOG: PUSH P,[ZUSER] ;DO LOGUSE THEN ZUSER + +;LOG RUNTIME AND SWAPIN REQUESTS USED BY JOB IN U +;JOB CALLED FOR SHOULD NOT BE CURRENT OR ABLE TO RUN DURING CALL +;JOB SHOULD NOT BE TOP LEVEL EXCEPT WHEN DMNPLO CALLS +; HERE JUST BEFORE SENDING THE USAGE TO THE DEMON +;CLOBBERS T,TT,I + +LOGUSE: MOVN TT,UTRNTM(U) + MOVN T,USIPRQ(U) + EXCH TT,TRUNTM(U) ;AVOID CHARGING FOR THIS USAGE TWICE + EXCH T,TSIPRQ(U) + SUB TT,TRUNTM(U) ;COMPUTE TOTAL USAGE NOT YET CHARGED + SUB T,TSIPRQ(U) + SKIPGE I,SUPPRO(U) ;FIND HIGHEST JOB IN TREE + POPJ P, ;BUT IF TOP LEVEL RETURN WITH USAGE IN TT, T +;THIS IS TO FIND A BUG. -- CStacy, 4/30/82 + CAME I,U ;IS THIS JOB ITS OWN SUPERIOR? + JRST LOGUS1 + BUG PAUSE,[SOME JOB IS ITS OWN SUPERIOR, U AND I=],OCT,U +LOGUS1: SKIPL SUPPRO(I) + JRST [ MOVE I,SUPPRO(I) ? JRST .-1 ] + ADDM TT,TRUNTM(I) ;ADD CHARGES TO TREE'S ACCOUNT + ADDM T,TSIPRQ(I) + POPJ P, + +;DO LOGOUT FOR TREE HEADED BY JOB IN U +;CALLER SHOULD THEN PUSHJ P,DMNPLI TO LOG JOB BACK IN +;THIS IS USED TO KEEP ACCOUNTING STRAIGHT WHEN DETACH, CHUNAME, RELOAD (SIGH) +;IF JOB IS CURRENTLY RUNNING, TIME USED IN CURRENT QUANTUM +;WON'T GET CHARGED THIS TIME AROUND. TOO BAD. +;CLOBBERS T,TT,I,J,D. CALL WITH CLKOFF OR IN PROGRESS. + +LOGUPD: PUSH P,U + MOVE J,UTMPTR(U) + MOVEI U,LUBLK +LOGUP1: ADDI U,LUBLK + CAML U,USRHI + JRST LOGUP2 + CAMN J,UTMPTR(U) ;SKIP JOBS IN OTHER TREES (FOR SPEED) + SKIPGE SUPPRO(U) ;AND SKIP TOP LEVEL JOBS + JRST LOGUP1 + SKIPE UNAME(U) ;DON'T GET CONFUSED BY EMPTY SLOTS + PUSHJ P,LOGUSE ;PROBABLY AN INFERIOR IN TREE LOGGING OUT, UPDATE ACCT + JRST LOGUP1 + +LOGUP2: POP P,U + JRST DMNPLO ;TELL DEMON ABOUT TREE'S USAGE + +SUBTTL USER UUO WAIT (HANG UP) ROUTINE +; DOES NOT WORK FOR XCT T OR FOR X (T) +; THE INSTRUCTION BEFORE THE PUSHJ P,UFLS GETS EXECUTED WITH AN +; ARGUMENT PASSED IN T AND ITS USER INDEX IN U. I BELIEVE IT +; IS ONLY ALLOWED TO BASH T AND A. +; +UFLS: CONSZ PI,77400 + BUG HALT,[UFLS WITH PI IN PROGRESS] + CONO PI,CLKOFF ;DOES NOT ALLOW CLOCK INTS + XCT CLUSAV + SKIPGE U,USER ;GET INDEX OF USER BEING BLOCKED + JRST 4,. ;NULL JOB SHOULD NOT GET BLOCKED + MOVEM T,EPDL2(U) ;SAVE C(T) FOR FLSINS AT PCLSR + MOVEM T,AC16S(U) ;SAVE IN SWAP OUT AC ALSO + POP P,UPC(U) ;WORK FOR INST INDEX OF P + MOVEI T,AC0S(U) + BLT T,AC15S(U) ;STORE REST OF ACS + MOVE T,UPC(U) ;GET PC AT CALL (=CALL+1 ; =SKIP +2) + SKIPA T,-2(T) ;GET POINTER TO SKIP +UFL3: MOVE T,(T) ;GET CONTENTS OF E (WAS AN XCT) + MOVE U,AC17S(U) ;WIN FOR INSNS INDEX OF U. + HRRI T,@T ;CALCULATE E + TLZ T,37 ;CLEAR OUT @ AND INDEX BITS + MOVE U,USER + MOVEM T,FLSINS(U) ;STORE AS BLOCKING CONDITION + TLC T,(XCT) + TLNN T,777740 + JRST UFL3 ;JUMP IF INSTRUCTION WAS XCT + CONO PI,UTCON-1 ;TURN ON ALL PIS EXCEPT CLOCK + MOVSI T,%SWPGW+%SWINT + ANDCAM T,USWST(U) ;CLEAR WAITING FOR PAGE TYPE FLSINS + SKIPGE RPCL(U) ;SKIP IF NOT BEING RPCLSRED + JRST UFL1 ;LOSER IS BEING RPCLSRED +UFL6: MOVE U,AC17S(U) ;FOR CLUSAV TO STORE + SETOM UFLSF + CONO PI,CLKRQ ;CAUSE INTERRUPT TRANSFERING TO CLOCK ROUTINE PI IN + ; PROGRESS +IFE KA10P, JRST . ;ON KL AND KS SEEMS TO TAKE A WHILE TO GO OFF ("I + ; CAN WAIT FOREVER, YOU KNOW") +IFN KA10P, JRST 4,. ;ON KA SHOULD GO OFF RIGHT AWAY + +UFL1: MOVE P,CPDLP ;MUST NOT USE USR PDL SINCE THAT CAN + ;GET CLOBBERED BY LSWDIS VIA UFL5 + ;CLOCK IS OFF, SO CPDLP IS OK +IFN KA10P,[ + MOVE T,UEXIT ;PICK UP EXIT INSTR + CAME T,[JRST ONEPROC] ;SKIP IF WAS TRYING TO ONE PROCEED THE UUO + ; THAT HUNG + JRST UFL1A ;NOT ONE PROCEEDING + MOVSI T,%PC1PR ;GET ONE PROCEED BIT + IORM T,UUOH ;TURN IT ON IN PC +UFL1A:] ;KA10P +IFN KS10P,[ + MOVE T,UEXIT ;PICK UP EXIT INSTR + CAME T,[JRST ONEPR4] ;SKIP IF WAS TRYING TO ONE PROCEED THE UUO + ; THAT HUNG + JRST UFL1A ;NOT ONE PROCEEDING + MOVSI T,OIPBIT ;GET ONE PROCEED BIT + IORM T,UUOH ;TURN IT ON IN PC +UFL1A:] ;KS10P + SOS T,UUOH ;UUOH HAS REAL PC IF UFL5 SKIPS. WILL GET SET BY ONEPR1 + PUSHJ P,UFL5 ;BACK UP TO UUO + JRST UFL6 ;FINALIZATION REQUIRED + MOVE T,RPCL(U) + JRST ONEFL2 ;WIN + +SUBTTL VARIOUS WAIT & LOCK-SWITCH ROUTINES +; +;WAIT FOR INSTRUCTION AFTER CALL TO SKIP WITH UTCCHN OFF +; +LWAIT1: CONO PI,UTCON ;TURN INTERRUPTS ON +LWAIT: PCLT + XCT @(P) ;ENTRY, EXECUTE INSTRUCTION + PUSHJ P,UFLS ;HANG TILL INSTRUCTION SKIPS + CONO PI,UTCOFF ;TURN INTERRUPTS OFF + XCT @(P) ;TRY AGAIN + JRST LWAIT1 ;LOSE + JRST POPJ1 ;WIN, RETURN SKIPPING OVER ARG +; +;WAIT FOR LOCK VAR (@ NEXT LOC) TO BE -1 AND SEIZE IT +; +SWTL: PCLT + MOVEI T,(@) ;ENTRY + HRLM T,(P) ;MAKE PC STORED ON PDL INDIRECT + SKIPGE @(P) ;SKIP IF ALREADY LOCKED + JRST SWTL1 ;NOT LOCKED SO TRY TO GRAB IT + MOVEI T,@(P) ;ADDRESS OF SWITCH + HLRZ T,1(T) ;USER THAT HAS SWITCH + ANDI T,777 + IMULI T,LUBLK + CAMN T,USER ;SKIP IF THIS USER DOESN'T HAVE IT + BUG ;THIS USER ALREADY HAS THAT SWITCH +SWTL1: SKIPL @(P) ;(DO NOT CHANGE TO AOSE) + PUSHJ P,UFLS ;HANG TILL NEGATIVE + CONO PI,CLKOFF + AOSE @(P) + JRST SWTL1 +SWTL2: MOVEI T,@(P) +SWTL3: PUSH P,U + PUSH P,T + MOVE T,USER + IDIVI T,LUBLK + ADDI T,600000 + MOVE U,USER + HRL T,LSWPR(U) + POP P,U + MOVSM T,1(U) + MOVE T,USER + HRRZM U,LSWPR(T) + POP P,U + JRST CLKOJ1 +; +;IF LOCK ALREADY SEIZED, JUST SET UP POINTERS +SWTLZ: MOVEI T,(@) + HRLM T,(P) + JRST SWTL2 + +SWTAD: PCLT ;TRY TO LOCK SWITCH (@NEXT LOCN). IF SUCEED, SKIP EXTRA TIME. + MOVE T,@(P) ;IF FAIL, DO N LSWPOPS (AS SPEC IN 4.6-4.1 OF NEXT WORD) + SKIPGE (T) ;AND WAIT FOR SWITCH TO SEEM TO BE AVAILABLE. + JRST SWTAD1 ;THEN RETURN (NOTE: NOT LOCKING IT). +SWTAD2: TLNN T,77000 + JRST SWTAD3 + PUSH P,T + PUSHJ P,LSWPOP + POP P,T + SUB T,[1000,,] + JRST SWTAD2 + +SWTAD3: SKIPL (T) + PUSHJ P,UFLS + JRST POPJ1 + +SWTAD1: CONO PI,CLKOFF + AOSE (T) + JRST [ CONO PI,CLKON + JRST SWTAD2 ] + AOS (P) ;SKIP OVER FAILURE RETURN + JRST SWTL3 + +; +;WAIT FOR INSTRUCTION AFTER CALL TO SKIP WITH CLKCHN OFF +CWAIT1: CONO PI,CLKON ;TURN CLOCK ON +CWAIT: PCLT + XCT @(P) ;ENTRY, EXECUTE INSTRUCTION + PUSHJ P,UFLS ;HANG TILL INSTRUCTION SKIPS + CONO PI,CLKOFF ;TURN CLOCK OFF + XCT @(P) ;TRY AGAIN + JRST CWAIT1 ;LOSE + JRST POPJ1 ;WIN, RETURN SKIPPING OVER ARG + +; +;WAIT FOR LOCK VAR (@ NEXT LOC) TO BE NON-NEGATIVE AND SEIZE IT +LSWTL: PCLT + MOVEI T,(@) ;IF 4.9 OF NEXT LOCN =1, RETURN WITH UTCOFF + HRLM T,(P) + MOVSI T,400000 + PUSHJ P,LWAIT + SKIPGE @-1(P) + IORM T,@(P) + MOVE T,(P) + SKIPL (T) + CONO PI,UTCON + MOVEI T,@(P) +LSWTL2: PUSH P,TT + MOVEI TT,601000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SWITCH LIST LOCK, DOES NOT WORK FOR SWITCHES POINTED TO INDEX OF A, B, OR D +;FOLLOW BY LIST OF SWITCHES +;4.9-4.4=0 4.3-4.1 0 AOSE SWITCH 1 SIGN SWITCH +SLUGH: PCLT + PUSH P,A + PUSH P,B + PUSH P,D + MOVEI T,AC0S(U) + BLT T,AC0S+17(U) ;FOR SLWAIT FIRST TIME +SLUGH1: HRRZ T,-3(P) ;POINTER TO SWITCH LIST + PUSHJ P,SLWAIT + PUSHJ P,UFLS + HRRZ T,-3(P) +SLUGH2: MOVE A,(T) ;TRY TO LOCK LIST + TLNE A,770000 + JRST SLUWIN ;REACHED END OF LIST + LDB B,[220400,,A] ;INDEX + LDB D,[330300,,A] + SKIPE B + ADD A,(B) + HRRZS A + CAIL D,2 + BUG + XCT SLLOCK(D) + JRST SLULOS + AOBJP T,SLUGH2 ;LH COUNTS SWITCHES SUCCESSFULLY SEIZED + ;SHOULD NVERE FALL THROUGH +SLWAIT: MOVE A,(T) + TLNE A,770000 + JRST POPJ1 ;WIN + LDB B,[220400,,A] ;INDEX + LDB D,[330300,,A] ;TYPE CODE + JUMPE B,SLWT1 + ADD B,U + ADD A,AC0S(B) +SLWT1: CAIL D,2 + BUG + XCT SLWATT(D) + POPJ P, ;LOSE + AOJA T,SLWAIT ;THAT SWITCH OK, TRY OTHERS + +SLWATT: SKIPL (A) ;WAIT FOR NEG (AOSE SW) + SKIPGE (A) ;WAIT FOR POS (SIGN SW) + +SLUWIN: POP P,D + POP P,B + POP P,A + SUB P,[1,,1] ;"RETURN" BUT NOT INCREMENTED + JRST (T) + +SLLOCK: PUSHJ P,SWTLX + PUSHJ P,LSWTLX + +SLULOS: HLRZ A,T +SLULO2: JUMPE A,SLUGH1 ;NONE SEIZED TRY AGAIN + PUSHJ P,LSWPOP ;RELEASE THOSE SEIZED + SOJA A,SLULO2 + +SWTLX: CONO PI,CLKOFF ;DON'T GO OFF HALF-LOCKED + AOSE (A) + JRST CLKONJ + EXCH A,T + PUSHJ P,SWTL3 + BUG +SWTLX1: EXCH A,T + JRST POPJ1 + +LSWTLX: CONO PI,UTCOFF + SKIPGE (A) + JRST UTCONJ + MOVSI B,400000 + IORM B,(A) + CONO PI,UTCON + EXCH A,T + PUSH P,TT + MOVEI TT,601000 + PUSHJ P,LSWSET + POP P,TT + JRST SWTLX1 + +;SET UP ROUTINE TO SETOM VARIABLE UPON UNLOCKING SWITCH +STMSET: PUSH P,TT + MOVEI TT,606000 + JRST COMSET + +IFN 0,[ +;SET UP ROUTINE TO BE CALLED ON PCLSR'ING OUT +FINSET: MOVE T,@(P) + HRLI T,-1(P) + PUSH P,TT + MOVEI TT,402000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 +] + +;SET UP ROUTINE TO AOS VARIABLE UPON UNLOCKING SWITCH +AOSSET: PUSH P,TT + MOVEI TT,605000 + JRST COMSET + +;SET UP ROUTINE TO SOS VARIABLE UPON UNLOCKING SWITCH +SOSSET: PUSH P,TT + MOVEI TT,603000 + JRST COMSET + +;SET UP ROUTINE TO SOS LH UPON UNLOCKING SWITCH +;HALT IF SWITCH'S LH EVER BECOMES NEGATIVE +SOLSET: PUSH P,TT + MOVEI TT,607000 + JRST COMSET + +;SET UP ROUTINE TO BE CALLED UPON UNLOCKING SWITCH +;THAT ROUTINE MAY ONLY CLOBBER A AND T!! IT GETS CALLED +;WITH USER IN U, AND THE JOB'S ACS IN AC0S(U)-AC17S(U) +LOSSET: MOVE T,@(P) + HRLI T,-1(P) + PUSH P,TT + MOVEI TT,602000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SET UP ROUTINE TO CLEAR SIGN BIT OF VARIABLE UPON UNLOCKING SWITCH +SGNSET: PUSH P,TT + MOVEI TT,601000 + JRST COMSET + +;SET UP ROUTINE TO DO NOTHING UPON UNLOCKING SWITCH +NULSET: PUSH P,TT + MOVEI TT,0 + PUSHJ P,LSWSET + POP P,TT + POPJ P, + +;ROUTINE TO ADD THIS PROCEDURE TO A LIST POINTED TO +;BY THE WORD AFTER THE CALL. UNLOCKING REMOVES IT FROM THE LIST +LSTSET: PUSH P,TT ;LEAVES CLKON + MOVEI TT,604000 + PUSHJ P,LSTST3 + POP P,TT + JRST POPJ1 + +LSTST3: PUSH P,U + PUSH P,Q + MOVEI Q,LSWB0(U) +REPEAT NULBLK,[ +IFN .RPCNT,ADDI Q,2 + SKIPN 1(Q) + JRST LSTST2 +] + BUG ;NOT ENOUGH BLOCKS +LSTST2: MOVE T,@-4(P) ;ADDRESS OF HEAD OF LIST + CONO PI,CLKOFF + PUSH P,(T) ;PUSH HEAD OF LIST + POP P,(Q) ;POP INTO LSWB BLOCK + MOVEM Q,(T) + HRLM T,(Q) + MOVE T,(Q) + TRNE T,-1 + HRLM Q,(T) + CONO PI,CLKON + JRST LSWSE3 + +IFN 0,[ +;SET UP ROUTINE TO SETOM VARIABLE UPON UNLOCKING OF SWITCH +;BY OTHER THAN PCLSRING OUT +STMNPS: PUSH P,TT + MOVEI TT,206000 + JRST COMSET + +;SET UP ROUTINE TO BE CALLED UPON UNLOCKING OF SWITCH +;BY OTHER THAN PCLSRING OUT +LNPSET: PUSH P,TT + MOVEI TT,202000 + JRST COMSET +];END IFN 0 + +COMSET: EXCH TT,(P) + MOVE T,@-1(P) + MOVEI T,@T + EXCH TT,(P) + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SET USER LOCK SWITCH BLOCK, WD1 IN T, MODE IN TT +LSWSET: PUSH P,U + MOVE U,USER + PUSH P,Q + MOVEI Q,LSWB0(U) +REPEAT NULBLK,[IFN .RPCNT,ADDI Q,2 + SKIPN 1(Q) + JRST LSWSE2 +] + BUG ;NOT ENOUGH BLOCKS + +LSWSE2: MOVEM T,(Q) +LSWSE3: MOVE T,U + IDIVI T,LUBLK + MOVE U,USER + HRL T,LSWPR(U) + IOR T,TT ;GET TYPE + MOVSM T,1(Q) + HRRZM Q,LSWPR(U) + JRST POPQUJ + +LSWCJ1: AOS (P) ;EXIT TO DO LSWCLR AND SKIP-RETURN. + +;UNLOCK ALL SWITCHES, CALLED BY OPENL, ADISOWN, IOADCR +LSWCLR: PUSH P,T +LSWCL1: +;TEMPORARY CODE ADDED 1/22/80 TO SEE IF THERE ARE ANY MORE OF +;THIS CLASS OF BUGS + CAME U,USER + BUG +;END TEMPORARY CODE + SKIPN T,LSWPR(U) ;MUST HAVE USER IN U + JRST POPTJ + PUSHJ P,LSWPOP + JRST LSWCL1 + +LSWPJ1: AOS (P) +LSWPOP: PUSH P,U + MOVE U,USER + TLO U,400000 ;SIGNAL NOT PCLSR + SKIPN T,LSWPR(U) + BUG + PUSHJ P,LSWPPP + JRST POPUJ + +LSWPPP: PUSH P,A + PUSH P,T + MOVE A,1(T) + HRRZM A,LSWPR(U) + CAIL T,USRSTG + SETZM 1(T) + PUSHJ P,LSWDIS + POP P,T + POP P,A + POPJ P, + +LSWZAP: PUSH P,U ;FROM PCLSR + PUSH P,A +LSWZP1: PUSH P,T + MOVE A,1(T) + HRRZM A,LSWPR(U) + CAIL T,USRSTG + SETZM 1(T) + PUSHJ P,LSWDIS + POP P,T + HRR U,-1(P) + SKIPE T,LSWPR(U) + JRST LSWZP1 + POP P,A + SUB P,[1,,1] + TLZN U,200000 ;HAS PC BEEN CLOBBERED? ;THIS IS ONLY FOR FINSET R.I.P. + JRST PCLSR7 ;NO + SKIPLE PCLDBM + SETZM LSUUO(U) ;INDICATE OCCURRENCE OF FINSET (WILL MEAN WE HAVEN'T MISSED MARK) + JRST PCLSR4 ;REQUIRED TO START UP ROUTINE + +;-1(P) HAS POINTER TO SWITCH BLOCK TO UNDO. +;A HAS SECOND WORD OF THAT BLOCK. +; 4.9=1 => PERFORM FUNCTION ON PCLSR +; 4.8=1 => PERFORM FUNCTION ON ANY LSWPOP OTHER THAN PCLSR +; 4.1-4.3 => FUNCTION +; 3.1-3.9 USER # LAST LOCKED BY +; 1.1-2.9 LSWPR THREAD + +LSWDIS: LDB T,[330300,,A] ;FUNCTION + TLNE A,400000 ;SKIP IF NOT FOR PCLSR + JUMPGE U,LSWDS1 ;PCLSRED AND 4.9=1 + TLNN A,200000 ;NOT FOR PCLSR OR FOR PCLSR BUT NOT PCLSRED + POPJ P, ;NOT FOR EITHER LSWPOP + JUMPGE U,CPOPJ ;FOR OTHER LSWPOP BUT PCLSRED +LSWDS1: JRST LSWTAB(T) + +LSWTAB: JRST UNSWTL ;0 (AOSE) ALSO USED FOR QUSR + JRST UNLSWT ;1 (SIGN) + JRST ULROUT ;2 (GO TO ROUTINE) + JRST ULAOS ;3 (AOS, SOS) + JRST UNLST ;4 (UNLOCK FROM LIST) + JRST ULSOS ;5 (SOS, AOS) + JRST ULSTM ;6 (SETOM) + JRST ULAOSL ;7 (AOS,SOS LEFT HALF) + +UNSWTL: MOVE T,-1(P) + SETOM (T) + POPJ P, + +ULSTM: MOVE T,@-1(P) + SETOM (T) + POPJ P, + +UNLSWT: MOVE T,@-1(P) + MOVSI A,400000 + ANDCAM A,(T) + POPJ P, + +ULAOSL: MOVE T,@-1(P) + MOVSI A,-1 + ADDB A,(T) + JUMPGE A,CPOPJ + BUG ;OVER-SOS'ED + +ULAOS: MOVE T,@-1(P) + SOS (T) + POPJ P, + +UNLST: SETOM DLSRCH + MOVS T,@-1(P) + HLRM T,(T) + MOVSS T + TRNE T,-1 + HLLM T,(T) + SETZM DLSRCH + POPJ P, + +ULSOS: MOVE T,@-1(P) + AOS (T) + POPJ P, + +ULROUT: MOVE T,@-1(P) + TLNE A,200000 + JRST ULROU1 ;A LOSSET - MAY CLOBBER A OR T; USR INDEX IN U + HRRZM T,UPC(U) ;IT'S A FINSET, EXPECTS THE OLD METHOD OF CALL. + TLNE T,-1 + HLRM T,AC15S(U) +IFE KA10P,[ + MOVSI T,%PSPCU ;IT MIGHT TRY AN XCTR + HLLM T,UPC(U) +] ;IFE KA10P + TLOE U,200000 ;SIGNAL PC CLOBBERED + BUG ;PC TRIED TO BE CLOBBERED TWICE + POPJ P, + +ULROU1: JUMPGE U,(T) ;IF LOSSET, AND LSWPOPPING, + MOVE A,[B,,AC0S+B] + ADDI A,(U) ;PUT THE ACS IN THE AC0S, SINCE + BLT A,AC0S+H(U) ;THAT'S WHERE THEY'LL BE IF CALL LOSSET ROUTINE WHILE PCLSRING. + JRST (T) + +;FIND SWITCH POINTED TO BY WORD AFTER +;PUSHJ P,LSWREM AND UNLOCK IT +LSWREM: PUSH P,T + PUSH P,U + PUSH P,Q + MOVE U,USER + SKIPN U,LSWPR(U) + BUG + HRRZ Q,@-3(P) + MOVEI T,1 +LSWRM1: CAMN U,Q + JRST LSWRM2 + HRRZ U,1(U) + SKIPN U + BUG + AOJA T,LSWRM1 +LSWRM2: POP P,Q + POP P,U + PUSHJ P,LSWPON + AOS -1(P) + JRST POPTJ + +LSWDEL: PUSH P,U ;REMOVE SWITCH FROM HEAD OF LIST + MOVE U,USER ;DO NOT ATTEMPT TO UNLOCK IT + PUSH P,T + SKIPN T,LSWPR(U) + BUG + PUSHJ P,LSWDDD + JRST POPTUJ + +LSWDDD: PUSH P,Q + HRRZ Q,1(T) + HRRZM Q,LSWPR(U) + CAILE T,USRSTG + SETZM 1(T) + POP P,Q + POPJ P, + +;POP C(T)'TH FROB BACK +LSWPON: PUSHJ P,LSWBAK + PUSHJ P,LSWPPP + POPJ P, + +;DELETE C(T)'TH FROB BACK +LSWDLN: PUSHJ P,LSWBAK + PUSHJ P,LSWDDD + POPJ P, + +LSWBAK: PUSH P,U + MOVE U,USER + TLO U,400000 ;SIGNAL NOT PCLSR IN CASE OF LSWPPP + PUSH P,Q + MOVE Q,T + MOVEI T,LSWPR-1(U) + SOJE Q,LSWBA3 ;UNLOCKING FIRST FROB + MOVE T,1(T) + SOJG Q,.-1 +LSWBA2: MOVE Q,T + HRRZ T,1(T) + PUSH P,LSWPR(U) ;DON'T WORRY, YOU CAN'T GET PCLSR'ED JUST BELOW + XCT @-3(P) + HRRZ T,LSWPR(U) + HRRM T,1(Q) + POP P,LSWPR(U) + JRST POPQU1 + +LSWBA3: MOVE T,LSWPR(U) + XCT @-2(P) + JRST POPQU1 + +SUBTTL VARIOUS RETURNS + +PPBAJ1: POP P,B +POPAJ1: AOSA -1(P) +POPBAJ: POP P,B +POPAJ: POP P,A +CPOPJ: POPJ P, + +POPQJ: POP P,Q + POPJ P, + +POPBJ1: AOSA -1(P) +POPCBJ: POP P,C +POPBJ: POP P,B + POPJ P, + +POPJ3: AOS (P) +POPJ2: AOSA (P) +POPCJ1: POP P,C +POPJ1: AOSA (P) +POPCJ: POP P,C + POPJ P, + +POPJJ1: AOS -1(P) +POPJJ: POP P,J + POPJ P, + +POPUJ1: AOSA -1(P) +POPTUJ: POP P,T +POPUJ: POP P,U + POPJ P, + +POPTJ: POP P,T + POPJ P, + +POPTTJ: POP P,TT + POPJ P, + +POPWJ2: AOS -1(P) +POPWJ1: AOS -1(P) +POPWJ: POP P,W + POPJ P, + +PIONJ: CONO PI,PION + POPJ P, + +CKOCJ1: CONO PI,CLKON + JRST POPCJ1 + +CLKOJ1: AOS (P) +CLKONJ: CONO PI,CLKON + POPJ P, + +CKOPJ1: AOS (P) +CLKOPJ: CONO PI,CLKON + JRST LSWPOP + +IFN OMXP,[ +OMXONJ: CONO PI,OMXON + POPJ P, +] + +TTYOJ1: AOS (P) +TTYONJ: CONO PI,TTYON + POPJ P, + +IFN PTRP, PTRONJ:: PTPONJ:: +LPTONJ: CONO PI,LPTON + POPJ P, + +IFN NETP,NETOJ1: +UTCOJ1: AOSA (P) +UTCOAJ: POP P,A +IFN NETP,NETONJ: +UTCONJ: CONO PI,UTCON + POPJ P, + +POPQU1: AOS -2(P) +POPQUJ: POP P,Q + POP P,U + POPJ P, + +POP1J1: AOS -1(P) +POP1J: SUB P,[1,,1] + POPJ P, + +POP2J: SUB P,[2,,2] + POPJ P, + +POP3J1: AOS -3(P) +POP3J: SUB P,[3,,3] + POPJ P, + +POP4J: SUB P,[4,,4] + POPJ P, + +POP7J: SUB P,[2,,2] +POP5J: SUB P,[5,,5] + POPJ P, + +SUBTTL UUO PROCESSOR + +.IOT=UUOMIN +.OPEN=UUOMIN+1_27. +.OPER=UUOMIN+2_27. +.CALL=UUOMIN+3_27. +.USET=UUOMIN+4_27. +.BREAK=UUOMIN+5_27. +.STATUS=UUOMIN+6_27. +.ACCESS=UUOMIN+7_27. + +DEFINE GLOSYM X + IRP Y,,[X] + SQUOZE 4,.!Y + .!Y + TERMIN + TERMIN + +;REPEAT OVER USET NAMES FROM 0 TO 77. + DEFINE USTIRP A + IRPS X,,[UPC VAL TTY FLS UNAME JNAME MASK USTP +PIRQC INTB MEMT SV40 IPIRQ APIRQ SNAME PICLR +MARA MARPC UUOH UIND RUNT MSK2 IFPIR APRC +CNSL UTRP IIFPI AIFPI IMASK AMASK IMSK2 AMSK2 +JPC OPC RTMR HSNAME BCHN MPVA IDF1 ADF1 +IDF2 ADF2 DF1 DF2 OPTION 40ADDR TVCREG +TTST TTS1 TTS2 WHO1 WHO2 WHO3 SUPPRO TR1INS +TR2INS MBOX MBO1 EBOX EBO1 XUNAME XJNAME FTL1 FTL2] +A +TERMIN +TERMIN + +;REPEAT OVER USET NAMES 600 AND UP. + DEFINE USTIR1 A + IRPS X,,[PAGRAN PAGAHD SERVER] + A + TERMIN TERMIN + +;NOTE: OPER'S BELOW ARE 8 PER LINE +; USE UP ILUUO'S BEFORE ADDING TO END +; THE FOLLOWING SHOULD GO AWAY EVENTUALLY +; ITYI (=ITYIC) +; SETMSK (=SUSET) +; WSNAME (=SUSET) +; UPISET (=SUSET) +; RDSW (=DATAI) +; EOFC (OBSOLETE) +DEFINE OPRIRP A + IRPS X,,[ITYI LISTEN SLEEP SETMSK SETM2 DEMON CLOSE +UCLOSE ATTY DTTY IOPUSH IOPOP DCLOSE DSTOP RDTIME +RDSW GUN UDISMT GETSYS IPDP GETLOC SETLOC DISOWN +DWORD DSTEP GENSYM LOGOUT REALT WSNAME UPISET RESET +ARMOVE DCONTIN CBLK ASSIGN DESIGN RTIME RDATE HANG +EOFC IOTLSR RSYSI SUPSET PDTIME ARMRS UBLAT IOPDL +ITYIC MASTER VSTST NETAC NETS REVIVE DIETIM SHUTDN +ARMOFF NDIS FEED EVAL REDEF IFSET UTNAM UINIT +RYEAR RLPDTM RDATIM RCHST RBTC DMPCH SWAP MTAPE +GENNUM NETINT] + A +TERMIN +TERMIN + +DEFINE CALIRP A +IRPS X,,[DISMIS LOSE TRANAD VALUE UTRAN CORE TRAND +DSTART FDELE DSTRTL SUSET LTPEN VSCAN POTSET] +A TERMIN TERMIN + +;THESE ARE THE SYMBOLS USED BY MIDAS AND DDT. THEY ALSO +;EXIST IN SYS:ITS DEFS. +;SYMBOLS SHOULD BE LEFT IN CURRENT ORDER OR DDT WILL LOSE +SYSYMB: USTIRP [SQUOZE 44,.R!X + .IRPCNT] + SQUOZE 44,.RIOC + 100 + SQUOZE 44,.RIOS + 120 + SQUOZE 44,.RIOP + 140 + SQUOZE 44,.RPMAP + 200 + USTIR1 [SQUOZE 44,.R!X + 600+.IRPCNT] + USTIRP [SQUOZE 44,.S!X + 400000+.IRPCNT] + USTIR1 [SQUOZE 44,.S!X + 400600+.IRPCNT] + + GLOSYM [IOT,OPEN,OPER] + +DEFINE DEFSYM X/ +IRPS Z,,[X] +SQUOZE 44,Z +Z +.ISTOP +TERMIN TERMIN + +.INSRT BITS > + +EXPUNG DEFSYM + + ZZ=1 + OPRIRP [IFSN X,ILUUO,[.!X=.OPER ZZ + SQUOZE 4,.!X + .!X] + ZZ==ZZ+1] + +MXOPR==ZZ + + SQUOZE 4,.CALL + .CALL + +CALIRP [ +IFSN X,UNUSD,[ + .!X=.CALL .IRPCNT+1, + SQUOZE 4,.!X + .!X +]] + + GLOSYM [USET,BREAK,STATUS,ACCESS] +SYSYME==.-1 + +;THESE SYMBOLS ARE USED BY DDT, SO THE USER CAN OPEN .PIRQC, ETC. + ;BEGINNING FOR .GETSYS (USYMS) +SYSUSB: +USTIRP [ + SQUOZE 4,.!X + .IRPCNT +] + SQUOZE 4,.IOC + 100 + SQUOZE 4,.IOS + 120 + SQUOZE 4,.IOP + 140 + SQUOZE 4,.PMAP + 200 +USTIR1 [ + SQUOZE 4,.!X + 600+.IRPCNT +] +SYSUSE==.-1 ;END FOR .GETSYS (USYMS) + +;SIXBIT NAME TABLES FOR WHO LINE GENERATION. +;ALSO USED BY PEEK FOR PRINTING OUT JOBS' STATUS. + +OPRSXB: SIXBIT/OPER/ +OPRIRP [ +.1STWD SIXBIT/X/ +] + +CALSXB: SIXBIT/CALL/ +CALIRP [ +.1STWD SIXBIT/X/ +] + SIXBIT/UNUSD/ + +UUOSXB: +IRPS X,,IOT OPEN OPER CALL USET BREAK STATUS ACCESS +.1STWD SIXBIT/X/ +TERMIN +NUUOSX==.-UUOSXB + +;MACRO TO SAVE ACS AS APPROPRIATE FOR OUR CPU, LOAD UP U, +;CHECK VARIOUS ERROR CONDITIONS. + +DEFINE UUOSAV + CONSZ PI,77400 + BUG AWFUL,[UUO WITH PI IN PROGRESS] +IFN KA10P,[ + UMOVEM U,17 ;SAVE 17 + SKIPGE U,USER ;LOAD CURRENT USERS INDEX, + BUG AWFUL,[UUO IN NULL JOB] + UMOVEM T,16 ;SAVE LOC 16 FOR USER + MOVEI T,0 ;HA HA + XCTR XBW,[BLT T,15] ;SAVE REST OF ACS IN USERS SHADOW 0-15 +] ;KA10P +IFE KA10P,[ + SYSCTX + SKIPGE U,USER + BUG AWFUL,[UUO IN NULL JOB] + LDB T,[330300,,MUUOCX(U)] + CAIE T,1 + BUG AWFUL,[UUO WHILE IN AC BLK ],DEC,T +] ;IFE KA10P +TERMIN + +; UUO AND ILLOP TRAP HANDLER +; +;EITHER DISPATCHES TO APPROPRIATE UUO ROUTINE, +; RETURNS CONTROL TO USERS UUO ROUTINE, GOES TO ILLOP, USRTRP, OR USRIOT. +;CODE ON THIS PAGE IS INTERRUPTABLE AT ANY POINT + +;COME HERE TO RETURN A UUO TO THE USER. RESTORES USER ACS W THROUGH U ONLY. +USRUUO: CAIG U,LUBLK + BUG AWFUL,[RETURNABLE UUO FROM SYS OR CORE JOB,PC=],OCT,UUOH + MOVE W,UUOH + TLNN W,%PCUSR + BUG AWFUL,[RETURNABLE UUO FROM EXEC MODE,PC=],OCT,UUOH + HRRZ W,40ADDR(U) + MOVE P,USRPDL(U) ;IN CASE AN XCTR FAULTS. + XCTR XR,[HLRZ H,1(W)] + CAIE H,(JSR) ;ELSE OK ONLY IF OPCODE IN 41 IS 0 OR JSR. + JUMPN H,ILUUO ;THIS IS IN CASE USER IS HANDLING USER-UUO'S WITH PUSHJ + ;AND HIS UUOH ISN'T ABLE TO BE JSR'D TO. + XCTR XR,[HRRZ H,1(W)] + JUMPE H,ILUUO ;0 ISN'T ACCEPTABLE AS UUOH ADDRESS. + MOVE T,FORTY + UMOVEM T,(W) ;ALL IS LEGAL; PLANT UUO INTO USERS "40". + MOVE T,UUOH ;SIMULATE A JSR AT USER'S "41" + UMOVEM T,(H) + AOS H + HRRM H,UUOH ;SET TO RETURN TO USER AT FIRST INSTRUCTION OF UUO HANDLER +IFN KA10P,[ + MOVE U,[W,,W] + XCTR XBR,[BLT U,U] +] ;KA10P +ULEAVE: USRCTX ;SELECT USER MODE AC BLOCK IF NEC. + +EBLK + +;THE FOLLOWING BLOCK OF LOCATIONS IS SWITCHED WITH SOME USER VARS + +UEXIT: JRST 2,@XUUOH ;EXIT FROM UUO (FOR KL-10, POINTS TO APPROPRIATE + ;UPT LOC) + +CLUSAV: MOVEM U,AC17S ;CLOCK SAVE OF U + +IFE KA10P,[ +CLCXSV: DATAI PAG,CLCX ;CLOCK LEVEL CONTEXT SAVE +] ;IFE KA10P + +IFN KA10P,[ +XUUOH: 0 ;UUO AND ILLOP TRAP GETS HERE - UUOH0 MUST BE . + 1. +] ;KA10P + +UEXND:: ;END OF SWAPPED UEXIT BLOCK. + +BBLK + +UUOH0: UUOSAV +MUUOT1: SKIPGE UTRAPM(U) ;IF SUPERIOR WANTS TO CATCH UUOS, THIS IS FATAL INT. + JRST USRTRP + SKIPGE T,FORTY ;PICK UP THE UUO OR ILLOP + JRST USRIOT + CAML T,[UUOMIN] + CAML T,[UUOMAX] + JRST USRUUO ;NOT A SYSTEM CALL, GIVE TO USER +;DROPS THROUGH + ;DROPS IN +;HERE WITH UUO TO BE HANDLED BY SYSTEM IN T +ILLOP1: JUMPN U,UUOH1 + MOVEI Q,0 ;SAVE SYS JOB EXEC MODE LSWPR PNTR + EXCH Q,LSWPR + MOVEM Q,SLSWPR +UUOH1: SKIPE LSWPR(U) + JRST 4,. + MOVEM T,LSUUO(U) ;SAVE UUO FOR DEBUGGING PURPOSES + LSH T,-27. ;RIGHT JUSTIFY OP CODE + SKIPL UUODSP-UUOMIN_-27.(T) + JRST UUOTR3 + MOVE H,OPTION(U) + TLNE H,%OPDEC + JRST USRUUO +UUOTR3: SETZM SYSCVL(U) ;DIDN'T GET INTO SYSTEM VIA .CALL + MOVE P,USRPDL(U) ;SET UP USER PDL + HRRZ C,FORTY ;PICK UP EFFECTIVE ADDRESS OF UUO + LDB R,[270400,,FORTY] ;PICK UP AC FIELD OF UUO + MOVEM R,UUAC(U) ;SAVE AC FLD + PUSHJ P,@UUODSP-UUOMIN_-27.(T) ;DISPATCH ON UUO TYPE + JRST URET ;NORMAL RETURN (NON SKIP) +URETJ1: +IFE KA10P, MOVE U,USER ;(SINCE UUOH IS IN THE USER VARIABLES) + AOS UUOH ;UUO ROUTINE SKIPPED, AOS USER RETURN POINT +URET: MOVE U,USER + MOVE A,PIRQC(U) ;CHECK FOR RETURNING TO USER WITH PCLSR'ING FATAL + ; INT SET. + TDNE A,[BADBTS&#<%PIC.Z\%PIDIS>] ;A FEW BITS ARE FATAL BUT SET + ; ASYNCHRONOUSLY. + JRST [ HRRZ A,UEXIT ;INT SET, MAKE SURE UEXIT IS CLOBBERED + IFN KA10P, CAIE A,ONEPRO ;TO A LOCATION WHICH WILL CHECK PIRQC. + IFN KS10P, CAIE A,ONEPR4 + CAIE A,ONEFLS + BUG + JRST .+1] + SKIPE UMAPS(U) + PUSHJ P,MPLDZ + CAMN U,PCLUSR + SKIPG PCLDBM + JRST URET2 + SKIPL PCLNXT + JRST URPCL1 +URET2: SKIPE LSWPR(U) + BUG + JUMPN U,URETC + MOVEI T,0 ;RESTORE SYS JOB EXEC LSWPR + EXCH T,SLSWPR + MOVEM T,LSWPR +URET1: CONSO PI,1 + BUG ;RETURNING TO USER MODE WITH CLOCK OFF +IFN KA10P,[ + MOVEI U,0 + XCTR XBR,[BLT U,U] ;RESTORE USERS ACS FROM USERS SHADOW 0-17 +] ;KA10P + JRST ULEAVE + +URETC: REPEAT NULBLK/2,[ + SKIPN CONC LSWB,\<2*.RPCNT>,+1(U) + SKIPE CONC LSWB,\<2*.RPCNT+1>,+1(U) + BUG +] + REPEAT NULBLK&1,[ + SKIPE CONC LSWB,\,+1(U) + BUG +] + JRST URET1 + +URPCL1: SKIPN LSUUO(U) + JRST URET2 ;DIDN'T REALLY MISS MARK (DUE TO FINSET) + SETOM PCLNXT ;MISSED MARK, REINITIALIZE + SETZM PCLL + SETZM PCLHSH + JRST URET2 + +UUOTRO: MOVE T,FORTY + JRST UUOH1 + +USRIOT: MOVSI T,(UIOT) ;I/O INST TURNS INTO PSEUDO UUO TO DISPATCH ON + JRST ILLOP1 + +IFE KA10P,[ + +;HANDLE UUOS EXECUTED FOR TRAPS (PDL OV, ARITH OV, ONE PROCEED). +;MOST ARE AS USUAL, BUT OPCODE 0 IORM'S ADDRESS INTO PIRQC. +;NOTE: LOSER IS NOT PERMITTED TO USE OPCODE 0 - SEE USTR1I, ETC. + +MUUOTR: UUOSAV + MOVE T,FORTY + TLNE T,-1 + JRST MUUOT1 ;IF OPCODE ISN'T 0, TREAT UUO NORMALLY (STARTING A + ; ONE PROCEED) + MOVSI A,%PSTR1+%PSTR2 + ANDCAB A,UUOH ;TURN OFF TRAP FLAGS, GET PC + TRNN T,%PIARO + JRST MUUOT2 + TLNE A,%PCFOV ;DISTINGUISH FIXED AND FLOATING OVERFLOW. + TLO T,(%PIFOV) +MUUOT2: MOVE A,MSKST(U) + IOR A,[BADBTS] + AND T,A ;INTS SETTING WHICH AREN'T DISABLED + IORM T,PIRQC(U) + SKIPN PICLR(U) + TDZA A,A + SETCM A,IDF1(U) + IOR A,[BADBTS] ;MASK FOR INTS WHICH AREN'T DEFERRED + TDNE T,A + JRST ONEPR1 ;TAKE INT + JRST URET ;IGNORE INT + +MUUOEX: BUG AWFUL,[MUUO IN EXEC MODE, PC=],OCT,EPT+425 + ;UUO IN EXEC MODE NOT IN SYS JOB + +LUUOEX: 0 + BUG AWFUL,[LUUO IN EXEC MODE,PC=],OCT,LUUOEX + +ILLTRP: 0 + BUG AWFUL,[TRAP IN EXEC MODE,PC=],OCT,ILLTRP +] ;IFE KA10P + +IFN KA10P,[ +EBLK +60H: 0 ;TRAPS FROM 60 +BBLK +60H0: UUOSAV ;IF WE LOSE PROCESSOR HERE, 60 GETS COPIED INTO 40, + ; 60H IS COPIED INTO UUOH, AND UPC GETS MOVED INTO + ; UUOH0. +60HE: CONO PI,CLKOFF + MOVE T,60H + MOVEM T,UUOH + MOVE T,60 + MOVEM T,FORTY + CONO PI,CLKON + JRST MUUOT1 +] ;KA10P + +;COME HERE FROM UEXIT WHEN USER IS BEING PCLSR'ED +; KA10 - ALL USER ACS ARE IN MACHINE ACS AND IN UUOACS +; KL10 & KS10 - ALL USERS ACS ARE IN AC BLOCK 1 + +ONEFLS: CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + SYSCTX + MOVE U,USER ;GET INDEX OF CURRENT USER +ONEPR2: SKIPE T,RPCL(U) ;SKIP IF NO RPCLSRING OCCURING + JRST ONEFL2 ;RPCLSRING GOING ON +ONEPR1: MOVE U,USER ;GET INDEX OF CURRENT USER + CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + SKIPE LSWPR(U) + JRST 4,. + MOVEI T,AC0S(U) ;PUT USER ACS INTO SWAP OUT ACS + XCTR XBR,[BLT T,AC17S(U)] + MOVE T,UUOH + MOVEM T,UPC(U) ;SIMULATE JRST 2,@UUOH +IFN KA10P, MOVE T,[JRST 2,@UUOH] +IFE KA10P,[ + MOVSI T,(JRST 2,@) + HRRI T,UUOH +] ;IFE KA10P + MOVEM T,UEXIT ;RESTORE UEXIT + USRCTX + MOVE U,USER ;AS IF HAD RETURNED TO USER THEN CLKBRK + ;EXCEPT THAT AC'S ARE ALREADY STORED IN AC0S + JRST UFL6 ;RESCHEDULE, ETC + +ONEFL2: JUMPG T,[JRST 4,.] ;LOSEY LOSEY (SHOULD NOT TRY TO EXIT WHILE TRYING TO RPCLSR SOMEONE) + MOVE A,FLSINS(T) ;GET FLSINS OF USER SUPPOSEDLY RPCLSRING YOU + SUBI A,RPCL(T) ;HIS FLSINS SHOULD BE A SKIPE OF HIS RPCL + CAME A,[SKIPE] ;SKIP IF HE HAS THE RIGHT FLSINS + JRST 4,. ;LOSEY LOSEY + CLEARM FLSINS(T) ;ASSURE NO INTERRUPT + SETZM RPCL(U) ;ACS IN UUO ACS CLOCK OFF + AOS USTP(U) ;STOP SELF + SETZM RPCL(T) ;UNHANG LOSER RPCLSR'ING YOU + JRST ONEPR1 + +;ROUTINES TO GIVE THE RUNNING JOB AN INTERRUPT AND ABORT THE CURRENT INSTRUCTION + +TTYLOS: SKIPA T,[%PITTY] ;JOB WHOSE %TBINT IS SET TRIED TO USE ITS TTY WHEN DIDN'T OWN IT +IOADC: MOVEI T,%PIMPV ;I/O UUO MEMORY PROTECT VIOLATION + JRST UUOERR + +ABREAK: MOVEI T,%PIBRK ;.BREAK - INTERRUPT TO SUPERIOR +ILLOP4: IORM T,PIRQC(U) + JRST ONEPR1 + + RADIX 10. +IOCERF: ;ADDRESS OF FIRST IO CHANNEL ERROR +ZZ==NIOTER +IFG ZZ-9,ZZ==9 +REPEAT ZZ,CONC IOCER,\.RPCNT+MIOTER,: JSP T,IOCERX +IFG NIOTER-9,[REPEAT NIOTER-9,CONC IOCR,\.RPCNT+MIOTER+9,: JSP T,IOCERX +] +IFN 0, IOCER1: IOCER2: IOCER3: IOCER4: IOCER5: IOCER6: IOCER7: ;FOR @ +.ALSO IOCER8: IOCER9: IOCR10: IOCR11: IOCR12: IOCR13: IOCR14: + + RADIX 8 +IOCERX: CONSZ PI,77400 + JRST 4,. ;ERR WITH PI IN PROGRESS + SUBI T,IOCER9-9+1 + MOVE U,USER + HRRZ TT,UUAC(U) + DPB TT,[BCHPTR] ;STORE LAST CHNL IN ERROR + ADD TT,U + DPB T,[330600,,IOCHST(TT)] +IOCERR: MOVEI T,%PIIOC + JRST UUOERR + +AILUUO:: +ILUUO: SKIPA T,[%PIILO] ;ILLEGAL SYSTEM UUO +TRPDEV: ;ATTEMPTED USE OF TRAP DEVICE +USRTRP: MOVSI T,(%PITRP) ;SYSTEM UUO IN TRAP MODE + +UUOERR: MOVE U,USER + IORM T,PIRQC(U) ;GIVE USER INT BIT +IOADCR: MOVE U,USER + MOVE T,OPTION(U);PC CLOBBERED TO HERE IF MPV IN EXEC MODE - INTR OUT OF UUO + TLNN T,%OPOPC ;UNLESS USER HAS SAID NOT TO, + AOS UUOH ;UNDO SOS THAT PCLSR'ING WILL DO; PC SHOULD END UP -> AFTER UUO. +UUOER2: CONO PI,CLKON ;THERE HAD BETTER BE A CLASS 1 OR 2 INT. PENDING. + MOVE P,USRPDL(U) + SETZM SCHMNY ;CAUSE FULL SCHEDULE SO INTERRUPT WILL BE SEEN + JFCL ; (IT'S A CROCK TO HAVE TO DO THIS, BUT HARD TO FIX) + PUSHJ P,UFLS ;LET THE INTERRUPT PCLSR US. + JRST 4,. + +UUOER1: MOVE U,USER ;UUOERR ASSUMING %OPOPC + IORM T,PIRQC(U) + JRST UUOER2 + +IFN KA10P,[ +ILEXPF: CONO PI,CLKOFF ;GET HERE AFTER EXEC PAGE FAULT TAKEN ON XCTRI + SPM UPGML(U) + MOVSI A,1770 ;CLEAR FAULT REASON BITS + ANDCAM A,UPQUAN(U) + LPMR UPGML(U) + JRST ILUUO +] ;KA10P +IFE KA10P, ILEXPF==ILUUO ;NO CLEANUP NECESSARY + +;UUO DISPATCH + +;AT DISPATCH TIME, P HAS UPDL, C HAS RH OF 40 +;R HAS AC FIELD OF UUO, U HAS USER INDEX + +UUODSP: SETZ AIOT ;SETZ FLAGS UUO'S TO REFLECT TO USER WHEN %OPDEC OPTIONS + SETZ AOPEN ;IN EFFECT. THEY ARE THE UUOS WHICH OVERLAP DEC + AOPER + ACALL + AUSET + ABREAK + ASTATUS + SETZ AACCESS + SETZ AUIOT +IF2,IFN _-27.+UUODSP-.+1,.ERR LOSE AT UUODSP + +;.CALL IOT +NIOT: CAIL W,3 ;SET IOTBTS TO USER'S 3RD ARG, OR TO 0. + SETZ C, + MOVEM C,IOTBTS(U) + HRRZ C,B ;ADDRESS OF 2ND ARG + SKIPGE SYSCVL(U) + SKIPA C,[SETZ] ;USING OUTPUT ARG INSTEAD OF INPUT, FOR UNIT INPUT MODE + CAIL W,2 + AOSA (P) ;GOING TO SUCCEED NOW + JRST OPNL30 ;NOT ENOUGH ARGS + JRST AIOT1 + +;.IOT +AIOT: SETZM CTLBTS(U) + SETZM IOTBTS(U) + ADDI R,IOCHNM(U) ;GET IOCHNM WD ADDR IN R. +AIOT1: MOVE A,U + IDIVI A,LUBLK + SKIPE B + BUG + HLRZ A,(R) ;PICK UP LEFT HALF (DEVICE DEPENDENT) + HRRZ B,(R) ;PICK UP RIGHT HALF (INDEX INTO IOTTB, ETC.) + MOVE D,IOTTB(B) ;GO TO ROUTINE FOR PARTICULAR DEV AND MODE + TLNE D,%IOTOT+%IOTBK+%IOTSP ;BUT FOR "NORMAL" UNIT MODE INPUT, SPECIAL: + JRST (D) + XCTR XRW,[MOVES (C)] ;MAKE SURE XCTR XW, BELOW WON'T PCLSR. + PUSH P,C + PUSHJ P,(D) ;CALL IOT ROUTINE, EXPECTING VALUE IN W. +AIOT3: JRST AIOT2 ;NOTE AIOT3 MAY BE CHECKED FOR ON PDL. + JRST AIOT2 + +AIOT2: POP P,C + SKIPGE C + SKIPA A,W ;RETURNING IN NEW SYSTEM-CALL STYLE + UMOVEM W,(C) + POPJ P, + +;RANDOM ACCESS + +AACCES: HRRZ A,UUAC(U) + UMOVE B,(C) + MOVE T,['ACCESS] + MOVEM T,LSCALL(U) ;IN CASE PASSED TO JOB DEVICE + MOVEI W,2 + PUSHJ P,NACCES + JRST IOCER8 ;FOR .ACCESS, SIGNAL FAILURE WITH IOC ERROR. + POPJ P, ;ONLY POSSIBLE FAILURE IS CHANNEL NOT OPEN. + +NACCES: MOVEI T,AIOCAL ;GET ,, IN R + MOVSI J,NACCE1 + JRST CHNDCD + +NACCE1: TLNN R,%CLSQ\%CLSU\%CLSFU + JRST OPNL34 + HRRM B,IOCHST-IOCHNM(R) ;STORE USR .ACCESS POINTER + TLNN R,%CLSQ + JRST POPJ1 ;NOT DISK + HLRZ I,(R) + MOVEM B,QRADAD(I) ;STORE ACCESS POINTER FOR DSK + MOVSI D,%QAACC + IORM D,QSRAC(I) ;SET ADR HAS BEEN HACKED FLAG + JRST POPJ1 + +;SIOT SYMBOLIC SYSTEM CALL - IOT A STRING. +; 1ST ARG CHANNEL NUMBER. +; 2ND ARG BYTE POINTER +; 3RD ARG STRING LENGTH +; 4TH (OPTIONAL) ARG DEVICE-INDEPENDENT CONTROL BITS +; CTLBTS DEVICE DEPENDENT CONTROL BITS + +NSIOT: TLNN B,1000 ;OBJECT IF B.P. OR COUNT IS IMMEDIATE. + TLNE C,1000 + JRST OPNL33 + CAIGE W,4 + SETZ D, + MOVEM D,IOTBTS(U) + MOVE D,IOTTB(H) + TLNE D,%IOTBK+%IOTSP ;SIOT ALLOWED ONLY ON UNIT MODE CHANNELS. + JRST OPNL12 ;"MODE NOT AVAILABLE". + XCTR XRW,[MOVES A,(B)] ;ENSURE BYTE POINTER WRITABLE + TLNE A,(@) ;CAN'T HACK BYTE POINTER WITH INDIRECT ADDRESSING + JRST OPNL33 ;MEANINGLESS ARGS + TLNE A,17 + PUSHJ P,NSIOT9 ;HACK INDEXING + XCTR XRW,[MOVES A,(C)] ;ENSURE BYTE COUNT WRITABLE + JUMPLE A,POPAJ1 ;0 BYTES TO BE XFERED => SUCCEED IMMEDIATELY. + HLRZ A,(R) + MOVE TT,B ;IN CASE SPECIAL ROUTINE WANTS TO CALL SIOKT + TLNE D,%IOTBP ;IF THERE'S A SPECIAL DEVICE ROUTINE FOR SIOT, + JRST -1(D) ;GO TO IT. +;THIS CALL IS LEGAL AND ORDINARY. LOOP, CALLING THE UNIT MODE ROUTINE. +NSIOT1: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D ;PUT ALL IMPORTANT INFO ON STACK FOR MAIN LOOP + HRRZS (P) ;TO LOOK AT. + PUSH P,R + TLNN D,%IOTOT + JRST NSIOIL ;INPUT AND OUTPUT PART HERE +NSIOOL: UMOVE A,@-3(P) + IBP A ;THIS HAIR IS TO AVOID INCREMENTING THE USER'S COPY + UMOVE D,(A) ;OF THE BYTE POINTER BEFORE THE BYTE HAS BEEN + HRRI A,D ;FINALLY TAKEN WITH NO POSSIBILITY OF PCLSR'ING OUT. + LDB D,A ;CAN'T USE XCTR XR,[LDB D,A] BECAUSE ON THE KA10 + MOVE C,[SETZ D] ;THAT WOULD USE THE LOSER'S AC A. + MOVE R,(P) + MOVE A,-4(P) ;SET UP ARGS FOR IOT ROUTINE; C HAS ADDR OF VALUE. + PUSHJ P,@-1(P) ;CALL THE IOT ROUTINE. + XCTR XRW,[IBP @-3(P)] ;NOW STEP THE B.P. AND COUNT. + XCTR XRW,[SOS A,@-2(P)] + JUMPG A,NSIOOL + JRST NSIOTX + +NSIOIL: UMOVE A,@-3(P) + IBP A ;MAKE SURE NO FAULT IDPB'ING THE BYTE + XCTR XRW,[MOVES (A)] + MOVE R,(P) ;NOW GET THE ARGS FOR THE IOT ROUTINE, + MOVE A,-4(P) + PUSHJ P,@-1(P) ;AND CALL IT, WITH VALUE COMING IN W. + JRST NSIOI3 ;NO SKIP => WE WIN. + JRST NSIOTX ;1 SKIP => THERE'S NO INPUT; RETURN WITHOUT STEPPING B.P. + ;2 SKIPS => THIS BYTE IS THE LAST ONE AVAILABLE. + XCTR XBYTE,[IDPB W,@-3(P)] + XCTR XRW,[SOS @-2(P)] + JRST NSIOTX + +NSIOI3: XCTR XBYTE,[IDPB W,@-3(P)] + XCTR XRW,[SOS A,@-2(P)] + JUMPG A,NSIOIL +NSIOTX: SUB P,[5,,5] + JRST POPJ1 + +NSIOT9: EXCH A,R ;INDEXED BYTE POINTER, EVAL INDEX ONCE AND WRITE BACK + PUSHJ P,ASCIND + EXCH A,R + UMOVEM A,(B) + POPJ P, + ; +; ROUTINES TO SIMULATE SOME I/O INSTRUCTIONS WHEN EXECUTED BY USER + +IFE KS10P,[ ; KS10 will never have any devices so we might as well punt + ; this sham right from the start. + +AUIOT: MOVE I,FORTY ;GET I/O INST + ANDI R,7 ;GET IOT TYPE FIELD + LDB J,[320700,,FORTY] + LDB D,[420200,,IOTTYP(R)] + JRST @IOTTYP(R) ;DISPATCH ON TYPE + +IOTTYP: 000000,,IOTTY3 ;BLKI + 000000,,IOTTY2 ;DATAI + 200000,,IOTTY3 ;BLKO + 200000,,IOTTY2 ;DATAO + 600000,,IOTTY2 ;CONO + 400000,,IOTTY2 ;CONI + 400000,,IOTTY1 ;CONSZ + 400000,,IOTTY1 ;CONSO + +IOTTY1: CAIN J,177 ;IF EQ INST WAS 7777XX,,XXXXXX + JRST ILUUO ;USER HAS EXECUTED A SMALL NEGATIVE NUMBER + JRST IOTTY2 + +IOTTY3: +IFN KL10P,[ + MOVE C,DCHNTB(J) + TRNE C,10000 + JRST IOTTY2 ;SPECIAL BLKI THAT IS TREATED LIKE DATAI +] + TLO I,40 ;BLOCK TYPE, TURN ON BIT TO CONVERT TO UNIT + UMOVE C,(I) ;GET BLOCK POINTER + ADD C,[1,,1] ;ADVANCE + TLNE C,-1 ;SKIP IF OVERFLOW + AOS (P) ;CAUSE RETURN TO SKIP + UMOVEM C,(I) ;STORE BACK + HRR I,C ;MODIFY INST ADR TO RH OF BLOCK POINTER +IOTTY2: SKIPL C,DCHNTB(J) + JRST IOTTYA + LSH C,19.(D) + SKIPL C + JRST ILUUO +IOTTYB: XCTR XRW,I ;DO IOT + POPJ P, ;NORMAL RETURN + JRST POPJ1 ;IOT SKIPPED RETURN + +IOTTYA: SKIPGE DCHNTC(J) + JRST ILUUO ;SUSPICIOUS DEVICE + JRST IOTTYB + +] ;IFE KS10P + +IFN KS10P, AUIOT==:ILUUO ; For now. + +IFN 0,[ ; Simple IO instruction simulating for the KS should look + ; like this. Unfortunately XCTR XRW,[APRID 100] clobbers + ; exec location 100. Further investigation is needed + ; before figuring out how to deal with this. + +AUIOT: LDB R,[271500,,FORTY] ; Get opcode and AC. + CAIE R,APRID_-27 ; For now this is the only instruction we + ; simulate on the KS + JRST ILUUO + XCTR XRW,FORTY ; Do it + POPJ P, ; Return normally + JRST POPJ1 ; It skipped (well APRID can't, but perhaps + ; someday something else will) +] ;IFN 0 + +SUBTTL .SUSET, .USET, .CALL USRVAR + +;COMMON CODE FOR USRVAR, TTYVAR, ETC. SYMBOLIC SYSTEM CALLS +;PUSHJ P,VARCAL WITH FIRST ARG DECODED INTO H,I,J,R; B,C,W,U SET UP AS IN .CALL +;NOTE B IS A POINTER TO THE SECOND ARG (IN BLOCK MODE IS WRITTEN BACK) +;POPJS (OR PUSHJS IN THE CASE OF BLOCK MODE) BACK WITH E CONTAINING +;VARIABLE SPEC, D INPUT DATA, W INSTRUCTION TO HACK IT (0 TO READ INTO A, +;OTHERWISE OP D, WITH RH CLEAR WHERE OP IS MOVEM, ANDCAM, ADDM, ETC.) + +VARCAL: HRRZ E,B ;USE 2ND ARG AND NUM OF ARGS TO DETERMINE TYPE OF OPERATION + TLNE B,1000 + JRST VARCA1 ;IMMEDIATE 2ND ARG + UMOVE E,(B) ;GET VALUE OF 2ND ARG + TLC E,777000 + TLCN E,777000 + JRST VARCBL ;BLOCK MODE (2ND ARG LOOKS LIKE AOBJN POINTER) +VARCA1: EXCH D,C ;D GETS 3RD ARG, INPUT DATA + CAIL W,4 + JRST VARCA2 ;JUMP IF IMMEDIATE INSTRUCTION MODE + CAIGE W,3 ;SKIP IF WRITING + TDZA W,W ;W 0 FOR READING + MOVSI W,(MOVEM D,) ;SIMPLE CASE OF WRITING (SEE VARCBL FOR HAIR) + POPJ P, ;CALLER WILL DO OPERATION AND POPJ1 OR OPEN-LOSS + +VARCA2: ADD P,[2,,2] ;IMMEDIATE INSTRUCTION MODE. MAKE STACK SAME AS AT VARCAL. + TLNN C,-1 ;E HAS VARIABLE SPEC + MOVSS C ;C GETS INSTRUCTION + PUSHJ P,VARCA3 ;PERFORM THE INSTRUCTION + JRST POP3J1 ;TAKE GOOD RETURN FROM THE CALL + +VARCBL: PUSH P,J ;BLOCK MODE. SAVE J WHICH SOME SUSETS CLOBBER + PUSH P,B ;SAVE POINTER TO AOBJN POINTER TO SPEC,INSN PAIR LIST + XCTR XRW,[MOVES B,@(P)] ;GET AOBJN POINTER, TEST WRITEABILITY +VARCB1: UMOVE E,(B) ;GET VARIABLE SPEC + UMOVE C,1(B) ;GET "INSTRUCTION" + MOVE J,-1(P) ;GET DECODED FIRST ARG OR WHATEVER (SOME USRVAR ROUTINES CLOBBER J) + PUSHJ P,VARCA3 ;PERFORM THE INSTRUCTION + MOVE B,[2,,2] + XCTR XRW,[ADDB B,@(P)] ;ADVANCE AOBJN POINTER + JUMPL B,VARCB1 ;MORE STUFF TO DO + JRST POP3J1 ;POINTER COUNTED OUT, POP B, J, PUSHJ TO VARCAL + +VARCA3: EXCH C,R ;HERE TO PERFORM INSTRUCTION IN C + TLNE R,37 + PUSHJ P,ASCIND ;EVALUATE INSTRUCTION'S EFFECTIVE ADDRESS + EXCH C,R + LDB B,[410300,,C] ;GET MAJOR PDP10 OPCODE CLASS + JRST @.+1(B) + VARCBE ;0 UUO ILLEGAL + VARCBE ;1 FP/BYTE ILLEGAL + VARCB2 ;2 MOVE/ADD/SUB + VARCBE ;3 CAM ETC. RESERVED FOR .HANGING IN THE FUTURE + VARCB4 ;4 BOOLE + VARCBE ;5 HWT ILLEGAL + VARCB6 ;6 TEST + VARCBE ;7 IOT ILLEGAL + +VARCBE: SUB P,[4,,4] ;POP PUSHJ TO VARCA3, B, J, PUSHJ TO VARCAL + JRST OPNL33 ;BAD ARG + +VARCB6: TLNE C,006000 ;TEST INSTRUCTION - SKIP IF NO SKIP + JRST VARCBE ;SKIPPING TESTS RESERVED FOR FUTURE .HANGS + TLNE C,010000 ;SKIP IF IMMEDIATE + XCTR XR,[SKIPA D,(C)] + HRRZ D,C + TLNE C,001000 ;SKIP IF TDX OR TRX + MOVSS D ;TSX OR TLX + LDB C,[370200,,C] ;GET MODIFICATION TYPE + XCT (C)[JRST VARCBE ;NO MODIFICATION OBVIOUSLY AN ERROR + MOVSI W,(ANDCAM D,) ;TXZ + MOVSI W,(XORM D,) ;TXC + MOVSI W,(IORM D,)] ;TXO + JRST VARCBA + +VARCB4: TLNE C,002000 ;BOOLEAN INSTRUCTION - OK IF RESULT TO AC + JRST VARCBE + TLNN C,001000 ;SKIP IF IMMEDIATE + XCTR XR,[SKIPA D,(C)] + HRRZ D,C + HLLZ W,C ;SET UP OPCODE TO HAVE A+M EXCHANGED + TLZ W,003777 ;AND RESULT TO BE SENT TO MEMORY + TLCE W,030000 + TLCE W,030000 + TLC W,030000 + TLO W,(<002000,,> D,) + JRST VARCBA + +VARCB2: SETZB W,D ;MOVE/ADD/SUB GROUP + HLRZ B,C + CAIN B,(MOVEM) + JRST VARCBB ;SIMPLY READING + TLNE C,002000 + JRST VARCBE ;RESULT MUST BE TO AC + TLZ C,(0 17,) ;CHANGE AC FIELD TO D + TLO C,(0 D,) + TLNE C,060000 ;SKIP IF MOVE GROUP + JRST VARCB5 + XCTR XR,C ;FETCH OPERAND, DO MODIFICATION IF CALLED FOR (MOVN) + MOVSI W,(MOVEM D,) ;OPERATION WILL BE SIMPLE STORE + JRST VARCBA + +VARCB5: TLC C,070000 + TLCE C,070000 + JRST VARCBE ;NOT ADD/SUB + XCTR XR,C ;ADD TO/SUBTRACT FROM ZERO IN D + MOVSI W,(ADDM D,) ;DROP INTO VARCBA + +;HERE WITH E, W, D ALL SET UP FOR WRITING. +VARCBA: PUSHJ P,@-3(P) ;CALL BACK TO CALLER OF VARCAL + JRST POP4J ;LOST, POP PUSHJ TO VARCA3, B, J, VARCAL, TAKE ERR RETURN + POPJ P, ;WON, RETURN FROM VARCA3 + +;HERE WITH E AND W SET UP FOR READING. +VARCBB: PUSH P,C ;SAVE ADDRESS TO BE READ INTO + XCTR XRW,[MOVES (C)] ;NO FAULT. INSURANCE OF WRITEABILITY. + PUSHJ P,@-4(P) ;GET VALUE OF VARIABLE INTO A + JRST POP5J ;LOST POP C, VARCA3, B, J, VARCAL, TAKE ERR RETURN TO USER + POP P,C ;WON, STORE RESULT INTO USER + UMOVEM A,(C) + POPJ P, ;AND RETURN FROM VARCA3 + +USETBT: 420200,,USETL(E) ;BYTE POINTER TO UENTRY FIELD A + 400200,,USETL(E) ; " B + 200200,,USETL(E) ; " C + 160200,,USETL(E) ; " D + +USETRL: 221600,,USETL(E) ;BYTE POINTER TO UENTRY FIELD E + 001600,,USETL(E) ; " F + +;IN EACH UENTRY ENTRY: A IS THE METHOD FOR USET READ +; B IS THE METHOD FOR SUSET READ +; C IS THE METHOD FOR USET SET +; D IS THE METHOD FOR SUSET SET +; E & F ARE USED BY THE METHODS AS LISTED BELOW +;METHOD 0 = ILLEGAL MODE +;METHOD 1 = USE F AS RELATIVE LOC OF VAR +;METHOD 2 = USE E AS ROUTINE TO TRANSFER TO +;METHOD 3 = USE F AS ROUTINE TO TRANSFER TO + +DEFINE UENTRY A,B,C,D,E,F + ZZ==.SUCCESS + A_20+B_16+E,,C_20+D_16+F + IF2 [ + IFN 777774&,[PRINTX /UENTRY A,B,C,D TOO BIG +/] IFN 740000&,[PRINTX /UENTRY E,F TOO BIG +/] IFSE [E!F],[PRINTX /UENTRY E,F NULL +/] ] + .SUCCESS==ZZ + TERMIN + +USETL: UENTRY 1,1,2,0,UPCSET,UPC-USRSTG ;.UPC + UENTRY 1,1,1,1,,VALUE-USRSTG ;.VAL + UENTRY 3,3,2,2,USTTY,URTTY ;.TTY + UENTRY 1,1,0,0,,FLSINS-USRSTG ;.FLS + UENTRY 1,1,0,2,UUNAME,UNAME-USRSTG ;.UNAME + UENTRY 1,1,2,2,UJNAME,JNAME-USRSTG ;.JNAME + UENTRY 1,1,2,2,USMASK,MSKST-USRSTG ;.MASK + UENTRY 1,1,2,0,USTOP,USTP-USRSTG ;.USTP + + UENTRY 1,1,2,2,USPIRQ,PIRQC-USRSTG ;.PIRQC + UENTRY 2,2,0,0,UGSUPR, ;.INTB + UENTRY 1,1,2,2,USMEMT,HUSRAD-USRSTG ;.MEMT + UENTRY 1,1,0,0,,SV40-USRSTG ;.SV40 +REPEAT 2,UENTRY 1,1,2,2,IAPIRQ,PIRQC-USRSTG ;.IPIRQ/.APIRQ + UENTRY 1,1,2,2,USYNST,USYSNM-USRSTG ;.SNAME + UENTRY 1,1,2,2,UPISET,PICLR-USRSTG ;.PICLR + + UENTRY 2,2,3,3,URMAR,USMAR ;.MARA + UENTRY 1,1,1,1,,UMARPC-USRSTG ;.MARPC + UENTRY 1,1,0,0,,SUUOH-USRSTG ;.UUOH + UENTRY 2,2,0,0,UINDEX, ;.UIND + UENTRY 1,2,0,0,UTRNTR,UTRNTM-USRSTG ;.RUNT + UENTRY 1,1,2,2,USMSK2,MSKST2-USRSTG ;.MSK2 + UENTRY 1,1,2,2,USIFPI,IFPIR-USRSTG ;.IFPIR + UENTRY 1,1,0,0,,APRC-USRSTG ;.APRC + + UENTRY 3,3,0,0,,URCNSL ;.CNSL + UENTRY 2,0,3,0,RUTRAP,SUTRAP ;.UTRP +REPEAT 2,UENTRY 1,1,2,2,IAIFPI,IFPIR-USRSTG ;.IIFPI/.AIFPI +REPEAT 2,UENTRY 1,1,2,2,IAMASK,MSKST-USRSTG ;.IMASK/.AMASK +REPEAT 2,UENTRY 1,1,2,2,IAMSK2,MSKST2-USRSTG ;.IMSK2/.AMSK2 + + UENTRY 3,3,2,2,UJPCS,UJPCR, ;.JPC + UENTRY 2,2,0,0,UROPC, ;.OPC + UENTRY 1,1,1,1,,RTIMER-USRSTG ;.RTMR + UENTRY 1,1,1,1,,HSNAME-USRSTG ;.HSNAME +;IFN KL10P,UENTRY 1,1,1,1,,ULSPBR-USRSTG ;.LSPBR +;.ELSE UENTRY 1,1,1,1,,SRN3-USRSTG + UENTRY 2,2,3,3,RUBCHN,SUBCHN, ;.BCHN + UENTRY 2,2,0,0,MPVARD ;.MPVA +REPEAT 2,UENTRY 1,1,2,2,IADF1,IDF1-USRSTG ;.IDF1, .ADF1 + +REPEAT 2,UENTRY 1,1,2,2,IADF2,IDF2-USRSTG ;.IDF2, .ADF2 + UENTRY 1,1,2,2,USDF1,IDF1-USRSTG ;.DF1 + UENTRY 1,1,2,2,USDF2,IDF2-USRSTG ;.DF2 + UENTRY 1,1,1,1,,OPTION-USRSTG ;.OPTION + UENTRY 1,1,1,1,,40ADDR-USRSTG ;.40ADDR +IFE N11TYS, UENTRY 1,1,1,1,,SRN3-USRSTG ;.TVCREG - JOB'S CONSOLE REGISTER CONTENTS +IFN N11TYS, UENTRY 1,1,1,2,STVCRG,TVCREG-USRSTG + UENTRY 1,1,1,1,,TTSTSV+2-USRSTG ;.TTST + + UENTRY 1,1,1,1,,TTSTSV-USRSTG ;.TTS1 + UENTRY 1,1,1,1,,TTSTSV+1-USRSTG ;.TTS2 + UENTRY 1,1,1,1,,UWHO1-USRSTG ;.WHO1 + UENTRY 1,1,1,1,,UWHO2-USRSTG ;.WHO2 + UENTRY 1,1,1,1,,UWHO3-USRSTG ;.WHO3 + UENTRY 3,3,0,0,,RUSUPP ;.SUPPRO +IFN KA10P, UENTRY 2,2,0,0,URTR1I ;.TR1INS +IFE KA10P, UENTRY 1,1,1,1,,TR1INS-USRSTG +IFN KA10P, UENTRY 2,2,0,0,URTR2I ;.TR2INS +IFE KA10P, UENTRY 1,1,1,1,,TR2INS-USRSTG + +IFE KL10P,[ +REPEAT 4,UENTRY 1,1,0,0,,SRN3-USRSTG +] ;IFE KL10P +IFN KL10P,[ + UENTRY 1,0,0,0,,MBOXCT-USRSTG ;.MBOX + UENTRY 1,0,0,0,,MBOXCT+1-USRSTG ;.MBO1 + UENTRY 1,0,0,0,,EBOXCT-USRSTG ;.EBOX + UENTRY 1,0,0,0,,EBOXCT+1-USRSTG ;.EBO1 +] ;KL10P + UENTRY 1,1,1,1,,XUNAME-USRSTG ;.XUNAME (USER'S REAL NAME) + UENTRY 1,1,1,1,,XJNAME-USRSTG ;.XJNAME + UENTRY 1,1,1,1,,SRN4-USRSTG ;.FTL1 + UENTRY 1,1,1,1,,SRN5-USRSTG ;.FTL2 + UENTRY 1,1,1,1,,PAGRAN-USRSTG ;.PAGRANGE + UENTRY 1,1,1,1,,PAGAHD-USRSTG ;.PAGAHEAD + UENTRY 2,2,3,3,URSERV,USSERV ;.SERVER +MXVAL==.-USETL +EXPUNGE UENTRY ;NO MORE UENTRY'S + +MXVAL2==.RADIX 2,CONC [.LENGTH/]\MXVAL-1,/ ;BASE 2 LOG OF TABLE SIZE + +;SIXBIT TABLE OF USER VARIABLE NAMES. MUST BE IN CORRECT ORDER, +;SAME AS SYSCTB. + +USETTB: SIXBIT/ADF1/ + SIXBIT/ADF2/ + SIXBIT/AIFPIR/ + SIXBIT/AMASK/ + SIXBIT/AMSK2/ + SIXBIT/APIRQC/ + SIXBIT/APRC/ + SIXBIT/BCHN/ + SIXBIT/CNSL/ + SIXBIT/DF1/ + SIXBIT/DF2/ + SIXBIT/EBO1/ + SIXBIT/EBOX/ + SIXBIT/FLS/ + SIXBIT/FTL1/ + SIXBIT/FTL2/ + SIXBIT/HSNAME/ + SIXBIT/IDF1/ + SIXBIT/IDF2/ + SIXBIT/IFPIR/ + SIXBIT/IIFPIR/ + SIXBIT/IMASK/ + SIXBIT/IMSK2/ + SIXBIT/INTB/ + SIXBIT/IPIRQC/ + SIXBIT/JNAME/ + SIXBIT/JPC/ + SIXBIT/MARA/ + SIXBIT/MARPC/ + SIXBIT/MASK/ + SIXBIT/MBO1/ + SIXBIT/MBOX/ + SIXBIT/MEMT/ + SIXBIT/MPVA/ + SIXBIT/MSK2/ + SIXBIT/OPC/ + SIXBIT/OPTION/ + SIXBIT/PAGAHE/ + SIXBIT/PAGRAN/ + SIXBIT/PICLR/ + SIXBIT/PIRQC/ + SIXBIT/RTMR/ + SIXBIT/RUNT/ + SIXBIT/SERVER/ + SIXBIT/SNAME/ + SIXBIT/SUPPRO/ + SIXBIT/SV40/ + SIXBIT/TR1INS/ + SIXBIT/TR2INS/ + SIXBIT/TTS1/ + SIXBIT/TTS2/ + SIXBIT/TTST/ + SIXBIT/TTY/ + SIXBIT/TVCREG/ + SIXBIT/UIND/ + SIXBIT/UNAME/ + SIXBIT/UPC/ + SIXBIT/USTP/ + SIXBIT/UTRP/ + SIXBIT/UUOH/ + SIXBIT/VAL/ + SIXBIT/WHO1/ + SIXBIT/WHO2/ + SIXBIT/WHO3/ + SIXBIT/XJNAME/ + SIXBIT/XUNAME/ + SIXBIT/40ADDR/ +IFN .-USETTB-MXVAL, .ERR USETTB INCONSISTENT WITH USETL +REPEAT 1_--1, -1 ;PAD TO POWER OF 2 WITH PLUS INFINITY + +;THE FOLLOWING TABLE IS PARALLEL TO USETTB AND GIVES THE NUMERIC USET CODE +;WHICH SHOULD BE IN THE RANGE 0 - 77 OR 600 AND UP. +USETBN: 47 ;.ADF1 + 51 ;.ADF2 + 33 ;.AIFPI + 35 ;.AMASK + 37 ;.AMSK2 + 15 ;.APIRQ + 27 ;.APRC + 44 ;.BCHN + 30 ;.CNSL + 52 ;.DF1 + 53 ;.DF2 + 73 ;.EBO1 + 72 ;.EBOX + 3 ;.FLS + 76 ;.FTL1 + 77 ;.FTL2 + 43 ;.HSNAME + 46 ;.IDF1 + 50 ;.IDF2 + 26 ;.IFPIR + 32 ;.IIFPI + 34 ;.IMASK + 36 ;.IMSK2 + 11 ;.INTB + 14 ;.IPIRQ + 5 ;.JNAME + 40 ;.JPC + 20 ;.MARA + 21 ;.MARPC + 6 ;.MASK + 71 ;.MBO1 + 70 ;.MBOX + 12 ;.MEMT + 45 ;.MPVA + 25 ;.MSK2 + 41 ;.OPC + 54 ;.OPTION + 601 ;.PAGAHE + 600 ;.PAGRAN + 17 ;.PICLR + 10 ;.PIRQC + 42 ;.RTMR + 24 ;.RUNT + 602 ;.SERVER + 16 ;.SNAME + 65 ;.SUPPRO + 13 ;.SV40 + 66 ;.TR1INS + 67 ;.TR2INS + 60 ;.TTS1 + 61 ;.TTS2 + 57 ;.TTST + 2 ;.TTY + 56 ;.TVCREG + 23 ;.UIND + 4 ;.UNAME + 0 ;.UPC + 7 ;.USTP + 31 ;.UTRP + 22 ;.UUOH + 1 ;.VAL + 62 ;.WHO1 + 63 ;.WHO2 + 64 ;.WHO3 + 75 ;.XJNAME + 74 ;.XUNAME + 55 ;.40ADDR +IFN .-USETBN-MXVAL, .ERR USETBN INCONSISTENT WITH USETL + +;.CALL USRVAR HACK USER VARIABLES. +;ARG 1 - SPEC +;ARG 2 - AOBJN PNTR FOR BLOCK MODE OR 0,,USER-VAR-NUMBER OR SIXBIT/USER-VAR-NAME/ +;ARG 3 - DATA IF WRITING AND NOT IN BLOCK MODE. (OPTIONAL) +;ARG 4 - IMMEDIATE INSTRUCTION, OVERRIDES ARG 3. (OPTIONAL) +;VAL 1 - DATA IF READING AND NOT IN BLOCK MODE + +NUSRVA: MOVE J,A ;DECODE FIRST ARG + JSP T,NCORUI ;GET JOB AND LOCK ITS DIELOK + JRST NUSRV0 ;DEFINITELY WRITEABLE + JSP T,NCORWR ;NOT SURE, CHECK FURTHER + TLO J,(SETZ) ;SET WRITE PROTECT BIT +NUSRV0: +IFN PDP6P,[ + TRNE J,400000 + PUSHJ P,NULSET +] + PUSHJ P,NUSRV5 ;DO IT + POPJ P, ;LOST + JRST LSWPJ1 ;WON, UNLOCK DIELOK AND TAKE SUCCESS RETURN + +NUSRV5: PUSHJ P,VARCAL ;DECODE ARGS, HACK BLOCK MODE, SET E, W, D. +NUSRV3: SETZB B,I ;ENTER HERE FROM .USET AND .SUSET + TLNN E,-1 ;NOW DECODE USER VARIABLE SPEC + JRST NUSRV1 ;JUMP IF OLD STYLE NUMERIC SPEC +REPEAT MXVAL2,[ ;SIXBIT SPEC LOOK UP IN TABLE + CAML E,USETTB+1_(B) + ADDI B,1_ +] + CAMN E,USETTB(B) + CAIL B,MXVAL + JRST OPNL11 ;ILLEGAL USER VARIABLE NAME + MOVE E,USETBN(B) ;TRANSLATE TO NUMERIC SPEC +NUSRV1: JUMPE W,NUSRV2 ;READING + JUMPL J,OPNL31 ;WRITING AND WRITE PROTECTED + MOVEI I,2 ;MAGIC INDEX 1.2=R/W 1.1=OTHER/SELF +NUSRV2: CAIN U,(J) + IORI I,1 +IFN PDP6P,[ + HRRE B,J + AOJE B,PDPPMT ;USER IS PDP6 +] + CAIL E,600 + JRST [ SUBI E,500 + JRST NUSRV4] + CAIL E,100 + JRST AUSET2 ;100 TO 577 ARE .IOC, .IOS, .IOP, .PMAP VARS. +NUSRV4: CAIL E,MXVAL ;DETECT USET CODE BEYOND 6XX MAXIMUM. + JRST OPNL11 + LDB B,USETBT(I) ;GET METHOD BITS + SOJL B,OPNL12 ;VARIABLE NOT AVAILABLE THIS MODE (WRITE PROTECT?) + SOJL B,AUSVAR ;SIMPLE VARIABLE + LDB B,USETRL(B) ;GET ADDRESS OF ROUTINE TO CALL + HRRZ A,J ;SOME ROUTINES WANT USER INDEX IN A + JUMPE W,(B) + CAMN W,[MOVEM D,] + JRST (B) + PUSH P,D ;READ/ALTER/REWRITE + PUSH P,E + PUSH P,I + PUSH P,W + PUSH P,J + TRZ I,2 ;FIRST READ IT + MOVEI W,0 + PUSHJ P,NUSRV4 + JRST POP5J ;READ LOST + POP P,J + POP P,W + POP P,I + POP P,E + POP P,D + HRRI W,A + XCT W ;MODIFY THE VALUE IN A + MOVE D,A + MOVSI W,(MOVEM D,) + JRST NUSRV4 ;THEN WRITE IT BACK + +; +; .SUSET [N,,LOC] ;SAME AS .USET (SEE BELOW) BUT REFERS TO SELF +; +ASUSET: HRRZ J,U ;JOB TO BE HACKED IS SELF + SETZM UUAC(U) ;IF ERROR, RETURN LOSS IN .IOS+0 + JRST AUSET0 + +; ;IF N&200000=1, BLOCK MODE +; .USET CH,[N,,LOC] ;IF N&400000=0, READS USER VAR SPECIFIED BY REST OF N + ; FOR INFERIOR OR FOREIGN USER OPEN ON CHANNEL CH + ; INTO USER LOCATION LOC + ;IF N&400000.NE.0, SETS USER VAR SPECIFIED BY REST OF N + ; FOR DIRECTLY INFERIOR USER OPEN ON CHANNEL CH + ; FROM USER LOCATION LOC +AUSET: MOVE J,R ;DECODE AC FIELD AS CHANNEL NUMBER + PUSHJ P,AUSETJ + JRST IOCER7 ;USR OP CHNL DOES NOT HAVE USR OPEN +AUSET0: XCTR XR,[HRRZ B,(C)] ;GET ADDRESS READING INTO OR WRITING FROM + XCTR XR,[HLRZ E,(C)] ;GET VARIABLE AND DIRECTION + TRNE E,200000 + JRST ABUSET ;BLOCK MODE + TRZN E,400000 + JRST AUSET1 ;JUMP IF READING + JUMPL J,IOCER7 ;WRITE PROTECT VIOLATION + MOVSI W,(MOVEM D,) ;FLAG WRITING + UMOVE D,(B) ;GET DATA TO WRITE + PUSHJ P,NUSRV3 ;DO THE WRITE + JRST ILUUO ;LOST + POPJ P, + +;BLOCK-MODE .USET +ABUSET: TRNE E,400000 + TLOE J,(MOVE) ;SET BLOCK BIT + JRST ILUUO ;BLOCK IN BLOCK LOSES + UMOVE Q,(C) ;GET AOBJN PTR AGAIN +ABUST2: UMOVEM Q,(C) ;STORE AWAY UPDATED POINTER + PUSH P,C + PUSH P,J + MOVE C,Q + PUSHJ P,AUSET0 + POP P,J + POP P,C + UMOVE Q,(C) + AOBJN Q,ABUST2 + POPJ P, + +AUSET1: MOVEI W,0 ;FLAG READING + XCTR XRW,[MOVES (B)] ;ENSURE WRITEABILITY + PUSH P,B + PUSHJ P,NUSRV3 ;GET VALUE OF VARIABLE INTO A + JRST ILUUO ;LOST + POP P,J +APTUAJ: UMOVEM A,(J) + POPJ P, + +;DECODE ARG FOR USET +AUSETJ: JSP T,NCRUI2 + JRST POPJ1 + JSP T,NCORWR + TLO J,(SETZ) + JRST POPJ1 + +AUSVAR: LDB C,USETRL+1 ;GET ADDRESS OF VARIABLE + ADDI C,USRSTG(J) + JUMPE W,[MOVE A,(C) + JRST POPJ1] + HRR W,C + XCT W + JRST POPJ1 + +IFN PDP6P,[ +PDPPMT: MOVEI A,%JSSIX#%JSNUM ;PDP6 HAS ONLY A FEW VARIABLES, WHICH ARE READ-ONLY + CAIN E,.RUIND + JRST POPJ1 + MOVEI A,LPDP6M*2000 ;FIXED MEM BOUND FOR PDP-6 + CAIN E,.RMEMT + JRST POPJ1 + JRST POPJ1 ;IGNORE OTHER VARIABLES +] + +;VARIABLES 100 - 577 (.IOC, .IOS, .IOP, .PMAP) +AUSET2: JUMPN W,OPNL31 ;JUMP IF TRYING TO WRITE + SUBI E,100 + CAIL E,40 + JRST AUSET4 ;>140=>.RIOP+M + TRZE E,20 + JRST AUSET3 ;117.RIOS+M + ADDI E,IOCHNM(J) ;77.RIOC+M +AUSETX: MOVE A,(E) ;GET VAR + JRST POPJ1 + +AUSET3: MOVE R,J ;INFERIOR USER INDEX + ADDI R,IOCHNM(E) ;GET CHANNEL POINTER + MOVE H,(R) + JRST NSTATUS ;DO A .CALL STATUS + +AUSET4: CAIL E,40+LUIOP ;COMPARE AGAINST LAST IO PDL LOC + JRST AUSET5 ;READ MAP ENTRY + ADDI E,SIOCHN-40(J) ;MAKE UP POINTER TO VAR + JRST AUSETX + +;USET VARIABLE 200+N -- READ MAP VARIABLE FOR PAGE N. +; (0 <= N < 400) E CONTAINS N+100. + +;VALUE OF MAP WORD READ: + +;4.9 - PAGE WRITEABLE. +;4.8 - PAGE EXISTS (IF THIS OFF, WHOLE WORD IS 0) +;4.7 - PAGE IS IN CORE. +;4.6 - PAGE IS PUBLIC (ANYONE CAN WRITE IT) + +;3.1 - 3.9 - # TIMES PAGE SHARED (LIKE CORTYP'S 4TH VALUE'S RH) +;2.1 - 2.9 - ABS PAGE # OR PAGE # IN NEXT SHARER +; (LIKE CORTYP'S 3RD VALUE) +;1.1 - 1.9 - 0 => ABS PAGE (OR NO PAGE, OF COURSE) +; -1 => UNSHARED PAGE, +; ELSE USR NUM. OF NEXT SHARER. + +AUSET5: CAIGE E,100 + JRST OPNL11 + PUSHJ P,SWTL + CIRPSW ;DON'T LET PAGE TABLES CHANGE. + MOVEI A,-100(E) ;PAGE NUMBER IN JOB. + PUSH P,J + PUSHJ P,NCORT0 ;PUT CORTYP'S VALUES IN A THRU D. + POP P,J + PUSHJ P,LSWPOP ;FREE CIRPSW. + ANDI B,777 ;CORTYP'S 2ND VALUE IN 1.1 - 1.9 + DPB C,[111100,,B] ;3RD VALUE IN 2.1 - 2.9 + TLO B,(D) ;4TH VALUE RH INTO 3.1-3.9 + LSH D,-20. + TLO B,(D) ;4TH VAL BITS 4.8-4.9 INTO 4.6-4.7 + IOR A,B ;TOGETHER WITH 1ST VALUE'S 4.8, 4.9. + JRST POPJ1 + +USTOP: AOS (P) ;GOING TO WIN + JUMPN D,1USTOP ;NONZERO VALUE => STOP THE JOB. + MOVE B,APRC(A) ;ZERO => START. + TLNE B,BULGOS ;BUT DON'T EVER START A JOB THAT'S BEING KILLED. + POPJ P, + JRST 1USTRT + +1USTOP: MOVNI D,1 ;SET TO STOP +1USTRT: PUSHJ P,RPCLSR ;STOP USER IN A + DPB D,[.BP BUSRC_22,USTP(A)] ;BUSRC +IFN SWPWSP,[ + EXCH U,A + PUSHJ P,LVLOAD + EXCH U,A +];SWPWSP + JRST UPCLSR + +;SET INFERIOR'S PC +UPCSET: PUSHJ P,RPCLSR ;STOP USER IN USER MODE + TLO D,%PCUSR ;BE SURE USER MODE IS ON IN NEW PC + TLZ D,BADPC ;BE SURE PRIVILEGED BITS ARE OFF + SKIPGE IOTLSR(A) ;SKIP UNLESS USER IS SUPPOSED TO BE IN IOT-USER MODE + TLO D,%PCUIO ;TURN ON IOT-USER MODE + MOVEM D,UPC(A) ;SET PC + PUSHJ P,UPCLSR ;RESTART + JRST POPJ1 + +UJPCS: CAIN U,(A) ;SET .JPC, WITH CARE IF SETTING OWN + SPM UPGML(U) + HRRM D,UPJPC(A) + CAIN U,(A) + LPMR UPGML(U) + JRST POPJ1 + +UJPCR: CAIN U,(A) ;READ .JPC: + SPM UPGML(U) ;IF READING ONE'S OWN, MAKE SURE IT'S UP TO DATE. + HRRZ A,UPJPC(A) + JRST POPJ1 + +IFN KA10P,[ +UROPC: HLLZ A,UPOPC(J) + LSH A,5 + HRR A,UPOPC(J) + JRST POPJ1 +] ;KA10P +IFE KA10P, UROPC: JRST OPNL12 ;.OPC NOT SUPPORTED ON KL AND KS ((CAN'T + ; USE == DUE TO FWD REF)) + +IFN N11TYS,[ ;SET OWN TV CONSOLE REGISTER +STVCRG: MOVEM D,TVCREG(U) ;ENABLE TVCREG TO BE SWAPPED IN AND OUT OF HARDWARE + JUMPL D,POPJ1 ;IF TURNING ON; OR, IF TURNING OFF, ALL DONE + SKIPGE TT11P ;ALLOWED TO TOUCH HARDWARE? + SKIPE TEN11F + CAIA + MOVEM D,400000+TTR10*2000 ;UPDATE REG IN HARDWARE + MOVEM D,TVCREG(U) ;AND UPDATE AGAIN IN SOFTWARE IN CASE CLOBBERED AT SSTVR2 + JRST POPJ1 +] + +IFE KS10P,[ ; KS10 doesn't have a MAR and it never will... + +;READ MAR +URMAR: MOVE A,UPMAR(J) +IFN KA10P, TLZ A,777770 +IFN KL10P, LDB B,[270400,,A] +IFN KL10P, HRL A,MARPTB(B) + JRST POPJ1 + +;SET MAR +USMAR: CONO PI,CLKOFF ;TURN OFF CLOCK INTERRUPTS + CAMN J,USER + SPM UPGML(J) ;STORE PG VARIABLES IF HACKING CURRENT USER +IFN KA10P,[ + TLZ D,777770 + TLO D,4 ;SET USER MODE +] ;KA10P +IFN KL10P,[ + LDB B,[220400,,D] + HLL D,MARPTB(B) +] ;KL10P + MOVEM D,UPMAR(J) + CAMN J,USER + LPMR UPGML(J) ;USE LPMR BECAUSE KL10 DOESN'T HAVE VANILLA LPM + JRST CLKOJ1 + +IFN KL10P,[ ;MAR PERMUTATION TABLE. MAYBE CAN DO BETTER???? ***** + +MARPTB: 0 1, 0 ;OFF ;NONE (EXEC) + 0 11, 0 ;FETCH ;NONE (USER) + 0 3, 2 ;WRITE ;WRITE(EXEC) + 0 17, 6 ;ANY ;WRITE (USER) + 0 1, 10 ;OFF ;READ (EXEC) + 0 11, 14 ;FETCH ;READ (USER) + 0 3, 12 ;WRITE ;NOT FETCH (EXEC) + 0 17, 16 ;ANY ;NOT FETCH (USER) + 0 5, 1 ;READ ;FETCH (EXEC) + 0 15, 5 ;READ+FETCH ;FETCH (USER) + 0 7, 13 ;NOT FETCH ;NOT READ (EXEC) + 0 13, 17 ;NOT READ ;NOT READ (USER) + 0 5, 11 ;READ ;READ+FETCH (EXEC) + 0 15, 15 ;READ+FETCH ;READ+FETCH (USER) + 0 7, 3 ;NOT FETCH ;ANY (EXEC) + 0 13, 7 ;NOT READ ;ANY (USER) +] ;KL10P +] ;IFE KS10P + +IFN KS10P,[ +URMAR: +USMAR: JRST OPNL12 +] ;KS10P + +RUSUPP: HRRE A,SUPPRO(J) ;READ SUPERIOR'S USER INDEX + JUMPL A,POPJ1 ;-1 => TOP LEVEL +UINDEX: IDIVI A,LUBLK ;GET INDEX NUMBER + JRST POPJ1 ;GIVE TO USER + +;READ OWN RUN TIME +UTRNTR: CONO PI,CLKOFF +IFN KA10P,[ + SPM UPGML(U) + LDB A,[2300,,UPQUAN(U)] + LSH A,-2 ;SIMULATE 4.069 USEC CLOCK +] ;KA10P +IFN KL10P,[ + SKIPL MTRUSR ;SKIP IF PERFORMANCE METER AVAILABLE + JRST [ RMBOXC A ;REQUIRES AC ORDER - A,B,C,D,E + DSUB A,STMBOX + DMUL A,KLMBCC ;BECAUSE DMUL PRODUCES FOUR WORD RESULT + REBOXC D + DSUB D,STEBOX + DADD B,D + DMUL B,KLEBCC + MOVE A,D + JRST UTRNT1 ] + RPERFC A + DSUB A,STPERF + DIVI A,50.*4096. +UTRNT1: +] ;KL10P +IFN KS10P,[ + SPM UPGML(U) + LDB A,[400400,,UPQUAN(U)] ; 3.9 USEC CLOCK +] ;KS10P + ADD A,UTRNTM(U) + JRST CLKOJ1 + +;SET JOB'S TTYTBL (.TTY VARIABLE). +USTTY: CONO PI,CLKOFF ;PREVENT TIMING ERROR. + HLLZ E,TTYTBL(J) ;GET CURRENT VALUE + XOR E,D ;GET WHICH BITS USER WANTS TO CHANGE + AND E,[%TBNVR+%TBINT+%TBWAT+%TBOUT+%TBINF+%TBIIN+%TBOIG,,] ;GET BITS USER IS ALLOWED TO CHANGE + TRNE I,1 + TLZ E,%TBWAT ;THESE BITS CAN BE ALTERED ONLY BY THE SUPERIOR + XORM E,TTYTBL(J) ;ALTER THE USER-CONTROLLED BITS WITHOUT WRITING THE OTHERS. + JRST CLKOJ1 + +;READ JOB'S TTYTBL (.TTY) VARIABLE +URTTY: CONO PI,CLKOFF + HRRZ A,TTYTBL(J) + SKIPGE TTYTBL(J) + IDIVI A,LUBLK + HLL A,TTYTBL(J) + JRST CLKOJ1 + +;READ JOB'S .CNSL VARIABLE - TTY# OF TREE'S CONSOLE +URCNSL: MOVE A,UTMPTR(J) + SUBI A,USRRCE + CAIL A,NCT + SUBI A,NCT+2 ;DISOWNED -1 SYS -2 + JRST POPJ1 + +UJNAME: JUMPE D,OPNL33 ;SET INFERIOR'S JNAME + CAME D,[SIXBIT/PDP6/] + CAMN D,[SIXBIT/PDP10/] + JRST OPNL33 ;CHANGING TO ILLEGAL NAME + CAIN I,3 ;.SUSET? + JRST UJNAMS ;YES... + PUSHJ P,RPCLSR + PUSHJ P,UJNAMU ;IS NEW JNAME UNIQUE? + JRST UJNAMG ;NO + MOVEM D,JNAME(A) ;YES + CONO PI,CLKON + PUSHJ P,UPCLSR + JRST POPJ1 + +UJNAMU: MOVE B,UNAME(A) + MOVEI E,0 + CONO PI,CLKOFF +UJNAM1: CAME B,UNAME(E) + JRST UJNAMF + CAMN D,JNAME(E) + POPJ P, +UJNAMF: ADDI E,LUBLK + CAMGE E,USRHI + JRST UJNAM1 + JRST POPJ1 + +UJNAMG: PUSHJ P,UPCLSR + CAME A,E + JRST OPNL13 ;DUPLICATE NAME + JRST CLKOJ1 ;WASN'T REALLY CHANGING THE NAME + +UUNAME: HLRE I,D ;SET OWN UNAME + AOJE I,OPNL33 ;CHECK FOR ILLEGAL ___nnn UNAME + SKIPA I,U +UJNAMS: SETO I, ;SET OWN JNAME + JUMPE D,OPNL33 ;CHECK FOR EVIL NAMES + CAME A,U ;SELF? + BUG ;SOMETHING SCREWED + SKIPL SUPPRO(U) + JRST OPNL40 ;MUST BE TOP LEVEL + CONO PI,CLKOFF ;TURN CLOCK OFF NOW SO WE DON'T GET REOWNED OR SOMETHING + SKIPL I + SKIPA C,JNAME(U) ;CHANGING UNAME, KEEPING JNAME + SKIPA C,UNAME(U) ;VICE VERSA + EXCH D,C ;NOW C=UNAME, D=JNAME + MOVEI E,0 ;CHECK FOR DUPLICATE NAMES +UUNAM0: SKIPE UNAME(E) + CAMN E,U ;ALLOW SETTING TO SAME NAME AS BEFORE + JRST UUNAM1 + HRRZ A,SUPPRO(E) + CAMN C,UNAME(E) + CAME D,JNAME(E) + CAMN A,I ;JOB CAN'T HAVE INFERIORS IF SETTING UNAME + JRST OPNL13 ;OR DUPLICATE U-JNAME IF SETTING EITHER +UUNAM1: ADDI E,LUBLK + CAMGE E,USRHI + JRST UUNAM0 + CAMN C,UNAME(U) + CAME D,JNAME(U) + SKIPA A,D ;D GETS CLOBBERED + JRST CLKOJ1 ;THE NAMES WEREN'T ACTUALLY CHANGED! (SYNCOM DOES IT). + CAME C,UNAME(U) ;IF NOT LOGGED IN, AND CHANGING UNAME, + SKIPGE TTYTBL(U) ; AND CONSOLE-CONTROLLED, + JRST UUNAM3 + HLLO J,UNAME(U) + AOJN J,UUNAM2 + AOS SUSRS ;DISGUST! SHOULD BE USING LOGIN +UUNAM2: HRRZ T,TTYTBL(U) + HRLI T,[ASCIZ / CHUNAM /] + PUSHJ P,SGWAIT ;REQUEST SYSTEM JOB TO PRINT OUR MSG + MOVEM C,SLGIV+2 ;INCLUDE NEW UNAME AS SECOND NAME +UUNAM3: PUSHJ P,LOGUPD ;CHARGE OLD NAME FOR USAGE SO FAR + MOVEM C,UNAME(U) ;THEN SWITCH NAMES + MOVEM A,JNAME(U) + PUSHJ P,DMNPLI ;LOG BACK IN UNDER NEW NAMES + JRST CLKOJ1 + +;WAIT FOR SLGIV VARIABLES TO BECOME FREE, AND REQUEST THE +;SYSTEM JOB TO PROCESS THEM. TAKES STRING,,TTY IN T, AND +;PLACES UNAME(U) IN SLGIV, AND T INTO SLGIV+1. THE CALLER +;IS RESPONSIBLE FOR FILLING IN SLGIV+2 + +SGWAIT: PUSH P,T + MOVSI T,SCLLGI ;SOMEBODY ELSE IS USING THOSE VARIABLES + PUSHJ P,CWAIT ;WAIT FOR THE SYSTEM JOB TO FINISH WITH + TDNE T,SUPCOR ;THEM. + IORM T,SUPCOR ;REQUEST THE SYSTEM JOB TO PRINT OUR MSG + POP P,SLGIV+1 ;STRING,,TTY # + MOVE T,UNAME(U) ;STORE AWAY THE UNAME + MOVEM T,SLGIV + POPJ P, + +RUTRAP: LDB A,[430100,,UTRAPM(J)] ;GET SPECIAL TRAP MODE INDICATOR + JRST POPJ1 + +SUTRAP: DPB D,[430100,,UTRAPM(J)] ;SET " " " " + JRST POPJ1 + +IFN KA10P,[ +URTR1I: SKIPA A,[0,,%PIARO] ;READ "TRAP 1 INSTRUCTION" FOR KA-10 +URTR2I: MOVEI A,%PIPDL ;TRAP 2 + JRST POPJ1 +] ;KA10P + +;SET MEMORY BOUND +USMEMT: CAMN U,A + JRST USMEM2 + PUSHJ P,RPCLSR + MOVSI B,BSSTP + IORM B,USTP(A) + PUSHJ P,UPCLSR +USMEM2: ADDI D,1777 + LSH D,-10. + MOVE B,D + MOVEM A,SRN5(U) ;ARGUMENT TO NCORFS + PUSHJ P,LOSSET + NCORFS ;CLEARS BSSTP IN USTP(A). + EXCH U,A + PUSHJ P,ACORE + JRST OPNL33 ;LOST + EXCH U,A + JRST LSWPJ1 + +;SET SYSTEM NAME (ZERO IGNORED) +USYNST: SKIPE D + MOVEM D,USYSNM(J) + JRST POPJ1 + +;SET INFERIOR'S INTERRUPT MASK +USMASK: SKIPA E,[2] ;MOVEM +IAMASK: ANDI E,1 ;ANDCAM OR IORM + ANDCM D,[VBDBTS] ;BITS FOR CLASS 1 INTS CAN'T BE CHANGED. + XCT (E)[ IORB D,MSKST(A) + ANDCAB D,MSKST(A) + MOVEM D,MSKST(A)] +IFN KA10P,[ + MOVEI B,440+APRCHN ;NOW UPDATE JOB'S APRC VARIABLE. + TRNE D,%PIARO + TRC B,60 + TLNE D,(%PIFOV) + TRC B,600 + HRRM B,APRC(A) + TRNE I,1 + CONO @APRC(A) +] ;KA10P +IFE KA10P, PUSHJ P,TRINST + JRST UPISE1 + +IFE KA10P,[ +;SET THE AROV AND PDLOV TRAP INSNS ACCORDING TO WHETHER THE +;INTERRUPTS ARE ENABLED; BUT DON'T OVERRIDE AN EXPLICIT SPECIFICATION +;BY THE USER, WHICH IS ANYTHING OTHER THAN 0 OR (CAI) IN THE LH. + +TRINST: MOVE D,MSKST(A) + MOVSI B,(CAI) ;CAI IS FASTER THAN JFCL - NO AC DECODE + TDNE D,[%PIFOV+%PIARO] ;AND OVERFLOW GOES OFF A LOT + MOVEI B,%PIARO + HLRZ C,TR1INS(A) + SKIPE C + CAIN C,(CAI) + MOVEM B,TR1INS(A) +; MOVSI B,(CAI) ;THESE LINES COMMENTED OUT TO MAKE +; TRNE D,%PIPDL ; PDL OVERFLOW CLASS 2 INSTEAD OF CLASS 3 + MOVEI B,%PIPDL + HLRZ C,TR2INS(A) + SKIPE C + CAIN C,(CAI) + MOVEM B,TR2INS(A) + POPJ P, +] ;IFE KA10P + +;SET INFERIOR'S PI IN PROGRESS FLAG +UPISET: ASH D,-35. ;SHIFT SIGN BIT TO BOTTOM BIT + MOVEM D,PICLR(A) ;SET VARIABLE +;COME HERE WHEN ANY INTERRUPT VARIABLE'S VALUE IS CHANGED +;BY A .USET OR .SUSET; TAKE ANY INTS THAT ARE NOW PENDING. +UPISE1: HRRZ A,J ;IAMASK, ETC. MODIFY A. RESTORE IT. + AOS (P) ;GOING TO WIN + TRNN I,1 ;SKIP IF A SUSET + JRST APISE6 + JRST APISE1 ;SEE IF SHOULD REINTERRUPT + +IAMSK2: ADDI A,MSKST2-IDF1 +IADF1: ADDI A,IDF1-IDF2 +IADF2: ADDI A,IDF2-PIRQC ;IORM OR ANDCAM INTO IDF2. +IAPIRQ: ADDI A,PIRQC-IFPIR +IAIFPI: ANDI E,1 ;GET USET PARITY (0=IORM, 1=ANDCAM) + XCT IAINS(E) ;DO APPRO OP + JRST UPISE1 + +IAINS: IORB D,IFPIR(A) ;SET BITS + ANDCAB D,IFPIR(A) ;FLUSH BITS + +USMSK2: ADDI A,MSKST2-IDF1 ;SET .MSK2, ETC. +USDF1: ADDI A,IDF1-IDF2 +USDF2: ADDI A,IDF2-PIRQC +USPIRQ: ADDI A,PIRQC-IFPIR +USIFPI: MOVEM D,IFPIR(A) + JRST UPISE1 + +;.RBCHN, .SBCHN READ/SET NUMBER OF LAST CHANNEL ON WHICH ERROR OCCURRED +RUBCHN: LDB A,[BCHPTR#(A#U)] + JRST POPJ1 + +SUBCHN: DPB D,[BCHPTR#(A#U)] + JRST POPJ1 + +;GET INT BIT +UGSUPR: HLLZ A,SUPPRO(J) + JRST POPJ1 + +;SAVE AWAY MA (HIGH BITS) ON LAST MPV OR WIRO +;CALLED FROM CLKBRK, DONT CLOBBER A OR D + +MPVMAS: +IFN KA10P,[ + HLRZ T,UPJPC(U) + LSH T,10. ;HIGH BITS ONLY ON KA +] ;KA10P +IFE KA10P, HRRZ T,UPFW(U) + HRRM T,IOTLSR(U) + POPJ P, + +;.RMPVA READ VIRTURAL PAGE # (8 BITS) OF LAST MPV OR WIRO + +MPVARD: HRRZ A,IOTLSR(J) + JRST POPJ1 + +;.RSERVER Read server user number, or -1 if none. +URSERV: SKIPL A,SERVER(J) + IDIVI A,LUBLK + JRST POPJ1 + +;.SSERVER Set server user number, or clear if negative. +; (To prevent timing screws, you should really use the SSERVE call to set +; this variable, but for debugging convenience...) +USSERV: IMULI D,LUBLK + SKIPGE D + SETOI D, + MOVEM D,SERVER(J) + JRST POPJ1 + +SUBTTL USER INSTRUCTION HANG ROUTINE (.HANG) + +; .HANG was rewritten by Alan Feb 87: +; +; The general theory is that .HANG should behave -exactly- like JRST .-1 as +; much as possible. Thus, it is considered to make sense to put any +; skipping or jumping instruction before a .HANG. We are always careful to +; return from the .HANG by jumping to the previous instruction, so any side +; effects (such as clearing bits or incrementing accumulators or memory) are +; always performed, and jumps will be correctly taken. +; +; There are two ways to leave a .HANG, either the job can get PCLSR'ed, or +; the awaited condition can become true. We arrange for -both- cases to +; return the job to the previous instruction by SOSing UUOH -once- before +; calling UFLS, and once more if UFLS returns. +; +; As an additional feature, .HANG with a non-zero accumulator behaves like +; the disjunction of ordinary .HANG and .SLEEP, allowing the user to do a +; timeout. The accumulator should initially contain an argument, as for +; .SLEEP, that indicates when .HANG should timeout. In that case only, +; .HANG returns to the following instruction and the designated accumulator +; will contain zero. If such a .HANG is interrupted, or if it returns +; because the awaited condition is now true, that accumulator will contain +; the correct negative number indicating the absolute time it would have +; timed out. +; +; Accepted instructions are: +; Any CAI, CAM, JUMP, SKIP, AOJ, AOS, SOJ, or SOS class instruction. +; Any test instruction. +; JFFO. +; JFCL with 0 in the AC field. +; Or an XCT that eventually fetches one of the above. +; +; As special cases SKIPA 0, and CAIA 0, are taken to request a schedule, +; and JFCL 0, and SKIP 0, set %SWDSO. +; +; As before, it is a limitation that changes to memory referenced by .HANG +; when computing effective addresses and fetching XCT'ed instructions will +; not cause the job to wake up. But how could it be otherwise? Changes to +; the accumulators will of course cause the job to be PCLSR'ed. + +AHANG: MOVE R,UUOH + UMOVE R,-2(R) ; Get user's flush instruction + HRLOI A,377777 ; A: most positive fixnum + JUMPE J,AHANG2 ; No AC => timeout when hell freezes over + XCTR XR,[MOVN A,(J)] ; A: argument as for .SLEEP + JUMPG A,AHANG2 ; 'twas already neg., so wait 'til then + SUB A,TIME ; else compute time + UMOVEM A,(J) ; store back negative for PCLSRing + MOVN A,A ; A: time to wait for +AHANG2: PUSHJ P,ASCIND ; Compute E for instruction + HLRZ C,R ; C: Opcode and AC + CAIE C,(JFCL) + CAIN C,(SKIP) + JRST AHANGI ; User might be waiting for a while + CAIE C,(SKIPA) + CAIN C,(CAIA) + JRST AHANGF ; User is just trying to cause a schedule + LSH C,-9 ; C: 9-bit opcode + CAIN C,XCT_-33 + JRST AHANG1 ; XCT - Go loop + CAIN C,JFFO_-33 + JRST AHANGO ; JFFO is like JUMPN + LSH C,-6 ; C: First 3 bits of opcode + CAIN C,CAI_-41 + JRST AHANGC ; CAI, CAM, JUMP, SKIP, AOJ, SOJ, AOS, SOS + CAIN C,TRN_-41 + JRST AHANGT ; Txxx +IFN KS10P, JRST ILUUO +IFE KS10P,[ +;CODE TO ALLOW CONSO, CONSZ AS .HANG INSTRUCTIONS + HLRZ C,R ;CHECK FOR CONSO, CONSZ + TRZ C,077477 + LDB B,[320700,,R] ;GET DEVICE CODE/4 + SKIPGE T,DCHNTB(B) + TRNE T,40000 + CAIE C,(CONSZ\CONSO) + JRST ILUUO ;UNRECOGNIZED INSTRUCTION, OR USER CONI NOT + ; ALLOWED + MOVEM R,EPDL(U) + MOVE T,A + SOS UUOH + PUSHJ P,AHANG9 + PUSHJ P,UFLS + JRST AHANGX + +AHANG9: XCT EPDL(U) + CAMGE T,TIME + AOS (P) + POPJ P, + +] ;IFE KS10P + +; XCT ? .HANG +AHANG1: PUSHJ P,OPBRK ; Don't let "XCT ." hang you up + UMOVE R,(R) ; Get new instruction + JRST AHANG2 ; And start over + +; CAI, CAM, JUMP, SKIP, AOJ, SOJ, AOS, SOS ? .HANG +AHANGC: TLNN R,040000 + JRST AHANG3 ; CAI, CAM, JUMP, SKIP + TLNN R,010000 + JRST AHANGJ ; AOJ, SOJ + TLNN R,020000 + SKIPA T,[-1] ; AOS: Compare with -1 + MOVEI T,1 ; SOS: Compare with 1 + TLZ R,770777 ; Clear all but last 3 bits of opcode + TLO R,(CAM T,) ; Build a CAM instruction + TLNE R,001000 ; With the opposite sense + TLC R,006000 + JRST AHANGM + +AHANG3: TLNN R,020000 + JRST AHANG4 ; CAI, CAM + TLNN R,010000 + JRST AHANGJ ; JUMP + TLZ R,(0 17,) ; SKIP + JRST AHANGM + +; JFFO ? .HANG +AHANGO: TLC R,(JFFO#JUMPN) +AHANGJ: HRRI R,AHANGX + JRST AHANGA + +; SKIPA ? .HANG -- just flush once (ignores timeout) +AHANGF: SOSA UUOH + SKIPA + PUSHJ P,UFLS + JRST AHANGX + +; JFCL ? .HANG -- hang infinitely (or until timeout) +AHANGI: MOVE B,TIME + ADDI B,60.*30. ; If sleeping for more than a minute + MOVSI C,%SWDSO ; Desire swap out + CAML A,B ; (just like .SLEEP) + IORM C,USWST(U) + SOS UUOH +AHANG5: MOVE T,A + CAML T,TIME + PUSHJ P,UFLS + JRST AHANGX + +; Txxx ? .HANG +AHANGT: TLZ R,060000 ; Make opcode be TRN or TDN series + TLNE R,010000 ; If TRN, only AC matters + JRST AHANGB ; TDN: Both AC and memory matter +; Wait for something that only references the user's accumulators. +; (Instruction in R might be some kind of jump to AHANGX.) +AHANGA: PUSHJ P,AHANGG ; Get contents of user's AC into T + SOS UUOH + XCT R ; Must try it once to prevent timing screw + JRST AHANG5 ; OK, wait forever for PCLSR + JRST AHANGX + +AHANG4: TLNN R,010000 ; If CAM, both AC and memory matter + JRST AHANGA ; CAI: Only AC matters +; Wait for something that references memory. +; (Instruction in R better not be a jump!) +AHANGB: PUSHJ P,AHANGG ; Get contents of user's AC into T +AHANGM: MOVEM R,EPDL(U) + SOS UUOH + TRNE R,-20 ; Memory reference really only AC? + JRST AHANG6 ; No, real memory, go wait + XCTR XRW,R ; Must try it once to prevent timing screw + JRST AHANG5 ; OK, wait forever for PCLSR + JRST AHANGX + + PUSHJ P,UHANG +AHANG6: PUSHJ P,UFLS +AHANGX: ;; Everyone exits here after SOSing UUOH once (before hanging). + ;; Thus we always exit to the previous instruction (just like being + ;; PCLSRed), unless we timeout instead. + CAMGE A,TIME ; Timeout? + JRST AHANGY ; Yes + SOS UUOH + POPJ P, + +AHANGY: XCTR XW,[SETZM (J)] ; Let user know we timed out + AOS UUOH ; And fall through instead of backing out + POPJ P, + +;.HANG flush instruction routine, called with PUSHJ only on clock level +UHANG: +IFE KS10P,[ + MOVEI TT,0 ; Save MAR word + EXCH TT,UPMAR(U) ; so will not MAR + LPMR UPGML(U) + MOVEM TT,UPMAR(U) ; Restore MAR +] ;IFE KS10P +IFN KS10P, LPMR UPGML(U) + MOVE TT,AC0S+A(U) + XCTRI XRW,EPDL(U) + CAMGE TT,TIME + AOS (P) ; Might be because location swapped out or + POPJ P, ; missing, but that's OK because we always + ; exit to the previous instruction! + +; Kind of like ASCIND for the accumulators... +AHANGG: LDB T,[270400,,R] + UMOVE T,(T) ; Get contents of AC from user + TLZ R,(0 17,) ; Clear out AC field in instruction + TLO R,(0 T,) ; Replace AC field with T + POPJ P, + +; Allow interrupt if being PCLSRed +OPBRK: PUSH P,T + MOVE T,UEXIT + CAMN T,[JRST ONEFLS] + PUSHJ P,UDELAY + POP P,T + POPJ P, + +SUBTTL .OPEN AND FRIENDS + +; +;.FDELE FILBLK ;DELETE OR RENAME FILE SPECIFIED AT FILBLK +; +AFDELE: SETZM UUAC(U) + UMOVE A,(C) ;GET DEVICE + MOVEI W,4 + DPB W,[OPNCOM,,A] ;SET OP TO SPECIFY AN .FDELE + JRST AFDEL1 +; +;OPEN SET UP AND DISPATCH +;3.1=0 => INPUT =1 OUTPUT +;3.2=0 => UNITS =1 BLOCK +;3.3=0 => ASCII =1 IMAGE +;4.9-4.7 OPERATION FIELD +; 0=> NORMAL READ OR WRITE +; 1=> WRITE OVER MODE +; 2=> MAKE LINK +; 4=> DELETE OR RENAME (INTERNAL) +; +;.OPEN CH,FILBLK ;OPEN FILE SPECIFIED AT FILBLK ON LOGICAL CHANNEL CH +; +AOPEN: ;C HAS EFF ADR OF UUO AND R ITS AC FIELD + ADDI R,IOCHNM(U) ;MAKE R POINT TO SPECIFIED I/O CHANNEL WORD + PUSH P,C + PUSHJ P,ACLOSE ;CLOSE PREV + POP P,C + UMOVE A,(C) ;GET DEV AND MODE BITS + LDB W,[OPNCOM,,A] + CAIN W,4 + JRST OPNL23 ;BARF IF TRY TO DELETE WITH .OPEN +AFDEL1: MOVEI TT,SRN3(U) ;MOVE 4TH-6HT ARGS + HRLI TT,3(C) ;TO SRN3 THRU SRN5 + MOVEI Q,3(TT) + XCTR XBR,[BLT TT,-1(Q)] + UMOVE B,1(C) ;GET 2ND, 3RG ARGS (FILENAMES) + UMOVE C,2(C) + MOVE D,USYSNM(U) ;USE DEFAULT SNAME. + HLRZ E,A ;GET MODE BITS. + HRLZI A,(A) ;LEFT-JUSTIFY DEVICE NAME. + SETZM EPDL(U) + SETZM EPDL3(U) +NOPNE: CAIN W,4 ;SKIP ON NOT .FDELE (ENTRY FOR NCALL TYPE OPEN, ETC COMMANDS) + SKIPN SRN3(U) ;SKIP ON RENAME + JRST AOPEN3 ;JUMP IF A .OPEN OR DELETING .FDELE + JUMPN B,AOPEN3 ;JUMP UNLESS RENAME WHILE OPEN. + MOVE TT,C ;GET CH ON WHICH FILE IS SUPPOSIDLY OPEN + TDNE TT,[-NIOCHN] ;SKIP IF CH LOGICALLY LESS THAN 20 + JRST OPNL14 ;BAD CHANNEL NUM + ADDI TT,IOCHNM(U) ;RELOCATE TO POINT TO CH WORD FOR USER + MOVE Q,(TT) ;GET CH WORD + JUMPE Q,OPNL44 ;CHNL NOT OPEN + HLRZ Q,CLSTB(Q) ;GET LEFT HALF OF CLOSE TABLE ENTRY FOR INDEX IN I/O CH WORD + TRNE Q,%CLSJI\%CLSJO + JRST JFDEL4 ;JOB DEVICE CHNL + TRNN Q,%CLSDO\%CLSQ ;SKIP IF A DIRECTORY DEVICE + JRST POPJ1 ;JUMP IF NOT DIRECTORY DEVICE + HLRZ J,(TT) ;PICK UP DEV CHNL NO + EXCH A,B ;PUT FN1, FN2 IN A, B. + EXCH B,C +IFN NUNITS,[ + TRNN Q,%CLSDO ;SKIP IF DEC TAPE + JRST NOPNE1 + MOVSI C,'UT0 ;GET DUMMY UT DEV NAME. + HRRZ I,UTTNO(J) ;GET POSSIBLE (?) TAPE NUM + TLO C,(I) ;STORE IN DEV NAME + MOVE TT,DVAUT ;WILL EXIT TO UTAPE OPEN RTN. + JRST OPEN2B +NOPNE1: +] + MOVSI C,'DSK ;NOT UT, MUST BE DSK. + MOVE TT,DVAQSK ;NOBODY ELSE HANDLES RENAME WHILE OPEN. + JRST OPEN2B + +AOPEN3: PUSHJ P,TRAN ;PERFORM I/O TRANSLATIONS + JRST OPNL3 ;TOO MANY TRANSLATIONS. + MOVEM D,USYSN1(U);SAVE TRAN'D SNAME FOR OPEN RTN. + PUSH P,A ;PUT NAMES ON STACK. + PUSH P,B + PUSH P,C + MOVSI B,-NDEVS ;LOAD LENGTH OF FIRST DEV NAME TABLE + CAME A,DEVTAB(B);SEARCH FIRST DEV NAME TABLE + AOBJN B,.-1 ;LOOP TILL FOUND OR COUNTED OUT + JUMPG B,OPEN1 ;JUMP IF NOT FOUND +OPEN2: MOVE TT,DEVADR(B) ;LOAD BITS,,OPEN-ROUTINE-ADDRESS +OPEN21: POP P,B ;UNSAVE SECOND FILE NAME + POP P,A ;UNSAVE FIRST FILE NAME + POP P,C ;UNSAVE DEVICE NAME + CAIN W,4 + JRST [ TLNN TT,%DVDEL + JRST OPNL34 ;DEVICE DOES NOT ALLOW DELETE + JRST OPEN2B ] + CAIN W,2 + JRST [ TLNN TT,%DVLNK + JRST OPNL34 ;DEVICE DOES NOT ALLOW LINK + JRST OPEN2B ] +OPEN2B: HRRZ D,E ;MODE BITS + EXCH E,C ;SAVE DEVICE IN E + HLL C,E ;SET UP OLD-STYLE C: MODE,,DEV + MOVSS C +; +;AT THIS POINT: A & B HAVE FILE NAMES, C HAS MAPPED DEV AND MODE BITS, D HAS MODE BITS, +;W HAS OPEN COMMAND, E HAS DEVICE NAME, TT HAS DEVADR WORD (BITS,,ROUTINE) +; + ROT D,-1 ;ROTATE IN/OUT BIT TO SIGN + CAIN W,4 ;SKIP IF NOT A .FDELE + TDZ D,[400000,,7] ;A .FDELE, MAKE LOOK LIKE OPEN FOR READ + PUSHJ P,FLDRCK + JRST OPEN2D ;NORMAL OPEN + JUMPL D,OPNL2 ;WRITING DIRECTORY? + JUMPN W,OPNL12 ;DELETING, RENAMING, LINKING, WRITING OVER DIRECTORY? + TLNE TT,%DVDIR + JRST (TT) ;OPEN DEVICE FOR DIRECTORY +;ASKING FOR DIR OF DEVICE SYSTEM DOESN'T HAVE DIR ROUTINE FOR. +;PASS IT OFF TO THE UNKNOWN-DEVICE HANDLER. + PUSH P,E ;PUSH DEVICE NAME + PUSH P,A ;PUSH FN1 + PUSH P,B ;PUSH FN2 + HLRZ E,C ;GET MODE BITS + JRST OPEN22 ;PASS TO UNKNOWN DEVICE JOB + +OPEN2D: TLNE TT,%DVIN + JUMPGE D,(TT) ;OPENING FOR INPUT AND DEVICE CAN DO INPUT + TLNE TT,%DVOUT + JUMPL D,(TT) ;OPENING FOR OUTPUT AND DEVICE CAN DO OUTPUT + JRST OPNL2 ;DEVICE DOESN'T GO THAT DIRECTION + +;CHECK FOR NUMBERED DEV +OPEN1: MOVE B,[-NDV1,,DVT1-DEVTAB] ;LOAD AOBJN POINTER WITH COUNT FOR 2ND DEV TABLE +OPEN1A: MOVEI I,0 ;INITIALIZE NUMBERED DEV NUM TO ZERO + MOVE D,[440600,,-2(P)] ;GET BYTE POINTER INTO DEV REQUESTED + MOVE C,[440600,,DEVTAB(B)] ;GET BYTE POINTER INTO CURRENT TABLE ENTRY +OPENA1: ILDB A,C ;GET CHAR FROM TABLE + ILDB J,D ;GET CHAR FROM DEV + JUMPE A,OPEN1B ;JUMP ON SPACE IN TABLE, "MATCHES" DIGIT IN DEV + CAIN A,(J) ;SKIP IF CHAR DIFFER + JRST OPEN1C ;SAME, TRY FOR NEXT CHAR +OPENZ1: AOBJN B,OPEN1A ;LOOP TO NEXT TABLE ENTRY OR COUNT OUT +;CHECK FOR NAMED SECONDARY PACK +;FIND THE ONE WITH THIS NAME AND THE BIGGEST QSFT. +;ASSUME THAT BY THE TIME WE GET HERE TUTS HAVE BEEN READ IN AND SO FORTH + SKIPE A,-2(P) ;GET DEVICE NAME AGAIN + CAMN A,[-1] ;0 OR -1 ARE NOT LEGAL PACK NAMES + JRST OPEN22 + MOVEI C,NQS-1 ;SEARCH NAMES OF SECONDARY PACKS + SETOB TT,I ;I BEST DRIVE SO FAR, TT BEST QSFT SO FAR +OPENZ2: CAMN A,QRESRV(C) + JRST [ CAML TT,QSFT(C) + JRST .+1 + MOVE TT,QSFT(C) + MOVE I,C + JRST .+1 ] + SOJGE C,OPENZ2 + MOVE TT,[%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,,QSKOB] + JUMPGE I,OPEN21 +; +;"UNKNOWN DEVICE" HANDLER. FOO DEVICE IS LOADED BY +;SYS;ATSIGN DEVICE FROM FILE DEVICE;JOBDEV FOO +; +OPEN22: POP P,EPDLT2(U) ;WHEN WE USE SYS:ATSIGN DEVICE AS A JOB DEVICE, + POP P,EPDLT1(U) ;SET UP THE "NAMES BEFORE LAST TRANSLATION" TO BE + POP P,EPDLT4(U) ;THE NAMES BEING USED, INCLUDING "FOO" AS THE DEVICE. + MOVE A,USYSN1(U) + MOVEM A,EPDLT3(U) + MOVSI C,'JOB + MOVE TT,DVAJOB ;DEVADR ENTRY FOR JOB: + MOVSI A,'SYS + MOVEM A,USYSN1(U) + MOVE A,['ATSIGN] + MOVE B,['DEVICE] + JRST OPEN2B + +OPEN1B: JUMPE J,OPEN1C ;JUMP IF DEV ARG EXHAUSTED + SUBI J,'0 ;CONVERT SIXBIT DIGIT TO NUMBER + JUMPL J,OPENZ1 ;JUMP IF TOO SMALL, NOT A DIGIT + CAILE J,9 ;SKIP IF LESS THAN 10. + JRST OPENZ1 ;LOSE, TRY NEXT + ASH I,3 ;MULTIPLY NUM SO FAR BY 8 + ADD I,J ;ADD NEW DIGIT +OPEN1C: TLNE C,770000 ;SKIP IF ALL SIX CHAR POSITIONS COMPARED + JRST OPENA1 ;GO TO NEXT POSITION + JRST OPEN2 + +NSOPEN: HRRZ R,A ;Args: 1 mode (LH) chnl (RH), 2 BP or aobjn -> block of BPs. + CAIL R,NIOCHN + JRST OPNL14 + ADDI R,IOCHNM(U) + PUSH P,A ;Save channel number. + PUSH P,B ;Save BP or BP block ptr. + PUSHJ P,CCLOSE + POP P,R ;Get back the BP or aobjn pointer. + MOVEM R,EPDL(U) ;Save where job device can get it. + PUSHJ P,FNPRS ;Parse into DEV, FN1, FN2, SNM in A, B, C, D. + MOVEM D,SRN3(U) ;Make symbolic open of network win using 5th arg as foreign host. + POP P,R ;Pop back channel number argument. + MOVE E,CTLBTS(U) + TSC E,E + TRZ E,-1 + XOR R,E + LDB E,[OPNCOM,,R] + CAIE E,2 + CAIN E,4 + JRST OPNL12 ;COMMAND CANT BE LINK OR FDELE FOR "NEW" CALL + HLRZ E,R + JRST NDEL1 + +;Given in R a BP into user memory, or an aobjn -> of BPs block in user memory, +;parse filenames into A, B, C, D. Clobbers Q, T, R, H, I. +FNPRS: SETZ Q, ;Guess that it is a BP, not a block of them. + SETZ A, ;Clear out the old-fashioned filename words. + SETZ B, + SETZ C, + SETZ D, + SETCM T,R ;Is our "BP" realy an aobjn pointer to fewer than 64 things? + TLNE R,-1 ;If LH is 0, treat as BP and replace with 440700 later. + TLNE T,777700 + JRST FNPRS8 + MOVE Q,R ;Put the aobjn pointer in Q and get the first BP in R. + UMOVE R,(Q) +FNPRS8: PUSHJ P,ASCIND +FNPRS7: PUSHJ P,FNPRS4 ; Read a sixbit word + JUMPL I,FNPRS9 ; Nothing there at all! + CAIN H,"; ; Directory? + JRST FNPRS0 ; Go do special hack + MOVEI I,B ; assume FN1 + SKIPE B ; unless we already have a FN1 + MOVEI I,C ; in which case assume FN2 + CAIN H,": + MOVEI I,A ; unless it was a device + SKIPN (I) ;Put it there, unless already something there. + MOVEM T,(I) + JUMPN H,FNPRS7 ;H=0 means end of last arg string. +FNPRS9: ;; Supply default values for all components except FN1. + SKIPN A + MOVSI A,(SIXBIT /DSK/) + SKIPN D + MOVE D,USYSNM(U) + SKIPN C + MOVSI C,(SIXBIT />/) + POPJ P, + +FNPRS0: SKIPN I,D + JRST FNPRS2 + LSH T,-6 + TLO T,(SIXBIT /./) +FNPRS1: LSH T,-6 + LSH I,6 + JUMPN I,FNPRS1 +FNPRS2: IOR D,T + JRST FNPRS7 + +;;; Extract in T the next SIXBIT word from user memory off bp in R, +;;; clobbering I (test 4.9 to see if there was no word read at all). +;;; Terminating character returned in H (0 means we got to the end of the +;;; string). Q should be an aobjn pointer to a block in user memory of +;;; additional BPs. +FNPRS4: SETZ T, + MOVE I,[440600,,T] +FNPRS6: PUSHJ P,FNPRS3 + JUMPE H,CPOPJ ; that was the end of the string + CAIE H,": + CAIN H,"; + JRST FNPRS5 ; done? + CAIN H,40 + JRST FNPRS5 ; done? + CAIN H,^Q + PUSHJ P,FNPRS3 + CAIL H,140 + SUBI H,40 + SUBI H,40 + TLNE I,770000 + IDPB H,I + JRST FNPRS6 + +FNPRS5: JUMPL I,FNPRS6 ; keep looking if we haven't seen anything yet. + POPJ P, + +;Extract in H the next character from user memory off the byte pointer in R. +;Q should be an aobjn pointer to a block of further BPs +;(in user memory) to use after this one is exhausted. +FNPRS3: TLNN R,-1 + HRLI R,440700 + IBP R + UMOVE H,(R) ;Fetch the word the BP points to. + PUSH P,R + HRRI R,H ;Change the BP to point to H. + LDB H,R ;Extract the desired byte. + POP P,R + JUMPN H,CPOPJ + AOBJP Q,CPOPJ ;When one BP is exhausted, go to the next (if any). + UMOVE R,(Q) + PUSHJ P,ASCIND + JRST FNPRS3 + +NOPEN: HRRZ R,A ;ARGS 1 MODE (LH) CHNL (RH) 2-5 LIKE NOPEN1 1-4 + CAIL R,NIOCHN + JRST OPNL14 + ADDI R,IOCHNM(U) + PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D + PUSH P,E + PUSH P,W + PUSHJ P,CCLOSE + POP P,W + SOS W ;STRIP OF FIRST ARG + POP P,D ;B-E POPPED INTO A-D + POP P,C + POP P,B + POP P,A + POP P,R ;A POPPED INTO R + TLC R,@CTLBTS(U) + LDB E,[OPNCOM,,R] + CAIE E,2 + CAIN E,4 + JRST OPNL12 ;COMMAND CANT BE LINK OR FDELE FOR "NEW" CALL + JSP T,NOPEN1 + MOVEM D,SRN3(U) ;MAKE SYMBOLIC OPEN OF NETWORK WIN USING 5TH ARG AS FOREIGN HOST. +NDEL1: CLEARM SRN4(U) +NRN2: CLEARM SRN5(U) +NOPENX: TRNE R,-NIOCHN + BUG ;BAD CHANNEL # + HRRZM R,UUAC(U) ;CHNL # (MAYBE ONLY FOR ERRS) IN R + ADDI R,IOCHNM(U) + LDB W,[OPNCOM,,R] + JRST NOPNE + +;DEFAULT THE ARGS FOR .CALL OPEN, ETC,; PUT MODE IN E. +NOPEN1: SETZM EPDL(U) + SETZM EPDL3(U) + CAIGE W,2 + MOVSI B,(SIXBIT /@/) + CAIGE W,3 + MOVSI C,(SIXBIT /@/) + CAIGE W,4 + MOVE D,USYSNM(U) ;SYSTEM NAME + HLRZ E,R ;GET MODE BITS FOR TRAN. + JRST (T) + +;MAKE LINK 1-4 AS NOPEN1, 5 SNAME 2 6,7 FN1,2(2) +NMLINK: MOVSI R,200000 + CAIN W,2 ;Only 2 args are BPs. + JRST [ PUSHJ P,2FNPRS + JRST NOPENX] + CAIGE W,7 ;Otherwise, must be seven word of sixbit. + JRST OPNL33 + MOVEM E,SRN3(U) + MOVEM TT,SRN4(U) + MOVEM I,SRN5(U) + JSP T,NOPEN1 + JRST NOPENX + +NDEL: SETZM SRN3(U) + CAIN W,2 + JRST OPNL33 + CAIN W,1 ;If it's just a BP (or block of them), + JRST [ MOVE R,A ;Parse it into filenames in A-D. + MOVEM R,EPDL(U) + PUSHJ P,FNPRS + JRST .+2] + JSP T,NOPEN1 + MOVSI R,400000 ;DELETE, ARGS AS NOPEN1 + SETZ E, + JRST NDEL1 + +NRNAM: MOVSI R,400000 + CAIN W,2 ;Only 2 args are BPs. + JRST [ PUSHJ P,2FNPRS + JRST NRN2] + CAIGE W,6 ;Otherwise, must be six word of sixbit. + JRST OPNL33 + MOVEM E,SRN3(U) + MOVEM TT,SRN4(U) + MOVSI R,400000 ;RENAME 1-4 AS NOPEN1 5,6 NEW FN1,2 + JSP T,NOPEN1 + JRST NRN2 + +;Parse two BPs (or aobjn pointers to blocks of BPs) into user memory +;into filenames. The second bunch go in SRN3 - SRN5; the first in A - D. +;The two args are saved in EPDL and EPDL3. Clears E, preserves R. +2FNPRS: PUSH P,R + MOVEM A,EPDL(U) ;Save two BPs for job device. + MOVEM B,EPDL3(U) + PUSH P,A ;Decode the second BP first, to get the new names. + MOVE R,B + PUSHJ P,FNPRS + MOVEM B,SRN3(U) ;Stick them where RENAME looks. + MOVEM C,SRN4(U) + MOVEM D,SRN5(U) + POP P,R ;Parse the first BP, to get the old file filenames. + PUSHJ P,FNPRS + SETZ E, + POP P,R + POPJ P, + +;Takes either channel, FN1 (sixbit) and FN2 (sixbit) +;or channel and BP (or aobjn -> block of BPs). +NRNWO: SETZM EPDL(U) + SETZM EPDL3(U) + PUSH P,A + CAIN W,2 + PUSHJ P,[MOVE R,B ;If channel and BP, parse the BP into filenames. + MOVEM R,EPDL3(U) ;But also save it for job device. + JRST FNPRS] + MOVEM B,SRN3(U) ;PUT AWAY NEW NAMES. + MOVEM C,SRN4(U) + POP P,C + ANDI C,-1 ;We call "RENAME" with old fn2 = channel number. + SETZB A,B + MOVEI D,0 + MOVSI R,400000 ;OPNCOM IS .FDELE . + MOVEI E,400000 + JRST NRN2 + +SUBTTL HACKS FOR OPENS THAT LOSE + + +IFN 0,[ ;THESE "DEFNS" EXIST ONLY SO @ WILL CREF THEM + OPNL1: OPNL2: OPNL3: OPNL4: OPNL5: OPNL6: OPNL7: +OPNL10: OPNL11: OPNL12: OPNL13: OPNL14: OPNL15: OPNL16: OPNL17: +OPNL20: OPNL21: OPNL22: OPNL23: OPNL24: OPNL25: OPNL26: OPNL27: +OPNL30: OPNL31: OPNL32: OPNL33: OPNL34: OPNL35: OPNL36: OPNL37: +OPNL40: OPNL41: OPNL42: OPNL43: OPNL44: OPNL45: OPNL46: OPNL47: +OPNL50: OPNL51: OPNL52: OPNL53: OPNL54: OPNL55: OPNL56: OPNL57: +OPNL60: OPNL61: OPNL62: OPNL63: OPNL64: OPNL65: OPNL66: OPNL67: +OPNL70: OPNL71: OPNL72: OPNL73: OPNL74: OPNL75: OPNL76: OPNL77: +] ;END OF IFN 0 + +;HERE ARE THE REAL DEFNS +REPEAT NOPNLS,CONC OPNL,\.RPCNT+1,: JSP D,OPENL +; +OPENL: CONSZ PI,77400 + BUG ;ERROR WITH PI IN PROGRESS + MOVE U,USER ;BE SURE U=CURRENT USER'S INDEX + MOVEI D,-OPNL1(D) ;GET LOSSAGE NUMBER + MOVE R,SYSCVL(U);POSSIBLY RETURN IN ERROR-CODE ARG TO .CALL + TLNE R,%SCVER + UMOVEM D,(R) + HRRZ R,UUAC(U) ;GET CH NUM + CAILE R,NIOCHN-1 + BUG ;UUAC BAD + PUSHJ P,LSWCLR ;UNLOCK SWITCHES + DPB R,[BCHPTR] ;SAVE AS MOST RECENT CHANNEL IN ERR + ADD R,U ;RELOCATE TO POINT TO USER VARS + DPB D,[220600,,IOCHST(R)] ;STORE IN STATUS WORD + JRST CLKONJ + +SUBTTL RCHST, STATUS, RFNAME, RFPNTR, WHYINT CALLS + +;.CALL RFNAME +;1ST ARG IS A , WHOSE CHANNEL IS TO BE LOOKED AT. +;2ND ARG IS A CHANNEL NUMBER. +;3RD ARG IS BP TO STORE ASCIZ FILENAME STRING THROUGH. +;4TH ARG IS MAXIMUM NUMBER OF CHARACTERS TO STORE (DEFAULTS TO 1,,0). +;ONLY 1 ARG => IT IS CHANNEL #, AND JOB IS "SELF". +;FIRST 4 VALUES ARE THE DEVICE, FN1, FN2 AND SNAME +; AS LEFT-JUSTIFIED SIXBIT WHOLEWORDS. +;FIFTH VALUE IS THE MODE THE CHANNEL MIGHT BE RE-OPENED IN + +NRFNAM: MOVE J,A ;FIRST ARG IS JOB SPEC + CAIL W,2 + SKIPA A,B ;GET CHANNEL # INTO A IN EITHER CASE + MOVEI J,%JSELF ;IF ONLY ONE ARG, JOB SPEC IS SELF + MOVE Q,C ;SAVE BP FOR STORING ASCIZ FILENAME STRING - IF ANY. + CAIGE W,3 + SETZ Q, + CAIGE W,4 + MOVSI D,1 + JSP T,NCORUI ;DECODE JOB SPEC + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;PDP6 DOESN'T HAVE CHANNELS +] + PUSH P,D + PUSH P,Q + MOVE W,D + MOVE U,J ;LOOK IN THAT JOB'S CHANNELS + PUSHJ P,NRFNM1 ;GET THE CRUFT + JRST POP2J + PUSHJ P,LSWPOP ;UNSOS DIELOK. + MOVE T,Q + POP P,Q + POP P,I ;I GETS 4TH ARG: MAX NUMBER OF CHARS TO STORE IN STRING. + JUMPE T,POPJ1 ;IF DEVICE ROUTINE HAS CLEARED Q, IT HAS STORED THE STRING. + ;NOTE NETRCH PUTS AN EXTRA VALUE FOR .RCHST (GARBAGE, TO US) IN Q! + JUMPE Q,POPJ1 ;IF BP ARG WAS 0, CALLER DOESN'T WANT A STRING. + MOVE R,Q + PUSHJ P,ASCIND + MOVE Q,R + MOVE J,A ;IF SO, STORE ALL 4 FILENAMES DOWN IT, ONE BY ONE. + MOVEI T,": + PUSHJ P,NRFNS1 + MOVE J,D + MOVEI T,"; + PUSHJ P,NRFNS1 + MOVE J,B + MOVEI T,40 + PUSHJ P,NRFNS1 + MOVE J,C + MOVEI T,0 + PUSHJ P,NRFNS1 + JRST POPJ1 + +;STORE THE SIXBIT WORD IN J FOLLOWED BY THE ASCII CHAR IN T +;INTO USER ADDRESS SPACE DOWN THE BP IN Q. +NRFNS1: JUMPE J,CPOPJ ;OUTPUT NOTHING AT ALL IF THE SIXBIT WORD IS EMPTY. + CAIGE I,4 ;GIVE UP NOW IF TOO CLOSE TO END OF ALLOCATED SPACE. + POPJ P, + SETZ R, + ROTC J,6 ;ELSE GET NEXT CHAR IN R, AND CONVERT TO ASCII AND STORE. + ADDI R,40 + SETZ TT, + CAIE R,": ;PRECEDE ANY SPECIAL CHARACTERS WITH ^Q. + CAIN R,"; + MOVEI TT,^Q + CAIN R,40 + MOVEI TT,^Q + JUMPE TT,NRFNS2 + SOS I + PUSHJ P,NRFNSB +NRFNS2: SOS I + MOVE TT,R + PUSHJ P,NRFNSB + JUMPN J,NRFNS1 + SOS I + MOVE TT,T + PUSHJ P,NRFNSB ;IF NAME FINISHED BUT NOT EMPTY, FOLLOW BY TERMINATOR. + JUMPE T,CPOPJ + CAIN T,40 + POPJ P, + MOVEI TT,40 + PUSHJ P,NRFNSB ;IF TERMINATOR IS : OR ;, FOLLOW IT WITH A SPACE. + SOJA I,CPOPJ + +;STORE A BYTE IN TT DOWN BP IN Q TO USER SPACE, INCREMENTING FIRST. +;XCTR XBYTE LOSES BECUSE IT GETS THE BP FROM USER SPACE. +NRFNSB: IBP Q + PUSH P,T + PUSH P,Q + UMOVE T,(Q) + HRRI Q,T + DPB TT,Q + POP P,Q + UMOVEM T,(Q) + POP P,T + POPJ P, + +;GET THE FILENAMES FOR THE CHANNEL IN A OF JOB IN U INTO A THRU D. +;IF Q IS NONZERO, IT IS A BP TO STORE AN ASCIZ STRING, AND W IS THE +;MAX NUMBER OF CHARACTERS TO STORE. +;THE DEVICE DEPENDENT ROUTINE CAN STORE THE STRING ITSELF +;AND SET Q TO ZERO SO THAT IT WILL NOT BE STORED THE STANDARD WAY. +NRFNM1: MOVE T,[4,,NRFNM2] + JRST CHNDCD ;R GETS ADDR OF IOCHNM WD, H GETS CONTENTS. +NRFNM2: HLRZ A,H ;PUT LH(IOCHNM WD) WHERE DEVICE RTN LOOKS + HLLZ J,DCHSTB(H) + JUMPG J,[ ;IF 6-LETTER DEVICE NAME, LH IS POSITIVE ADDRESS + HLRZS J ;OF FULL NAME. NOTE THERE BETTER BE NO + MOVE J,(J) ;3-CHAR DEVICES WHOSE NAME DOES NOT START + JRST .+1 ] ;WITH A LETTER. + PUSH P,J ;SAVE THE PROBABLE VALUE OF DEVICE NAME + LDB J,[1400,,DCHSTB(H)] + HLRZ J,DRFNTB(J) ;GET RFNAME ROUTINE POINTER + SETZB B,C ;FN1, FN2 ARE 0 FOR NON-DIR-DEV + SETZ D, ;SNAME IS 0 FOR NON-MULTI-DIR-DEV + LDB E,[.BP (%IOTOM),IOTTB(H)] ;PROBABLE VALUE OF MODE + PUSHJ P,(J) ;CALL DEVICE-SPECIFIC ROUTINE + SKIPA A,(P) ;NO SKIP => USE DEVICE NAME FROM DCHSTB + MOVE A,J ;SKIP => USE DEVICE NAME RETURNED IN J + JRST POP1J1 + +;.CALL RFPNTR +;ARG 1 - CHANNEL NUMBER +;VAL 1 - ACCESS POINTER OF CHANNEL +;VAL 2 - BYTE SIZE OF CHANNEL. +;FAILS IF NOT A RANDOM-ACCESS DEVICE + +NRFPNT: HLRZ A,H ;CHANNEL ALREADY DECODED, SET UP LH(IOCHNM) FOR DEV RTN + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DRFNTB(J) ;GET RFPNTR ROUTINE POINTER + JRST (J) ;IT SHOULD PUT POINTER IN A AND POPJ1, OR OPNL34 + +;SYMBOLIC CALL "RCHST" +;1ST ARG IS A CHANNEL NUMBER. +;6 OR MORE VALUES. THE FIRST 4 ARE THE DEVICE, FN1, FN2 AND SNAME +; AS LEFT-JUSTIFIED SIXBIT WHOLEWORDS. +;THE 5TH IS THE ACCESS POINTER, OR -1 IF NOT RANDOM ACCESS. +;THE 6TH IS THE MODE THE CHANNEL MIGHT BE RE-OPENED IN. +;MORE VALUES ARE RETURNED ONLY FOR NET:, AT THE MOMENT. +;THE DEV SUBROUTINE MAY PUT EXTRA RESULTS IN TT, I, AND Q, AND PUT # RESULTS INTO W + +NRCHST: SETO I, ;DEFAULT POSSIBLE EXTRA RESULTS + SETO TT, ;DEFAULT ACCESS POINTER TO -1 + MOVEI W,6 ;NORMAL NUMBER OF RESULTS IS 6 + SETZ Q, + PUSHJ P,NRFNM1 ;GET RESULTS 1 THROUGH 4 AND 6, AND SET UP R AND H + POPJ P, ;CHANNEL NUMBER MUST HAVE BEEN BAD + PUSH P,A + PUSH P,B ;SAVE THE AC THAT RFPNTR CLOBBERS. + HLRZ A,H ;GET ROUTINE TO GET ACCESS POINTER + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DRFNTB(J) ;ROUTINE BETTER PRESERVE B,C,D,E,TT,I,Q + CAIL J,OPENL ;KLUDGILY SKIP IF WOULD OPEN-LOSS + PUSHJ P,(J) ;GET ACCESS POINTER IN A, ALWAYS SKIPS + MOVE A,TT ;NOT RANDOM ACESS, USE DEFAULT VALUE + MOVE TT,E ;OPEN MODE IS 6TH RESULT + MOVE E,A ;ACCESS POINTER IS 5TH RESULT + JRST PPBAJ1 + +;.RCHST AC, WITH AC/ CH,,ADDR +;RETURNS, IN THE 5 OR MORE WORDS STARTING AT ADDR, +;THE RESULTS OF A SYMBOLIC RCHST ON CHANNEL CH. +;EXCEPTION - THE DEVICE NAME IS RETURNED IN THE RH +;OF THE FIRST WORD , SO IT IS TRUNCATED TO 18 BITS. +;EXCEPTION - THE OPEN MODE VALUE IS NOT RETURNED. LATER VALUES +;ARE SHIFTED DOWN ONE WORD. +;NEVER SKIPS. + +ARCHST: UMOVE J,(J) ;GET CONTENTS OF AC + HLRZ A,J + CAIL A,NIOCHN + JRST ILUUO ;BAD CHANNEL NUMBER + PUSH P,J + PUSHJ P,NRCHST ;DO THE REAL WORK. + BUG ;ONLY ERROR RETURN SHOULD BE BAD CHANNEL NUMBER + HLRZS A ;PUT DEV NAME IN RH FOR HISTORY'S SAKE + POP P,J ;RH(J) HAS PLACE TO STORE DATA + MOVE TT,I + MOVE I,Q ;SHIFT DOWN LAST 2 VALS OVER THE OPEN MODE. + HRLI J,A + ADDI W,-2(J) ;W HAD 1+ # VALS, NOW HAS PLACE TO PUT LAST ONE + XCTR XBW,[BLT J,(W)] + POPJ P, + +;.STATUS CH,LOC ;STORE IN LOC THE STATUS OF CHANNEL CH + ;AND OF THE DEV OPEN ON IT IF ANY +;1.1-1.6 SYS PERIPHERAL DEVICE CODE +;1.7-2.9 DEVICE DEPENDENT +;3.1-4.9 LH(IOCHST) + +ASTATUS:ADDI R,IOCHNM(U) ;SET UP AC'S LIKE CHNDCD +ASTAT1: MOVE H,(R) ;ENTER HERE FROM .USET [.RIOS,,] + HLL R,CLSTB(H) + PUSHJ P,NSTATUS ;CALL NEW SYSTEM CALL VERSION + BUG + UMOVEM A,(C) ;GIVE TO USER + POPJ P, + +;.CALL STATUS +;ARG 1 - CHANNEL NUMBER +;VAL 1 - SAME AS .STATUS + +NSTATUS:HLRZ A,H ;SET UP LH(IOCHNM) + LDB D,[140600,,DCHSTB(H)] ;GET SYS PERIPHERAL DEVICE CODE + LDB J,[340300,,IOTTB(H)] ;GET I/O CHANNEL MODE FROM 4.5-4.2 + DPB J,[060300,,D] ;RETURN IN BITS 1.9-1.7 + LDB J,[1400,,DCHSTB(H)] + HLRZ J,DSTSTB(J) ;GET STATUS ROUTINE POINTER + PUSHJ P,(J) ;ROUTINE FILLS OUT STATUS WORD IN D + HLL D,IOCHST-IOCHNM(R) ;FILL IN LEFT HALF FROM IOCHST + TLZ D,740000 ;CLEAR BITS USED FOR CHANNEL NUM ON IO PDL + MOVE A,D ;RETURN VALUE IN A + JRST POPJ1 ;THIS CALL ALWAYS SUCCEEDS + +;.CALL WHYINT +;ARG 1 - CHANNEL NUMBER +;VAL 1 - %WY CODE FOR TYPE OF DEVICE +;ADDITIONAL VALUES DEVICE-DEPENDENT +;THIS IS THE USUAL CALL TO GIVE IN RESPONSE TO A SECOND WORD INTERRUPT + +NWHYINT:HLRZ A,H ;SET UP LH(IOCHNM) + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DSTSTB(J) ;GET WHYINT ROUTINE POINTER + JRST (J) + +;DEVICE-SPECIFIC RFNAME/RCHST ROUTINES +;CALLED WITH STANDARD CHNDCD STUFF IN H AND R, LH(IOCHNM) IN A +;MUST PRESERVE H AND R; CAN CLOBBER W TO INDICATE EXTRA STUFF FOR RCHST + +RCHUSR: MOVE B,UNAME(A) ;GET UNAME + MOVE C,JNAME(A) ;GET JNAME + POPJ P, + +IFN NUNITS,[ ;UTAPE .RCHST +RCHUTP: HRRZ C,UTTNO(A) + MOVSI J,'UT0(C) ;GET REAL DEV NAME "UTN" IN J + AOS (P) ;SKIP TO RETURN CHANGED DEV NAME + MOVE D,UTASS(C) ;THE "SNAME" IS THE USER TAPE IS ASSIGNED TO. + CAIGE A,NUTIC + JRST RCHUTI ;INPUT + MOVE B,UTN1(A) ;OUTPUT, GET FN1 + MOVE C,UTN2(A) ;NOW FN2 + POPJ P, + + ;UTAPE INPUT .RCHST +RCHUTI: LDB T,[220500,,UTDBC(A)] ;GET FILE NUMBER + SUBI T,1 + LSH T,1 ;TURN INTO INDEX INTO DIRECTORY + CONO PI,CLKOFF + ADD T,UDIRO(C) ;GET POINTER TO FILE NAMES + MOVE B,(T) ;GET FN1 + MOVE C,(T) ;GET FN2 + JRST CLKONJ +] + +;RCHST ROUTINE FOR TTY +RCHTTY: MOVE J,A + ANDI J,#%TICNS#(.BM $TIIDX) + IOR E,J ;MERGE TTY OPEN MODE BITS WITH THE GENERAL ONES. + TRNE A,%TICNS + POPJ P, + ANDI A,7 + MOVEI J,'T00(A) + HLRZ A,(R) +RCHST1: ANDI A,70 + LSH A,3 + ADD J,A + HRLZS J ;J NOW HAS SIXBIT/TNM/, NM = TTY #. + JRST POPJ1 ;SKIP TO SAY DEV NAME IS IN J. + +;RCHST ROUTINE FOR STY +RCHSTY: MOVE J,TTYOPT(A) + TLNE J,%TOHDX + IORI E,4 ;STY BIT 1.3 => TTY IS HALF-DUPLEX. + MOVE J,STYSTS-NFSTTY(A) + TLNE J,%SSORS + IORI E,20 ;BIT 1.5 => WANT TO RECEIVE %TDORS ON .RESET OF TYOC, + TRNN E,1 ;FIND THE DON'T-HANG-BIT FOR THIS DIRECTION. + TLZA J,#%SSOHG ;AND FLUSH THE ONE FOR THE OTHER DIRECTION. + TLZ J,#%SSHNG + TLNE J,-1 ;THEN TESTING BOTH TESTS ONLY THE RELEVANT ONE. + IORI E,10 + SUBI A,NFSTTY + ANDI A,7 + MOVEI J,'S00(A) + HLRZ A,(R) + SUBI A,NFSTTY + JRST RCHST1 + +RCHDRH: HRRZ A,IOCHST-IOCHNM(R) ;TRACK NUMBER + IMULI A,LMNBLK ;DIRHNG DEVICE RFNAME + ADDI A,2000-LMNBLK*NUDSL + ADD A,QMDRO + MOVE D,MNUNAM(A) + POPJ P, + +;RCHST ROUTINE FOR DIRECTORY CHANNELS AND THE ERR DEVICE. +RCHDIR: MOVE T,DSKLST(A) ;GET THE TYPE OF DIRECTORY CODE. + SKIPE J,UDUSR(A) ;IF DEVICE # IS NONZERO, ADD IT TO DEV NAME + HRLZS J ;(ONLY HAPPENS FOR UTAPE) + ADD J,RCHDRD-1(T) ;DETERMINE DEV NAME FROM DIRECTORY TYPE + MOVE B,RCHDR1-1(T) ;SAME FOR FN1 + SKIPN C,RCHDR2-1(T) ;AND FN2, EXCEPT 0 FOR ERR DEVICES + MOVE C,UUDPP(A) ; SO WE WILL GET THE STATUS WORD BEING DECODED. + CAIN T,3 + MOVE D,UDSYSN(A) ;FOR DISK UFD'S, GET THE SNAME + JRST POPJ1 ;RETURN, SAYING WE HAVE SPEC'D THE DEVICE NAME. + +.SEE UDT ;THESE TABLES ARE IN PARALLEL WITH UDT +RCHDRD: 'UT0,, ? 'CLU,, ? 'DSK,, ? 'DSK,, + 'ERR,, ? 'TTY,, ? 'COR,, +IF2 IFN .-UDTLN-RCHDRD,.ERR RCHDRD WRONG LENGTH + +RCHDR1: '.FILE. ? '.FILE. ? '.FILE. ? 'M.F.D. + 3 ? '.FILE. ? '.FILE. +IF2 IFN .-UDTLN-RCHDR1,.ERR RCHDR1 WRONG LENGTH + +RCHDR2: SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ ? SIXBIT /(FILE)/ + 0 ? SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ +IF2 IFN .-UDTLN-RCHDR2,.ERR RCHDR2 WRONG LENGTH + + + +;CORE LINK .RCHST ROUTINE + +RCHCLO: CONO PI,CLKOFF + MOVE B,CLN1(A) ;GET FN1 + MOVE C,CLN2(A) ;GET FN2 + MOVE D,CLSYN(A) ;GET SYSTEM NAME + JRST CLKONJ + +;RFNAME ROUTINE FOR DSK + +RCHQSK: MOVE H,QUDPR(A) ;FILE STATUS FOR DISK PICKUP USER DIR POINTER + PUSHJ P,QUDLK ;LOCK DIRECTORY + MOVE C,QSNLCN(H) ;LOCATION OF DIRECTORY + MOVE D,UDNAME(C) + ADD C,QUDFPR(A) ;ADD LOCN OF FILE WITHIN DIRECTORY + MOVE B,(C) ;GET FIRST FILE NAME + MOVE C,1(C) ;GET SECOND FILE NAME + PUSHJ P,QUDULK + MOVE H,QSRAC(A) + TLNE H,%QALNK + TRO E,20 ;LINK MODE + MOVE H,(R) ;PRESERVE H + POPJ P, + +;RFNAME ROUTINE FOR BOJ: + +RCHBOJ: CONO PI,CLKOFF ;BOJ DEVICE .RCHST ROUTINE + MOVE T,JBCUI(A) ;RETURNS CREATOR'S NAME + MOVE B,UNAME(T) + MOVE C,JNAME(T) + SKIPGE JBCG(A) + SETZB B,C ;CREATOR GONE, RETURN BLANK NAMES + JRST CLKONJ + +;RFNAME ROUTINE FOR JOB: + +RFNJOB: SKIPE Q + PUSHJ P,RFNJ1 + CONO PI,CLKOFF + MOVE B,JBFN1(A) + MOVE C,JBFN2(A) + MOVE D,JBSYS(A) + MOVE E,JBOPNM(A) + MOVE J,JBDEV(A) + JRST CLKOJ1 + +;COPY THE BOJ JOB'S ASCIZ FILENAME STRING INTO OUR CALLER'S STRING. +;THE CALLER'S BP IS IN Q, AND HIS MAX CHARS TO STORE IS IN W. +RFNJ1: SKIPN B,JBFNP(A) + POPJ P, + PUSH P,TT + PUSH P,T + MOVE J,JBCJUI(A) + AOS DIELOK(J) ;PREVENT THE JOB FROM DIEING. + PUSHJ P,SOSSET + DIELOK(J) + TLZ B,37 + MOVE D,B + PUSHJ P,RFNJ3 + MOVEI TT,1 +;D HAS BP TO FETCH WITH, POINTING INTO C, WHICH CONTAINS WORD FETCHED FROM BOJ JOB. +;RH(B) HAS ADDR OF NEXT WORD TO FETCH FROM THE BOJ JOB. +;TT CONTAINS THE PREVIOUS CHARACTER TRANSFERRED, OR 1 +;IF THE PREVIOUS CHARACTER WAS QUOTED WITH A ^Q. +RFNJ2: ILDB E,D + TRNN D,#C ;IF THE BP IN D ADVANCES PAST C, + JRST RFNJ4 + PUSHJ P,RFNJ3 ;FETCH ANOTHER WORD INTO C, MAKE D POINT THERE AGAIN, + LDB E,D ;AND FETCH THE SAME BYTE OVER AGAIN. +RFNJ4: SOJL W,RFNJ5 + EXCH TT,E + PUSHJ P,NRFNSB ;STORE BYTE INTO CALLER, UNLESS HIS STRING IS FULL. + EXCH TT,E + CAIN TT,^Q ;A QUOTED CHAR DOES NOT TERMINATE AND DOES NOT QUOTE. + MOVEI E,1 + MOVE TT,E + JUMPN E,RFNJ2 ;STOP STORING AFTER A NULL WHICH ISN'T QUOTED. +RFNJ5: SETZ Q, + POP P,T + POP P,TT + JRST LSWPOP + +;READ THE NEXT WORD (ADDR IN B) FROM THE BOJ JOB. +RFNJ3: SETZ C, + PUSH P,U + PUSH P,A + PUSH P,Q + MOVE U,JBCJUI(A) + LDB A,[121000,,B] + PUSHJ P,UPLC ;LOOK UP THE BOJ JOB'S PAGE. + POP P,Q + POP P,A + POP P,U + LDB J,T ;IF IT DOESN'T EXIST, LOAD A ZERO, + JUMPE J,RFNJ6 ;AVOID GETTING MPV. + MOVE J,JBCJUI(A) + PUSHJ P,MPLDJ + UMOVE C,(B) +RFNJ6: HRRI D,C + AOJA B,MPLDZ + +;RFPNTR FOR USR: + +RFPUSR: HRRZ A,IOCHST-IOCHNM(R) ;GET THE ACCESS PTR + MOVEI B,36. ;BYTE SIZE IS ALWAYS FULL WORD. + JRST POPJ1 + +;RFPNTR FOR DISK + +RFPQSK: LDB B,[QSBSIZ(A)] ;GET FILE BYTE SIZE + MOVSI T,%QAACC + TDNN T,QSRAC(A) ;IF .ACCESS WAS DONE AND NOT HANDLED, + JRST RFPQS1 + MOVE A,QRADAD(A) ;GET WHAT THE .ACCESS SPECIFIED. + JRST POPJ1 + +RFPQS1: MOVE J,QFBLNO(A) ;GET BYTE # OF STRAT OF CURRENT BLOCK. + SKIPGE QSMDN(A) ;SKIP ON A BUFFER ACTIVE + JRST RFPQS2 ;NONE ACTIVE => QFBLNO POINTS TO NEXT BLOCK TO BE READ. + ADD J,QMPBSZ(A) ;ELSE CORRECT FOR THE NUMBER OF BYTES WE'VE PROCESSED + SUB J,QSMPRC(A) ;IN THE ACTIVE BLOCK (QFBLNO -> 1ST WD OF BLOCK). +RFPQS2: MOVE A,J + JRST POPJ1 + +SUBTTL RESET,IOPUSH,IOPOP,IOPDL,FORCE,FLUSH .CALLS + +;.RESET CH, ;RESET BUFFERED INFO ON CHANNEL CH + ;NOT IMPLEMENTED FOR MANY DEVICES + ;HAS SPECIAL EFFECTS ON "USR" DEVICE +;.CALL RESET +;ARG 1 - CHANNEL NUMBER + +NRESET: HRRZ A,H + AOSA (P) +ARESET: HRRZ A,(R) ;PICK UP INDEX FROM I/O CH WORD + SKIPA T,[HRRZ T,RSTB1(A)] ;.RESET USES RH OF TABLE +AIOPP1: MOVE T,[HLRZ T,RSTB1(A)] ;.IOPUSH, .IOPOP USE LH OF TABLE + IDIVI A,7 ;TABLE IS IN 5-BIT BYTES TO SAVE SPACE + ADD A,[440500,,RSTB] + IBP A + SOJGE B,.-1 + LDB A,A ;GET BYTE FROM TABLE + XCT T ;GET REAL TABLE ENTRY IN T + JRST (T) ;DISPATCH + +;IO CHANNEL PUSH DOWN LIST ROUTINES +;C(I) =0 AT DSP => IOPUSH =1 => IOPOP + +NIOPUS: AOS (P) +AIOPUSH:MOVE T,SIOCP(U) ;PICK UP PDL POINTER + CAML T,[LUIOP-1,,0] ;LUIOP-2,, is OK, leaves room for 1 more. + JRST IOCER6 ;OVER PUSH ERROR + PUSH T,(R) ;PUSH CURRENT IOCHNM + PUSH T,IOCHST-IOCHNM(R) ;&IOCHST + HRRZ A,(R) + HRRZ J,UUAC(U) + DPB J,[400400,,(T)] ;STORE CHANNEL NUM FOR POSSIBLE USE BY AIOPDL + MOVEM T,SIOCP(U) ;STORE BACK PDL POINTER + MOVEI I,0 ;INDICATE IOPUSH + PUSH P,R + PUSHJ P,AIOPP1 ;CALL DEVICE'S IOPDL HANDLER. SHOULD NOT HANG + POP P,R + SETZM (R) ;CLEAR OUT IOCHNM + SETZM IOCHST-IOCHNM(R) ;&IOCHST + POPJ P, + +NIOPOP: AOS (P) +AIOPOP: PUSHJ P,ACLOSE ;CLOSE WHATEVER MAY BE OPEN ON CHANNEL POPPING INTO + MOVE T,SIOCP(U) ;PICK UP PDL POINTER + TLNN T,-1 + JRST IOCER5 ;OVER POP ERROR + POP T,IOCHST-IOCHNM(R) ;POP BACK IOCHST + POP T,(R) ;&IOCHNM + HRRZ A,(R) + SETZM 1(T) ;CLEAR OUT PDL WORD TO AVOID CONFUSION IN + ;ROUTINES THAT GROVEL OVER I/O PDL + MOVEM T,SIOCP(U) ;STORE BACK PDL POINTER + MOVEI I,1 ;INDICATE IOPOP + JRST AIOPP1 ;CALL DEVICE'S IOPDL HANDLER + +AIOPDL: MOVE T,SIOCP(U) ;PICK UP PDL POINTER + TLNN T,-1 ;SKIP UNLESS IO PDL EMPTY + POPJ P, + LDB R,[400400,,(T)] ;FIND OUT WHAT CHNL TOP ENTRY WAS PUSHED FROM + ADDI R,IOCHNM(U) + PUSHJ P,AIOPOP ;POP BACK INTO CHNL PUSHED FROM + JRST AIOPDL + +IIOPPR: JUMPE I,[JRST 4,CPOPJ] ;IOPUSH + SETZM (R) ;CLOSE CHANNEL + SUBI R,IOCHNM(U) ;GET CHANNEL NUMBER + MOVE R,CHNBIT(R) ;SECOND WORD INTERRUPT BIT + IORM R,IFPIR(U) ;GIVE TO USER + POPJ P, + +;.CALL FORCE +;ARG 1 - CHANNEL NUMBER +;IF ANY OUTPUT IS BUFFERED UP, CAUSES IT TO BE SENT TO THE DEVICE +;(IF FORCE WAS NOT DONE, IT MIGHT NOT BE SENT UNTIL A COMPLETE +;BUFFERFULL HAD BEEN OUTPUT BY THE USER.) + +NFORCE: SKIPA T,[HLRZ T,DFRCTB(D)] ;FORCE USES LH OF TABLE +NFINI1: MOVE T,[HRRZ T,DFRCTB(D)] ;FINISH USES RH OF TABLE + HLRZ A,(R) ;PASS LH(IOCHNM) TO DEVICE ROUTINES + HRRZ D,(R) ;USE RH(IOCHNM) AS BYTE INDEX INTO RSTB + IDIVI D,7 ;TABLE IS IN 5-BIT BYTES TO SAVE SPACE + ADD D,[440500,,RSTB] + IBP D + SOJGE E,.-1 + LDB D,D ;GET BYTE FROM TABLE + XCT T ;GET REAL TABLE ENTRY IN T + JRST (T) ;DISPATCH + +;.CALL FINISH +;ARG 1 - CHANNEL NUMBER +;FIRST DOES A FORCE, THEN WAITS FOR ALL OUTPUT TO GET TO THE DEVICE + +NFINIS: PUSHJ P,NFORCE ;CALL DEV ROUTINE FOR FORCING + POPJ P, + JRST NFINI1 ;THEN CALL DEV ROUTINE FOR WAITING + +;.NETS CH, - UUO VERSION OF .CALL FORCE. +ANETS: PUSHJ P,NFORCE + JRST IOCER1 ;ILLEGAL HARDWARE OPERATION + POPJ P, + +SUBTTL I/O DEVICE DISPATCH TABLES + +COMMENT | + This page tries to document the ITS I/O device dispatch tables and +dispatch environment. It is not completed yet. + +The tables use several different indices, which are: + opnidx - result of device name lookup in DEVTAB + ioidx - result of OPEN; has symbolic values. This is the index + stored in RH of IOCHNM (per-job channel table) + sidx - secondary index from DCHSTB(ioidx) + ridx - secondary index from RSTB(ioidx) + +The following system calls are dispatched through these tables. +There are 11 dispatch routines that each device must specify. +The format is "CALL [table name(index-used) -> device-routine]" + +OPEN [DEVADR(opnidx) -> devO] + "opnidx" is looked up from DEVTAB which holds the device names. + The device's OPEN routine is in the RH of DEVADR. + It must set up the user's IOCHNM word for the channel, + by setting the RH to the right "ioidx" and the LH to whatever + the device wants. + + Context: + +CLOSE [CLSTB(ioidx) -> devCLS] + The device's CLOSE routine is in the RH of CLSTB. + It must zero the user's IOCHNM word for the channel. + + Context: + +IOT, SIOT [IOTTB(ioidx) -> devVarious] + These routines do I/O transfers. The main reason "ioidx" + has so many possible values (causing IOTTB to be large) is + because lots of devices specify different ioidx's for different + modes - input/output, block/unit, image/ascii, etc - in order + to speed up actual I/O transfers, which are probably the most + common device-related system calls. + + Context: + +STATUS [LH(DTSTB(sidx)) -> devSTA] + +WHYINT [RH(DTSTB(sidx)) -> devWHY] + +RCHST, RFNAME [LH(DRFNTB(sidx)) -> devRCH] + +RFPNTR [RH(DRFNTB(sidx)) -> devRFP] + +IOPUSH, IOPOP [LH(RSTBI(ridx)) -> devIOP] + +RESET [RH(RSTBI(ridx)) -> devRST] + +FORCE [LH(DFRCTB(ridx)) -> devFRC] + +FINISH [RH(DFRCTB(ridx)) -> devFIN] + +| + +;DISPATCH TABLE FOR .CLOSE UUO +;TRANSFERED THROUGH USING RIGHT HALF OF IOCHNM WORD AS AN INDEX +;R HAS THE ADDRESS OF THE IOCHNM WORD. +; +;VARIOUS ROUTINES USE THE BITS IN THE L.H. TO DECIDE WHETHER +;A CHANNEL IS ACCEPTABLE FOR SOME OPERATION. +%CLS==1,,525252 +%CLSU==400000 ;USR DEVICE (INFERIOR) +%CLSDO==200000 ;DECTAPE OUTPUT +%CLSJI==100000 ;JOB INPUT +%CLSDI==40000 ;DECTAPE INPUT +%CLSTI==20000 ;TTY INPUT +%CLSCL==10000 ;CORE-LINK DEVICE +%CLSBJ==4000 ;BOJ DEVICE +%CLSQO==2000 ;DISK OUTPUT +%CLSFU==1000 ;NON-INFERIOR USR +%CLSNRM==400 ;STANDARD CLOSE ROUTINE USED FOR THIS DEVICE. + ;RH SHOULD POINT, NOT AT THEROUTINE, BUT AT THE USR-USE PAIR +%CLSQ==200 ;DISK +%CLS6==100 ;PDP6 +%CLSJO==40 ;JOB OUTPUT +%CLSST==20 ;STY DEVICE +%CLST==10 ;TRAP DEVICE + +%CLSJ==%CLSJI\%CLSJO ;EITHER DIRECTION OF JOB DEVICE +%CL1QO==%CLSQO\%CLSQ ;BOTH BITS FOR DISK OUTPUT + +CLSTB: CPOPJ + OFFSET -CLSTB +TYIDN:: REPEAT 2, %CLSTI,,TYICLS ;TYI +TYODN:: REPEAT 2, TYOCLS ;TYO +NLIDN:: REPEAT 4, CPOPJ ;NULL +UWIDN:: REPEAT 4, %CLSU ,,CPOPJ ;USER +FUWIDN:: REPEAT 2, %CLSFU,,CPOPJ ;FOREIGN USER +DNDIRH:: DIRHCL ;DIRHNG +DNTRAP:: %CLST,,CPOPJ ;TRAP +DNLCK:: LCKCL ;LOCK +IFN KS10P,DNUBI:: UBICL ;UNIBUS INTERRUPT +IFN CHAOSP,CHAIDN:: REPEAT 2, CHACLS ;CHAOS NET +IFN NUNITS,[ +DNUACII:: REPEAT 3,[ + %CLSDI,,UTICL ;UTAPE. + %CLSDO,,UTOCL +]] +IFN OLPTP,LPTDN:: REPEAT 2, LPTCLS ;LPT +IFN NLPTP,[ +NLPTDN:: NLPDCL + NLPTCL +] +IFN GLPTP,GLPTDN:: REPEAT 2, GLPCLS +DIRCHN:: REPEAT 4, UTDCLS ;DIRECTORY DEVICE +IFN VIDP,NVIDOP:: REPEAT 2, NVDCLS ;NVIDI +IFN PLTP,PLTDN:: REPEAT 2, %CLSNR,,PLTUSR ;PLOTTER +IFN PTRP,[ +PTPI:: REPEAT 5, %CLSNR,,PTPUSR ;PAPER TAPE PUNCH +] +IFN IMXP,IMPXDN:: REPEAT 4, IMPXCL ;IMX +IFN OMXP,OMPXDN:: REPEAT 4, OMPXCL ;OMX +DCLUAI:: %CLSCL,,CLCLRA ;CORE LINK + %CLSCL,,CLCLWU + REPEAT 2,[ + %CLSCL,,CLCLRB + %CLSCL,,CLCLWB + ] +IFN PTRP,[ +REDUAI:: REPEAT 5, PTRCLS ;PAPER TAPE READER +] +IFN 340P,[ +DN340B:: REPEAT 4, ADCL1 ;340 +; ADCL1 ;IDS +] +IFN CODP,[ +CODDN:: REPEAT 2, CODCLS ;CODE DEV +] +DQUAI:: %CLSQ ,,QICL ;DISK + %CL1QO,,QOCLR + %CLSQ ,,QICL + %CL1QO,,QOCL + %CLSQ ,,QICL + %CL1QO,,QOCL +IFN VIDP,DNVDIU:: REPEAT 4, TVCCLS ;TVC +IFN PDP6P,PDPUIO:: REPEAT 4, %CLS6 ,,PDPCLS ;USR IN PDP10 MODE +IFN TABP,DTABUI:: REPEAT 2, %CLSNR,,TABUSR ;TABLET +IFN NMTCS,[ +MTUAIX:: REPEAT 3, MTICL ;MAG TAPE + REPEAT 3, MTOCL + ] +JDUAI:: REPEAT 3,[ + %CLSJI,,JOBCLS ;JOB DEVICE + %CLSJO,,JOBCLS + ] +BDUAI:: REPEAT 6, %CLSBJ,,CPOPJ ;BOJ +IIOPOP:: [JRST 4,CPOPJ] ;INTERRUPT ON IOPOP DEVICE +ISPY:: CPOPJ ;SPY +STYDUI:: REPEAT 2,[ ;PSEUDO TTY + %CLSST,,STYICL + %CLSST,,STYOCL + ] +IFN NCPP,NETDUI:: REPEAT 4, NETCLS ; Arpanet NCP +IFN TCPP,TCPDUI:: REPEAT 4, TCPCLS ; Internet TCP +IFN INETP,IPQDN:: IPQCLS ; Internet Queue +IFN MSPP,MSPIO:: MSCLOS ;MESS SWITCHER (DM) +IFN STKP,STKDP:: STKCLS ;STANFORD KEYBOARD +IFN NTYP,NTYIT:: REPEAT 4, NTYCLS ;A KLUDGE ON THE NTY + OFFSET 0 +IF2,IFN .-CLSTB-LIOTTB,.ERR BARF AT CLSTB + +;DISPATCH TABLE FOR .IOT UUO +;TRANSFERED THROUGH USING RIGHT HALF OF I/O CHANNEL WORD AS AN INDEX +%IOT==1,,525252 +%IOTBK==400000 ;4.9 = 1 => BLOCK = 0 => UNIT +%IOTOT==200000 ;4.8 = 1 => OUTPUT = 0 => INPUT " +%IOTBP==100000 ;4.7 = 1 => THERE IS A SPECIAL ROUTINE FOR SIOT, + ;AND ITS ADDRESS IS -1 + RH(IOTTB WORD). +%IOTSP==40000 ;4.6 => THIS DEVICE IS FUNNY. SIOT ISN'T ALLOWED, + ;AND IOT LETS THE DEVICE RTN DO ALL THE WORK. + ;PRESENT ONLY FOR UNIT INPUT MODES. +%IOT10==20000 ;4.5 => THIS CHANNEL WAS OPENED WITH BIT 1.4 SET IN MODE +%IOTIM==10000 ;4.4 => THIS CHANNEL WAS OPENED WITH BIT 1.3 (IMAGE MODE) SET IN MODE +; 4000 ;4.3 COPIES %IOTBK. THUS, BITS 4.5-4.2 REFLECT THE BOTTOM 4 BITS +; 2000 ;4.2 COPIES %IOTOT. OF THE OPEN-MODE. +%IOTOM==36000 ;BITS 4.5 - 4.2 + +%IOTBO==606000 ;BLOCK OUTPUT. +%IOTBI==404000 ;BLOCK INPUT. +%IOTUO==202000 ;UNIT OUTPUT. +%IOTUI==000000 ;UNIT INPUT. + +IOTTB: IOCER8 + OFFSET -IOTTB +TYIDN:: %IOTUI,,TYI ;TTY ENTRIES MUST BE COMPACT +TYIBN:: %IOTBI,,TTYBI +TYODN:: %IOTUO,,TYO (%IOTBP) +TYOBN:: %IOTBO,,TTYBO ;LAST TTY DEVICE +NLIDN:: %IOTUI,,NULI +NLBIDN:: %IOTBI,,NULBI +NLODN:: %IOTUO,,CPOPJ +NLBDN:: %IOTBO,,NULBOD +UWIDN:: %IOTUI,,UWI (%IOTIM) +UBIDN:: %IOTBI,,UBI +UWODN:: %IOTUO,,UWO (%IOTIM) +UBODN:: %IOTBO,,UBO +FUWIDN:: %IOTUI,,UWI (%IOT10) +FUBIDN:: %IOTBI,,UBI (%IOT10) +DNDIRH:: %IOTUI,,IOCR10 +DNTRAP:: TRPDEV +DNLCK:: %IOTUO,,IOCR10 +IFN KS10P,[ +DNUBI:: %IOTUI,,IOCR10 +];KS10P +IFN CHAOSP,[ +CHAIDN:: %IOTUI+%IOTBP,,CHAUI +CHAODN:: %IOTUO+%IOTBP,,CHAUO +];CHAOSP +IFN NUNITS,[ +DNUACII:: %IOTUI,,UASCII +DNUACCO:: %IOTUO,,UASCCO +DNUBKI:: %IOTBI,,UBLKI +DNUBKO:: %IOTBO,,UBLKO +DNUDTI:: %IOTUI,,UDATAI (%IOTIM) +DNUDTO:: %IOTUO,,UDATAO (%IOTIM) +] +IFN OLPTP,[ +LPTDN:: %IOTUO,,PILPT1 +LPTBN:: %IOTBO,,BLPTO +] +IFN NLPTP,[ +NLPTDN:: %IOTUO,,NLPT1 +NLPTBN:: %IOTBO,,BNLPTO +] +IFN GLPTP,[ +GLPTDN:: %IOTUO,,GLPTDO (%IOTBP) +GLPTBN:: %IOTBO,,GLPTBO +] +DIRCHN:: %IOTUI,,DIRCH +DIRBN:: %IOTBI,,DIRB +NDATAI:: %IOTUI,,DDATAI (%IOTIM+%IOTBP) +NBLKI:: %IOTBI,,DBLKI (%IOTIM) +IFN VIDP,[ +NVIDOP:: %IOTUI,,NVIDIT (%IOTSP) +BNVIDO:: %IOTBI,,BNVIDI +] +IFN PLTP,[ +PLTDN:: %IOTUO,,PLOT +PLTBN:: %IOTBO,,BPLOT +] +IFN PTRP,[ +PTPI:: %IOTUO,,PIPUN (%IOT10) +PTPA:: %IOTUO,,APIPUN +PTPB:: %IOTBO,,BPIPUN +PTPWA:: %IOTUO,,WAPIPN (%IOTIM) +PTPWB:: %IOTBO,,WBPIPN (%IOTIM) +] +IFN IMXP,[ +IMPXDN:: %IOTUI,,IMPXS (%IOTSP) +IMXDN:: %IOTUI,,IMPXS1 (%IOTSP) +BIMXDN:: %IOTBI,,BIMXS1 (%IOTSP) +BIMPXD:: %IOTBI,,BIMPXS (%IOTSP) +] +IFN OMXP,[ +OMPXDN:: %IOTUO,,OMPXS (%IOTSP) +OMXDN:: %IOTUO,,OMXDS (%IOTSP) +BOMXDN:: %IOTBO,,BOMXDS (%IOTSP) +BOMPXD:: %IOTBO,,BOMPXS (%IOTSP) +] +DCLUAI:: %IOTUI,,CLUAI +DCLUAO:: %IOTUO,,CLUAO +DCLBI:: %IOTBI,,CLBI +DCLBO:: %IOTBO,,CLBO +DCLUBI:: %IOTUI,,CLUBI (%IOTIM) +DCLUBO:: %IOTUO,,CLUBO (%IOTIM) +IFN PTRP,[ +REDUAI:: %IOTUI,,PTRUAI +REDBAI:: %IOTBI,,PTRBAI +REDUII:: %IOTUI,,PTRUII (%IOTIM) +REDBII:: %IOTBI,,PTRBII (%IOTIM) +REDUTI:: %IOTUI,,PTRUTI (%IOT10) +] +IFN 340P,[ +DN340B:: %IOTBO,,340B ;340 ENTRIES MUST BE COMPACT; BLOCK FIRST, THEN UNIT +DN340W:: %IOTUO,,340W (%IOTSP) +DN340C:: %IOTUO,,340C (%IOTSP) +DN340H:: %IOTUO,,340H (%IOTSP) +;DN340I:: %IOTUO,,340I (%IOTSP) +DN340L:: ;LAST 340 DEVICE ENTRY +] +IFN CODP,[ +CODDN:: %IOTUO,,SEND +CODBN:: %IOTBO,,BSEND +] +DQUAI:: %IOTUI,,QUAI (%IOTBP) +DQUAO:: %IOTUO,,QUAO (%IOTBP) +DQBI:: %IOTBI,,QBI +DQBO:: %IOTBO,,QBO +DQUII:: %IOTUI,,QUII (%IOTIM %IOTBP) +DQUIO:: %IOTUO,,QUIO (%IOTIM %IOTBP) +IFN VIDP,[ +DNVDIU:: %IOTUI,,RNVDIU (%IOTSP) +DNVDIB:: %IOTBI,,RNVDIB (%IOTSP) +DNVDOU:: %IOTUO,,RNVDOU (%IOTSP) +DNVDOB:: %IOTBO,,RNVDOB (%IOTSP) +] +IFN PDP6P,[ +PDPUIO:: %IOTUO,,UWO ;BUT JOB WILL BE -1 TO INDICATE PDP6 +PDPBIO:: %IOTBO,,UBO +PDPUII:: %IOTUI,,UWI +PDPBII:: %IOTBI,,UBI +] +IFN TABP,[ +DTABUI:: %IOTUI,,UTABI +DTABBI:: %IOTBI,,BTABI +] +IFN NMTCS,[ +MTUAIX:: %IOTUI,,MTUAI (%IOTBP) ;MAGTAPE +MTUIIX:: %IOTUI,,MTUII (%IOTIM %IOTBP) +MTBIX:: %IOTBI,,MTBI +MTUAOX:: %IOTUO,,MTUAO (%IOTBP) +MTUIOX:: %IOTUO,,MTUIO (%IOTIM %IOTBP) +MTBOX:: %IOTBO,,MTBO +] +JDUAI:: %IOTUI,,JBUI(%IOTBP) +JDUAO:: %IOTUO,,JBUI(%IOTBP) +JDBI:: %IOTBI,,JBBI +JDBO:: %IOTBO,,JBBI +JDUII:: %IOTUI,,JBUI (%IOTBP %IOTIM) +JDUIO:: %IOTUO,,JBUI (%IOTBP %IOTIM) +BDUAI:: %IOTUI,,BJUI +BDUAO:: %IOTUO,,BJUO +BDBI:: %IOTBI,,BJBI +BDBO:: %IOTBO,,BJBO +BDUII:: %IOTUI,,BJUI (%IOTIM) +BDUIO:: %IOTUO,,BJUO (%IOTIM) +IIOPOP:: [JRST 4,CPOPJ] ;INTERRUPT ON IOPOP DEVICE +ISPY:: %IOTUI,,SPYI +STYDUI:: %IOTUI,,STTYI ;PSEUDO TTY +STYDUO:: %IOTUO,,STTYW +STYDBI:: %IOTBI,,STTBI +STYDBO:: %IOTBO,,STTBO +IFN NCPP,[ +NETDUI:: %IOTUI,,NETI +NETDUO:: %IOTUO,,NETW (%IOTBP) +NETDBI:: %IOTBI,,NETBI +NETDBO:: %IOTBO,,NETBO +] +IFN TCPP,[ +TCPDUI:: %IOTUI,,TCPI (%IOTBP) +TCPDUO:: %IOTUO,,TCPW (%IOTBP) +TCPDBI:: %IOTBI,,TCPBI +TCPDBO:: %IOTBO,,TCPBO +] +IFN INETP,[ +IPQDN:: IPQIO ; No I/O calls used on this dev! +] +IFN MSPP,[ +MSPIO:: IOCR10 +] +IFN STKP,[ +STKDP:: STKI +] +IFN NTYP,[ +NTYIT:: %IOTUI,,NTYTI ;KLUDGE FOR FAST, LARGE BUFFER ON NTY +NTYOT:: %IOTUO,,NTYTO +NTYBIT:: %IOTBI,,NTYBI +NTYBOT:: %IOTBO,,NTYBO +] + OFFSET 0 +LIOTTB==.-IOTTB + +;TABLES FOR VARIOUS CHANNEL STATUS CALLS + +;DCHSTB - INDEXED BY IOTTB INDEX (RH OF IOCHNM) +;LH SIXBIT MAIN DEVICE NAME +;1.1-2.3 INDEX INTO THE NEXT TWO TABLES +;2.4-2.9 SYSTEM PERIPHERAL DEVICE CODE (FOR .STATUS) +.SEE DCHSTB ;ASSEMBLED SECOND TO GET VALUES OF THE TEMPORARY %%dev SYMBOLS. + +;DSTSTB - INDEX FROM DCHSTB +;LH STATUS ROUTINE, RH WHYINT ROUTINE (OPNL34 IF DEVICE DOESN'T GIVE 2ND WD INTS) + +DSTSTB: CPOPJ,,OPNL44 ;0 CHANNEL NOT OPEN + STDSTA,,OPNL34 ;1 RANDOM DEVICE + CPOPJ,,OPNL34 ;2 OTHER KIND OF RANDOM DEVICE + STATYI,,TYIWHY ;3 TTY INPUT + STATYO,,TYOWHY ;4 TTY OUTPUT + CPOPJ,,OPNL34 ;5 USR DEVICE + CPOPJ,,OPNL34 ;6 DIR "DEVICE" + CLISTA,,OPNL34 ;7 CORE LINK INPUT + STDSTA,,OPNL34 ;10 CORE LINK OUTPUT + CPOPJ,,OPNL34 ;11 DISK + JBSTAT,,OPNL22 ;12 JOB DEVICES (WHYINT SHOULDN'T GET HERE) + CPOPJ,,OPNL34 ;13 BOJ DEVICE + STASTI,,STIWHY ;14 STY INPUT + STASTO,,STOWHY ;15 STY OUTPUT + CPOPJ,,TRPDEV ;16 TRAP DEVICE + CPOPJ,,OPNL34 ;17 DIRHNG DEVICE + CPOPJ,,OPNL34 ;20 SPY DEVICE + CPOPJ,,OPNL34 ;21 LOCK DEVICE +OFFSET -DSTSTB ;BEGIN OPTIONAL DEVICES +IFN KS10P, %%UBI:: CPOPJ,,UBIWHY +IFN NMTCS, %%MT:: STAMTC,,OPNL34 +IFN NUNITS,%%UTP:: CPOPJ,,OPNL34 +IFN OLPTP, %%OLP:: STALPT,,OPNL34 +IFN NCPP, %%NET:: STANET,,NETWHY +IFN TCPP, %%TCP:: TCPSTA,,TCPWHY +IFN INETP, %%IPQ:: IPQSTA,,IPQWHY +IFN CHAOSP,%%CHA:: CPOPJ,,CHAWHY +OFFSET 0 + +;DRFNTB - INDEX FROM DCHSTB +;LH RFNAME ROUTINE, RH RFPNTR ROUTINE OR OPNL34 IF NOT RANDOM ACCESS + +DRFNTB: CPOPJ,,OPNL44 ;0 CHNL NOT OPEN + CPOPJ,,OPNL34 ;1 RANDOM DEVICE + CPOPJ,,OPNL34 ;2 OTHER KIND OF RANDOM DEVICE + RCHTTY,,OPNL34 ;3 TTY INPUT + RCHTTY,,OPNL34 ;4 TTY OUTPUT + RCHUSR,,RFPUSR ;5 USR DEVICE + RCHDIR,,OPNL34 ;6 DIR "DEVICE" + RCHCLO,,OPNL34 ;7 CORE LINK INPUT + RCHCLO,,OPNL34 ;10 CORE LINK OUTPUT + RCHQSK,,RFPQSK ;11 DISK + RFNJOB,,RFPJOB ;12 JOB DEVICES + RCHBOJ,,OPNL34 ;13 BOJ DEVICE + RCHSTY,,OPNL34 ;14 STY INPUT + RCHSTY,,OPNL34 ;15 STY OUTPUT + CPOPJ,,CPOPJ ;16 TRAP DEVICE + RCHDRH,,OPNL34 ;17 DIRHNG DEVICE + SPYRCH,,OPNL34 ;20 SPY DEVICE + LCKRCH,,OPNL34 ;21 LOCK DEVICE +OFFSET -DRFNTB ;BEGIN OPTIONAL DEVICES +IFN KS10P, %%UBI:: UBIRCH,,OPNL34 +IFN NMTCS, %%MT:: RCHMGT,,OPNL34 +IFN NUNITS,%%UTP:: RCHUTP,,OPNL34 +IFN OLPTP, %%OLP:: CPOPJ,,OPNL34 +IFN NCPP, %%NET:: NETRCH,,OPNL34 +IFN TCPP, %%TCP:: TCPRCH,,TCPRFP +IFN INETP, %%IPQ:: IPQRCH,,IPQRFP +IFN CHAOSP,%%CHA:: CHARCH,,OPNL34 +OFFSET 0 +IFN <.-DRFNTB>-, .ERR DRFNTB & DSTSTB NOT SAME LENGTH + +DEFINE XX NTIMES,DEVNAM,DN,SNXXX,IDX +IFNB DN, DN==:.-DCHSTB ;CHECK THAT DCHSTB IS IN SAME ORDER AS IOTTB +IFG SIXBIT/DEVNAM/, ZZ==[SIXBIT/DEVNAM/] ;DECIDE WHETHER FITS IN LH +.ELSE [ +IFE SIXBIT/DEVNAM/&777777, ZZ==(SIXBIT/DEVNAM/) +.ELSE ZZ==[SIXBIT/DEVNAM/] +] +REPEAT NTIMES, ZZ,,SNXXX_14+IDX +TERMIN + +DCHSTB: XX 1,,,,0 ;CHNL NOT OPEN + XX 2,TTY,TYIDN,,3 ;TTY INPUT + XX 2,TTY,TYODN,,4 ;TTY OUTPUT + XX 4,NUL,NLIDN,SNNUL,1 ;NUL DEVICE + XX 4,USR,UWIDN,SNUSR,5 ;USR DEVICE + XX 2,USR,FUWIDN,SNFUSR,5 ;FOREIGN USR + XX 1,DIRHNG,DNDIRH,SNDIRH,17 ;DIRHNG + XX 1,TRAP,DNTRAP,SNTRAP,16 ;TRAP + XX 1,LOCK,DNLCK,SNLCK,21 ;LOCK +IFN KS10P, XX 1,UBI,DNUBI,SNUBI,%%UBI ;UBIBUS INTERRUPT +IFN CHAOSP, XX 2,CHAOS,CHAIDN,SNCHA,%%CHA ;CHAOS NET +IFN NUNITS, XX 6,UT,DNUACII,SNUTC,%%UTP ;MICRO TAPE +IFG LPTP-1, XX 2,OLP,LPTDN,SNLPD,%%OLP ;DATA PRODUCTS LPT IN 2-LPT SYSTEM +.ELSE IFN OLPTP, XX 2,LPT,LPTDN,SNLPD,%%OLP ;DATA PRODUCTS LPT +IFN NLPTP, XX 2,LPT,NLPTDN,SNLPV,1 ;"VOGUE" LPT (ACTUALLY ODEC) +IFN GLPTP, XX 2,LPT,GLPTDN,SNLPV,1 ;GOULD LPT + XX 4,DIR,DIRCHN,SNDIR,6 ;DIR "DEVICE" +IFN VIDP, XX 2,NVD,NVIDOP,SNBAT,2 ;VIDISSECTOR +IFN PLTP, XX 2,PLT,PLTDN,SNPLT,1 ;PLOTTER +IFN PTRP, XX 5,PTP,PTPI,SNPTP,1 ;PAPER TAPE PUNCH +IFN IMXP, XX 4,IMX,IMPXDN,SNIMPX,1 ;INPUT A/D MULTIPLEXOR +IFN OMXP, XX 4,OMX,OMPXDN,SNOMPX,1 ;OUTPUT A/D MULTIPLEXOR + XX 3,CLO,DCLUAI,SNCLK,7 ;CORE LINK INPUT + XX 3,CLO,DCLBO,SNCLK,10 ;CORE LINK OUTPUT +IFN PTRP, XX 5,PTR,REDUAI,SNPTR,1 ;PAPER TAPE READER +IFN 340P, XX 4,DIS,DN340B,SN340,2 ;340 DISPLAY +;IFN 340P, XX 1,IDS,DN340I,SN340I,2 ;340 INTERPRETIVE DISPLAY +IFN CODP, XX 2,COD,CODDN,SNCOD,1 ;CODE + XX 6,DSK,DQUAI,SN2311,11 ;DISK +IFN VIDP, XX 4,TVC,DNVDIU,SNBAT,2 ;TV CAMERA +IFN PDP6P, XX 4,PDP,PDPUIO,SNPDP,5 ;PDP-6 DEVICE +IFN TABP, XX 2,TAB,DTABUI,SNTAB,2 ;TABLET +IFN NMTCS, XX 6,MT0,MTUAIX,SNMTC,%%MT ;MAGTAPE + XX 6,JOB,JDUAI,SNJOB,12 ;JOB DEVICES + XX 6,BOJ,BDUAI,SNBOJ,13 ;BOJ DEVICE + XX 1,IIP,IIOPOP,0,2 ;INTERRUPT-ON-IOPOP DEVICE + XX 1,SPY,ISPY,SNSPY,20 ;SPY +REPEAT 2,[ + XX 1,STY,,SNSTY,14 ;STY INPUT + XX 1,STY,,SNSTY,15 ;STY OUTPUT +] +IFN NCPP, XX 4,NET,NETDUI,SNNET,%%NET ; Arpanet NCP +IFN TCPP, XX 4,TCP,TCPDUI,SNTCP,%%TCP ; Internet TCP +IFN INETP, XX 1,IPQ,IPQDN,SNIPQ,%%IPQ ; Internet Queue +IFN MSPP, XX 1,MSP,MSPIO,SNMSP,2 ;MS SWITCH HACK +IFN STKP, XX 1,STK,STKDP,SNSTK,2 ;STANFORD KEYBOARD +IFN NTYP, XX 4,NTY,NTYIT,SNNUL,2 ;NTY 11 KLUDGE + +IFN .-DCHSTB-LIOTTB,.ERR BARF AT DCHSTB +EXPUNGE XX,%%UBI,%%MT,%%UTP,%%OLP,%%NET,%%TCP,%%CHA,%%IPQ + +DCHSTE==.-1 ;END FOR GETSYS (CHDEVS) + +;RSTB - INDEXED BY IOTTB INDEX FROM RH(IOCHNM) +;THIS TABLE IS IN 5-BIT BYTES; THE VALUES ARE THE INDICES +;INTO THE RSTB1 AND DFRCTB TABLES. +.SEE RSTB ;ASSEMBLED SECOND TO GET VALUES OF TEMPORARY %%dev SYMBOLS. + +;RSTB1 - INDEX FROM RSTB (BELOW) +;LH IOPUSH/POP ROUTINE, RH RESET ROUTINE +RSTB1: CPOPJ,,CPOPJ ;0 RANDOM DEVICE + TYIIOP,,TYIRS ;1 TTY INPUT + TYOIOP,,TYORS ;2 TTY OUTPUT + CPOPJ,,USRST ;3 USR DEVICE + CPOPJ,,JBIRS ;4 JOB INPUT + CPOPJ,,JBORS ;5 JOB OUTPUT + IIOPPR,,[JRST 4,CPOPJ] ;6 INTERRUPT ON IOPOP DEVICE + STYIIP,,STYIRS ;7 STY INPUT + STYOIP,,STYORS ;10 STY OUTPUT + CPOPJ,,CPOPJ ;11 DISK OUTPUT + DIRHIP,,CPOPJ ;12 DIRHNG + CPOPJ,,TRPDEV ;13 TRAP + OFFSET -RSTB1 ;OPTIONAL DEVICES BEGIN HERE +IFN KS10P, %%UBI:: UBIIOP,,CPOPJ +IFN OLPTP, %%LPT:: CPOPJ,,LPTRS +IFN NLPTP, %%NLP:: CPOPJ,,NLPTRS +IFN PLTP, %%PLT:: CPOPJ,,PLTRS +IFN PTRP, %%PTR:: CPOPJ,,PTRRS +IFN PTRP, %%PTP:: CPOPJ,,PUNCLR +IFN IMXP, %%IMX:: CPOPJ,,IMPXRS +IFN 340P, %%340:: CPOPJ,,DSIZAP +IFN CODP, %%COD:: CODIOP,,CODRS +IFN PDP6P, %%PDP:: PDPIOP,,PDPRST +IFN TABP, %%TAB:: CPOPJ,,TABCLR +IFN NCPP, %%NET:: NETIOP,,NETRS +IFN TCPP, %%TCP:: TCPIOP,,TCPRST +IFN INETP, %%IPQ:: IPQIOP,,IPQRST +IFN STKP, %%STK:: CPOPJ,,STKRS +IFN CHAOSP,%%CHA:: CHAIOP,,CPOPJ + OFFSET 0 + +;DFRCTB - INDEX FROM RSTB (BELOW) +;LH FORCE ROUTINE, RH FINISH ROUTINE +DFRCTB: OPNL34,,OPNL34 ;0 RANDOM DEVICE + OPNL2,,OPNL2 ;1 TTY INPUT (ILLEGAL) + POPJ1,,TTYFIN ;2 TTY OUTPUT + OPNL34,,OPNL34 ;3 USR + OPNL2,,OPNL2 ;4 JOB (SHOULDN'T GET HERE?) + OPNL22,,OPNL22 ;5 JOB (SHOULDN'T GET HERE?) + OPNL22,,OPNL22 ;6 IIP (SHOULDN'T GET HERE) + OPNL2,,OPNL2 ;7 STY INPUT (ILLEGAL) + POPJ1,,STYFIN ;10 STY OUTPUT + QSKFRC,,QSKFIN ;11 DISK OUTPUT + OPNL34,,OPNL34 ;12 DIRHNG + TRPDEV,,TRPDEV ;13 TRAP + OFFSET -DFRCTB ;OPTIONAL DEVICES BEGIN HERE +IFN KS10P, %%UBI:: OPNL34,,OPNL34 +IFN OLPTP, %%LPT:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN NLPTP, %%NLP:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN PLTP, %%PLT:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN PTRP, %%PTR:: OPNL34,,OPNL34 +IFN PTRP, %%PTP:: POPJ1,,PUNFIN +IFN IMXP, %%IMX:: OPNL34,,OPNL34 +IFN 340P, %%340:: OPNL34,,OPNL34 +IFN CODP, %%COD:: POPJ1,,CODFIN +IFN PDP6P, %%PDP:: OPNL34,,OPNL34 +IFN TABP, %%TAB:: OPNL34,,OPNL34 +IFN NCPP, %%NET:: NETFRC,,NETFIN +IFN TCPP, %%TCP:: TCPFRC,,TCPFIN +IFN INETP, %%IPQ:: IPQFRC,,IPQFIN +IFN STKP, %%STK:: OPNL34,,OPNL34 +IFN CHAOSP,%%CHA:: CHAFRC,,CHAFIN + OFFSET 0 + +;TABLE OF INDICES INTO THE RSTB1, DFRCTB TABLES ON THE PRECEDING PAGE +;THESE INDICES ARE UNRELATED TO THE INDICES IN DCHSTB A COUPLE PAGES BACK. +;NOTE THAT THE %% SYMBOLS ARE PURELY TEMPORARY AND EXPUNGED AT THE BOTTOM OF THIS PAGE. + +RSTB: .BYTE 5 + + 0 ;CHNL NOT OPEN + REPEAT 2,1 ;TTY INPUT + REPEAT 2,2 ;TTY OUTPUT + REPEAT 4,0 ;NUL DEVICE + REPEAT 4,3 ;USR DEVICE + REPEAT 2,0 ;FOREIGN USR + 12 ;DIRHNG + 13 ;TRAP + 0 ;LOCK +IFN KS10P, %%UBI ;UNIBUS INTERRUPT +IFN CHAOSP, REPEAT 2,%%CHA +IFN NUNITS, REPEAT 6,0 ;DEC TAPE +IFN OLPTP, REPEAT 2,%%LPT +IFN NLPTP, REPEAT 2,%%NLP +IFN GLPTP, REPEAT 2,0 + REPEAT 4,0 ;DIR "DEVICE" +IFN VIDP, REPEAT 2,0 +IFN PLTP, REPEAT 2,%%PLT +IFN PTRP, REPEAT 5,%%PTP +IFN IMXP, REPEAT 4,%%IMX +IFN OMXP, REPEAT 4,0 + REPEAT 6,0 ;CORE LINK. +IFN PTRP, REPEAT 5,%%PTR +IFN 340P, REPEAT 4,%%340 +;IFN 340P, 0 +IFN CODP, REPEAT 2,%%COD ;CODE + REPEAT 3, 0 ? 11 ;DISK IN, DISK OUT +IFN VIDP, REPEAT 4,0 +IFN PDP6P, REPEAT 4,%%PDP ;PDP-6 DEVICE +IFN TABP, REPEAT 2,%%TAB +IFN NMTCS, REPEAT 6,0 ;MAGTAPE + REPEAT 3,[4 + 5 + ] ;JOB + REPEAT 3,[0 ;BOJ INPUT + 0 ;BOJ OUTPUT + ] ;BOJ + 6 ;INTERRUPT ON IOPOP DEVICE + 0 ;SPY + 7 ? 10 ? 7 ? 10 ;PSEUDO-TTY +IFN NCPP, REPEAT 4,%%NET ;NET RESET INR/INS +IFN TCPP, REPEAT 4,%%TCP ; TCP RESET +IFN INETP, %%IPQ ; Internet Queue +IFN MSPP, 0 ;MS SWITCH HACK +IFN STKP, %%STK ;STANFORD KEYBOARD +IFN NTYP, REPEAT 4,0 ;NTY 11 KLUDGE + +IFN LIOTTB-.BYTC,.ERR BARF AT RSTB + .BYTE +EXPUNGE %%UBI,%%LPT,%%NLP,%%PLT,%%PTR,%%PTP,%%IMX,%%340,%%COD,%%PDP,%%TAB,%%NET,%%TCP,%%STK,%%CHA,%%IPQ + +DEFINE DVHR X,Y +X!Y!TERMIN + +DEFINE DV NAME,OPNRTE,BITS,TAG + SIXBIT/NAME/ +DVHR [DEFINE DVHR X,Y +X!][TAG BITS,,OPNRTE +Y!TERMIN] +TERMIN + +;DEVICE TABLES FOR AOPEN +; +;DEVTAB SIXBIT NAME +;DEVADR + %DVIN==400000 ;4.9 DEVICE CAN DO INPUT + %DVOUT==200000 ;4.8 DEVICE CAN DO OUTPUT + %DVDIR==100000 ;4.7 DEVICE CAN GIVE DIRECTORY + %DVDEL==40000 ;4.6 ALLOW DELETE/RENAME + %DVLNK==20000 ;4.5 ALLOW MLINK + ;RIGHT HALF, OPEN ROUTINE ADDRESS +%DV==1,,520000 ;BIT TYPEOUT MASK + +DEVTAB: +IFN NLPTP, DV LPT,NLPTO,%DVOUT +IFG OLPTP-NLPTP,DV LPT,LPTO,%DVOUT +IFG LPTP-1, DV OLP,LPTO,%DVOUT +IFN GLPTP, DV LPT,GLPTO,%DVOUT +IFN TTLPTP, DV LPT,LPTO,%DVOUT + + DV DSK,QSKO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,DVAQSK: + DV COM,COMO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + MNAME [ DV ],QSKO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;"AI:" ON + ; AI, ETC. + DV SYS,SYSO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + DV DNRF,DNRFO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;DSK NO REF DATE + DV DNR,DNRFO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;DSK NO REF DATE + DV DIRHNG,DIRHO,%DVIN + DV TRAP,TRPDEV,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + DV LOCK,LCKO,%DVOUT + DV UBI,UBIO,%DVIN + DV TTY,TTYO1,%DVIN+%DVOUT+%DVDIR + DV NUL,NULO,%DVIN+%DVOUT + DV USR,USRO,%DVIN+%DVOUT +IFN VIDP, DV NVD,NVIDI,%DVIN+%DVOUT +IFN CHAOSP, DV CHAOS,CHASO,%DVIN+%DVOUT +IFN NCPP, DV NET,NETO,%DVIN+%DVOUT +IFN TCPP, DV TCP,TCPO,%DVIN+%DVOUT +IFN INETP, DV IPQ,IPQO,%DVIN+%DVOUT +IFN MSPP, DV IPC,IPCO,%DVIN+%DVOUT + DV STY,STTYO,%DVIN+%DVOUT + DV JOB,JOBO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,DVAJOB: + DV BOJ,BOJO,%DVIN+%DVOUT + DV OJB,JOBO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK +IFN STKP, DV STK,STKO,%DVIN +IFN PLTP, DV PLT,PLOTO,%DVOUT +IFN PLTP, DV IPL,IPLO,%DVOUT ;INTERPRETED PLOTTER +IFN XGP, DV XPL,XPLO,%DVOUT +IFN IMXP, DV IMX,IMPXO,%DVIN +IFN OMXP, DV OMX,OMPXO,%DVOUT +IFN PTRP, DV PTR,PTRO,%DVIN +IFN PTPP, DV PTP,PTPO,%DVOUT +IFN 340P, DV DIS,DISO,%DVOUT ;340 AS OUTPUT DEVICE +;IFN 340P, DV IDS,IDISO,%DVOUT ;340 AS INTERPRETED DISPLAY + DV CLU,CLUO,%DVIN+%DVOUT+%DVDIR+%DVDEL + DV CLO,CLOO,%DVIN+%DVOUT+%DVDIR+%DVDEL + DV CLI,CLIO,%DVOUT+%DVDIR+%DVDEL + DV CLA,CLAO,%DVIN+%DVDIR+%DVDEL +IFN CODP, DV COD,CODO,%DVOUT +IFN VIDP, DV TVC,TVCO,%DVIN+%DVOUT + DV ERR,ERRO,%DVIN +IFN TPLP+TTLPTP&DEMON, DV TPL,TPLO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK +IFN TABP, DV TAB,TABO,%DVIN + DV SPY,SPYO,%DVIN + DV COR,CORO,%DVDIR ;DIR=LAST LINE OF TTY^F +IFN NTYP, DV NTY,NTYOPN,%DVIN+%DVOUT ;NTY 11 KLUDGE + +NDEVS==.-DEVTAB + +DVT1: DV TTY,TTYO,%DVIN+%DVOUT+%DVDIR + DV TY,TTYO,%DVIN+%DVOUT+%DVDIR + DV T,TTYO,%DVIN+%DVOUT+%DVDIR +IFN NUNITS, DV UT,UTO,%DVIN+%DVOUT+%DVDIR+%DVDEL,DVAUT: + DV STY,STTYOA,%DVIN+%DVOUT + DV ST,STTYOA,%DVIN+%DVOUT + DV S,STTYOA,%DVIN+%DVOUT + DV DSK,QSKUO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR UNIT + DV DK,QSKUO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR UNIT + DV PK,QSKPO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR PACK + DV P,QSKPO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR PACK +IFN NMTCS, DV MT,MAGTO,%DVIN+%DVOUT ;MAGTAPE + +NDV1==.-DVT1 +EDEVS==.-1 ;END FOR GETSYS (DEVS) + +DEVADR: DVHR +IFN .-DEVADR-NDEVS-NDV1,.ERR DVHR LOST + +SUBTTL .OPER, .CALL DISPATCH + +AOPER: MOVE J,R ;AC FIELD OF UUO + ADDI R,IOCHNM(U) ;SET UP IO CHANNEL REFERENCE POINTER + CAIL C,MXOPR ;SKIP IF UUO E FIELD IS LESS THAN MAX OPR + JRST ILUUO ;ILLEGAL OPER + JRST @OPRDSP(C) ;LEGAL OPER-- DISPATCH ON E FIELD OF UUO + +OPRDSP: ILUUO + OPRIRP A!X ;AITYI,ALISTEN,ASLEEP,ETC. + +; +;CALL DISPATCH +; +ACALL: MOVE B,C ;SET UP COPY OF ERR ADR NOT TO BE RELOCATED + JRST @CALDIS(R) ;DISPATCH INDEX OF UUO'S AC FIELD + +CALDIS: ASYSC + ADISMIS + ALOSE + ATRANAD + AVALRET ;4 + AUTRAN + UACORE + ATRNDL + ADSTART ;10 + AFDELE + ADSTL + ASUSET + ALTPEN ;14 + AVSCAN + APOTSET +REPEAT 20-.+CALDIS,ILUUO + +SUBTTL MISCELLANEOUS UUO'S + +;SHUT DOWN SYSTEM + +ASHUTD: UMOVE C,(J) ;Arg is time to down in thirtieths. + JUMPL C,AREVIV ;Negative time means REVIVE. + CAMG C,[43200.*30.*60.] ;If time is longer than thirty days + CAIGE C,5*60.*30. ; or less than five minutes + POPJ P, ; Fail (prevent clock delta-T from losing). + ADD C,TIME ;Interval+now is when we will die. + PUSHJ P,SWTL ;Seize shutdown lock. + SHUTLK + SKIPGE SHUTDN ;Already down? + JRST LSWPOP ; Yes. + PUSHJ P,CLQDEL ;Flush obsolete clock queue entry, if any. + DEDBLK + MOVEM C,SHUTDN ;Remember time we will die. + SUB C,TIME ;Interval until death. + LSH C,1 ;Time till death after next clock-queue int. + MOVEM C,DEDTIM ;Remember time until death. + PUSHJ P,DEATHX ;Make DEATH entry on clock queue. + BUG ; DEDTIM says time to die already? + JRST LSWPJ1 ;Unlock shutdowns. + +;READ TIME TILL SYSTEM DOWN + +ADIETI: XCTR XW,[SETOM (J)] ;READ -1 IF NOT GOING DOWN + SKIPG A,SHUTDN + POPJ P, ;NOT DYING + SUB A,TIME + JRST APTUAJ ;GIVE TO USER + +;REVIVE SYS + +AREVIV: PUSHJ P,SWTL + SHUTLK + SKIPN SHUTDN + JRST LSWPOP ;NOT DYING + PUSHJ P,CLQDEL + DEDBLK + SETZM SHUTDN + SETZM DEDTIM + PUSHJ P,DEATHM + JRST LSWPOP + +;FROM CLOCK QUEUE BLOCK + +DEATHZ: PUSHJ P,DEATHX + SKIPA + JRST CLQRET + MOVSI T,SCLOUT + PUSHJ P,SUPSET ;DIE + SETOM DEDTIM + JRST CLQRET + +;GET VARIOUS SYS STATUS + +ASSTAT: CONO PI,CLKOFF + SKIPLE A,SHUTDN + SUB A,TIME + SKIPG SHUTDN + SUBI A,1 ;TIME TILL DOWN IF > 0, -1 IF UP, -2 IF DOWN + CONO PI,CLKON + MOVE B,SYSDBG + MOVE C,SUSRS + MOVE D,PARERR + ADD D,NXMERR + MOVE E,TIME + MOVE TT,[ITSMCH] ;SIXBIT NAME OF THIS MACHINE. + MOVE I,[ITSVRS] + MOVN Q,USRHI ;Q GETS NUMBER OF FREE JOB SLOTS + IDIVI Q,LUBLK + ADDI Q,MAXJ + MOVE J,USRHI +ASSTT1: SUBI J,LUBLK + SKIPN UNAME(J) + ADDI Q,1 + JUMPG J,ASSTT1 + JRST POPJ1 + +SUBTTL SYMBOLIC SYSTEM CALL HANDLER + +;IN ORDER @A...Z[\]^_ !".../0...9:;,=.? (THAT IS IN NUMERICAL ORDER) + +SYSCTB: SIXBIT /ACCESS/ ;IOCHNL, ADR + SIXBIT /ATTACH/ + SIXBIT /ATTY/ + SIXBIT /CALL/ ;SIXBIT // +IFN CHAOSP,[ + SIXBIT /CHAOSO/ + SIXBIT /CHAOSQ/ +];CHAOSP + SIXBIT /CLOSE/ ;IOCHNL + SIXBIT /CNSGET/ ;GET SEMIPERMANENT TTY INFO + SIXBIT /CNSSET/ ;SET SEMIPERMANENT INFO (TCMXH, TCTYP, TTYOPT, TTYCOM, ETC) + SIXBIT /CORBLK/ ;HACK PAGE MAP + SIXBIT /CORTYP/ ;READ STATUS OF PAGE. + SIXBIT /DELETE/ ;FILE DELETE + SIXBIT /DELEWO/ ;DELETE FILE OPEN ON SPEC'D CHANNEL +IFN DEMON,SIXBIT /DEMSIG/ ;SIGNAL DAEMON + SIXBIT /DETACH/ ;DISOWN ENTIRE TREE + SIXBIT /DIRSIZ/ + SIXBIT /DISMIS/ + SIXBIT /DISOWN/ ;DISOWN AN INFERIOR JOB +IFN DL10P, SIXBIT /DL10MP/ + SIXBIT /DSKUPD/ ;SIMULATE REFERENCE OF FILE + SIXBIT /ECHOIN/ ;ECHO-NEGOTIATE + SIXBIT /FILBLK/ ; READ NAME AREA OF FILE + SIXBIT /FILLEN/ ;READ FILE LENGTH + SIXBIT /FINISH/ + SIXBIT /FLAP/ ;TAPE # + SIXBIT /FLUSH/ ;OLD NAME FOR FINISH, EVENTUALLY " + SIXBIT /FORCE/ + SIXBIT /IOPOP/ + SIXBIT /IOPUSH/ + SIXBIT /IOT/ ;IOCHNL, QUAN OR BLK POINTER +IFN INETP,SIXBIT /IPKIOT/ + SIXBIT /ITYIC/ + SIXBIT /JOBCAL/ ;GENERAL JOBGET + SIXBIT /JOBGET/ ;JOB CHNL + SIXBIT /JOBINT/ ;JOB CHNL + SIXBIT /JOBIOC/ + SIXBIT /JOBRET/ ;JOB CHNL + SIXBIT /JOBREU/ + SIXBIT /JOBSTS/ ;SET JOB CHNL STATUS +IFN KL10P,SIXBIT /KLPERF/ ;ACTIVATE & CONTROL PERFORMANCE METER + SIXBIT /LISTEN/ ;IOCHNL, ADR + SIXBIT /LNKEDP/ ;DISK CH. RETURNS NONZERO IF LINKS WERE TRACED TO OPEN IT. + SIXBIT /LOAD/ ;USER CH, I/O CH, VARBLK + SIXBIT /LOGIN/ ;SIXBIT // + SIXBIT /LOGOUT/ ;. . . + SIXBIT /LOSE/ + SIXBIT /MLINK/ ;MAKE LINK +IFN NCPP, SIXBIT /NETAC/ + SIXBIT /NETBLK/ ;HANG ON NCP STATE +IFN IMPP,[ + SIXBIT /NETHST/ ;GETS STATUS OF HOST + SIXBIT /NETIMP/ ;GETS STATUS OF IMP +];IMPP +IFN NCPP, SIXBIT /NETINT/ +IFN INETP,[ ; A temporary cond, should become permanent. + SIXBIT /NETRFC/ ; Get pending request for connection +] + SIXBIT /OPEN/ ;FILE OPEN + SIXBIT /PDUMP/ ;USER CH, I/O CH, VARBLK + SIXBIT /PGDUMP/ ;OLD NAME FOR PGWRIT, EVENTUALLY DELETE + SIXBIT /PGWRIT/ ;DUMP PAGE OUT OF CORE +IFN CHAOSP, SIXBIT /PKTIOT/ +IFN QAUTHP, SIXBIT /RAUTH/ ;READ AUTHOR OF FILE + SIXBIT /RCHST/ ;READ OPENED FILENAMES & ACCESS POINTER + SIXBIT /RCPOS/ ;READ CURSOR POS +IFN DEMON,SIXBIT /RDDMST/ ;READ DEAMON STATUS + SIXBIT /RDMPBT/ ;READ FILE DUMPED BIT IOCHN, ADR + SIXBIT /RELOAD/ + SIXBIT /RENAME/ ;FILE RENAME + SIXBIT /RENMWO/ ;RENAME WHILE OPEN + SIXBIT /REOWN/ + SIXBIT /RESET/ + SIXBIT /RESRDT/ ;RESTORE REFERENCE DATE + SIXBIT /RFDATE/ ;READ TIME OF CREATION OF FILE IOCHN, ADR + SIXBIT /RFNAME/ ;READ FILE NAME AND MODE CHANNEL OPEN TO + SIXBIT /RFPNTR/ ;READ ACCESS POINTER + SIXBIT /RQDATE/ ;READ DSK DATE + SIXBIT /RSSIZE/ ;READ SCREEN SIZE +IFN QAUTHP, SIXBIT /SAUTH/ ;SET AUTHOR OF FILE + SIXBIT /SCML/ ;SET # COMMAND LINES + SIXBIT /SCPOS/ ;SET TTY CURSOR POSITION + SIXBIT /SDMPBT/ ;SET FILE DUMPED BIT IOCHN, ADR + SIXBIT /SETIOC/ ;CAUSE IO CHANNEL ERROR IN JOB/BOJ CHANNEL + SIXBIT /SFDATE/ ;SET TIME OF CREATION OF FILE IOCHN, ADR + SIXBIT /SIOT/ ;IOT A STRING GIVEN B.P. AND LENGTH + SIXBIT /SOPEN/ ;OPEN, TAKING MODE,,CHNL AND BP. + SIXBIT /SRDATE/ ;SET REFERENCE DATE + SIXBIT /SREAPB/ ;SET THE DO NOT REAP BIT + SIXBIT /SSERVE/ ;Set .SERVER without timing errors + SIXBIT /SSTATU/ ;READS VARIOUS SYSTEM STATUS + SIXBIT /STATUS/ +IFN DEMON,SIXBIT /STDMST/ ;SET DEAMON STATUS + SIXBIT /STLGET/ ;GET INFO ON SERVER TELNET CONTROLLING A STY + SIXBIT /STYGET/ ;GET INFO ABOUT SPECIFIED STY +IFN NETP,SIXBIT /STYNET/ ;CONNECT STY TO NETWORK SOCKETS, FOR TELNET SERVERS. + SIXBIT /T11MP/ ;TEMP ? TEN11 HACKER +IFN TCPP,SIXBIT /TCPOPN/ ; Open TCP Internet connection + SIXBIT /TRANAD/ ;CREATE TRANSLATION ENTRY + SIXBIT /TRANCL/ ;CLEAR TRANSL. LIST(S) FOR A JOB. + SIXBIT /TRANDL/ ;DELETE A TRANSL. ENTRY. + SIXBIT /TRANEX/ ;READ A JOB'S TRANSL. LIST. + SIXBIT /TRANS/ ;TRANSLATE A FILENAME. + SIXBIT /TRPOPN/ ;OPEN TRAP DEVICE FOR AN INFERIOR + SIXBIT /TTYESC/ ;SIMULATE TYPING OF ^_ + SIXBIT /TTYFLS/ ;FLUSH ITYIC'ED INPUT + SIXBIT /TTYGET/ ;SUPPLY TTY CH, RETURNS THREE WORDS OF TTY STATUS + SIXBIT /TTYSET/ ;SUPPLY TTY CH AND THREE WORDS OF TTY STATUS + SIXBIT /TTYVAR/ ;HACK TTY VARIABLES + SIXBIT /TVWHER/ + SIXBIT /UNLOCK/ ;UNLOCK A SPEC'D JOBS LOCKS. + SIXBIT /USRMEM/ ;READ OR WRITE A JOB'S MEMORY. + SIXBIT /USRVAR/ ;HACK USER VARIABLES + SIXBIT /VIDBUF/ ;ASSIGN/DEASSIGN VIDEO BUFFER. + SIXBIT /VIDSW/ ;SET VIDEO SWITCH. + SIXBIT /WHOLIN/ ;GET OR SET WHO-LINE MODE AND JOB. + SIXBIT /WHYINT/ ;FIND OUT WHY AN I/O CHANNEL INTERRUPTED + SIXBIT /XGPIM/ ;OUTPUT TO XGP IN IMAGE MODE +LSYSCT==:.-SYSCTB + +ZZ==.-SYSCTB-1 +RADIX 2 +ZZ2==CONC [.LENGTH /]\ZZ,/ +RADIX 8 +REPEAT 1_-ZZ-1,377777,,-1 +;4.X BIT IMPLIES SUPPLY ROUTINE WITH POINTER TO X'TH ARG, NOT ARG ITSELF +;3.9-3.7 = MINIMUM NUMBER OF ARGS +;3.1 => DECODE 1ST ARG AS IO CHNL, LEAVING IOCHNM WD ADDR IN RH(R), +; IOCHNM WD CONTENTS IN H, CLSTB ENTRY'S LH IN LH(R). +;3.2 => NEVER PASS TO SPECIAL CHECKER FOR JOB CHNL +;3.3 => DON'T BARF IF CHNL NOT OPEN, CALLED ROUTINE WILL HANDLE IT + +;# ARGS ACTUALLY SUPPLIED IN W WHEN DISPATCHING THRU SYSCTD, ARGS IN A...J +SYSCTD: 200,,NACCES + 100,,NATTAC + 100,,NATTY + 100,,NCALL +IFN CHAOSP,[ + 200,,CHAOSO + 100,,CHAOSQ +];CHAOSP + 100,,NCLOSE(7) + 100,,NCNSGET + 100,,NCNSSET + 24300,,NCORBL + 100,,NCORTY + 100,,NDEL + 100,,DELEWO(1) +IFN DEMON,100,,ADEMSIG + NDETAC + 100,,NDIRSIZ(1) + 1100,,NDISMIS + 100,,NDISOWN +IFN DL10P, 100,,DL10MP + 100,,ADSKUP(1) + 6500,,NECHOIN(1) + 100,,NFILBLK(1) + 100,,NFILLEN(1) + 100,,NFINIS(1) +IFN NUNITS, 100,,NFLAP +IFE NUNITS, 100,,OPNL1 + 100,,NFINIS(1) ;OLD NAME FOR FINISH, EVENTUALLY FLUSH + 100,,NFORCE(1) + 100,,NIOPOP(7) + 100,,NIOPUS(7) + 2100,,NIOT(7) ;(7) FOR CHNL NOT OPEN TO BE IOC ERROR, (3) TO BE OPEN LOSS +IFN INETP, 100,,IPKIOT(1) ; Requires at least 1 arg + 100,,NITYIC + 100,,NJBCL(1) + 100,,NJBGT(1) + 100,,NJBINT(1) + 100,,NSTIOC(1) + 100,,NJBRT(1) + 20500,,NJBREU + 100,,NJBSTS(1) +IFN KL10P,KLPERF + 100,,NLISTE + 100,,NLNKEDP(1) + 200,,NLOAD + 200,,NLOGIN + ALOGOU + 100,,NLOSE + 200,,NMLINK +IFN NCPP, 100,,ANETAC(1) +IFE INETP,[ +IFE CHAOSP, 4200,,ANETBLK(1) +IFN CHAOSP, 4200,,CHANBK(1) +] +IFN INETP, 4200,,NETBLK(1) ; Block (.hang) on net I/O channel +IFN IMPP,[ + 100,,ANETHST + ANETIMP +];IMPP +IFN NCPP, 100,,NNETINT(1) +IFN INETP, 100,,NETRFC + 200,,NOPEN + 4300,,PDUMP + 100,,NPGWRT ;OLD NAME FOR PGWRIT, EVENTUALLY DELETE + 100,,NPGWRT +IFN CHAOSP, 200,,PKTIOT(1) +IFN QAUTHP, 100,,ARAUTH(1) + 100,,NRCHST + 100,,ARCPOS +IFN DEMON,100,,ARDDMST + 100,,NRDMPBT(1) + 000,,NRELOAD + 200,,NRNAM + 200,,NRNWO + 100,,NREOWN(3) + 100,,NRESET(7) + 100,,NRESRDT(1) + 100,,NRFDATE(1) + 100,,NRFNAM + 100,,NRFPNT(3) + ARQDAT + 100,,ARSSIZ +IFN QAUTHP, 200,,ASAUTH(1) + 200,,ASCML + 100,,NSCPOS + 200,,NSDMPBT(1) + 200,,NSTIOC(1) + 200,,NSFDATE(1) + 6300,,NSIOT(7) ;(7) FOR IOC ERROR IF CHNL NOT OPEN, (3) FOR OPEN LOSS + 200,,NSOPEN + 200,,NSRDATE(1) + 100,,ASREAP(1) + 100,,NSSERV + ASSTAT + 100,,NSTATUS(7) +IFN DEMON,100,,ASTDMST + 100,,NSTLGT + 100,,NSTYGT +IFN NETP,200,,NSTYNT(3) + 200,,NT11M +IFN TCPP,500,,TCPOPN + 300,,NTRNAD + 100,,NTRNCL + 200,,NTRNDL + 200,,NTRNEX + 100,,NTRNS + 200,,TRPOPN + 100,,NTTYESC + 100,,NTTYFLS + 100,,ATTYGT + 300,,ATTYST + 2200,,NTTYVA + 100,,NTVWHERE + 100,,NUNLOCK + 2200,,NUSRME + 2200,,NUSRVA + 100,,NVDBF + 200,,NVIDSW + 100,,NWHOLI + 100,,NWHYINT(1) + 1100,,NXGPIM + +IFN .-SYSCTD-1-ZZ,.ERR NEW SYS CALL DISPATCH LOSES!!! + +REPEAT 1_-ZZ-1,ILUUO + +;.CALL ADR1 SKIPS UNLESS SOMETHING WRONG +;ADR1: SETZ +; SIXBIT // +; REPEAT #ARGS,BITS,,
+; BITS= 4.9 => LAST ARG +; 4.3 - 4.1 0 = NORMAL ARG +; 1 = IMMEDIATE +; 2 = OUTPUT ARG +; 3 = RETURN THE FAILURE CODE IF FAIL +; 4 = WORD OF CONTROL BITS +; 5 = IMMEDIATE CONTROL BITS + +ASYSC: PUSHJ P,ASCGRG ;B HAS E OF UUO + JRST OPNL43 ;CALL NAME UNKNOWN. + JRST OPNL15 ;MORE THAN 8 ARGS + JRST OPNL30 ;TOO FEW ARGS + PUSHJ P,ASYSC1 ;DISPATCH TO ROUTINE. + POPJ P, ;NO SKIP - OPENL HAS ALREADY BEEN CALLED. + AOS (P) ;SKIP - PROPAGATE THE SKIP UP THE PDL + MOVE U,USER ;!! + MOVE R,SYSCVL(U);SUCCESS RETURN, ZERO ERROR CODE ARG IF ANY + TLNE R,%SCVER + XCTR XW,[SETZM (R)] + JUMPGE R,CPOPJ ;JUMP IF NO OUTPUT VALUES WANTED +SYSCPT: HRRZ W,FORTY ;VALUES WANTED, PUT INTO USER MEMORY FROM ACS + ADDI W,2 + MOVSI T,-8 +SYSCP2: UMOVE R,(W) + TLNN R,1000 + TLNN R,2000 + JRST SYSCP3 + PUSHJ P,ASCIND + MOVE J,1(T) + UMOVEM J,(R) + AOBJP T,CPOPJ +SYSCP3: JUMPL R,CPOPJ + AOJA W,SYSCP2 + +ASYSC1: MOVE T,SYSCTD(H) + TLNN T,1 ;DECODE 1ST ARG AS IO CHNL? + JRST (T) ;NO, DISPATCH TO CALL. + TLNE T,2 ;OK TO GIVE TO JOB CHNL CHECKER? + JRST CHNDCD ;NO - GO DECODE CHANNEL + HRL J,T ;SAVE DISPATCH ADDR + HRRI T,AIOCAL ;MAKE DECODER RETURN TO CHECK FOR JOB DEVICE + JRST CHNDCD + +NCALL: MOVE T,A + MOVE R,[B,,A] + BLT R,A+6 + SETZM A+7 ;MAX 8 ARGS, 1 USED FOR NAME + SOS W + PUSHJ P,ASCRCH + JRST OPNL43 + MOVEI J,ASYSC+2 ;LOOK LIKE PUSHJ'ED FROM ASYSC + MOVEM J,(P) + LDB J,[331000,,SYSCTD(H)] + JUMPE J,NCALL2 + AOS B,FORTY + JRST NCALL3 ;HE WANTS POINTERS, WE HAVE JUST VALUES. + ;MUST GET ARGS AGAIN + +ASCRCH: MOVEI H,0 + REPEAT ZZ2,[CAML T,SYSCTB+1_(H) + ADDI H,1_ + ] + CAMN T,SYSCTB(H) + AOS (P) + POPJ P, + +;JSP T,HERE TO DECODE IO CHNL IN A, MODIFIERS IN 3.1-3.3 OF T. +;IF RH(T) = AIOCAL, LH(J) IS REAL RETURN ADDRESS. +;RETURNS IOCHNM ADDR IN RH(R), IOCHNM WD CONTENTS IN H, CLSTB BITS IN LH(R) +;CAN POPJ OUT FOR INVALID CHANNEL. + +CHNDCD: TRNE A,-NIOCHN ;IS 1ST ARG A LEGAL CHNL NUM? + JRST OPNL14 + CAMN U,USER + HRROM A,UUAC(U);REMEMBER CHNL # FOR IOC ERRORS, ETC. + MOVEI R,(A) + ADDI R,IOCHNM(U) ;YES, COMPUTE IOCHNM WD ADDR + MOVE H,(R) ;RETURN CONTENTS IN H. + HLL R,CLSTB(H) ;RETURN CLSTB BITS IN LH(R). + TLNE R,%CLST + JRST [ CAME U,USER ;TRAP DEVICE + JRST .+1 ;IF CHANNEL BELONGS TO THIS USER, TRAP + JRST TRPDEV ] ;OTHERWISE, IS PROBABLY RFNAME, LET IT THROUGH + TRNN H,-1 ;IF CHNL NOT OPEN + TLNE T,4 ;AND NOT SPECIALLY OK FOR THIS SYSTEM CALL + JRST (T) + JRST OPNL44 ;THEN BARF + +;JOB DEVICE CHECKER - PUT AIOCAL IN RH(T), JRST CHNDCD + +AIOCAL: HLRZ T,J ;GET DISPATCH ADR BACK + TLNN R,%CLSJ ;IS CHANNEL JOB DEVICE? + JRST (T) ;NO - DISPATCH + HLRZS H ;ISOLATE JOB DEVICE INDEX + DPB W,[230400,,JBSTS(H)] ;SAVE ARG COUNT + MOVNS W + HRLZS W + HRRI W,1 ;NOW HAVE AOBJN PNTR TO DATA + MOVE T,(W) ;COPY ARGS TO JOB AC TABLES + MOVEM T,@JBACTB-1(W) + AOBJN W,.-2 + MOVEI W,10 ;SET NON-STANDARD OP-CODE + HRRM W,JBSTS(H) + MOVE E,H ;PUT JOB INDEX IN E FOR JBWT + CONO PI,CLKOFF +AIOCA1: PUSHJ P,JBWT ;WAIT FOR JOB TO ANSWER + MOVE H,E ;GET JOB INDEX BACK IN H (FOR JBACTB) + MOVE W,[-8,,1] ;LOAD ANSWERS INTO ACS + MOVE T,@JBACTB-1(W) + MOVEM T,(W) + AOBJN W,.-2 + LDB T,[350400,,JBSTS(H)] ;GET SKIP COUNT + JUMPN T,POPJ1 ;SKIP COUNT NOT ZERO - SKIP + LDB C,[270600,,JBSTS(H)] ;GET OPEN LOSS CODE + SKIPE C ;MAKE SURE IN BOUNDS + CAILE C,NOPNLS + MOVEI C,22 + JRST OPNL1-1(C) ;GO REPORT LOSSAGE AND DON'T SKIP + +;SYSTEM CALL GET ARGS +ASCGRG: UMOVE T,(B) + CAME T,[SETZ] + JRST ILUUO + UMOVE T,1(B) + MOVEM T,LSCALL(U) + PUSHJ P,ASCRCH + POPJ P, ;CALL NAME UNRECOGNIZED. + AOS (P) + LDB J,[331000,,SYSCTD(H)] ;GET BITS CORRESP TO ARGS WHICH SAY SUPPLY PNTR TO NTH ONE +NCALL3: MOVEI W,2(B) + MOVE T,[-9,,A] + SETZM CTLBTS(U) +ASYSC2: UMOVE R,(W) + TLNE R,37 + PUSHJ P,ASCIND ;CALC EFFECTIVE ADDRESS + TLNE R,2000 + JRST ASYSC3 ;OUTPUT OR ERRORCODE ARG + TLNE R,4000 + JRST ASYSC5 ;CONTROL BITS + AOBJP T,CPOPJ + ROT J,-1 + JUMPL J,ASYSC7 ;J IF WANT ADDRESS, NOT VALUE + TLNE R,1000 + TLZA R,-1 ;IMMEDIATE, GET 0,,ADR + UMOVE R,(R) ;ELSE GET WORD POINTED TO +ASYSC7: MOVEM R,-1(T) ;PUT INTO AC + JRST ASYSC4 + +ASYSC5: TLNE R,1000 ;CTL BITS + TLZA R,-1 ;IMMEDIATE, GET 0,,ADR + XCTR XR,[HRRZ R,(R)] ;ELSE WORD ADDRESS + XORM R,CTLBTS(U) ;XOR ALL THESE ARGS TOGETHER +ASYSC4: XCTR XR,[SKIPL (W)] ;SKIP IF TERMINATE BIT ON + AOJA W,ASYSC2 + HLRE W,T + ADDI W,9 ;COMPUTE NUMBER OF ARGUMENTS SUPPLIED +NCALL2: LDB T,[300300,,SYSCTD(H)] + SUB T,W + JUMPG T,POPJ1 ;NOT ENOUGH ARGS + JRST POPJ2 ;OK + +ASYSC3: TLNE R,1000 + JRST ASYSC8 ;ERROR CODE ARG + XCTR XRW,[MOVES (R)] ;OUTPUT ARG, JUST MAKE SURE IT'S THERE + MOVSI R,%SCVOT ;AND FLAG PRESENCE +ASYSC9: IORM R,SYSCVL(U) + JRST ASYSC4 + +ASYSC8: HRLI R,%SCVER ;ERROR-CODE ARG + TDNE R,SYSCVL(U);CAN'T HAVE MORE THAN ONE ERRORCODE ARG + JRST CPOPJ ;SAY "TOO MANY ARGS" + XCTR XRW,[MOVES (R)] ;MAKE SURE IT'S THERE; MUSTN'T PCLSR OUT OF OPENL + JRST ASYSC9 + +;PERFORM INDEXING AND INDIRECTION ON ADDRESS WORD IN R. +;DON'T CLOBBER BITS 3.6 - 4.9. SET BITS 3.1 - 3.5 TO ZERO +;PUT ADDR IN RH. +ASCIND: TLNN R,37 + POPJ P, +ASCIN1: PUSH P,R + LDB R,[220400,,R] + CAIE R,0 + XCTR XR,[HRRZ R,(R)] + ADD R,(P) + HLL R,(P) ;GET ORIG @, MAY HAVE BEEN CARRIED INTO BY -1(17) + TLZ R,17 + TLZE R,(@) + UMOVE R,(R) + DPB R,[2700,,(P)] + POP P,R + TLNN R,37 + POPJ P, + PUSHJ P,OPBRK ;ALLOW PCLSR + JRST ASCIN1 + +TPFLT: CONO PI,CLKOFF ;PREVENT INTERRUPT AFTER IORM SPM ING BACK + ; ON TOP OF 1000 BIT +IFN KA10P,[ + SPM UPGML(U) + PUSH P,B + MOVSI B,1000 + IORM B,UPQUAN(U) + POP P,B + LPMRI UPGML(U) ;TAKE TRAP, MAYBE DONT COME BACK + JRST CLKONJ +] ;KA10P +IFN KL10P,[ + POP P,PFOPC1 ;IF RESTART FAULT, RETURN FROM TPFLT + JRST TPFLT1 ;JOIN REGULAR PAGE FAIL CODE +] ;KL10P +IFN KS10P,[ + POP P,EPTPFO ; If fault returns, just return from TPFLT + JRST TPFLT1 +] ;KS10P + +SUBTTL PURE DUMP + +;`PDUMP' SYMBOLIC SYSTEM CALL +; ARG 1 - JOB SPEC FOR JOB TO BE DUMPED +; ARG 2 - DISK CHANNEL TO DUMP ONTO +; ARG 3 - STATE WORD (MODIFIED) INITIALLY 0, THEN 4.9 + PAGE # ABOUT TO DUMP + +PDUMP: MOVE J,A + JSP T,NCRUI2 ;DECODE JOB SPEC (1ST ARG) + JFCL + MOVE A,J + JUMPL J,OPNL31 ;CAN'T PDUMP THE PDP6. + MOVE D,B + JSP T,PDUMDC ;DECODE 2ND ARG, B-> IOCHNM WORD. + TLNN J,%CLSQO + JRST OPNL34 ;NOT DISK WRITE CHANNEL. + HRRZM D,UUAC(U) ;SO SET IN CASE OF ERROR + HLRZ D,(B) + MOVEM D,SRN3(U) ;REMEMBER DISK CHANNEL NUMBER FOR LATER. + PCLT + XCTR XRW,[MOVES D,(C)] + MOVEM C,SRN4(U) ;REMEMBER STATE WORD ADDRESS FOR LATER + MOVEM A,EPDL(U) ;USER INDEX +PDUMA: CAIN A,(U) ;IF PDUMP'ING SELF, MUSTN'T PCLSR, + PUSHJ P,NULSET ;SO DO A NULSET INSTEAD OF THE SOSSET + CAIN A,(U) + JRST PDUMP9 ;SO THAT A LSWPOP CAN BE DEON AT THE END IN EITHER CASE. + PUSHJ P,RPCLSR ;HACKING ANOTHER JOB: STOP IT. + PUSHJ P,SOSSET + USTP(A) +PDUMP9: MOVE A,SRN3(U) ;GET DISK CHANNEL NUMBER + MOVE C,SRN4(U) + UMOVE D,(C) ;PICK UP STATE WORD + JUMPN D,PDUMP5 ;JUMP IF ALREADY WROTE MAP PAGE + PUSHJ P,PDBWG ;GET BUFFER AND COMMIT DISK TRACK FOR MAP PAGE + SETZM (E) ;CLEAR FIRST WORD OF MAP + ;AND DROP INTO PDUMP4 +;HANDLE THE NEXT PAGE. +PDUMP4: PUSHJ P,PUPLC ;GET BYTE POINTERS + LDB W,Q ;CIRC POINTER ENTRY + LDB R,T ;PAGE MAP ENTRY + ANDCMI R,PMAGEM ;CLEAR AGE BITS + CAIN W,-1 + TLO R,(SETZ) ;ABS PAGE + SKIPN W + MOVEI R,0 ;PAGE NON-EXISTANT + TRNN R,600000 + LSH R,16. ;SWAPPED OUT + MOVE W,D ;VIRTUAL PAGE NUMBER + ADDI W,1(E) ;ADDRESS OF ENTRY IN BLOCK + MOVEM R,(W) ;STORE ENTRY + CAIGE D,377 + AOJA D,PDUMP4 + HRLI W,1(W) + SETZM 1(W) + HRRI W,2(W) + BLT W,1777(E) + MOVE D,EPDL(U) + MOVEI W,1000(E) ;1000-1017 ACS + CAMN D,U + JRST [ XCTR XBR,.+2 + JRST .+3] + HRLI W,AC0S(D) + BLT W,1017(E) + PUSHJ P,QSBWW + SETZM QSMPRC(A) ;SO NEXT IOT GETS A NEW BUFFER + MOVSI D,(SETZ) ;SET STATE WORD TO `DUMPING PAGE 0' +;DROPS THROUGH + ;DROPS IN +;DUMP NEXT PAGE +PDUMP5: MOVE C,SRN4(U) ;STORE BACK STATE WORD + UMOVEM D,(C) +PDUMP8: PUSHJ P,PUPLC + LDB W,Q + CAIE W,-1 + SKIPN W + AOJA D,PDUMP6 ;PAGE ABSOLUTE OR NONEXISTANT +PDUMP3: PUSHJ P,PDBWG ;GET BUFFER AND COMMIT DISK TRACK TO DUMP THIS PAGE INTO + MOVE J,EPDL(U) ;SET UP MAP TO POINT TO USER BEING DUMPED + PUSHJ P,MPLDJ + HRLZ J,D ;GET VIRTUAL ADDRESS OF PAGE BEING DUMPED + LSH J,10. + HRR J,E ;BLT POINTER TO COPY THE PAGE + XCTR XBR,[BLT J,1777(E)] ;COPY PAGE INTO DISK BUFFER + PUSHJ P,MPLDZ ;RESTORE TO NORMAL MAP + PUSH P,D + PUSHJ P,QSBWW ;WRITE OUT THE COPIED PAGE + SETZM QSMPRC(A) ;SO NEXT IOT GETS NEW BUFFER + POP P,D + AOS D ;DONE WITH THIS PAGE +PDUMP6: TRNN D,400 ;SKIP IF FINISHED WHOLE ADDRESS SPACE + JRST PDUMP5 + JRST LSWPJ1 ;UNSTOP USER AND POPJ1 + +;ROUTINE TO GET DISK BUFFER AND COMMIT TRACK (FOR PDUMP) +;RETURNS BUFFER ADDRESS IN E. PRESERVES D. + +PDBWG: SKIPL E,QSMDN(A) ;GET CORE BLOCK # OF DISK BUFFER + JRST [ LSH E,10. ;CONVERT TO ADDRESS + POPJ P, ] + MOVE E,[444400,,1] ;NO BUFFER, GET ONE + MOVEI B,QBOV + PUSHJ P,QSBWG + PUSHJ P,UDELAY ;CAN'T GET MEMORY, WAIT A WHILE + JRST PDBWG + +;ROUTINE TO LOOK UP PAGE (FOR PDUMP AND PURE LOAD) +;PAGE# IN RH(D), USER# IN EPDL(U). RESULTS FROM UPLC IN Q AND T. + +PUPLC: PUSH P,A + PUSH P,U + MOVE U,EPDL(U) + MOVE A,D + ANDI A,377 + PUSHJ P,UPLC + POP P,U + JRST POPAJ + +;DECODE 2ND ARG TO PDUMP & LOAD. +;B GETS IOCHNM WORD ADDR, LH OF J GETS LH OF CLSTB ENTRY, RH GETS LH(IOCHNM). + +PDUMDC: TRNE B,-NIOCHN + JRST OPNL14 + ADDI B,IOCHNM(U) + HRRZ J,(B) + HLLZ J,CLSTB(J) + HLR J,(B) + JRST (T) + +SUBTTL PURE AND SBLK LOAD + +;`LOAD' SYMBOLIC SYSTEM CALL +; ARG 1 - JOB SPEC FOR JOB TO BE LOADED +; ARG 2 - DISK CHANNEL TO LOAD FROM +; ARG 3 - (OPTIONAL) FIRST ADDR,,LAST ADDR TO BE LOADED +; OR ZERO => LOAD ONLY PURE PAGES +; WHEN LOADING A PDUMPED FILE, FIRST,,LAST ROUNDED OFF TO PAGES +; DEFAULT 3RD ARG IS 0,,-1 NORMALLY, 20,,-1 LOADING SELF, 20,,37777 LOADING PDP6 + +;PAGE WORD +;4.9=1 ABSOLUTE, 1.1-2.9 = PTW +;4.8=1 SHARED WITH OTHER PAGES AT LEAST ONE OF WHICH IS WRITE +;4.7=1 LINK WITH VIRT PG IN RH 1.8-1.1 +;2.9-2.8 0 NXM, 1 RD ONLY, 2 OR 3 READ/WRITE +;2.7=1 WORD ALREADY PROCESSED + +NLOAD: MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC. + JRST NLOAD6 ;JOB GUARANTEED WRITEABLE. + JSP T,NCORWR ;ELSE CHECK IF WRITEABLE. + CAIN J,-1 ;BUT CAN WRITE PDP6. + CAIA + JRST OPNL31 ;NOT WRITEABLE. +NLOAD6: HRREI A,(J) ;MAKE SURE EXTEND SIGN IF PDP6. + JSP T,PDUMDC ;DECODE 2ND ARG. + TLNN J,%CLSQO + TLNN J,%CLSQ + JRST OPNL34 ;NOT DISK READ CHANNEL. + LDB J,[QSBSIZ(J)] + CAIE J,36. + JRST OPNL12 ;"MODE NOT AVAILABLE" IF CHANNEL NOT 36-BIT BYTES. + MOVE R,B ;IOCHNM ADDRESS IN CASE WE GET TO QICL + JUMPL A,NLOADE ;DONT STOP THE 6 + CAMN A,U + JRST NLOADA ;DONT STOP IF LOADING INTO SELF + PUSHJ P,RPCLSR + PUSHJ P,LSWPOP ;SOS JOB'S DIELOK - IT CAN'T DIE WHILE STOPPED. + MOVSI T,BSSTP ;STOPPING WITH BSSTP INSTEAD OF RH OF USTP + IORM T,USTP(A) ;AVOIDS DEADLY EMBRACE WITH CORE JOB (SEE CUSTOP) + SOS USTP(A) + PUSHJ P,LOSSET ;ARRANGE TO CLEAR BSSTP ON PCLSR. + NLUPCL + CAIGE W,3 + HRLOI C,0 ;DEFAULT 3RD ARG + JRST NLOADE + +NLOADA: PUSHJ P,LSWPOP ;DIELOK + CAIGE W,3 + HRLOI C,20 ;DEFAULT 3RD ARG +NLOADE: MOVEM A,SRN3(U) ;SAVE USER INDEX (-1 => PDP6) +IFN PDP6P,[ + JUMPL A,[HLRZ A,C ;PDP6, ENSURE LIMITS SMALL ENOUGH + CAIGE A,20 + HRLI C,20 ;ACS NOT ACCESSIBLE + MOVEI A,LPDP6M*2000-1 + CAIGE A,(C) + HRR C,A ;HAS ONLY 16K MEMORY + JRST .+1] +] + HLRZ A,(B) + MOVEM A,SRN4(U) ;SAVE # OF DISK CHANNEL + SETZM SRN5(U) ;START LOADING AT VIR PG #0 + MOVEM C,EPDLT1(U) ;SAVE LOAD LIMITS + HLRZ D,C + CAILE D,(C) + JRST OPNL33 ;FIRST > LAST + HLRZ C,QPCLSR(A) + JUMPE C,NLOADD + HRRZ Q,SRN3(U) + CAIN C,(Q) + JRST NLDSBB ;(COMING BACK AFTER PCLSR) + SETZM QPCLSR(A) +;DROPS THROUGH + ;DROPS IN +;GET FIRST BLOCK OF FILE BEING LOADED +NLOADD: CAMN U,PCLUSR + SETZM PCLIDX + SKIPL TT,QSMDN(A) + JRST NLOADB + PCLT + SKIPG QSBFS(A) + PUSHJ P,UFLS ;HANG UNTIL A BLOCK IS READ IN + MOVE Q,QSRAC(A) + TLNE Q,%QAACC+%QAMPU+%QAPAR + JRST OPNL7 ;LOST ONE WAY OR ANOTHER + MOVE E,[444400,,1] + MOVEI B,QBIV + PUSHJ P,QSBGB ;SET UP CHNL AREA. TT ADDR OF FIRST WORD OF BLOCK + BUG + JRST NLOADC ;QSBGB SKIPS FOR NORMAL RETURN + JRST OPNL46 ;SKIPPED TWICE => EOF + +NLOADB: MOVE J,QMPBSZ(A) + LSH TT,10. +NLOADC: SKIPE (TT) ;SKIP IF PURE DUMPED FILE + JRST NLDSB ;SBLK + SKIPGE SRN3(U) + JRST OPNL34 ;TRYING TO PURE LOAD PDP6 + MOVSI Q,%QAACC ;WILL GO RANDOM ACCESSING THROUGH FILE + IORM Q,QSRAC(A) ;THIS ALSO INHIBITS ACTIVATION AT PI LEVEL + HLRZ H,EPDLT1(U);LOW LOAD BOUNDARY + SKIPE EPDLT1(U) + CAIL H,20 + JRST NLOADH ;ACS NOT BE LOADED + MOVSI Q,1000(TT);ADDRESS OF DUMPED ACS + HRLS H + ADD Q,H + HRRZ H,EPDLT1(U);HIGH LOAD BOUNDARY + CAILE H,17 + MOVEI H,17 + HRRZ J,SRN3(U) ;JOB TO BE LOADED + PUSHJ P,MPLDJ + XCTR XBW,[BLT Q,(H)] ;LOAD UP HIS ACS + PUSHJ P,MPLDZ +NLOADH: MOVEI R,1(TT) ;ADDRESS OF FIRST WORD OF DUMPED MAP + MOVEM R,EPDL3(U) ;SAVE + MOVEI Q,2000 + PUSHJ P,QFNTR ;FIND DISK ADDRESS OF SECOND BLOCK + JRST OPNL46 ;OFF END OF FILE + SOS QSBI(A) ;UNDO QFNTR HACK + AOS QSLGL(A) + PUSHJ P,QUDULK ;UNLOCK USER DIRECTORY + PUSHJ P,SWTL ;LOCK CIRPSW + CIRPSW +;DROPS THROUGH + ;DROPS IN +;HERE TO DO NEXT PAGE (WHEN LOADING PDUMPED FILE) +NLOAD0: PUSHJ P,OPBRK + MOVE A,@EPDL3(U) + TRNE A,600000 ;SKIP IF NO ACCESS (IGNORE) + TRNE A,100000 + JRST NLD14 ;THIS PAGE ALREADY DONE OR NO ACCESS + MOVE Q,EPDLT1(U) + TRNE A,400000 ;SKIP IF READ ONLY + JUMPE Q,NLD14 ;IMPURE NOT BE LOADED + MOVE A,SRN5(U) ;VIRTUAL PAGE NUMBER + JUMPE Q,NLD16 + AND Q,[-2000,,-2000] + LSH Q,-10. ;FIRST PAGE,,LAST PAGE + HLRZ T,Q + CAIL A,(T) + CAILE A,(Q) + JRST NLD14 ;PAGE OUTSIDE OF RANGE TO BE LOADED +NLD16: MOVE U,SRN3(U) ;USER INDEX + PUSHJ P,UPLC + LDB R,Q ;LOOK IN CIRCULAR POINTER ENTRY FOR THIS PAGE + JUMPE R,NLOAD1 ;DOESN'T ALREADY HAVE THIS VIRTUAL PAGE + PUSH P,T ;SAVE BYTE POINTER TO PAGE MAP FOR THIS VIRTUAL PAGE + PUSH P,Q ;SAVE BYTE POINTER TO CIRCULAR POINTER ENTRY FOR THIS PAGE + PUSHJ P,PAGERT ;FLUSH THE ALREADY EXISTING VIRTUAL PAGE + POP P,Q + POP P,T +NLOAD1: MOVE U,USER + MOVE R,@EPDL3(U) ;PICK UP DUMPED PAGE MAP WORD + ANDCMI R,PMAGEM ;CLEAR AGE BITS (WOULD LOSE AT NLOAD4+4) + JUMPGE R,NLOAD3 ;NOT ABSOLUTE PAGE + ANDI R,PMRCM ;ABS PG # + CAIL R,TSYSM +IFE PDP6P, JRST OPNL32 +.ELSE [ + JRST [ CAIGE R, + CAIGE R, + JRST OPNL32 + HRRZ R,@EPDL3(U) ;ALLOW USER TO LOAD WRITABLE PDP6 PAGES. + ANDCMI R,PMAGEM\PMUNSD ;GIVE HIM WHATEVER ACCESS HE RQ'S. + JRST NLOAD5]] +;IFN TEN11P,[ ;NOT NECESSARY SINCE 10-11 PAGES ABOVE TSYSM NOW +; TRNN R,400 +; JRST .+3 +; MOVE E,T11MP-400(R) +; AOJN E,NLOAD2 ;DONT ALLOW PAGE TO POINT TO TEN11 +;] + + LDB E,[MUR,,MEMBLT(R)] + CAIN E,MUHOLE + TDZA R,R ;IF PAGE NXM TODAY, DON'T ACTUALLY GIVE ACCESS + +NLOAD5: TRO R,200000 ;RD ONLY + DPB R,T ;STORE ENTRY IN PAGE MAP + MOVEI R,-1 + DPB R,Q ;STORE -1 IN CIRCULAR POINTER +NLOAD2: MOVE E,SRN5(U) ;VIRTUAL PAGE NUMBER + MOVE U,SRN3(U) ;USER INDEX LOADING INTO + PUSHJ P,GHUSRA ;RECOMPUTE HUSRAD +NLD14: MOVE U,USER + MOVEI R,100000 + IORB R,@EPDL3(U) ;MARK DUMPED PAGE WORD AS ALREADY DONE + MOVE A,SRN4(U) ;DISK CHANNEL + TLNN R,500000 ;SKIP IF NO CORRESPONDING BLOCK IN FILE + TRNN R,600000 ;SKIP IF MUST ADVANCE ONE BLOCK + JRST .+3 ;DON'T ADVANCE FILE POINTER + PUSHJ P,QFNTN ;ADVANCE TO NEXT DISK ADDRESS + JRST OPNL46 ;PREMATURE EOF + AOS R,SRN5(U) ;NEXT VIRTUAL PAGE + CAMN U,PCLUSR + MOVEM R,PCLIDX + AOS EPDL3(U) ;NEXT MAP WORD + CAIGE R,400 + JRST NLOAD0 ;LOOP + PUSHJ P,LSWPOP ;RELEASE CIRPSW + MOVE B,SRN3(U) ;USER INDEX LOADING INTO + CAME B,U ;SKIP IF LOADING INTO SELF + PUSHJ P,LSWPOP ;UNSTOP USER + MOVE B,QFBLNO(A) + SETZM QFBLNO(A) + MOVEM B,QRADAD(A) + JRST POPJ1 + +NLOAD3: TLNN R,100000 ;SKIP IF LINK WITH PAGE IN RH OF R + JRST NLOAD4 + PUSH P,T ;SAVE BYTE POINTER TO MAP ENTRY FOR THIS VIRTUAL PAGE + PUSH P,Q ;SAVE POINTER TO CIRCULAR POINTER ENTRY FOR THIS PAGE + LDB A,[1700,,R] ;VIRTUAL PAGE NUMBER BEING LINKED TO + CAIL A,400 + JRST NLOAD8 ;BAD VIRT PAGE # + MOVE E,SRN5(U) ;VIRTUAL PAGE NUMBER OF PAGE BEING LINKED + MOVE U,SRN3(U) ;USER INDEX LOADING INTO + PUSHJ P,UPLC + LDB W,Q ;CIRCULAR POINTER OF OTHER ENTRY + JUMPE W,NLOAD8 ;DIDN'T EXIST + CAIN W,-1 + JRST NLOAD8 ;POINTS TO AN ABSOLUTE PAGE + MOVE C,U + IDIVI C,LUBLK + SKIPE D + BUG ;L DOESN'T DIVIDE U + LSH C,10 ;USER NUMBER _ 8 + TRZE C,400000 + BUG ;USER INDEX WAS TOO LARGE + IOR C,E ;NEW CIRCULAR POINTER + POP P,D ;NEW CIRCULAR POINTER BYTE POINTER + DPB W,D ;STORE OTHER ENTRY AS NEW CIRCULAR POINTER ENTRY + DPB C,Q ;MAKE OTHER CIRCULAR POINTER ENTRY POINT TO NEW ONE + LDB E,T ;OTHER MAP ENTRY + POP P,T ;POINTER TO NEW MAP ENTRY + ANDI R,600000 ;PROTECTION BITS + TRZN E,600000 + JRST NLD11 + IOR E,R + JRST NLD10 +NLD11: LSH R,-20 + DPB R,T +NLOAD9: AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + AOSA NSWPGS(U) ;USER LOADING INTO HAS ONE MORE SWAPPED OUT PAGE +NLD10: DPB E,T +NLD13: AOS NMPGS(U) ;USER HAS ONE MORE PAGE + AOS SNMPGS ;SYSTEM HAS 1 MORE PAGE +NLD15: MOVE U,USER + JRST NLOAD2 ;RECOMPUTE HUSRAD AND LOOP + +NLOAD4: MOVE A,SRN4(U) ;DISK CHANNEL + MOVEI TT,(R) ;PUT DESIRED ACCESS IN RH(TT), + ANDI TT,600000 + TDNE R,[200000,,400000] + IORI TT,%CBCPY ;ALONG WITH INITIAL-SWAPIN BIT IF NEC. + PUSHJ P,NCORQ7 ;FIND OR CREATE MMP ENTRY. + JRST OPNL37 ;MMP FULL + MOVE E,SRN5(U) ;GET PAGE # IN JOB BEING LOADED + MOVE U,SRN3(U) ;TARGET USER. + PUSHJ P,NCORR1 ;INSERT THE PAGE. + JRST NLD15 + +NLOAD8: SUB P,[2,,2] + JRST OPNL46 + +NLOADZ: PUSHJ P,LSWPOP ;FREE CIRPSW + MOVEI T,3 + CAMLE T,LMEMFR + PUSHJ P,UFLS + PUSHJ P,SWTL + CIRPSW +POPSM2: SOS (P) ;RETURN TO LOCN BEFORE PUSHJ + SOS (P) + POPJ P, + +;QTAOS: PUSHJ P,QTLOCK ;LOCK TUT +QTAOS1: MOVE D,QSLGL(A) ;DISK TRACK + PUSHJ P,TUTPNT + SKIPG B + BUG ;NOT PART OF ANY FILE + CAIGE B,TUTMNY + AOS B + DPB B,D ;ADD ONE TO TUT ENTRY FOR THIS TRACK + JRST QTULK + +NLUPCL: MOVSI T,BSSTP ;THIS IS THE LOSSET ROUTINE TO CLEAR BSSTP. + SKIPGE A,SRN3(U) + BUG + ANDCAM T,USTP(A) + POPJ P, + +NLDSBB: HRRZ J,SRN3(U) ; (COMING BACK AFTER PCLSRING OUT) A HAS DSK CHNL #) + PUSHJ P,MPLDJ ;LOAD MAP (ALSO CLOBBER UMAPS) + SKIPL C,SRN3(U) + CAIN U,(C) + JRST NLDSBH + PUSHJ P,LSWPOP + PUSHJ P,LOSSET + NLUPCL + MOVSI B,BSSTP + IORM B,USTP(C) +NLDSBH: HRRZ B,QPCLSR(A) + JRST (B) + +NLDSB: SKIPN EPDLT1(U) + JRST OPNL12 ;LOAD ONLY PURE FROM SBLK FILE LOSES + HRLZ B,SRN3(U) + HRRI B,NLDSBD + MOVEM B,QPCLSR(A) ;RESTART POINT IN CASE OF PCLSR + MOVEM J,QSMPRC(A) + MOVEM TT,QSMPRP(A) + HRRZ J,SRN3(U) + PUSHJ P,MPLDJ ;LOAD MAP (ALSO CLOBBER UMAPS) + +;DROPS THROUGH + +;DROPS IN +NLDSB1: HRROI I,EPDL3(U) + MOVEM I,SRN4(U) ;SET UP AOBJN PTR TO READ INTO EPDL3 +NLDSBD: MOVEI C,SRN4(U) ;SET C UP TO POINT TO AOBJN PTR + HRLI C,(TRN) ;INDICATE EXEC MODE ADR + PUSHJ P,QBI + SKIPGE SRN4(U) + JRST NLDSB9 ;PREMATURE EOF + MOVE I,EPDL3(U) + CAME I,[JRST 1] + JRST NLDSB1 ;IGNORE INITIAL STUFF UNTIL JRST 1 +NLDSBK: MOVEI B,NLDSBE + HRRM B,QPCLSR(A) +NLDSBE: HRROI I,QLDPTR(A) + MOVEM I,SRN4(U) + MOVEI C,SRN4(U) + HRLI C,(TRN) + PUSHJ P,QBI ;GET AN AOBJN POINTER + SKIPGE SRN4(U) + JRST NLDSB9 ;PREMATURE EOF + SKIPL B,QLDPTR(A) + JRST NLDSB6 ;NOT AN AOBJN POINTER + HLRZ C,EPDLT1(U);FIRST ADDRESS TO BE LOADED + SUBI C,(B) + JUMPLE C,NLDSB3 + HLROS B ;SKIP # WDS IN C + ADD B,C ;-# WDS REMAINING IN BLOCK + SKIPLE B + SUB C,B ;FLUSH WHOLE BLOCK + LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + ADD D,C ;ADVANCE ACC PTR TO SKIP PART OR ALL OF BLOCK + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) + JUMPGE B,[AOS QRADAD(A) ;SKIPPING WHOLE BLOCK, ALSO SKIP CHECKSUM + JRST NLDSBK] ;AND GO READ NEXT BLOCK + HRLS C + ADDM C,QLDPTR(A) ;UPDATE AOBJN POINTER +NLDSB3: MOVEI B,NLDSBF ;MAYBE FLUSH EXISTING MEMORY AND GET NEW + HRRM B,QPCLSR(A) +NLDSBF: HRRZ E,QLDPTR(A) ;START ADR OF BLOCK + HLRE C,QLDPTR(A) ;-LENGTH OF BLOCK + SUB E,C ;DON'T COMBINE THIS INSN WITH NEXT, MIGHT BE MOBY BLOCK + SUBI E,1 ;GET END ADR OF BLOCK + HRRZ T,EPDLT1(U);HIGH LOAD LIMIT + SUBM E,T ;NUMBER OF WORDS OF EXCESS IN BLOCK + MOVEM T,EPDLT2(U) ;SAVE FOR LATER USE + JUMPLE T,NLDSB7 ;JUMP IF BLOCK HAS NO EXCESS + SUB E,T ;ADJUST END ADDRESS + HRLZS T + ADDM T,QLDPTR(A);DECREASE COUNT IN AOBJN POINTER +NLDSB7: LSH E,-10. ;LAST PAGE NEEDED + PUSH P,A + PUSH P,R ;R HAS IOCHNM WD, NEEDED IF REACH QICL VIA QBI. + PUSH P,E ;PAGE NO. OF LAST PAGE NEEDED +NLDSB4: MOVE E,(P) + CAMGE E,SRN5(U) + JRST NLDSB5 ;ALREADY HAVE NEEDED PAGES + MOVE A,SRN5(U) + PUSH P,U + MOVE U,SRN3(U) ;LOOK UP THIS PAGE IN MAP OF USER WE'RE HACKING. + PUSHJ P,UPLC ;IF THERES A WRITABLE PAGE + POP P,U + LDB A,T ;IN THE SLOT ALREADY, KEEP IT. + TRNN A,600000 + TRNN A,2 + TRNE A,400000 + JRST NLDSBM + CAME U,SRN3(U) ;IF NOT HACKING SELF, NCORLL WILL LSWPOP + PUSHJ P,NULSET ;WHAT IT THINKS IS A LOSSET LIKE NLUPCL + PUSHJ P,SWTL + CIRPSW + MOVEI R,%JSNEW ;GET FRESH PAGE + MOVE TT,SRN3(U) ;INTO THE JOB WE'RE HACKING. + MOVE C,SRN5(U) ;PAGE # TO GIVE IT. + MOVSI A,%CBRED+%CBWRT+%CBNDW ;WANT WRITE ACCESS. + PUSHJ P,NCORL ;UNDOES NULSET AND SWTL. + JRST NLSBPL ;COULDNT GET PAGE (CALLED LSWCLR) +NLDSBM: AOS SRN5(U) + JRST NLDSB4 ;CHECK WHETHER WE NEED MORE PAGES. + +NLDSB5: SUB P,[1,,1] ;NOW WE HAVE ALL PAGES NEEDED TO LOAD THIS BLOCK. + POP P,R + POP P,A +NLDSBQ: MOVEI B,NLDSBC + HRRM B,QPCLSR(A) +NLDSBC: HRRZI C,QLDPTR(A) + HRLI C,(SETZ) + PUSHJ P,QBI ;DO A BLOCK IOT, USING THAT AOBJN POINTER. + AOSG B,EPDLT2(U);SKIP RESIDUE OF BLOCK AND CHECKSUM + MOVEI B,1 ;NO RESIDUE, JUST SKIP CHECKSUM + LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + ADD D,B + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) + JRST NLDSBK + +NLDSB6: LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + SUBI D,1 + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) +NLDSB8: CAME U,SRN3(U) ;UNLESS HACKING SELF OR PDP6, WE HAVE A SOSSET OF USTP TO POP. + SKIPGE SRN3(U) + CAIA + PUSHJ P,LSWPOP + AOSA (P) +NLDSB9: PUSHJ P,OPNL46 ;LOAD FILE NOT IN VALID SBLK FORMAT +NLSBP1: PUSHJ P,MPLDZ + SETZM QPCLSR(A) + POPJ P, + +NLSBPL: SUB P,[2,,2] ;FLUSH PUSHES OF E AND R. + POP P,A + JRST NLSBP1 + +SUBTTL .GUN, .LOGOUT + +;DESTROY PROCEDURE TREE WHOSE TOP INDEX SUPPLIED BY USER +AGUN: XCTR XR,[SKIPG A,(J)] + POPJ P, ;LOSE, NEG OR SYSTEM JOB + IMULI A,LUBLK + CONO PI,CLKOFF + CAMGE A,USRHI ;USER INDEX UNREASONABLE => LOSE. + CAIG A,LUBLK + JRST CLKONJ + JRST ALOGO6 + +ALOGOU: SKIPL SUPPRO(U) + JUMPN J,ABREAK ;.LOGOUT N, TURNS INTO .BREAK N,33 IF NOT TOP LEVEL + MOVE A,U ;.LOGOUT, AND STY CLOSE. + CONO PI,CLKOFF +;A HAS JOB BEING LOGGED OUT; U HAS JOB THAT'S DOING IT. +;.GUN AND .LOGOUT ACT BY PUTTING THE JOB IN SUCH A STATE THAT +;IT CAN DO NOTHING BUT TRY TO DISAPPEAR. IF THE JOB IS ALREADY +;IN THAT STATE, THIS ROUTINE DOES NOTHING. THAT PREVENTS +;RECURSION LOOPS WHEN KILLING CYCLIC STRUCTURES INVOLVING STY'S. +;EXCEPTION: IF THE JOB TO BE LOGGED OUT IS THE RUNNING JOB, +;WE DO THE REAL WORK BY GOING TO ALOGO1. +ALOGO6: SKIPE UNAME(A) ;JOB TO BE LOGGED OUT IS GONE. + SKIPL SUPPRO(A) ;CAN'T LOG OUT UNLESS TOP LEVEL. + JRST CLKONJ + CAME A,U + AOS (P) ;IF .GUN GETS THIS FAR, IT HAS "SUCCEEDED". + MOVSI T,BULGOS+BULGO + TDNE T,APRC(A) ;IF JOB IS ALREADY LOGGING OUT, + JRST ALOGO7 ; SEE IF IT IS THE RUNNING JOB + MOVSI B,%PCUSR + CAMN A,USER + AOJA B,ALOGO5 + PUSH P,U + MOVE U,USER + MOVEM A,SRN3(U) ;AUCL4 FINDS USR IDX TO HACK HERE. + PUSHJ P,LOSSET + AUCL4 ;CLEAR BULGOS IF AUCL3 PCLSR'S + PUSHJ P,AUCL3 ;SET BULGOS AND WAIT FOR DIELOK TO CLEAR. + POP P,U + CONO PI,CLKOFF + PUSHJ P,LSWDEL + EXCH B,UPC(A) ;SET HIM UP TO LOG OUT. +ALOGO4: MOVEM B,SRN3(A) ; Remember old PC for unlocking locks. + MOVE B,[.LOGOUT] ;PUT THE FOLLOWING ROUTINE IN JOB'S AC'S: + MOVEM B,AC0S(A) ; 0/ .LOGOUT + CAMN A,USER ; 1/ .VALUE + UMOVEM B,0 ; 2/ JRST 0 + MOVSI B,(.VALUE) + MOVEM B,AC0S+1(A) + CAMN A,USER + UMOVEM B,1 + MOVSI B,(JRST) + MOVEM B,AC0S+2(A) + CAMN A,USER + UMOVEM B,2 + MOVSI B,BULGOS + IORM B,APRC(A) ;SAY HE'S DIEING SO NO-ONE WILL HACK HIM. + MOVEM U,EPDL(A) ;RECORD WHO IS KILLING HIM. + MOVE B,UNAME(U) + MOVEM B,SRN4(A) + MOVE B,JNAME(U) + MOVEM B,SRN5(A) + SETZM PICLR(A) ;PREVENT INTERRUPTS. + SETZM MSKST(A) + SETZM PIRQC(A) + MOVSI B,BUSRC + ANDCAM B,USTP(A) ;MAKE SURE HE CAN RUN - ELSE HE WOULDN'T LOG OUT. +ALOGO7: CONO PI,CLKON + CAME A,USER + POPJ P, + JRST ALOGO1 ;IF JOB IS RUNNING JOB, MUST HACK AROUND + +ALOGO5: EXCH B,UUOH ;LOGGING OUT SELF - MAKE OUR PC LOOK + SOJA B,ALOGO4 ; AS IF WE HAD EXECUTED THE .LOGOUT IN AC 0 + +;COME HERE IF LOGGING OUT ONESELF (A=USER). +ALOGO1: MOVE U,A + PUSHJ P,AUCL3 ;WAIT TILL NO-ONE IS LOOKING AT ME, + PUSHJ P,UBLAM ;CLOSE MY CHANNELS AND KILL MY INFERIORS AND CORE. + MOVE A,USER + CONO PI,CLKOFF ;DON'T SCHEDULE WHILE GOING AWAY + MOVSI T,BULGO + IORM T,APRC(A) ;SYS JOB KILLS ANY TREES WITH BULGO SET. + MOVSI T,SCLGUN + IORM T,SUPCOR ;TELL SYS JOB TO LOOK AROUND FOR TREES TO KILL. + MOVSI T,BUSRC ;SUICIDE: MAKE SURE WE DON'T RUN ANY MORE. + IORM T,USTP(A) + JRST UDELAY ;CAUSE A SCHEDULE + +;COME WITH JOB INDEX IN A. INDICATE THAT JOB IS ABOUT TO DIE, +;THEN WAIT TILL IT'S SAFE TO KILL IT. +;TURNS CLOCK ON. +AUCL3: MOVSI T,BULGOS + IORM T,APRC(A) ;SAY THIS JOB STARTING TO GO AWAY. + CONO PI,CLKON ;NOONE CAN START HACKING US NOW; SAFE. + CAME A,USER ;IF NOT LOGGING OUT RUNNING USER, + PUSHJ P,1USTOP ;STOP THE JOB BEING KILLED. + SKIPE DIELOK(A) ;WAIT TILL NO-ONE IS LOOKING AT THAT JOB. + PUSHJ P,UFLS + HRLOI T,#BUSRC ;AND NO-ONE ELSE HAS HIM PCLSR'ED. + TDNE T,USTP(A) + PUSHJ P,UFLS + POPJ P, ;WE SUCCEEDED, BUT CALLER HAS WORK TO DO. + +SUBTTL REAL TIME USER FEATURE +; +;.REALT AC, SKIPS ONLY IF REAL TIME FACILITY REQUESTED AND SEIZED +;AC= 4.9=>TURN OFF OLD CLOCK RATE, FLUSHING REAL TIME FACILITY AND +; REMAINDER OF CURRENT TICK AND ZEROING TICK COUNT +; 4.8=>TURN ON NEW CLOCK RATE +; 4.7=>TRY TO SEIZE REAL TIME USER FACILITY +; 4.6=>DON'T SETTLE FOR PSEUDO-REAL TIME STATUS +; 4.5 =>ONLY WANT PSEUDO +; 4.4=>PROGRAM TO BE BLOCKED EXCEPT FOR HIGH PRIORITY PHASE OR INT. LEVEL +; 4.3=>READ INTO WD3+4 AS DESCRIBED BELOW (BEFORE ANY OTHER BITS INTERPRETED) +; 3.1-4.2=RESERVED FOR EXPANSION, SHOULD BE ZERO +; 1.1-2.9=RH=POINTER TO 4 WORD BLOCK +; WD1=FRAME TIME IN 60'THS (MUST BE <2**18.) +; WD2=PRIORITY TIME IN 60'THS (MUST BE <7 AND .CALL [SETZ ? SIXBIT/LOSE/ ? 401000,,X ] + +;.CALL LOSE +; USED TO REPORT LOSSAGE TO SUPERIOR PROCEDURE +;ARG 1 - LOSING INSTRUCTION ADDR,,LOSSAGE CODE (CODES DEFINED BY DDT) +;ARG 2 - NEW PC (DEFAULT = PC-2 SO CAN USE AS A NON-SKIP-RETURN HANDLER) +;CTL 1.1 - DEFAULT ARG 2 TO PC INSTEAD OF PC-2 +;CTL 1.2 - SETZM @.40ADDR +;CTL 1.3 - DON'T USE THE NEW PC AS THE LOSING INSTRUCTION ADDR + +ALOSE: HRRZ A,FORTY ;ARG 1 = EFF ADDR OF UUO + MOVEI W,1 + TDZA T,T +NLOSE: MOVE T,CTLBTS(U) + MOVE D,40ADDR(U) + TRNE T,2 + XCTR XRW,[MOVES (D)] + TLZ B,BADPC ;COMPUTE NEW PC FROM ARG 2 OR UUOH + SKIPGE IOTLSR(U) + TLO B,%PCUIO + TLO B,%PCUSR + MOVE C,UUOH + TRNN T,1 + HRRI C,-2(C) + CAIGE W,2 + MOVE B,C + TRNN T,4 + HRL A,B + HRRI B,1(B) ;PCLSR'ING WILL SOS + MOVEM A,VALUE(U) ;PASS TO SUPERIOR + MOVEM B,UUOH + TRNE T,2 + XCTR XW,[SETZM (D)] + MOVSI T,%PJLOS + JRST UUOERR + +AUCLOSE: +IFN PDP6P,[ + MOVE A,(R) ;OPER 10 + MOVE A,CLSTB(A) + TLNE A,%CLS6 + JRST PDPUCL +] + PUSHJ P,AUCL2 + POPJ P, + PUSHJ P,1USTOP + MOVEM A,SRN3(U) + PUSHJ P,LOSSET + AUCL4 + PUSHJ P,AUCL3 ;STOP JOB, AND WAIT TILL SAFE TO KILL IT + ;(TURNS CLOCK ON) + EXCH U,A + PUSH P,A + HLLZ T,SUPPRO(U) + PUSH P,T + PUSH P,R + PUSHJ P,UBLAST + POP P,R + PUSHJ P,ZUSLOG ;ACCOUNT FOR USAGE THEN FLUSH LAST VESTIGES + CONO PI,CLKON + POP P,T + POP P,U + ANDCAM T,IFPIR(U) + JRST LSWDEL + +AUCL4: HRRZ A,SRN3(U) + MOVSI T,BULGOS + ANDCAM T,APRC(A) + POPJ P, + +AUCL2: HLRZ A,(R) ;GUY BEING CLOSED + HRRZ B,(R) + LDB TT,[.BP (%CLSFU),CLSTB(B)] + JUMPN TT,OPNL31 ;FOREIGN JOB => .UCLOSE ISCAN'T MODIFY JOB + SKIPL CLSTB(B) .SEE %CLSU + JRST OPNL34 ;NOT A JOB AT ALL? + CONO PI,CLKOFF + MOVE TT,TTYTBL(U) + JUMPGE TT,AUCL1 ;HAVE TTY NOW + TLNN TT,%TBDTY ;NOT GIVING IT AWAY. + CAIE A,(TT) ;SKIP IF GAVE IT TO GUY WE'RE KILLING + JRST AUCL1 + PUSHJ P,SDTTY ;TAKE IT BACK FROM HIM. + JFCL +AUCL1: HLRZ A,(R) + JRST POPJ1 + +;DISMIS SYSTEM CALL. 1ST ARG INT PDL PTR (WILL BE DECREMENTED +;IF NOT AN IMMEDIATE ARG) +;2ND ARG OPTIONAL PC TO DISMIS TO (OVERRIDES THAT IN INT PDL) +;3RD ARG OPTIONAL NEW .DF1 VALUE " " " " +;4TH ARG OPTIONAL NEW .DF2 VALUE ... +;5TH ARG OPTIONAL ERROR CODE AS IN LOSE. IF PRESENT WILL LOSE RIGHT AFTER DISMISSING. +;IF 4 ARGS GIVEN, 1ST IGNORED EXCEPT FOR POSSIBLY DECREMENTING, OR POPPING OF ACS. +;CTL BITS (SAME FORMAT AS LH OF 1ST WORD OF INTERRUPT DISPATCH TABLE) +;SPECIFY POPPING OF SAME EXTRA INFO THAT INTERRUPTS CAN PUSH. + +NDISMIS:CAIL W,5 + MOVEM E,VALUE(U) + MOVE E,A ;GET IN E THE INT PDL PTR. + TLNN E,1000 ;IF 1ST ARG IMMEDIATE, IT IS PTR, + UMOVE E,(A) ;ELSE IT PTS TO PTR. + MOVE H,E ;SAVE UNPOPPED PDL POINTER FOR PDL OV CHECKING. + TLNE A,1000 ;IF PDL PTR ISN'T IMMEDIATE, POP IT ACC. TO CTL BITS. + JRST NDISM2 + MOVE T,CTLBTS(U) + TRNE T,400000 + SUB E,[3,,3] ;POP OFF DEBUGGING INFO IF IT WAS PUSHED. + LDB TT,[000500,,T] + JUMPE TT,NDISM2 ;IF ACS WERE PUSHED, POP THEM TOO. + HRLS TT + SUB E,TT ;DECREMENT THE PDL POINTER ENOUGH + LDB I,[060500,,T] + HRLI I,1(E) ;AND COPY FROM THE PDL TO THE ACS. + ADDI TT,-1(I) + XCTR XBRW,[BLT I,(TT)] +NDISM2: CAIGE W,2 ;IF NO 2ND ARG, GET PC FROM INT PDL + UMOVE B,(E) + CAIGE W,3 ;IF NO 3RD ARG, GET .DF1 FROM INT PDL + UMOVE C,-2(E) + CAIGE W,4 ;IF NO 4TH ARG GET .DF2 FROM INT PDL + UMOVE D,-1(E) + TLNE A,1000 ;IF 1ST ARG NOT IMMED, DECREMENT IT + JRST NDISM3 + SUB E,[5,,5] + UMOVEM E,(A) + JUMPGE E,NDISM3 ;AND CHECK FOR PDL OVFLO. + SKIPL H + PUSHJ P,NDISMP ;PDL OVFLO, SET INT BIT IF INT ENABLED. +NDISM3: MOVEM C,IDF1(U) ;RESTORE THE PC, .DF1, .DF2 + MOVEM D,IDF2(U) + MOVSI T,%PJLOS + CAIL W,5 + IORM T,PIRQC(U) + JRST NDISM1 + +NDISMP: MOVEI TT,%PIPDL ;PDL OV INT BIT. + TDNE TT,MSKST(U) + IORM TT,PIRQC(U) + POPJ P, + +;OLD-STYLE DISMISS JOINS HERE +ADISMIS:UMOVE B,(B) ;CALL 1, +NDISM1: TLO B,%PCUSR + TLZ B,BADPC + SKIPGE IOTLSR(U) + TLO B,%PCUIO +IFN KL10P,[ + SETCM A,UUOH ;IF ONE-PROCEEDING THE .DISMISS + TLNN A,%PS1PR-%PSINH + TLO B,%PS1PR-%PSINH ;TRAP IMMEDIATELY AT THE NEW PC +] + MOVEM B,UUOH + SETOM PICLR(U) + +;CHECK FOR PENDING INTERRUPTS AND TAKE THEM RIGHT AWAY +APISE1: +IFN PDP6P,[ + CAMN U,PDPISR + CONO DSDEV,DSDCHN ;ENABLE INTERRUPT FROM 6 +] + MOVE A,U + PUSHJ P,APISE6 ;SEE IF ANY DEVICES WANT TO RE-INTERRUPT. + MOVEI C,%PIARO + ANDCAB C,PIRQC(U) + SETCM D,MSKST(U) + IOR D,IDF1(U) ;FIND ALL DISABLED OR DEFERRED + SKIPN PICLR(U) ;(ALL ARE DEFERRED WHEN PI IS OFF). + SETO D, + AND D,[BADBTS] ;BAD + TDNE C,D ;PENDING INTERRUPTS + JRST ADISM7 ;IF THERE ARE ANY, LET THEM HAPPEN. + AND C,MSKST(U) + ANDCM C,IDF1(U) + JUMPN C,ADISM7 ;1ST WD INT. PENDING. + MOVE C,IFPIR(U) + AND C,MSKST2(U) + ANDCM C,IDF2(U) + JUMPE C,CPOPJ ;JUMP IF NO 2ND WORD INT PENDING. +ADISM7: MOVE C,[JRST ONEFLS] + MOVEM C,UEXIT + POPJ P, + +APISE6: MOVE D,MSKST(A) ;IF INTERRUPT FROM CONSOLE ENDBLED, + TRNN D,%PITYI + JRST APISE7 + SKIPL T,TTYTBL(A) ;IF THIS JOB HAS ITS CONSOLE + SKIPN TINTC(T) ;AND THE CONSOLE HAS INT. CHARS, + JRST APISE7 + MOVEI D,%PITYI ;GENERATE AN INTERRUPT. + IORM D,PIRQC(A) +APISE7: MOVE D,MSKST2(A) ;LOOK AT HIS ENABLED IO CHANNELS. + ANDI D,177777 +APISE0: JFFO D,APISE9 ;CHECK EACH ONE. + JRST APISE8 ;ALL CHECKED. + +APISE9: MOVNS E ;CHECK ONE IO CHNL THAT'S ENABLED TO INT. + ANDCM D,CHNBIT+35.(E) ;MARK THIS CHNL AS HANDLED. + ADDI E,35.+IOCHNM(A) ;GET ADDR OF IOCHNM WD FOR CHANNEL. + HRRZ T,(E) ;IS IT A TTY INPUT CHANNEL? + CAIL T,TYIDN + CAILE T,TYIBN + JRST APISE2 + LDB T,[$TIIDX,,(E)] ;YES, GET THE TTY NUMBER. + HRRZ C,TTYSTS(T) + CAIE T,%TINON ;IF IT ISN'T A DISOWNED TY CHANNEL, + CAIE C,(A) ;AND THE TTY BELONGS TO THIS JOB, + JRST APISE0 + SKIPN TINTC(T) ;AND IT HAS AN INT. CHAR WAITING, + JRST APISE0 + MOVE C,TYIMSK(T) +APISE4: AND C,MSKST2(A) ;GIVE AN INT. ON ONE OF THE CHANNELS IT'S OPEN ON. + MOVN T,C + AND C,T + IORM C,IFPIR(A) + JRST APISE0 + +APISE2: CAIN T,STYDUI ;NOT A TTY CHNL. IS IT A STY CHNL? + JRST APISE3 + CAIE T,STYDBI + JRST APISE0 +APISE3: LDB T,[$TIIDX,,(E)] ;YES, GET TTY #. + SKIPL C,STYSTS-NFSTTY(T) ;STY IN USE BY THIS JOB? + CAIE C,(A) + JRST APISE0 + SKIPGE TTYOAC(T) ;TTY OUTPUT PENDING? + JRST APISE0 + MOVE C,STYMSK-NFSTTY(T) ;YES, INT. ON ONE CHANNEL. + JRST APISE4 + +APISE8: +IFN STKP,[ + SKIPL C,STKUSR + CAIE C,(A) + POPJ P, + HRRZ C,STKMSK + AND C,MSKST2(A) + SKIPLE STKBC + IORM C,IFPIR(A) +] + POPJ P, + +;.SLEEP AC, ;IF C(AC) + OR ZERO: ;BECOME DORMANT FOR C(AC) 1/30'THS OF A SEC + ;IF C(AC) -: ;BECOME DORMANT TILL MAGNITUDE OF C(AC) > C(TIME) +ASLEEP: XCTR XR,[MOVN T,(J)] ;PICK UP NEGATIVE OF C(AC) + JUMPGE T,ASLP1 ;JUMP IF C(AC) WAS NEG + SUB T,TIME ;COMPUTE NEG OF TIME SLEEP SHOULD RUN OUT + UMOVEM T,(J) ;STORE BACK SO YOU WILL WIN IF PCLSR'ED OUT +ASLP1: MOVMS A,T ;MAKE POSITIVE + SUBI A,60.*30. ;IF SLEEPING FOR MORE THAN A MINUTE + MOVSI B,%SWDSO + CAMLE A,TIME + IORM B,USWST(U) ;PUT RIP VAN WINKLE ON ICE + PCLT + JRST ASLP2 ;ALWAYS GO TO UFLS AT LEAST ONCE + + CAMLE T,TIME ;HANG TILL C(T) LESS THAN C(TIME) +ASLP2: PUSHJ P,UFLS + XCTR XW,[SETZM (J)] ;CLEAR OUT ARG (FOR COMPATIBILITY WITH WHEN AC WAS COUNTED OUT) + JRST CLKONJ ;MAKE SURE CLKCHN ON IN CASE SLEEP WAS 0 & SKIPPED UFLS ENTIRELY + +;RELOAD CALL - IGNORE ARGS +;MUST BE FROM TOP LEVEL NON-DISOWNED JOB +;RELOADS AND STARTS SYS: ATSIGN WHATEVER + +NRELOAD:SKIPGE SUPPRO(U) + SKIPGE APRC(U) + JRST OPNL40 ;NOT TOP LEVEL + CONO PI,CLKOFF + PUSHJ P,LOGUPD ;LOG OUT + PUSHJ P,DMNPLI ;AND IN AGAIN + PUSHJ P,USRST2 ;RESET USER VARS + CONO PI,CLKON + SETZM @UTMPTR(U) ;TEMPORARY HIGH PRIORITY + JRST USTCDR ;LOAD FILE AND START IT + +AMASTER:UMOVE J,(J) + CONO PI,CLKOFF ;OPER 61 + SKIPL A,UMASTER + JRST AMAST2 + SKIPGE J +AMAST1: HRRZM U,UMASTER + JRST CLKOJ1 + +AMAST2: CAME U,A + JRST AMAST3 + SKIPL J + SETOM UMASTER + JRST CLKOJ1 + +AMAST3: JUMPGE J,CLKOJ1 + SKIPGE TTYTBL(U) + JRST CLKONJ ;LOSEY + PUSHJ P,RPCCK + CAME A,UMASTER + JRST AMASTER + JRST AMAST1 + +;.CALL SSERVE - Set .SERVER variable without timing screw. +; ARG1: , the client whose .SERVER variable is to be munged +; ARG2: , the server to be stored in the variable +; If one arg is given, it is the server and the client defaults to %JSELF +NSSERVER: + MOVE J,A + CAIL W,2 + SKIPA A,B + MOVEI J,%JSELF + JSP T,NCORUI ; Decode client and AOS his DIELOK + JRST NSSRV1 ; OK to write + JSP T,NCORWR ; Check further + JRST OPNL31 ; CAN'T MODIFY JOB +NSSRV1: +IFN PDP6P,[ + CAIN J,-1 ; PDP6? + JRST OPNL34 ; WRONG TYPE DEVICE +];PDP6P + EXCH J,A ; A: client J: server + JSP T,NCORUI ; Decode server and AOS his DIELOK + JFCL ; Don't give a damn about writability +IFN PDP6P,[ + CAIN J,-1 ; PDP6? + JRST OPNL34 ; WRONG TYPE DEVICE +];PDP6P + MOVEM J,SERVER(A) ; Safe to set it now + PUSHJ P,LSWPOP ; Server's DIELOK + JRST LSWPJ1 ; Client's DIELOK + + + SUBTTL LOGIN/ATTACH/DETACH/DISOWN CODE + +;SYMBOLIC CALL LOGIN: LOG A TREE IN. MUST BE GIVEN BY TOP-LEVEL NON-LOGGED-IN JOB +;WITH NO INFERIORS. +;ARG 1 - DESIRED UNAME +;ARG 2 - "TERMINAL NAME", PUT IN TRMNAM USER VARIABLE AND PRINTED AS SIXBIT ON SYSCON. +;ARG 3 - DESIRED XUNAME, FOR DEMON TO KNOW WHO TO ACCOUNT. + +NLOGIN: HLRE T,UNAME(U) + AOJN T,OPNL31 ;JUMP ON ALREADY LOGGED IN + SKIPL SUPPRO(U) + JRST OPNL40 ;CAN'T LOG IN IF NOT TOP LEVEL + JUMPE A,OPNL11 + HLRE T,A + AOJE T,OPNL11 ;BAD NAME + CAIGE W,3 + MOVE C,A ;IF XUNAME (ARG 3) MISSING, DEFAULT TO UNAME. + MOVEI D,0 + CONO PI,CLKOFF +ALOG2: SKIPN UNAME(D) + JRST ALOG4 + MOVE T,JNAME(D) + CAMN T,JNAME(U) + CAME A,UNAME(D) + JRST ALOG3 + JRST OPNL13 ;CONSOLE CONTROLLED TREE ALREADY LOGGED IN THAT NAME + +ALOG3: HRRZ T,SUPPRO(D) + CAMN T,U ;CAN'T LOGIN IF HAVE INFERIOR. RESTRICTION IMPOSED HERE + JRST OPNL12 ;SINCE WE NO CODE HERE TO SET INFERIOR'S UNAME. +ALOG4: ADDI D,LUBLK + CAMGE D,USRHI + JRST ALOG2 ;LOOP FOR ALL SETS OF PROCEDURE VARIABLES + HRRZ T,TTYTBL(U) + HRLI T,[ASCIZ / LOGIN /] + PUSHJ P,SGWAIT ;ASK THE SYSTEM JOB TO PRINT OUT THE RELEVANT INFO + SKIPL TTYTBL(U) ;SKIP IF NOT CONSOLE CONTROLLED + AOS SUSRS ;INCREMENT COUNT OF LOGGED IN CONSOLE CONTROLLED TREES + MOVEM A,UNAME(U) ;SET UNAME TO WHAT LOGGED IN AS + MOVEM A,SLGIV + MOVEM A,USYSNM(U) ;SET SNAME " + MOVEM A,HSNAME(U) ;SET HOME SNAME " + MOVEM C,XUNAME(U) ;SET XUNAME " " (USER MAY MUNG LATER) + MOVEM B,TRMNAM(U) + MOVEM B,SLGIV+2 ;INCLUDE TRMNAM AS SECOND NAME PRINTED + PUSHJ P,DMNPLI ;GIVE INFO TO DEMON + JRST CLKOJ1 ;TURN CLK ON AND SKIP RETURN + +ASETM2: UMOVE A,1(J) ;.OPER 5 + MOVEM A,MSKST2(U) +ASETMSK: UMOVE D,(J) ;OPER 4 + MOVE A,U + MOVEI I,1 + SOS (P) ;WILL SKIP RETURN + JRST USMASK ;ACT LIKE .SUSET. + +ARSYSI: SKIPA A,[ITSVRS] ;OPER 52 +ARDTIME:MOVE A,TIME ;OPER 17 + JRST APTUAJ + +IFE KS10P,[ ; On the KS10 they made DATAI 0, a UUO! +ARDSW: DATAI A ;OPER 20 + JRST APTUAJ +] ;IFE KS10P +IFN KS10P, ARDSW==:ILUUO + +ASUPSET:MOVEI C,003777 ;OPER 53 + XCTR XR,[AND C,(J)] + MOVE D,SUPCOR ;SAVE OLD CONTENTS + XORB C,SUPCOR + UMOVEM C,(J) + HRROI A,SUPCOR + JRST ASPST2 + +; .CALL DET +; ERROR RETURN +; NORMAL RETURN + +;DET: SETZ +; SIXBIT /DETACH/ +; SETZ [] ;SEE NCORUI + +;DISOWN JOB'S ENTIRE TREE AND FREE CONSOLE. IF TREE HAS NO +;CONSOLE, JUST MAKES IT DISOWNED. NO ARG => THIS JOB'S TREE +;ALWAYS SKIPS IF THE JOB SPEC IS REASONABLE. + +;CTL BIT 1.1 => DON'T SET SIGN OF APRC (DON'T MAKE TREE "DISOWNED"). +;CTL BIT 1.2 => USE SYSTEM TREE'S RESOURCE WORD +;CTL BIT 1.4 => KILL TREE AN HOUR FROM NOW IF IT ISN'T REOWNED +;CTL BIT 1.5 => SUPPRESS THE CONSOLE-FREE MESSAGE ON THE TTY + +NDETAC: HLRZ B,A ;XOR LH OF 1ST ARG INTO CTL BITS + XORM B,CTLBTS(U) + PUSHJ P,SWTL ;MAKE SURE NOBODY ELSE IS REARRANGING TREES. + TREESW + MOVEI J,(U) ;DEFAULT TO OUR TREE + JUMPE W,NDETA0 ;JUMP IF NO ARGS SUPPLIED + MOVE J,A ;JOB SPEC + JSP T,NCORUI ;DECODE ARG, GET USER INDEX IN J + JFCL ;IGNORE INFO ON WRITEABILITY + CAIG J,LUBLK ;DONT DETACH SYSJOB OR CORE JOB + JRST OPNL31 +NDETA0: SKIPL T,SUPPRO(J) ;FIND TOP LEVEL JOB OF TREE (IN J) + JRST [ MOVE J,T + JRST NDETA0 ] + HRRZ A,J ;TOP OF TREE + SKIPGE APRC(A) + JRST LSWCJ1 ;TREE IS ALREADY DISOWNED. + MOVEI Q,NDETA8 + PUSHJ P,IFPLUP ;STOP ALL BUT THIS JOB + PUSHJ P,NDETA7 ;DO THE WORK + JRST LSWCJ1 ;UNSTOP THE TREE + +NDETA7: PUSH P,U ;US + PUSH P,A ;TOP LEVEL + MOVEI U,(A) + CONO PI,CLKOFF + PUSHJ P,LOGUPD ;FOR ACCOUNTING PURPOSES, THIS IS LIKE A LOGOUT + CONO PI,CLKON +NDETA1: MOVEI U,(A) ;GET IN U USER INDEX OF OWNER OF TTY + MOVE A,TTYTBL(U) ;GET IN A TTY NUMBER + TLNE A,%TBDTY ;TREE HAS NO TTY => + JRST [ POP P,A ;JUST MAKE IT DISOWNED. + POP P,U + JRST NDETA5 ] + JUMPL A,NDETA1 ;GAVE TTY AWAY + MOVE T,(P) ;TOP-LEVEL JOB OF TREE SAVES USER TTY OPTIONS IN + MOVE B,TTYOPT(A) ;HIS STTYOP VARIABLE + AND B,[%TOUSR,,%TPUSR] + MOVEM B,STTYOP(T) + LDB B,[.BP (%TCRFS+%TCQRY),TTYCOM(A)] + IORI B,4 ;MAKE STTYOP NON-ZERO TO SHOW IT WAS STORED + DPB B,[170300,,STTYOP(T)] ;OVERLAPS PADLF FIELD + HRRZS A + PUSH P,TTYSTS(A) ;SAVE THIS TTY INFO + PUSH P,TTYST1(A) ;WILL PUT INTO TTY OWNER'S USER VARS + PUSH P,TTYST2(A) ;AFTER SUCCEED IN FREEING THE TTY + MOVE B,A + IMULI B,TPLEN*2 + MOVN B,TPVB+TPLEN(B) + ADD B,TCMXV(A) + PUSH P,B + MOVSI B,%TCDET ;IF TREE DETACHED DUE TO TOP LVL INT, + SKIPN USER ;THE CONSOLE FREE MESSAGE SHOULD SAY SO. + IORM B,TTYCOM(A) .SEE SYSCFM + ;THIS ALSO HAPPENS IF DIALUP LINE HUNG UP, OS'ERS BEWARE! +;DROPS THROUGH + ;DROPS IN +IFN N11TYS,[ + CONO PI,CLKOFF + PUSHJ P,TVBNCL ;CLEAR VIDEO BUFFER # + CONO PI,CLKON +];N11TYS + MOVE B,-5(P) ;GET BACK IDX OF RUNNING JOB + MOVE B,CTLBTS(B) + MOVSI T,%TACFM + TRNE B,20 ;CTL BIT 1.5 => MARK THE TTY AS NOT NEEDING CNSL FREE MSG. + IORM T,TTYSTA(A) + PUSHJ P,TTYLO1 ;NOW MAKE CONSOLE FREE. + POP P,B ;CAN'T PCLSR AFTER THIS POINT + DPB B,[$TBECL,,TTYTBL(U)] + POP P,TTSTSV+1(U) ;STORE INTO TTY'S OLD OWNER + POP P,TTSTSV(U) ;OLD TTY VARS FROM BEFORE FREEING IT + POP P,B + MOVEM B,TTSTSV+2(U) + SKIPA A,(P) ;TOP LEVEL JOB +NDETAA: HRRZ A,T + SKIPGE T,TTYTBL(A) ;SKIP IF HE HAS IT + JRST NDETAA ;NOW DO GUY HE GAVE IT TO + CAIE A,(U) + BUG ;BUT. BUT. BUT. + MOVSI B,%TBNOT+%TBDTY ;TAKEN FROM --ME-- AND DOESN'T HAVE IT + IORM B,TTYTBL(A) + HLLZS TTYTBL(A) + POP P,A ;TOP LEVEL + POP P,U ;US + HLRO B,UNAME(A) + AOSE B ;IF DETACHED TREE WAS LOGGED IN + SOS SUSRS ;ONE LESS CONSOLE CONTROLLED TREE +NDETA5: MOVSI B,BUMRTL ;IF REQUESTED, MARK TREE AS DUE TO DIE + MOVE D,CTLBTS(U) ;IN AN HOUR. + ANDCAM B,APRC(A) + TRNE D,10 + IORM B,APRC(A) + CONO PI,CLKOFF ;PERFORM ACCOUNTING FOR THIS USER AS IF HE WERE LOGGING OUT. + EXCH U,A + PUSHJ P,LOGUPD + EXCH U,A + MOVE D,JNAME(A) ;IF TOP LEVEL JOB ... + CAME D,[SIXBIT /HACTRN/] ;IS A HACTRN, + JRST NDETA3 +NDETA2: AOS D ;AOS ITS NAME LEVEL UNTIL ... + PUSHJ P,UJNAMU ;IT IS UNIQUE + JRST NDETA2 ;(UJNAMU TURNS OFF CLOCK) + MOVEM D,JNAME(A) +NDETA3: EXCH U,A + PUSHJ P,DMNPLI ;LOG BACK IN, NAME MAY HAVE CHANGED FROM HACTRN TO HACTRO + EXCH U,A + CONO PI,CLKON + MOVEI Q,NDETA9 ;NOW SAY ALL JOBS IN TREE + JRST IFPLUP ;ARE DISOWNED + +NDETA8: CAIE A,(U) ;IF JOB ISN'T SELF, STOP IT + JRST IFSTOP + POPJ P, + +;"ATTACH" SYSTEM CALL: +;1ST ARG - JOB SPEC -> OUR INFERIOR, OR TOP OF A DISOWNED TREE. +;2ND ARG - TTY SPEC (OF A TTY WHICH MUST BE FREE) + ;2ND ARG ABSENT => USE OUR CONSOLE, AND GUN OUR TREE +;CONTROL BIT 400000 => CHANGE JOB'S NAME TO HACTRN (IF 2 ARGS) +; 4 => START JOB AFTER ATTACHING (JUST LIKE DETACH) + +;CONNECTS THE SPECIFIED JOB TO THE SPECIFIED TTY, AS A CONSOLE CONTROLLED TREE. +;IF THE TTY IS OUR CONSOLE, WE ARE LOGGED OUT. +;IF THE JOB IS OUR INFERIOR, IT IS FIRST DISOWNED. + +NATTAC: PUSHJ P,SWTL + TREESW + SOJE W,NATTAN + EXCH A,B ;2ND ARG => IT IS TTY SPEC, SO DECODE IT. + JSP J,ATTYCI + MOVE A,B + MOVE B,I ;AND PUT IT IN B. + JRST NATTA6 + +NATTAN: SKIPL B,SUPPRO(U) ;NO 2ND ARG => WE MUST BE TOP LEVEL, SINCE WE'LL HAVE + JRST OPNL40 ;TO LOG OUT. B GETS NEGATIVE. +NATTA6: MOVE J,A + JSP T,NCRUI2 ;DECODE 1ST ARG, GET USR IDX IN J. + JFCL + SKIPGE A,SUPPRO(J) + JRST NATTA5 ;JOB SPEC'D MUST BE EITHER + CAIE U,(A) ;OUR INFERIOR, OR + JRST OPNL31 + JRST NATTA7 + +NATTA5: SKIPL APRC(J) ;THE TOP OF A DISOWNED TREE. + JRST OPNL31 +;NOW IF TTY IS OUR CONSOLE, B IS NEGATIVE; OTHERWISE, B HAS TTY #. +NATTA7: PUSH P,CTLBTS(U) + SETZM CTLBTS(U) ;DON'T GET FAKED OUT AT NATTA1, NATTA2, DSWNTY. + PUSH P,J + MOVE A,J + MOVEI Q,NDETA8 ;STOP SPEC'D JOB AND ITS INFERIORS. + PUSHJ P,IFPLUP + JUMPL B,NATTAG +NATTAM: CONO PI,TTYOFF + SKIPL T,TTYSTA(B) ;SEE IF TTY IS FREE + JRST NATTAL + MOVSI T,(SETZ) ;IT IS, GRAB IT + ANDCAM T,TTYSTA(B) .SEE %TACFM + ANDCAM T,TTYSTS(B) .SEE %TSFRE + CONO PI,TTYON + JRST NATTA8 ;SINCE NO PCLSR POSSIBLE, DON'T BOTHER WITH A LOSSET OF THESE + +NATTAL: HRRE Q,TTYSTS(B) + CONO PI,TTYON + SKIPG Q ;IF TTY IS IN USE + TLNE T,%TACTZ ;OR BEING ^Z'ED, DEVICE NOT AVAIL + JRST [ SUB P,[2,,2] ? JRST OPNL10 ] + MOVSI T,%TACFM+%TACTZ ;OTHERWISE JUST WAIT FOR CONSOLE FREE + TDNN T,TTYSTA(B) ;MESSAGE TO FINISH COMING OUT + PUSHJ P,UFLS + JRST NATTAM + +NATTAG: MOVE A,U ;IF HACKING OUR CONSOLE, MUST STOP OUR WHOLE TREE + MOVEI Q,NDETA8 ;(EXCEPT US, OF COURSE - NDETA8 CHECKS THAT). + PUSHJ P,IFPLUP + MOVEI B,(U) +NATTA4: MOVE B,TTYTBL(B) ;FIND THE TTY'S NUMBER. + TLNE B,%TBDTY + JRST NATTAL ;THIS TREE HAS NO TTY? + JUMPL B,NATTA4 .SEE %TBNOT + PUSHJ P,SDTTY ;GET TTY BACK TO TOP OF TREE FOR AGBLT3 LATER. + BUG + HRRO B,TTYTBL(U) +;I BELIEVE THAT NOTHING CAN PCLSR BEYOND THIS POINT. +;RH OF B HAS TTY #; SIGN IS SET IF TTY IS OUR CONSOLE. +NATTA8: AOS TTNTO(B) ;KEEP DSWNTZ FROM HALTING (WILL UNDO THIS LATER) + PUSH P,B ;PUSH ,, + HRRZ A,-1(P) ;LEGALITY OF CALL FULLY CHECKED; CAN START ALTERING. + SKIPGE APRC(A) ;IF SPEC'D JOB IS OUR INFERIOR, DISOWN IT. + JRST NATTA9 + MOVE B,TTYTBL(A) + TLNE B,%TBDTY ;IF THE INFERIOR HAS THE TTY, TAKE IT AWAY. + JRST NATTAF + PUSHJ P,SDTTY + BUG +NATTAF: HRRZ A,-1(P) + MOVEI Q,DSWNTY ;JUST LIKE .DISOWN, BUT KNOW JOBS ARE ALREADY STOPPED. + PUSHJ P,IFPLUP + PUSHJ P,NATTA1 +NATTA9: MOVEI Q,NATTA2 + MOVE A,U + SKIPGE (P) ;IF HACKING OUR CONSOLE, DISOWN OUR TREE SO IT IS FREE. + PUSHJ P,IFPLUP + ;OUR TTY NOW IN INCONSISTENT STATE SINCE WE ARE DISOWNED + ;BUT TTY STILL BELONGS TO US. AGBLT3 FIXES THAT. + MOVE B,(P) + SOSGE TTNTO(B) + BUG + MOVE TT,-1(P) ;NOW "RE-OWN" THE SPEC'D JOB + MOVE A,UNAME(TT);NOT CHANGING ITS UNAME + HRRZ J,B ;TO THE DESIRED TTY, WITH APPRO. RESOURCE WORD. + MOVEI D,USRRCE(B) + TLO D,400000 ;TELLS UFN2A THE TREE SHOULD BECOME UN-DISOWNED. + SETZ B, ;NO INTERRUPT BIT NEEDED. + SETOM DLSRCH ;INHIBIT SCHEDULING (UFN2A UNDOES THIS) + PUSH P,U + PUSHJ P,UFN2A + POP P,U + HRRZ A,-1(P) + SKIPA C,A +NATTAH: MOVE C,D ;FIND THE JOB IN THE TREE BEING ATTACHED + MOVE D,TTYTBL(C) + TLNN D,%TBDTY ;THAT IS SUPPOSED TO GET CONTROL OF THE TTY. + JRST NATTAH + SETOM SUPPRO(A) ;BUT DON'T LEAVE IT THINKING IT IS OUR INFERIOR. + SKIPGE I,(P) + JRST NATTAD + HLRE B,UNAME(A) ;ATTACHING JOB TO FREE TTY: + AOSE B + AOS SUSRS ;THIS MAY MEAN 1 MORE LOGGED IN CONSOLE-CTL'ED TREE. + CONO PI,TTYOFF + PUSHJ P,TTYINI ;INIT TTYOPT, ECHO AREA, TTYCOM, TTYSTA. + MOVSI B,%TSFRE ;NOW MAKE TTY'S TTYSTS HAPPY + ANDCAM B,TTYSTS(I) + MOVSI B,%TSCNS + IORM B,TTYSTS(I) + HRRM A,TTYSTS(I) + CONO PI,TTYON#1 ;TTYCHN ON, BUT NOT CLKCHN. + PUSH P,U + PUSH P,I ;IF THE JOB BEING ATTACHED IS LOGGED IN, + MOVE U,-3(P) ;PERFORM ACCOUNTING FOR IT. + HLRO T,UNAME(U) + AOSE T + PUSHJ P,LOGUPD + POP P,I + POP P,U +;DROPS THROUGH + ;DROPS IN + MOVE D,['HACTRN] + PUSHJ P,UJNAMU + JRST NATTAI + MOVE B,-2(P) ;SAVED CTLBTS(U) AT ENTRY + TRNE B,400000 + MOVEM D,JNAME(A) +NATTAI: MOVE B,-2(P) ;CTLBTS + MOVSI D,%USTSP ;BUSRC + TRNE B,4 + ANDCAM D,USTP(A) ;START JOB BEING ATTACHED, IF REQUESTED TO + PUSH P,U + HRRZ U,C ;GET USR IDX GIVING TTY TO IN U, +IFN N11TYS,[ + HRRZ T,I ;TTY # IN T FOR USTTV0 + PUSHJ P,USTTV0 ;GIVE THE JOB A BLINKER IF IT DESERVES ONE. + JFCL +] + POP P,A ;USR IDX TAKING TTY FROM (BUT NOT REALLY TAKING). I AND U STILL SET. + PUSHJ P,AGBLT4 ;MOVE HIS PER-JOB VARIABLES INTO THE TTY'S VARIABLES, ETC. + JRST NATTAE ;CLOCK IS NOW BACK ON. + +NATTAD: CONO PI,CLKOFF + MOVE J,JNAME(U) ;ATTACHING OUR TTY TO JOB: + MOVEM J,JNAME(A) ;GIVE JOB OUR JNAME ALONG WITH OUR TTY. + MOVE A,U + HRRZ U,C + PUSHJ P,AGBLT6 ;TRANSFER TTY TO HIM, SAVING OUR TTY STATE AND LOADING HIS. +NATTAE: MOVE U,A + POP P,B + EXCH U,(P) ;U := USER INDEX OF TOP OF TREE BEING ATTACHED + MOVSI T,BUMRTL ;SINCE TREE HAS BEEN ATTACHED, IT SHOULDN'T + ANDCAM T,APRC(U) ;DIE AN HOUR AFTER IT WAS DETACHED. + SKIPN STTYOP(U) ;RESTORE SAVED TTY OPTIONS, IF ANY + JRST NATTAP + LDB T,[170200,,STTYOP(U)] + DPB T,[.BP (%TCRFS+%TCQRY),TTYCOM(I)] + MOVE T,[%TOUSR,,%TPUSR] + ANDCAM T,TTYOPT(I) + AND T,STTYOP(U) + IORM T,TTYOPT(I) +NATTAP: HLRE T,UNAME(U) + CONO PI,CLKOFF + AOSE T + PUSHJ P,DMNPLI ;LOG HIM IN + CONO PI,CLKON + POP P,U + SUB P,[1,,1] ;FLUSH SAVED CTLBTS + PUSHJ P,LSWCLR ;UNSTOP THE JOBS AND FREE TREESW + JUMPGE B,POPJ1 ;RETURN IF WE DIDN'T GIVE AWAY OUR CONSOLE. + SETOM TTYTBL(U) ;DON'T WANT ALOGOU TO TYPE LOGOUT MESSAGE. + JRST ALOGOUT ;LOG THIS JOB OUT. + +;.CALL DISOWN +; RH OF ARG IS JOB SPEC, OF OUR INFERIOR. +; LH OF ARG XOR CONTROL BITS: +; 1.1 => RETAIN PRIORITY (DON'T SET APRC) +; 1.2 => USE SYSTEM RESOURCE +; 1.3 => CLEAR .USTP AFTER DISOWNING (THUS AVOIDING TIMING ERROR) +; 1.4 => SET BUMRTL SO THAT JOB WILL BE GUNNED IF IT IS STOPPED FOR A WHOLE HOUR +; AND NOT REOWNED OR ATTACHED. + +NDISOWN:HLRZ J,A + XORM J,CTLBTS(U) ;XOR LH OF 1ST ARG INTO CTL BITS. + HRRZ J,A + JSP T,NCRUI2 ;DECODE JOB SPEC; DON'T SET DIELOK. + JFCL + CAIN J,-1 + JRST OPNL31 ;PDP6 NO GOOD. + MOVEI R,IOCHNM(U) + ADD R,A ; R GETS ADDR OF IOCHNM WORD IF ARG WAS CHANNEL #, + TRNE A,400000 ;GET S0 IF ARG WAS OTHER SORT OF JOB SPEC. + SETZ R, + HRRZ A,J + HRRZ J,SUPPRO(A) + CAME J,U + JRST OPNL31 ;NO GOOD IF NOT OUR INFERIOR. + JRST NDISO1 ;JOIN OLD-STYLE DISOWN + +;.DISOWN CH, ;MAKES DIRECTLY INFERIOR PROCEDURE OPEN ON CHANNEL CH + ;THE TOP LEVEL JOB OF A DISOWNED JOB + +ADISOWN:HRRZ B,(R) ;PICK UP CH TYPE INDEX + SKIPL CLSTB(B) .SEE %CLSU ;SKIP IF AN INF. USER CHANNEL + JRST IOCER7 ;OTHER TYPE, GIVE IOC ERROR + HLRZ A,(R) ;PICK UP INF.'S INDEX + SETZM CTLBTS(U) +NDISO1: PUSHJ P,SWTL + TREESW + SETZM STTYOP(A) + MOVE B,TTYTBL(A) + TLNE B,%TBDTY ;SKIP IF TTY TAKEN AWAY + JRST ADISO1 + PUSH P,R + PUSH P,A ;JOB TO BE DISOWNED HAS THE TTY: TAKE IT AWAY. + PUSHJ P,SDTTY + BUG + POP P,A + POP P,R +ADISO1: MOVEI Q,DSWNTY + PUSHJ P,IFPHAK ;HACK INFERIORS + CAME U,USER + BUG + PUSHJ P,NATTA1 ;FLUSH OUR POINTERS TO INFERIOR, AND SET FLAGS + CAME U,USER + BUG + JRST LSWCJ1 ;UNSTOP HIS TREE AND FREE TREESW + +;FLUSH INFERIOR-JOB CHANNELS FROM JOB IN U TO JOB IN A +;CANNOT PCLSR BECAUSE JOB IS CURRENT OR STOPPED ALREADY +NATTA1: MOVEI R,0 ;NO PROTECTED CHANNEL + MOVEI D,%CLSU + EXCH U,A + PUSHJ P,ZUSES1 ;FLUSH POINTERS TO INFERIOR + EXCH U,A + SETOM SUPPRO(A) ;MARK AS TOP LEVEL + MOVE W,CTLBTS(U) + MOVSI TT,BUSRC ;CLEAR .USTP IF REQUESTED + TRNE W,4 + ANDCAM TT,USTP(A) + MOVSI TT,BUMRTL + TRNE W,10 + IORM TT,APRC(A) + POPJ P, + +DSWNTY: SKIPL TTYTBL(A) + BUG ;CHECKED AT HIGHER LEVEL, DATA INCONSISTENT +NATTA2: TDZA T,T ;DO SOS TTNTO OF CONSOLE TTY. +NDETA9: SETO T, ;DON'T. + PUSHJ P,CHSCAA ;LOOK AT ALL CNHLS + PUSHJ P,DSWNTZ ;BLESSING CONSOLE TTY CHNLS + MOVEI TT,SYSRCE ;SET RESOURCE POINTER TO SYSTEM OR DISOWNED + MOVE W,CTLBTS(U);DEPENDING ON CTLBTS + TRNN W,2 + MOVEI TT,USRRCE+NCT + MOVEM TT,UTMPTR(A) + MOVSI T,400000 + TRNN W,1 + IORM T,APRC(A) ;MARK AS DISOWNED + POPJ P, + +;BLESS CONSOLE TTY CHANNELS. IF T NONZERO, DON'T SOS TTNTO. +DSWNTZ: HLRZ B,(R) ;GET LH OF IOCHNM WORD + HRRZ J,(R) ;GET DEV TYPE INDEX + CAIL J,TYIDN ;SKIP IF LESS THAN LEAST TTY INDEX + CAILE J,TYOBN ;SKIP UNLESS .LTEQ. HIGHEST + POPJ P, ;NOT A TTY CHANNEL + TRZ B,#%TICNS#(.BM $TIIDX) + TRZE B,%TICNS ;SKIP IF NOT A CONSOLE TTY + CAIN B,%TINON ;DO NOTHING TO "DISOWNED" TTY CHNLS + POPJ P, + MOVEI J,%TINON ;CHANGE OTHER TTY CHNLS TO DISOWNED + DPB J,[$TIIDX,,(R)] ;CHNLS. + JUMPN T,CPOPJ ;IN NDETAC, TTNTO ALREADY SETZM'D. + SOSLE TTNTO(B) ;DECREMENT OPEN COUNT + POPJ P, + BUG ;SHOULD BE OPEN AT HIGHER LEVELS + +;ROUTINE TO SCAN ALL I/O CHANNEL AND I/O PDL SLOTS OF A PROCEDURE +;R 4.9=1 => REGULAR CHANNEL 4.9=0 => IOPUSHED CHANNEL +CHSCAA: MOVEI R,IOCHNM(A) +CHSCAN: HRLI R,-20 +CHSCA2: XCT @(P) + AOBJN R,CHSCA2 + HRLI R,-+400000 +CHSCA4: XCT @(P) + ADD R,[1,,2] + JUMPG R,CHSCA4 + JRST POPJ1 + ; +;IFPHAK AND IFPLUP TAKE A USER INDEX IN A AND THE ADDRESS OF A ROUTINE +; IN Q. THEY CALL THE ROUTINE FOR THE PROCEDURE AND ALL OF ITS +; INFERIORS BUT IFPHAK ALSO STOPS THE SPECIFIED PROCEDURE AND +; ALL ITS INFERIORS STRINGING THEIR USTP'S INTO THE CURRENT USER'S +; LSWPR. +; +IFPHAK: PUSH P,U + PUSH P,Q + MOVE U,USER ;MADE SURE YOU USE THE RIGHT LSWPR + MOVEI Q,IFSTOP ;SET UP TO STOP + PUSHJ P,IFPLUP + POP P,Q + POP P,U +IFPLUP: PUSH P,E ;SAVE E + PUSH P,H ; " H + SKIPA H,A +IFPLU5: MOVE A,E ;RECURSE + PUSH P,H + PUSH P,Q + PUSHJ P,(Q) ;CALL ROUTINE + POP P,Q + POP P,H + MOVEI E,LUBLK*2 ;INITIALIZE TO INDEX OF JOB AFTER CORE JOB +IFPLU2: SKIPN UNAME(E) + JRST IFPLU3 + HRRZ T,SUPPRO(E) + CAIN T,(A) + JRST IFPLU5 +IFPLU3: ADDI E,LUBLK ;STEP TO NEXT VAR BLOCK + CAMGE E,USRHI ;SKIP IF ALL EXAMINED + JRST IFPLU2 ;NOT ALL, CONTINUE + CAME H,A ;ALL, SKIP IF BACK TO TOP LEVEL + JRST IFPLU4 ;NOT AT TOP LEVEL, POP UP + POP P,H ;RESTORE H + POP P,E ; " E + POPJ P, ;RETURN FROM CALL TO IFPLUP + +IFPLU4: MOVE E,A ;POP + HRRZ A,SUPPRO(A) ;UP + JRST IFPLU3 ;AND CONTINE + +IFSTOP: PUSHJ P,RPCLSR ;STOP ROUTINE WHOSE INDEX IS IN A + HRRZ T,USTP(A) + SOJE T,IFSTP1 + SKIPE LSWB0+1(A) + JRST UPCLSR ;HAVE ALREADY HACKED THIS GUY +IFSTP1: MOVEI T,USTP(A) ;GET LOC OF USTP (WAS AOSED BY RPCLSR) + MOVEI H,LSWB0(A) ;GET LOC OF A LOCKED SWITCH BLOCK OF PROC STOPPED + MOVEM T,(H) ;SET WD1 + PUSH P,U + HRRZ T,U + IDIVI T,LUBLK + POP P,U + HRL T,LSWPR(U) + IORI T,603000 ;SOS WHEN UNLOCKED + MOVSM T,1(H) + MOVEM H,LSWPR(U) ;ADD TO LOCKED SWITCH LIST OF USER + POPJ P, + +UBLAM: SKIPL APRC(U) ;SKIP IF DISOWNED + PUSHJ P,SDTTY ;GET TTY UP TO THIS LEVEL + JFCL +UBLAST: PUSHJ P,IODCL ;CLOSE IO DEVICES ETC +UBLST2: SETZ B, + PUSH P,U ;DO NOT USE THIS ROUTINE FOR CORING UP. + HRRZ Q,U +IFE SWPWSP,[ + CAME Q,BUSR + JRST UBLST4 + SETOM BUSR ;SWAP-BLOCKED NO MORE + SOS NUSWB + MOVSI TT,(SETZ) + ANDCAM TT,USWSCD(U) +];SWPWSP +UBLST4: MOVE U,USER + PUSHJ P,ACRF1 ;CORE DOWN TO NUM OF BLOCKS IN B + BUG + MOVE U,USER ;;CHECK FOR ALLEGED BUG SOMEPLACE IN ACRF1 + SKIPL CORRQ(U) ; + BUG ;;NOT SUPPOSED TO RETURN UNTIL CORE REQUEST SATISFIED + POP P,U + SKIPE NMPGS(U) ; + BUG ;;THUS GUY'S CORE SHOULD BE GONE BY NOW + POPJ P, + + +AEOFC: UMOVE B,(J) + LDB B,[400,,B] ;OPER 50 + ADDI B,IOCHNM(U) + MOVE A,(B) + MOVE A,CLSTB(A) + HLR A,(B) +IFN NUNITS, TLNE A,%CLSDI +.ALSO SKIPA A,UTEOF(A) + MOVEI A,EOFCH + JRST APTUAJ + +;OPER TO REQUEST OR FLUSH RUNNING IN IOT USER MODE +AIOTLS: MOVSI A,400000 + MOVSI B,%PCUIO + XCTR XR,[SKIPGE (J)] + JRST AIOTL1 ;JUMP IF WANT TO ENTER IOTLSR MODE + ANDCAM A,IOTLSR(U) + ANDCAM B,UUOH + POPJ P, + +AIOTL1: SKIPGE IOTLSR(U) + JRST AIOTL2 ;ALREADY IN IOTLSR, JUST TURN THE BIT ON AGAIN FOR HIM + BUG INFO,SIXBIT,UNAME(U),SIXBIT,JNAME(U),[IOTLSR] + MOVEI T,SCRMSG ;WAIT FOR IT TO BE PRINTED (HA HA WHAT ABOUT BUFFERING?) + TDNE T,SUPCOR + PUSHJ P,UFLS + IORM A,IOTLSR(U) +AIOTL2: IORM B,UUOH + JRST CLKONJ + +SUBTTL FILENAME TRANSLATION + +;ROUTINE TO TRANSLATE A FILENAME. +;WANTS DEV, FN1, FN2, SNAME IN A, B, C, D RESP. LEFT-JUST. +;WANTS MODE IN RH OF E. +;RETURNS TRANSLATED NAMES IN SAME PLACE. +TRAN: SKIPN D ;MAYBE DEFAULT THE SNAME. +TRAN6: MOVE D,USYSNM(U) + MOVEM B,EPDLT1(U) + MOVEM C,EPDLT2(U) + MOVEM D,EPDLT3(U) + MOVEM A,EPDLT4(U) + SKIPN TRNCNT ;IF NO TRANSL. ENTRIES IN USE, + JRST POPJ1 ;SHORT CUT. + PUSHJ P,TRANRF ;GET READ ACCESS TO TRANSL LISTS. + LDB I,[100,,E] ;GET INPUT/OUTPUT BIT. + MOVEI H,10 ;MAX. NUM. TRANSLS ALLOWED. +TRAN0: HRROI Q,(U) ;1ST TRY THIS JOB'S TRNLST. + MOVE J,TRNLST(U) + JRST TRAN5 +TRAN1: SKIPGE Q,SUPPRO(Q) ;MOVE UP TREE TO TRNLS1. + SETZ Q, ;AFTER TOP OF TREE, USE SYS. +TRAN2: MOVE J,TRNLS1(Q) ;USE THIS GUY'S TRNLS1. + MOVEI Q,(Q) ;INDICATE THAT FACT IN SIGN. + JRST TRAN5 +TRAN3: CAME B,TRANI1(J) ;ENTRY'S FN1 MATCHES + SKIPN TRANI1(J) ;OR IS NULL? + SKIPA TT,TRANI2(J) ;YES, GET FN2. + JRST TRAN4 ;NO, TRY NEXT ENTRY. + CAME TT,C ;FN2 MTCHES OR NULL. + JUMPN TT,TRAN4 + CAME D,TRANIS(J) ;SNAME ? + SKIPN TRANIS(J) + SKIPA TT,TRANID(J) ;YES, GET DEV. + JRST TRAN4 + CAME A,TT + JUMPN TT,TRAN4 ;TEST DEV. + HLRZ TT,TRANLK(J) ;GET ENTRY'S MODE BITS. + TRNN TT,1(I) ;TRANSLATE OUR MODE? + JRST TRAN4 ;NO. + MOVEM B,EPDLT1(U) + MOVEM C,EPDLT2(U) + MOVEM D,EPDLT3(U) + MOVEM A,EPDLT4(U) +IRPS X,,OD O1 O2 OS + SKIPE TRAN!X(J) + MOVE A+.IRPCN,TRAN!X(J) +TERMIN ;REPLACE NAMES FROM ENTRY. + TRNE TT,400000 ;ATOMIC? + JRST TRANX3 ;YES, EXIT. + SOJG H,TRAN0 ;ELSE RETRANSL. + JRST TRANX2 ;IF TOO MANY TRANSL., DON'T SKIP. + +TRAN4: HRRE J,TRANLK(J) ;CDR DOWN LIST. +TRAN5: JUMPGE J,TRAN3 ;TRY NEXT UNLESS AT END. + JUMPL Q,TRAN2 ;IF DID TRNLST, DO SAME JOB'S TRNLS1. + JUMPN Q,TRAN1 ;ELSE DO SUPPRO'S TRNLS1. +TRANX3: AOS (P) ;EXIT IF DID SYS. +TRANX2: SOS TRNREF ;NO LONGER USING TRANSL. LISTS. + POPJ P, + +TRANRF: AOS TRNREF ;SAY USING TRANSL. LISTS. + SKIPGE TRANSW + POPJ P, ;OK IF NOT BEING CHANGED. + SOS TRNREF ;NOT REFERENCING AFTER ALL. + SKIPL TRANSW ;WAIT TILL FREE. + PUSHJ P,UFLS + JRST TRANRF ;TRY AGAIN. + ;TRANS SYSTEM CALL. +NTRNS: JSP T,DEFARG ;DEFAULT 5 ARGS TO 0. + 5 + XOR E,CTLBTS(U) ;XOR CTL BITS WITH ARG S + PUSHJ P,TRAN ;TRANSLATE NAME. + JRST OPNL3 ;FAIL IF TOO MANY TRANSL. + JRST POPJ1 ;ELSE GIVE BACK TRANSL'D NAMES. + + +DEFARG: CAML W,(T) ;IF NOT ALL SPEC'D, + JRST 1(T) + SETZM A(W) ;DEFAULT ONE AND RETRY. + AOJA W,DEFARG + +;LOCK TRANSW, AND SET UP 1ST ARG FOR NTRNAD, NTRNDL, NTRNCL. +;RH OF A HAS JOB SPEC; CONTROL BIT ARGS XOR'D INTO LH. +;THE 4.8 BIT, IF SET, INDICATES TRNLS1 RATHER THAN TRNLST. +;OTHER LH BITS IGNORED,, NOT CHANGED BY NTRNUI. +;ON RETURN, A'S LH IS UNCHANGED, RH IS SUCH THAT +; TRANLK(A) IS THE ADDR OF THE SPECIFIED TRNLS VAR. +NTRNUI: PUSHJ P,SWTL + TRANSW + TSC A,CTLBTS(U) + MOVEI J,(A) + JSP T,NCRUI2 ;DECODE THE JOB-SPEC. + JRST NTRNU1 ;JOB GUARANTEED WRITEABLE. + JUMPE J,NTRNU1 ;ALLOW JOBS TO MUNG THE SYSTEM TRANSLATION LIST. + JSP T,NCORWR ;ELSE CHECK. + JRST OPNL31 ;NOT WRITEABLE. +NTRNU1: CAIN J,-1 + JRST OPNL34 ;PDP6?? + HRRI A,TRNLST-TRANLK(J) + TLNE A,200000 ;4.8 BIT SAYS WHICH TRNLS TO USE. + ADDI A,TRNLS1-TRNLST + JRST (Q) + +;GET UP TO 4 ARGS INTO D ... D+3, FROM AOBJN PTR IN B. +NTRNGA: MOVSI H,-4 ;UP TO 4 ARGS. + JUMPGE B,NTRNG3 +NTRNG0: UMOVE J,(B) + JUMPGE W,NTRNG2 ;W IS -1 FOR .TRANA, .TRAND; + TRNN H,-1 ;IN THAT CASE LEFT-JUST. DEV. (1ST ARG) + HRLZI J,(J) +NTRNG2: CAMN J,[SIXBIT/*/] + MOVEI J,0 ;REPLACE * BY BLANK. + MOVEM J,D(H) ;STORE AWAY. + AOBJP H,CPOPJ ;DONE AFTER 4TH ARG. + AOBJN B,NTRNG0 ;ELSE GET NEXT. +NTRNG3: SETZM D(H) ;ZERO REMAINING ARGS. + AOBJN H,NTRNG3 + POPJ P, + ;TRANEX CALL -- READ IN A JOB'S TRANSL LIST. +;1ST ARG RH - JOB SPEC. BIT 4.8 - IF SET, TRNLS1 NOT TRNLST. +;2ND ARG AOBJN -> PLACE TO STORE LIST INTO. +;UPDATED AOBJN PTR IS OUTPUT ARG. +;SKIPS IF ENTIRE LIST FIT IN BUFFER. +;EACH ENTRY TAKES 9 WDS OF SPACE: MODE,, IN 1ST, +;INPUT DEV, FN1, FN2, SNAME; THEN OUTPUT DEV, FN1, FN2, SNAME. +NTRNEX: PUSHJ P,TRANRF ;GET READ ACCESS TO TRANSL LISTS. + PUSHJ P,SOSSET ;RELINQUISH IF BLOCKED. + TRNREF + TSC A,CTLBTS(U) + MOVEI J,(A) + JSP T,NCRUI2 ;DECODE THE JOB SPEC. + JFCL ;NOT TRYING TO WRITE. + HRRI A,TRNLST-TRANLK(J) + TLNE A,200000 ;MAKE TRANLK(A) BE TRNLS VAR. + ADDI A,TRNLS1-TRNLST + SUB B,[1,,1] ;SINCE WE AOBJ BEFORE ACTING. +NTRNE1: HRRE T,TRANLK(A) ;AT END -> RETURN SKIPPING. + JUMPL T,NTRNE8 + HLLZ D,TRANLK(T) ;RETURN LH ONLY OF 1ST WD. + TLOA T,-9 +NTRNE2: MOVE D,TRANLK(T) ;ALL OF OTHER 8 WDS. + AOBJP B,[ PUSHJ P,OPNL37 + JRST NTRNE9] + ;FAIL IF NO ROOM. + UMOVEM D,(B) + ADDI T,SIOMT-1 + AOBJN T,NTRNE2 ;STORE ALL 9. + MOVEI A,-9*SIOMT(T) ;GO TO NEXT. + JRST NTRNE1 + +NTRNE8: AOS (P) + AOBJP B,.+1 ;COMPENSATE FOR SUB . + PUSHJ P,LSWPOP ;RELEASE READ ACCESS. +NTRNE9: MOVE A,B + JRST SYSCPT ;RETURN AOBJN PTR. + ;TRANDL CALL -- DELETE ENTRY FROM TRANSL LIST. +;1ST ARG RH JOB SPEC. OF JOB WHICH IS OK TO MODIFY. +;1ST ARG LH MODE BITS AS FOR .TRANAD, ALSO 4.8 BIT SAYS TRNLS1 +; (SPEC'D JOB AND INFS, RATHER THAN JUST SPEC'D JOB) +;2ND ARG AOBJN -> INPUT DEV, FN1, FN2, SNAME. (ONLY DEV NEC.). +;SKIPS IF SOMETHING WAS DELETED. +NTRNDL: JSP Q,NTRNUI ;PROCESS 1ST ARG., LOCK TRANSW. +NTRND: PUSHJ P,NTRNDA ;ACTUALLY DELETE. + JRST OPNL4 ;NOTHING TO DELETE => FILE NOT FOUND + JRST LSWPJ1 ;SKIP IF NTRNDA DID. + +NTRNDA: TLZ A,-1#400003 + PUSHJ P,NTRNGA ;ELSE GET INPUT NAMES. + SKIPGE TRANLK(A) + POPJ P, + HRRZS (P) ;CLEAR SKIP FLAG. + SKIPA T,A +NTRND2: MOVEI T,(H) ;CDR DOWN BOTH PTRS. +NTRND0: HRRE H,TRANLK(T) ;LOOK AT NEXT ENTRY. + JUMPL H,NTRNDX ;EXIT IF END. + CAMN D,TRANID(H) ;ALL 4 INPUT NAMES MUST MATCH. + CAME E,TRANI1(H) + JRST NTRND2 ;ELSE NOT TO BE DELETED. + CAMN TT,TRANI2(H) + CAME I,TRANIS(H) + JRST NTRND2 + HLLZ R,A ;GET MODE FROM ARG. + TLZ R,400000 ;DONT CLOBBER ATOM BIT + ANDCA R,TRANLK(H) ;TURN OFF IN MODE FROM ENTRY. + CAME R,TRANLK(H) ;IF DELETED ONE, CALL WILL SKIP. + HRROS (P) + MOVEM R,TRANLK(H) + TLNE R,3 ;IF NEITHER DIRECTION LEFT, SPLICE OUT. + JRST NTRND2 + SKIPE TRNREF ;WAIT TILL NOONE READING TRANSL LISTS. + PUSHJ P,UFLS + SOS TRNCNT ;ONE LESS ENTRY IN USE. + HRRZ R,TRANFL ;MAKE LINK -> CURRENT FREE LIST. + EXCH R,TRANLK(H) + HRRM R,TRANLK(T) ;REST OF TRNLS INTO PREDECESSOR'S LINK. + HRRZM H,TRANFL ;ADD THIS ONE TO FREE LIST. + JRST NTRND0 + +NTRNDX: HRRES TRANLK(A) ;IN CASE DELETED 1ST ENTRY. + SKIPGE (P) + AOS (P) ;SKIP IF SET FLAG. + POPJ P, + ;TRANAD CALL. -- ADD AN ENTRY TO A TRANSL LIST. +;1ST 2 ARGS AS FOR TRANDL. +;3RD ARG LIKE 2ND BUT GIVES OUTPUT NAMES. +;SKIPS UNLESS ALL ENTRIES WERE IN USE. +NTRNAD: JSP Q,NTRNUI +NTRNA: TLNN A,3 ;IF RELLY NOTHING WOULD BE TRANSL'D, + JRST LSWPJ1 ;DON'T BOTHER ADDING.. + PUSHJ P,NTRNDA ;DELETE ANY EXISTING TRANSL. FOR THESE INPUT NAMES. + JFCL ;IF WERE NONE. + SKIPGE T,TRANFL + JRST OPNL5 ;NO FREE ENTRIES - DIRECTORY FULL. + AOS TRNCNT ;1 MORE ENTRY IN USE. +IRPS X,,ID I1 I2 IS + MOVEM D+.IRPCN,TRAN!X(T) +TERMIN ;PUT INPUT NAMES INTO ENTRY. + MOVE B,C + PUSHJ P,NTRNGA ;GET OUTPUT NAMES. +IRPS X,,OD O1 O2 OS + MOVEM D+.IRPCN,TRAN!X(T) +TERMIN ;STORE OUTPUT NAMES. + MOVE H,TRANLK(A) ;PUT CURRENT TRNLS INTO LINK. + EXCH H,TRANLK(T) + HRREM H,TRANFL ;STORE BACK REST OF FREE LIST. + MOVEM T,TRANLK(A) ;TRNLS NOW STARTS WITH THSI ONE. + HLLM A,TRANLK(T) ;STORE MODE BITS. + JRST LSWPJ1 + ;TRANCL CALL -- RESET A ONE OR BOTH TRANSL LISTS FOR A JOB. +;1ST ARG RH HAS JOB SPEC OF MODIFYABLE JOB. +; BIT 4.8 CLEAR TRNLS1 VAR. (TRANSL FOR THIS JOB & INFS). +; BIT 4.7 CLEAR TRNLST VAR. (TRANSL FOR THIS JOB ONLY). +; ALWAYS SKIPS IF VALID. +NTRNCL: JSP Q,NTRNUI ;RH(A) -> TRNLST OR TRNLS1 VAR. + TLNE A,200000 + SUBI A,TRNLS1-TRNLST ;MAKE -> TRNLST VAR. + SUBI A,TRNLST-TRANLK + JRST NTRNC4 + +NTRNCA: SUBI A,TRNLST-TRANLK ;MAKE HOLD USR IDX. +NTRNC: PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW +NTRNC4: AOS (P) + SKIPE TRNREF ;WAIT FOR READ REFS TO FINISH. + PUSHJ P,UFLS + TLNN A,100000 ;IF 4.7, HANDLE TRNLST. + JRST NTRNC0 + HRRE T,TRNLST(A) + SETOM TRNLST(A) ;SET LIST TO NIL. + JUMPGE T,NTRNC1 ;IF WASN'T NIL, FREE ENTRIES ON IT. +NTRNC0: TLZN A,200000 ;MAYBE HANDLE TRNLS1. + JRST LSWPOP + HRRE T,TRNLS1(A) + SETOM TRNLS1(A) + JUMPL T,LSWPOP ;NOTHING TO DO IF ALREADY NIL. +NTRNC1: MOVEI C,(T) ;SAVE START OF LIST. +NTRNC2: SOS TRNCNT ;UPDATE NUM ENTRIES IN USE. + HRRES H,TRANLK(T) + JUMPL H,NTRNC3 ;AT END, SPLICE INTO FREELIST. + MOVEI T,(H) ;ELSE CDR DOWN. + JRST NTRNC2 +NTRNC3: EXCH C,TRANFL + HRRZM C,TRANLK(T) + JRST NTRNC0 ;MAYBE CONSIDER THE OTHER LIST. + ;.TRANA, .TRAND CALLS. +ATRANA: UMOVE E,(B) + JSP T,ATRNDT ;SET UP ARGS FOR NTRNA . + PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW + JRST NTRNA + +ATRNDL: +ATRAND: XCTR XR,[SKIPN E,(B)] + JRST ATRND0 ;ZERO UNAME -> TRANCL . + JSP T,ATRNDT ;SET UP ARGS. + PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW + JRST NTRND + +ATRND0: JSP T,ATRNDT + TLO A,300000 ;SAY CLEAR BOTH LISTS. + CAMN D,[SIXBIT/*/] + SUBI A,TRNLS1-TRNLST ;NAKE SURE -> TRNLST VAR. + JRST NTRNCA + +ATRNDT: MOVE C,JNAME(U) + MOVEM C,ATRNJN ;WHO THE HELL'S USING THESE? + CAME E,UNAME(U) ;UNAME MUST BE 0 OR THSI JOB'S. + JUMPN E,CPOPJ ;ELSE MAKE UUO FAIL. + MOVNI W,1 ;SIGNAL TO NTRNGA. + MOVEI C,5(B) ;SET UP 2 AOBJN PTRS + MOVEI B,2(B) + HRLI C,-3 ;-> INPUT NAMES (B), OUTPUT NAMES (C). + HRLI B,-3 + XCTR XR,[HLL A,(B)] ;GET MODE BITS. + UMOVE D,-1(B) + JUMPE D,CPOPJ ;JNAME MUSTN'T BE 0. + CAME D,[SIXBIT/*/] ;IF *, USE THIS JOB'S TRNLS1. + JRST ATRND2 + HRRI A,TRNLS1-TRANLK(U) + JRST (T) + +ATRND2: MOVEI H,0 ;ELSE FIND JOB WITH THAT JNAME. + MOVE E,UNAME(U) ;THIS JOB'S UNAME. +ATRND1: CAMN E,UNAME(H) + CAME D,JNAME(H) + JRST ATRND3 ;NOT THE ONE WE'RE LOOKING FOR. + HRRE E,SUPPRO(H) + CAIE U,(E) ;IS THIS OUR INF. + CAIN U,(H) ;IS IT THE CURRENT JOB? + CAIA + POPJ P, ;NO, CAN'T SET ITS TRANSL LIST. + HRRI A,TRNLST-TRANLK(H) + JRST (T) ;OK, SET ITS TRNLST VAR. +ATRND3: ADDI H,LUBLK + CAMGE H,USRHI ;LOOK AT ALL JOBS. + JRST ATRND1 + POPJ P, ;CAN'D TRANAD NON EX JOB. + +SUBTTL JOB, BOJ DEVICE ROUTINES + +EBLK +JBMN==10 ;MAXIMUM NUMBER OF JOBS ON JOB DEVICE + +JBCUI: REPEAT JBMN,-1 ;-1 => CHNL FREE, ELSE (IF JBCG POSITIVE) CREATOR'S USR IDX. +JBCG: BLOCK JBMN ;-1 IF CREATOR GONE AWAY +JBWST: REPEAT JBMN,SNJOB ;CREATED JOB'S WAIT STATUS (CREATED JOB=HANDLER JOB) +%JB==1,,525252 +%JBWIN==400000 ;4.9 => CREATED JOB HAS DONE A SUCCESSFUL JOBRET +%JBREU==200000 ;4.8 => JOB CLOSED AND MADE ITSELF AVAILABLE FOR REUSE +%JBVAL==020000 ;4.5 => VALID BIT (CREATOR CAME IN, NO JOBRET YET) +%JBSTR==010000 ;4.4 => STORED BIT (CREATOR CAME IN, NO JOBGET YET) +%JBUNH==004000 ;4.3 => BOJ BLK UNHANG BIT +%JBSIO==001000 ;4.1 => IF DOING AN IOT, THIS BITS SAYS ITS REALLY A SIOT +%JBLOS==000400 ;3.9 => CREATED JOB WAS CLOSED AND KNOWS IT, SO DON'T REUSE + ;1.1-2.9 => LAST STATUS SET BY BOJ + +JBDEV: BLOCK JBMN ;DEVICE NAME, USER-SETTABLE (MOSTLY FOR PEEK AND WHO LINES) +JBFN1: BLOCK JBMN ;FN1 +JBFN2: BLOCK JBMN ;FN2 +JBSYS: BLOCK JBMN ;SYSNAME +JBOPNM: BLOCK JBMN ;OPEN MODE +JBFNP: BLOCK JBMN ;BP TO ASCIZ FILENAME STRING IN USER ADDRESS SPACE (OR 0 IF NONE). +JBCJUI: BLOCK JBMN ;RH = CREATED JOB'S USER INDEX. + ;LH = -1 IFF CREATED JOB GOING AWAY. JOB MUST EXIST + ;SINCE WHEN IT DIES IT FLUSHES THE JOB CHANNEL + ;AND ITS CREATOR'S CHANNELS. +JBSTS: BLOCK JBMN ;STATUS OF JOB-BOJ INTERACTIONS +;4.9=1 => IMAGE =0 => ASCII +;4.8=1 => BLOCK =0 => UNIT +;4.7=1 => WRITE =0 => READ +;4.6-4.3 => NUMBER OF TIMES TO SKIP +;4.2-3.6 => OPEN LOSS +;3.5-3.2 => # OF ARGS ON LAST .CALL +;1.4 => SYSTEM CALL OTHER THAN THOSE BELOW. +;1.3-1.1 => SYSTEM CALL + ;0 OPEN + ;1 IOT OR SIOT + ;2 MLINK + ;3 RESET + ;4 RCHST + ;5 ACCESS + ;6 FDELE (DELETE OR RENAME) + ;7 FDELE (RENAME WHILE OPEN) + +JBST2: BLOCK JBMN ;SECOND WORD OF JOBGET INFO + ;FOR UNIT IOT, 1 + ;FOR SIOT, THE BYTE COUNT + ;FOR BLOCK IOT, THE BLOCK POINTER + ;NEW FN1 FOR RENAME, MLINK. +JBOFN1: BLOCK JBMN ;FN1 BEFORE LAST TRANS +JBOFN2: BLOCK JBMN ;FN2 "" "" +JBOSYN: BLOCK JBMN ;SYSNAM "" +JBODEV: BLOCK JBMN ;DEV " " +JBNFN2: BLOCK JBMN ;NEW FN2 FOR FDELE. +JBAC7: BLOCK JBMN ;7TH ARG TO .CALL, NEW SNAME FOR MLINK. +JBAC10: BLOCK JBMN ;TABLE FOR .CALL ARG 10, FIRST BP ARG TO SOPEN/RENAME/MLINK/DELETE. +JBAC11: BLOCK JBMN ;TABLE FOR .CALL ARG 11, SECOND BP ARG TO RENAME, MLINK OR RENMWO. + +JBACTB: JBST2(H) ;TABLE OF POINTERS TO .CALL ARG TABLES + JBOFN1(H) + JBOFN2(H) + JBOSYN(H) + JBODEV(H) + JBNFN2(H) + JBAC7(H) + JBAC10(H) + JBAC11(H) + +JBIOCJ: BLOCK JBMN ;IO CHNL ERROR WORD. 4.9 => IOCER ON NEXT JOB IOT + ;RH = IOCER TYPE + +JBSW: -1 ;LOCK ON ASSIGNMENT OF INDEX IN ABOVE TABLES + 0 +BBLK + +;OPEN ON BOJ: DEVICE + +;3.5 = 1 => UNHANG ON BLK IOT AFTER EACH XFER OF MAXIMAL SIZE +BOJO: JUMPN W,OPNL12 ;NO SUCH MODE + SKIPGE E,JBI(U) ;JOB CHANNEL INDEX + JRST [ MOVE E,OPTION(U) ;IF THIS JOB ISN'T A JOB DEVICE, + TLNN E,%OPOJB ;IF IT'S EXPECTING TO BE AN OJB DEVICE, OK. + JRST OPNL10 ;OTHERWISE IT CAN'T WIN. + SKIPGE JBI(U) ;IF IT CAN WIN, WAIT TILL IT HAS. + PUSHJ P,UFLS + JRST BOJO] ;THEN TRY AGAIN. + CAIL E,JBMN + BUG ;JOB CHANNEL INDEX TOO BIG + CAME U,JBCJUI(E) + BUG + HRLZ A,E + HLRZS C + MOVSI TT,%JBUNH + TRNE C,20 + IORM TT,JBWST(E) + JSP Q,OPSLC7 + BDUAI,,BDUAO + BDBI,,BDBO + BDUII,,BDUIO + BDBI,,BDBO + +;OPEN ON JOB: DEVICE +;MODE BITS: +;3.1-3.3 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT +;A,B HAVE FILENAMES, RH(C) HAS DEVICE (JOB OR OJB) +;RH(D) AND LH(C) BOTH HAVE OPEN-MODE. + +JOBO: PUSHJ P,FLDRCK + JRST JOBO3 + JRST OPNL11 ;ILLEGAL FILE NAME +JOBO3: CAMN A,[SIXBIT /M.F.D./] + CAME B,[SIXBIT /(FILE)/] + JRST JOBO2 + JRST OPNL11 ;ILLEGAL FILE NAME +JOBO2: MOVEI J,0 ;SET J TO JOBGET "COMMAND" NUMBER + CAIN W,2 + MOVEI J,2 ;MLINK, MOSTLY JUST LIKE FDELE, BUT SEE JOBOF3 + CAIN W,4 + MOVEI J,6 ;FDELE + MOVNI E,1 + MOVSI Q,-JBMN + PUSHJ P,SWTL ;LOCK JOB CHNL ASSIGN SWITCH + JBSW +JOBO5: SKIPGE TT,JBCUI(Q) ;SKIP IF NOT FREE + JRST JOBO4 + MOVE T,UUOH + TLNN T,%PCFPD + JRST JOBORU ;JUMP IF THIS IS FIRST ATTEMPT TO OPEN + HRRZ H,C + CAIN H,'OJB + JRST JOBO6 + SKIPGE JBCG(Q) ;LOOK FOR CHANNEL ON WHICH THIS USER + CAIE TT,(U) ;PREVIOUSLY ATTEMPTED TO OPEN, BUT PCLSRED + JRST JOBO6 + MOVE T,EPDLT1(U) + MOVE TT,EPDLT2(U) + CAMN T,JBFN1(Q) + CAME TT,JBFN2(Q) + JRST JOBO6 ;NOT OPENING SAME FILE + MOVE TT,EPDLT4(U) + MOVE T,EPDLT3(U) + CAMN TT,JBDEV(Q) + CAME T,JBSYS(Q) + JRST JOBO6 ;NOT FOR SAME FILE + CONO PI,CLKOFF + HLRZ H,C + HRRZ T,JBSTS(Q) + CAIN T,(J) + CAME H,JBOPNM(Q) + JRST JOBO6 ;NOT FOR SAME OPEN TYPE AND MODE + MOVE TT,JBWST(Q) + TLNE TT,%JBLOS+%JBWIN+%JBREU + JRST JOBO6 ;HANDLER JOB NOT IN CORRECT STATE + HRRZ E,Q ;REUSE SAME HANDLER JOB AS IN PREVIOUS ATTEMPT TO OPEN + SETZM JBCG(E) ;I'M BACK + PUSHJ P,LSWPOP ;FREE JBSW + TLO TT,%JBVAL + MOVEM TT,JBWST(E) ;RE-GIVE OPEN COMMAND STILL SITTING IN JBSTS ETC. + HRLI E,400000 ;OPEN-TYPE WAIT + PUSHJ P,JBWT2 ;WAIT FOR HANDLER JOB TO PROCESS IT + JRST JOBO8 ;FINISH OFF THEN OPEN + +;FIRST ATTEMPT TO OPEN, CHECK FOR REUSEABLE HANDLER JOBS BEFORE CREATING NEW +JOBORU: CONO PI,CLKOFF + MOVE TT,JBWST(Q) + SKIPGE JBCG(Q) + TLZN TT,%JBREU + JRST JOBO6 ;IN USE ALREADY OR NOT WILLING TO BE REUSED + MOVE T,EPDLT4(U) + CAMN T,JBODEV(Q) + JRST JOBOR1 ;IF SAME SIMULATED DEVICE, OK TO SIEZE + CAMN A,JBOFN1(Q) + CAME B,JBOFN2(Q) + JRST JOBO6 ;DIFFERENT HANDLER NAME + MOVE T,USYSN1(U) + CAME T,JBOSYN(Q) + JRST JOBO6 ;DIFFERENT HANDLER NAME +JOBOR1: MOVEM TT,JBWST(Q) ;THIS ONE OK, SIEZE IT + HRRZ E,Q + MOVEM U,JBCUI(E) + HLRZM C,JBOPNM(E) + SETZM JBCG(E) + SETZM JBIOCJ(E) + PUSHJ P,LSWPOP ;FREE JBSW + JRST JOBO7 + +JOBO4: HRRZ E,Q ;REMEMBER FREE JOB CHNL IN CASE NEEDED +JOBO6: CONO PI,CLKON + AOBJN Q,JOBO5 ;SCAN REST OF JOB CHANNELS + JUMPL E,OPNL6 ;DEVICE FULL + MOVEM U,JBCUI(E);STORE CREATOR'S USER INDEX + PUSHJ P,LSWPOP ;FREE JOBSW + PUSHJ P,STMSET ;SETOM JBCUI(E) ON LOSSAGE + JBCUI(E) + SETZM JBDEV(E) + SETZM JBFNP(E) + HLRZM C,JBOPNM(E) + SETZM JBCG(E) + SETZM JBIOCJ(E) + MOVEI T,SNJOB ;INITIALIZE STATUS + MOVEM T,JBWST(E) + PUSH P,R + PUSH P,U + PUSH P,J + PUSH P,D + PUSH P,E + PUSH P,A + PUSH P,B + ANDI C,-1 ;FOR OJB DEVICE, LOOK FOR EXISTING JOB. + CAIN C,'OJB + JRST JOBO6B + MOVE A,UNAME(U) ;FOR JOB DEVICE, CREATE NEW JOB. + IDIVI E,10. + MOVEI B,'0(E) + LSH B,6 + ADDI B,'0(TT) + ADD B,[SIXBIT /JOB./] ;CREATE JNAME = 'JOB.MN' + MOVE C,[7,,(SIXBIT /USR/)] + MOVE D,[SETZ 3] + PUSHJ P,USROJ ;GENERATE USER(CAN ONLY PCLSR BEFORE CREATING INFERIOR) + JRST POP7J ;USER OPEN FAILED, MUST HAVE GONE TO OPNL ALREADY + CONO PI,CLKOFF + POP P,B + POP P,A + POP P,E + SETOM SUPPRO(TT) + MOVE T,[JBSTCD,,AC0S] + ADDI T,(TT) + BLT T,AC17S(TT) + HRLZI T,%PCUSR + MOVEM T,UPC(TT) + MOVEM A,AC0S+10(TT) + MOVEM B,AC0S+11(TT) + MOVE T,USYSN1(U) + MOVEM T,USYSNM(TT) ;SET CREATED JOB'S SYS NAME TO OURS + SETZM USTP(TT) ;START JOB AS SOON AS CLK BACK ON + JRST JOBO6C + +;OJB: DEVICE, LOOK FOR JOB WHOSE NAMES ARE THE FILENAMES SPECIFIED IN THE OJB OPEN. +JOBO6B: MOVE C,[7+UBPFJ,,'USR] ;DON'T EVER CREATE JOB FOR OJB. + MOVE D,[SETZ 3+UBPFJ_<-1>] + PUSHJ P,USROOJ + JRST POP7J + SUB P,[2,,2] + POP P,E +;TT HAS USER IDX OF JOB TO BE USED; CAN'T PCLSR AFTER THIS POINT. +JOBO6C: PUSHJ P,LSWDEL ;SETOM JBCUI(E) + POP P,D + POP P,J + POP P,U + POP P,R + HRRZM TT,JBCJUI(E) + MOVEM E,JBI(TT) +JOBO7: CONO PI,CLKOFF + MOVE TT,EPDLT1(U) + MOVEM TT,JBOFN1(E) + MOVEM TT,JBFN1(E) + MOVE TT,EPDLT2(U) + MOVEM TT,JBOFN2(E) + MOVEM TT,JBFN2(E) + MOVE TT,EPDLT3(U) + MOVEM TT,JBOSYN(E) + MOVEM TT,JBSYS(E) + MOVE TT,EPDLT4(U) + MOVEM TT,JBODEV(E) + MOVEM TT,JBDEV(E) + MOVE TT,EPDL(U) + MOVEM TT,JBAC10(E) + MOVE TT,EPDL3(U) + MOVEM TT,JBAC11(E) + JUMPN J,[PUSHJ P,JFDEL5 ;DELETE/RENAME/MLINK + JRST JOBO9] + LDB TT,[000300,,JBOPNM(E)] + ROT TT,-3 + MOVEM TT,JBSTS(E) + HRRZ C,JBOPNM(E) ;GET ALL OF OPEN MODE + MOVEM C,JBNFN2(E) ;GIVE IT +JOBO9: PUSHJ P,JBWT1 ;STORE STUFF AND HANG +JOBO8: LDB TT,[350400,,JBSTS(E)] + JUMPE TT,JOBOPL ;OPEN LOST + LDB C,[000400,,JBSTS(E)] + JUMPN C,[ SETOM JBCG(E) ;DELETE/RENAME/MLINK + JRST POPJ1 ] + MOVE C,JBOPNM(E) + SETZM IOCHST-IOCHNM(R) + HRLZ A,E + JSP Q,OPSLC7 + JDUAI,,JDUAO + JDBI,,JDBO + JDUII,,JDUIO + JDBI,,JDBO + +JOBOPL: LDB C,[270600,,JBSTS(E)] + SETOM JBCG(E) + SKIPE C + CAILE C,NOPNLS + MOVEI C,22 + JRST OPNL1-1(C) + +;RENAME WHILE OPEN ON JOB CHNL +JFDEL4: HLRZ E,(TT) ;JOB CHNL INDEX + MOVEI J,7 + PUSHJ P,JFDEL5 ;DO "FDELE" + MOVE TT,EPDL3(U) ;PASS ALONG THE BP ARG IF THERE WAS ONE. + MOVEM TT,JBAC11(E) + SETZM JBAC10(E) + JRST AIOCA1 ;GET RESULTS + +;FDELE/RENMWO/MLINK ON JOB CHANNEL +JFDEL5: MOVEM J,JBSTS(E) + MOVE TT,SRN3(U) ;REMEMBER NAMES TO RENAME AS + MOVEM TT,JBST2(E) ;FOR JOBGET TO RETURN. + MOVE TT,SRN4(U) + MOVEM TT,JBNFN2(E) + MOVE TT,SRN5(U) ;IN CASE THIS IS MLINK, MAKE SURE THE "TO" SNAME + MOVEM TT,JBAC7(E) ;IS GIVEN TO JOBGET. + CONO PI,CLKOFF + POPJ P, + +;GIVE AN INTERRUPT TO THE JOB DEVICE HANDLER. +;JOB CHNL INDEX IN E, CLOBBERS TT,J,Q,H +;CALL WITH CLKOFF + +JBINT: HRRZ TT,JBCJUI(E) + MOVEI J,IOCHNM(TT) + HRLI J,-20 + MOVSI H,%CLSBJ +JBINT1: MOVE Q,(J) + TDNN H,CLSTB(Q) ;SKIP IF BOJ +JBINT2: AOBJN J,JBINT1 + JUMPGE J,CPOPJ + SUBI J,IOCHNM(TT) + MOVE Q,CHNBIT(J) + IORM Q,IFPIR(TT) + ADDI J,IOCHNM(TT) + JRST JBINT2 + +;THIS IS THE CODE PUT IN THE ACS TO LOAD IN THE JOB DEVICE HANDLER + +JBSTCD: .OPEN 1,7 ;0 + .LOGOUT + .CALL 12 + .LOGOUT + .IOT 1,2 + .CLOSE 1, + JRST (2) + 4,,(SIXBIT /DSK/) ;7 + 0 ;10 FN1 + 0 ;11 FN2 + SETZ ;12 + SIXBIT /LOAD/ + 16 + SETZ 17 + -1 ;16 (LOAD INTO SELF) + 1 ;17 + +;HAND THE JOB DEVICE HANDLER A SYSTEM CALL AND WAIT FOR IT TO BE HANDLED. +;CALL WITH CLOCK OFF, JOB CHNL IN E +JBWT1: TLOA E,400000 ;OPEN/FDELE/MLINK, CLOSE CHANNEL IF PCLSR +JBWT: TLZ E,400000 ;NORMAL ENTRY POINT, DON'T CLOSE IF PCLSR + TLZA E,200000 +JBWTI: HRLI E,200000 ;ENTER HERE TO INHIBIT SETTING %PCFPD IF PCLSR + MOVSI TT,%JBVAL+%JBSTR + IORM TT,JBWST(E) ;TURN ON VALID AND STORED +JBWT2: PUSHJ P,JBINT ;GIVE INT + PUSHJ P,LOSSET + JBPCL ;CLEAR VALID AND STORED IF PCLSR + MOVE T,E ;CAUSES EPDL2 TO HAVE JOB INDEX + PCLT +JBFLS: SKIP JBFLS + PUSHJ P,UFLS ;AWAIT RESULTS FROM HANDLER JOB + MOVSI TT,%PCFPD + ANDCAM TT,UUOH ;NOW WE KNOW WE'LL RETURN TO USER WITHOUT PCLSRING FIRST + JRST LSWDEL + +JBPCL: MOVE A,AC0S+E(U) ;HERE IF PCLSR OUT + SKIPL JBCJUI(A) ;UNLESS HANDLER GOING AWAY + TLNE A,200000 ;OR THIS SYSTEM CALL DOESN'T WANT IT, + JRST JBPCL1 + MOVSI T,%PCFPD ;SET FIRST PART DONE FLAG + IORM T,UPC(U) ;NOTE PCLSR HAS ALREADY MOVED UUOH INTO UPC +JBPCL1: MOVSI T,%JBVAL+%JBSTR ;NOT VALID, NOT STORED + ANDCAM T,JBWST(A) + JUMPGE A,CPOPJ + SETOM JBCG(A) ;SAY THE CREATOR HAS CLOSED IT +IRPS X,,E TT J Q H + PUSH P,X +TERMIN + MOVE E,A ;AND GIVE THE HANDLER AN INTERRUPT + PUSHJ P,JBINT +IRPS X,,H Q J TT E + POP P,X +TERMIN + POPJ P, + +;JOB DEVICE BLOCK MODE IOT EITHER DIRECTION +JBBI: XCTR XRW,[MOVES D,(C)] ;REFERENCE POINTER + LDB B,[410300,,D] + CAIGE B,3 + POPJ P, + MOVEM D,JBST2(A) + MOVE B,C + HRRZ T,D ;-> FIRST WORD TO TRANSFER + HLROS D ;MINUS WORD COUNT + IORI D,700000 ;FLUSH CHAR COUNT + SUBM T,D ;D -> LAST WORD + 1 TO TRANSFER + JRST JBIPG ;SWAP IN BUFFER THEN DO IOT + +;JOB DEVICE UNIT MODE IOT EITHER DIRECTION + JRST JBSI ;SIOT +JBUI: MOVSI T,%JBSIOT + ANDCAM T,JBWST(A) + MOVEI T,1 + MOVEM T,JBST2(A) + UMOVE W,(C) ;FOR UNIT OUTPUT +JBIOT1: HRRZ TT,JBOPNM(A) + ROT TT,-3 ;MODE + HRRI TT,1 ;IOT CMD + HRRZ E,A ;JOB CHNL INDEX + MOVEM TT,JBSTS(E) + MOVEM C,SRN3(U) ;MAY BE ADDRESS OF BLOCK IOT POINTER + CONO PI,CLKOFF + SKIPL TT,JBIOCJ(E) + JRST JBWTI ;GO SIGNAL HANDLER JOB + SETZM JBIOCJ(E) ;TAKE IOC ERROR INSTEAD + JRST IOCERF-MIOTER(TT) + +;JOB DEVICE SIOT EITHER DIRECTION +JBSI: AOS (P) ;SIOT SHOULD SKIP RETURN + MOVSI T,%JBSIOT + IORM T,JBWST(A) + XCTR XRW,[MOVES T,(B)] ;BYTE PNTR ARG + LDB E,[300600,,T] ;BYTE SIZE + MOVEI D,36. + IDIVM D,E ;E := # BYTES PER WORD + XCTR XRW,[MOVES D,(C)] ;BYTE COUNT ARG + MOVEM D,JBST2(A) + IDIV D,E ;D := WORD COUNT, E := EXCESS BYTES + IBP T ;-> FIRST WORD TO TRANSFER + ADD D,T + SOJLE E,JBIPG +JBSI1: IBP D + SOJG E,JBSI1 +JBIPG: HRRZS D ;-> LAST WORD TO TRANSFER + 1 + ANDI T,-2000 ;-> FIRST PAGE INVOLVED IN TRANSFER + LDB E,[.BP .UII#.UIO,JBOPNM(A)] ;0 INPUT 1 OUTPUT +JBIPG1: SKIPE E ;SWAP IN THE NECESSARY PAGES + XCTR XR,[SKIPA 20(T)] + XCTR XRW,[MOVES 20(T)] + ADDI T,2000 + CAMGE T,D + JRST JBIPG1 + JRST JBIOT1 + +;FLSINS ROUTINE TO WAIT FOR CREATOR TO BE HUNG AT JBFLS +;4.9 OF SRN3 = 1 => WAIT FOR WRITE 0 => READ +;1.1-1.4 => CODE OF UUO TO WAIT FOR + +BJWAIT: SKIPE B,FLSINS(T) + CAME B,JBFLS + POPJ P, ;NOT HUNG AT JBFLS + HRRZ B,EPDL2(T) ;JOB INDEX THAT CREATOR IS HACKING + HLRZ E,T ;JOB INDEX OF BOJ USER + CAME B,E + POPJ P, ;CREATOR HACKING JOB DEVICE ON SOME OTHER CHANNEL + MOVE TT,JBSTS(B) + LSH TT,2 ;4.9 => READ/WRITE BIT NOW + EQV TT,SRN3(U) ;4.9 OF SRN3 => WHAT TO LOOK FOR + JUMPGE TT,CPOPJ ;DOESN'T MATCH + MOVE TT,JBSTS(B) ;INSN CREATOR IS DOING + XOR TT,SRN3(U) ;INSN LOOKING FOR + TRNN TT,17 + AOS (P) ;THEY MATCH, AWAKEN BOJ JOB + POPJ P, + +;BOJ DEVICE UNIT MODE OUTPUT +BJUO: SKIPGE C + SKIPA H,(C) + UMOVE H,(C) + MOVEI B,1 ;WAIT FOR INPUT IOT + MOVEM B,SRN3(U) + HRLZ T,A ;JOB INDEX + HRR T,JBCUI(A) ;CREATOR'S USER INDEX + PUSHJ P,CWAIT ;WAIT FOR CREATOR TO BE IN IOT, RETURN WITH CLK OFF + PUSHJ P,BJWAIT + PUSHJ P,BJUO1 + JRST CLKONJ + +BJUO1: MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJUOB ;BLOCK MODE CREATOR IOT + LDB D,[.BP (%JBSIOT),JBWST(A)] + JUMPN D,BJUOS ;CREATOR SIOT + MOVEM H,AC0S+W(T) +BJIUNH: MOVSI D,%JBWIN + IORM D,JBWST(A) ;SET SUCCESSFUL JOBRET BIT + MOVSI D,%JBVAL+%JBSTR + ANDCAM D,JBWST(A) + MOVEI D,0 + DPB D,[350400,,JBSTS(A)] ;DON'T SKIP + EXCH D,FLSINS(T) ;RESTART CREATOR + CONSO PI,1 + CAME D,JBFLS + BUG ;HE WASNT WHERE HE BELONGED + POPJ P, ;NEED NOT CLKON, CALLER WILL TURN IT ON + +;BOJ UNIT OUTPUT TO JOB SIOT +BJUOS: PUSHJ P,BJBINI + XCTRI XBYTE,[IDPB H,(B)] + SKIPA C,AC0S+C(T) + BUG + XCTR XRW,[SOSG (C)] + JRST BJIUNP + JRST PLDZ + +BJBINI: HRLI T,%UMALL + MOVE J,T + PUSHJ P,PLD1 + MOVE B,AC0S+B(T) + XCTRI XRW,[MOVE D,(B)] + POPJ P, + BUG + +;BOJ UNIT OUTPUT TO JOB BLOCK IOT +BJUOB: PUSHJ P,BJBINI + SKIPL JBSTS(A) + JRST BJUOBA ;ASCII + XCTRI XW,[MOVEM H,(D)] + CAIA + BUG + ADD D,[1,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + JUMPGE D,BJIUNP + JRST PLDZ + +;BOJ UNIT OUTPUT TO JOB BLOCK IOT, ASCII MODE +BJUOBA: LDB E,[410300,,D] ;CHAR COUNT + CAIGE E,3 + JRST BJIUNP + XCTRI XR,[MOVE W,(D)] + SKIPA E,BTOCHT-3(E) + BUG + IDPB H,E + XCTRI XW,[MOVEM W,(D)] + CAIA + BUG + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + TLNE D,700000 + JRST PLDZ +BJIUNP: PUSHJ P,BJIUNH ;UNHANG CREATOR + JRST PLDZ + +;BOJ DEVICE BLOCK OUTPUT +BJBO: SKIPGE JBCG(A) + POPJ P, + XCTR XRW,[MOVES D,(C)] ;D GETS IOT POINTER + LDB E,[410300,,D] + CAIGE E,3 + POPJ P, + HLRO B,D + IORI B,700000 ;FLUSH CHAR CNT + HRRZ T,D + SUB T,B + CAILE T,-1 + JRST IOADC ;DON'T WRAP AROUND (WHY NOT?) + UMOVE H,(D) ;H GETS FIRST WORD + MOVEI B,1 + PUSHJ P,BJBWT ;WAIT FOR JOB INPUT IOT, COME BACK WITH CLK OFF. + JRST CLKONJ ;UNHANG + MOVEI I,1 ;FOR BJBB + MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJBB ;CREATOR IOT IS IN BLOCK MODE + JUMPGE TT,BJBOA ;CREATOR IOT IS ASCII + ADD D,[1,,1] +BJBO1: PUSH P,C + PUSH P,D + PUSHJ P,BJUO1 + POP P,D + POP P,C + XCTRI XW,[MOVEM D,(C)] + SKIPA T,IOTTB+BDBO + BUG +BJBEX: TLNN D,700000 + JRST CLKONJ ;BOJ BLOCK POINTER EXHAUSTED + MOVE E,JBWST(A) + CONO PI,CLKON + TLNN E,%JBVAL ;SKIP IF JOB IOT STILL WAITING FOR MORE + TLNN E,%JBUNH + JRST (T) ;TRANSFER MORE + POPJ P, ;UNHANG BOJ IOT PREMATURELY + +;BOJ BLOCK ASCII OUTPUT FETCH CHARACTER +BJBOA: MOVE E,BTOCHT-3(E) + MOVE W,H + ILDB H,E + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + JRST BJBO1 + +;BOJ BLOCK IOT WAIT. AWAITS JOB IOT, UNLESS UNHANGING. +;TURNS CLKOFF. SKIPS UNLESS SUPPOSED TO UNHANG. +BJBWT: MOVEM B,SRN3(U) ;SAVE WHAT JOB UUO TO WAIT FOR + HRLZ T,A ;SET UP ARG FOR BJWAIT FLSINS + HRR T,JBCUI(A) + MOVE TT,JBWST(A) ;CHECK FOR DON'T HANG MODE + TLNE TT,%JBUNH + JRST BJBWT1 + PUSHJ P,CWAIT ;WAIT FOR JOB IOT + PUSHJ P,BJWAIT + JRST POPJ1 + +BJBWT1: CONO PI,CLKOFF ;IF NOT ALREADY IN JOB IOT, DON'T WAIT + JRST BJWAIT ;TEST CREATOR STATUS, POPJ OR POPJ1 + +;BOJ DEVICE UNIT MODE INPUT +BJUI: MOVE B,[SETZ 1] ;WAIT FOR OUTPUT IOT + MOVEM B,SRN3(U) + HRLZ T,A ;JOB INDEX + HRR T,JBCUI(A) ;CREATOR'S USER INDEX + PUSHJ P,CWAIT ;WAIT FOR CREATOR TO IOT, RETURN WITH CLKOFF + PUSHJ P,BJWAIT + PUSHJ P,BJUI1 + JRST CLKONJ + +BJUI1: MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJUIB ;BLOCK MODE CREATOR IOT + LDB D,[.BP (%JBSIOT),JBWST(A)] + JUMPN D,BJUIS + MOVE W,AC0S+W(T) + JRST BJIUNH ;SUCCESSFUL + +;BOJ UNIT INPUT FROM JOB SIOT +BJUIS: PUSHJ P,BJBINI + XCTRI XBYTE,[ILDB W,(B)] + SKIPA C,AC0S+C(T) + BUG + XCTR XRW,[SOSG (C)] + JRST BJIUNP + JRST PLDZ + +;BOJ UNIT INPUT FROM JOB BLOCK IOT +BJUIB: PUSHJ P,BJBINI + SKIPL JBSTS(A) + JRST BJUIBA + XCTRI XR,[MOVE W,(D)] + CAIA + BUG + ADD D,[1,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + JUMPGE D,BJIUNP + JRST PLDZ + +;BOJ UNIT INPUT FROM JOB BLOCK IOT, ASCII MODE +BJUIBA: LDB E,[410300,,D] ;CHAR COUNT + MOVEI W,0 + CAIGE E,3 + JRST BJIUNP + XCTRI XR,[MOVE W,(B)] + SKIPA E,BTOCHT-3(E) + BUG + ILDB W,E + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + TLNN D,700000 + JRST BJIUNP + JRST PLDZ + +;BOJ DEVICE BLOCK MODE INPUT +BJBI: SKIPGE JBCG(A) + POPJ P, ;EOF + XCTR XRW,[MOVES D,(C)] ;D GETS IOT POINTER + LDB B,[410300,,D] + CAIGE B,3 + POPJ P, + HLRO E,D + IORI E,700000 ;FLUSH CHAR CNT + HRRZ T,D + SUB T,E + CAILE T,-1 + JRST IOADC ;DON'T WRAP AROUND + MOVE B,[SETZ 1] + PUSHJ P,BJBWT ;WAIT FOR JOB OUTPUT IOT, COME BACK WITH CLK OFF + JRST CLKONJ ;UNHANG + MOVEI I,0 ;FOR BJBB + MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJBB ;CREATOR IOT IS IN BLOCK MODE + PUSH P,C + PUSH P,D + PUSHJ P,BJUI1 ;GET DATA OUT OF CREATOR UNIT MODE IOT + POP P,D + POP P,C + MOVE H,W + MOVEI T,BJBI + JUMPGE TT,BJBIA ;ASCII + XCTRI XW,[MOVEM H,(D)] + CAIA + BUG + ADD D,[1,,1] + JRST BJBIX + +;BOJ BLOCK ASCII INPUT STORE CHAR +BJBIA: LDB E,[410300,,D] + CAIGE E,3 + JRST CLKONJ + XCTRI XR,[MOVE W,(D)] + SKIPA E,BTOCHT-3(E) + BUG + IDPB H,E + XCTRI XW,[MOVEM W,(D)] + CAIA + BUG + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] +BJBIX: MOVEI T,BJBI + XCTRI XW,[MOVEM D,(C)] + JRST BJBEX + BUG + +BJOV: BJBI + BJBO + +;BOJ BLOCK IOT TO/FROM JOB BLOCK IOT +BJBB: MOVE J,T + HRLI J,%UMALL ;UMAPS FOR PURELY CREATOR IOT + MOVEM J,SRN4(U) +BJBBL: MOVE J,SRN4(U) + PUSHJ P,PLD1 + MOVE E,SRN3(T) + XCTRI XRW,[MOVES H,(E)] + CAIA ;H HAS JOB BLOCK IOT POINTER + BUG + PUSHJ P,PLDZ + XCTRI XRW,[MOVES D,(C)] + CAIA ;D HAS BOJ BLOCK IOT POINTER + BUG + JUMPGE H,[PUSHJ P,BJIUNH + MOVE T,BJOV(I) + JRST BJBEX] + JUMPGE D,CLKONJ + HLRE B,H + CAML D,H + HLRE B,D ;CHOOSE SMALLER OF TWO BLOCK SIZES + MOVNS B ;COUNT TO BE XFERRED + HRLZ E,H ;JOB ADDRESS + HRR E,D ;JOB,,BOJ (FROM,,TO FOR BOJ INPUT) + HLRZ Q,E ;JOB ADDRESS + CAIGE Q,20 + JRST BJBB1 ;JOB ADDR IS AN AC + HRRZ J,T ;SET UP UMAPS (JOB USER INDEX IN RH) + TRZE E,400000 + TLOA J,%UMMPL ;TO HI PG, HACK OUR LO PAGE + TLO J,%UMMPU ;TO LO PG, HACK OUR HI PAGE + TLZE E,400000 + TLOA J,%UMLTU ;TO POINT TO HIS UPPER + TLO J,%UMUTL ;TO POINT TO HIS LOWER + TLNN J,%UMMPU+%UMUTL ;MAPPING HIS UPPER FROM OUR LOWER? + JRST BJBB3 ;YES. MAKE SURE NOT SCREWED BY AC PNTR +BJBB3A: PUSHJ P,PLD1 + TRZ Q,400000 + MOVNS Q ;LIMIT SIZE OF XFER TO MIN OF + ADDI Q,400000 ;DIST OF TO ADR FROM SEG BOUNDARY + CAMLE B,Q ;AND DIST OF FROM ADR FROM SEG BOUNDARY + HRRZ B,Q + MOVNI Q,(E) ; - BOJ ADDR + ADDI Q,400000 + CAMLE B,Q + HRRZ B,Q + TLNN J,%UMMPL ;BUGGER ADDRESSES SO RIGHT DBRS WILL BE USED + TLOA E,400000 ;SET JOB ADDR TO HI SEG + TRO E,400000 ;SET BOJ ADDR TO HI SEG + SKIPE I + MOVSS E ;XFER OTHER DIRECTION + MOVE Q,E ;SAVE COPY OF BLT POINTER + ADDI B,(E) ;GET LA + 1 + XCTRI XBRW,[BLT E,-1(B)] ;XFER DATA + HRRZS E,B ;NO FAULT. SIMULATE STORE BACK OF POINTER (CAN BE 1,,0) + PUSH P,J + PUSHJ P,PLDZ + SUBM E,Q +BJBB2: HRLS Q ;NUMBER OF WORDS ACTUALLY XFERRED IN BOTH HALVES + XCTRI XRW,[ADDM Q,(C)] ;UPDATE BOJ BLK PNTR + JRST .+2 + BUG + MOVE J,SRN4(U) + PUSHJ P,PLD1 ;MAP TO CREATOR + POP P,J + MOVE W,SRN3(T) + XCTRI XRW,[ADDM Q,(W)] ;UPDATE JOB BLK PNTR + JRST .+2 + BUG + CAIN B,(E) + JRST BJBBL ;NO FAULT, LOOP BACK + PUSHJ P,PLD1 ;RESTORE TO FROB AT TIME OF FAULT +BJBBF: PUSHJ P,TPFLT ;TAKE FAULT (TURNS CLK ON) + PUSHJ P,MPLDZ ;RESTORE NORMAL MAP + JRST @BJOV(I) ;RESTART THE IOT + +;JOB ADDR IS AN AC +BJBB1: ADDI Q,UUOACS(T) + JUMPN I,BJBB1A + MOVE B,(Q) ;READ JOB WORD +BJBB3C: XCTRI XW,[MOVEM B,(E)] + JRST .+2 + JRST BJBBF +BJBB2A: MOVEI Q,1 ;1 WORD XFERRED + HRRZ B,E ;FAKE OUT FAULT TEST + PUSH P,J + JRST BJBB2 + +BJBB1A: XCTRI XR,[MOVE B,(E)] + JRST .+2 + JRST BJBBF + MOVEM B,(Q) + JRST BJBB2A + +BJBB3: TLNE E,777760 ;SKIP ON XFERRING FROM AC AREA, HI TO HI + JRST BJBB3A ;NO. OK TO DO BLT + JUMPN I,BJBB3B + HRLI J,%UMALL ;HACK OUR HI TO POINT TO HIS HI + PUSHJ P,PLD1 + XCTRI XR,[MOVE B,(Q)] + JRST .+2 + BUG + PUSHJ P,PLDZ + HRRZ E,D ;TO ADDRESS + JRST BJBB3C + +BJBB3B: XCTRI XR,[MOVE B,(D)] + JRST .+2 + JRST BJBBF + HRLI J,%UMALL + PUSHJ P,PLD1 ;HACK OUR HI TO POINT TO HIS HI + XCTRI XW,[MOVEM B,(Q)] + JRST .+2 + BUG + PUSHJ P,PLDZ + JRST BJBB2A + +;.CALL JOBGET +;ARG 1 - BOJ CHNL +;UP TO SIX WDS RETURNED +;WD1 BITS: +%JG==1,,525252 + ;4.9-4.7 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT + ; 4.9-4.7 SHOULDN'T BE USED, SINCE THE FULL MODE IS IN WD7 ON AN OPEN +%JGCLS==40000 ;4.6 => CLOSE (NOTE 4.5 USED TO BE A CLS BIT ALSO) +%JGSIO==1000 ;4.1 => SIOT (ONLY IF OPCODE = 1) +%JGFPD==200 ;3.8 => THIS CALL WAS PCLSRED AND IS RESTARTING +;1.4-1.1 => TYPE OF OPERATION +%JO==,,-1 +%JOOPN==0 ;OPEN +%JOIOT==1 ;IOT/SIOT +%JOLNK==2 ;MLINK +%JORST==3 ;RESET +%JORCH==4 ;RCHST +%JOACC==5 ;ACCESS +%JORNM==6 ;FDELE (DELETE OR RENAME) +%JORWO==7 ;FDELE (RENAME WHILE OPEN) +%JOCAL==10 ;SYMBOLIC .CALL + +;WD2 SET ONLY FOR BLOCK IOT POINTER, ACCESS POINTER, NEW FN1 FOR FDELE +;WD3 FN1 +;WD4 FN2 +;WD5 SYS NAME +;WD6 LEFT ADJUSTED DEVICE NAME +;WD7 NEW FN2 FOR FDELE. +;IGNORE ALL RETURNED INFO ON AN ERROR RETURN +;IF 4.5 OR 4.6 IS SET THEN ALL ELSE IS MEANINGLESS + +NJBGT: SETZM T ;INDICATE JOBGET, NOT JOBCAL +NJBCL0: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD + TLNN R,%CLSBJ ;NOT A BOJ CHANNEL => WRONG TYPE DEVICE + JRST OPNL34 + CONO PI,CLKOFF + MOVE C,JBWST(E) + TLNN C,%JBVAL + JRST NJBGTE ;FAIL IF VALID NOT SET + TLZ C,%JBSTR + MOVEM C,JBWST(E) ;CLEAR STORED BIT + MOVE B,JBCUI(E) + MOVE B,SUUOH(B) + CONO PI,CLKON + MOVE A,JBSTS(E) + TLZ A,077777 ;FLUSH RANDOM BITS FROM LH + TLNE B,%PCFPD + TLO A,%JGFPD + TLNE C,%JBSIOT + TLO A,%JGSIO + JUMPN T,NJBCL1 ;BRANCH IF JOBCAL +NJBGT0: MOVE B,JBST2(E) + MOVE C,JBOFN1(E) + MOVE D,JBOFN2(E) + MOVE TT,JBODEV(E) + MOVE I,JBNFN2(E) + MOVE E,JBOSYN(E) + CONO PI,CLKON + JRST POPJ1 + +NJBGTE: SKIPL JBCG(E) ;HAS CREATOR GONE AWAY? + JRST OPNL36 ;NO, VALID CLEAR + CONO PI,CLKON ;YES, GIVE CLOSE + MOVSI A,%JBLOS + IORM A,JBWST(E) + MOVSI A,%JGCLS ;GIVE CLOSE BITS + JRST POPJ1 ;DON'T GIVE ANYTHING ELSE WHETHER JOBGET OR JOBCAL + +; .CALL ADR +; ERROR RETURN +; NORMAL RETURN + +;ADR: SETZ +; SIXBIT /JOBCAL/ +; [BOJCHNL] +; [-N,,ADR OF DATA BUFFER] ;OPTIONAL +; SETZM OPCODE +; OPCODE WILL BE THE SAME AS RETURNED IN WD1 BY JOBGET +; IF OPCODE<10 THEN WD2-WD7 OF JOBGET WILL BE WRITTEN INTO DATA BUFFER +; FOLLOWED BY JOB'S EPDL AND EPDL3 (THE BPS FOR BP-STYLE OPENS, ETC). +;IF OPCODE=10 THEN JOB'S LAST .CALL WILL BE DESCRIBED: +; WORD 1 OF DATA BUFFER => SIXBIT OF OPERATION (I.E. THE NAME +; OF THE .CALL) +; WORD 2 OF DATA BUFFER => FLAG BITS OF .CALL +; WORD 3 OF DATA BUFFER => # OF ARGS TO .CALL +; WORDS 4-12 => INPUT ARGS TO .CALL + +NJBCL: CAIL W,2 ;DID CALLER SUPPLY AOBJN POINTER? + SKIPN T,B ;IF SO AND NON-ZERO USE IT + MOVEI T,1 ;OTHERWISE SET T NONZERO + JRST NJBCL0 ;GO JOIN JOBGET CODE FOR ERROR CHECKING + +NJBCL1: JUMPGE T,POPJ1 ;BACK FROM JOBGET - ANY AOBJN PNTR? + MOVEI C,9 ;YES - OPCODE 10? + TRNN A,10 + JRST NJBCL2 ;NO - JUST COPY 9 STANDARD ARGS + HLRE D,T ;GET LENGTH OF USERS DATA BUFFER + MOVE B,JBCUI(E) ;GET JOB'S USER INDEX + MOVE C,LSCALL(B) ;GET NAME OF JOB'S LAST CALL + UMOVEM C,(T) ;PUT INTO CALLERS BUFFER + AOJE D,POPJ1 ;IF NO MORE ROOM - DONE + MOVE C,CTLBTS(B) ;GET USER'S .CALL FLAG BITS + UMOVEM C,1(T) + AOJE D,POPJ1 + LDB C,[230400,,JBSTS(E)] ;GET # OF ARGS + UMOVEM C,2(T) + JUMPE C,POPJ1 ;ANY ARGS TO PASS? + ADD T,[3,,3] ;YES - COPY INTO BUFFER +NJBCL2: JUMPGE T,POPJ1 ;ANY ROOM LEFT? + MOVNS C ;GET SMALLEST WORD COUNT + HLRE B,T + CAMLE C,B + HRL T,C ;MAKE AOBJN PNTR AS SMALL AS POSSIBLE + MOVE H,E ;JOB INDEX IN H FOR USING JBACTB + MOVEI B,JBACTB ;GET PNTR TO ARG TABLES +NJBCL3: MOVE C,@(B) ;GET NEXT ARG + UMOVEM C,(T) ;GIVE TO CALLER + AOS B + AOBJN T,NJBCL3 + JRST POPJ1 ;DONE - GO SKIP + +; .CALL ADR +; ERROR RETURN +; NORMAL RETURN + +;ADR: SETZ +; SIXBIT /JOBRET/ +; [BOJCHNL] +; [OPEN LOSS #(IF RH = 0),,# TIMES FOR CREATING JOB TO SKIP] +; SETZ [-N,,ADR OF DATA BUFFER] + +;RETURN DATA (E.G. RETURN TO RCHST,STATUS OR THE RETURN ARGS TO A .CALL) +;WILL BE COPIED FROM THE CALLER'S DATA BUFFER + +NJBRT: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD + TLNN R,%CLSBJ ;NOT BOJ CHNL => WRONG TYPE DEVICE. + JRST OPNL34 + CAIGE W,3 ;RETURN ARGS PROVIDED? + SETZM C ;NO - ZERO IT + JUMPGE C,NJBRT1 ;DO NOTHING IF NO RETURNS OR NO AOBJN + HLRE D,C ;GET LENGTH OF BUFFER + CAMGE D,[-8.] ;MAKE SURE AREA AT MOST 8 LONG + MOVNI D,8 ;OVER 8 - USE 8 + HRL C,D ;FIX AOBJN PNTR + MOVMS D + ADDI D,-1(C) ;GET ADDRESS OF LAST WORD NEEDED + XCTR XR,[SKIP (C)] ;MAKE SURE PAGES ARE IN + XCTR XR,[SKIP (D)] +NJBRT1: CONO PI,CLKOFF ;NOW OK TO TURN CLOCK OFF + MOVE A,JBWST(E) + TLNE A,%JBVAL + TLNE A,%JBSTR + JRST OPNL36 ;FAIL IF STORED IS SET OR IF VALID IS CLEARED + SKIPGE JBCG(E) + JRST OPNL41 + HRRZ TT,JBCUI(E) + MOVE D,FLSINS(TT) + CAME D,JBFLS + BUG + TLO A,%JBWIN + TLZ A,%JBVAL+%JBSTR + MOVEM A,JBWST(E) ;SET SUCCESSFUL JOBRET BIT, CLEAR VALID AND STORED + DPB B,[350400,,JBSTS(E)] ;NUMBER OF TIMES TO SKIP + MOVSS B + DPB B,[270600,,JBSTS(E)] ;OPEN LOSS + MOVSI B,-6 ;DEFAULT # WDS TO RETURN FOR .RCHST IS 6. + MOVEM B,JBAC11(E) + JUMPGE C,NJBRT3 ;ANY RETURN ARGS? + MOVEM C,JBAC11(E) ;REMEMBER HOW MANY, FOR .RCHST TO RETURN THAT MANY. + MOVE H,E ;YES - COPY THEM + MOVEI D,JBACTB +NJBRT2: XCTRI XR,[MOVE B,(C)] ;GET IT + AOSA D + BUG ;PAGE IS TIED - NO? + MOVEM B,@-1(D) ;PUT INTO ARG TABLE + AOBJN C,NJBRT2 +NJBRT3: SETZM FLSINS(TT) ;RESTART CREATOR + JRST CLKOJ1 + +;JOB DEVICE CLOSE ROUTINE +JOBCLS: SETOM JBCG(A) + MOVE E,A + CONO PI,CLKOFF + PUSHJ P,JBINT ;INTERRUPT POOR BOJ GUY + JRST CLKONJ ;SINCE HE HAS NO CREATOR + +; ROUTINES FOR JOB ACCESS, RFPNTR, RESET, AND STATUS + +RFPJOB: MOVEI J,4 ;USE OLD .RCHST OPERATION, OPCODE 4 + HRRM J,JBSTS(A) + MOVE E,A + CONO PI,CLKOFF + PUSHJ P,JBWT ;SIGNAL JOB, WAIT FOR ANSWER + HLRE TT,JBAC11(E) ;GET # VALUES RETURNED + MOVNS TT + CAIL TT,5 + SKIPA A,JBODEV(E) ;GET ACCESS POINTER RETURNED + SETO A, ;NO ACCESS POINTER RETURNED, USE -1 + CAIL TT,6 ;UP TO TWO MORE EXTRA RCHST RESULTS MIGHT BE RETURNED + MOVE Q,JBNFN2(E) + CAIL TT,7 + MOVE I,JBAC7(E) + CAIL TT,5 + MOVEI W,1(TT) ;# RESULTS FOR RCHST + MOVEI B,36. ;ALWAYS RETURN 36. AS BYTE SIZE UNTIL MORE WINNING + JRST POPJ1 ;CONVENTIONS EXIST. + +JBSTAT: HLRZ A,(R) ;GET JOB INDEX + HRRZ D,JBWST(A) ;GET MOST RECENT STATUS + POPJ P, + +JBORS: +JBIRS: MOVEI D,3 ;RESET IS OPCODE 3 + HLRZ A,(R) + HRRM D,JBSTS(A) + CONO PI,CLKOFF + MOVE E,A + PUSHJ P,JBWT ;WAIT FOR IT TO GET PROCESSED + POPJ P, + +JBACCS: MOVEI D,5 ;ACCESS IS OPCODE 5 + HLRZ A,(R) + HRRM D,JBSTS(A) + MOVEM B,JBST2(A) + CONO PI,CLKOFF + MOVE E,A + PUSHJ P,JBWT + JRST POPJ1 + +;.CALL JOBIOC (OLD NAME SETIOC STILL WORKS) +;ARG1: CHANNEL BOJ DEVICE IS OPEN ON +;ARG2: TYPE OF IOCER TO CAUSE + +;THIS CALL CAUSES THE NEXT IOT EXECUTED BY THE +;PROCEDURE ON THE OTHER END OF THE CHANNEL TO GET +;THE SPECIFIED IO CHANNEL ERROR + +NSTIOC: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD. + CAIL B,MIOTER + CAILE B,NIOTER + JRST OPNL33 ;BAD ARG. (NOT LEGAL IOCER) + TLO B,(SETZ) ;IN CASE IOCER 0 EVER EXISTS + TLNN R,%CLSBJ + JRST OPNL34 ;NOT BOJ CHANNEL + CONO PI,CLKOFF + MOVE A,JBCUI(E) ;PREPARE TO STOP CREATOR. + SKIPGE JBCG(E) + JRST OPNL41 ;CREATOR WENT AWAY + MOVE H,APRC(A) + TLNE H,BULGOS + JRST OPNL41 ;HE'S BEING KILLED NOW. + PUSHJ P,RPCLSR ;STOP + MOVEM B,JBIOCJ(E) + AOS (P) + JRST UPCLSR + + +;.CALL JOBSTS +;ARG1 - CHANNEL BOJ IS OPEN ON - REMAINING ARGS ARE OPTIONAL - +;ARG2 - NEW STATUS (RIGHT HALF OF STATUS WORD ONLY - I.E. DEVICE DEPENDENT STUFF) +;ARG3 - NEW DEVICE NAME FOR PEEK, WHO-LINE STATUS, RFNAME/RCHST +;ARG4 - NEW FN1 FOR .. +;ARG5 - NEW FN2 FOR .. +;ARG6 - NEW SNAME FOR .. +;ARG7 - NEW OPEN MODE FOR .. +;ARG8 - BP TO ASCIZ STRING IN USER ADDRESS SPACE CONTAINING FULL FILENAMES. + +NJBSTS: TLNN R,%CLSBJ + JRST OPNL34 + HLRZ A,(R) ;GET JOB INDEX + CAIGE W,2 ;DID HE SUPPLY STATUS? + MOVEI B,SNJOB ;NO - RESET TO INITIAL + HRRM B,JBWST(A) ;REMEMBER WHAT HE SAYS + MOVEI B,8 + SUB B,W + JUMPGE B,.+1(B) ;STORE WHATEVER ADDITIONAL ARGS WERE GIVEN + JSP B,NJBST2 ;8 + JSP B,NJBST1 ;7 + MOVEM TT,JBSYS(A) ;6 + MOVEM E,JBFN2(A) ;5 + MOVEM D,JBFN1(A) ;4 + MOVEM C,JBDEV(A) ;3 + JRST POPJ1 ;2 + JRST POPJ1 ;1 (DON'T TAKE THIS INSN OUT) + +NJBST1: XOR I,JBOPNM(A) + TRNE I,.BAO#.UAI + JRST OPNL12 ;NOT ALLOWED TO CHANGE BLOCK VS UNIT, IN VS OUT + XORM I,JBOPNM(A) + JRST (B) + +NJBST2: MOVE R,Q ;STORE BP IN Q INTO JBFNP WORD, + PUSHJ P,ASCIND ;AFTER DOING INDEXING AND INDIRECT. + MOVEM R,JBFNP(A) + JRST (B) + +; .CALL ADR ;SKIPS UNLESS JOB END OF CHNL NOT THERE + +;ADR: SETZ +; SIXBIT /JOBINT/ +; 401000,,BOJCH + +;GIVE CREATOR A SECOND WORD INT ON CHANNEL CORRESP TO BOJCH + +NJBINT: TLNN R,%CLSBJ ;ERROR IF NOT BOJ CHNL. + JRST OPNL34 + CONO PI,CLKOFF + HLRZ E,H + SKIPGE JBCG(E) + JRST OPNL41 + MOVE A,JBCUI(E) + MOVSI D,%CLSJ + SETZ C, + PUSHJ P,CHSCAA + PUSHJ P,[HRRZ B,(R) + SKIPGE R ;IOPDL CHNLS DON'T INTERRUPT + TDNN D,CLSTB(B) + POPJ P, + HRRZ B,R + SUBI B,IOCHNM(A) + IOR C,CHNBIT(B) + POPJ P,] + AND C,MSKST2(A) + JUMPE C,OPNL41 ;I CAN'T + MOVN B,C + AND C,B ;INT ONLY ONCE, ON HIGHEST NUMBERED CHANNEL + IORM C,IFPIR(A) + JRST CLKOJ1 + + +;.CALL JOBREU +;ARG 1 - SIMULATED DEVICE NAME +;ARG 2 - FN1 OF .. +;ARG 3 - FN2 OF .. +;ARG 4 - SNAME OF FILE WHICH HANDLER LOADED FROM +;ARG 5 - AMOUNT OF TIME TO SLEEP WAITING FOR SOMEONE TO OPEN + +;THIS CALL, WHEN EXECUTED BY A JOB DEVICE HANDLER JOB, MAKES +;THE HANDLER AVAILABLE FOR RE-USE. TAKES SUCCESS RETURN IF +;SOMEONE REUSES YOU; YOU SHOULD THEN DO THE "INITIAL JOBGET" + +NJBREU: SKIPGE H,JBI(U) + JRST OPNL10 ;NOT A BOJ HANDLER JOB + SKIPL JBCG(H) + PUSHJ P,UFLS ;WAIT FOR CLOSE TO FINISH HAPPENING + MOVEM A,JBODEV(H) + MOVEM B,JBOFN1(H) + MOVEM C,JBOFN2(H) + MOVEM D,JBOSYN(H) + TLNE E,1000 + JRST [ MOVNI E,(E) ;IMMEDIATE TIME, LOSE ON PCLSR + SUB E,TIME ;BUT ACCEPT ANYWAY SINCE NETBLK DOES + JRST NJBRU1 ] + MOVE TT,E + UMOVE E,(TT) ;GET TIME ARGUMENT + JUMPL E,NJBRU1 + MOVNS E + SUB E,TIME + UMOVEM E,(TT) ;POS REL TIME GIVEN, MAKE NEG ABS AND WRITE BACK +NJBRU1: MOVSI TT,%JBREU ;E NOW HAS NEGATIVE TIME TO SLEEP UNTIL + IORM TT,JBWST(H) + PUSHJ P,LOSSET + NJBRUL ;TURN OFF %JBREU WHEN CALL EXITED FOR WHATEVER REASON + SKIPA T,H + PUSHJ P,NJBRUW + PUSHJ P,UFLS + SKIPGE JBCG(H) + JRST OPNL41 ;TIMED OUT + JRST LSWPJ1 + +;FLSINS ROUTINE TO WAIT UNTIL TIMED OUT OR OPENED BY SOMEONE +NJBRUW: MOVN A,AC0S+E(U) + CAML A,TIME + SKIPL JBCG(T) + AOS (P) + POPJ P, + +;LOSSET ROUTINE TO LEAVE AWAITING-REUSE STATE +NJBRUL: MOVSI A,%JBREU + MOVE T,AC0S+H(U) + ANDCAM A,JBWST(T) + POPJ P, + +SUBTTL PERIPHERAL DEVICE ROUTINES IN SEPARATE FILES + +IFN NMTCS,[ + IFN TM10P,[ +$INSRT MTAPE + ] + IFN TM03S,[ +$INSRT NMTAPE +] +] +IFN NUNITS,[ +$INSRT UTAPE +] + +$INSRT DISK + +IFN NETP,[ ; General ITS network code, includes specific nets +OVHMTR NET +$INSRT NET +] + +IFN E.SP,[ +$INSRT ITSDIS +] + +IFN MSPP,[ +$INSRT ITSMSP +] + +$INSRT TS3TTY + +$INSRT ITSDEV + +.BYTE 0 ;RECORD THE SYMS .EVAL'ED BY USER PROGRAMS +$INSRT EVSYMS +.BYTE + +SUBTTL DM DAEMON UUO'S + +IFE DEMON,ADEMON==ILUUO + +IFN DEMON,[ +ADEMON: JUMPE J,[AOJA J,.+2] ;IF J = 0 THEN SUBTRACT ONE + UMOVE J,(J) ;GET VALUE HERE + PUSHJ P,LSWTL + 400000,,DEMSW + PUSHJ P,DEMUSR ;FIND CURRENT USER IN DEMON TABLE + JRST UTOLKJ ;FAIL, JUST RETURN, NOT DEMON + HRRE TT,DMTTBL+2(B) + SUB TT,J + HRRM TT,DMTTBL+2(B) ;PUT NEW COUNT IN DEMON TABLE + SKIPLE TT +UTOLJ1: AOS (P) +UTOLKJ: CONO PI,UTCON + JRST LSWPOP + +ADEMSIG:MOVE D,B + CONO PI,CLKOFF ;DON'T LET SYS JOB LOOK TILL WE'RE READY. + MOVSI T,SCLDMN ;TELL IT TO LOOK FOR US, AFTER UFLS TURNS CLOCK ON. + IORM T,SUPCOR + SETZB T,SRN3(U) ;SYS JOB WILL SETOM SRN3 TO RESTART US + SKIPN SRN3(U) ;WITH 0 IN T => FILE EXISTS, OR OPNL CODE. + PUSHJ P,UFLS ;SYS JOB DETECTS US BY PC=ADEMS1. + ;DEMON NAME IS EXPECTED TO BE IN A. +ADEMS1: JUMPN T,OPNL1-1(T) + CAIGE W,2 ;NO SECOND ARG, JST SIGNAL + JRST ADEMS3 + JUMPL D,NUDMTB ;IF 2ND ARG < MERELY CALL NUJBST, NO DEMON ENTRY + TDZA TT,TT ;ZERO OUT TT +ADEMS3: SETOM TT ;SET FLAG + PUSHJ P,LSWTL ;SIEZE SWITCH + DEMSW + PUSHJ P,DEMSIG + JRST LSWPOP ;SIGNAL FAILED + SKIPN TT ;FLAG NOT SET + HRLM D,DMTTBL +2(B) ;SET TIME RQ + JRST CKOPJ1 ;RELEASE SWITCH + +NUDMTB: PCLT + PUSHJ P,DMBLK1 ;WAIT TILL DEMON BLOCK IS CLEARED + PUSHJ P,UFLS + HRROI T,DMBLK + MOVEM A,DMBLK ;SAVE IN BLOCK NOW + PUSHJ P,NUJBST + JRST NUDMTB ;IF FAILURE AFTER WAIT LOOP BACK + JRST POPJ1 ;SUCCESS + +DMBLK1: SKIPGE DMBLK+1 ;FOR DEMON BLOCK TEST + POPJ P, ;RETURN, NOT FINISHED LOADING + MOVE T,UTTYCT + CAIGE T,MXCZS ;ROOM IN RING BUFFER + AOS (P) + POPJ P, ;SKIP IF ROOM + ;UTILITY ROUTINES FOR DEAMONS + +DEMSIG: PUSHJ P,DEMNAM ;LOOK FOR NAME + JRST DEMSG2 ;HAVE TO MAKE NEW ENTRY +DEMSG1: AOS (P) + HLLZ E,DMTTBL+2(B) ;18 BITS 2'S COMPLEMENT + AOS DMTTBL+2(B) + HLLM E,DMTTBL+2(B) ;MUST DO THIS WAY TO FIT ABOVE + SKIPE DMTTBL+1(B) ;DOWN, WANT SYS JOB TO LOOK AT + POPJ P, + MOVSI E,SCLDMN + IORM E,SUPCOR + AOS REQCNT ;ONLY SIGNAL IF NECESSARY + POPJ P, + +DEMSG2: SOSGE DEMCNT ;IF NO ROOM FLUSH + POPJ P, + PUSH P,A + MOVEI A,DMTLL ;BUMP POINTER + ADDB A,DMTPTR + IDIVI A,DMLNG ;TRUNCATE TO LENGNTH OF TABLE + SKIPE DMTTBL(B) + JRST .-4 ;SEARCH FOR NEW ENTRY + POP P,DMTTBL(B) ;SET NAME IN TABLE + JRST DEMSG1 + +;ROUTINES TO FIND ENTRY IN TABLE. +;DEMNAM TAKES NAME IN A, DEMUSR TAKES USER INDEX IN U +;THEY SKIP RETURN IF SUCCESSFUL, RETURN OTHERWISE +;IF SUCCESSFUL DEMON TABLE INDEX IS IN B + +DEMUSR: JUMPL U,CPOPJ + MOVSI B,-DMLNG + CAMN U,DMTTBL+1(B) + JRST POPJ1 + ADD B,[DMTLL,,DMTLL] + JUMPL B,.-3 + POPJ P, + +DEMNAM: MOVSI B,-DMLNG ;SEARCH BY NAME + CAMN A,DMTTBL(B) + JRST POPJ1 + ADD B,[DMTLL,,DMTLL] + JUMPL B,.-3 + POPJ P, + +DEMOUT: PUSHJ P,LSWTL ;CALLED BY KILLING JOB (IN CASE OWNED) + 400000,,DEMSW + PUSHJ P,DEMUSR + JRST UTOLKJ + SETZM DMTTBL+1(B) ;MARK AS DOWN,SYSTEM JOB DECIDES WHAT TO DO + AOS REQCNT + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST UTOLKJ + +DEMMRV: SETZM DMTTBL+2(B) ;CALL WITH UTCOFF (SYS JOB) REMOVES ENTRY FROM TBL + SETZM DMTTBL+3(B) ;WITH INDEX OF DEMON IN B + SETZM DMTTBL(B) + MOVEI B,1 + AOSGE DEMCNT + MOVEM B,DEMCNT + JRST UTCONJ + + +;DEAMON READ AND SET STATUS ROUTINES + +ARDDMST: PUSHJ P,LSWTL ;READ DEAMON STATUS + DEMSW + PUSHJ P,DEMNAM + JRST RDDMS1 ;LOST TRY USER INDEX + MOVE A,DMTTBL+1(B) + MOVEI C,L + IDIVM C,A ;DIVIDE BY L, DON'T CLOBBER B +RDDMS2: MOVE C,DMTTBL+3(B) + MOVE B,DMTTBL+2(B) + PUSHJ P,LSWPOP + JRST POPJ1 + +RDDMS1: PUSH P,U + MOVE U,A + PUSHJ P,DEMUSR ;BAD USER + JRST LKUPOP + POP P,U + MOVE A,DMTTBL(B) + JRST RDDMS2 +LKUPOP: POP P,U + JRST LSWPOP + +ASTDMST: PUSHJ P,LSWTL ;SET DEAMON STATUS + 400000,,DEMSW + MOVE D,B + PUSHJ P,DEMNAM + JRST STDMS1 +STDMS2: JUMPL D,STDMS4 +STDMS3: SOSLE W + MOVEM D,DMTTBL+2(B) + SOSLE W + MOVEM C,DMTTBL+3(B) + JRST UTOLJ1 +STDMS1: PUSH P,U + MOVE U,A + PUSHJ P,DEMUSR + JRST UTULKP + POP P,U + JUMPGE D,STDMS2 +STDMS4: SKIPGE DMTTBL+1(B) ;REMOVE FROM TABLE IF POSSIBLE + JRST UTOLKJ ;CAN'T DELETE, LOADING + SETZM DMTTBL+1(B) ;DOWN + SETZM DMTTBL+2(B) ;REMOVE REQUESTS + AOS REQCNT ;SIGNAL SYS JOB + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST UTOLJ1 +UTULKP: POP P,U + JRST UTOLKJ +] + + +SUBTTL .GETSYS UUO + +;.GETSYS AC, ;TRANSFERS SYSTEM AREA SPECIFIED BY C(AC+1) + ;TO USER AREA STARTING AT R.H. C(AC) OF LENGTH MINUS L.H. C(AC) + +AGETSYS: +; Alan 4/2/86: Took this out because people don't use .GETSYS this way +; anymore: +; PUSHJ P,UDELAY ;CAUSE A SCHEDULE TO STOP GETSYSER FROM +; ; MONOPOLIZING SYSTEM + MOVSI A,-LGSNAM ;NEGATIVE OF TABLE LENGTH + UMOVE B,1(J) ;LOOK AT USERS AC+1, THE 6BIT NAME + CAME B,GSNAME(A) ;CYCLE THROUGH TABLE + AOBJN A,.-1 ;OF NAMES, POINTER IN RIGHT HALF OF A + JUMPGE A,AGETSL ;JUMP IF NOT IN TABLE + UMOVE B,(J) ;GET POINTER TO USERS RECEPTACLE BLOCK +AGETS1: HLRZ C,GSYS1(A) ;GET LOW END OF BLOCK + HRRZS A ;CLEAR COUNT IN L.H. OF A + CAIGE A,NUTCFN ;SKIP IF UTC OFF NOT REQUIRD + CONO PI,UTCOFF ;TURN OFF ALL CHANNELS BUT CH 1 + skipn c ; If LH contains 0, RH is routine to call. + jrst @gsys1(a) ; (JUMPE C,@GSYS1(A) generates spurious + ; page faults, so don't "fix" this.) + HRRZ D,GSYS1(A) ;GET HIGH END OF BLOCK +;AT THIS POINT: ;B USER'S POINTER (UNRELOCATED) + ;C BEGINNING OF AREA IN SYS + ;D END OF AREA +agets2: SUBI D,-1(C) ;BLOCK LENGTH TO BE SENT + HLRZ E,B ;GET NEG BLK LENGTH FROM USERS PNTR + ADDI E,-1(D) ;-1 CAUSES CARRY BIT IF .GT. + TLNE E,-1 ;CARRY INDICATES LOSS + JRST AGETS5 ;MORE THAN USER WANTS + HRLS D ;BLOCK LENGTH IN BOTH HALVES + HRRZ E,B ;FIRST WORD (UNRELOCATED) + HRL E,C ;SOURCE ADDRESS FOR BLT + HRRZ C,E ;DESTINATION INTO C + ADD C,D ;FINAL ADDRESS +1 +AGETS7: XCTRI XBW,[BLT E,-1(C)] ;BLT IT TO HIM + AOSA (P) ;INCREMENT RETURN, INDICATE SUCCESS + JRST AGETS6 + CONO PI,UTCON + ADD B,D + UMOVEM B,(J) ;TELL USER HOW MUCH HE GOT +AGETS4: POPJ P, + +AGETSL: XCTR XW,[SETZM 1(J)] ;INDICATE BAD SIXBIT + POPJ P, + +AGETS5: MOVNS D ;TELL USER HOW MUCH HE NEEDS + CONO PI,UTCON ;NEGATIVE OF RIGHT BLOCK LENGTH + XCTR XRW,[HRLM D,(J)] ;SET UP PROPER BLOCK LENGTH IN HIS AC + JRST AGETS4 + +AGETS6: CONO PI,UTCON ;ONE PAGE WASN'T THERE + XCTR XRW,[MOVES (E)] ;SO TOUCH IT (TAKE MPV INTERRUPT IF REAL MPV) + JRST AGETS1 ;AND TRY AGAIN (BLT WILL GET FARTHER THIS TIME) + ;HAD TO RETRY FROM BEGINNING SINCE THIS MAY BE + ;ONE THAT HAS TO BE TRANSFERRED INTACT WITH UTCOFF + +GSNAME: SIXBIT /MEMORY/ +IFN NUNITS,SIXBIT /UTAPE/ +IFN NCPP,[SIXBIT /NCPSM/ + SIXBIT /NCPPQ/ + SIXBIT /NCPHT/ +] +NUTCFN==.-GSNAME ;NUMBER TO GET WITH UTCOFF (same as NETOFF) + SIXBIT /USERS/ + SIXBIT /USER/ + SIXBIT /GETS/ + SIXBIT /DEVS/ + SIXBIT /CALLS/ +IFN IMXP, SIXBIT /IMPX/ + SIXBIT /CLINK/ + SIXBIT /DSYMS/ + SIXBIT /USYMS/ ;.UPC, .VAL, .TTY, ETC. + SIXBIT /CHDEVS/ + SIXBIT /NCALLS/ + SIXBIT /TTYVAR/ + SIXBIT /USRVAR/ + SIXBIT /ITSNMS/ +LGSNAM==:.-GSNAME + +;ENTRIES ARE: BOTTOM,,TOP OF AREA TO BE TRANSMITTED OR INST TO EXECUTE +GSYS1: IOBFTL,,EMEMTL ;lh zero => jrst to THIS ENTRY +IFN NUNITS, UTCHNT,,UTCHE ;UTAPE +IFN NCPP,[IMSOKB,,IMSOKE ;NCP SOCKET MAP + IMPBPQ-1,,IMPEPQ ;NCP PENDING RFC QUEUE + IMPHTB,,IMPHTB+255. ;NCP HOST TABLE +] + 0,,USRSV ;USERS + 0,,USR1V ;USER + GSNAME,,GSNAME+LGSNAM-1 ;GETS + DEVTAB,,EDEVS ;DEVS + SYSYMB,,SYSYME ;CALLS +IFN IMXP, IMXTBB,,IMXTBE ;IMPX + CLVBEG,,CLVEND ;CLINK + 0,,DSYMS ;DSYMS + SYSUSB,,SYSUSE ;USYMS + DCHSTB,,DCHSTE ;CHDEVS + SYSCTB,,SYSCTB+LSYSCT-1 ;NCALLS + TYVTAB,,TYVTAB+LTYVTA-1 ;TTYVAR + USETTB,,USETTB+MXVAL-1 ;USRVAR + ITSNMS,,ITSNMS+LITSNM-1 ;ITSNMS +IFN LGSNAM-<.-GSYS1>, .ERR GSNAME and GSYS1 don't match. + +ITSNMS: ITSIRP [ + SIXBIT /ITS/ + ] +LITSNM==:.-ITSNMS + 0 + 0 ; Make it easy to add more. + +USRSV: MOVEI C,USRSTG + MOVE D,USRHI + ADDI D,USRSTG-1 + JRST agets2 + +USR1V: UMOVE C,2(J) + IMULI C,LUBLK + CAML C,USRHI + JRST USR1VL + ADDI C,USRSTG + MOVE D,C + ADDI D,LUBLK-1 + JRST agets2 + +USR1VL: XCTR XW,[SETOM 2(J)] + JRST AGETS4 + +DSYMS: HRRZ C,DDT-2 + HLRE D,DDT-2 + SETCMM D ;OFFSET BY ONE + ADD D,C + JRST agets2 + +SUBTTL .GETLOC, .EVAL, ETC. + +;GET AN ABSOLUTE LOCATION ;.GETLOC AC, ;C(A)=FROM(ABS),,TO(RELATIVE) +; +AGETLOC:UMOVE A,(J) ;GET TO ADDRESS + HLRZ B,A ;GET FROM ADDRESS + XCTRI [MOVE C,(B)] + JRST .+2 + JRST ILEXPF ;ILLEGAL EXEC PAGE FAULT + UMOVEM C,(A) ;GIVE TO USER + POPJ P, + +;SET AN ABSOLUTE LOCATION ;.SETLOC AC, ;C(AC)=FROM(RELATIVE),,TO(ABS) +; +ASETLOC:TDZA D,D ;CLEAR COND FLAG, SKIP + +;SET AN ABSOLUTE LOCATION ONLY IF C(ABS)=C(TEST) & SKIP IF SUCCESSFUL +;.IFSET AC, ;C(AC)=,,TO ADR(ABS) +;WORD 1=TEST ;WORD 2=NEW C(ABS) + +AIFSET: MOVNI D,1 ;SET COND FLAG + XCTR XR,[HRRZ A,(J)] ;GET TO ADDRESS (ABSOLUTE) + XCTR XR,[HLRZ B,(J)] + UMOVE C,(B) ;GET WORD + XCTRI [MOVES (A)] + JRST .+2 + JRST ILEXPF + JUMPE D,ASPST1 ;NORMAL SETLOC + UMOVE D,1(B) ;GET NEW VALUE + CONO PI,CLKOFF ;PREVENT INTERRUPTS + CAME C,(A) ;CHECK WORD AGAINST TEST WORD + JRST CLKONJ ;NOT EQUAL => IGNORE + MOVE C,D + AOS (P) ;CAUSE RETURN TO SKIP + CAIG A,SYSB_10. ;CHECK IF IN SYS + JRST ASPST1 ;YES SO DO REG SETLOC + EXCH D,(A) ;NO SO DO NOW BEFORE SHUFFLE & GET OLD +ASPST2: MOVE C,D + HRROS A ;LET SYS JOB KNOW ALREADY DONE +ASPST1: CAMN C,(A) ;SKIP IF DIFFERENT FROM C(TO ADR) + JRST CLKONJ ;SAME + MOVE D,SYSITM ;IF SYSTEM JOB HAS BEEN HUNG OR LOOPING FOR 30 SEC, + ADDI D,30.*30. + CAMGE D,TIME + JUMPGE A,ASPST3 ;GO DO THE WORK OURSELVES (BUT DON'T DO IT TWICE). +ASPST4: MOVE D,UNAME(U) ;GET UNAME OF SETLOCER + MOVSI T,SCLSET + PUSHJ P,CWAIT ;WAIT TILL VARIABLES TO COMMUNICATE WITH SYS JOB ARE FREE + TDNE T,SUPCOR ;ARG TO CALL IN .-1 + MOVEM A,SETSLC ;REMEMBER ABS LOCATION + MOVEM C,SETSLQ ; " NEW CONTENTS (OR OLD IF LH(SETSLC)=-1) + MOVEM D,SETSU ; " USER +CSPST: IORM T,SUPCOR ;TELL SYS JOB TO DO IT + JRST CLKONJ + +ASPST3: HRRZ D,UPC ;SYS JOB HAS BEEN HANGING FOR 30 SEC. + CAIN D,SCOR1 ;WHY? JUST SLEEPING? + JRST ASPST4 ;YES => SIGNAL IT TO DO THE WORK + MOVEM C,(A) ;ELSE GIVE UP ON IT AND DO IT NOW + JRST CLKONJ + +;LOOK UP ITS SYMBOL ;.EVAL AC, ;C(AC)=SQUOZE SYMBOL +;REPLACES SYMBOL BY VALUE & SKIPS IF SUCCESSFUL +;IF YOU WANT TO .EVAL A SYMBOL IN A PROGRAM HABITUALLY AND IMPLICITLY, +;AND WANT IT TO CONTINUE TO WORK, YOU HAD BETTER ADD AN ENTRY TO THE FILE +;AI:SYSTEM;EVSYMS > SAYING WHAT PROGRAM AND WHAT SYMBOL. THEN, ITS HACKERS +;CAN AVOID SCREWING YOU WITHOUT WARNING. + +AEVAL: PUSHJ P,SWTL + ARDFSW + UMOVE B,(J) ;GET SYM + PUSHJ P,SYMLK ;LOOK UP + JRST LSWPOP ;NOT FOUND + MOVE A,(C) ;GET VALUE + PUSHJ P,LSWPOP + AOS (P) ;CAUSE UUO TO SKIP + JRST APTUAJ ;RETURN VALUE + +;REDEFINE ITS SYMBOL ;.REDEF AC, ;C(AC)=POINTER TO 2 WORD BLOCK +;WORD 1 = SYMBOL ;WORD 2 = VALUE +;DELETE SYM IF ALL 4 FLAG BITS SET +; OTHERWISE SET SYMBOL FLAGS TO THOSE SPECIFIED, EXCEPT REJECT ANY ATTEMPT TO +; ADD A PROGRAM NAME +;ADD SYM IF NOT FOUND ;FAIL ONLY IF NOT ENOUGH ROOM +;SKIPS IF SUCCESSFUL + +AREDEF: PUSHJ P,SWTL + ARDFSW + XCTR XR,[HRRZ D,(J)] ;GET POINTER FROM AC + UMOVE B,(D) ;GET SYMBOL + PUSHJ P,SYMLK ;LOOK UP + JRST ARDF2 ;NOT FOUND, CREATE + XCTR XR,[SETCM A,(D)] ;GET SYM (COMPLEMENTED) + TLNN A,740000 ;SKIP IF ANY FLAGS NOT SET + JRST ARDF3 ;ALL SET => DELETE + SETCA A, + TLNN A,740000 + JRST LSWPOP + MOVEM A,-1(C) + UMOVE A,1(D) ;GET VALUE + MOVEM A,(C) ;STORE IN SYMTAB + JRST ARDF4 ;SORT AND SKIP-RETURN. + +ARDF2: MOVE C,DDT-2 ;GET POINTER + SUB C,[2,,2] ;DECREMENT FOR NEW ENTRY + MOVEI A,-1(C) ;FUDGE FOR BLOCK CALC + LSH A,-10. ;CONVERT TO # OF BLOCKS UP TO SYMTAB -1 + UMOVE B,(D) ;GET SYM + MOVE T,FDDTPG + LSH T,10. + TLNE B,740000 ;LOSE IF PROG NAME + CAMLE A,T ;CHECK FOR LOSSAGE + JRST LSWPOP ;DON'T OVERWRITE ITS + EXCH B,2(C) ;STORE OVER GLOBAL BLOCK HEADER, + MOVEM B,(C) ;MOVE THAT HEADER DOWN 2 WDS. + UMOVE A,1(D) ;GET VALUE + EXCH A,3(C) + ADD A,[-2,,] ;1 MORE SYM IN GLOBAL BLOCK. + MOVEM A,1(C) ;STORE + MOVEM C,DDT-2 ;UPDATE POINTER + JRST ARDF4 ;GO SORT AND SKIP-RETURN. + +ARDF3: MOVE B,DDT-2 ;GET POINTER + MOVE A,(B) ;MOVE THE GLOBAL HEADER + EXCH A,2(B) ;UP OVER 1ST SYM + MOVEM A,-1(C) ;WHICH GOES INTO FREE SLOT. + MOVE A,1(B) + ADD A,[2,,] ;GLOBAL BLOCK 1 SYM SHORTER. + EXCH A,3(B) + MOVEM A,(C) + MOVE A,[2,,2] + ADDM A,DDT-2 ;UPDATE POINTER +ARDF4: MOVSI E,(SETZ) ;TELL DDT ITS SYMTAB WAS ALTERED. + IORM E,DDT-1 + PUSHJ P,SBUBL ;DO 1 BUBBLE-SORT UP AND 1 DOWN. + JRST LSWPJ1 ;FREE ARDFSW AND EXIT. + +;DO ONE BUBBLE SORT PASS UP, ONE DOWN; LEAVE J <0 IFF DID AN EXCHANGE. +;CLOBBER A-E. +SBUBL: MOVE E,DDT-2 + HLL E,1(E) + ADD E,[2,,2] ;AOBJN -> SYMS IN GLOBAL BLOCK. +SBUBL0: SETZ J, + MOVE B,[2,,2] ;INCREMENT FOR UPWARD PASS. + MOVE C,[JUMPL A,SBUBL1] + SUBI E,2 ;(WILL INCREMENT BEFORE ACTING) + MOVE A,E + PUSHJ P,SBUBL2 + MOVNS B ;DECREMENT FOR DOWNWARD PASS. + MOVE C,[CAMN A,E] + JRST SBUBL2 + +SBUBL1: MOVE D,1(A) ;CHECK NEXT PAIR OF ENTRIES. + CAMG D,3(A) + JRST SBUBL2 ;IN CORRECT ORDER. + EXCH D,3(A) + MOVEM D,1(A) ;WRONG ORDER, EXCHANGE. + MOVE D,(A) + EXCH D,2(A) + MOVEM D,(A) + SETO J, ;SAY DID AN EXCHANGE. +SBUBL2: ADD A,B ;MOVE TO NEXT ENTRY. + XCT C ;TEST IF FINISHED. + POPJ P, + JRST SBUBL1 ;(NOT FINISHED) + +;LOOK UP SYMBOL IN B IN ITS SYMBOL TABLE (CLOBBERS A,B,C) +;RETURN WITH POINTER TO VALUE WORD IN C +;SKIPS IF SUCCESSFUL + +SYMLK: TLZ B,740000 ;FLUSH FLAGS + MOVE C,774000-2 ;PICK UP AOBJN POINTER TO SYMTAB FROM EXEC DDT +SYMLK2: MOVE A,(C) ;GET SYM + AOBJP C,[JRST 4,.+1] ;INCREMENT POINTER + TLNE C,376 ;GO THROUGH HAIR EVERY 200 SYMS + JRST SYMLK3 ;NOT THIS TIME + PUSHJ P,OPBRK +SYMLK3: TLNN A,200000 ;SKIP IF DELETE INPUT (FLAG PREVENTS MATCH) + TLZE A,740000 ;FLUSH FLAGS & CAUSE LOSS IF ALL 0 (PROG NAME) + CAME A,B ;COMPARE + AOBJN C,SYMLK2 ;LOSS, TRY ANOTHER + JUMPL C,POPJ1 ;SKIP RETURN IF FOUND + POPJ P, ;NOT SO IF LOSS + +AWSNAME:XCTR XR,[SKIPE B,(J)] ;OPER 35 + MOVEM B,USYSNM(U) + POPJ P, + +AUPISET:UMOVE B,(J) ;OPER 36 + ASH B,-35. + EXCH B,PICLR(U) + UMOVEM B,(J) + SKIPN PICLR(U) + POPJ P, + JRST APISE1 + +;GENERATE A UNIQUE SYM ;.GENSYM AC, ;LOADS AC WITH SYM +; +AGENSYM:PUSHJ P,SWTL ;WAIT TILL INTERLOCK FREE THEN SEIZE IT + GENSSW + MOVEI TT,IGNSYM + PUSHJ P,SIXAOS ;INCREMENT SYM + MOVE A,IGNSYM ;GET SYM + PUSHJ P,LSWPOP ;UNLOCK FOR NEXT USER + JRST APTUAJ ;GIVE USER GENERATED SYMBOL + +;GENERATE A UNIQUE NUM ;.GENNUM AC, ;LOADS AC WITH NUMBER +; +AGENNUM:AOS A,IGNNUM ;INCREMENT NUMBER + JRST APTUAJ ;AND GIVE IT TO USER + +EBLK + +GENSSW: -1 + 0 +IGNSYM: SIXBIT /SYS/ + +IGNNUM: 0 + +BBLK + +SIXAOS: PUSH P,I + PUSH P,J + AOS (TT) ;INCREMENT SYM + MOVE I,[440600,,(TT)] ;GET POINTER TO FIRST CHAR +SIXAS2: ILDB J,I ;GET FIRST (NEXT) CHAR + SKIPN J ;SKIP IF NOT ZERO + MOVEI J,1 ;REPLACE EMBEDDED SPACE WITH "!" + DPB J,I ;PUT BACK + CAME I,[60600,,(TT)] ;SKIP IF FIRST FIVE CHARS HAVE BEEN EXAMINED + JRST SIXAS2 ;GO TO NEXT CHAR + POP P,J + POP P,I + POPJ P, + +IFN KL10P,[ + +SUBTTL KL10 PERFORMANCE COUNTER + +;KLPERF SYMBOLIC SYSTEM CALL +;ARG 1: TO MEASURE PERFORMANCE DURING; + ;-3 => NULL JOB, -4 => ALL JOBS +;ARG 2: P.A. ENABLES WORD (SEE NON-EXISTENT KL10 SYS REF MAN) + ;0 => FREE THE FACILITY, ELSE TRIES TO GRAB IT +;NO ARGS => JUST READS THE VALUES WITHOUT CHANGING THE ENABLING CONDITIONS. + ;IN THAT CASE, IT IS OK IF FACILITY IS OWNED BY SOMEONE ELSE +;VAL 1: PREVIOUS SETTING +;VAL 2: PREVIOUS P.A. ENABLE WORD +;VAL 3: TIME BASE HIGH WORD +;VAL 4: TIME BASE LOW WORD +;VAL 5: PERF CTR HIGH WORD +;VAL 6: PERF CTR LOW WORD + +KLPERF: CONO PI,CLKOFF + JUMPN W,KLPER1 +KLPER0: MOVE J,MTRJOB ;NO ARGS => DONT CHANGE SETTINGS, + MOVE B,PAEON ;JUST RETURN CURRENT COUNT. + JRST KLPER3 + +KLPER1: JUMPN B,KLPER2 ;TRYING TO TURN IT ON? + CAME U,MTRUSR + JRST KLPER0 ;FREEING THE FACILITY WHEN DON'T OWN IT? + PUSHJ P,PRFOFF ;NO, TRYING TO FREE IT - DO SO. + MOVEI J,-2 + JRST KLPER3 + +KLPER2: SKIPGE MTRUSR ;IF FACILITY IS FREE, SIEZE IT. + MOVEM U,MTRUSR + CAME U,MTRUSR + JRST OPNL10 ;ALREADY BELONGS TO SOME OTHER JOB. + MOVEI J,2(A) + CAIN J,-2 ;ALL JOBS? + JRST KLPER4 + CAIN J,-1 ;NULL JOB? + JRST KLPER3 + MOVE J,A + JSP T,NCRUI2 ;ELSE DECODE JOB SPEC; OBJECT TO PDP6 + JFCL + CAME J,U + JRST KLPER3 +;TRYING TO TURN ON FOR SELF OR ALL JOBS - IT OUGHT TO BE ON RIGHT NOW! +KLPER4: CONO MTR,2001 ;TURN ON TIME BASE, INTERVAL PIA=1 + WRPAE B ;SET ENABLES +KLPER3: EXCH B,PAEON + SKIPGE A,MTRJOB + TRZA A,2 ;UN CONVERT -1 => -3, -2 => -4 + LSH A,-9 ;IDIVI A,LUBLK +IF2 IFN LUBLK-1000,.ERR NO DIVIDE + HRREM J,MTRJOB + RCCL C ;C,D GET TIME BASE + RPERFC E ;E,TT GET PERFC + JRST CLKOJ1 + +;TURN OFF THE PERFORMANCE COUNTER. PUT BACK IN RUN-TIME MEASURING MODE +PRFOFF: MOVNI A,2 ;NOT ATTACHED TO ANY JOB + MOVEM A,MTRJOB + WRPAE [1576,,1200] ;MEASURE MAIN-PROGRAM TIME IN 80 NS UNITS (MODEL A) + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 + RPERFC STPERF ;START-OF-QUANTUM TIME IS NOW + RPERFC NULPRF ;ALSO FOR NULL-JOB + SETOM MTRUSR ;NO LONGER IN USE + POPJ P, +] ;END IFN KL10P + +$INSRT CORE ;CORE JOB AND MEMORY MANAGEMENT ROUTINES + +SUBTTL NULL DEVICE +; IMMEDIATE EOF ON INPUT, HAS NO EFFECT ON OUTPUT +; +NULO: HLRS A,C ;REMEMBER MODE FOR .STATUS + JSP Q,OPSLC3 ;SET UP IOCHNM WORD AND EXIT + NLIDN,,NLODN ;ARG + NLBIDN,,NLBDN ;ARG + +;UNIT NULL DEVICE INPUT +NULI: JRST UNIEOF + +;BLOCK NULL DEVICE INPUT +NULBI: POPJ P, + +;BLOCK NULL DEVICE OUTPUT ENTRY +;ADVANCE BLOCK MODE .IOT POINTER +NULBOD: XCTR XR,[HLRE A,(C)] ;GET NEG LENGTH FROM LEFT HALF + MOVNS A ;GET POSITIVE LENGTH + XCTR XR,[ADD A,(C)] ;ADD STARTING LOC (R.H.) + XCTR XW,[HRRZM A,(C)] ;STORE BACK "COUNTED OUT" POINTER + POPJ P, + +;STANDARD DEVICE .STATUS ROUTINE +STDSTA: DPB A,[60300,,D] ;A HAS LH OF IOC WORD + TRO D,1_9 ;SYS BUF CAP FULL + TRNE D,1_6 ;SKIP IF INPUT + TRC D,3_9 ;TURN OFF SYS BUF CAP FULL, SET EMPTY + POPJ P, + +SUBTTL USER DEVICE + +UBPFJ==10 ;DEMAND FOREIGN JOB (BIT IN LH (DEV) FOR .OPEN (USR)) + +USROJ: TDZA J,J ;ENTRY FROM JOB DEVICE DONT GET CORE. +USRO: MOVNI J,1 ;INDICATE NOT FROM JOB OPEN + CAIA +USROOJ: MOVEI J,1 ;OJB DEVICE; EXISTING JOB OK ONLY IF %OPOJB BIT SET. + PCLT + SKIPL CORRQ(U) + PUSHJ P,UFLS ;PREVENT ATTEMPT TO CORE, PCLSR OUT, AND THINK YOU'VE WON AT SETBF1, ETC + PUSHJ P,SWTL + TREESW + JUMPE B,USRO4 ;JNAME = 0 => UNAME IS JOB SPEC. + SKIPN A ;IF UNAME=0 + MOVE A,UNAME(U) ;MAKE IT THIS JOB'S UNAME + CAME A,UNAME(U) ;SKIP IF FIRST FILE NAME IS UNAME OF OPENER + JRST USROA + CAME B,[SIXBIT /PDP10/] ;SKIP IF SECOND FILE NAME IS "PDP10" + CAMN B,[SIXBIT /PDP6/] ;OR PDP6 +IFN PDP6P,JRST PDPO + .ELSE JRST OPNL1 +USROA: CONO PI,CLKOFF + PUSHJ P,LSWPOP ;TREESW +USROB: SETZ TT, +USRO3: CAME A,UNAME(TT) + JRST AGIN + CAMN B,JNAME(TT) + JRST UFN1 ;FOUND UNAME JNAME PAIR +AGIN: ADDI TT,LUBLK + CAMGE TT,USRHI + JRST USRO3 + TLNE C,UBPFJ ;JOB MUST EXIST TO WIN IF UBPFJ SET + JRST OPNL4 + CAME A,UNAME(U) ;INFERIOR PROCEDURE MUST HAVE SAME UNAME + JRST OPNL20 + PUSH P,U +TCORS: MOVSI T,%TBNOT+%TBDTY ;DOESN'T HAVE TTY, ISN'T GIVING IT AWAY + PUSHJ P,USTRA + JRST TCORS1 ;USTRA FAILED - SEE WHY, MAYBE RETRY (U CLOBBERED) + MOVEM A,UNAME(U) + MOVEM B,JNAME(U) + MOVEM A,USYSNM(U) + MOVE TT,U + POP P,U + MOVE A,UTMPTR(U) + MOVEM A,UTMPTR(TT) + MOVE A,HSNAME(U) + MOVEM A,HSNAME(TT) + MOVE A,XUNAME(U) + MOVEM A,XUNAME(TT) + MOVEM B,XJNAME(TT) + PUSHJ P,USRST5 ;SET UP TTY STUFF + MOVSI A,400000 + SKIPGE APRC(U) + IORM A,APRC(TT) ;NEW INFERIOR IS DISOWNED IF CREATOR IS. + JUMPE J,CLKOJ1 ;RETURN HERE FOR JOB DEVICE (INDEX IN TT) + PUSHJ P,ULUP1 ;FIND AN INTERRUPT BIT FOR THE JOB. + JRST NOGO1 ;NONE => GO KILL THE JOB AND RETURN FAILURE. + CONO PI,CLKON ;NOW CAN'T FAIL TO CREATE THE JOB FOR GOOD. + HRLZ B,B + HRR B,U + MOVEM B,SUPPRO(TT) + MOVE U,TT + PUSHJ P,UFOUND ;SET UP THE OPENER'S CHANNEL. + JFCL + MOVE Q,TT + MOVEI B,1 + PUSHJ P,ACORE1 ;MAY PCLSR OUT, BUT CORE JOB WILL DO WORK ANYWAY. + SKIPA R,UUAC(U);NO CORE AVAILABLE, KILL THE JOB + JRST POPJ1 ;SUCCESS + ADDI R,IOCHNM(U) + PUSHJ P,AUCLOSE + JRST OPNL37 ;NO CORE AVAILABLE + +ULUP1: CLEARB A,T +ULUP: HRRZ E,SUPPRO(T) + SKIPN UNAME(T) ;SKIP IF VARIABLE BLOCK IN USE + JRST ULUP2 + CAIN E,(U) ;SKIP IF NOT AN INFERIOR + IOR A,SUPPRO(T) ;IOR IN INTERRUPT BIT OF INFERIOR +ULUP2: ADDI T,LUBLK ;ADVANCE TO NEXT BLOCK + CAMGE T,USRHI ;SKIP IF ALL EXAMINED + JRST ULUP ;LOOP +UFIN: MOVEI B,1 ;SELECT INT BIT +UFIN2: TLON A,(B) + JRST POPJ1 + LSH B,1 + CAIGE B,1_ + JRST UFIN2 + POPJ P, + +NOGO1: MOVSI T,BULGO+BULGOS + IORM T,APRC(TT) ;TELL THE SYS JOB TO KILL THE JOB WE JUST GOT + MOVSI T,SCLGUN + IORM T,SUPCOR + JRST OPNL5 ;DIREC FULL (TOO MANY LOSERS) + +NOGO4: SUB P,[1,,1] + JRST OPNL6 + +TCORS1: PCLT ;COME HERE FROM TCORS IF ATTEMPT TO FIND FREE JOB SLOT FAILED. + SKIPGE SJCFF ;IF THIS IS NEGATIVE, USTRA DIDN'T EVEN REQUEST MORE + JRST [ SKIPGE SJCFF + PUSHJ P,UFLS + JRST TCORS2] + MOVE TT,USRHI + CAIL TT,MAXJ*LUBLK + JRST NOGO4 ;USER MEM EXPANDED TO MAX + SKIPGE SUPCOR .SEE SCLEX ;PRESUMABLY USTRA ASKED SYS JOB FOR MORE JOB SLOTS + PUSHJ P,UFLS ;SO WAIT TILL SYS JOB ANSWERS THE REQUEST +TCORS2: CONO PI,CLKOFF ;AND SEE IF THERE ARE NOW ENOUGH SLOTS. + JRST TCORS + +USRO4: EXCH J,A ;USR: OPEN WITH JNAME=0: USE UNAME AS JOB SPEC. + JSP T,NCORUI + JFCL +IFN PDP6P,[ + CAIN J,-1 ;SPEC'D JOB IS PDP6 => OK, + JRST PDPO +] + CONO PI,CLKOFF + PUSHJ P,LSWPOP ;SOS DIELOK(J) + PUSHJ P,LSWPOP ;TREESW + MOVE TT,J + MOVE J,A +;COME HERE WHEN JOB ALREADY EXISTS, WITH CLOCK OFF AND USR IDX IN TT. +;A, B, C STILL HAVE UNAME, JNAME AND OPEN MODE. +UFN1: JUMPE J,[ADDI B,10000 ;OPENING JOB-DEVICE AND JOB EXISTS?? + JRST USROB] ;KEEP CHANGING JNAME UNTIL WE CREATE A JOB. + CAIG TT,LUBLK + JUMPL J,UFNDF ;SKIP SOME CHECKS ON SYS & CORE + JUMPG J,[MOVSI T,%OPOJB ;OJB DEVICE OPEN; IF JOB DOESN'T HAVE %OPOJB SET, + TDNE T,OPTION(TT) ;THEN IT HASN'T GIVEN PERMISSION TO BE HACKED. + SKIPL JBI(TT) ;IF IT'S ALREADY A JOB DEVICE DON'T HACK IT. + JRST [CONO PI,CLKON ;IN EITHER CASE, WAIT TILL ALL'S OK, + SKIPL JBI(TT) + PUSHJ P,UFLS + TDNN T,OPTION(TT) + PUSHJ P,UFLS + JRST USROOJ] ;THEN RE-TRY THE OPEN. + LDB T,[.BP BULGOS_22,APRC(TT)] + JUMPN T,OPNL42 + JRST CLKOJ1] ;RETURN SUCCESS TO JOBO6C. + TLNE C,UBPFJ + JRST UFNDF ;USER WANTS IT AS FOREIGN JOB + HRRZ E,SUPPRO(TT) + CAIN E,(U) + JRST UFN1C ;OPENING UP INFERIOR + SKIPGE T,APRC(TT) + SKIPL SUPPRO(TT) ;UNLESS IT'S A TOP-LEVEL DISOWNED JOB, + JRST UFNDF ;THEN FOREIGN JOB + PUSHJ P,UFN2B ;REOWN DISOWNED TREE + POPJ P, ;CAN'T + JRST UFOUND ;DID + +UFN1C: MOVE U,TT ;OPENING PROCEDURE IMMEDIATE SUPERIOR OF PROCEDURE BEING OPENED + JRST UFOUND + +; +; REOWN A DISOWNED PROCEDURE TREE +; + +NREOWN: TLNN R,%CLSFU ;MUST BE A FOREIGN USER CHANNEL + JRST OPNL34 + CONO PI,CLKOFF + HLRZ TT,H + SKIPGE T,APRC(TT) + SKIPL SUPPRO(TT) + JRST OPNL31 ;TO A TOP-LEVEL DISOWNED JOB + HRLM R,(P) + PUSHJ P,UFN2B ;REOWN THE JOB (TURNS CLOCK ON) + POPJ P, ;FAILED + HLRZ R,(P) ;TURN THE CHANNEL INTO AN INFERIOR CHANNEL. + MOVNI T,FUWIDN-UWIDN + ADDM T,(R) + JRST POPJ1 + +;REOWN JOB TT POINTS TO, ITS APRC IS IN T. SKIPS IF SUCCESSFUL. +;CALL WITH CLKOFF, WILL TURN IT ON. +UFN2B: TLNE T,BULGOS + JRST OPNL42 ;CAN'T REOWN JOB WHICH IS LOGGING OUT. + SKIPGE APRC(U) ;IF REOWNING JOB IS DISOWNED, PROHIBIT SO THAT + JRST OPNL31 ;IT DOESN'T REOWN ITSELF AND SCREW THINGS UP + PUSHJ P,ULUP1 ;FIND AN INTERRUPT BIT FOR IT. (IN B) + JRST OPNL5 ;WE HAVE 8 INFERIORS ALREADY. + AOS (P) ;GOING TO WIN + SETOM DLSRCH ;INHIBIT SCHEDULING + CONO PI,CLKON ;TURN CLOCK BACK ON, THIS MAY TAKE A WHILE + MOVSI A,BUMRTL ;DOOMED DETACHED JOBS ARE RESCUED BY REOWNING. + ANDCAM A,APRC(TT) + MOVE A,UNAME(U) ;PICK UP NEW UNAME + SETCM D,APRC(U) + TLZ D,#400000 ;SIGN OF D SET IFF REOWNER ISN'T DISOWNED. + MOVE J,UTMPTR(U) ;PICK UP NEW USER RESOURCE POINTER + HRR D,J + SUBI J,USRRCE ;GET NEW CONSOLE # + CAIL J,NCT ;IF NEW TREE STILL HAS NO TTY, + MOVEI J,%TINON ;"DISOWNED" TTY CHNLS SHOULD REMAIN SUCH +;HERE, A HAS UNAME, D HAS ,,UTMPTR, J HAS CONSOLE # OR %TINON, +;U HAS REOWNER, TT HAS JOB BEING REOWNED. +UFN2A: PUSH P,B ;SAVE INTERRUPT BIT +UFN3: MOVEM A,UNAME(TT) ;SET TO NEW UNAME + HRRZM D,UTMPTR(TT) ;SET TO NEW USER RESOURCE POINTER + MOVEI R,IOCHNM(TT) + PUSHJ P,CHSCAN + PUSHJ P,UFN3ZZ + HLLZ T,D ;LH(D) HAS 0 IF REOWNER DISOWNED, ELSE 400000 + ANDCAM T,APRC(TT) ;MARK AS NOT DISOWNED IF REOWNER ISN'T DISOWNED. +UFNL3: MOVE B,JNAME(TT) ;PICK UP CURRENT JNAME + MOVEI E,0 ;LOOP ON ALL USERS +UFNL1: CAMN A,UNAME(E) ;SKIP ON NOT SAME UNAME + CAME B,JNAME(E) ;SKIP ON SAME UNAME-JNAME + JRST UFNL2 ;NOT SAME NAME AND/OR VAR BLK NOT IN USE + JRST UFN7 ;NAME CONFLICT, RESOLVE +UFNL2: ADDI E,LUBLK + CAMGE E,USRHI + JRST UFNL1 + MOVEI E,0 ;INITIALIZE FOR LOOP TO LOOK FOR INFERIORS AND DUPLICATE NAMES +UFN4: SKIPN UNAME(E) ;SKIP IF VAR BLOCK IN USE + JRST UFN5 ;TRY NEXT + HRRZ I,SUPPRO(E) ;PICK UP SUPERIOR POINTER OF BLOCK BEING EXAMINED + CAIN I,(TT) ;SKIP IF NOT INFERIOR + JRST UFN6 ;INFERIOR, PSEUDO-RECURSE +UFN5: ADDI E,LUBLK ;ADVANCE TO NEXT BLOCK + CAMGE E,USRHI ;SKIP IF ALL EXAMINED + JRST UFN4 ;LOOP + SKIPGE SUPPRO(TT) ;SKIP IF NOT BACK TO TOP + JRST UFNX ;BACK TO TOP LEVEL + MOVE E,TT ;POP BACK UP + HRRZ TT,SUPPRO(E) ;TO PREVIOUS LEVEL + MOVE B,JNAME(TT) ;RESTORE B + JRST UFN5 ;PROCEED AT PREVIOUS LEVEL + +UFNX: POP P,B + HRLM B,SUPPRO(TT) + HRRM U,SUPPRO(TT) ;SET UP SUPERIOR POINTER IN TO LEVEL DISOWNED + SETZM DLSRCH ;RE-ENABLE SCHEDULING + MOVE U,TT + POPJ P, + +UFN6: MOVE TT,E ;PSEUDO-RECURSE + JRST UFN3 ;START UP ON LOWER LEVEL + +UFN7: CAMN E,TT ;SKIP UNLESS FOUND SELF + JRST UFNL2 + ADDI TT,JNAME ;SET UP ARG TO SIXAOS + PUSHJ P,SIXAOS ;INCREMENT JNAME + SUBI TT,JNAME ;RESTORE TT + JRST UFNL3 ;RESTART LOOP + +;RESUSCITATE TTY CHNLS +UFN3ZZ: HRRZ Q,(R) + CAIL Q,TYIDN + CAILE Q,TYOBN + POPJ P, ;NOT A TTY CH + HLRZ Q,(R) + TRNN Q,%TICNS + POPJ P, ;NOT CONSOLE + CAIE J,%TINON + AOS TTNTO(J) + DPB J,[$TIIDX,,(R)] + POPJ P, + +UFOUND: HLRZS C ;U HAS INF PROC + HRL A,U + MOVE U,USER + HRRZ R,UUAC(U) + ADDI R,IOCHNM(U) ;CLOBBERED BY CORE + JSP Q,OPSLC3 + UWIDN,,UWODN + UBIDN,,UBODN + +UFNDF: TLNE C,1 + JRST OPNL12 ;ATTEMPTED OUTPUT + LDB A,[.BP BULGOS_22,APRC(TT)] + JUMPN A,OPNL42 ;USER GOING AWAY + HRL A,TT + JSP Q,OPSLD1 + FUWIDN,,FUBIDN + +USRST: PUSHJ P,AUCL2 ;.RESET SIMULATES CLOSING AND REOPENING + POPJ P, + CONO PI,CLKON + PUSHJ P,1USTOP + EXCH U,A ;BUT WITH LESS OVERHEAD + PUSH P,A + PUSHJ P,IODCL + MOVEI B,BULGOS ;WE'RE NOT REALLY TRYING TO KILL THE INFERIOR, + ANDCAM B,APRC(U) ;SO DON'T LET OTHERS THINK HE'S BEING KILLED. + MOVE Q,U + SETZ B, + EXCH U,(P) + PUSHJ P,ACRF1 ;FLUSH ALL OF CORE + BUG +USRST1: MOVEI B,1 + MOVE Q,(P) + PUSHJ P,ACRF1 ;THEN GET 1 PAGE + JRST [ PUSHJ P,UDELAY + JRST USRST1] + EXCH U,(P) + MOVSI T,%TBNOT+%TBDTY + MOVEM T,TTYTBL(U) + MOVE J,U + EXCH U,(P) + PUSHJ P,MPLDJ + XCTR XW,[CLEARM 0] + MOVEI T,1 + XCTR XBRW,[BLT T,1777] + PUSHJ P,MPLDZ + EXCH U,(P) + PUSHJ P,LOGUSE + CONO PI,CLKOFF + PUSHJ P,USRST2 + CONO PI,CLKON + PUSHJ P,USRST4 ;SHOULD SKIP + BUG + POP P,A + EXCH U,A + MOVE TT,A +USRST5: MOVE A,TTSTSV(U) ;INITIALIZE SAVED TTYSET OF NEW JOB EQUAL TO CREATOR'S. + SKIPL B,TTYTBL(U) ;NOTE THAT THE WHEREABOUTS OF THE CREATOR'S TTYSET + MOVE A,TTYST1(B) ;DEPENDS ON WHETHER HE HAS THE TTY NOW. + MOVEM A,TTSTSV(TT) + MOVE A,TTSTSV+1(U) + SKIPL B + MOVE A,TTYST2(B) + MOVEM A,TTSTSV+1(TT) + MOVEI A,(TT) ;RH OF NEW JOB'S SAVED TTYSTS IS HIS INDEX. + HRLI A,%TSCNS ;NOW CONSTRUCT THE LH. + MOVE B,UTMPTR(TT) ;TO DO THAT, FIND THE TREE'S TTY NUMBER + MOVE B,TTYOPT-USRRCE(B) ;TO FIND THE TTY'S TTYOPT WORD, + TLNE B,%TOROL ;WHICH TELLS HOW TO INIT THE BITS IN THE TTYSTS. + TLO A,%TSROL + TLNN B,%TOMOR + TLO A,%TSMOR + TLNE B,%TOSA1 + TLO A,%TSSAI + MOVEM A,TTSTSV+2(TT) + POPJ P, + +;.CALL USRMEM +; ARG 1 JOB WHOSE MEMORY SHOULD BE READ OR WRITTEN +; ARG 2 ADDRESS TO READ OR WRITE +; ARGS 3,4 LIKE USRVAR, TTYVAR +; VAL 1 PREVIOUS CONTENTS OF LOCATION +; VAL 2 NEW CONTENTS OF LOCATION (SAME AS PREVIOUS IF NOT WRITING). +; (NOT VALID IN BLOCK MODE) + +; BIT 1.1 IF SET, THEN IF PAGE ISN'T READABLE OR WRITEABLE, GIVE AN MPV +; OR PURE INTERRUPT TO THE JOB BEING REFERENCED. +; BIT 2.9 IF SET, ALLOWS US TO WRITE IN ANY JOB. + +NUSRMEM: + MOVE J,A + JSP T,NCORUI + JRST NUSRM1 ;WE CAN SURELY WRITE. + MOVE H,CTLBTS(U) + CAIGE W,3 ;ELSE, IF WE WANT TO WRITE, + TRNE H,1 ;OR WANT TO GIVE THE REFERENCED JOB INTERRUPTS, + TRNE H,400000 ;THEN UNLESS WE ARE FORCING IT, + JRST NUSRM1 + JSP T,NCORWR ;SEE IF IT IS A JOB WE ARE ALLOWED TO WRITE IN. + JRST OPNL31 +NUSRM1: MOVE H,CTLBTS(U) + CAIE J,-1 + CAIG J,LUBLK ;CAN'T GIVE SYS OR CORE JOBS INTERRUPTS, OR PDP6. + TRNN H,1 + CAIA + JRST OPNL31 +IFN PDP6P,[ + CAIN J,-1 + JRST NUSRMS +];PDP6P + CAILE J,LUBLK + CAMN J,U + JRST NUSRMS + MOVE A,J ;IF TARGET JOB ISN'T SELF OR PDP6 + PUSHJ P,RPCLSR ; OR SYS OR CORE, STOP IT. + PUSHJ P,SOSSET + USTP(J) +NUSRMS: PUSHJ P,NUSRM2 ;DO THE WORK + POPJ P, ;LOST, OPNL HAS LSWCLR'ED + JRST LSWCJ1 ;POSSIBLY UNLOCK USTP, DIELOK AND TAKE SUCCESS RETURN + +NUSRM2: PUSHJ P,VARCAL ;E:=ADDR, D:=DATA, W:=INSTRUCTION + HRRZS E + CAIGE E,20 + JRST NUSRM6 ;ACS ALWAYS SWAPPED-IN AND ACCESSIBLE + PUSH P,U + MOVE U,J + LDB A,[121000,,E] ;GET PAGE # IN A AND REF'D JOB IN U. +IFE PDP6P, PUSHJ P,UPLC +IFN PDP6P,[ + PUSHJ P,[ CAIE J,-1 ;SKIP IF PDP6 + JRST UPLC ;DECODE THEM FOR ORDINARY JOB. + CAIL A,LPDP6M + TDZA T,T ;FOR PDP6, MOST PAGES DON'T EXIST, + MOVE T,[002200,,[600000]] ;AND THE REST ARE WRITABLE. + POPJ P,] +];PDP6P + POP P,U + LDB A,T ;GET PAGE ACCESS HALFWORD. + TRNN A,600000 ;IF PAGE SWAPPED OUT, PUT ACCESS BITS IN PLACE THEY WOULD BE + LSH A,16. ; FOR AN IN-CORE PAGE. + JUMPE A,NUSRM9 ;LOSE IF NO PAGE THERE + TRNN A,400000 ;OR IF WE ARE TRYING TO WRITE THE WORD AND PAGE IS READ-ONLY. + JUMPN W,NUSRM8 +NUSRM6: PUSHJ P,MPLDJ ;NOW LOAD MAP OF JOB IN J + HRLI E,(SKIP) ;GET ACCESS TO DATA WORD, SWAP IN PAGE + SKIPE W + HRLI E,(MOVES) +NUSRM4: CONO PI,CLKOFF ;CLK OFF SO ONCE IN CAN'T SWAP OUT AGAIN + XCTRI XRW,E ;NOT GETTING BENEFIT OF USUAL PCLSR BEFORE + JRST NUSRM5 ;SWAP OUT FEATURE SINCE IT'S ANOTHER JOB + PUSHJ P,TPFLT + JRST NUSRM4 + +NUSRM5: UMOVE B,(E) ;NOW THAT PAGE IS IN, GET OLD CONTENTS + MOVE A,B ;IN A AND B + JUMPE W,NUSRM3 + HRRI W,B ;IF WRITING, + XCT W ;EXECUTE USER'S INSN., MODIFYING 2ND VALUE IN B, + TRNN J,-1 ;SYSTEM JOB? + JRST OPNL31 ;******* WRITING SYS, TURN INTO .SETLOC ******* + UMOVEM B,(E) ;AND STORE IT BACK INTO REF'D JOB. +NUSRM3: PUSHJ P,MPLDZ ;RESTORE NORMAL PAGE MAP, TURN CLKON. + JRST POPJ1 ;SUCCESS + +NUSRM8: SKIPA T,[%PIWRO] ;HERE IF TRYING TO WRITE IN READ ONLY PAGE. +NUSRM9: MOVEI T,%PIMPV ;HERE IF ACCESSING NONEXISTENT PAGE. + TRNN H,1 ;SKIP IF TO GIVE INTERRUPT + JRST OPNL32 + CAMN J,USER + JRST UUOERR ;INTERRUPT TO SELF + IORM T,PIRQC(J) ;INTERRUPT OTHER USER + JRST OPNL32 ;CAN'T GET THAT ACCESS TO PAGE. + +;COMMENTS BELOW APPLY TO UBI IN MANY CASES. FOR UBO, TRANSFER GOES THE +;OTHER DIRECTION + +UBO: MOVNI I,1 + JRST UBIL + +UBI: MOVEI I,0 ;SIGNAL UBI + +UBIL: JUMPL C,UBIA + XCTR XRW,[MOVES TT,(C)] ;MAKE SURE WRITE CYCLES WILL WIN +UBIB: TRNE A,200000 ;SKIP UNLESS 6 + MOVNI A,1 ;SO CAILE BELOW WILL SKIP OVER SUSTPR AMONG OTHER REASONS + CAILE A,LUBLK ;SKIP ON SYS JOB, CORE JOB, PDP6 OR JOB ALREADY STOPPED + PUSHJ P,SUSTPR ;RANDOM JOB STOP + JUMPGE TT,UBI4 ;THRU + TLO A,400000 ;INDICATE ALREADY STOPPED SO WONT TRY IT AGAIN + HLRO B,TT + MOVNS B ;COUNT TO BE XFERRED + HRLZ E,IOCHST-IOCHNM(R) ;EXAMINED USER ADDRESS + HRR E,TT ;FROM,,TO (INFERIOR ADR,,SUPERIOR ADR) + HLRZ Q,E + TLNE A,200000 + JRST UBI5A ;PDP6 +UBI5: CAIGE Q,20 ;INF ADR IN Q + JRST UBI3 ;READ AC + HRRZ J,A ;SET UP UMAPS WORD + TRZE E,400000 + TLOA J,%UMMPL ;TO HI PG, HACK OUR LOW PG + TLO J,%UMMPU ;TO LOW PG, HACK OUR HI PG + TLZE E,400000 + TLOA J,%UMLTU ;TO POINT TO HIS UPPER + TLO J,%UMUTL ;TO POINT TO HIS LOWER + TLNN J,%UMMPU+%UMUTL ;MAPPING HIS UPPER WITH OUR LOWER? + JRST UBI3A ;YES MAKE SURE NOT SCREWED BY AC PNTR +UBI3B: PUSHJ P,MPLD1 + TRZ Q,400000 + MOVNS Q ;LIMIT SIZE OF XFER TO MIN OF DESIRED + ADDI Q,400000 ;DIST OF TO ADR FROM SEG BOUNDARY + CAMLE B,Q + HRRZ B,Q + MOVNI Q,(E) ;AND DIST OF FROM ADR FROM SEQ BOUNDARY + ADDI Q,400000 + CAMLE B,Q + HRRZ B,Q + TLNN J,%UMMPL ;BUGGER ADDRESSES SO RIGHT DBRS WILL BE USED + TLOA E,400000 ;SET FROM ADR TO HI PG + TRO E,400000 ;SET TO ADR TO HI PG + SKIPE I ;SKIP ON UBI + MOVSS E ;UBO, XFERR OTHER DIRECTION + MOVE Q,E ;SAVE COPY OF BLT PNTR + ADDI B,(E) ;GET LA +1 +UBI3H: XCTRI XBRW,[BLT E,-1(B)] ;XFERR DATA +UBI3K: MOVEI E,(B) ;NO FAULT, SIMULATE STORE BACK OF BLT PNTR AFTER COMP OF BLT (RH ANYWAY) +UBI3L: PUSH P,J + PUSHJ P,MPLDZ ;RETURN TO NORMAL MAP TO STORE BACK USER PNTR + POP P,J ;SAVE PREV MAP FOR EVENTUAL USE + SUBM E,Q ;FIGURE OUT HOW MANY WDS ACTUALLY XFERRED + HRRZS Q +UBI3E: HRLS Q ;# WDS TRANSFERRED,,SAME + JUMPL C,UBIC ;UPDATE USER PNTR + XCTRI XRW,[ADDM Q,(C)] + JRST .+2 + BUG ;SHOULD HAVE ALREADY CHECKED THIS +UBID: ADD Q,IOCHST-IOCHNM(R) ;UPDATE INFERIOR PNTR + HRRM Q,IOCHST-IOCHNM(R) ;WRAPPING AROUND IF PASS 1,,0 + TLZ B,-1 + CAIN B,(E) ;WAS THERE A FAULT? + JRST UBIL ;NO, LOOP + PUSHJ P,UBI4 ;UNSTOP THE JOB. + PUSHJ P,MPLD1 ;RESTORE TO FROB AT TIME OF FAULT +UBI3C: PUSHJ P,TPFLT + PUSHJ P,MPLDZ + JRST UBIL + +UBI4: TLNN A,200000 ;SKIP ON REALLY PDP6 + TLZ A,400000 ;FLUSH RANDOM BIT SO COMPARE WILL WORK + CAILE A,LUBLK + JRST UPCLSR + POPJ P, + +UBMCK1: PUSHJ P,UBI4 + JRST IOADC + +UBIA: TRNE C,777760 + BUG + MOVE TT,(C) + JRST UBIB + +UBIC: TRNE C,777760 + BUG + ADDM Q,(C) + JRST UBID + +UBI5A: CAIL Q,400000 + JRST UBMCK1 + JRST UBI5 + +UWO: SKIPGE C + SKIPA D,(C) + UMOVE D,(C) + TDZA I,I +UWI: SETO I, ;0 FOR OUTPUT, -1 FOR INPUT. + TRNE A,200000 + MOVNI A,1 ;-1 MEANS PDP6. + CAMN A,USER + HRLI A,-1 ;DON'T STOP SELF + CAIG A,LUBLK + JRST UWI1 ;SYS, CORE, SELF, OR PDP6 + PUSHJ P,SUSTPR + PUSHJ P,SOSSET ;MIGHT TAKE PAGE FAULT AND GET PCLSRED + USTP(A) +UWI1: HRRZ E,IOCHST-IOCHNM(R) + HRRZ J,A + PUSHJ P,MPLDJ ;MAP JOB BEING IOT'ED FROM. + XCTR XRW,[ MOVE W,(E) + MOVEM D,(E)]+1(I) + AOS IOCHST-IOCHNM(R) ;ADVANCE ACCESS POINTER + CAILE A,LUBLK + PUSHJ P,LSWPOP + JRST MPLDZ + +UBI3A: TLNE E,777760 ;SKIP ON XFERRING FROM AC AREA, HI TO HI + JRST UBI3B ;NO OK + JUMPN I,UBO3A ;UBO + PUSHJ P,MPLDJ + XCTRI XR,[MOVE B,(Q)] ;PICK UP WD + JRST .+2 ;OK + JRST UBI3C ;TAKE FAULT + PUSHJ P,MPLDZ ;BACK TO NORMAL MAP + HRRZ E,TT ;TO ADR + JRST UBI3D + +;USR DEV IOT STOP ROUTINE +USUSTP: SOS USTP(A) +SUSTPR: MOVSI T,BCSTOP+BUCSTP + TDNE T,USTP(A) ;WAIT TILL NOT BEING SHUFFLED + PUSHJ P,UFLS + PUSHJ P,RPCLSR ;AOS'ES USTP + MOVSI T,BCSTOP+BUCSTP + TDNE T,USTP(A) + JRST USUSTP + POPJ P, + +UBI3: ADDI Q,AC0S(A) + JUMPN I,UBO3 ;UBO + TLNE A,200000 + TDZA B,B ;READ PDP6 AC + MOVE B,(Q) ;READ NORMAL AC +UBI3D: XCTRI XW,[MOVEM B,(E)] + JRST .+2 + JRST UBI3C ;TAKE FAULT +UBI3G: MOVEI Q,1 ;1 WD XFERRED + HRRZ B,E ;FAKE OUT FAULT TEST + JRST UBI3E + +UBO3: TLNE A,200000 + JRST UBI3G ;TRYING TO WRITE PDP6 AC IGNORE + XCTRI XR,[MOVE B,(E)] + JRST .+2 + JRST UBI3C + MOVEM B,(Q) + JRST UBI3G + + +UBO3A: XCTRI XR,[MOVE B,(TT)] + JRST .+2 + JRST UBI3C ;TAKE FAULT + PUSHJ P,MPLDJ ;MAP HIM. + XCTRI XW,[MOVEM B,(Q)] + JRST .+2 + JRST UBI3C + PUSHJ P,MPLDZ ;BACK TO NORMAL + JRST UBI3G + +SUBTTL CORE LINK DEVICE + +EBLK +CLVBEG: NCLCH +CLSYN: BLOCK NCLCH ;SYSTEM NAME ;0=>VARIABLES FREE +CLN1: BLOCK NCLCH ;FN1 +CLN2: BLOCK NCLCH ;FN2 +CLUSR: REPEAT NCLCH,-1 ;LH=WRITING USER ;RH=READING USER ;-1=>NOT OPEN THAT HALF +CLRAC: BLOCK NCLCH ;4.9=LOCKED BY CORE ALLOCATOR + ;4.8=VERY SLOW CLOCK ROUTINE CONSIDERING FLUSHING THIS BUFFER + %CAFLS==100000 ;4.7=INPUT CLOSED, TURN OUTPUT INTO NUL DEVICE + %CA==1,,500000 ;RH=UT BUFFER NUMBER (IOBFT ADR) + +CLOSW: -1 ;USER LOCK TO STOP MORE THAN ONE PERSON FROM SIMULTANEOUSLY MODIFYING + 0 ;THE CORE LINK VARIABLES +CLVEND==.-1 +BBLK + +;FORMAT OF CORE LINK 200 WORD BUFFER +; +CLBVSP==8 +CLBCHS==100. +CLBEOF==/5 +IFG CLBVSP+CLBCHS+CLBEOF-128.,.ERR CLBXXX LOSSAGE + +; +;0: CHARACTER COUNT +;1&2: READ AND WRITE CHARACTER OR WORD POINTERS +;3&4: READ AND WRITE EOF POINTERS +;CLBVSP TO CLBVSP+CLBCHS-1: CHARACTERS OR WORDS +;CLBVSP+CLBCHS UP: EOF BITS STORED AS SEVEN FIVE BIT BYTES PER WORD, +; EACH BIT CORRESPONDING TO A CHARACTER POSITION. + +CLAO: SKIPA J,[2] ;CLA .OPEN (TO ANSWER A CLI INTERRUPT) +CLIO: MOVNI J,1 ;CLI .OPEN (INTERRUPTS USER SPECIFIED BY FILE NAME) + JRST CLI2 + +CLUO: TDZA J,J ;CLU .OPEN +CLOO: MOVEI J,1 ;CLO .OPEN +CLI2: JUMPL C,CLFDEL ;JUMP IF AN .FDELE + PUSHJ P,FLDRCK + JRST CLO1 ;NOT FILE DIRECTORY + MOVEI J,2 + JRST LISTF7 + +CLFDEL: MOVEI J,3 +CLO1: PUSHJ P,SWTL ;SEIZE SWITCH TO STOP VARIABLES FROM CHANGING UNDER YOU + CLOSW + LDB H,[220100,,C] ;DIRECTION BIT + JUMPL J,CLOO5 +CLOO5B: MOVE Q,USYSN1(U) ;PICK UP SNAME + MOVSI I,-NCLCH + CAIN J,2 ;SKIP UNLESS CLA + JRST CLO1A ;JUMP IF CLA .OPEN + CAIGE J,0 +CLO1A1: MOVE Q,[SIXBIT/_CLI_/] +CLOL: CAMN Q,CLSYN(I) ;LOOK FOR SNAME, FN1, & FN2 + CAME A,CLN1(I) + JRST CLOO1 + CAME B,CLN2(I) + JRST CLOO1 + JUMPL J,OPNL23 ;"FILE LOCKED" IF ALREADY EXISTS, FOR CLI:. + CAIN J,3 ;SKIP UNLESS DELETE + JRST CLO1D ;FOUND FILE TO DELETE +CLO1A6: LDB TT,CLOOT1(H) + CAIE TT,-1 + JRST OPNL23 ;ALREADY OPEN THIS DIRECTION (FILE LOCKED) + HRRZ TT,CLRAC(I) + LDB Q,[IOSA,,IOBFT(TT)] + LSH Q,6 +CLOX: DPB U,CLOOT1(H) ;STORE USER INDEX + MOVSI TT,200000 + ANDCAM TT,CLRAC(I) ;CLEAR VERY SLOW CLOCK BIT + PUSHJ P,LSWPOP ;RELEASE SWITCH + HRL A,I + LDB C,[220300,,C] + SKIPGE J + PUSHJ P,CLOX1 ;FOR CLI:, PUT OUR UNAME AND JNAME INTO BUFFER. + MOVEI TT,44 ;WORD + TRNN C,6 + MOVEI TT,7 ;UNIT ASCII + ADD Q,H ;OFFSET FOR DIRECTION + DPB TT,[300600,,1(Q)] ;SET UP ITEM POINTER + MOVEI TT,5 ;WORD + TRNN C,6 + MOVEI TT,1 ;UNIT ASCII + DPB TT,[300600,,3(Q)] ;SETUP EOF POINTER + JSP Q,OPSLC7 ;SET UP IOCHNM OF USER + DCLUAI,,DCLUAO ;UNIT ASCII INPUT ;UNIT ASCII OUTPUT + DCLBI,,DCLBO ;BLOCK INPUT ;BLOCK OUTPUT + DCLUBI,,DCLUBO ;UNIT BINARY INPUT ;UNIT BINARY OUTPUT + DCLBI,,DCLBO + +CLOX1: MOVEI TT,44 ;CHANGE OUTPUT BYTE SIZE TO 36. + DPB TT,[300600,,2(Q)] + MOVEI TT,5 ;WHICH INVOLVES STORING 5 CHARACTERS OF EOF BITS AT ONCE. + DPB TT,[300600,,4(Q)] + PUSH P,C + HRROI C,TT + MOVE TT,UNAME(U) + PUSHJ P,CLOXO ;NOW WE CAN IOT WORDS OUT, EVEN IF CHANNEL IS ASCII MODE. + SUBI Q,1 + MOVE TT,JNAME(U) + PUSHJ P,CLOXO + SOJA Q,POPCJ ;NOW RETURN, AND SET UP THE CORRECT BYTE SIZES. + +CLOO1: AOBJN I,CLOL ;LOOP FOR ALL SETS OF CORE LINK VARIABLES + CAIE J,1 + JUMPGE J,OPNL4 ;CLA, CLU DELETE LOSE + MOVSI I,-NCLCH +CLOO3: SKIPN CLSYN(I) ;LOOK FOR FREE VARIABLES TO CREATE FILE + JRST CLOO2 + AOBJN I,CLOO3 + JRST OPNL5 ;GIVE DIREC FULL ERROR + +CLOOT1: 2200,,CLUSR(I) ;READING + 222200,,CLUSR(I) ;WRITING + +CLOO2: MOVEM A,CLN1(I) ;SET UP VARIABLES + MOVEM B,CLN2(I) + MOVEI D,SCNCLO(I) ;SYS CHNL NO + PUSHJ P,TCALL ;GET 200 WORD BUFFER + JRST IUTCONS + JRST CLOO4 ;NO MEM AVAIL + MOVEM Q,CLSYN(I) ;DONT SET UP SYS UNTIL MEM AVAIL + HRRM A,CLRAC(I) + LDB Q,[IOSA,,IOBFT(A)] ;SET UP BUFFER + LSH Q,6 + SETZM (Q) ;CHAR COUNT + MOVE TT,Q + ADDI TT,CLBVSP ;SET UP BUF POINTERS + MOVEM TT,1(Q) + MOVEM TT,2(Q) + HRLI TT,440000 + ADDI TT,CLBCHS ;SET UP EOF POINTERS + MOVEM TT,3(Q) + MOVEM TT,4(Q) + JRST CLOX + +;NO MEMORY AVAILABLE FOR 200-WD BUFFERS +CLOO4: AOS SWPOPR ;MAYBE SWAPPING SOMETHING OUT WILL HELP + PUSHJ P,LSWPOP ;UNLOCK CLOSW + PUSHJ P,UDELAY ;WAIT A WHILE + JRST CLO1 ;TRY AGAIN + +CLOO5: CONO PI,CLKOFF ;TURN OFF CLOCK TO STOP U&J NAMES FROM CHANGING + MOVEI Q,2*LUBLK +CLOO5A: CAMN A,UNAME(Q) ;LOOK FOR USER WHOSE NAMES MATCH THE SPECIFIED FILE NAMES + CAME B,JNAME(Q) + JRST CLOO6 + MOVEI T,%PICLI ;IF GET TO HERE, HAVE FOUND USER WITH RIGHT NAMES + TDNN T,MSKST(Q) ;SKIP IF HE HAS CLI INT DISABLED + JRST OPNL11 + IORM T,PIRQC(Q) ;GIVE USER INT + CONO PI,CLKON + JRST CLOO5B + +CLOO6: ADDI Q,LUBLK ;GO TO NEXT USER SLOT + CAMGE Q,USRHI ;SKIP IF ALL EXAMINED + JRST CLOO5A + JRST OPNL11 + +CLO1D: MOVE T,CLUSR(I) + AOJN T,OPNL23 ;FILE LOCKED + AOS (P) + MOVE A,I + PUSHJ P,CLIOTB ;NO TIMING ERROR SINCE CORE JOB WILL PCLSR USR ON + SKIPN B,SRN3(U) ;CORE LINK BEFORE MOVING BUFFER + JRST CLO1D2 + MOVEM B,CLN1(A) + MOVE B,SRN4(U) + MOVEM B,CLN2(A) + JRST LSWPOP ;CLOSW + +CLO1A: MOVE A,UNAME(U) + MOVE B,JNAME(U) + JRST CLO1A1 + +;CORE LINK .IOT SET UP ROUTINE + +CLIOTB: SKIPGE CLRAC(A) ;WAIT IF BUFFER LOCKED BY CORE ALLOCATOR + PUSHJ P,UFLS ;(DO NOT CHANGE ABOVE TO "SKIPGE TT,CLRAC(A)") + HRRZ TT,CLRAC(A) + LDB Q,[IOSA,,IOBFT(TT)] ;GET POINTER TO BUFFER + LSH Q,6 + POPJ P, + + +;CORE LINK .IOT ROUTINE FOR UNIT ASCII INPUT + +CLUAI: PUSHJ P,CLIOTB ;SETUP + MOVSI T,%CAFLS + TDNE T,CLRAC(A) + PUSHJ P,UFLS + SKIPN (Q) ;WAIT TILL CHAR COUNT NON-ZERO + PUSHJ P,UFLS +CLUAI1: MOVE J,3(Q) + ILDB I,J ;GET EOF BIT + JUMPN I,UNIEOF +CLUAIE: ILDB W,1(Q) ;GET CHARACTER + SOS (Q) ;DECREMENT BUF COUNT +CLFAXP: LDB TT,[700,,1(Q)] ;FIX UP POINTERS + CAIN TT,CLBVSP+CLBCHS-1 + PUSHJ P,CLFAX2 ;MAYBE TIME TO RING BUFFER + HLRZ TT,J ;GET BYTE POSITION AND SIZE + CAIN TT,010100 ;IF TO END OF 35-BIT WORD, ADVANCE + IBP J ;TO NEXT WORD (5-BIT BYTES 1 BIT AT A TIME) + MOVEM J,3(Q) + POPJ P, + +UNIEOF: HRROI W,EOFCH + JRST POPJ1 + +CLFAX2: LDB TT,[370500,,1(Q)] ;PICK UP TOP 5 BITS OF BYTE POSITION + JUMPN TT,CPOPJ ;NOT QUITE YET +CLFBX2: MOVEI TT,CLBVSP ;J HAS NEW EOF PNTR + DPB TT,[700,,1(Q)] ;RING CHAR POINTER + MOVEM J,3(Q) + MOVEI J,44 + DPB J,[360600,,1(Q)] + MOVEI TT,CLBVSP+CLBCHS + DPB TT,[700,,3(Q)] ;RING EOF POINTER + DPB J,[360600,,3(Q)] + MOVE J,3(Q) + POPJ P, + +;CORE LINK .IOT ROUTINE FOR UNIT ASCII OUTPUT + +CLUAO: MOVE T,CLRAC(A) + TLNE T,%CAFLS + POPJ P, + PUSHJ P,CLIOTB ;SETUP + MOVEI T,CLBCHS*5-11. + CAMGE T,(Q) ;WAIT TILL THERE IS SPACE IN BUF + PUSHJ P,UFLS + MOVE J,4(Q) + SKIPGE C + SKIPA B,(C) ;GET CHAR FROM EXEC + UMOVE B,(C) ;GET CHAR FROM USER + MOVEI TT,0 + IDPB TT,J ;INDICATE NOT AN EOF + IDPB B,2(Q) ;STORE IN BUF + MOVEI TT,1 ;GET MASK FOR LOW ORDER BIT + ANDCAM TT,@2(Q) ;FLUSH IN CURRENT WORD +CLCWU2: AOS (Q) ;INCREMENT BUF COUNT + MOVEI I,0 ;FAKE OUT EOF TEST + AOJA Q,CLFAXP ;FAKE OUT CLFAXP AND FIX UP POINTERS + + +CLBI: JSP W,WRDBTI ;BLOCK INPUT. + +;CORE LINK .IOT ROUTINE FOR UNIT BINARY INPUT + +CLUBI: PUSHJ P,CLIOTB ;SETUP + MOVSI T,%CAFLS + TDNE T,CLRAC(A) + PUSHJ P,UFLS + MOVEI T,5 + CAMLE T,(Q) ;WAIT TILL A WORD IS AVAILABLE + PUSHJ P,UFLS +CLUBI1: MOVE J,3(Q) + ILDB I,J ;GET EOF BITS + JUMPN I,CLUBIF ;JUMP ON EOF +CLUBIE: ILDB W,1(Q) ;GET WORD +CLCRB2: MOVNI T,5 + ADDB T,(Q) ;DECREMENT COUNT + JUMPGE T,CLFBXP + SETZM (Q) ;CAME FROM CLCLRL WITH PARTIAL WORD IN BUFFER +CLFBXP: JRST CLFAXP + +CLUBIF: TROE I,20 ;SKIP IF EOF NOT ON FIRST CHAR OF WORD + JRST POPJ1 + DPB I,J ;SET EOF ON FIRST CHAR + MOVE J,1(Q) + ILDB W,J ;PICK UP WORD WITH EOF IN MIDDLE + POPJ P, + +;CORE LINK .IOT ROUTINE FOR UNIT BINARY OUTPUT + +CLUBO: MOVE T,CLRAC(A) + TLNE T,%CAFLS + POPJ P, + PUSHJ P,CLIOTB ;SETUP +;CLI: OPEN CALLS HERE TO OUTPUT UNAME AND JNAME. +CLOXO: MOVEI T,CLBCHS*5-11. + CAMGE T,(Q) ;WAIT TILL THERE IS SPACE FOR A WORD + PUSHJ P,UFLS + MOVE J,4(Q) + SKIPGE C + SKIPA B,(C) ;GET WORD FROM EXEC + UMOVE B,(C) ;GET WORD FROM USER + MOVEI TT,0 + IDPB TT,J ;INDICATE NOT AN EOF + IDPB B,2(Q) ;STORE IN BUF +CLCWB2: MOVEI TT,5 + ADDM TT,(Q) ;INCREMENT COUNT + AOJA Q,CLFAXP ;FAKE OUT CLFBXP AND FIX UP POINTERS + + +;CORE LINK .IOT ROUTINE FOR BLOCK OUTPUT + +CLBO: MOVE I,C ;SAVE A POINTER TO USERS BLKO POINTER + XCTR XR,[SKIPL H,(I)] ;PICKUP BLKO POINTER + POPJ P, + SKIPA E,H ;SECOND COPY, ALSO FLAG TO CLBIN +CLBI2: UMOVEM E,(I) ;TO INFORM USER & IN CASE YOU ARE PCLSR'ED + HRRZ C,E + PUSHJ P,CLUBO ;TRANSFER ONE WORD + AOBJN E,CLBI2 ;TRY FOR NEXT +CLBI3: UMOVEM E,(I) ;COUNT EXHAUSTED OR EOF + POPJ P, + +;CORE LINK .CLOSE ROUTINE FOR BINARY OR BLOCK OUTPUT + +CLCLWB: PUSHJ P,CLCWC ;STORE EOF BITS FOR WORD + JRST CLCWU6 ;NO ROOM SO LAST MUST HAVE BEEN EOF HACK SO FLUSH + IBP 2(Q) ;KEEP WORD POINTER IN STEP + PUSHJ P,CLCWB2 ;FIX UP COUNT AND POINTERS +CLCWU6: MOVNI B,1 + DPB B,[222200,,CLUSR(A)] ;OBLITERATE USER INDEX + MOVSI B,%CAFLS + ANDCAM B,CLRAC(A) + JRST LSWPOP ;RELEASE SWITCH + +;CORE LINK .CLOSE ROUTINE FOR UNIT ASCII OUTPUT + +CLCLWU: PUSHJ P,CLCWC ;STORE EOF BIT FOR CHAR + JRST CLCWU6 + MOVEI TT,EOFCH + IDPB TT,2(Q) ;STORE AN EOF CHAR + PUSHJ P,CLCWU2 ;FIX UP COUNT AND POINTERS + SOS Q ;CLCWU2 AOJAS + LDB TT,[360600,,2(Q)] + SOJE TT,CLCWU6 ;JUST FILLED A WHOLE WORD => STOP PADDING. + PUSHJ P,LSWPOP ;ELSE PAD ONCE MORE. + JRST CLCLWU + + +;COMMON SUBROUTINE FOR CORE LINK OUTPUT .CLOSE ROUTINES + +CLCWC: PUSHJ P,SWTL ;LOCK SWITCH (IF SIGN OF CLRAC IS EVER REALLY USED, + CLOSW ;THIS MIGHT CAUSE A DEADLY EMBRACE). + PUSHJ P,CLIOTB ;SETUP + MOVEI T,CLBCHS*5-5. + CAMGE T,(Q) ;WAIT FOR THERE TO BE ROOM + POPJ P, + MOVE J,4(Q) + MOVNI TT,1 + IDPB TT,J ;SET EOF BIT(S) + JRST POPJ1 + +;CORE LINK .CLOSE ROUTINE FOR INPUT + +CLO1D2: SETZM CLSYN(A) ;FREE VARIABLES + HRRZS A,CLRAC(A) ;CORE LINK NO LONGER IN USE + PUSHJ P,BRTN ;RETURN BUFFER TO FREE STATE + JRST LSWPOP + +CLISTA: PUSHJ P,CLIOTB ;CORE LINK INPUT STATUS + SKIPN J,(Q) ;COUNT + TRO D,1_10. ;SYS BUF CAP EMPTY + CAIL J,CLBCHS*5-5 + TRO D,1_9 ;SYS BUF CAP EMPTY + POPJ P, + +CLCLRA: TDZA C,C ;UNIT ASCII +CLCLRB: MOVNI C,1 ;IMAGE OR BLOCK (I.E. WORDS) + PUSHJ P,CLIOTB + PUSHJ P,SWTL + CLOSW +;FLUSH ALL REAL DATA +CLCLRL: SKIPN (Q) ;SKIP IF BUFFER CONTAINS DATA, READ IT UNTIL EOF + JRST CLCLR1 + PUSHJ P,[JUMPE C,CLUAI1 ? JRST CLUBI1] + JRST CLCLRL +CLCLR2: MOVE J,3(Q) ;FOUND AN EOF, FLUSH THE EOF WORD + ILDB I,J + PUSHJ P,[JUMPE C,CLUAIE ? JRST CLUBIE] + MOVE T,1(Q) + TLNE T,760000 + JRST CLCLR2 ;NOT YET TO WORD BOUNDARY + JRST CLCLR3 + +CLCLR1: MOVSI B,%CAFLS + IORM B,CLRAC(A) + PUSH P,A + PUSH P,Q + HLRZ A,CLUSR(A) + PUSHJ P,NJRPCL + PUSHJ P,NJUPCL + POP P,Q + POP P,A +CLCLR3: HLLOS B,CLUSR(A) ;NO LONGER OPEN FOR INPUT + SKIPN (Q) ;IF NO DATA IN BUFFER + AOJE B,CLO1D2 ;AND NOT OPEN FOR OUTPUT, GO FREE THE BUFFER AND VARS + JRST LSWPOP + +SUBTTL LOCK DEVICE + +NLCKCH==:8 ; Should be enough. + +EBLK + +LCKNAM: REPEAT NLCKCH, 0 ; 0 => free lock channel, else contains + ; name of lock held by this channel. +LCKUSR: REPEAT NLCKCH, 0 ; Job that holds the lock. Nothing looks + ; at this currently. +LCKSW: -1 ? 0 ; Prevent more than one user from trying to + ; lock a lock at the same time. +BBLK + +; LCKO is .OPEN routine for LOCK device. First filename is name of lock to +; seize. 0 is illegal. Only opens for output are permitted (some day we +; might allow multiple opens for input). +; +; Bit 1.4 controls what happens if lock is already held: +; 0 => error: %ENAFL +; 1 => Hang until you can seize it +LCKO1: PUSHJ P,LSWPOP ; We lose this time + TLNN C,10 ; 1.4 => HANG MODE + JRST OPNL23 ; FILE LOCKED + MOVE T,A + CAMN T,LCKNAM(I) ; Wait for unlock, then try again + PUSHJ P,UFLS +LCKO: JUMPE A,OPNL11 ; ILLEGAL FILE NAME + PUSHJ P,SWTL ; One potential locker at a time + LCKSW + MOVSI I,-NLCKCH ; Check if it is already locked + CAME A,LCKNAM(I) + AOBJN I,.-1 + JUMPL I,LCKO1 ; Already held + MOVSI I,-NLCKCH ; Search for free lock channel + SKIPE LCKNAM(I) + AOBJN I,.-1 + JUMPGE I,OPNL6 ; DEVICE FULL + HRRZM U,LCKUSR(I) + MOVEM A,LCKNAM(I) + HRLZI T,(I) + HRRI T,DNLCK + MOVEM T,(R) ; Set up channel + JRST LSWPJ1 ; And return + +; .CALL RFNAME returns name of lock: +LCKRCH: MOVE B,LCKNAM(A) + POPJ P, + +; .CLOSE releases the lock: +LCKCL: SETZM LCKNAM(A) + POPJ P, + +SUBTTL COMMON I/O ROUTINES + +;STANDARD DEVICE OPEN + +STDOP1: MOVEI R,R ;ENTRY TO NOT CLOBBER IOCHNM +STDOPN: HLRZ A,(Q) ;LH MASK ON 4.9-3.2 OF LH OPEN WRD + AND D,A ;RH POINTER TO ..USR,..USE PAIR + ROT D,-1 ;FOLLOWING WORDS CONTAIN LIST FOR ALL MASKED STATES + ADDI D,(Q) ;LH MSKED STATE =0, RH =1, IOTTB ENTRY NUMBERS + HRRZ A,1(D) + SKIPL D + HLRZ A,1(D) + JUMPE A,OPNL12 ;MODE NOT AVAIL + HRRZ E,(Q) + CONO PI,CLKOFF + CAME U,(E) + SKIPGE 1(E) + AOSA 1(E) + JRST OPNL10 ;DEVICE NOT AVAIL + MOVEM U,(E) + HLL A,C + JRST OPNSLT + +OPSLD1: ANDI D,1 ;ENTRY TO USE BOTTOM BIT OF AC D +OPSLD3: ANDI D,3 ;ENTRY TO USE BOTTOM TWO BIT OF AC D + MOVE C,D +OPSLC3: ANDI C,3 ;ENTRY TO USE BOTTOM TWO BITS OF AC C +OPSLC7: ANDI C,7 ;ENTRY TO USE BOTTOM THREE BITS OF AC C + ROT C,-1 + ADDI C,(Q) + HRR A,(C) + SKIPL C + HLR A,(C) +OPNSLT: MOVEM A,(R) ;SET USERS IOCHNM + JRST CLKOJ1 + +;BLOCK OUTPUT TO CHARACTER DEVICE +;ADR OF CHR ROUTINE IN E +; THAT ROUTINE MUST NOT CLOBBER C, D, E, OR TT +;C POINTS TO AOBJN POINTER IN USER SPACE +;MUSTN'T CLOBBER J (TTY OUTPUT ASSUMES). + +NBTOCH: XCTR XRW,[MOVES D,(C)] ;CHECK WRITEABILITY OF AOBJN PTR + LDB TT,[410300,,D] ;USE HIGH 3 BITS OF USER PNTR AS CHR CNT + CAIGE TT,3 + POPJ P, ;USER TRYING TO XFER >32K FLUSH + SKIPA TT,BTOCHT-3(TT) ;PICK UP APPROPRIATE BYTE PTR (WORD IN W) +NBTO1: UMOVEM D,(C) ;UPDATE USER'S AOBJN PTR + UMOVE W,(D) ;FETCH CURRENT WORD FROM USER + ILDB A,TT ;FETCH CURRENT CHARACTER + PUSHJ P,(E) ;SEND TO DEVICE + ADD D,[700000,,] ;UPDATE PTR + TLNE D,500000 + JRST NBTO1 ;GO TO NEXT CHR + MOVE TT,BTOCHT+4 + ADD D,[500001,,1] ;INCR TO NEXT WORD + JUMPL D,NBTO1 + UMOVEM D,(C) ;COUNTED OUT, UPDATE FINAL TIME & RETURN + POPJ P, + +BTOCHT: REPEAT 5,<44-<4-.RPCNT>*7>_14+700,,W + +;BLOCK INPUT FROM CHARACTER DEVICE +;E AND C SET UP LIKE NBTOCH +;INTERNALLY LH OF E USED FOR FLAGS: +; 4.9 EOF FLAG (SIGN) +; 4.8 => JUST RETURN WITHOUT ERROR IF AT BEGINNING OF WORD, +; OTHERWISE IGNORE BIT. +; 4.7 => RETURN WITHOUT ERROR EVEN IF NOT AT BEGINNING OF WORD. + +INBTCH: HRRZS E ;CLEAR GARBAGE IN LH + XCTR XRW,[MOVES D,(C)] ;SET UP LIKE NBTOCH + LDB TT,[410300,,D] + CAIGE TT,3 + POPJ P, + SKIPA TT,BTOCHT-3(TT) +INBTO1: UMOVEM D,(C) + XCTR XRW,[MOVES (D)] ;CHECK WRITABILITY OF CURRENT WORD + JUMPL E,INBTO2 ;JUMP IF EOF + PUSH P,C + PUSH P,D + PUSH P,TT + PUSH P,R + HLRZ A,(R) + PUSHJ P,(E) ;RETN CHR IN W + JRST .+3 + TLO E,200000 + TLO E,400000 + MOVE I,W + POP P,R + POP P,TT + POP P,D + POP P,C + LDB W,[410300,,D] + TLNN E,100000 + CAIN W,7 ;SKIP IF NOT AT 1ST CHAR. + TLNN E,300000 + JRST INBTO3 + POPJ P, + +INBTO3: UMOVE W,(D) ;PICK UP CURRENT WORD + IDPB I,TT ;INSERT CHARACTER + UMOVEM W,(D) ;PUT WORD BACK + ADD D,[700000,,] + TLNE D,500000 + JRST INBTO1 ;DO ANOTHER CHR THIS WORD + MOVE TT,BTOCHT+4 + ADD D,[500001,,1] ;INCR TO NEXT WD + SKIPL E ;SKIP IF EOF + JUMPL D,INBTO1 + UMOVEM D,(C) ;DONE, UPDATE POINTER AND RETURN + POPJ P, + +INBTO2: MOVEI I,EOFCH ;EOF, STORE EOF CHARACTER + JRST INBTO3 + +;BLOCK IO TO WORD DEVICE +;C POINTS TO AOBJN POINTER IN USER SPACE +;Q POINTS TO WORD HANDLING ROUTINE (POINTER WILL BE IN C) +;MUST NOT CLOBBER Q OR H (PTR ROUTINES DO POPJ2 SOMETIMES) +;WRDBRT CHECKED FOR ON PDL BY TVC ROUTINES + +WRDBT: MOVE H,C + UMOVE C,(H) ;FETCH USER'S AOBJN POINTER + JUMPGE C,CPOPJ + JRST WRDBT3 + +WRDBT2: PUSHJ P,OPBRK +WRDBT3: ANDI C,-1 + PUSHJ P,(Q) +WRDBRT: JRST WRDBT5 ;NO SKIP - WORD XFERRED + SKIPA C,[1,,1] ;1 SKIP - LAST WORD XFERRED + POPJ P, ;2 SKIPS - EOF, NO WORD XFERRED + XCTR XRW,[ADDM C,(H)] + POPJ P, + +WRDBT5: MOVE C,[1,,1] + XCTR XRW,[ADDB C,(H)] + JUMPL C,WRDBT2 + POPJ P, + +;JSP W,WRDBTI TO DO WRDBT FOR A UNIT MODE INPUT ROUTINE SATISFYING NEW +;CALLING CONVENTION FOR THOSE. +WRDBTI: JSP Q,WRDBT + XCTR XRW,[MOVES (C)] + PUSH P,W + PUSHJ P,(W) + JRST WRDBT4 + JRST POPWJ2 + AOS -1(P) +WRDBT4: UMOVEM W,(C) + MOVEI Q,WRDBTI+1 + POP P,W + POPJ P, + +;CHANGED CONVENTIONS: + ;1) EOF IS NO LONGER CHECKED FOR CHARACTER BY CHARACTER. + ; INSTEAD, THE GET-BUFFER ROUTINE SHOULD SET UP THE BYTE COUNT + ; TO A SMALLER VALUE THAN USUAL. + ; AN ATTEMPT TO GET ANOTHER BUFFER AFTER REACHING EOF + ; SHOULD CAUSE THE GET-BUFFER ROUTINE TO SKIP TWICE. + ;2) THE THE BUFFER POINTER IS NOW A B.P. EVEN IN IMAGE MODE. + ; ALSO, THE L.H. OF THE B.P. IS NOT INITTED HERE. + ; IT MUST BE SET UP BY THE OPEN ROUTINE. ALSO, ACCESS ROUTINES + ; FOR DSK MUST KNOW HOW TO SET IT UP. + ; ALSO, THE BUFFER GET ROUTINE SHOULD SET IT UP, + ; INSTEAD OF RETURNING THE BUFFER ADDRESS IN TT. + ;3) THE BYTE SIZE THE FILE IS OPEN ON IS PASSED AS AN ARGUMENT. + ; THIS ROUTINE WORKS FOR ANY CHANNEL BYTE SIZE WITH ANY + ; SIOT BYTE SIZE. + +;GENERAL BLOCK I/O +;RH OF E HAS # BYTES/WORD OF FILE BYTE SIZE. LH OF E HAS B.P. 44NN00. +;RH(C) = ADDR OF COUNT, IN USER MEMORY +;RH(TT) = ADDR OF USER'S B.P. +; ARGUMENTS B -> +;0(B) ADDR OF ACTIVE BUFFER BYTE PTR, 4.9=0 => INPUT, =1 => OUTPUT +;1(B) ADDR OF COUNT OF BYTES REMAINING IN CURRENT BUFFER +;2(B) ROUTINE TO GET NEXT BUFFER. NO SKIP IF NO MEMORY +; OTHERWISE SKIP; BUFFER BYTE COUNT IN @1(B) +; AND BUFFER BYTE POINTER ALREADY SET UP. +; 2 SKIPS => THERE IS NO BUFFER, DUE TO EOF. +; WHEN THIS ROUTINE IS CALLED, E CONTAINS THE +; NUMBER OF BYTES/WORD (GOOD FOR DETERMINING CHANNEL MODE). +;3(B) ROUTINE TO PUT BUFFER (OUTPUT) OR DISCARD (INPUT) +; MAY REACTIVATE CURRENT BUFFER BY SETTING @1(B) TO NONZERO, +; IN WHICH CASE IT SHOULD CONTAIN THE NEW NUMBER OF BYTES. +;4(B) NOT USED +;5(B) IF POSITIVE, INSTRUCTION TO WAIT FOR I/O +; IF NEGATIVE, ROUTINE ASSUMES 2(B) AND 3(B) WILL WAIT + +;RELOADING ROUTINES MUST NOT CLOBBER B,E,A,C,I +;SIOKT CLOBBERS C,D,J,TT, AND WHATEVER THE RELOADING ROUTINES CLOBBER. + +SIOKT: PUSH P,E + PUSH P,TT + PUSH P,C + JRST SIOKT1 + +;NEXT BUFFER + +SIOKNB: PUSHJ P,@3(B) ;"DISCARD" BUFFER + SKIPE J,@1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST SIOKT1 ;IT SPRUNG BACK TO LIFE (WRITE OVER MODE LAST BLOCK OF FILE) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST SIOKF1 ;NO. +SIOKN1: SKIPG 5(B) ;COME HERE IF MUST WAIT FOR SOME REASON OR OTHER + JRST SIOKW1 ;DEVICE CAN'T WAIT SO UDELAY + XCT 5(B) ;DEVICE WAIT +SIOKF: PUSHJ P,UFLS + +SIOKF1: PUSHJ P,@2(B) ;NOW GET NEXT BUFFER + JRST SIOKN1 ;HMM, HAVE TO WAIT + JRST SIOKT1 ;BUFFER HAS BEEN GOT. + JRST POP3J1 ;EOF, TRANSFER IS COMPLETE + +SIOKT1: UMOVE TT,@(P) ;GET COUNT OF BYTES TO TRANSFER + JUMPLE TT,POP3J1 ;COUNT DECREMENTED TO 0; TRANSFER DONE. + SKIPG D,@1(B) ;CHECK AMOUNT LEFT IN BUFFER + JRST SIOKNB ;NEW BUFFER NEEDED + CAMLE TT,D ;AMT OF ROOM LEFT IN CURRENT BUFFER + MOVE TT,D ;TRANSFER ONLY AMT LEFT IN BUFFER + UMOVE J,@-1(P) + IBP J + LDB D,[301400,,J] + MOVE C,@(B) + IBP C ;TO TRANSFER WORD-WISE, BOTH B.P.'S MUST + HRL J,C + LDB C,[301400,,C] + CAIE C,(D) ;HAVE SAME BYTE SIZE, + JRST SIOKS1 + LDB D,[060600,,C] + ANDI C,77 + ADDI C,(D) +;DROPS THROUGH + ;DROPS IN + CAIGE TT,@-2(P) ;THERE MUST BE AT LEAST 1 WORD TO TRANSFER, + JRST SIOKS1 + CAIE C,44 ;AND MUST BE ABOUT TO START THE NEXT WORD. + JRST SIOKSL + PUSH P,TT+1 + IDIVI TT,@-3(P) ;GET # WDS TO BLT + POP P,TT+1 + SKIPGE (B) + MOVSS J ;WRITING, SWAP BLT POINTER + MOVE D,J + ADDI TT,(D) ;1+LAST WORD TO BLT INTO + SKIPGE (B) + JRST SIOKN6 ;JUMP IF WRITING + XCTRI XBW,[BLT D,-1(TT)] ;READING +SIOKN7: MOVEI D,(TT) ;NO FAULT, UPDATE PTR TO LAST WORD + 1 (LIKE KL10) +SIOKN8: SUBM D,J + HRRZS J ;# WDS ACTUALLY XFERRED + ADDM J,@(B) ;INCR BUFFER PNTR + XCTR XRW,[ADDM J,@-1(P)] + IMULI J,@-2(P) + MOVNS J + XCTR XRW,[ADDM J,@(P)] + ADDM J,@1(B) ;DECREMENT COUNT LEFT IN BUFFER + CAIE D,(TT) ;SKIP IF TRANSFERRED ALL WE COULD + PUSHJ P,TPFLT ;TAKE FAULT +SIOKN3: SKIPN @1(B) + PUSHJ P,@3(B) ;BUFFER EXHAUSTED, DISCARD (MAY COME BACK TO LIFE). + JRST SIOKT1 ;TRY AGAIN TO TRANSFER. + +SIOKW1: PUSHJ P,UDELAY + JRST SIOKF1 + +SIOKN6: XCTRI XBR,[BLT D,-1(TT)] ;WRITING TRANSFER + JRST SIOKN7 + JRST SIOKN8 + +;COME HERE FOR SLOW (BYTE AT A TIME) SIOT TO BLOCK MODE DEVICE. +;TT HAS NUMBER OF BYTES TO TRANSFER - IT IS KNOWN THAT THE DEVICE +;CAN SUPPLY THAT MANY FROM ITS CURRENT BUFFER. +SIOKSL: SUBM C,D ;D GETS SIZE; C HAS # BITS REMAINING TO BE HANDLED + IDIV C,D ;C GETS # BYTES TO XFER TILL REACH WORD BOUNDARY. + MOVE TT,C ;XFER THAT MANY, THEN TRY AGAIN, SO WILL USE FAST MODE. +SIOKS1: SKIPL (B) + JRST SIOKSI ;INPUT AND OUTPUT PART HERE + LDB D,[300600,,@(B)] ;BYTE SIZE IN THE BUFFER + MOVEI C,36. + IDIV C,D ;D := # EXTRA BITS AT RIGHT END OF WORD + MOVEI J,1 + LSH J,(D) + SOS J ;J := MASK FOR THEM + UMOVE C,@-1(P) ;GET COPY OF USER'S B.P. FOR SWAPPING IN PAGES. +SIOKS3: IBP C ;IF NOT FOR THESE 2 INSNS, ILDB MIGHT GET PAGE FAULT + UMOVE (C) ;WHICH WOULD CAUSE EXTRA INCREMENTING OF B.P. + XCTR XBYTE,[ILDB D,@-1(P)] ;FETCH NEXT BYTE, + IDPB D,@(B) + MOVE D,@(B) + ANDCAM J,(D) ;TURN OFF EXTRA BITS IN THIS WORD OF BUFFER + SOS @1(B) + XCTR XRW,[SOS @(P)] + SOJG TT,SIOKS3 + JRST SIOKN3 + +SIOKSI: UMOVE C,@-1(P) ;GET COPY OF USER'S B.P., FOR WRITEABILITY TESTING. +SIOKS2: IBP C + XCTR XRW,[MOVES (C)] ;MAKE SURE WE CAN WRITE IN NEXT BYTE. + ILDB D,@(B) ;GET NEXT BYTE FROM DEVICE BUFFER + XCTR XBYTE,[IDPB D,@-1(P)];GIVE IT TO USER. + XCTR XRW,[SOS @(P)] ;UPDATE USER'S COUNT + SOS @1(B) ;AND THE SYSTEM'S COUNT. + SOJG TT,SIOKS2 + JRST SIOKN3 + +;CONVENIENT EXIT ROUTINE FOR BUFFER-GET ROUTINES. +;ASSUMES ADDR OF START OF BUFFER IN TT, +;SIZE (IN WORDS) OF DATA AREA IN J. +;E SHOULD HAVE WHAT IT HAD WHEN SIOKT WAS CALLED. +SIOBGX: IMULI J,(E) +SIOBG1: HLL TT,E +SIOBG2: MOVEM TT,@(B) + MOVEM J,@1(B) + JRST POPJ1 + +;BYTE AT A TIME I/O TO BLOCK MODE DEVICE +;SEE PRECEDING PAGE (SIOKT) FOR COMMENTS ON CALLING SEQUENCE +;EXCEPT: ON INPUT, VALUE RETURNED IN W, AND C,D HAVE NO SIGNIFICANCE; +;ON OUTPUT, RH(C) HAS ADDRESS OF ARG, SIGN(C) SET IFF ADDRESS IS EXEC-MODE, +; AND D HAS NO SIGNIFICANCE. + +CHRKT: SKIPGE (B) + JRST CHRKTO ;WRITING + JRST CHRKTI ;READING + +CHRKTI: SOSGE @1(B) ;DECREMENT ACTIVE CHAR COUNT + JRST CHRKT1 ;GET NEW BUFFER + ILDB W,@(B) ;READ - GET NEXT CHAR + POPJ P, + +CHRKTO: SKIPGE C ;USED WHEN FILLING OUT BLOCK AT CLOSE, AND ELSEWHERE. + SKIPA J,(C) + UMOVE J,(C) ;GET CHAR. FROM USER + SOSGE @1(B) ;DECREMENT ACTIVE CHAR COUNT + JRST CHRKT1 ;GET NEW BUFFER + IDPB J,@(B) ;DEPOSIT IN BUFFER + CAIE E,5 ;SKIP IF ASCII + POPJ P, + MOVEI J,1 + MOVE D,@(B) + ANDCAM J,(D) ;CLEAR EXTRA BIT + POPJ P, + +CHRKT1: AOS @1(B) ;COMPENSATE FOR OVER-SOS + PUSHJ P,@3(B) ;GET RID OF THIS BUFFER + SKIPLE J,@1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST CHRKT ;SPRUNG BACK TO LIFE (LAST BLOCK OF FILE WRITE OVER) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST CHRKF1 ;NO. +CHRKN1: SKIPG 5(B) ;HAVE TO WAIT + JRST [ PUSHJ P,UDELAY + JRST CHRKF1 ] + XCT 5(B) ;DEVICE WAIT + PUSHJ P,UFLS + +CHRKF1: PUSHJ P,@2(B) ;GOBBLE NEW BLOCK + JRST CHRKN1 ;NOT READY, WAIT + JRST CHRKT + CAME E,[444400,,1] + JRST UNIEOF ;READING PAST EOF IN ASCII MODE. + JRST IOCER2 ;READING PAST EOF IN IMAGE MODE. + +;GENERAL BLOCK I/O +;E HAS BPLH,,# BYTES/WORD OF FILE BYTE SIZE - MUST BE 444400,,1 +;RH(C) = ADDR OF AOBJN POINTER +; AND 4.9 => AOBJN PTR IS IN EXEC ADDRESS SPACE, +; 4.8 => BLOCK IT POINTS TO IS IN EXEC ADDRESS SPACE. (INPUT ONLY) +; ARGUMENTS B -> +;0(B) ADDR OF ACTIVE BUFFER BYTE PTR, 4.9=0 => INPUT, =1 => OUTPUT +;1(B) ADDR OF COUNT OF BYTES REMAINING IN CURRENT BUFFER +;2(B) ROUTINE TO GET NEXT BUFFER. NO SKIP IF NO MEMORY +; OTHERWISE SKIP; BUFFER BYTE COUNT IN @1(B) +; AND BUFFER B.P. IN @(B) ALREADY SET UP. +; 2 SKIPS => THERE IS NO BUFFER, DUE TO EOF. +;3(B) ROUTINE TO PUT BUFFER (OUTPUT) OR DISCARD (INPUT) +; MAY REACTIVATE CURRENT BUFFER BY SETTING @1(B) TO NONZERO. +;4(B) NOT USED +;5(B) IF POSITIVE, INSTRUCTION TO WAIT FOR I/O +; IF NEGATIVE, ROUTINE ASSUMES 2(B) AND 3(B) WILL WAIT + +;RELOADING ROUTINES MUST NOT CLOBBER B,E,A,C,I +;BLKT CLOBBERS C,D,J,TT, AND WHATEVER THE RELOADING ROUTINES CLOBBER. + +;CODE IS ON NEXT PAGE + +BLKT: CAME E,[444400,,1] + BUG ;BLKT CALLED ON UNIT ASCII MODE CHANNEL?? + SKIPL C ;SKIP IF POINTER IN USER SPACE + XCTR XRW,[MOVES (C)] ;USER SPACE, MAKE SURE WRITE CYCLE WILL WIN + JRST BLKT1 + +;NEXT BUFFER + +BLKTNB: PUSHJ P,@3(B) ;"DISCARD" BUFFER + SKIPE @1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST BLKT1 ;IT SPRUNG BACK TO LIFE (WRITE OVER MODE LAST BLOCK OF FILE) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST BLKTF1 ;NO. +BLKTN1: SKIPG 5(B) ;COME HERE IF MUST WAIT FOR SOME REASON OR OTHER + JRST BLKTW1 ;DEVICE CAN'T WAIT SO UDELAY + XCT 5(B) ;DEVICE WAIT +BLKTF: PUSHJ P,UFLS + +BLKTF1: PUSHJ P,@2(B) ;NOW GET NEXT BUFFER + JRST BLKTN1 ;HMM, HAVE TO WAIT + JRST BLKT1 + POPJ P, ;EOF, TRANSFER FINISHED + +BLKT1: SKIPGE C ;SET UP FOR TRANSFER + SKIPA J,(C) ;GET EXEC MODE BLOCK .IOT (AOBJN) POINTER + UMOVE J,(C) ;GET USER MODE AOBJN POINTER + JUMPGE J,CPOPJ ;POINTER COUNTED OUT, TRANSFER DONE + SKIPG D,@1(B) ;CHECK AMOUNT LEFT IN BUFFER + JRST BLKTNB ;NEW BUFFER NEEDED + HLRE TT,J + MOVNS TT ;DESIRED SIZE OF BLOCK + CAMLE TT,D ;AMT OF ROOM LEFT IN CURRENT BUFFER + MOVE TT,D ;TRANSFER ONLY AMT LEFT IN BUFFER + MOVE D,@(B) ;CANONICALIZE THE BUFFER B.P. SO RH => NEXT WORD TO XFER + IBP D + HRL J,D ;MERGE WITH USER'S BLOCK ADDR TO GET BLT AC. + SKIPGE (B) + MOVSS J ;WRITING, SWAP BLT POINTER + MOVE D,J + ADDI TT,(D) ;1+LAST WORD TO BLT INTO + TLNE C,200000 + JRST BLKTN9 ;JUMP IF EXEC AOBJN POINTER + SKIPGE (B) + JRST BLKTN6 ;JUMP IF WRITING + XCTRI XBW,[BLT D,-1(TT)] ;READING +BLKTN7: MOVEI D,(TT) ;NO FAULT, UPDATE PTR TO LAST WORD + 1 (LIKE KL10) +BLKTN8: SUBM D,J + HRRZS J ;# WDS ACTUALLY XFERRED + ADDM J,@(B) ;INCR BUFFER PNTR + HRLS J ;PUT # WDS IN BOTH HALVES + JUMPL C,BLKTN3 ;UPDATE AOBJN PTR IN EXEC SPACE + XCTRI XRW,[ADDM J,(C)] ;UPDATE AOBJN PTR IN USER SPACE + JRST .+2 + BUG ;MUMBLE. THIS WAS SUPPOSED TO BE THERE. + +BLKTN4: MOVNI J,(J) + ADDM J,@1(B) ;DECREMENT COUNT LEFT IN BUFFER + CAIE D,(TT) ;SKIP IF TRANSFERRED ALL WE COULD + PUSHJ P,TPFLT ;TAKE FAULT IF ANY + SKIPN @1(B) + PUSHJ P,@3(B) ;BUFFER EXHAUSTED, "DISCARD" + JRST BLKT1 ;GO TRANSFER ANOTHER CHUNK + +BLKTN3: ADDM J,(C) ;UPDATE EXEC AOBJN POINTER + JRST BLKTN4 + +BLKTW1: PUSHJ P,UDELAY + JRST BLKTF1 + +BLKTN6: XCTRI XBR,[BLT D,-1(TT)] ;WRITING TRANSFER + JRST BLKTN7 + JRST BLKTN8 + +BLKTN9: BLT D,-1(TT) ;READING INTO EXEC SPACE + JRST BLKTN7 + +SUBTTL DIRECTORY AND ERR DEVICES + +QMLSTF: MOVEI J,4 ;ENTRY TO GET MASTER 2314 DIRECTORY + JRST LISTF7 + +QLISTF: MOVEI J,3 ;ENTRY FOR 2314 USER DIRECTORY +LISTF7: MOVEI I,0 +LISTFE: PUSHJ P,SWTL ;ENTER HERE FOR ALL KINDS OF DIRECTORIES. + UDCSW + MOVSI TT,-NUDCH +UD1: SKIPGE UDUSR(TT) + JRST UD2 + AOBJN TT,UD1 + PUSHJ P,LSWPOP + PUSHJ P,UDELAY ;DIRECTORY NOT AVAILABLE NOW, WAIT + JRST LISTFE + +UD2: MOVEM J,DSKLST(TT) + MOVEM I,UDUSR(TT) + MOVEM U,UDUIND(TT) + PUSHJ P,LSWPOP + MOVE Q,USYSN1(U) + MOVEM Q,UDSYSN(TT) + JUMPG J,UDIF ;JUMP IF NOT UTAPE DIR. +IFE NUNITS, BUG ;HOW DID UTAPE GET HERE? +IFN NUNITS,[ + CONO PI,CLKOFF + MOVE Q,UDIRO(I) + MOVEM Q,DIRPT(TT) + CONO PI,CLKON + MOVEI J,200 + TRNE D,2 + JRST UDBIN ;IMAGE MODE UTAPE DIR + MOVEI Q,LISTF ;ASCII MODE UTAPE DIR +] +UDIF1: MOVEM Q,DIRPC(TT) + HRL A,TT + JSP Q,OPSLD1 + DIRCHN,,DIRBN + +UDIF: HLRZ Q,UDT-1(J) ;INITIAL COROUTINE PC + HRRZ T,UDT-1(J) ;PLACE TO FINISH OPENING - USUALLY UDIF1. + JRST (T) + +UQL1: HRRZM H,UUDPP(TT) ;2314 MFD (FROM UDIF) + MOVEI J,2000 + TRNE D,2 + JRST QUDBIN + JRST UDIF1 + +UQL1A: PUSHJ P,STMSET ;DISK UFD (FROM UDIF). WE CAN STILL PCLSR, + UDUSR(TT) ;ARRANGE TO GIVE BACK THE DIRECTORY CHANNEL. +UQL1B: PUSH P,TT + PUSHJ P,QUDLK + PUSHJ P,TCALL ;GET A LOW-HALF PAGE TO COPY UFD INTO. + JRST IOMQ ;GET LOW HALF PAGE + JRST UQL1W ;NOT AVAIL NOW + MOVEI T,MU23LS + DPB T,[MUR,,MEMBLT(A)] ;MARK THE PAGE AS A UFD COPY. + LSH A,10. + MOVEM A,DIRPT(TT) + MOVEM A,UUDPP(TT) + HRL A,QSNLCN(H) + HRRI T,2000(A) + BLT A,-1(T) ;COPY UFD + PUSHJ P,QUDULK + PUSHJ P,LSWDEL ;STMSET OF UDUSR. + SKIPG QSNNR(H) + BUG ;WE ALWAYS GET OUR MAN + PUSHJ P,LSWPOP ;SOS QSNNR + POP P,TT + MOVEI J,2000 + TRNE D,2 + JRST UDBIN + JRST UDIF1 + +UQL1W: PUSHJ P,QUDULK + POP P,TT + PUSHJ P,UDELAY + JRST UQL1B + +;LH INITIAL PC RH DISP ADR AT OPEN TIME +UDT: NDLF,,UDIF1 ;NON DIR DEVICE + UCL1,,UDIF1 ;CORE LINK + UQL2,,UQL1A ;2314 UFD + QMLS1,,UQL1 ;2314 MFD + ERR1,,ERR2 ;ERR DEVICE + TTYFLD,,UDIF1 ;TTY DIR + TTYF99,,UDIF1 ;COR DIR (LAST LINE OF TTY DIR) +UDTLN==.-UDT + +QUDBIN: HRRZ T,QMDRO + MOVEM T,DIRPT(TT) +UDBIN: MOVEM J,NUM(TT) ;DOESN'T USE DIRPC THIS PC + MOVEM J,ENDT(TT) + MOVEI J,444400 + HRLM J,DIRPT(TT) + HRL A,TT + JSP Q,OPSLD1 + NDATAI,,NBLKI + +UTDCLS: MOVE B,DSKLST(A) + CAIN B,3 + JRST UTDCL1 +UTDCLX: SETOM UDUSR(A) + POPJ P, + +UTDCL1: PUSH P,A + MOVE A,UUDPP(A) + LSH A,-10. + PUSHJ P,MEMR + POP P,A + JRST UTDCLX + +;UNIT MODE IOT ON DIR DEVICE COMES HERE (RETURN CHAR IN W) +DIRCH: SETOM SRN3(U) ;SAY WE WANT ONLY 1 CHARACTER. + PUSHJ P,DIRCHR + HRRZ W,I + CAIN W,^C + JRST UNIEOF + POPJ P, + +;BLOCK MODE IOT ON DIR DEVICE. +DIRB: JSP Q,WRDBT ;PUSHJ'S TO .+1 FOR EACH WORD. +DIRB1: XCTR XRW,[MOVES (C)] ;MAKE SURE WE CAN WRITE. + PUSH P,C + PUSH P,H + SETZM SRN3(U) ;SAY WE WANT A WHOLE WORD OF CHARS. + PUSHJ P,DIRCHR + POP P,H + POP P,C + LDB Q,[350700,,SRN3(U)] + CAIN Q,^C ;IF THE WORD STARTS WITH ^C, + JRST POPJ2 ;IT IS EOF; DON'T RETURN IT, UNHANG IOT. + MOVE Q,SRN3(U) + UMOVEM Q,(C) + MOVEI Q,DIRB1 ;FASTER THAN PUSHING AND POPPING Q. + POPJ P, ;RETURN INTO WRDBT + + SKIPA T,[SIOKT] +DDATAI: MOVEI T,CHRKTI ;UNIT IMAGE INPUT FROM DIRECTORY. + CAIA +DBLKI: MOVEI T,BLKT ;BLOCK IMAGE INPUT FROM DIRECTORY + MOVE E,[444400,,1] + JSP B,(T) ;TO BLKT, SIOKT, OR CHRKTI + DIRPT(A) + NUM(A) + POPJ2 ;EOF IF TRY TO GET ANOTHER BUFFER + CPOPJ ;BUFFER DISCARD ROUTINE + BUG + SKIPA + +;ERR DEVICE AND ERROR MESSAGE TABLES +; ERR DEVICE WORKS MUCH LIKE DIR DEVICE + +ERRO: MOVEI J,5 + JRST LISTF7 + +ERR2: SOJE A,ERR21 ;LAST ERRONEOUS CHANNEL + SOJE A,ERR22 ;CHANNEL SPECIFIED IN B + SOJE A,ERR23 ;STATUS WORD IN B + SOJE A,ERR24 ;.CALL ERROR ARG IN B + SETOM UDUSR(TT) + JRST OPNL11 + +ERR21: LDB B,[BCHPTR] +ERR22: ANDI B,17 + ADDI B,IOCHST(U) + SKIPA B,(B) +ERR24: MOVSS B +ERR23: MOVEM B,UUDPP(TT) + JRST UDIF1 + +CORO: PUSHJ P,FLDRCK + JRST OPNL11 + MOVEI J,7 + JRST LISTF7 + +ERR1: SKIPN I,UUDPP(A) + JRST ERR3 + LDB B,[220600,,UUDPP(A)] ;OPEN LOSS FIELD + JUMPE B,ERR1B + CAIL B,NERMES+1 + MOVEI B,NERMES+1 + MOVE TT,ERMST1-1(B) + JSP B,MESPNT +ERR1B: LDB B,[300300,,UUDPP(A)] ;IDS ERROR FIELD + JUMPE B,ERR1C + MOVE TT,ERMST2-1(B) + JSP B,MESPNT +ERR1C: LDB B,[330400,,UUDPP(A)] ;IOCERR FIELD + JUMPE B,UCL7 + CAIL B,MIOTER + CAIL B,NERM1+MIOTER + MOVEI B,NERM1+MIOTER + MOVE TT,ERMST3-MIOTER(B) + JSP B,MESPNT + JRST UCL7 + +ERR3: MOVEI TT,[ASCIZ /ISE0 +/] + JSP B,MESPNT + JRST UCL7 + +;LISP ASSUMES THAT NO "ERR" DEVICE MESSAGE WILL EVER CONTAIN +; !, #, ^, OR LOWER CASE LETTERS. PLEASE MAINTAIN THIS STATE +; GLS (GUY STEELE) + +ERMST1: [ASCIZ /NO SUCH DEVICE +/] + [ASCIZ /WRONG DIRECTION +/] + [ASCIZ /TOO MANY TRANSLATIONS +/] + [ASCIZ /FILE NOT FOUND +/] + [ASCIZ /DIRECTORY FULL +/] + [ASCIZ /DEVICE FULL +/] + [ASCIZ /DEVICE NOT READY +/] + [ASCIZ /DEVICE NOT AVAILABLE +/] + [ASCIZ /ILLEGAL FILE NAME +/] + [ASCIZ /MODE NOT AVAILABLE +/] + [ASCIZ /FILE ALREADY EXISTS +/] + [ASCIZ /BAD CHANNEL NUMBER +/] + [ASCIZ /TOO MANY ARGUMENTS (CALL) +/] + [ASCIZ /PACK NOT MOUNTED +/] + [ASCIZ /DIRECTORY NOT AVAIL +/] + [ASCIZ /NON-EXISTENT DIRECTORY +/] + [ASCIZ /LOCAL DEVICE ONLY +/] + [ASCIZ /SELF-CONTRADICTORY OPEN +/] + [ASCIZ /FILE LOCKED +/] + [ASCIZ /M.F.D. FULL +/] + [ASCIZ /DEVICE NOT ASSIGNABLE TO THIS PROCESSOR +/] + [ASCIZ /DEVICE WRITE-LOCKED +/] + [ASCIZ /LINK DEPTH EXCEEDED +/] + [ASCIZ /TOO FEW ARGUMENTS (CALL) +/] + [ASCIZ /CAN'T MODIFY JOB +/] + [ASCIZ /CAN'T GET THAT ACCESS TO PAGE +/] + [ASCIZ /MEANINGLESS ARGS +/] + [ASCIZ /WRONG TYPE DEVICE +/] + [ASCIZ /NO SUCH JOB +/] + [ASCIZ /VALID CLEAR OR STORED SET +/] + [ASCIZ /NO CORE AVAILABLE +/] + [ASCIZ /NOT TOP LEVEL +/] + [ASCIZ /OTHER END OF PIPELINE GONE OR NOT OPEN +/] + [ASCIZ /JOB GONE OR GOING AWAY +/] + [ASCIZ /ILLEGAL SYSTEM CALL NAME +/] + [ASCIZ /CHANNEL NOT OPEN +/] + [ASCIZ /INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL +/] + [ASCIZ /UNRECOGNIZABLE FILE +/] + [ASCIZ /LINK TO NON-EXISTENT FILE +/] +IFN .-ERMST1-NOPNLS,.ERR WRONG TABLE LENGTH +;ADD NEW MESSAGES HERE + +IFN 0,[ A CLASSIFICATION OF OPEN-LOSS MESSAGES + +FULL - NO CORE (MMP FULL) + DIR NOT AVAIL (DIR CHNL TABLE FULL) + DEVICE FULL + DIR FULL + MFD FULL + INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL + +NO SUCH - DEVICE, FILE, JOB, DIRECTORY, PAGE (CAN'T GET ACCESS) + ILLEGAL SYSTEM CALL NAME + +ALREADY ONE SUCH - FILE (FILE ALREADY EXISTS - RENAME) + +WRITING - CAN'T MODIFY JOB + DEVICE WRITE-LOCKED + WRONG DIRECTION + MODE NOT AVAILABLE + CAN'T GET ACCESS TO PAGE + +ARGS (THE PARAMETERS ARE RIDICULOUS) - + SELF-CONTRADICTORY OPEN COMMAND + ILLEGAL FILE NAME + BAD CHANNEL NUMBER + TOO FEW ARGS + TOO MANY ARGS + MEANINGLESS ARGS + CHANNEL NOT OPEN + +NOT AVAILABLE (IT EXISTS BUT YOU CAN'T USE IT) - + DEVICE NOT READY + DEVICE NOT AVAILABLE + NOT ASSIGNABLE TO THIS PROCESSOR + LOCAL DEVICE + PACK NOT MOUNTED + FILE LOCKED + OTHER END OF PIPELINE GONE + JOB GONE OR GOING AWAY + +DEPTH - LINK DEPTH EXCEEDED + TOO MANY TRANSLATIONS + +OTHER - NOT TOP LEVEL + VALID CLEAR OR STORED SET +] + +NERMES==.-ERMST1 + [ASCIZ /OPEN TYPE NOT DETERMINED +/] + +ERMST2: [ASCIZ /IDS ILLEGAL SCOPE MODE +/] + [ASCIZ /IDS SCOPE HUNG +/] + [ASCIZ /MORE THAN 1K SCOPE BUFFER +/] + [ASCIZ /IDS MEM PROTECT +/] + [ASCIZ /IDS ILLEGAL SCOPE OP +/] + [ASCIZ /IDS MEM PROTECT ON PDL PNTR +/] + [ASCIZ /IDS ILLEGAL PARAMETER SET +/] + +ERMST3: [ASCIZ /DEVICE HUNG OR REPORTING NON-DATA ERROR +/] + [ASCIZ /END OF FILE +/] + [ASCIZ /NON-RECOVERABLE DATA ERROR +/] + [ASCIZ /NON-EXISTENT SUB DEVICE +/] + [ASCIZ /OVER IOPOP +/] + [ASCIZ /OVER IOPUSH +/] + [ASCIZ /USR OP CHNL DOES NOT HAVE USR OPEN +/] + [ASCIZ /CHNL NOT OPEN +/] + [ASCIZ /DEVICE FULL +/] + [ASCIZ /CHNL IN ILLEGAL MODE ON IOT +/] + [ASCIZ /ILLEGAL CHR AFTER CNTRL P ON TTY DISPLAY +/] + [ASCIZ /DIRECTORY FULL +/] + [ASCIZ /DIRECTORY'S ALLOCATION EXHAUSTED +/] +;INSERT NEW MESSAGES HERE +NERM1==.-ERMST3 + [ASCIZ /IOT OR OPR TYPE NOT DETERMINED +/] + +;DIRECTORY LISTING ROUTINES + +UQL3C: SKIPA I,["*] +UQL3: MOVEI I,"- + PUSHJ P,OUTC + JRST UQL3A + +UQL2: MOVEI TT,[MNAME ASCIZ /, /] ;GENERATE USER DIRECTORY + JSP B,MESPNT + MOVE I,UUDPP(A) + MOVEI J,UDNAME(I) + JSP B,SIXTYC ;SEND DIRECTORY NAME + MOVEI TT,[ASCIZ / +FREE BLOCKS /] + JSP B,MESPNT + MOVSI E,-NQS +UQL2A: SKIPGE QACT(E) + JRST UQL3 ;UNIT NOT ENGAGED + MOVE J,QTUTO(E) + TLNE J,40000 + JRST UQL3C ;TUT FOR UNIT NOT IN + MOVEI I,"# + PUSHJ P,OUTC + MOVE TT,QPKID(E) + JSP B,GDPT ;AND # + MOVEI I,"= + PUSHJ P,OUTC + MOVE TT,QSFT(E) + JSP B,GDPT ;AND # FREE TRACKS +UQL3A: PUSHJ P,OUTCS + AOBJN E,UQL2A + JSP B,MESPCR + MOVE I,UUDPP(A) + MOVEM I,DIRPT(A) + MOVE Q,UDNAMP(I) +UQL4: CAIL Q,2000 + JRST UCL7 + HRLI I,440600+Q + HLLM I,DIRPT(A) + +UQLP: ADDI Q,2 ;MOVE PNTR TO 3RD WRD OF FILE DESC + MOVE I,@DIRPT(A) + MOVEI TT,[ASCIZ /* /] ;DELETED OR BEING WITTEN + TLNN I,UNIGFL + MOVEI TT,[ASCIZ / /] + JSP B,MESPNT + MOVE I,@DIRPT(A) + TLNE I,UNLINK + JRST UQLL1 ;LINK + LDB TT,[UNPKN+@DIRPT(A)] + JSP B,GDPT ;PRINT PACK # + LDB TT,[UNPKN+@DIRPT(A)] + CAIG TT,9 +UQLL2: PUSHJ P,OUTCS + PUSHJ P,OUTCS + SUBI Q,2 ;BACK TO FIRST WD + JSP B,SIXTYA ;SEND FIRST FILE NAME + JSP B,SIXTYB ;AND SECOND (AOSES Q) + PUSHJ P,OUTCS + AOS Q ;SET Q TO POINT TO FILE DESC PNTR + LDB E,[UNDSCP+@DIRPT(A)] ;PICK UP FILE DESC PNTR + IDIVI E,UFDBPW + ADDI E,UDDESC ;COMPUTE WORD ADDRESS + MOVE I,@DIRPT(A) ;SAVE STATUS WORD + EXCH E,Q ;MOVE INTO PNTR + MOVE TT,QBTBLI(TT) + TLO TT,Q + HLLM TT,DIRPT(A) ;SET UP DIRPT TO POINT TO FILE DESC + TLNE I,UNLINK + JRST QLL1 ;LINK + MOVEI TT,0 +UQL5: JSP B,UQL5R ;CHECK IF ABOUT TO INCREMENT OFF WORD + ILDB I,DIRPT(A) + JUMPE I,UQL5A ;STOP + CAILE I,UDTKMX + JRST UQL5B + ADD TT,I + JRST UQL5 + +UQLL1: MOVEI I,"L + PUSHJ P,OUTC + JRST UQLL2 + +QLL1: CLEARM ENDT(A) ;CNTS TO 3 FOR USER NAME AND 2 FILE NAMES +QLL3: CLEARM NUM(A) ;CHR CNTR +QLLIST: JSP B,UQL5R + ILDB I,DIRPT(A) + JUMPE I,QLL4 + CAIN I,'; + JRST QLL2 + CAIN I,': + JRST QLL5 +QLL5A: ADDI I,40 + PUSHJ P,OUTC + AOS I,NUM(A) + CAIGE I,6 + JRST QLLIST +QLL2: PUSHJ P,OUTCS + AOS I,ENDT(A) + CAIGE I,3 + JRST QLL3 +QLL4: JSP B,MESPCR + MOVEI Q,3(E) ;ADVANCE Q + JRST UQL4 + +QLL5: JSP B,UQL5R + ILDB I,DIRPT(A) + JRST QLL5A + +UQL5R: MOVE I,DIRPT(A) ;CHECK IF ABOUT TO ILDB OFF WORD + TLNE I,770000 + JRST (B) ;NO + MOVEI I,440600+Q ;YES INCREMENT Q INSTEAD + HRLM I,DIRPT(A) + AOJA Q,(B) + +UQL5B: CAIGE I,UDWPH ;PLACE HOLDER + AOJA TT,UQL5 ;SKIP AND TAKE + CAIN I,UDWPH + JRST UQL5 ;NULL + REPEAT NXLBYT,[JSP B,UQL5R + IBP DIRPT(A) +] + AOJA TT,UQL5 ;SPACE OVER 2ND HALF OF LOAD ADDRESS + +UQL5A: JSP B,GDPT ;TYPE OUT # BLOCKS + PUSHJ P,OUTCS + MOVE Q,E ;FILE POINTER + MOVEI I,"! + SKIPGE B,@DIRPT(A) ;SKIP ON NOT DUMPED + MOVEI I,40 + PUSHJ P,OUTC ;HAS NOT BEEN BACKED UP + MOVEI I,"$ + TLNN B,UNREAP ;SKIP ON DON'T-REAP + MOVEI I,40 + PUSHJ P,OUTC + MOVEI Q,1(E) + LDB E,[1200,,DIRPT(A)] + JUMPN E,[JRST 4,.] + MOVE TT,@DIRPT(A) + AOJE TT,UQL5C ;DATE NOT KNOWN + LDB TT,[UNMON+@DIRPT(A)] + JSP B,GDPT ;TYPE MONTH + MOVEI I,"/ + PUSHJ P,OUTC + LDB TT,[UNDAY+@DIRPT(A)] + JSP B,GDPT ;TYPE DAY + MOVEI I,"/ + PUSHJ P,OUTC + LDB TT,[UNYRB+@DIRPT(A)] + JSP B,GDPT ;TYPE YEAR + PUSHJ P,OUTCS + HRRZ TT,@DIRPT(A) + IDIVI TT,60.*60.*2 + MOVE E,I + JSP B,G2DPT + MOVEI I,": + PUSHJ P,OUTC + MOVE TT,E + IDIVI TT,60.*2 + MOVE E,I + JSP B,G2DPT + MOVEI I,": + PUSHJ P,OUTC + MOVE TT,E + LSH TT,-1 + JSP B,G2DPT +UQL5D: JSP B,MESPCR + ADDI Q,2 ;ADVANCE Q + JRST UQL4 + +UQL5C: MOVEI I,"- + PUSHJ P,OUTC + JRST UQL5D + +;GENERATE MFD LISTING +QMLS1: CONO PI,CLKOFF + MOVE Q,QMDRO + HRLI Q,440600+Q + MOVEM Q,DIRPT(A) + MOVE Q,MDNAMP(Q) + CONO PI,CLKON +QMLS2: CAIL Q,1777 + JRST UCL7 + SKIPN @DIRPT(A) + JRST QMLS3 + JSP B,SIXTYA + JSP B,MESPCR +QMLS3: ADDI Q,LMNBLK + JRST QMLS2 + +;DIRECTORY LISTING ROUTINES FOR UTAPE + +IFN NUNITS,[ +LISTF: MOVEI Q,220600+Q + HRLM Q,DIRPT(A) + MOVEI Q,177 + MOVE TT,@DIRPT(A) + AOJE TT,LISTF1 + JSP B,SIXTYP +LISTF1: MOVEI TT,[ASCIZ / +FREE FILES /] + JSP B,MESPNT + MOVSI Q,-23. + MOVEI TT,0 +LISTF4: SKIPE @DIRPT(A) + AOJA Q,LISTF8 + AOS Q + SKIPN @DIRPT(A) + AOS TT +LISTF8: AOBJN Q,LISTF4 + JSP B,GDPT + MOVEI TT,[ASCIZ / FREE BLOCKS /] + JSP B,MESPNT + SETZB J,TT + JSP B,BLKPNT +LISTD2: JSP B,MESPCR + MOVSI Q,-23. +LISTF2: MOVEI I,440600+Q + HRLM I,DIRPT(A) + MOVE I,@DIRPT(A) + JUMPE I,LISTF5 +LISTF6: PUSHJ P,OUTCS + JSP B,SIXTYA + JSP B,SIXTYB + PUSHJ P,OUTCS + MOVEI J,1(Q) + JSP B,BLKPNN +LISTD4: JSP B,MESPCR +LISTF3: AOBJN Q,LISTF2 +];END IFN NUNITS + +UCL7: MOVEI I,14 ;END DIR WITH FORMFEED AND EOF CHARS + PUSHJ P,OUTC + HRROI I,EOFCH + JRST .-2 + +IFN NUNITS, LISTF5: AOJA Q,LISTF3 + +; DIRECTORY LISTING ROUTINES FOR MISC. DEVICES + CORE LINK + +NDLF: MOVEI TT,[ASCIZ / +NON-DIRECTORY DEVICE/] + JSP B,MESPNT + JRST UCL7 + +;DIRECTORY OF CORE LINK DEVICE +UCL1: MOVSI Q,-NCLCH +UCL6: SKIPN CLSYN(Q) + JRST UCL5A + MOVEI J,CLSYN(Q) + JSP B,SIXTYC + MOVEI J,CLN1(Q) + JSP B,SIXTYC + MOVEI J,CLN2(Q) + JSP B,SIXTYC + HLRE B,CLUSR(Q) + AOJE B,UCL2 + MOVEI J,UNAME-1(B) + MOVEM B,NUM(A) + JSP B,SIXTYC + MOVE B,NUM(A) + MOVEI J,JNAME-1(B) + JSP B,SIXTYC +UCL3: MOVEI TT,[ASCIZ /->/] + JSP B,MESPNT + HRRE B,CLUSR(Q) + AOJE B,UCL4 + MOVEI J,UNAME-1(B) + MOVEM B,NUM(A) + JSP B,SIXTYC + MOVE B,NUM(A) + MOVEI J,JNAME-1(B) + JSP B,SIXTYC +UCL5: JSP B,MESPCR +UCL5A: AOBJN Q,UCL6 + JRST UCL7 + +UCL4: MOVEI B,UCL5 + JRST .+2 +UCL2: MOVEI B,UCL3 + MOVEI J,[SIXBIT /CLOSED/] +SIXTYC: HRLI J,440600 + MOVEM J,DIRPT(A) + PUSHJ P,OUTCS + JRST SIXTYP + +; DIRECTORY LISTING ROUTINES FOR TTY + +TTYFLD: MOVEI TT,[ASCIZ / +TTY UNAME JNAME CORE TOTAL IDX +/] + JSP B,MESPNT + MOVSI Q,-NCT +TTYF1: HRRE E,TTYSTS(Q) + AOJE E,TTYF5 ;JUMP IF NOT IN USE + MOVE E,TTYSTS(Q) + MOVEI I,"T ;TTY + TLNN E,%TSCNS + MOVEI I,"D ;"DEVICE" + PUSHJ P,OUTC + HRRZ TT,Q + JSP B,G2OPT + HRRZS E +TTYF11: MOVEI J,UNAME(E) + JSP B,SIXTYC + MOVEI J,JNAME(E) + JSP B,SIXTYC + PUSHJ P,OUTCS + MOVE TT,NMPGS(E) + JSP B,G4SDPT + PUSHJ P,OUTCS + PUSHJ P,OUTCS + MOVEM E,DIRPT(A) + MOVE E,UTMPTR(E) + SETZB B,TT +TTYF3: SKIPE UNAME(B) + CAME E,UTMPTR(B) + JRST TTYF4 + ADD TT,NMPGS(B) +TTYF4: ADDI B,LUBLK + CAMGE B,USRHI + JRST TTYF3 + JSP B,G4SDPT + PUSHJ P,OUTCS + PUSHJ P,OUTCS + HRRZ TT,DIRPT(A) + SKIPL SUPPRO(TT) + JRST [ HRRZ TT,SUPPRO(TT) ? JRST .-1 ] + IDIVI TT,LUBLK + JSP B,GOPT + JSP B,MESPCR +TTYF5: AOBJN Q,TTYF1 +TTYF99: MOVEI TT,[ASCIZ /FREE CORE /] + JSP B,MESPNT + MOVE TT,MEMFR + SUB TT,NCBCOM + JSP B,GDPT + MOVEI TT,[ASCIZ / OUT /] + JSP B,MESPNT + MOVE TT,NPGSWO + JSP B,GDPT + JSP B,MESPCR + JRST UCL7 + +SIXTYB: AOS Q +SIXTYA: PUSHJ P,OUTCS + MOVEI I,440600+Q + HRLM I,DIRPT(A) + +SIXTYP: ILDB I,DIRPT(A) + ADDI I,40 + PUSHJ P,OUTC + MOVE I,DIRPT(A) + TLNE I,770000 + JRST SIXTYP + JRST (B) + +MESP3S: SKIPA TT,[[ASCIZ / /]] +MESPCR: MOVEI TT,[ASCIZ / +/] +MESPNT: HRLI TT,440700 + MOVEM TT,NUM(A) + ILDB I,NUM(A) + JUMPE I,(B) + PUSHJ P,OUTC + JRST .-3 + +OUTCS: MOVEI I,40 +OUTC: SKIPL TT,SRN3(U) ;IF WANT 1 CHAR, RETURN WITH IT, SAVING ACS. + JRST OUTC1 ;IF WANT WHOLE WORD, SEE IF WORD IS FULL. +OUTC2: MOVEM E,SAVE(A) + MOVEM Q,SAVQ(A) + MOVEM B,SAVB(A) + POP P,DIRPC(A) + POPJ P, + +OUTC1: LSH TT,6 + ADDI TT,(I) ;MERGE THIS CHAR (IN I) INTO WORD BEING ACCUMULATED. + LSH TT,1 + MOVEM TT,SRN3(U) + TLNE TT,774000 ;IF THE WORD IS FULL, RETURN TO DIRB. + JRST OUTC2 + POPJ P, ;ELSE POPJ FROM OUTC, TO GET MORE CHARS. + +;NUMERIC PRINTOUT ROUTINES FOR FILE DIRECTORIES. +;ALL CALLED WITH JSP B,. ALL TAKE ARG IN TT. + +;PRINT NUMBER IN TT IN DECIMAL, RIGHT-ADJUSTED IN FOUR COLUMNS. +G4SDPT: CAIL TT,1000. + JRST GDPT ;IF IT NEEDS 4 DIGITS, JUST PRINT IT. + MOVEM TT,NUM(A) + CAIL TT,100. ;ELSE FIGURE OUT HOW MANY LEADING SPACES ARE NEEDED + JRST G4SDP1 + CAIL TT,10. + JRST G4SDP2 + PUSHJ P,OUTCS ;AND PRINT THAT MANY. +G4SDP2: PUSHJ P,OUTCS +G4SDP1: PUSHJ P,OUTCS + MOVE TT,NUM(A) + JRST GDPT + +;PRINT CONTENTS OF TT AS TWO OCTAL DIGITS. +G2OPT: IDIVI TT,8 + JRST G2DPT2 + +;PRINT CONTENTS OF TT AS THREE DECIMAL DIGITS. +G3DPT: IDIVI TT,100. + MOVEM I,NUM(A) + MOVEI I,"0(TT) + PUSHJ P,OUTC + MOVE TT,NUM(A) +G2DPT: IDIVI TT,10. +G2DPT2: MOVEM I,NUM(A) + MOVEI I,"0(TT) + PUSHJ P,OUTC + MOVE I,NUM(A) + ADDI I,"0 + PUSHJ P,OUTC + JRST (B) + +;PRINT ARG IN TT IN DECIMAL USING AS MANY DIGITS AS IT NEEDS. +GDPT: HRLI B,10. + JRST GDPT0 + +;PRINT ARG IN TT IN OCTAL USING AS MANY DIGITS AS NECESSARY. +GOPT: HRLI B,8 +GDPT0: MOVSS B + SETZM ENDT(A) + MOVEM TT,NUM(A) +GDPT1: PUSH P,Q + MOVE Q,TT + IDIVI TT,(B) + CAME TT,ENDT(A) + JRST .-3 + MOVEM Q,ENDT(A) + POP P,Q + ADDI I,"0 + PUSHJ P,OUTC + MOVE TT,NUM(A) + CAME TT,ENDT(A) + JRST GDPT1 + MOVSS B + JRST (B) + +;ROUTINE TO CALL A DIRECTORY COROUTINE +DIRCHR: MOVE E,SAVE(A) + MOVE B,SAVB(A) + MOVE Q,SAVQ(A) + JRST @DIRPC(A) + +IFN NUNITS,[ +BLKPNA: MOVEI J,1(I) + LSH J,-1 + JRST BLKPNT+1 + +BLKPNN: LSH J,-1 +BLKPNT: MOVEI TT,0 + MOVEI I,56 +BLKPN2: MOVEI E,440500+I + HRLM E,DIRPT(A) +BLKPN1: ILDB E,DIRPT(A) + CAIN E,37 + JRST BLKPN3 + CAMN E,J + AOS TT + HLRZ E,DIRPT(A) + TRNE E,760000 + JRST BLKPN1 + AOJA I,BLKPN2 +BLKPN3: JUMPE J,GDPT + MOVSI I,-23. +BLKPN4: MOVE E,@DIRPT(A) + AOS I + CAMN J,@DIRPT(A) + JUMPE E,BLKPNA + AOBJN I,BLKPN4 + JRST GDPT +];NUNITS +EBLK + +UDUSR: REPEAT NUDCH,-1 ;-1 => FREE, ELSE UTAPE # IF UTAPE DIR, ELSE 0. +UDUIND: BLOCK NUDCH ;IF DIR CHANNEL IN USE, HOLDS JOB # OF JOB USING IT. + +IRPS X,,DIRPC:DIRPT:NUM:ENDT:SAVB:SAVQ:UDSYSN:UUDPP:SAVE: +X: REPEAT NUDCH,-1 + TERMIN +UDCSW: -1 + 0 + +DSKLST: BLOCK NUDCH ;0 LISTING UTAPE 1 NON-DIR DEVICE + ;2 CORE LINK 3 2311 +;NO BBLK SINCE VARIABLES ON NEXT PAGE + +SUBTTL UTC LEVEL INTERRUPT + +;NO EBLK SINCE VARIABLES ON PREVIOUS PAGE + +UTCPDP: -LUTCP,,UTCP-1 ;UTC-LEVEL PDL +UTCP: BLOCK LUTCP +UTACS: BLOCK 20 ;UTC-LEVEL AC SAVE + +IFE KS10P,[ ; On the KS10 we can take advantage of the Unibus interrupt + ; vectoring scheme to dispatch quicker, so this code was + ; reorganized somewhat. +UTCBRK: 0 +BBLK +IFN KL10P,[ + CONSO PI,1_<7-UTCCHN> + JRST 4,. ;HARDWARE BUG ALLEGEDLY FIXED +] + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP +IFN NUNITS,[ +IFE NEWDTP,[ + CONSZ DC,6 + JRST PIPOS ;HAS CHNL >1 +PIPX: +] +IFN NEWDTP,[ + SKIPGE CUINT + JRST UTCB0 +] +];IFN NUNITS +IFN IMPP,[ ; See if it's an IMP interface interrupt +IFN KAIMP,[ + CONI IMP,TT + LDB A,[000300,,TT] + CAIE A,NETCHN + JRST UTCB2 + TRNE TT,IMPLW+IMPHER+IMPERR+IMPOD+IMPID +] +IFN DMIMP,[ + CONI FI,TT + TRNN TT,70 ;CHECK PIA + JRST UTCB2 ;DO NOT PROCESS IF NO PIA + TRNE TT,FILW+FIDOWN+FIWASD+FIOD+FIID +] + JRST IMPINT +UTCB2:] ;IFN IMPP + +IFN DC10P,[ + CONI DC0,TT + TRNE TT,DPIRQC + JRST QINT +] +IFE KA10P, CONO PI,020000+200_<-UTCCHN> ;BAG-BITING DEC LOSERS +IFN T300P,[ + SKIPE DSCDON + JRST T3INT +];T300P +IFN RP10P,[ + CONI DPC,TT + TRNE TT,7 + TRNN TT,10 ;IF BIT IS ON IT IS INTERRUPTING - LET QINT HAVE IT + SKIPGE QGTBZY + JRST QINT +] +IFN RH10P,[ + CONI DSK,TT + TRNN TT,%HIDON+%HIATN ;INTERRUPTING HARDWARILY + SKIPGE QGTBZY ;INTERRUPTING SOFTWARILY + JRST QINT +] +IFN TM10P,[ + CONI MTC,A + CONI MTS,C + LDB TT,[030300,,A] + CAIE TT,MTCCHN + JRST UTCBK2 + TRNN C,100 ;IF NOT JOB DONE + TRZ C,30000 ; THEN DON'T BELIEVE PAR ERR OF EOF + TRNN A,400 ;IF NEXT UNIT NOT ENABLED + TRZ C,2 ;THEN TURN OFF NEXT UNIT FLAG + TRNE C,440302 ; UNIT HUNG, ILLEGAL, BAD TAPE (UGH), LOAD NEXT UNIT, JOB DONE + JRST MGHBRK +UTCBK2: SKIPN MGTBZY ; SOFT WARE CALL + JRST MGSBRK +] +IFN NUNITS, JRST UTCB0 + +POPRET: +IFN NUNITS,[ + MOVE A,TIME + MOVEM A,LUTOTM +] +DSKEX: +IMPEX: +MGEX: MOVSI U,UTACS + BLT U,U + JRST 12,@UTCBRK + +] ;IFE KS10P + +IFN KS10P,[ + +UTCBRK: 0 ; Still EBLK'ed from previous page... +BBLK + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP + CONO PI,020000+200_<-UTCCHN> ;BAG-BITING DEC LOSERS +IFN KSIMP,[ + AOSN IMPBZY ;-1 if IMP wants a jump-start + PUSHJ P,IMPINT +] +IFN RH11P,[ + SKIPGE QGTBZY + JRST QINT +] ;RH11P +IFN TM03S,[ + SKIPN MGTBZY + JRST MGSBRK +] +IMPEX: +MGEX: +DSKEX: MOVSI U,UTACS + BLT U,U + JRST 12,@UTCBRK + +;;; Interrupt routines that are directly dispatched to by the KS10/Unibus +;;; interrupt kludge should do JSR UTCSAV as their very first instruction. +;;; The word before the JSR is expected to contain the interrupted PC. +;;; They should then exit through DSKEX just like everybody else. + +EBLK +UTCSAV: 0 +BBLK + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP + MOVE U,UTCSAV + MOVE TT,-2(U) + MOVEM TT,UTCBRK + JRST (U) + +] ;KS10P + +$INSRT SYSJOB ;SYSTEM JOB AND RELATED STUFF + + +SUBTTL DCHNTB AND DCHNTC + +EBLK +CHSPUR: BLOCK 8 ;NUM OF SPURIOUS INTS PER CH (ZERO = DCHK) +BBLK + +IFE KS10P,[ ; KS10 doesn't even pretend to have devices. + +;***** DCHNTB ***** +;4.9 = KNOWN DEVICE +;4.8 = HAS PIA 2 +;4.7-4.4 PIA 2 SHIFT +;4.3-4.1 PIA 2 ACTIVE VALUE +;3.9 = PIA 2 MAY BE ZERO +;3.8 = HAS PIA 1 +;3.7-3.4 PIA 1 SHIFT +;3.3-3.1 PIA 1 ACTIVE VALUE +;2.9 = PIA 1 MAY BE ZERO +;2.8 = ALLOW USER DATAI, BLKI +;2.7 DATAO, BLKO +;2.6 CONI, CONSO, CONSZ +;2.5 CONO +;2.4 SPECIAL KL10 DEVICE, BLKI/BLKO ARE DATAI/DATAO TO A SECOND DEVICE REGISTER +;1.6-1.1=N, IF NON ZERO: IGNORE DEV UNLESS CONI BIT N-1 IS ON + ;(IF DSDEV PRESENT) + +;***** DCHNTC ***** +;4.9 = SUSPICIOUS DEVICE +;4.8 = FOUND CLOBBERED +;4.7 = SUSPECTED OF CAUSING SPURIOUS INTS +;4.6-4.4 = CHANNEL CAUSING INTS ON +;3.9-3.1 = SUSPICION COUNT +;2.9-1.1 = CONI + +DCHNTB: +IFE KL10P,[ + 400200+APRCHN,,240000 ;0 APR + SETZ ;4 PI +] +IFN KL10P,[ + 400200+APRCHN,,250000 ;0 APR (ALLOW DATAI, "BLKI", CONI) + SETZ 010000 ;4 PI (ALLOW NOTHING) +] + +DEFINE DCHENT D,W +LOC DCHNTB+D_-2 + W + TERMIN + +IFN KL10P,[ + DCHENT PAG,SETZ 240000 ;ALLOW DATAI, CONI, BUT NOT "BLKI" + DCHENT CCA,SETZ ;ALLOW NOTHING +;XCTR of some of the instructions for these devices fails to relocate +;the address to user space, due to bugs in the hardware. Flush 'em. +; DCHENT TIM,SETZ 250000 ;ALLOW DATAI, "BLKI", CONI +; DCHENT MTR,[400201,,250000] ;INTERVAL TIMER PIA=1. ALLOW DI,BI,CI + DCHENT TIM,SETZ ;20 ALLOW NOTHING + DCHENT MTR,SETZ ;24 ALLOW NOTHING + DCHENT 30,SETZ ;30 RESERVED +] +IFN DSDP, DCHENT DSDEV,[REPEAT 2,400200+DSDCHN,,440000] ;20,24 +IFN DL10P,[ DCHENT DLB,SETZ 240000 ;60 DL10 + DCHENT DLC,[400200+TTYCHN,,240000] ;64 DL10 +] +IFN STKP, DCHENT STK,[400200+LPTCHN,,440000] ;70 STK +IFN PTRP, DCHENT PTP,[400200+PCHCHN,,440000] ;100 PTP +IFN PTRP, DCHENT PTR,[400200+PTRCHN,,440000] ;104 PTR +IFN NOTYS, DCHENT TTY,[400200+TTYCHN,,40000] ;120 TTY +IFN OLPTP, DCHENT OLPT,[400200+LPTCHN,,440000] ;124 OLPT +IFN 340P, DCHENT DIS,[630600+DISCHN+SDCHN_9,,440001] ;130 DIS +IFN E.SP, DCHENT DIS,[400200+DISCHN,,440000] ;130 E&S +IFN KL10P, DCHENT DTE,[400200+IFE PDCLKP,[APRCHN].ELSE [TTYCHN],,240000] ;200 DTE20 +IFN RP10P, DCHENT DPC,[400200+DSKCHN,,440000] ;250 DPC +IFN RH10P, DCHENT DSK,[400200+DSKCHN,,040000] ;270 RH10 +IFN NUNITS,[ +IFE NEWDTP,[ + DCHENT DC,[400000,,440000] ;200 DC + DCHENT UTC,[400200+UTCCHN,,440000] ;210 UTC + DCHENT UTS,[SETZ 40000] ;214 UTS +] +IFN NEWDTP,[ + DCHENT DTC,[630600+UTCCHN+DCCHN_9.,,440000] ;320 + DCHENT DTS,[SETZ 40000] ;324 +] +] ;END OF IFN NUNITS +IFN TM10P,[ + DCHENT MTC,[400230+MTCCHN,,440001] ;340 MTC + DCHENT MTS,[SETZ 40001] ;344 MTS +] +IFN MTYP, DCHENT MTY,[400200+TTYCHN,,40000] ;400 MORTON BOX + ;420 SPACEWAR CONSOLES +IFN DMIMP, DCHENT FI,[400230+NETCHN,,400000] ;424 DM IMP HARDWARE +IFN NDAP, DCHENT 454,[400200,,760000] ;454 D/A +IFN KAIMP, DCHENT IMP,[400000,,400001] ;460 AI-KA/ML-KA/MC-KL IMP + ; HARDWARE THIS SAYS IMP + ; HAS NO PIA BECAUSE IT + ; CHANGES +IFN NLPTP, DCHENT NLPT,[400200+LPTCHN,,440000] ;464 NEW LPT +IFN CH10P, DCHENT CHX,[400200+CHXCHN,,040000] ;470 CHAOSNET +IFE KL10P, DCHENT 500,[400000,,240000] ;500 ML-KA, DM CALENDAR; AI-KA R CLK +IFN KL10P&PDCLKP,DCHENT 500,[400200+APRCHN,,240000] ;500 MC-KL F CLK +IFN ARMP, DCHENT TIPDEV,[400200+TIPBCH,,440000] ;504 ARM TIP BREAK +IFE MCOND AIKA, DCHENT 510,[400000,,360000] ;510 ANOTHER D/A?? + ;DOES ANYONE KNOW WHAT DEVICE 510 IS?? +IFN RBTCP, DCHENT RBTCON,[400200+TABCHN,,440001] ;514 ROBOT CONSOLE +IFN ARMP, DCHENT 564,[400200,,440000] ;564 ARM TACTILE SENSE +IFN OMXP, DCHENT OMPX,[400200+OMPCHN,,440001] ;570 OMX +IFN IMXP, DCHENT MPX,[SETZ 40001] ;574 IMX +;Comment this out since the AI-KA one is no longer on the bus +;IFN TK10P, DCHENT NTY,[400200+TTYCHN,,40000] ;600 NTY +IFN NTYP, DCHENT NTY,[400200+NTYCHN,,40000] ; NTY FOR 11 KLUDGE +IFN DPKPP, DCHENT DPK,[400200+TTYCHN,,40000] ;604 DATAPOINT KLUDGE +IFN DC10P,[ + DCHENT DC0,[400200+DSKCHN,,40000] ;610 DC0 + DCHENT DC1,[400000,,] ;614 DC1 +] +IFN VIDP, DCHENT NVDX,[REPEAT 4,400200+NVDCHN,,440001] ;620-634 BAT +IFN PLTP, DCHENT PLT,[400200+PLTCHN,,440000] ;654 PLT + DCHENT 704,[400000,,440000] ;704 ??? +IFN HCLKP,[ + DCHENT CLK1,[400200,,240000] ;710 CLK1 + DCHENT CLK2,[SETZ 40000] ;714 CLK2 +] +LOC DCHNTB+127. +EBLK +DCHNTC: BLOCK 128. +DCACS: BLOCK 20 ;SAVE ACS +CCSDEV: 0 ;+ => SOME SUSPICIOUS DEVICES +BBLK + +DCHK: 0 ;TO CALL FROM DDT + MOVEM 17,DCACS+17 + MOVEI 17,DCACS + BLT 17,DCACS+16 + MOVEI J,0 + JSP E,SPUR + SKIPN W + AOS DCHK + MOVEI 17,DCACS + BLT 17,17 + JRST @DCHK + +;CHECK FOR CLOBBERED DEVS, CALL WITH JSP E, +CHECK: JSP H,DCSTUP +CHECK1: SKIPL TT,DCHNTB(I) + JRST CHECK4 ;UNKNOWN DEVICE +IFN DSDP,[ + TRNN TT,77 + JRST CHECK2 + ANDI TT,77 + JSP H,DCCONI + LSH B,-1(TT) + JUMPGE B,CHECK4 + MOVE TT,DCHNTB(I) +] +CHECK2: JSP H,DCCONI + TLNN TT,200 ;SKIP IF PI TO TEST + JRST CHECK4 + LDB T,[250400,,TT] ;GET SKIP + MOVEI Q,7 + LSH Q,(T) + AND B,Q + LDB Q,[220300,,TT] ;GET CHANNEL + LSH Q,(T) + CAME B,Q + JRST CHECK5 +CHECK3: LSH TT,-9 ;SHIFT TO PIA2 + JRST CHECK2 + +CHECK5: JUMPN B,CHECKL ;JUMP IF NONZERO AND WRONG + TRNE TT,400000 ;SKIP IF CAN NOT BE ZERO + JRST CHECK3 ;ZERO OK + JRST CHECKL + +CHECK4: ADD A,[400,,] ;INCREMENT DEVICE CODE + AOBJN I,CHECK1 +SPURCX: SKIPE C + BUG PAUSE,[BITS ],OCT,C,[MAY BE STUCK ON IN I/O BUS] + MOVSI T,SCLCK5 + SKIPE W ;SKIP IF NO TROUBLE DETECTED + IORM T,SUPCOR + JRST (E) + +DCSTUP: MOVE A,[CONI B] ;SET UP + MOVEI W,0 + MOVNI C,1 + MOVSI I,-128. + JRST (H) + +DCCONI: XCT A + AND C,B + SKIPL DCHNTC(I) ;SKIP IF DEVICE ALREADY SUSPICIOUS,SAVES FIRST SUSPICIOUS + HRRM B,DCHNTC(I) ;STORE AWAY CONI + JRST (H) + +CHECKL: JSP H,DCSAOS + MOVSI T,600000 ;CLOB + IORM T,DCHNTC(I) + JRST CHECK3 + +DCSAOS: MOVE D,A ;MAKE A CONO + TDZ D,[40,,-1] + SKIPL T,DCHNTB(I) ;SKIP IF KNOWN DEV + JRST DCSAS2 ;JUST RESET UNKNOWN TO ZERO + TLNE T,200000 ;SKIP IF NO PIA2 + TLNE T,400 ;SKIP IF PIA2 CAN NOT BE ZERO + JRST DCSAS1 + LDB TT,[330300,,T] ;GET PIA2 + LDB T,[360400,,T] ;GET PIA2 SHIFT + LSH TT,(T) + IOR D,TT ;ADD CORRECT CANNEL TO CONO + MOVE T,DCHNTB(I) ;SKIP IF NO PIA1 +DCSAS1: TLNE T,200 ;SKIP IF PIA1 CANNOT BE ZERO + TRNE T,400000 + JRST DCSAS2 + LDB TT,[220300,,T] ;GET P1A 1 + LDB T,[250400,,T] ;GET PIA 1 SHIFT + LSH TT,(T) ;OR IN PIA 1 + IOR D,TT ;ZAP +DCSAS2: XCT D + HLRZ T,DCHNTC(I) + TLNN T,300000 + AOS W ;THIS MAY BE THE CAUSE OF OUR TROUBLES + ANDI T,777 + AOS T + AOS CCSDEV + CAILE T,777 + SOJA T,[JRST 4,.+1] ;LOSEY LOSEY + DPB T,[221100,,DCHNTC(I)] + JRST (H) + +;CHANNEL IN J SPURIOUS INTERRUPT ON, CALL WITH JSP E, +SPUR: SKIPL J + CAIL J,10 + JRST 4,SPUR1 + AOS U,CHSPUR(J) +SPUR1: MOVE U,E + JSP E,CHECK + MOVE E,U + JSP H,DCSTUP +SPUR2: SKIPGE TT,DCHNTB(I) + JRST SPUR4 + JSP H,DCCONI + JUMPGE B,SPUR4 + JSP H,DCSAOS + MOVSI T,500000 + IORM T,DCHNTC(I) + DPB J,[360300,,DCHNTC(I)] +SPUR4: ADD A,[400,,] + AOBJN I,SPUR2 + JRST SPURCX + +] ;IFE KS10P + +IFN KS10P,[ + +SUBTTL KS10 UNIBUS + +DEFINE UBINT VEC,-REST +.VEC.== +IFN .VEC.&3, .ERR Bogus interrupt vector: VEC +.VEC.==.VEC./4 +IFL .VEC.-.MIN., .MIN.==.VEC. +IFG .VEC.-.MAX., .MAX.==.VEC. +IF2,[ +LOC .BAS.+.VEC. + REST +];IF2 +TERMIN + +NUBIDV==0 + +DEFINE UBIDV VEC +.VEC.== +CONC [UB]\NUBIDV,NM==:<.UBA.,,.VEC.> +CONC [UBINT .VEC., JSR UB]\NUBIDV,BK +NUBIDV==NUBIDV+1 +TERMIN + +;;; +;;; Interrupt table for Unibus Q. +;;; +UBAQIT: +.UBA.==UBAQ +.MIN.==777777 +.MAX.==0 +IF2, .BAS.==UBAQIB + +UBINT PHVEC, JSR DSKBRK ; RH11 FOR DISK + +UBAQIB==:UBAQIT-.MIN. +LOC UBAQIB+.MAX.+1 + +;;; +;;; Interrupt table for Unibus I. +;;; +UBAIIT: +.UBA.==UBAI +.MIN.==777777 +.MAX.==0 +IF2, .BAS.==UBAIIB + +IFE TM03S, UBIDV 224 ; Tape +UBIDV 300 ; NI1010 In +UBIDV 304 ; NI1010 Out +IFL DZ11NB-4,[ +REPEAT 4-DZ11NB,[ +UBIDV 340+<10*> ; DZ In +UBIDV 344+<10*> ; DZ Out +]] + +IFN TM03S,[ +UBINT %TMVEC, JSR MGHBRK ;RH11 FOR TAPE +] + +REPEAT DZ11NB,[ +UBINT 340+<10*.RPCNT>, CONC JSR DZ,\.RPCNT,RB ; DZ receive +UBINT 344+<10*.RPCNT>, CONC JSR DZ,\.RPCNT,XB ; DZ transmit +];REPEAT DZ11NB + +IFN KSIMP,[ +UBINT %LHVEC, JSR IMPIBK ;IMP Input side break +UBINT %LHVEC+4, JSR IMPOBK ;IMP output side break +] + +IFN CH11P,[ +UBINT 270, JSR CHXBKH ; Usual Chaosnet vector +UBINT 230, JSR CHXBKH ; Except some interrupt here instead +];CH11P + +UBAIIB==:UBAIIT-.MIN. +LOC UBAIIB+.MAX.+1 + +;;; Assignment of pages in Unibus pager for DMA devices. +;;; All of the Q UBA is statically assigned. The lower half of the I +;;; UBA is statically assigned, while slots in the upper half of the I UBA +;;; are assigned dynamically by the UBAASL routine and freed by the +;;; UBAFSL routine below. +;;; +;;; Note that static pages are 2000 PDP-10 words long (ITS sized) rather +;;; than 1000 (DEC sized). Each page here thus occupies -two- locations in +;;; the Unibus pager. There are 32. such pages on the Q Unibus and 16. +;;; such pages on the I unibus. +;;; +;;; Slots handed out by UBAASL are good for mapping 1000 PDP-10 words +;;; (one DEC page, and coincidentally the size of a network buffer). +;;; The number obtained from UBAASL is a direct index into the UBA +;;; paging RAM, and will range from 32. to 63. +;;; +;;; This two different page size thing is all a mess and I should fix it +;;; sometime. +;;; +;;; Unibus Q: +QUBPG==:5 ; Chosen at random. + +;;; Unibus I: + +;;; Static pages +IFN TM03S,[ +IUTPG==:5 ;Magtape IO page. well, 5 worked last time +] + +IFN KSIMP,[ +IUIMPG==:6 ;IMP Data transfer page +] + +;;; Dynamic pages + +EBLK +UBAIFS: 777777777760 ;Slot map, bit on if free +BBLK + +; Allocate a UBA I slot +; Return +1, A/ slot index + +UBAASL: PUSH P,B + CONO PI,PIOFF + MOVE A,UBAIFS + JFFO A,UBASL1 + CONO PI,PION + POP P,B ;Clean up for no good reason + BUG HALT,[Out of UBA slots] + +UBASL1: MOVNS B + MOVSI A,400000 + LSH A,B ;A/ bit to snarf + ANDCAM A,UBAIFS + CONO PI,PION + MOVN A,B + ADDI A,32. ;First dynamic slot + POP P,B + POPJ P, + +; Deallocate the UBA slot in A +; A/ UBA index to free. Bashes A,TT +UBAFSL: CAIL A,32. + CAIL A,64. + BUG HALT,[Bad UBA index],OCT,A ;Paranoid for now + MOVEI A,-32.(A) + MOVNS A + MOVSI TT,400000 + LSH TT,A + IORM TT,UBAIFS + POPJ P, + +SUBTTL UBI DEVICE + +UBIDVS:: +REPEAT NUBIDV,[ +EBLK + 0 ; Bit in -7(I) + -1 ; User or -1 in -6(I) + 0 ; Count in -5(I) + 0 ; Saved I in -4(I) +CONC UB,\.RPCNT,BK: + 0 +BBLK + MOVEM I,.-2 + JSP I,UBIBRK +CONC UB,\.RPCNT,DV: + JRST 12,@ + CONC UB,\.RPCNT,NM ; Name in 1(I) +IFE .RPCNT, LUBIDV==:.-UBIDVS +];REPEAT NUBIDV + +UBINAM==:1 +UBISVI==:-4 +UBICNT==:-5 +UBIUSR==:-6 +UBIBIT==:-7 + +UBIBRK: AOS UBICNT(I) + EXCH U,UBIUSR(I) + JUMPL U,UBIBK9 + EXCH T,UBIBIT(I) + TDNE T,MSKST2(U) + IORM T,IFPIR(U) + EXCH T,UBIBIT(I) +UBIBK9: EXCH U,UBIUSR(I) + HRLI I,UBISVI(I) + JRA I,(I) + +EBLK +UBISW: -1 ? 0 +BBLK + +; .OPEN +UBIO: MOVEI T,NUBIDV + SKIPA I,[UB0DV] +UBIO1: MOVEI I,LUBIDV(I) + CAME A,UBINAM(I) + SOJG T,UBIO1 + JUMPLE T,OPNL4 ; FILE NOT FOUND + PUSHJ P,SWTL + UBISW + SKIPL UBIUSR(I) + JRST OPNL23 ; FILE LOCKED + MOVEI T,(R) + SUBI T,IOCHNM(U) + MOVE T,CHNBIT(T) + MOVEM T,UBIBIT(I) + HRRZM U,UBIUSR(I) + HRLZI T,(I) + HRRI T,DNUBI + MOVEM T,(R) + JRST LSWPJ1 + +; .IOPUSH/.IOPOP +UBIIOP: HLRZ A,(R) + JUMPE I,UBIOP7 + SUBI R,IOCHNM(U) + SKIPA R,CHNBIT(R) +UBIOP7: SETZI R, + MOVEM R,UBIBIT(A) + POPJ P, + +; .CALL WHYINT +UBIWHY: MOVE B,UBICNT(A) + MOVEI A,%WYUBI + JRST POPJ1 + +; .CALL RFNAME +UBIRCH: MOVE B,UBINAM(A) + POPJ P, + +; .CLOSE +UBICL: SETOM UBIUSR(A) + POPJ P, + +] ;KS10P + +SUBTTL OVERHEAD METERING ROUTINE + +IFN KL10P,[ + +EBLK +;TABLE OF OVERHEAD REGIONS. ENTRY IS SIXBITNAME,,PC ? COUNT + 0 ;COUNTS STUFF BEFORE FIRST OVHMTR MACRO +OVHTBL: OVHTAB + 'USR,,-1 + 0 ;COUNTS USER-MODE PC'S +LOVHTB==.-OVHTBL + +;COME HERE ON PI CHANNEL 1 EVERY 39 MILLISECONDS +OVHSVA: 0 +OVHSVB: 0 +OVHBRK: 0 +BBLK + CONO TIM,060000+3900. ;CLEAR DONE + EXCH T,OVHBRK ;GET PC INTERRUPTED OUT OF + TLNE T,%PSUSR ;ONLY METER IF EXEC MODE + JRST OVHBRX + MOVEM A,OVHSVA + MOVEM B,OVHSVB + MOVSI A,-LOVHTB +OVHBR1: HRRZ B,OVHTBL(A) + AOBJN A,.+1 ;2-WORD ENTRIES + CAIG B,(T) ;SKIP IF PC LIES IN PREVIOUS REGION + AOBJN A,OVHBR1 + SKIPGE A ;IN CASE T = 777777 + AOS OVHTBL-2(A) ;AOS PREVIOUS REGION'S COUNT + MOVE B,OVHSVB + SKIPA A,OVHSVA +OVHBRX: AOS OVHTBL+LOVHTB-1 ;AOS COUNT OF USER-MODE PC's + EXCH T,OVHBRK + JRST 12,@OVHBRK +];KL10P + +IFN KS10P,[ +RDPCST=DATAI 14, ;INSTRUCTIONS FOR PC SAMPLING TABLE +WRPCST=DATAO 14, + +;TABLE OF OVERHEAD REGIONS. ENTRY IS PC,,SIXBITNAME +OVHTB1: 0,,'LOW ;LOWER FENCE + OVHTAB + 377777,,'USR ;UPPER FENCE +LOVHTB==.-OVHTB1 +REPEAT <1_<36.-<.LZ >>>-LOVHTB, 377777,,-1 ;PAD TO POWER OF TWO SIZE + +EBLK + +OVHTB2: BLOCK LOVHTB ;CORRESPONDING COUNTS (LAST IS FOR USER MODE) + +OVHCNT: 28. ;COUNTER TO SLOW THINGS DOWN TO CUT OVERHEAD + +LOVHPC==100 ;64 SAMPLES SHOULD BE ENOUGH +OVHPCS: BLOCK LOVHPC + +BBLK + +;CALCULATE OVERHEAD USING PC SAMPLE TABLE +;CLOBBERS A,B,C +OVHCLK: SOSL OVHCNT ;TIME TO DO IT YET? + JRST OVHCL9 ;NO, IGNORE THESE SAMPLES + MOVEI A,28. ;SEE ONLY ONE SAMPLE OUT OF EVERY 29 ON AVERAGE + MOVEM A,OVHCNT ;SO TIME SPENT IN THIS ROUTINE IS NOT EXCESSIVE + RDPCST C ;SEE HOW FULL THE PC SAMPLING TABLE IS + HRLOI C,-OVHPCS-1(C) + EQVI C,OVHPCS ;AOBJN POINTER TO SAMPLES ACTUALLY TAKEN + JUMPGE C,OVHCL9 ;NONE + CAMGE C,[-LOVHPC,,OVHPCS] + JRST OVHCL9 ;BOGUS AOBJN POINTER, MAYBE PCST NOT TURNED ON +OVHCL1: MOVE A,(C) ;NEXT SAMPLED PC + TLNE A,%PSUSR ;ONLY SEARCH TABLE IF EXEC MODE + JRST OVHCL8 ;ALL USER MODE PC'S ARE COUNTED IN LAST BUCKET + HRLO A,A ;-1 IN RH IS GREATER THAN ANY SIXBIT + MOVEI B,1_<35.-<.LZ >> ;HALF THE SIZE OF THE TABLE +REPEAT <36.-<.LZ >>,[ ;LOG SEARCH + CAMG A,OVHTB1(B) ;NOT CAMGE BECAUSE OF PADDING AT END + SUBI B,1_<35.-.RPCNT-<.LZ >> + ADDI B,1_<34.-.RPCNT-<.LZ >> +] + LOC .-1 ;OPTIMIZE OUT ADDI B,0 + AOSA OVHTB2(B) +OVHCL8: AOS OVHTB2+LOVHTB-1 + AOBJN C,OVHCL1 +OVHCL9: WRPCST [-LOVHPC,,OVHPCS] ;TURN ON / RESTART PC SAMPLING + POPJ P, +];KS10P + +;HERE IS A TABLE OF REGISTERED 3-LETTER OVERHEAD REGION CODES + +;ALC - ALLOCATE CORE PAGE FRAME +;CHx - CHAOSNET STUFF (VARIOUS VALUES OF x) +;FLT - MISCELLANEOUS FAULTS +;IMP - ARPANET INTERRUPT (NOT STYNET) +;LOW - LOW CORE, BEFORE FIRST OVHMTR MACRO & PCS IN UPPER HALF OF EXEC SPACE +;NET - ALL NETWORKS, ALL PI LEVELS, NOT OTHERWISE ACCOUNTED FOR +;PGF - PAGE FAULT +;PPI - PPIUM +;QIN - DISK INTERRUPT LOW LEVEL +;QSC - DISK INTERRUPT HIGH LEVEL, DISK SCHEDULER +;SC1 - SCHEDULER 1 - ENTRY +;SC2 - SCHEDULER 2 - SEARCH +;SC3 - SCHEDULER 3 - EXIT +;SC4 - SCHEDULER 4 - UNSWAPBLOCK +;SLW - SLOW CLOCK +;SWF - SWAP FIND NEW USER (SWAPOUT SCHEDULER) +;SWP - SWAP PAGE +;SWS - SWAP SCHEDULER +;SWU - SWAP USER +;TTI - TTY INPUT INTERRUPT LEVEL +;TTO - TTY OUTPUT INTERRUPT LEVEL +;TTY - MISC TTY CODE +;USR - USER MODE +;UUO - UUO LEVEL, MISCELLANEOUS ROUTINES, AND TOTAL MISCELLANY +;WS - WORKING SET & SWAP-BLOCK ENTRY CODE + +SUBTTL PC LSR TEST FEATURE + +;CALLED BY PCLT MACRO +;WHICH ASSEMBLES +;SKIPE PCLDBM +;PUSHJ P,PCLTST + +PCLTST: PUSH P,U + MOVE U,PCLIDX + MOVEM U,PCLHT + MOVE U,USER + CAME U,PCLUSR + JRST POPUJ +PCLX: CAIA ;PATCH IN OTHER CHECKS (SHOULD JRST POPUJ TO IGNORE) + MOVE U,USER ;PATCH ROUTINE MAY CLOBBER U + AOSN PCLNXT + JRST PCLT1 ;FOUND PLACE, CAUSE PCLSR + HRRZ U,-1(P) + CAME U,PCLL + JRST POPUJ ;NOT MARK (NOT AT RIGHT LOCN) + HRRO U,USER ;4.9 U FLAG +PCLT1: PUSH P,A ;COMPUTE HASH ADR OF RETURNS ON PDL + PUSH P,B + PUSH P,C + HRREI A,-USRSTG(P) + JUMPL A,PCLT1A ;SYS JOB'S PDL? + IDIVI A,LUBLK + IMULI A,LUBLK + MOVEI A,USRPDL(A) ;GET START OF USERS PDL IN A +PCLT3: HRRZ B,(A) + JUMPE B,PCLT2 + CAIL B,HSYSCD + JRST PCLT2 + HLRZ C,-1(B) + TRZ C,37 + CAIE C,(PUSHJ P,) + JRST PCLT2 + XOR B,PCLHT + ROT B,1 + MOVEM B,PCLHT +PCLT2: CAIGE A,-2-3(P) + AOJA A,PCLT3 + MOVE A,PCLHT ;COMPUTED HASH + JUMPGE U,PCLT4 ;GOING TO PCLSR HERE, STORE HASH AS MARK FOR NEXT TIME + CAME A,PCLHSH + JRST PCLT5 + SKIPGE PCLDBM + JRST PCLT6 ;IN HOLD MODE, PCLSR HERE + SETOM PCLNXT ;FOUND MARK, PCLSR NEXT TIME +PCLT5: POP P,C + POP P,B + POP P,A + JRST POPUJ + +PCLT4: MOVEM A,PCLHSH ;STORE HASH FOR NEXT TIME + HRRZ A,-3-1(P) + MOVEM A,PCLL +PCLT6: CONO PI,CLKOFF + MOVE B,PCLDBM + MOVEI A,%PIC.Z + CAIN B,1 ;DON'T ^Z. + IORM A,PIRQC(U) + POP P,C + POP P,B + POP P,A + POP P,U + JRST PCLME + + PUSHJ P,PCLME1 +PCLME: PUSHJ P,UFLS + JRST 4,. + +PCLME1: PUSHJ P,PCLSR + JFCL + JRST POPJ1 + +PCLT1A: TRNE U,-1 + JRST 4,. + JRST 4,. ;TEMP MODIFY END CHECK IF WANT TO WIN FOR SYS JOB + +SUBTTL ILLUO NON-RELEVANT SYSTEM CALLS +IFE E.SP,[ + ADSTEP==URET + ADCONT==URET + ADWORD==URET +] +IFE 340P\E.SP,[ + ADSTAR==URET + ADCLOS==URET + ADSTOP==URET + ADSTL==URET +] +IFE 340P,[ + ALTPEN==URET + ANDIS==URET +] +IFE VIDP,[ + AVSCAN==ILUUO + AVSTST==ILUUO +] +IFE IMXP,[ + APOTSET==ILUUO +] +IFE PDP6P,[ + AIPDP==ILUUO +] +IFE NMTCS,[ + AMTAPE==ILUUO +] + +IFE ARMP,[ + AARMOV==ILUUO + AARMRS==ILUUO + AARMOF==ILUUO +] +IFE PTRP,[ + AFEED==CPOPJ +] +IFE RBTCP,[ + ARBTC==ILUUO +] +IFE NETP,[ + ANETIM==OPNL1 ;NO SUCH DEVICE ERROR FOR SYMBOLIC SYSTEM CALLS. + ANETBL==OPNL1 + ANETHS==OPNL1 +];NETP +IFE NCPP,[ + ANETAC==CPOPJ ;MAKE OLD UUOS FAIL + ANETIN==CPOPJ +];NCPP + +IFE NUNITS,[ + AUBLAT==URET + AUTNAM==URET + AUINIT==URET + AUDISM==URET + AASSIGN==URET + ADESIGN==URET +] + +;Here generate the table for the BUG macro. Note that entries for +;bugs in the initialization code will appear here also! That's +;why we have the kludgey add 10 +BUGTAB: BLOCK LBUGTB+10 +LBUGT2==.-BUGTAB + 0 ;Marks end of table + +CONSTANTS +HSYSCD:: ;HIGHEST SYSTEM CODE + +SUBTTL RANDOM STORAGE +EBLK + +SCHHP: SCHHB ;PNTR TO SCHED HIST BUFFER +SCHHB: BLOCK SSCHDB ;SCHED HIST BUFFER + ;4.9 =1 EXEC + ;4.8 =1 QUANT TERMINATED BY PG FAULT + ;4.7-3.8 LENGTH OF RUN TIME IN 512 USEC UNITS + ; MUST ACCOMODATE 150 MILLISECOND QUANTA + ;3.7-3.1 USER ("NUMERIC INDEX) + ;RH PC QUANT STARTED AT +SWPHTP: SWPHTB +SWPHTL==200 +SWPHTB: BLOCK SWPHTL ;SWAPPING HISTORY TABLE + ;4.9-4.8 EVENT: 0=START LOADING, 1=FINISH LOADING, + ; 2=SWAP OUT, 3=SWAP BLOCK + ;4.7-3.9 WORKING SET SIZE MINUS ONE (0=0) + ;3.8-3.1 USER NUMBER + ;2.9-1.1 RH(TIME) + BLOCK SWPHTL ;CORRESPONDING UTRNTM + +PGIHTP: PGIHTB +PGIHTL==200 +PGIHTB: BLOCK PGIHTL ;PAGE-IN HISTORY TABLE + ;4.9 1 IF JOB WAS LOADING + ;4.7-3.9 USER VIRTUAL PAGE NUMBER + ;3.8-3.1 USER NUMBER + ;2.9-1.1 RH(TIME) + BLOCK PGIHTL ;CORRESPONDING UTRNTM + +IFN SCHBLN,[ +SCHMNY: 0 ;0 DO FULL SCHEDULE, -1 NEXT "SCHEDULE" SHOULD LOOK IN SCHBTB +SCHBNJ: 0 ;NUMBER OF VALID ENTRIES IN SCHBTB +SCHBTB: BLOCK SCHBLN ;RUNNABLE JOB BUFFER +SCHBPR: BLOCK SCHBLN ;PRIORITIES OF THOSE +NSCHOV: 0 ;COUNT OF BUFFER OVERFLOWS +] +;TRANSLATION ENTRY _ T +;TRANLK(T) IS MODE,,NEXT ENTRY +;MODE IS 0 IF ENTRY ON FREE LIST, ELSE NOT 0, AND + ;BITS 3.1 => INPUT, 3.2 => OUTPUT, 4.9 => ATOMIC TRANSLATION (DON'T RETRANSLATE) +;NEXT-ENTRY IS -1 FOR NIL, ELSE IDX REL TRAN!X +;TRANID(T) THRU TRANIS(T) - FROM-NAMES +;TRANOD(T) THRU TRANOS(T) - TO-NAMES + +TRANLK: REPEAT SIOMT,,,.RPCNT-1 ;GENERATE 1ST WDS, LINKED TOGETHER. +TRANID: BLOCK SIOMT +TRANI1: BLOCK SIOMT +TRANI2: BLOCK SIOMT +TRANIS: BLOCK SIOMT +TRANOD: BLOCK SIOMT +TRANO1: BLOCK SIOMT +TRANO2: BLOCK SIOMT +TRANOS: BLOCK SIOMT + +TRANFL: SIOMT-1 ;TRANSL ENTRY FREE LIST. +TRNCNT: 0 ;NUM ENTRIES IN USE. +TRNREF: 0 ;NUM. READ-ONLY ACCESSES TO TRANSL LISTS. +TRANSW: -1 ;SWITCH FOR WRITE REF. + 0 + +IFE SCHBLN, U0P: 0 ;PRIORITY OF BEST USER SO FAR + +USER: -1 ;USER # OF CURRENT LOSER +SYSL: SYSB*2000 +LITM: 0 ;LAST TIME SYS INCREASED CORE + +SLGIV: BLOCK 3 ;LOGIN + +SETSLC: 0 ;SETLOC VARIABLES +SETSLQ: 0 +SETSU: -1 + +SWUNAM: 0 ;SYS WRITE VARIABLES +SWJNAM: 0 +SWFN1: 0 +SWFN2: 0 +SWFN3: 0 +SWMOD: 0 + +DMON: SIXBIT /DRAGON/ + -1 ;USER INDEX OF DEMON JOB + +NQMFWR: 0 ;COUNT OF FILES WRITTEN ON .MAIL. - FOR MAILER DEMON TO HANG ON. +IFN XGP,[ +NXGPFW: 0 ;COUNT OF FILES WRITTEN ON .XGPR. - FOR XGPSPL +] + +;DEAMON VARIABLES +;VARIABLES FOR DEAMON CODE HACK +IFN DEMON,[ + +IFN TTLPTP,TPLFLG: 1 ;FLAG FOR TPL + +DMTLL==4 ;LEGNTH OF DEAMON TABLE SLOT +NODEAM==20. ;NUMBER OF SLOTS +DMLNG==NODEAM*DMTLL + +DEMSW: 0 + 0 ;MAIN PROG SWITCH FOR DEMON +REQCNT: 1 ;COUNT OF REQUEST'S FOR SYS JOB +DMTPTR: 0 ;POINTER FOR DEMSIG TO DEM TBL, AN INDEX INTO IT, TAKEN MODULO DMLNG +DMLSEX: -DMLNG,,0 ;POINTER TO DEAMON TABLE AOBJN +DEMCNT: ;AMOUNT OF SLOTS REMAINING IN THE TABLE + +DMBLK: 0 + 0 ;SLOT FOR NON DEAMON LOAD VIA NUJBST + +DMOBLK: SIXBIT / SYS/ + SIXBIT /ATSIGN/ + 0 ;BLOCK USED BY SYSTEM JOB TO CHECK OPEN + +;DEAMON TABLE--CONSISTS OF SLOTS OF FOUR WORDS FOR EACH DEMON +;WORD 1 CONTAINS ITS SIXIT NAME +;WORD 2 CONTAINS THE USER INDEX,-1 IF LOADING, 0 IF DOWN +;WORD 3 2 QUANTITIES IN 18 BIT 2'S COMPLEMENT-- +;LH ALWAYS > = 0, IF 0 ONLY TAKES EXPLICIT REQUESTS IN > 0 A REQUEST +;RH CONTAINS THE NUMBER OF REQUESTS PENDING FOR THE DEAMON +;FOR THE DEAMON WILL BE GENERATED EVERY 2 MINUTES +;WORD 4 CONTAINS THE TIME TILL THE NEXT IMPLICIT REQUEST WILL BE GENERATED. + + +DMTTBL: SIXBIT /DEMSTR/ + 0 + 1 ;STARTUP DEAMON + 0 + +BLOCK *DMTLL +] +TIMOFF: -1 ;TIME SINCE MIDNIGHT IN HALF SECONDS ("TIME IN DSK FORMAT"). +QDATE: -1 ;DISK FORMAT DATE: -1 => SYSTEM DOESN'T KNOW DATE, ELSE + ;BITS 3.1-3.5 HAVE DAY OF MONTH, 3.6-3.9 HAVE MONTH OF YEAR, + ;4.1-4.7 HAVE YEAR MOD 100. . +QDATEI: -1 ;-1 => SYSTEM DOESN'T KNOW DATE, ELSE + ;DATE AND TIME THE DATE AND TIME WERE FIRST DETERMINED, IN DSK FORMAT. +PDYTIM: -1 ;TIME SINCE BEGINNING OF YEAR IN HALF-SECONDS (BACKUP TO PDCLK) +FYEAR: 0 ;YEAR (E.G. 1969.) +PDTIME: 0 ;NON-ZERO => OFFSET FOR PDCLK + ;WHEN SUBTRACTED FROM PDCLK DATAI GIVES # PD-UNITS SINCE + ; BEGINNING OF YEAR + ;ONE SECOND = 60. PD-UNITS + ; Also contains similar offset for KS-10 clock in 60ths. +LPDTIM: -1 ;LAST PD CLK TIME, -1 IF PD CLK NOT RUNNING OR JUST PDSET'ED + +SUPCOR: 0 ;CONTROLS SYS JOB, SEE SYSDTB, SCOR, ETC + ;EACH BIT REQUESTS ONE FUNCTION IF SET. +SUPCOP: SCLDAT+IFN DEMON,[SCLDMN],,SCRCKS + ;THIS WORD OR'D INTO SUPCOR EVERY SECOND. +SCKPHS: 0 ;USED FOR COUNTING EVERY SECOND 1/2 SECOND CLOCK + ;TO SET SUPCOP BITS EVERY SECOND +SYSITM: 0 ;TIME SYS JOB LAST STARTED WAITING ON SUPCOR +LNETIM: 0 ;TIME AT WHICH NETWORK WAS LAST BROUGHT UP +RSWTIM: 1 ;Time (in DSK format) when last checked system resources. + +MXPARS==10. ;MAX # PAR ERRS TO PRINT OUT +PARPG: BLOCK 8 ;STORAGE OF PAGE MAP WHILE HACKING PARITY ERROR CHECK +PARCNT: 0 ;# OF PAR ERROR ENTRIES IN TABLE +PARCON: BLOCK MXPARS ;CONTENTS OF BAD PARITY LOCATIONS +PARADR: BLOCK MXPARS ;ADDRESSES OF BAD PARITY LOCATIONS +PARAND: -1 ;QND OF ALL BAD WORDS +PARIOR: 0 ;IOR OF ALL BAD WORDS +PARAAN: -1 ;AND F ALL BAD ADDRS +PARAOR: 0 ;IOR OF ALL BAD ADDRS +IFE KA10P,[ +PARPFW: 0 ;PAGE FAIL WORD +PARERA: 0 ;ADDRESS OF PAR ERR +PARWRD: 0 ;BAD DATA +] ;IFE KA10P +IFN KL10P,[ +PARRSN: 0 ;0 => PAR ERR PAGE FAULT IN PROG + ;-1 => PAR ERR INTERRUPT; NEEDN'T STOP + ;THE RUNNING JOB. +] ;KL10P +PARDIE: 0 ;-1 => FATAL PARITY ERROR +TPLSWP: 0 ;-1 => USE OLP FOR TPL +IFN PDP6P,[ +PDP6UP: 0 ;0 => PDP6 IS DOWN. (AS USUAL) +] +IFN ECCMEM,[ +IFE MCOND AIKA,[ +ECCADR: 1,,777760 ;ECC HISTORY STARTS HERE +ECCLEN==16. ;16 LOCATIONS OF ECC HISTORY +ECCIDX: 0 ;LAST LOCATION ACCESSED +]] +IFN TEN11P,[ +TEN11F: 0 ;0 -> NORMAL + ;-1 -> COMPLETELY IGNORE 10-11 INTERFACE + ; 1 -> RESET 10-11 INTERFACE, OTHERWISE IGNORE +T11ERC: 0 ;COUNT OF CONTROL PAGE RAM ERRORS +T11CCN: 0 ;CORRECT CONTENTS +T11WCN: 0 ;WRONG CONTENTS +T11PG: 0 ;PAGE # INVOLVED +] +IFN N11TYS,[ +TVBLAD: 17742 ;VIDEO BUFFER TO FLASH WHEN JOB RUNNING (PDP10 VIDEO BUFFER ADDR) +] +IFN DL10P,[ +DL10F: -1 ;-1 NORMAL, 0 => 11 DOWN +DL10HC: 0 .SEE TTDLBRK ;NUMBER OF LOOPS WHEN HUNG UP WAITING FOR 11 TO GOBBLE BUFFER +] + +DLSRCH: 0 ;-1 => DON'T RUN ANY USER BUT THE ONE ALREADY RUNNING + ;(UNLESS WE TAKE A PAGE FAULT). +CPDLP: -CPDLL,,LCPDL-1 ;CLOCK PDL POINTER +LCPDL: BLOCK CPDLL ;CLOCK INT LEVEL PDL + +CLKBSW: 0 ;READ SWITCHES INTO HERE TO DECIDE WHETHER TO GO TO DDT. + +CLROOT: SSLCKB ;CLOCK QUEUE ROOT + +SSLCKB: SCLKI ;SLOW CLOCK RQ BLOCK + .+2 .SEE CHA5CK ;OR 15SCLB + JRST SSLCK + +IFN CHAOSP,[ +CHA5CK: 5*60.-SCLKI ;5-SECOND CLOCK FOR CHAOS NET + 15SCLB ;NOTE INITIAL TRIGGERING OF CLOCKS BELOW DELAYED AN EXTRA 5 SECONDS + JRST CHA5CL +];CHAOSP + +15SCLB: 15.*60.-SCLKI + .+2 .SEE PRVCLB ;OR VSLCKB + JRST 15SCLK + +IFE SWPWSP,[ +PRVCLB: NPVSEC*60.-15.*60.-SCLKI ;PRIVILEDGED USER VARIABLE CHECK + VSLCKB + JRST PRVCLK +];SWPWSP + +VSLCKB: 0 ;VERY SLOW CLOCK BLOCK + CLINFB ;CAUSE SLOW CLOCK TICK SOON AFTER SYS COMES UP + JRST VSSLCK + +CLINFB: 377777,,-1 ;ABOUT 15 YEARS + 0 + BUG ;? + +IFN CCLKP,[ +CCLKB: 0 ;FOR CHESS CLOCK HACK + -1 + JRST RCCLK +CCLK1: 0 +CCLK2: 0 +] + +IINTIC==60. ;# TWO-MINUTE TICKS PER VERY VERY SLOW CLOCK TICK (2 HOURS) +IINCNT: 0 ;# TWO-MINUTE TICKS REMAINING UNTIL NEXT VERY VERY SLOW CLOCK TICK +.SEE VSCLK + +IFN N11TYS,[ +WHOCLB: 0 ;WHO LINE TIMER + -1 + JRST WHOSET +] + +UTTYS: BLOCK MXCZS ;RING BUFFER FOR JOBS TO BE STARTED +UTTYI: UTTYS +UTTYO: UTTYS +UTTYCT: 0 + +PCLDBM: 0 ;.NE. 0 ACTIVATE PC LSR DEBUG MODE + ;1 => ADVANCE PLACE WHERE PCLSR + ;2 => ADVANCE BUT DON'T ^Z. + ;- HOLD +PCLUSR: -1 ;USER PCLSR MODE ACTIVE FOR +PCLL: 0 ;PLACE WHERE LAST PCLSR TESTED +PCLHSH: 0 ;HASH OF RETURNS ON PDL AT LAST PLACE TRAPPED OUT OF +PCLNXT: -1 ;-1 => FROB NEXT TIME IN ADVANCE MODE +PCLHT: 0 ;TEMP +PCLIDX: 0 ;INITIALIZE PCLT TO THIS (SET TO LOOP COUNT IF NECESSARY) + +CORRNR: 0 ;LAST USER TO RUN CORE +SJSPG: 0 ;-1 => LAST FREE PG RESERVED FOR SYS JOB; DON'T GIVE IT TO ANYONE ELSE. +UTBFLF: 0 ;-1 SIGNAL TO TRY TO FLUSH I/O BLOCKS +UFDFLF: 0 ;-1 SIGNAL TO TRY TO FLUSH 2311 UFDS +CORCNT: 0 +UFLSF: 0 ;FLAG FROM UFLS TO CLKBRK +CLKFL1: 0 ;FLAG COUNTER TO CONTROL CLOCK LEVEL +SCHFLG: 0 ;SCHEDULE TIMER (DIVIDES 60 CPS) +27FCLK: 0 ;-1 IF FAST CLOCK SHOULD CALL TYP27S +SCITM: 0 ;SEE SYSEX, SYSDEC +LCLK1: 0 +SYSCKP: -LTSTB,,TSTB ;SYSTEM CHECKSUMS CHECKER POINTER +SYSPDP: -LSYSP,,SYSPDL-1 ;PDL POINTER FOR SYSTEM JOB +SYSPDL: BLOCK LSYSP ;PDL FOR SYS JOB +IFN TPLP,TPLBUF: BLOCK TPLBSZ ;PSEUDO LPT BUFFER - MUST BE ABOVE SUACS +IFN TPLP\DEMON,TPLFNO: SIXBIT /!/ ;UNIQUE TPL FIRST FILE NAME +SJCFF: 0 ;-1 WHEN SYS JOB IN PROCESS OF FLUSHING CORE + ;AVOIDS TIMING ERROR DUE TO HUSRAD NOT REALLY REFLECTING WHAT ITS GOING TO BE +SLSWPR: 0 ;STORE SYS JOB'S LSWPR WHILE HACKING UUOS + +BBLK + +IFN TPLP, TPLFN: 2,,(SIXBIT /TPL/) +IFN KL10P,[ +KLEBCC: 0 ? <1_23.>/<4*25./2> ;EBOX COUNTER CONVERSION TO 4 USEC CONSTANT (FOR 25 MHZ) + ;RESULT IS IN AC+2 AFTER DMUL AC,KLEBCC +KLMBCC:; 1 ? 110000,, ;FOR CONVERTING AN MBOX COUNT TO THE TIME (IN EBOX UNITS) + ;IT SUPPOSEDLY AMOUNTS TO. + ;WE ASSUME 102.5 NANOSEC OD WAITING TIME PER MBOX CYCLE + ;THIS NUMBER IS 102.5/80. + ;DMUL AC,KLMBCC PUTS ANSWER IN AC+1, AC+2 + ;WITH BINARY POINT BETWEEN THE WORDS. + 0 ? 0 ;M8538 MODIFIED SO EBOX COUNTER CONTINUES TO COUNT + ;DURING MBOX WAIT TIME, SO SET KLMBCC = ZERO. +EBLK + +MTRUSR: -1 ;USER TO WHOM PERF CTR IS ASSIGNED +MTRJOB: -2 ;USER BEING MEASURED BY PERF CTR, + ;OR -1 => NULL JOB, OR -2 => ALL JOBS. + +PAEON: 0 ;SELECTED PERF CTR ENABLE WORD +PAEOFF: 0 ;DISABLE THE PERF CTR (WHEN WRONG JOB IS RUNNING) +STPERF: 0 ? 0 ;VALUE OF PERF COUNTER AT START OF QUANTUM +STEBOX: 0 ? 0 ;VALUE OF EBOX COUNTER AT START OF QUANTUM +STMBOX: 0 ? 0 ;VALUE OF MBOX COUNTER AT START OF QUANTUM +] ;KL10P +IFE KL10P, EBLK +IFN TPLP,[ +TPLFN1: 0 +TPLFN2: 0 +TPLFN3: 0 +] +IFN NLPTP, NTNLPL: 0 ;NUMBER OF TIMES NLPT LOST PIA +VARIABLES + + +TSTB: REPEAT CKNUM,CONC CK,\.RPCNT, +LTSTB==.-TSTB + +CKSUMS: BLOCK CKNUM +CKXORS: BLOCK 36. ;XOR OF ALL ADRS IN PURE AREAS IN SYS WITH CORRESP + ;BIT SET (RH) +TCKXOR: BLOCK 36. ;TEST XORS + +SSYSCL==SSYS +SYSCLB==SSYSCL_-10.+IFN 1777&SSYSCL,1 + +IFE KA10P,[ +AC1PTR: UUOACS ;-> WHERE AC BLOCK 1 IS CURRENTLY LOADED FROM +] ;IFE KA10P + +USRHI: 0 ;HIGHEST LOC USED FOR USER STORAGE + +SUBTTL LOCATIONS TO PATCH WHEN DEBUGGING + +SYSDBG: 0 ;0 NORMAL TIMESHARING + ;+ GIVE "ITS BEING DEBUGGED" MESSAGE + ;-N ALSO ALLOW ONLY CONSOLE #N AND T00 TO CTRL/Z. + ;-512.*N => ALLOW ONLY HOST N TO TELNET IN. + ;-512.*N+M => ALLOW HOST N AND TTY M. +DMLLDF: -1 ;-1 => START DAEMONS AUTOMATICALLY, 0 DON'T. +IFN DEMON,DMNFLG: 1 ;1 => START DM-STYLE DAEMONS, 0 DON'T. + +IFN NETP,NETUSW: 0 ;-1 => DON'T START UP A JOB IN ANSWER TO A CONNECT REQUEST + ;FROM A HOST OTHER THAN OURSELVES + +SYSCN: SYSCON ;NUMBER OF TTY TO RECEIVE SYSTEM CONSOLE OUTPUT. + ;-1 TO THROW IT AWAY. YOU CAN CHANGE THIS ANY TIME. + +SUPPLG: 0 ;-1 => SUPPRESS LOGIN/LOGOUT MESSAGES ON SYSTEM CONSOLE. + +IFE KS10P,[ ; KS has no lights. +MIPGDS: 0 ;-1 => DON'T LIGHT LIGHTS (KA HAS HARDWARE SWITCH, KL NEEDS + ; THIS) +] ;IFE KS10P + +IFN RH10P+RH11P,[ +USFHLT: 0 ;-1 => HALT ON DISK UNSAFES AND OTHER BAD ERRORS + ;0 => RETRY. NOTE SET POSITIVE FOR 1/2 SECOND AFTER + ; A RETRY TO AVOID LOOPING, DETECT SOLID ERRORS. +] ;RH10P+RH11P + +.SEE USEHM ;NONZERO => USE HIGH MOBY, ELSE ONLY 256K + +.SEE USEMDM ;NONZERO => USE MEDIUM MEMORY AS ADDITIONAL "LOW HALF" PAGES + +IFN N11TYS,[ +TT11P: 1 ;0 => PDP11-TTYS ARE NOT IN USE + ;1 => SYSTEM SHOULD INITIALIZE THEM + ;-1 => INITIALIZED AND IN USE + ;TO BRING THE TV'S DOWN, ZEROING TT11P ISN'T ENOUGH + ;EITHER DO WHAT TT11LS DOES, OR JUST SET SCR11D IN SUPCOR + ;(THE LATTER MAY NOT TAKE EFFECT INSTANTLY, HOWEVER) + ;TO BRING THE TV'S UP, JUST SET TT11P TO 1 AND WAIT 2 SECONDS +] + +.SEE IMPUP ;0 UP, -1 DOWN, 1 DOWN AND DON'T TRY TO BRING BACK UP + +.SEE TEN11F ;0 UP, -1 TOTALLY DOWN, 1 RESET PLEASE + +.SEE DL10F ;0 PDP11 DOWN, -1 UP + +.SEE PDP6UP ;0 PDP6 DOWN, -1 UP + +.SEE LASTGC ;NAME OF LAST DISK DIRECTORY GARBAGE COLLECTED + + +SUBTTL SWAPPING ALGORITHM CONTROL SWITCHES + +IFE SWPWSP,[ ;THESE AREN'T LOOKED AT IN SWPWSP SYSTEM +ENSWSC: SWBLK ;ENABLE CALLING OF SWSCD FROM 15 SEC CLOCK +ENUPC: 1-SWBLK ;ENABLE USER-PC PAGE OF RUNNING USER NOT BE SWAPPED OUT +ENPZRO: SWBLK ;ENABLE PAGE-ZERO OF RUNNING USER NOT BE SWAPPED OUT +ENSWBK: SWBLK ;ENABLE SWPNX1 TO SWAP BLOCK A USER +ENPVCL: 1-SWBLK ;ENABLE PRVCLK ROUTINE +ENPREE: 1-SWBLK ;ENABLE PREEMPTION ON PAGE SWAP IN (SEE QSWI1) +ENAGE: 1-SWBLK ;ENABLE AGE BITS TO ABORT SWAP OUT IF PAGE IS USED +];SWPWSP +AGERTE: 8 ;NUMBER OF PAGES TO AGE EACH 1/2 SECOND. + ;IN A 512K SYSTEM, LAP TIME IS ABOUT 200/AGERTE SECONDS. + +SUBTTL SYSTEM LOCKS + +CIRPSW: -1 ;CIRCULAR POINTER SWITCH + 0 + +MEMFRZ: -1 ;MEMORY FROZE + 0 + +CASW: -1 ;CORE ALLOCATE INTERLOCK SWITCH (REQUESTS TO CORE JOB) + 0 + +SHUTLK: -1 ;LOCK VAR FOR SHUTDN + 0 ;USED TO TELL WHO CAUSED SYS DOWN + +TREESW: -1 ;LOCK MANIPULATION OF JOB TREE STRUCTURE + 0 ;ATTACH, DETACH, DISOWN, REOWN ALL LOCK. + +CUSER: -1 ;CORE ALLOCATOR USER + 0 ;DUMMY CORE ALOC USE VAR + +ARDFSW: -1 ;LOCK VAR FOR .REDEF + 0 + +IFN 340P\E.SP,[ +DISUSR: -1 ;340 USER + 0 ;DUMMY 340 USE VAR +] + +IFN CODP,[ +CODUSR: -1 ;CODE SENDER +CODUSE: -1 +] + +IFN PLTP,[ +PLTUSR: -1 ;PLOTTER USER +PLTUSE: -1 +] + +IFN LPTP\TTLPTP,[ +LPTUSR: -1 ;LINE PRINTER USER +LPTUSE: -1 +] +IFG LPTP-1,[ +OLPUSR: -1 +OLPUSE: -1 +] +IFN LPTP,[ + IFE LPTP-1,[ + IFN NLPTP,[ + NLUSR==LPTUSR + NLUSE==LPTUSE + ] + IFN OLPTP,[ + OLUSR==LPTUSR + OLUSE==LPTUSE + ] + ] + IFG LPTP-1,[ + OLUSR==OLPUSR + OLUSE==OLPUSE + NLUSR==LPTUSR + NLUSE==LPTUSE + ] +] + +IFN PTRP,[ +PTPUSR: -1 +PTPUSE: -1 + +PTRUSR: -1 +PTRUSE: -1 +] + +IFN VIDP,[ +NVDUSR: -1 +NVDUSE: -1 +] + +IFN PDP6P,[ +PDPUSR: -1 ;PDP-6 USER +PDPUSE: -1 +PDPISR: -1 ;PDP6 AS INFERIOR (INTS ON IO CHANNEL) +PDPISE: -1 ;PDP6 USE VAR +] + +IFN TABP,[ +TABUSR: -1 ;TABLET USER +TABUSE: -1 +] + +IFN STKP,[ + STKUSR: -1 + STKUSE: -1 +] + +TIME: 0 ;TIME SINCE SYSTEM START IN 1/30'THS +SUSRS: 0 ;NUMBER USERS ON SYS +RVVTIM: 0 ;VALUE OF TIME WHEN SYSTEM WAS LAST REVIVED FROM A CRASH +USRRCE: BLOCK NCT+1 ;USER RESOURCE +1 FOR DISOWNED JOBS +SYSRCE: 0 ;SYS JOB RESOURCE +SLOADU: 0 ;100. * , IN FIXED POINT. +RNABLU: 0 ;RUNNABLE USERS +NPGWTU: 0 ;NUMBER OF JOBS CURRENTLY WAITING FOR A PAGE +LOUTIM: 0 ;TOTAL TIME USED BY LOGGED OUT USERS +UMASTER: -1 ;INDEX OF MASTER USER +SWRCE: BLOCK NCT+2 ;SWAP SCHED RESOURCE +SWIPRQ: 0 ;TOTAL # SWAP IN REQUESTS +SHUTDN: 0 ;"TIME" SYS WILL DIE, 0 IF NOT DYING, -1 IF DEAD +DEDTIM: 0 ;TIME TILL DEATH AFTER NEXT CLK QUEUE INT + ; < 0 => SYSTEM ACTUALLY DOWN (CHECKED BY ^Z, NUJBST, %OPLIV JOBS) +DTHTIM: 0 ;TIME SYSTEM DIED +DEDBLK: 0 + -1 + JRST DEATHZ + +ATRNJN: 0 ;JNAME OF LAST JOB TO DO A .TRANAD OR .TRANDL + ;(SO I CAN SEE IF THEY'RE USED AT ALL). + +IFN DZ11P,[ +DZXSPR: 0 ;Count of spurious DZ-11 transmitter interrupts. +DZRSPR: 0 ;Count of spurious DZ-11 receiver interrupts. +];DZ11P + +NCORRQ: 0 ;NUMBER CORE RQS HERE SO TRANSFERRED TO PEEK +NCBCOM: 0 ;NUMBER CORE BLOCKS COMMITTED TO CORGP + +NQDE: BLOCK NQS ;NUMBER OF 2314 DATA ERRORS +NQHE: BLOCK NQS ;NUMBER OF 2314 HARDWARE ERRORS + BLOCK 1 ;NQSE-1 COUNTS SPUR INTS WHILE NO XFER (QSDU -1) +NQSE: BLOCK NQS ;NUMBER OF SPURIOUS 2314 ERROR INTERRUPTS +NQCMPE: BLOCK NQS ;NUMBER OF 2314 READ/COMPARE ERRORS +NQWDE: BLOCK NQS ;# DATA ERRS ON WRITE +NQRDE: BLOCK NQS ;# DATA ERRS ON READS +NIRSWE: 0 ;# IRRCV ERRS ON SWAPPING XFERS +QIRRCV: 0 ;IRRECOVERABLE DISK ERRORS +QIRCBK: 0 ;BLOCK # W/ IRRCV ERROR +QIRUNT: 0 ;UNIT OF ABOVE +NQWRE: 0 ;# WRITE ERRS RCC OK +NQWIRE: 0 ;# WRITE ERRS RCC LOST +NWXFR: 0 ;NUMBER WRITE TRANSFERS (FILE, DIR, ETC.) +NRXFR: 0 ;NUMBER READ +NSWXFR: 0 ;NUMBER WRITE SWAPS +NSRXFR: 0 ;NUMBER READ SWAPS + +;DON'T CHANGE ORDER .SEE MEMTYP +PARERR: 0 ;COUNT OF CORE PARITY ERRORS +NXMERR: 0 ;COUNT OF NXMS +IFE KA10P, BPFERR: 0 ;COUNT OF BAD PAGE FAILS +PARPC: 0 ;PC ON CORE PARITY INTERRUPT +NXMPC: 0 ;PC ON NXM +IFE KA10P, BPFPC: 0 ;PC ON BAD PAGE FAIL +PARUSR: -1 ;USER ON PAR ERR +NXMUSR: -1 ;USER ON NXM +IFE KA10P, BPFUSR: -1 ;USER ON BAD PAGE FAIL +IFE KA10P, BPFPFW: 0 ;PFW ON BAD PAGE FAIL + +IFN KS10P,[ +ECCERR: 0 ;COUNT OF ECC CORRECTED ERRORS LOGGED +ECCERA: 0 ;MEMORY STATUS AND ADDRESS OF MOST RECENT +ECCAND: -1 ;AND OF ALL ERRORS +ECCIOR: 0 ;IOR OF ALL ERRORS +] ;IFN KS10P + +IFN DPKPP, NDPKPE: 0 ;# PARITY ERRS FROM DATAPOINT KLUDGE + +SNMPGS: 0 ;SYSTEM, NUMBER OF VIRTUAL USER PAGES +SNSWPG: 0 ;SYS, NUM OF SWAPPED OUT VIR. PGS + +USRTM1: 0 ;4USEC TICKS USED BY USERS SINCE LAST (1/2 SEC) UPDATE TO USRTIM +USRTIM: 0 ;TIME USED BY ALL USERS 1 SEC UNITS +NULTM1: 0 ;4USEC TICKS USED BY NULJOB SINCE LAST (1/2 SEC) UPDATE TO NULTM3 +NULTM3: 0 ;NUMBER OF SECONDS USED BY NULJOB +NULTIM: 0 ;TIME USED BY NULL JOB (60'THS) - OBSOLETE BUT STILL MAINTAINED +IFN KL10P,[ +NULEBC: 0 ? 0 ;EBOX COUNT WHEN NULL JOB ENTERED +NULMBC: 0 ? 0 ;MBOX COUNT WHEN NULL JOB ENTERED +NULPRF: 0 ? 0 ;PERF COUNT WHEN NULL JOB ENTERED +] ;KL10P +IFE KA10P,[ +PFAILF: 0 ; KL: -1 => ENTRY TO CLOCK LEVEL WAS VIA PFAIL + ; -2 => VIA INTPFL + ; KS: -1 => BOTH CASES +] ;IFE KA10P +LOSTM1: 0 ;4USEC TICKS LOST SINCE LAST (1/2 SEC) UPDATE TO LOSTIM +LOSTIM: 0 ;SECONDS OF LOST TIME (ALL OTHERWISE RUNNABLE JOBS WAITING FOR PAGES) +IDLTM1: 0 ;4 USEC TICKS IDLE SINCE LAST (1/2 SEC) UPDATE TO IDLTIM +IDLTIM: 0 ;SECONDS OF IDLE TIME (NO JOBS WANT TO RUN) +LOSRCE: 0 ;USRRCE WORD FOR LOST TIME +IDLRCE: 0 ;USRRCE WORD FOR IDLE TIME + +UREALT: -1 ;RH=INDEX OF THE REAL TIME USER + ;LH=0=> THIS USER HAS HIGHEST PRIORITY + ;LH>0=> USER NOT IN HIGH PRIORITY PHASE + ;LH<0=> FACILITY IDLE +INFORM [HIGHEST USED]\<.-1> + SUBTTL USER VARIABLES + +;ONE COPY FOR EACH PROCEDURE +;FOR KL AND KS, THIS IS THE UPT + +IFN KL10P,[ +DEFINE KLUPT N,NAME/ ;CHECKS "HARD-WIRED" UPT LOCATIONS +IFN .-USRSTG-,[ +.ERR "NAME" LOST IN UPT +LOC USRSTG+ +] +TERMIN +] ;KL10P + +IFE KL10P,[ +DEFINE KLUPT N,NAME/ +TERMIN +] ;IFE KL10P + +IFN KL10P, LOC <.+777>&-1000 ;KL UPT MUST START AT HARDWARE PAGE BOUNDARY + +IFN KS10P, LOC <.+7>&-10 ; KS UPT must be 0 mod 8 (see UUOPCW) + +USRSTG:: KLUPT 0,;USER PAGE MAP + +UPGMP: BLOCK NUVPG/2 ;PAGE MAP STORAGE (PROGRAMS UP TO NUVPG LONG) +; 2.9-2.8 ACCESS RIGHTS +; 00 NO ACCESS (BY SOFTWARE CONVENTION, 1.2-1.1 +; HAVE THE "REAL" ACCESS BITS, WHICH MAY BE 00, +; BUT MAY NOT, E.G. FOR A SWAPPED OUT PAGE). +; 01 READ ONLY +; 10 READ/WRITE/FIRST +; 11 READ/WRITE +.SEE PMCSHM ;CACHE BIT +.SEE PMAGEM ;AGE BITS +.SEE PMRCM ;LOW N BITS ARE PHYSICAL CORE PAGE NUMBER (IN 1K PAGES) +UPGCP: BLOCK NUVPG/2 ;CIRCULAR POINTERS (CORRESPONDS 1-1 WITH UPGMP) +; IF -1, ABSOLUTE PAGE, NOT LINKED. OTHERWISE: +; 2.9 IF 0: +; 2.8-1.9 USER INDEX +; 1.8-1.1 PAGE NUMBER IN THAT USER'S UPGCP +; IF 1: +; 2.8 IF 0: +; 2.7-1.1 LINK TO MMP TABLE +; IF 1: +; 2.7-1.1 LINK TO MEM PNT TABLE +UMAPS: 0 ;USER MAP STATUS + .SEE %UM +UDBR1A==UPGMP ;ADDRESS TO PUT IN DBR1 +UDBR2A==UPGMP+ ;ADDR FOR DBR2 +UPGCPH==UPGCP+ ;ADDR OF HIGH HALF OF CIRC PNTRS + +TTYTBL: 0 ;TTY ASSIGNED THIS USER OR INDICATION THAT THERE IS NONE +%TBNOT==400000 ;4.9 DOES NOT HAVE TTY NOW +%TBNVR==200000 ;4.8 IF JOB DOESN'T HAVE TTY, OPENS SHOULD FAIL. +%TBINT==100000 ;4.7 IF JOB DOESN'T HAVE TTY, ATTEMPT TO USE TTY SHOULD INTERRUPT. + ;JOB CAN SET BITS 4.8 AND 4.7. +%TBWAT==40000 ;4.6 IF 1, %TBINT AND %TBNVR ARE OVERRIDDEN AND TTY USE ATTEMPTS + ; ALWAYS HANG. SET BY DDT FOR $P, CLEARED BY ^P. ONLY SUPERIOR CAN SET. +%TBDTY==010000 ;4.4 TTY TAKEN FROM --ME--. WHEN GIVEN BACK, + ;DON'T PASS IT ON TO MY INFERIOR. +%TBOUT==004000 ;4.3 ALLOW THIS JOB TO OUTPUT WHETHER OWNS TTY OR NOT +%TBINF==002000 ;4.2 ALLOW MY INFERIORS TO OUTPUT IF THEY HAVE %TBOUT. +%TBOIG==001000 ;4.1 IGNORE MY OUTPUT +%TBIIN==000400 ;3.9 INTERRUPT IF I TRY TO DO INPUT +$TBECL==220600 ;3-6-3.1 # ECHO LINES IF I DONT HAVE DISPLAY + ;RH USER NUM GAVE TTY AWAY TO OR TTY NUM IF HAS IT +%TBCLR==410077 ;CLEAR THESE BITS IN TTYTBL OF A JOB RECEIVING THE TTY + +TTSTSV: BLOCK 3 ;JOB'S SAVED TTYST1,TTYST2,TTYSTS, WHEN JOB DOESN'T HAVE THE TTY. + +NMPGS: 0 ;NUMBER OF NON-ABSOLUTE PAGES (INCLUDES PURE) +NSWPGS: 0 ;NUMBER SWAPPED OUT PAGES (AOSED FOR EACH USER OF SHARED PAGE SWAPPED OUT) +HUSRAD: 0 ;MEM ADR OF PAGE ABOVE HIGHEST THAT EXISTS (MAX 1,,0) +UPC: 0 ;USER PC STORAGE +LUBTM: 0 ;TIME LAST UNBLOCKED (FOR IDENTIFYING INACTIVE JOBS) +JBI: -1 ;JOB DEVICE INDEX. IF NOT -1, THIS JOB IS A JOB-DEVICE, + ;AND JBI HAS INDEX INTO JOB DEVICE TABLES. + +UPGML: ;USER PAGE MAP LOAD (EIGHT WORDS FOR LPM AND SPM INSTRUCTIONS) +IFE KS10P,[ ; KS10 version given below. + UPJPC: 0 ;JPC. KA HAS FAULT ADDRESS IN LH. +IFE KL10P, UPOPC: 0 ;OLD PC FLAGS,,OPC (UNUSED ON KL-10) + UPMAR: 0,,0 ;MAR ADDRESS AND CONDITION + ;FOR KA-10: + ; 3.3 0=EXEC, 1=USER + ; 3.2-3.1 MAR CONDITION: + ; 0 NEVER + ; 1 INSTR FETCH + ; 2 WRITE + ; 3 ALWAYS + ; 2.9-1.1 VIRTUAL ADDRESS + ;FOR KL-10: + ; 3.9-3.7 ADDRESS BREAK CONDITIONS: + ; 3.9 FETCH + ; 3.8 READ + ; 3.7 WRITE + ; 3.6 0=EXEC, 1=USER + ; 3.5-1.1 VIRTUAL ADDRESS +IFE KL10P, UPQUAN: EXPGNG+1,,0 ;F.S. QUAN AND FAULT BITS +IFN KL10P, UPFW: 0 ;PAGE FAIL WORD +IFE KL10P,DBL==100_1 +IFN KL10P,DBL==0 + UPDBR1: DBL,,UPGMP ;DBR1 + UPDBR2: DBL,,UPGMP+100 ;DBR2 +IFE KL10P, UPDBR3: DBL,,EXEUMP ;DBR3 +IFE KL10P, UPACP: 1040,,UUOACS ;B KEY,C KEY,,AC POINTER +] ;IFE KS10P + +IFN KS10P,[ +UPDBR1: UPGMP ; DBR1 +UPDBR2: UPGMP+100 ; DBR2 +UPQUAN: 0 ; Runtime counter +UPJPC: 0 ; User mode JPC if microcode supports +UPEJPC: 0 ; Exec mode JPC if microcode supports +] ;KS10P + +UPGMLE:: ;END OF PAGE MAP (+1) + +IFN KL10P,[ + KLUPT 420, ;RESERVED UPT 420 +UPT420: 0 + KLUPT 421, ;TRAP 1 INSN ;ARITHMETIC OVERFLOW +TR1INS: JSR ILLTRP ;FOR ITS-STYLE INTERRUPT, CONTAINS 0,,%PIARO + KLUPT 422, ;TRAP 2 INSN ;PDL OVERFLOW +TR2INS: JSR ILLTRP ;SYS JOB SHOULDN'T OVERFLOW ;FOR ITS-STYLE, 0,,%PIPDL + KLUPT 423, ;TRAP 3 INSN ;USED FOR ONE-PROCEED +TR3INS: JSR ILLTRP ;SYS JOB SHOULDN'T ONE-PROCEED ;FOR ITS-STYLE, 0,,%PI1PR + KLUPT 424, ;MUUO DEPOSIT LOCATION +SV40:: +MUUODP: 0 .SEE FORTY + KLUPT 425, ;MUUO OLD PC STORAGE +SUUOH:: +XUUOH: 0 + KLUPT 426, ;MUUO PAGING AND CONTEXT WORD +MUUOCX: 0 + KLUPT 427, ;RESERVED UPT 427 +UPT427: 0 + KLUPT 430, ;MUUO NEW PC WORDS +MUUOKN: %PSPCU,,UUOH0 ;FOR OTHER JOBS, MUUOEX (A JRST 4,). +MUUOKT: %PSPCU,,MUUOEX ;NO JOB SHOULD EVER TRAP IN EXEC MODE. +MUUOSN: %PSPCU,,MUUOEX ;NO JOB SHOULD EVER RUN IN SUPERV. STATE. +MUUOST: %PSPCU,,MUUOEX ;.. +MUUOCN: %PSPCU,,UUOH0 ;NORMAL UUOS +MUUOCT: %PSPCU,,MUUOTR ;UUOS AS TRAP INSN +MUUOPN: %PSPCU,,UUOH0 ;PUBLIC MODE IDENTICAL TO CONCEALED MODE, +MUUOPT: %PSPCU,,MUUOTR ; ALTHOUGH IT'S A SCREW FOR A LOSER TO BECOME PUBLIC +] ;END OF IFN KL10P + +IFN KS10P,[ +DEFINE KSUPT UPTNAM +IFN .-USRSTG-,[ +.ERR UPTNAM lost in UPT +LOC USRSTG+ +] +TERMIN + +UPFW: 0 ; Saved page fail word from last fault. Copied from EPTPFW + ; at time of fault usually. + +KSUPT UPTTR1 +TR1INS: JSR ILLTRP + +KSUPT UPTTR2 +TR2INS: JSR ILLTRP + +KSUPT UPTTR3 +TR3INS: JSR ILLTRP + +KSUPT UPTUUO +SV40:: +MUUODP: 0 + +KSUPT UPTUPC +SUUOH:: +XUUOH: 0 + +KSUPT UPTUCX +MUUOCX: 0 + +KSUPT 427 +UPT427: 0 + +KSUPT UPTUEN +MUUOKN: %PSPCU,,UUOH0 ;UUO in Exec mode new PC + ;For other jobs: %PSPCU,,MUUOEX +KSUPT UPTUET +MUUOKT: %PSPCU,,MUUOEX ;UUO as trap instruction in Exec mode new PC + +KSUPT UPT1PO ;PC saved here after one-proceed +1PROPC: 0 + +KSUPT UPT1PN ;One-proceed sets PC to this +1PRNPC: %PSPCU,,ONEPRO + +KSUPT UPTUUN +MUUOCN: %PSPCU,,UUOH0 ;Normal UUO new PC + +KSUPT UPTUUT +MUUOCT: %PSPCU,,MUUOTR ;UUO as trap instruction new PC + +EXPUNGE KSUPT + +] ;KS10P + +UUOACS: BLOCK 20 +AC0S: BLOCK 15 ;SWAP OUT AC S +AC15S: 0 +AC16S: 0 +AC17S: 0 + +IFN KL10P,[ +;KLUPT 500, ;PAGE FAIL WORD STORAGE ;MICROCODE MOD PUTS +;KLUPT 501, ;PAGE FAIL OLD PC STORAGE ; THESE LOCATIONS IN +;KLUPT 502, ;PAGE FAIL NEW PC ; THE EPT FOR ITS +] ;END OF IFN KL10P + +UUO:: ;THE FOLLOWING LOCATIONS (UP TO SUEXND) ARE SWAPPED IN & OUT OF + ;UEXIT ETC. WITH THE USER +SUEXIT: JRST 2,@XUUOH ;USER UUO EXIT INS +SCLUSV: MOVEM U,AC17S ;CLOCK U SAVE + +IFN KA10P,[ +SUUOH: 0 ;C(@41) (ABSOLUTE) +SUEXND:: + +SV40: 0 ;C(40) WHEN USER OUT (SEE SWITCH) +] ;KA10P + +IFE KA10P,[ +SCLCXS: DATAI PAG,CLCX ;CLOCK SAVE OF CONTEXT +SUEXND:: +] ;IFE KA10P + +IFN -, .ERR SUEXIT BLOCK LOST + +IFE KA10P,[ +CLCX: 0 ;SAVED CONTEXT (DATAI PAG,) AT CLKBRK AND PFAIL +] ;IFE KA10P + +IFN KL10P,[ +KLUPT 504, ;EBOX COUNT +EBOXCT: 0 ? 0 ;NUMBER OF EBOX TICKS (25 MHZ) OVER 2 LEFT 12. THAT EBOX + ;RAN FOR THIS USER +KLUPT 506, ;CACHE COUNT +MBOXCT: 0 ? 0 ;NUMBER OF MBOX CYCLES REQUESTED BY EBOX FOR THIS USER LEFT 12. + +EXPUNGE KLUPT +] ;KL10P + +UTIME: 0 ;RH=CLOCK INTERVAL IN 60'THS, LH=COUNT OF TICKS SINCE READ +UTRNTM: 0 ;TOTAL RUN TIME IN 4 MICROSEC UNITS +USIPRQ: 0 ;# SWAPIN REQUESTS + +USWST: 0 ;SWAPPING STATUS BITS. +%SW==525252(1) ;IN THE LEFT HALF +%SWDSO==400000 ;4.9 => DESIRED TO BE SWAPPED OUT (MUST BE SIGN BIT). +%SWPGW==200000 ;4.8 => FLSINS IS WAITING FOR A PAGE +%SWBEM==100000 ;4.7 => BEST EFFORT MADE TO SWAP OUT, DON'T LOOK AT JOB AGAIN +%SWRUN==040000 ;4.6 => SWAPPED OUT WHILE RUNNABLE, SO CONSIDER MEM STATUS BEFORE REACTIVATION + ; THIS BIT IS NEVER LOOKED AT. +%SWPCL==020000 ;4.5 => PAGE SWAPPED OUT WHILE BLOCKED IN EXEC MODE + ; SO WHEN FLSINS SKIPS DON'T CLEAR IT BUT PCLSR INSTEAD. +%SWINT==010000 ;4.4 => IF WAITING FOR PAGE, NEED IT TO INTERRUPT +%SWPRV==004000 ;4.3 => "PRIVELEGED USER" +IFN SWPWSP,[ +EXPUNGE %SWPRV +%SWOUT==000400 ;3.9 => JOB IS SWAPPED OUT OR SWAP BLOCKED +%SWSB== 000200 ;3.8 => JOB IS SWAP BLOCKED +%SWLOD==000100 ;3.7 => JOB IS LOADING + ;VALID STATES OF ABOVE 3 BITS: 0=SWAPPED IN, 1=LOADING, 4=SWAPPED OUT, 6=SWAP BLOCKED + +UWRKST: 0 ;WORKING SET. 2**18 TIMES SUM(ALL THIS JOB'S PAGES) 1 OVER # SHARERS + ;INCREMENTALLY MAINTAINED WHILE JOB IS LOADING OR SWAPPED IN. + ;NOTE # SHARERS IS IN RH(MMSWP) +USVWRK: 0 ;SAVES UWRKST AS OF LAST TIME SWAPPED IN +USWTIM: 0 ;TIME ENTERED LOADING, SWAPPED OUT, OR SWAP BLOCKED STATE. + ;WHILE SWAPPED IN, HAS THE TIME AT WHICH IT CEASES TO BE PROTECTED + ;AGAINST MEMORY PREEMPTION. +];SWPWSP +USWPRI: 0 ;JOB SWAP PRIORITY. LOWER NUMBER MEANS MORE LIKELY TO STAY IN + ; AND MORE LIKELY TO COME IN. SEE ALSO SWRCE, WHICH IS SIMILAR. +IFE SWPWSP, ;THIS IS THE AVERAGE (DECAYS BY 1/2 IN 30 SECONDS) OF THE PRODUCT + ;OF THE WORKING SET TIMES THE FRACTION OF CPU USED + ;WHICH IS A MEASURE OF MEMORY USE WITH INTERACTIVE JOBS GIVEN AN ADVANTAGE. +IFN SWPWSP, ;THIS IS THE AVERAGE (DECAYS BY 1/2 IN 30 SECONDS) OF THE "ADJUSTED + ;MEMORY USAGE", WHICH IS THE (LOGARITHM OF THE WORKING SET SIZE) + ;MULTIPLIED BY THE SUM OF CPU TIME AND I/O WAIT TIME. ALSO, WHEN + ;A DISOWNED JOB IS SWAPPED OUT, USWPRI IS MULTIPLIED BY 4 TO PREVENT + ;IT FROM COMING BACK IN FOR A WHILE UNLESS THERE IS REALLY NO + ;COMPETITION FOR MEMORY. ALSO, WHEN A SWAPPED-OUT JOB WAKES UP FROM + ;AN I/O WAIT, USWPRI IS DIVIDED BY 2 TO GIVE INTERACTIVE JOBS AN + ;ADVANTAGE. THE SWPWSP SYSTEM DOES NOT CURRENTLY LOOK AT SWRCE. +IFE SWPWSP,[ +USWSCD: 0 ;SWAP SCHEDULING WORD 4.9=1 SWAPIN INHIBITED THIS JOB (SWAP BLOCKED) +LTRNTM: 0 ;SAVED RUN TIME FOR PRIV USR +LSIPRQ: 0 ;SAVED SWAP IN REQ FOR PRIV USER +UPGSEC: 0 ;NUMBER OF PAGE FAULTS PER RUN TIME SECONDS +LPRVTM: 0 ;LAST TIME PRIV USER +];SWPWSP +PAGRAN: 0 ;.PAGRANGE. 1ST PG #,,LAST PG # INCLUSIVE RANGE OF PAGES TO BE PAGED AHEAD. +PAGAHD: 0 ;.PAGAHEAD. 0, OR PAGE-AHEAD-DISTANCE,,PAGE-BEHIND-DISTANCE + +TRUNTM: 0 ;IF NOT TOP LEVEL, MINUS RUNTIME (4.069 US) ALREADY SENT TO SUPERIOR + ;IF TOP LEVEL, RUNTIME USED BY SUBTREE MINUS TIME SENT TO DEMON ALREADY +TSIPRQ: 0 ;DITTO FOR SWAPIN REQUESTS +UTMPTR: SYSRCE ;POINTER TO RESOURCE WORD FOR THIS LOSER (JTMU FOR TREE) +JTMU: 0 ;REDUCED BY 1/16 EVERY 1/2 SEC + ;INCREMENTED BY TIME RUN IN 4 USEC + ;MAX EQV VAL 1000000/8-1/16X=0 + ;EQV VAL=2X10^6 + ;AMONG JOBS WITH EQUAL RESOURSE + ;LOWEST JTMU HAS HIGHEST PRIORITY + +IOCHNM: REPEAT NIOCHN,0 ;IO CHANNEL ASSIGNMENT + ;RH INDEX INTO IOTTB AND CLSTB + ;LH DEV CHNL AND/OR OTHER +SIOCHN: BLOCK LUIOP ;MUST FOLLOW IOCHNM + ;I/O CHANNEL PDL +SIOCP: SIOCHN-1 ;POINTER INTO I/O CHANNEL PDL +IOCHST: BLOCK NIOCHN ;I/O CHANNEL STATUS FOR CH'S AT IOCHNM + ;3.1-4.9 IO STATUS + ;1.1-2.9 .ACCESS POINTER + +CORRQ: -1 ;RQ TO CORE JOB + ;4.9=1=>NO REQUEST + ;4.8=0 OLD TYPE RQ,1.1-1.9 # BLKS,3.1-3.8=USR NUMBER RQ'ED FOR + ;4.8=1 NEW TYPE + ;4.3 ADD FRESH BLOCK (IGNORE 4.2,4.1) + ;4.1=1=> ADDING ABSOLUTE BLOCK + ;3.9=1=>REQUEST WRITE ABILITY + ;2.9=1 INSERT, =0 DELETE ONLY IGNORE 4.1-4.3 + ;2.1-2.8 VIRTUAL PAGE AFFECTED + ;1.1-1.9 USER RQ IS FOR + +APRC: APRCHN ;R.H. CONO TO APR WHEN USER STARTS (HAS AR OV ENABLE, ETC.) + ;4.9=1=> PROCEDURE IS IN A DISOWNED TREE +BUMRTL==100000 ;4.7 => GUN TREE IF HASN'T RUN FOR AN HOUR + ;(MEANINGFUL ONLY IN TOP LEVEL JOB). + ;CLEARED BY REOWNING OR ATTACHING. +BUSRCR==40000 ;4.6 CORE RQ PENDING ON THIS JOB +BULGO==20000 .SEE SYSGUN ;USER IS DISABLED, WAITING TO BE FLUSHED BY SYS JOB. +BCHPTR==330400,,APRC(U) ;4.1-4.4 LAST CH ON WHICH AN ERR OCCURED (SEE ERR DEV) +BULGOS==400 ;AN ATTEMPT IS BEING MADE TO DELETE OR LOG OUT THIS JOB + ;SO NO-ONE ELSE SHOULD START TO. THIS BIT ALSO LOCKS OUT + ;MOST WAYS OF HACKING THE JOB (INCL. THOSE THAT SET DIELOK). + ;3.1-3.5 MUST BE ZERO + +DIELOK: 0 ;NUMBER OF JOBS LOOKING AT OR HACKING THIS JOB. + ;BEFORE KILLING A JOB, WAIT FOR ITS DIELOK TO BECOME 0. + +USTP: 0 ;0 RUNNABLE, (IS SET NON ZERO FOR IDLE SETS OF VARS TO SPEED SEARCH) +%UST==1,,537777 +%USTCM==400000 ;CORE BEING SHUFFLED (SHOULD ACTUALLY BE OBSOLETE). +%USTCJ==200000 ;CORE BEING GIVEN BY CORE JOB. +%USTSP==100000 ;STOPPED BY SUPERIOR +%USTCG==40000 ;STOPPED BY SUPERIOR TO GIVE IT CORE (CORBLK, OR .USET OF .MEMT). + +BCSTOP==400000 ;BIT IN USTP FOR CORE MOVAGE +BUCSTP==200000 ;CORE STOPPING LOSER TO GIVE MORE CORE RQSTED BY ANOTHER LOSER +BUSRC==100000 ;USER CONTROL BIT, SET & CLEARED BY SUPERIOR PROCEDURE +BSSTP==40000 ;SET BY SUPERIOR WHEN HACKING MEM BOUND AT URMEMT OR UMEMEX +;1.1-2.9 ;USED BY UBO AND FRIENDS INHIBITS RELOCATION BY CORE ALLOCATOR + ;MUST BE MODIFIED WITH CLKOFF MUST NOT BE SET IF CSTOP IS SET + ;IS A COUNTER OF TRANSIENT REASONS FOR PROCEDURE BEING STOPPED + +PIRQC: 0 ;INT REQ AWAITING SERVICE (SOFTWARE INTS EFFECTED BY SEARCH) +MSKST: 0 ;INT MASK REGISTER FOR BITS IN PIRQC +IFPIR: 0 ;SECOND WORD OF INTERRUPT REQUESTS + ;3.8-3.1 INF PROC INT + ;2.7-1.1 IO CHANNEL INT + ;1.1= CHANNEL 0 +MSKST2: 0 ;INT MASK FOR IFPIR +IDF1: 0 ;DEFER BITS FOR 1ST WD INTERRUPTS. +IDF2: 0 ;FOR 2ND WORD INTERRUPTS. + ;IF AN INTERRUPT IS DEFERRED, IT IS TREATED AS + ;IF THE JOB'S PICLR VAR HELD 0. +PICLR: 0 ;INT IN PROGRESS FLAG, -1=>ENABLED, 0=>IN PROGRESS + +SUPPRO: 0 ;-1 => TOP LEVEL PROCEDURE + ;OTHERWISE: INT BIT,,PNTR TO SUPERIOR PROCEDURE + +FLSINS: 0 ;USER BLOCKING INSTRUCTION; STATE: + ; 0 => RUNABLE (UNLESS USTP .NE. 0) + ; OTHERWISE HUNG, IF NO SKIP SAFE TO RESTART AT UUO (UNLESS UFINAL .NE. 0) +RPCL: 0 ;0,,N RPCLSR'ING N + ;-1,,N BEING RPCLSR'ED BY N + +UNAME: 0 ;USER NAME + ;THIS WORD FOR EACH PROCEDURE IS COPIED FROM THE UNAME OF THE PROCEDURE + ;THAT CREATES IT (SEE USR DEV). FOR AN INITIAL TOP LEVEL PROCEDURE IT + ;IS INITIALLY -1 BUT IS MODIFIED BY ALOGIN. IT IS THE SAME FOR ALL + ;PROCEDURES IN A TREE. +JNAME: 0 ;JOB NAME + ;EACH LOGGED IN PROCEDURE HAS A UNIQUE UNAME, JNAME PAIR. THE JNAME + ;OF AN INITIAL TOP LEVEL JOB IS "HACTRN". FOR OTHER JOBS IT IS THE SECOND + ;FILE NAME SPECIFIED IN THE .OPEN ON THE USR DEVICE THAT CREATES THEM. +USYSNM: 0 ;USER SYSTEM NAME + ;THIS VARIABLE IS INITIALLY SET TO THE SAME VALUE AS UNAME FOR + ;A PROCEDURE. IT CAN BE READ OR WRITTEN BY THE PROCEDURE (ASUSET) + ;OR BY ITS SUPERIOR (AUSET). ITS ONLY USE IS AS THE DEFAULT THIRD FILE NAME ON + ;USER SHARED DEVICES (2311'S (SEE QSKO), AND CORE + ;LINK (SEE CLOO)). +USYSN1: 0 ;3RD NAME FOR QSKO, CLOO (AFTER DEFAULTING AND TRANSLATION) +HSNAME: 0 ;HOME SNAME + +IOTLSR: 0 ;4.9 IOT USER MOD (=1 ENABLES USER TO DO DIRECT I/O + ; INSTRUCTIONS) + ;RH VIRTUAL PAGE # OF LAST MPV, WIRO OR NXI (SHIFTED TO + ; ADDRESS SIZE) +UMARPC: 0 ;PC AT MAR INTERRUPT +LSWPR: 0 ;LOCKED SWITCH POINTER +UCLBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST UREALB +URTIME: 0 ;LH=0=>LOW PRIORITY PHASE 1=> LOW PRIORITY WITH BLOCKING + ;LH=-1=>HIGH PRIORITY PHASE 2=> HIGH PRIORITY WITH BLOCKING + ;RH=LENGTH OF HIGH PRIOITY IN 60'THS +RTIMER: -1 ;POSITIVE => MICROSEC RUNTIME TILL RUNTIME INT + +LSPCL: 0 ;UPC AT LAST PCLSR,,DIFFERENT UPC AT PREVIOUS PCLSR +LEXFDR: 0 ;DEBUGGING INFO FOR PAGE FAULTS WHICH SIGNAL AN INTERRUPT + ; TO THE LOSER + ;LH FAULT BITS OF LAST SUCH FAULT + ;RH PC OF LAST SUCH FAULT THAT WAS FROM EXEC MODE (WENT TO + ; IOADCR) + ;PAGE FAULTS WHICH JUST SWAP IN A PAGE DON'T SET THIS. +LSUUO: 0 ;LAST SYS UUO (FOR DEBUGGING PURPOSE) +LSCALL: 0 ;SIXBIT NAME OF LAST .CALL 0, (FOR PEEK) +CTLBTS: 0 ;CTL BITS TO .CALL 0, XORED TOGETHER IN HERE (RIGHT HALF) +SYSCVL: 0 ;CONTROLS OUTPUT ARGS FROM SYSTEM .CALL + %SCV==1,,525252 + %SCVOT==400000 ;4.9 CALL HAS OUTPUT ARGS FLAG (TO SAVE TIME) + %SCVER==200000 ;4.8 CALL HAS ERROR CODE ARG FLAG + ;3.6-4.7 UNUSED 3.1-3.5 MUST BE ZERO + ;1.1-2.9 ADDRESS OF ERROR CODE ARG +IOTBTS: 0 ;DEVICE-INDEPENDENT IOT CONTROL BITS GO HERE, IN IOT AND SIOT +USTYN: 0 ;TTY NO OF THE STY WHICH THIS JOB KNOWS AS "STY:" (WITHOUT + ; NUMBER). +UUAC: 0 ;AC FLD OF LAST UUO OR DESIRED CHANNEL IN CASE OF NOPEN ETC + ;SELECTS CHNL FOR ALL IOTS, OPENS ETC + ;LH -1 IF STORED BY CHNDCD, ELSE ZERO (SEE WHO LINE ROUTINES) +TRMNAM: 0 ;TERMINAL IDENTIFICATION +TRNLST: 0 ;TRANSL LIST FOR THIS JOB. -1 => NIL, OR IDX INTO TRAN!X +TRNLS1: 0 ;TRANSL LIST FOR THIS JOB & INFERS. +UTRAPM:: ;SIGN BIT OF OPTIONS IS UUO-TRAP-TO-SUPERIOR MODE +OPTION: 0 ;OPTIONS WORD, SETTABLE BY USER + ;EACH BIT CONTROLS SOME SYSTEM ACTION FOR THIS JOB + .SEE %OP +XUNAME: 0 ;"WHO I REALLY AM" AS OPPOSED TO "WHO I AM LOGGED IN AS" +XJNAME: 0 ;JOB NAME USER SPEC'ED AS OPPOSED TO UNIQUIZED VERSION + +40ADDR: 20,,40 ;RH=ADDRESS OF USER'S 6-WORD BLOCK FOR UUO'S, INTS, SWITCHES, LOCKING. + ;LH=ADDRESS OF USER'S 20-WORD BLOCK FOR SUPERIOR'S USE. 0=20. +IFN N11TYS,[ +TVCREG: -1 ;TV CONSOLE REG FOR THIS USER OF -1 NONE +TVVBN: -1 ;-1 OR CONSOLE REG FOR RUN BLINKING +NVDBA: 0 ;# VIDEO BUFFERS ASSIGNED (WITH NVDBA SYSTEM CALL). +];N11TYS +UWHO1: 0 ;WHOLINE FLAGS +UWHO2: 0 ;TWO HALFWORDS, PRINTING CONTROLLED BY UWHO1 4.9-3.3 +UWHO3: 0 ;TWO MORE HALF WORDS, CONTROLLED BY UWHO1 3.2-1.5 +IFN KL10P,[ +ULSPBR: 0 ;STBR,,GCSTBR FOR SPECIAL LISP INSTRUCTIONS +] +SERVER: -1 ;User index of server job who is allowed write access to + ; this job to implement some oddball protocol. -1 if none. +;INSERT NEW USER VARIABLES HERE^ + +USRPDL: -LUPDL,,UPDL-1 ;USER PDL +UPDL: BLOCK LUPDL-1 +EPDL2: 0 ;SAVES C(T) FOR FLSINS +QLD: 0 ;LINK DEPTH +VALUE:: ;PROCEDURE "VALUE" RETURN +SRN3: 0 ;SAVED N3, N4 FOR RENAMES AT AOPEN ALSO USER INDEX AT NLOAD + ;SRN3, SRN4 USED BY CORBLK .CALL +.SEE IODCS2 ;SRN3 contains saved user mode PC for unlocking own locks. +.SEE ALOGO4 ;NO CLOSE ROUTINE MAY USE SRN4 OR SRN5 +SRN4: 0 ;ALSO DEVICE CHNL IOCHNM POINTER AT NLOAD +SRN5: 0 ;SAVED N5 FOR LINK ALSO VIRTUAL PAGE NUMBER AT NLOAD +EPDL3: 0 ;USED BY 2311 ROUTINES (QFNG) ALSO QSMDN ADDR AT NLOAD ALSO BY TYOW2 +.SEE ALOGO4 ;NO CLOSE ROUTINE MAY USE EPDL + ;FOR BP-STYLE RENAME, RENMWO AND MLINK, + ;HOLDS BP (OR BP BLK PTR) TO NAMES TO RENAME OR LINK TO. +EPDL: 0 ;USED BY 2311 ROUTINES. + ;FOR SOPEN AND BP-STYLE RENAME, DELETE, HOLDS BP OR BP BLOCK PTR. +EPDLT1: 0 ;FN1 BEFORE LAST TRANSLATION, USED BY NLOAD +EPDLT2: 0 ;FN2 " " " , USED BY NLOAD +EPDLT3: 0 ;SYS NAME " " " +EPDLT4: 0 ;LEFT ADJ DEVICE NAME " " " + +STTYOP: 0 ;IN THE TOP OF A DETACHED TREE, THIS CONTAINS THE SAVED USER TTY + ; OPTIONS. 2.9=1 IF IT IS VALID, 2.7-2.8 ARE QUERY AND REFUSE MODE, + ; THE REST ARE TTYOPT BITS. + +IFN 0,[ ;FAKE OUT @ +LSWB0: +] +REPEAT NULBLK,[ +CONC LSWB,\.RPCNT,: BLOCK 2 +] ;SWITCH BLOCK FORMAT + ;WD1 ASSOCIATED ADDRESS OR QUANTITY + ;3.6-3.1 USER NUMBER OF SWITCH HOLDER + ;2.9-1.1 PNTR TO NEXT SWITCH ON LIST OR 0 IF NONE + ;FOR REMAINDER OF FORMAT SEE LSWDIS + +IFN KL10P,[ +IFGE USRSTG+1000-., INFORM SPACE LEFT IN UPT,\1000-<.-USRSTG> +IFL USRSTG+1000-., .ERR USER VARS TOO BIG FOR UPT! +.ELSE LOC USRSTG+1000 +] ;IFN KL10P + +IFN KS10P, LOC <.+7>&-10 ; KS UPT must be 0 mod 8 (see UUOPCW) + +LUBLK==.-USRSTG +L==LUBLK +INFORM [STORAGE PER LOSER]\LUBLK + BLOCK LUBLK ;USER VARIABLES FOR CORE JOB +SYSB==<1777+.>_-10. +MXC==SYSUSB-SYSB ;AVAIL BLOCKS AFTER SYS+DDT + + SUBTTL TSS INITIALIZATION +;NEXT LINE COMMENTED OUT BECAUSE IT CAUSES MORE TROUBLE THAN IT SAVES +;.HKALL==1 ;(THE FOLLOWING CODE IS WIPED OUT AT ICLR) +EXEUMP=UPGMP+100 ;EXEC UPPER MAP LIVES IN SYSTEM JOB'S PAGE TABLE + ;SYMBOL IS DEFINED HERE SINCE UPGMP WAS JUST DEFINED 6 PGS AGO + +BEG: SKIPN SALV ;SEE IF LOSER FORGOT TO LOAD SALV WHEN BUILDING SYSTEM, + ;OR SALV MEM IS NXM. EVIL! EVIL! + BUG AWFUL,[HEY! WHERE'S THE SALVAGER?] + JSR SALV+1 ;CALL NO-QUESTIONS-ASKED SALVAGER +GO: JFCL 17,.+1 + JRST .+1 + JFCL 1,[JRST 4,.] ;SYSTEM WONT RUN ON 6 +IFN KL10P,[ + CONSO PAG,600000 + SWPIA ;IF CACHE OFF, FLUSH CRUFT THAT MAY BE IN IT + CONSZ PAG,600000 + SWPUA ;IF CACHE ON, UPDATE CORE SO DDT IS GOOD + CONSZ 200000 + JRST .-1 + SPCCTX 0,1,USRSTG,DISABLE ;SET UP UPT ADDR, BUT NO ACCTING TILL + MOVEI T,0 ;MORE INIT IS DONE. + XCTR XBW,[BLT T,17] ;CLEAR BLK 1 TO AVOID RANDOM PARITY + ; ERRORS +] ;KL10P +IFN KS10P,[ + CONO 20700+APRCHN ; Clear memory related APR flags + ; (ECC, Bad, NXM) + MOVSI TT,%KEHLD+%KEREF+%KEPWR + IOWR TT,[KSECCS] ; Reset memory status register. + MOVEI TT,%UBTIM+%UBBAD+%UBPAR+%UBNXD+%UBINI + IOWRQ TT,UBASTA ; Reset both Unibus's and both adaptors. + IOWRI TT,UBASTA + MOVEI TT,DSKCHN_3 ; Set PI level for RH11. (No, you can't do + IOWRQ TT,UBASTA ; this at the same time you reset the Unibus.) + MOVEI TT,MTCCHN_3+TTYCHN ; PI for Tape, for Chaos and TTYs. + IOWRI TT,UBASTA + WRHSB [HSB] ; Set halt status block location. + CLRCSH ; Reset cache once for good measure. + SPCCTX 0,1,USRSTG ; Set up UPT and AC blocks. +] ;KS10P +IFN TEN11P,[ + MOVEI TT,600000+ + SKIPGE TEN11F + MOVEI TT,0 + DPB TT,[.T11CP+EXEUMP] + SETOM T11MP+_-10. ;DONT USE MAP PAGE AS 10-11 PAGE +;IFN PDP6P,[ ;THESE ARE IN SEPARATE MOBIES NOW +; MOVE TT,[-LPDP6M,,_-10.] +; SETOM T11MP(TT) ;CONFLICTS WITH PDP-6 MEM +; AOBJN TT,.-1 +;] +;IFG TSYSM-256.,[ +; MOVSI TT,-TSYSM+256. +; SETOM T11MP(TT) ;CONFLICT PAGES +; AOBJN TT,.-1 +;] +] + MOVE P,SYSPDP + +;INIT THE EXEC PAGE MAP'S DDT PAGES. + HRRZ A,DDT-2 ;LOWEST ADDR IN SYMBOL TABLE + SUBI A,100 ;LEAVE ROOM FOR EXTRA SYMS, 340 ROUTINES' LOSSAGE, ETC. + LSH A,-10. ;GET PAGE SYMTAB STARTS IN + MOVEM A,FDDTPG + MOVEI Q,NQS-1 ;PUT THE TUTS JUST BELOW THE DDT PAGES +BEGTT1: SKIPE QACT(Q) + JRST BEGTT3 ;UNIT NOT IN USE + MOVE T,NTBL(Q) ;NUMBER OF PAGES IN THIS TUT +BEGTT2: SUBI A,1 + MOVE B,[MU23TT_<.TZ .BM >] + MOVEM B,MEMBLT(A) + DPB Q,[MNUMB,,MEMBLT(A)] + SOJG T,BEGTT2 + MOVE B,A + LSH B,10. + HRLI B,640000 + MOVEM B,QTUTO(Q) +BEGTT3: SOJGE Q,BEGTT1 + MOVEM A,FTUTPG + ;NOW MAKE SURE ALL THOSE PAGES ARE MAPPED + MOVEI B,-200(A) ;ASSUMING TSYSM AT LEAST 128K + LSH B,-1 ;GET A B.P. TO IDPB MAP HWD OF 1ST DDT PAGE + ADD B,[442200,,EXEUMP] + TRNE A,1 + IBP B + MOVEI C,600000+PMCSHM(A) ;COMPUTE CONTENTS OF THAT MAP WORD. + MOVE D,[MUDDT_<.TZ .BM >] +BEG3: CAML A,FDDTPG + MOVEM D,MEMBLT(A) +IFG TSYSM-128., IDPB C,B + AOS C +IFG TSYSM-400, CAIE A,400 +.ELSE CAIE A,TSYSM ;STORE THAT MAP WORD AND ALL REST THERE ARE. + AOJA A,BEG3 + +;INITIALIZE REST OF EXEC PAGE MAP +IFN DIRMAP,[ + MOVE Q,[222200,,EXEUMP] + SETZB A,B + SKIPE USEMDM ;MAKE MEDIUM MEM NXM IF DIRMAP NOT TURNED ON + MOVEI B,600200+PMCSHM ;THIS MAY BE USEFUL FOR DEBUGGING + MOVE T,FTUTPG + SUBI T,201 ;STOP AT 1ST TUT PAGE. +BEG2: CAIL A,NEXPGS + DPB B,Q + IBP Q + ADDI B,1 + CAMGE A,T + AOJA A,BEG2 +];END IFN DIRMAP +;DROPS THROUGH + ;DROPS IN + +;SET UP EXEC LOWER MAP (EVEN ON KA, WILL BE LOOKED AT BY .CALL CORBLK) + MOVE A,[600000,,600001+PMCSHM] ;PAGE 0 IS NOT CACHED + MOVSI B,-100 + MOVEM A,EXELMP(B) + TLO A,PMCSHM + ADD A,[2,,2] + AOBJN B,.-3 + +;SET UP SYS JOB'S CIRCULAR POINTERS SO ALL THE PAGES IT HAS ARE ABSOLUTE + + MOVE A,[442200,,UPGMP] + MOVE B,[442200,,UPGCP] + MOVEI D,0 +BEG6: ILDB T,A + MOVEI E,-1 + JUMPN T,BEG7 + CAIL D,200+MMP0 ;ALLOW USERS TO COPY MMP EXEC PGS + CAILE D,200+NEXPGS + MOVEI E,0 ;PG IT DOESN'T HAVE, AND NOT COPYABLE EXEC PG +BEG7: IDPB E,B + CAIGE D,377 + AOJA D,BEG6 + +;EXEC MAP PREPARED, NOW TURN ON PAGING + +IFN KA10P,[ + LPMR UPGML + CONO 633550 +] ;KA10P +IFN KS10P,[ + CONO 67760 ; Disable and Clear all flags + CONO 127660 ; Enable and Clear all flags except memory ECC + APRID A + TLNN A,%UCITS + BUG AWFUL,[ITS WON'T RUN WITH THE DEC MICROCODE] + LDBR3 EXEUMP ; Load exec DBRs. + LDBR4 EXELMP + LPMR UPGML + SPCCTX 1,1,USRSTG ; Select AC blocks and set UBR. + WREBR 020000+ ; Paging on and set EBR. +] ;KS10P +IFN KL10P,[ + CONO 327740 ;ENABLE AND CLEAR ALL FLAGS EXCEPT SWEEP DONE + APRID A + TLNN A,%UCITS + BUG AWFUL,[ITS WON'T RUN WITH THE DEC MICROCODE] + SPCCTX 6,6 ;LOAD MICROCODE CONSTANTS NEEDED BY PAGEING INTO + ; BLOCK 6. + MOVEI 3,EXEUMP ;DBR3 + MOVEI 4,EXELMP ;DBR4 + MOVSI 5,PMAGEM ;LH.AGE + MOVEI 6,PMAGEM ;RH.AGE + MOVEI 7,1000 ;CN1000 + MOVEI 10,100 ;CN100 + CONO PAG,660000+ ;CACHE ON, ITS PAGER, TRAP ENB, EPT ADDR + SPCCTX 1,1,USRSTG,DISABLE + LPMR UPGML +] ;END IFN KL10P + MOVE P,SYSPDP + +;INITIALIZE FREE LISTS IN MEMBLT + + MOVEI A,1 ;A PG NO - NOTE: DON'T DO PAGE ZERO +BEGF0: CAML A,FTUTPG ;IF THIS ISN'T A DDT OR TUT PAGE, THEN + CAIL A,400 + PUSHJ P,CIMEMR ;PUT THIS PAGE ON THE RIGHT FREE LIST + CAIGE A,TSYSM-1 + AOJA A,BEGF0 +IFN TEN11P,[ + SKIPGE TEN11F + JRST BEG4 + MOVSI A,-256. ;CLEAR THE INTERFACE'S "VALID" BITS. + SETZM 400000+T11CP*2000(A) + AOBJN A,.-1 +BEG4:] +IFN XGP,[ + SKIPE TEN11F + JRST BEGX1 + MOVE A,[600000+,,1777] + PUSHJ P,T11AD + BUG ;NO 10-11 PAGES AVAILABLE? + MOVEI TT,600000+<_8>(B) ;GET CORRESP EXEC MAP PG SETUP + DPB TT,[.XGPC+EXEUMP] + MOVEI TT,600000+<_8>+XGPTP + DPB TT,[.XGPB+EXEUMP] ;SETUP PAGE FOR PDP-11 BUFFER +BEGX1:] + +;CHECK AVAIL MEM FOR EXISTANCE + +IFN ECCMEM,[ + LDB TT,[121200,,ECCADR] ;GET PAGE THAT ECC HISTORY IS ON + IORI TT,200000 ;GRANT READ ACCESS + DPB TT,[.ECCPG+EXEUMP] + LPMR UPGML + MOVE A,400000+ECCPG*2000+1760 ;GET CURRENT HISTORY POINTER + LSH A,-32. + MOVEM A,ECCIDX +];ECCMEM + MOVEI A,TSYSM-1 +CKML: MOVEI TT,600000(A) + DPB TT,[.PAREP+EXEUMP] + LPMR UPGML +IFN ECCMEM,[ + LDB TT,[121200,,ECCADR] ;GET PAGE THAT ECC HISTORY IS ON + CAMN A,TT ;THIS PAGE? + JRST CKML1A ;YES, TREAT AS IF OFFLINE, THOUGH WILL ACCESS IT + ; DIRECTLY FROM TIME TO TIME +] + MOVE TT,A + LSH TT,10. + MOVSI T,-8 + CAML TT,MEMLZL(T) + CAML TT,MEMLZH(T) + AOBJN T,.-2 + JUMPL T,CKML1A ;THIS BLOCK KNOWN TO BE LOSING + SKIPL USEHM + CAIGE A,256. + JRST .+2 + JRST CKML1A ;HIGH MOBY NOT TO BE USED +IFN KL10P,[ + MOVEI TT,CKML1 ;KL10 CAN GET PARITY FAULT ON REFERENCE TO NXM + MOVEM TT,PFNPC + HRRM TT,MUUOKN ;IT CAN ALSO GET A UUO +] ;KL10P +IFN KS10P,[ + MOVEI TT,CKML1 + MOVEM TT,EPTPFN +] ;KS10P + CAIL A,256. ;IF NOT IN BOTTOM 256K, DON'T ASSUME GOOD DATA + SETZM 400000+PAREP*2000+20 ;STORE ZERO SO DON'T GET PARITY ERROR + MOVE 0,400000+PAREP*2000+20 ;IF THIS NXMS, MEM THE SYS THINKS + ; IT HAS IS NON EXISTANT +IFN KA10P,[ + CONSZ 10000 + JRST CKML1 ;THAT MEM NXM +] ;KA10P +IFN KL10P,[ + MOVEI TT,PFAIL + MOVEM TT,PFNPC + MOVEI TT,UUOH0 + HRRM TT,MUUOKN + CONSZ 2000 + JRST CKML1 ;THAT MEM NXM +] ;KL10P +IFN KS10P,[ + MOVEI TT,PFAIL + MOVEM TT,EPTPFN + CONSZ 400 + JRST 4,. ; This can't happen, right? (If we got a NXM, we + ; would have trapped to CKML1 already.) +] ;KS10P + SKIPL CKMBLK ;WINS + JRST CKML6 ;THUS ENDING BLOCK OF LOSERS +CKML2: SOJGE A,CKML + AOSN CKMFLG ;ANY MEM OFF UNEXPECTEDLY? + JRST CKML5 ;NO + MOVEI TT,[ASCIZ/ +IS THIS OK? /] ;YES, MAKE SURE SOMEBODY KNOWS ABOUT IT. MAY BE SERIOUS SCREW. + PUSHJ P,T00ASZ + PUSHJ P,T00TYI + ANDI A,137 + CAIE A,"Y + JRST DDT + MOVEI TT,[ASCIZ/ +/] + PUSHJ P,T00ASZ ;CRLF +CKML5: +IFN KL10P,[ + CONO 26400 ;CLEAR ANY NXM AND PARITY INTERRUPTS + CONI MTS,TT + TLNN TT,400 + BUG PAUSE,[TAPE DF-10 IS IN KA MODE, PLEASE FLIP THE SWITCH] + CONI DSK,TT + TLNN TT,4000 + BUG PAUSE,[DISK DF-10 IS IN KA MODE, PLEASE FLIP THE SWITCH] +] ;KL10P +IFN KS10P, CONO 20400 ; Clear NXM flag +;DROPS THROUGH + ;DROPS IN + +IFN RP10P,[ + DATAI DPC,A + TLNN A,NOWRIH ;CHECK FOR FORMAT SWITCH ON RP10 + BUG PAUSE,[RP-10 WRITE HEADERS ENABLED, PLEASE FLIP THE SWITCH] +];RP10P + +IFE &,[ ;CHECK FOR LOSING SWITCHES ON MEMORY ON ML-KA AND DM + + MOVSI D,(DWRITC) ;MAKE COMMAND FOR VERY LAST BLOCK ON DISK + MOVEI A,NCYLS+XCYLS-1 + DATAO DPC,[DNOOPC] ;DETERMINE TYPE OF DRIVE 0 + DATAI DPC,B + TRNE B,RP03BT + MOVEI A,MCYLS+XCYLS-1 ;RP03 + DPB A,[DCYL D] + LSH A,-8 + DPB A,[DCYLXB D] + MOVEI A,NHEDS-1 + DPB A,[DSURF D] + ADDI D,QICWA + MOVEM D,CKMSWC + SUB D,[DWRITC-DREADC] + MOVEM D,CKMSRC + SUB D,[DREADC-DSEEKC] + MOVEM D,CKMSSC + MOVEI A,0 +CKMS1: LDB TT,[MUR,,MEMBLT(A)] ;MEM EXIST? + CAIE TT,MUFR ;AND NOT DDT? + JRST CKMS2 + MOVEI B,600000(A) + DPB B,[.PAREP+EXEUMP] + LPMR UPGML + CAIGE A,CKMSZZ ;MEM LOADED? + JRST CKMS3 ;YES + MOVSI B,'FOO ;NO, LOAD IT + MOVEM B,CKMSBF + MOVE B,[CKMSBF,,CKMSBF+1] + BLT B,CKMSBF+177 + MOVEI B,'BAR + HRRM B,CKMSBF+69. + HRRM A,CKMSBF+6 ;MAKE DIFF FROM OTHER SUCH PAGES + MOVEI C,1 + MOVE B,A + LSH B,-4 ;16K BLOCK # IN B + LSH C,(B) ;GET UNIQUE BIT SO PARITY ERR IF TWO AT SAME ADDR + MOVEM C,CKMSBF+35 + MOVE B,[CKMSBF,,400000+PAREP*2000] + BLT B,400000+PAREP*2000+177 +CKMS3: MOVE B,A ;MAKE IOWD + LSH B,10. + SOS B + HRLI B,-200 + LDB C,[100300,,A] ;MA 15-17 + TRC C,7 + DPB C,[410300,,B] + MOVEM B,QICWA + SETZM QICWA+1 + CONO DPC,175700 + DATAO DPC,CKMSSC ;POSITION HEADS + CONSO DPC,10 + JRST .-1 + DATAO DPC,CKMSWC ;WRITE OUT SECTOR + CONSZ DPC,20 + JRST .-1 + CONI DPC,B + TLNE B,17 + JRST CKMS4 ;CHANNEL ERROR MEM LOSING + TRNE B,177700 + JRST CKMS2 ;FOO, DISK LOSING + MOVE B,[-200,,CKMSBF-1] ;READ IT BACK + MOVEM B,QICWA + SETZM QICWA+1 + SETZM CKMSBF+69. + CONO DPC,175700 + DATAO DPC,CKMSRC + CONSZ DPC,20 + JRST .-1 + CONI DPC,B + TLNE B,17 + JRST CKMS2 ;MEM LOSS IN CKMSBF? + TRNE B,177700 + JRST CKMS2 ;FOO, DISK LOSING + MOVSI B,-200 ;COMPARE + MOVE C,CKMSBF(B) + CAME C,400000+PAREP*2000(B) + JRST CKMS4 ;NOT SAME SWITCHES LOSING + AOBJN B,.-3 +CKMS2: +IFE MCOND DM, ADDI A,16. ;MA10'S !! +IFE MCOND MLKA, ADDI A,32. ;ML-KA MEM IS IN 32K MODULES + CAIGE A,TSYSM + JRST CKMS1 + CONO DPC,175700 ;RESET THE DISK CONTROL + DATAO DPC,[DEASEC+776] ;AT EASE! + CONO PI,20000 ;TURN OFF IOB PI REQ LIGHT + JRST CKMSX ;DONE WITH THIS, CONTINUE INITIALIZATION + +CKMSBF: BLOCK 200 + +CKMS4: MOVEI TT,[ASCIZ/MEM ADDR SWITCHES DISAGREE CPU VS DSK AT LOC /] + PUSHJ P,T00ASZ + PUSHJ P,T00BKO + MOVEI TT,[ASCIZ/0000/] + PUSHJ P,T00ASZ + JRST DDT + +CKMSZZ==./2000+2 ;ABOVE HIGHEST CODE + +CKMSX: +] ;END IFE MCOND MLKA & DM + ;DROPS IN + MOVEI TT,0 + DPB TT,[.PAREP+EXEUMP] + LPMR UPGML +IFN KA10P, CONO PI,240000+11577+IFN C1MXP,20000 +IFE KA10P, CONO PI,11577 +IFN NOTYS, CONO TTY,TTYCHN +IFN NETYS,[ + SETOM DTEODN ;CAN GET SET ON WHILE LOADING, BUT INTR GETS LOST +IFE PDCLKP, CONO DTE,1170+APRCHN ;CLEAR ALL FLAGS AND ASSIGN PI CHANNEL +IFN PDCLKP, CONO DTE,1170+TTYCHN ;CLEAR ALL FLAGS AND ASSIGN PI CHANNEL +] ;END OF IFN NETYS +IFN E.SP,[ + CONO DIS,515330 ;RESET E&S + MOVEI TT,E.SPM + MOVEM TT,34 ;SET PAGER LOC (USED BY DSKDUMP) +] +IFN TM10B,[ + MOVEI TT,MIOWD + MOVEM TT,MICWA ;SETUP LOC FOR MEM CHAN TAPE +] +IFN RP10P+RH10P,[ + MOVEI TT,QIOWD + MOVEM TT,QICWA ;SETUP FOR DEC DISK CHANNEL +] +IFN ARMP, DATAO 760,[0] ;RESET LITE ON ARM +IFN DSDP, CONO DSDEV,10 ;RESET INT RQ FROM PDP10 +IFN RBTCP, CONO RBTCON,0 ;RESET TABLET + + MOVE A,DDT-2 ;PUT GLOBAL BLOCK HEADER AT BEGINNING + MOVE B,[SQUOZE 0,GLOBAL] + CAME B,(A) ;SEARCH FOR GLOBAL BLOCKS + AOBJN A,[ AOBJN A,.-1 + JRST BEGS1] + MOVE C,DDT-2 + MOVEI D,(C) + SUBI D,(A) ;GET ,,-#WDS BEFORE GLOBAL BLOCK + MOVSI D,(D) + ADDM D,1(A) ;GLOBAL BLOCK NOW LARGER + EXCH B,(C) ;EXCHANGE IT WITH FIRST SYM + MOVEM B,(A) + MOVE B,1(A) + EXCH B,1(C) + MOVEM B,1(A) +BEGS1: PUSHJ P,SBUBL + JUMPL J,BEGS1 ;KEEP SORTING UNTIL SYMS IN ORDER + MOVSI A,400000 + IORM A,DDT-1 + +; SORT THE UUO/SUSET/BIT SYMBOL TABLE BY VALUE + + MOVE E,[SYSYMB-SYSYME-1,,SYSYMB] + PUSHJ P,SBUBL0 + JUMPL J,.-2 + + MOVE A,[-LTSTB,,TSTB] +BEG1: MOVE B,(A) + MOVEI C,(B) + EQV C,(B) + AOBJN B,.-1 + MOVEM C,CKSUMS-TSTB(A) + MOVE B,(A) +CKXC2: MOVE C,(B) +REPEAT 36.,[ + IFL .RPCNT-18., TLNE C,400000_<-.RPCNT> + .ELSE TRNE C,400000_<18.-.RPCNT> + XORM B,CKXORS+.RPCNT +] + AOBJN B,CKXC2 + AOBJN A,BEG1 + HRRZS 37 ;MAKE SURE SYS DOESNT IMMEDIATELY COME DOWN +;DROPS THROUGH + ;DROPS IN + MOVEI A,0 + CLEARM QACTB +QSETUP: MOVE B,DCHBT(A) + SKIPN QACT(A) + IORM B,QACTB + CAIGE A,NQS-1 + AOJA A,QSETUP +IFN DC10P, CONO DC0,DCCSET+DCDENB+DSKCHN ;RESET 2314 AND SET DATA ERROR ENABL +IFN 340P, CONO DIS,100 +IFN TK10P, CONO NTY,TTYCHN +IFN MTYP, CONO MTY,TTYCHN + CLEARM USRHI + CLEARB U,USER + MOVE P,SYSPDP +IFN DPKPP,[ + CONO DPK,400070+TTYCHN ;INITIALIZE DP KLUDGE + DATAO DPK,[4,,DPKBAS] + MOVE T,[-NDPTYS,,NFDPTY] + MOVEI B,0 ;LINE # +DPIL: LDB A,[$TTOSP,,TTYTYP(T)] ;OUTPUT SPEED + MOVE A,DPSP(A) ;MAP TO DPK SPEED CODE + DPB B,[140400,,A] ;LINE # + CONO DPK,500+TTYCHN(A) ;LOAD OUT SPEED + LDB A,[$TTISP,,TTYTYP(T)] ;INPUT SPEED + MOVE A,DPSP(A) ;MAP TO DPK SPEED CODE + DPB B,[140400,,A] + CONO DPK,700+TTYCHN(A) ;LOAD IN SPEED + AOS B + AOBJN T,DPIL +] +IFN DZ11P,[ + PUSHJ P,DZINIT +];DZ11P +IFN N11TYS,[ + SKIPE TEN11F + JRST BEG5 + MOVSI R,-NTTPG-NTVBP+1 + MOVE T,[.TTPG0+EXEUMP] +BEG9: MOVEI A,(R) ;SET UP 1 MORE TEN-11 MAP ENTRY + LSH A,20. + IORI A,1777 ;A FULL PAGE + TLO A,600000+TT11NM*400 + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> ;READ-WRITE, IN HIGH MOBY. + DPB B,T + IBP T + AOBJN R,BEG9 + MOVE A,[(600000+TT11NM*400)TT11CR_8] ;POINTER TO CONSOLE REG + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> + DPB B,T + LPMR UPGML + SKIPE TT11P ;IF WE'RE SUPPOSED TO USE THE TV 11, + SETZM TT11UP ;REQUEST IT TO RE-INIT. + ;IF TT11UP BECOMES NONZERO, THE 11 IS UP. +BEG5: ];END IFN N11TYS +IFN CH11P,[ + XCTRI [IORDI A,CAIMYN] + CAIA + BUG HALT,[CHAOSNET INTERFACE NOT RESPONDING (CHECK THE BREAKER ON THE UNIBUS)] +] ;CH11P +IFN CHAOSP,[ IFN T11CHP,[ + SKIPE TEN11F ;SET UP TEN-11 CHAOS NET INTERFACE PAGE + JRST BEG8 + MOVE A,[(600000+CH11NM*400)1004_8+1777] + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> + DPB B,[.CHSPG+EXEUMP] +BEG8: ]] ;CHAOSP, T11CHP +IFN DL10P,[ ;INITIALIZE DL10 + CONO DLC,400000 ;MR CLR + CONO DLB,1 ;TURN OFF EXCESS LIGHTS + CONO DLB,2 ;.. + CONO DLB,3 ;.. + CONO DLB,DL10AR ;64 WORDS FOR PDP11 #0 AT DL10AR + DATAO DLC,[200001,,] ;KA INTERRUPT MODE + SKIPE DL10F + CONO DLC,100020+TTYCHN ;ENB PDP11 PORT #0 AND ENB INTR + MOVSI T,1 + SKIPN DL10UP + SOJG T,.-1 + SKIPGE T ;IF THE 11 DIDN'T SAY IT WAS UP, + SETZM DL10F ;MARK IT NON-FUNCTIONAL. +] +IFN KL10P,[ + CONO TIM,460000+3900. ;SET INTERVAL TIMER TO 39 MILLISECONDS FOR OVHMTR + CONO MTR,433001 ;TIME BASE ON, ACCOUNT FOR USER + EXEC NO PI, INTERVAL PIA=1 + PUSHJ P,PRFOFF ;INIT PERFORMANCE COUNTER +] ;KL10P + +;DROPS IN + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;SYS JOB HAS NO CONSOLE ALL TO ITSELF + MOVEI U,LUBLK + PUSHJ P,USSINI ;INITIALIZE SYS JOB VARIABLES BLOCK + JRST .-1 + AOS NMPGS +IFE KA10P,[ + MOVEI T,UUOH0 ;CLOBBERED BY USSINI + HRRM T,MUUOKN +] ;IFE KA10P + MOVSI T,600000 + HLLM T,UPGMP ;GIVE PG 0 TO SYS JOB + MOVSI T,-1 + HLLM T,UPGCP + MOVEI T,2000 + MOVEM T,HUSRAD + MOVEI T,SYSRCE ;SET SYS JOB RESOURCE POINTER + MOVEM T,UTMPTR + MOVSI A,(SIXBIT /SYS/) ;""" NAMES + MOVEM A,USYSNM(U) + MOVEM A,UNAME(U) + MOVEM A,XUNAME(U) + MOVEM A,JNAME(U) + MOVEM A,XJNAME(U) + SETZM USTP(U) + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;CORE JOB HAS NO CONSOLE + MOVEI U,2*LUBLK + PUSHJ P,USSINI ;SET UP CORE JOB VARIABLES BLOCK + JRST .-1 + MOVE A,[SIXBIT /CORE/] + MOVEM A,USYSNM(U) + MOVEM A,UNAME(U) + MOVEM A,XUNAME(U) + MOVSI A,(SIXBIT /JOB/) + MOVEM A,JNAME(U) + MOVEM A,XJNAME(U) + MOVEI T,SYSRCE + MOVEM T,UTMPTR+LUBLK + SETZM USTP(U) + MOVEI A,CORJI +IFE KA10P, HRLI A,%PSPCU ;DOES CORE JOB XCTR? + MOVEM A,UPC(U) +IFE KA10P,[ + MOVE T,[JSR ILLTRP] ;SYS AND CORE JOBS SHOULDN'T TRAP + MOVEM T,TR1INS ;THESE WON'T BE USED ANYWAY UNLESS + MOVEM T,TR2INS ;SOMEDAY THEY SHOULD RUN IN USED MODE + MOVEM T,TR3INS + MOVEM T,TR1INS+L + MOVEM T,TR2INS+L + MOVEM T,TR3INS+L +] ;IFE KA10P + MOVEI A,SYSB+2 ;GIVE SYSTEM CORE TO SYS JOB, WITH A COUPLE + MOVEM A,CORRQ ; SPARE JOB SLOTS + AOS NCORRQ + SOS A + ADDM A,NCBCOM +; DATAI CLK1,LCLK1 + CONO PI,100+UTCON-1 ;ALL EXCEPT 7 +IFN KA10P, CONO 3000+APRCHN +IFN KL10P,[ +IFN PDCLKP, CONO CLK,APRCHN +.ELSE [ MOVEI A,%DTCLN ;TURN ON 60-CYCLE CLOCK + MOVEM A,DTECMD + SETZM DTEFLG + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] + CONO APRCHN ;ENABLE APR FAULT INTERRUPTS + SWPUA ;UPDATE MEMORY AGAIN TO MAKE SURE DDT + SYMBOL + ; TABLE OUT OF CACHE + CONSZ 200000 + JRST .-1 +] ;KL10P +IFN KS10P,[ + WRINT [KSFREQ] ; 60 cycle clock. + CONO APRCHN ; Enable APR faults and clock ints. + CLRCSH ; Is this necessary? What the heck... +] ;KS10P +IFN CH10P,[ + CONI CHX,T ;CHECK CHAOS ADDRESS SWITCHES + LDB T,[$CHXAD,,T] + CAIE T,MYCHAD + JRST [ MOVEI TT,[ASCIZ/CHAOSNET ADDRESS SWITCHES ARE SET WRONG/] + PUSHJ P,T00ASZ + JRST DDT ] + CONO CHX,@CHXCNO ;ENABLE INTERRUPTS +];CH10P + JRST ICLR + +CKML1: ;MEM NON-EXISTANT PATCH OUT +IFN KA10P, CONO 10000 ;TURN OFF NXM FLAG +IFN KL10P,[ + CONO 22000 + MOVEI TT,PFAIL + MOVEM TT,PFNPC + MOVEI TT,UUOH0 + HRRM TT,MUUOKN +] ;KL10P +IFN KS10P,[ + CONO 20400 + MOVEI TT,PFAIL + MOVEM TT,EPTPFN +] ;KS10P + SKIPGE CKMBLK + MOVEM A,CKMBLK ;HIGHEST IN BLOCK OF LOSERS +CKML1A: LDB TT,[MUR,,MEMBLT(A)] + CAIE TT,MUFR + BUG ;? + CAIG A,SYSB+1 + JRST 4,. ;SYS MEM NON EX? (BUG PROBABLY WON'T WORK) + PUSHJ P,MPOUT2 ;FLUSH THAT BLOCK + MOVEI TT,MUHOLE + DPB TT,[MUR,,MEMBLT(A)] + CAIL A,400 ;IF NXM IN LOW MOBY + JRST CKML2 + MOVEI U,0 + PUSHJ P,UPLC + LDB TT,T + ANDI TT,PMRCM + CAIE TT,(A) + JRST CKML2 + DPB U,T ;PATCH THIS BLOCK OUT OF EXEC MAP + DPB U,Q + JRST CKML2 + +; REPORT A BLOCK OF LOSING MEMORY + +CKML6: PUSH P,A + MOVEI TT,[ASCIZ/MEM OFF /] + AOSN CKMFLG + PUSHJ P,T00ASZ + ADDI A,1 ;LOWEST LOSER = HIGHEST WINNER + 1 PAGE + PUSHJ P,T00BKO + MOVEI A,"- + PUSHJ P,T00TYO + MOVE A,CKMBLK + PUSHJ P,T00BKO + MOVEI A,40 + PUSHJ P,T00TYO + SETOM CKMBLK + POP P,A + JRST CKML2 + +USEHM: -1 ;-1 => USE MEM IN HIGH MOBY (IF PRESET) + +CKMBLK: -1 ;IF + HIGHEST LOSING BLOCK IN CONTIG RANGE +CKMFLG: -1 ;IF + PRINTED MESSAGE ALREADY +CKMSWC: 0 ;WRITE CMD +CKMSRC: 0 ;READ CMD. +CKMSSC: 0 ;SEEK CMD. +;UP TO 8 RANGES OF ADDRESSES THAT SHOULD NOT BE USED BECAUSE THEY +;DON'T WORK BUT AREN'T NXM. +MEMLZL: BLOCK 8 ;LOWEST LOC +MEMLZH: BLOCK 8 ;HIGHEST LOC+1 +FTUTPG: 0 ;FIRST PAGE USED FOR TUTS + +;INPUT CHAR FROM CONSOLE TTY AND ECHO + +T00TYI: +IFN KA10P,[ + CONSO TTY,40 + JRST .-1 + DATAI TTY,A + ANDI A,177 +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEI A,%DTTYI + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SKIPN A,DTEF11 + JRST T00TYI +] ;KL10P +IFN KS10P,[ + SKIPN A,8CTYIN + JRST .-1 + ANDI A,177 +] ;KS10P + +; TYPE CHAR IN A ON CONSOLE TTY + +T00TYO: +IFN KA10P,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,A +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] ;KL10P +IFN KS10P,[ + PUSH P,A + ANDI A,177 + IORI A,400 + MOVEM A,8CTYOT + CONI A + IORI A,80INT + CONO (A) + SKIPE 8CTYOT + JRST .-1 + POP P,A +] ;KS10P + POPJ P, + +; TYPE BLOCK NO IN A AS HIGH 3 OCTAL DIGITS OF ADDR +; (ALL MEMORIES MULTIPLE OF 4K. MAX MEMORY 2M WORDS.) + +T00BKO: PUSH P,A + PUSH P,B + LSHC A,-8 +REPEAT 3,[ + ADDI A,"0 + PUSHJ P,T00TYO + MOVEI A,0 + LSHC A,3 +] + JRST POPBAJ + +; TYPE ASCIZ IN TT ON T00 + +T00ASZ: PUSH P,A + HRLI TT,440700 +T00AZ1: ILDB A,TT + JUMPE A,POPAJ + PUSHJ P,T00TYO + JRST T00AZ1 + +IFN DPKPP,[ ;MAP SYSTEM SPEED CODES TO DATAPOINT KLUDGE CODES +DPSP: 0_9 ;134 + 1_9 ;600 + 2_9 ;110 + 3_9 ;150 + 4_9 ;300 + 5_9 ;1200 + 5_9 ;1800 * + 6_9 ;2400 + 7_9 ;4800 +REPEAT 20-<.-DPSP>, 7_9 ;FAST * +];DPKPP + +CONSTANTS +VARIABLES + +IEND: +.HKALL==0 + +; Define location known as start of SALV disk salvager. If system overruns +; this address, must either reduce system size or increase the SALV start +; address. If SALV is changed, the SALV program must also be changed to +; start at the right place. There is a limit to how high it can go, +; however. +IFN KL10P, SALV==:105*2000 ; MC-KL is getting huge +.ELSE SALV==:100*2000 +IFG IEND-SALV,.FATAL System overruns SALV start addr! + +IFGE TSYSM-256.,DDT=774000 +.ELSE DDT=TSYSM*2000-4000 +DSKDMP==DDT+3700 + +IFG LBUGTB-LBUGT2,[ +.ERR MAKE THE BUGTAB BIGGER +INFORM LBUGTB-LBUGT2,\LBUGTB-LBUGT2 +.FATAL FATAL ERROR, RUNNING THIS WOULD CAUSE TOTALLY WEIRD BUGS +] + +IF2 EXPUNGE FOO,ZZZQ,FNM,ZCHR,ZZ,ZZZ,BUGB,BUGF,BUGN,BUGNN + +END BEG ;START AT BEG TO SALVAGE AND RUN ITS, START AT GO TO JUST ITS diff --git a/src/system/itsdev.974 b/src/system/itsdev.974 new file mode 100755 index 00000000..caef28fd --- /dev/null +++ b/src/system/itsdev.974 @@ -0,0 +1,5321 @@ +; I T S MISCELLANEOUS DEVICES + +IFN PTRP,[ + +SUBTTL PAPER TAPE PUNCH ROUTINES + +PTPO: JSP Q,STDOPN + 7,,PTPUSR + PTPA,,PTPB + PTPWA,,PTPWB + PTPI,,0 + PTPI,,0 + +BPIPUN: JSP E,NBTOCH + CAIN A,EOFCH + POPJ P, + JRST APIPU2 + +APIPUN: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +APIPU2: CAIN A,14 + JRST PUNFF + TRO A,200 + JRST PIPUN3 + +PIPUN: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +PIPUN3: SKIPG PUNCC + JRST PUNW1 +PIPUN2: IDPB A,PUNIP + HRRZ A,PUNIP + CAIN A,PUNBE-1 + MOVEI A,PUNBO + HRRM A,PUNIP + SOS PUNCC +PUNST: SKIPGE PUNNT + POPJ P, ;PUNCH OUT OF TAPE + CONSO PTP,7 + CONO PTP,10+PCHCHN + POPJ P, + + PUSHJ P,PUNW2 +PUNW1: PUSHJ P,UFLS + JRST PIPUN2 + +PUNW2: SKIPG T,PUNCC + POPJ P, + CAIL T,PUNSIZ*2 + JRST POPJ1 + JRST POPJ3 + +PUNFF: MOVEI T,55 + CAMLE T,PUNCC + PUSHJ P,UFLS + MOVSI B,-4 + PUSHJ P,PUNFF2 + MOVEI A,214 + PUSHJ P,PIPUN2 + MOVSI B,-50 +PUNFF2: MOVEI A,0 + PUSHJ P,PIPUN2 + AOBJN B,PUNFF2 + POPJ P, + +WBPIPN: JSP Q,WRDBT +WAPIPN: MOVEI T,6 + CAMLE T,PUNCC + PUSHJ P,UFLS + SKIPGE C + SKIPA B,(C) + UMOVE B,(C) + MOVSI E,-6 +WPIPN2: MOVEI A,2 + LSHC A,6 + PUSHJ P,PIPUN2 + AOBJN E,WPIPN2 + POPJ P, + +PBRK1: MOVEI A,PUNSIZ*4-4 + CAMG A,PUNCC + JRST PUNSTP + CONSZ PTP,100 ;CHECK NO TAPE FLAG + JRST PBRK2 ;PUNCH OUT OF TAPE + ILDB A,PUNOP + DATAO PTP,A + HRRZ A,PUNOP + CAIN A,PUNBE-1 + MOVEI A,PUNBO + HRRM A,PUNOP + AOSA PUNCC +PUNSTP: CONO PTP,0 + JRST LPBKRT + +PBRK2: SETOM PUNNT ;PTP OUT OF TAPE + JRST PUNSTP + +;PTP SLOW CLOCK ROUTINE +PTPCHK: SKIPGE PUNNT + CONSZ PTP,100 + POPJ P, + HRRZM P,PUNNT + JRST PUNST ;PTP HAS TAPE NOW + +EBLK + +PUNNT: 105 ;-1 => PTP OUT OF TAPE +PUNCC: PUNSIZ*4-4 +PUNIP: (1000)PUNBO-1 +PUNOP: (1000)PUNBO-1 +PUNBO: BLOCK PUNSIZ +PUNBE: + +BBLK + +PUNCLR: MOVEI A,PUNSIZ*4-4 + MOVE B,PUNIP + MOVEM A,PUNCC + MOVEM B,PUNOP + POPJ P, + +PUNFIN: MOVE T,PUNSIZ*4-4 ;.CALL FINISH + CAMLE T,PUNCC + PUSHJ P,UFLS + POPJ P, + +AFEED: HRRZ A,(R) + CAIL A,PTPI ;LOWEST PTP DEV # + CAILE A,PTPWB ;HIGHEST PTP DEV # + POPJ P, ;PTP NOT OPEN ON CHNL + MOVEI A,0 + PUSHJ P,PIPUN3 + JRST POPJ1 + +SUBTTL PAPER TAPE READER ROUTINES + + PTRCHX==10 ;NUMBER OF CHARACTERS IGNORED AT END OF TAPE + +PTRO: PUSH P,[PTRO1] ;SO STDOPN WILL RETURN + JSP Q,STDOPN + 7,,PTRUSR + REDUAI,,REDBAI ;ASCII MODE + REDUII,,REDBII ;IMAGE MODE + REDUTI,,0 ;ALL 8 HOLES MODE + REDUTI,,0 ;" " " " + + ;RETURN FROM STDOPN +PTRO1: POPJ P, ;OPEN LOST + AOS (P) ;OPEN WON, MAKE RETURN SKIP + SKIPE PTRUSE + POPJ P, ;READER ALREADY OPEN, DON'T RESET + ;READER NOT ALREADY OPEN, SO + ;RESET PTR POINTERS AND START UP READER + CONO PI,PTROFF ;INHIBIT INTERRUPTS + MOVEI T,20 ;BUSY FLAG + PUSHJ P,PTRST ;START UP READER IF NOT ALREADY RUNNING + ;RESET PTR BUFFER POINTERS +PTRZAP: MOVE A,[041000,,PTRBUF-1] ;BUFFER BYTE POINTER + MOVEM A,PTRIP ;BUFFER INPUT (INTERRUPT) POINTER + MOVEM A,PTROP ;BUFFER OUTPUT (IOT) POINTER + MOVEI A,PTRCHX ;REINITIALIZE CHARACTER COUNT + MOVNM A,PTRCC ;" " " + CONO PI,PTRON ;RE-ENABLE INTERRUPTS + JRST PTRSIW ;RESET STATUS OF IMAGE WORD AND RETURN + + ;CLOSE CHANNEL ON WHICH PTR OPEN + +PTRCLS: CONO PI,PTROFF ;INHIBIT INTERRUPTS + SOSL PTRUSE ;DECREMENT USE COUNTER + JRST PTRONJ ;PTR OPENED ON MORE CHANNELS + SETOM PTRUSR ;NO MORE OPENS ON READER, INDICATE NO USER + SETOM PTRDIE ;EVENTUALLY TURN OFF READER + JRST PTRZAP ;RESET BUFFER STATUS + +PTRRS: CONO PI,PTROFF ;PTR .RESET ROUTINE + JRST PTRZAP + + ;BLOCK ASCII INPUT + +PTRBAI: JSP E,INBTCH ;DO IT A CHARACTER AT A TIME + + ;GET AN ASCII CHARACTER IN W + +PTRUAI: +PTRCHA: PUSHJ P,PTRCH ;GET CHARACTER - SKIPS IF EOF. + TRZA W,200 ;CLEAR 200 BIT + JRST POPJ1 + JUMPE W,PTRCHA ;IF RESULT ZERO THEN DON'T CALL IT ASCII + CAIN W,177 ;IF RUBOUT, + JRST PTRCHA ;THEN IGNORE IT + POPJ P, ;ASCII, USE IT + +PTRBII: JSP W,WRDBTI ;BLOCK IMAGE INPUT. + + ;UNIT IMAGE INPUT + ;END-OF-FILE GIVES SIXBIT /######/ + +PTRUII: PUSHJ P,PTRCH ;GET CHARACTER + TRNE W,200 + CAIA ;CALL IT BINARY IF 200 SET, OR IF EOF. + JRST PTRUII + IDPB W,PTRIBP + JUMPL W,PTRUI2 ;IF REACHED EOF, SKIP 1 OR 2. + SOSLE PTRICC ;IF WORD NOT FULL, + JRST PTRUII ;THEN GO BACK FOR MORE + JRST PTRUI1 ;ELSE RETURN THE WORD. + +PTRUI2: SOSG B,PTRICC + JRST PTRUI3 + CAIE B,5 + JRST PTRUII + JRST PTRUI4 + +PTRUI3: AOS (P) ;IF WE REACHED EOF, SKIP TWICE. +PTRUI4: AOS (P) ;REACHED EOF BEFORE WORD; SKIP ONCE. +PTRUI1: MOVE W,PTRIW ;WORD FULL, +PTRSIW: MOVEI B,6 ;NOW REINITIALIZE POINTERS TO WORD + MOVEM B,PTRICC ;CHARACTER COUNT OF WORD + MOVE B,[440600,,PTRIW] ;POINTER TO WORD + MOVEM B,PTRIBP + POPJ P, + + ;GET A CHARACTER IN W OR SKIP RETURNING -1,,EOFCH IF NONE AVAILABLE + +PTRUTI: ;UNIT MODE ALL-HOLES INPUT. +PTRCH: MOVEI T,20 ;BUSY FLAG + PUSHJ P,PTRCHW ;WAIT FOR A CHARACTER + PUSHJ P,UFLS + SOSGE I,PTRCC ;DECREMENT CHARACTER COUNT + JRST PTRCH1 ;BUFFER EMPTY + MOVEI T,10 ;DONE FLAG + CAIGE I,REDSIZ-PTRCHX ;IF BUFFER LESS THAN 1/4-FULL, + PUSHJ P,PTRST ;THEN MAKE SURE READER RUNNING + ILDB W,PTROP ;GET CHARACTER + HRRZ B,PTROP ;RING THE BUFFER + CAIL B,PTRBUF+REDSIZ-1 + MOVEI B,PTRBUF + HRRM B,PTROP + POPJ P, + + ;END-OF-FILE ENCOUNTERED DURING PTRCH + +PTRCH1: AOS PTRCC ;RESTORE CHARACTER COUNT TO ITS ORIGINAL STATE + JRST UNIEOF + + ;SKIP IF CHARACTER IN BUFFER OR END-OF-TAPE + +PTRCHW: SKIPG PTRCC ;IF CHARACTER IN BUFFER, + CONSO PTR,400 ;OR POWER IS OFF, + JRST POPJ1 ;THEN EXIT SKIPPING + ;OTHERWISE, + ;MAKE SURE READER RUNNING + +PTRST: CONSZ PTR,7 + CONSO PTR,30 ;IF RUNNING, + JRST .+2 + POPJ P, ;THEN THAT'S ALL + CONO PTR,PTRCHN(T) ;NOT RUNNING, RESTART WITH SELECTED FLAG + SETOM PTRDIE ;LET SLOW CLOCK FIGURE OUT IF THERE'S TAPE + POPJ P, + + ;PTR INTERRUPT ROUTINE + +PTRBRK: AOSN PTRSTP ;IF READER SHOULD BE STOPPED THIS BREAK, + JRST PTRFUL ;THEN STOP IT (BUFFER FULL) + DATAI PTR,A ;GET CHARACTER + SETOM PTRDIE ;TELL SLOW CLOCK THAT BREAK HAS HAPPENED + IDPB A,PTRIP ;PUT IN BUFFER + HRRZ A,PTRIP ;RING THE BUFFER + CAIN A,PTRBUF+REDSIZ-1 + MOVEI A,PTRBUF + HRRM A,PTRIP + AOS A,PTRCC ;TOTAL CHARACTER COUNT-PTRCHX + CAIGE A,REDSIZ*4-10-PTRCHX + JRST LPBKRT + SETOM PTRSTP ;STOP READER AT NEXT BREAK + JRST LPBKRT + +PTRFUL: CONO PTR,PTRCHN ;BUFFER FULL, STOP READER + MOVEI A,1 ;TELL SLOW CLOCK... + MOVEM A,PTRDIE ;NOT TO TURN IT OFF + JRST LPBKRT + + ;SLOW CLOCK ROUTINE + ;CHECKS READER EVERY HALF-SECOND + +PTRCHK: AOS A,PTRDIE + CAIN A,1 ;IF UNINTENTIONALLY STOPPED FOR OVER HALF-SECOND + CONO PTR,400 ;THEN TURN THE READER OFF + POPJ P, + +EBLK + ;PTR VARIABLES + +PTRDIE: -264 ;END-OF-TAPE DETECTION +PTRSTP: 0 ;-1 => STOP READER AT NEXT BREAK (SET DURING BREAK WHEN BUFFER FULL) +PTRIP: 041000,,PTRBUF-1 ;BUFFER INPUT (INTERRUPT) POINTER +PTROP: 041000,,PTRBUF-1 ;BUFFER OUTPUT (IOT) POINTER +PTRBUF: BLOCK REDSIZ ;READER BUFFER +PTRCC: -PTRCHX ;NUMBER OF CHARACTERS IN BUFFER -PTRCHX + +PTRIW: 0 ;CURRENT WORD FOR IMAGE MODE +PTRIBP: 440600,,PTRIW ;POINTER TO CURRENT WORD +PTRICC: 0 ;CHARACTER COUNT TO CURRENT IMAGE MODE WORD + +BBLK + +] ;END OF IFN PTRP + +SUBTTL LINE PRINTER ROUTINES + +IFN NLPTP,[ +NLPTO: MOVE A,UTMPTR(U) + SKIPGE NLUSR + SKIPL TTYTYP-USRRCE(A) + JRST TPLO + SETOM NLFREE + MOVEI T,LPTBSZ + CAME T,NLPTBR ;WAIT TILL LPT BUFFER IS EMPTY. + PUSHJ P,UFLS + CONSZ NLPT,207 ;AND LPT ISN'T STILL PRINTING LAST WD + PUSHJ P,UFLS + PUSH P,[NLPTO1] + JSP Q,STDOPN + 1,,NLUSR + NLPTDN,,NLPTBN + +NLPTO1: POPJ P, ;LPT NOT AVAIL & NOT ASSIGNED. + ;LPT ASSIGNED, INIT IT. + CONO NLPT,1000 ;PUT LPT INTERFACE IN IMAGE MODE, + DATAO NLPT,[23*2] ;TURN ON THE LPT'S MOTOR. + MOVEI I,1000 + CONSZ NLPT,200 ;WAIT TILL IT IS ON. + SOJG I,.-1 + AOS (P) +NLPTO3: HRROI I,NLPTCF + HRROI C,I + PUSHJ P,BNLPTO ;CAN'T PCLSR SINCE BUFFER IS EMPTY. + HRRZ I,NLPTBP + HRLI I,010700 + MOVEM I,NLPTIP + POPJ P, + +NLPTCF: 15_29.+14_22.+177_15.+177_8+177_1 +] + +IFN GLPTP,[ ;GOULD ELECTROSTATIC PRINTER ROUTINES + +IFE DL10P,.ERR GOULD PRINTER WITHOUT A PDP11 TO RUN IT? + +;OPEN ROUTINE + +GLPTO: SKIPE GLPTER + JRST OPNL7 ;DEV NOT READY IF 11 UNHAPPY + MOVEI Q,[1,,LPTUSR + GLPTDN,,GLPTBN] + PUSHJ P,STDOPN + POPJ P, + SETZM GLPGRF + TLNE C,10 ;BIT 3.4 => GRAPHICS MODE. + SETOM GLPGRF + JRST POPJ1 + + + + + + +;IOT ROUTINES + + SKIPA T,[SIOKT] ;SIOT HANDLER = UNIT HANDLER MINUS ONE +GLPTDO: MOVEI T,CHRKTO + MOVE E,[440700,,5] + JRST GLPTOO + +GLPTBO: MOVEI T,BLKT + MOVE E,[444400,,1] +GLPTOO: JSP B,(T) + SETZ GLPMPP + GLPMPC + GLPBGB + GLPBWW + JRST 4,. + SKIPE GLPTBC + +;CLOSE ROUTINE + +GLPCLS: SKIPE GLPMPP ;IF THERE'S AN UN-SENT BUFFER, + PUSHJ P,GLPBWW ;BARK AT THE PDP11 + SKIPE GLPTBC ;WAIT FOR ALL BUFFERED STUFF TO BE SENT + PUSHJ P,UFLS + PUSHJ P,GLPBG0 ;AVOID IOCERR AT NEXT OPEN + IRPS CH,,12 14 177 105 + MOVE C,[SETZ I] ;AT CLOSE SEND FF, EOF + MOVEI I,CH ;THIS CAN'T PCLSR ONCE IT GETS A NEW BUFFER. + PUSHJ P,GLPTDO + TERMIN + SETZM GLPGRF + PUSHJ P,GLPBWW ;WRITE LAST BUFFER + SETOM LPTUSR + SETOM LPTUSE + POPJ P, + +;BUFFER GET ROUTINE + +GLPBGB: SKIPE GLPTER + JRST IOCER1 ;DEV NOT READY IF 11 UNHAPPY ABOU IT. + SKIPE GLPTBC + POPJ P, ;BUFFER BUSY +GLPBG0: MOVEI TT,GLPTBF + MOVEI J,GLPBSZ + JRST SIOBGX + +;BUFFER DISCARD ROUTINE + +GLPBWW: MOVE D,[450000,,GLPTBF-1] ;DL10 BYTE POINTER (7-BIT BYTES) + SKIPE J,GLPGRF + HRLI D,340000 ;GRAPHICS MODE => 8-BIT BYTES + MOVEM D,GLPTBP + SKIPN D,GLPMPP ;COMPUTE # CHARS IN BUFFER + POPJ P, + JUMPL D,[SOJA D,GLPBW1] + MOVEI TT,15 ;INDEPENDENT OF E, BLOCK VS UNIT, ETC. + TLNE D,760000 + JRST [ IDPB TT,D ? JRST .-1 ] +GLPBW1: MOVEI D,-GLPTBF+1(D) + IMUL D,[4 ? 5]+1(J) ;GRAPHICS => 4, ELSE 5. + MOVEM D,GLPTBC ;START THE PDP11 + SETZM GLPMPP ;FLAG THAT BUFFER IS NOT ACTIVE AT M.P. LEVEL + SETZM GLPMPC + POPJ P, + +;NOTE: TPL CODE HAS DELIBERATELY BEEN OMITTED. +;THE DL10 LIMITS THE BUFFER SIZE TO 256 WORDS. WITH THIS SMALL +;A BUFFER THE SYSTEM JOB CAN'T DRIVE THE PRINTER AT FULL SPEED +;BECAUSE IT CAN ONLY IOT ONCE A SECOND OR SO. +;ANYWAY, THE NECESSARY TPL CODE IS HAIRY. +] ;END IFN GLPTP + +IFN OLPTP,[ + +LPTLPP==60. + +LPTO: CAMN U,OLUSR + JRST LPTO2 ;ALREADY HAS IT + MOVE A,UTMPTR(U) ;GET POINTER TO USER RESOURCE + ;(TTY DEPENDANT) + SKIPL TTYTYP-USRRCE(A) + JRST TPLO +LPTO2: PUSH P,[LPTO1] + JSP Q,STDOPN + 1,,OLUSR + LPTDN,,LPTBN + +LPTO1: POPJ P, ;OPEN LOST + SKIPE OLUSE ;OPEN WON + JRST POPJ1 ;NOT FIRST OPEN BY THIS USER + AOS (P) +LPTRS2: MOVEI A,15 ;ENTRY FROM LPTRS, DUMP OUT CRUD ON THIS LINE THEN FORM FEED + PUSHJ P,PILPT + MOVEI A,14 + JRST PILPT + +BLPTO: MOVEI E,PILPT + JRST NBTOCH + +PILPT1: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +PILPT: CAIN A,177 + POPJ P, ;IGNORE RUBOUTS + MOVEI T,130. ;LPTCC COMPARED WITH 132. BY SYSTEM JOB BEFORE TRY OF .OPEN + CAMLE T,LPTCC + JRST LPTW1 ;WAIT +LPTIM: CAIGE A,40 + JRST LPTRC + CAIL A,140 + SUBI A,40 +LPTIM2: AOSN LPTBSF + PUSHJ P,LPC ;PRINT PREV STUFF AND SPACE OVER + AOS T,LINEPOS +BADCOL: CAIN T,-1 ;PATCH NUM OF BAD COL IN HERE WHEN NECESSARY + JRST LPTBC1 + CAILE T,120. + JRST PILPT2 +LPC1: SUBI A,40 + IDPB A,LPTIP + HRRZ A,LPTIP + CAIN A,LPTBE-1 + MOVEI A,LPTBO + HRRM A,LPTIP + SOS LPTCC + CONSO OLPT,7 + CONO OLPT,LPTCHN + POPJ P, + +LPTBC1: PUSH P,A + MOVEI A,40 + PUSHJ P,LPC1 + POP P,A + JRST LPC1 + +LPTRC: CAIN A,10 + JRST LPTBS ;BACK SPACE + CAIN A,11 + JRST LPTTAB + CAIN A,12 + JRST LPTLF + CAIN A,14 + JRST LPTFF + CAIN A,EOFCH + JRST LPTEOF + SETOM PCL + CAIE A,15 + JRST LPTRCH +LPT.CR: SETZM LINEPOS + SETZM LPTBSF + JRST LPC1 + + PUSHJ P,LPTW2 +LPTW1: PUSHJ P,UFLS + JRST LPTIM + +LPTW2: CAMLE T,LPTCC + POPJ P, + MOVE T,LPTCC + CAIL T,*2 + JRST POPJ1 + JRST POPJ3 + +LPTBS: SKIPG LINEPOS + POPJ P, ;AT BEG OF LINE, IGNORE + SOS LINEPOS + SETOM LPTBSF + POPJ P, + +LPTRCH: CAIN A,33 + JRST LPTALT + MOVE B,A + MOVEI A,"^ + PUSHJ P,LPTIM2 + MOVEI A,100(B) + JRST LPTIM2 + +LPTALT: MOVEI A,"$ + JRST LPTIM2 + +PILPT2: SOS LINEPOS + POPJ P, + +LPTEOF: SKIPE OLUSR + POPJ P, + SUB P,[1,,1] ;SYSTEM JOB HACKING SO CLOBBER TO EOF + XCTR XRW,[CLEARM (C)] + POPJ P, + +LPTCLS: SKIPLE OLUSE ;LPT CLOSE, IS THIS THE ONLY CHANNEL LPT OPEN ON + JRST LPTCL3 + SKIPN LINEPOS ;THIS IS LAST CLOSE, CHECK TO SEE IF LOSER LEFT POSITION SCREWED + SKIPE LPTPPS + PUSHJ P,LPTCL2 ;INCREMENT TO NEXT PAGE + MOVEI T,SCRTPC + IORM T,SUPCOR ;LOOK FOR TPL FILES TO PRINT + SETOM OLUSR ;DO THIS FIRST SO DONT NEED CLOCK OFF LPT HACKED BY ONE JOB AT A TIME +LPTCL3: SOS OLUSE ;DECREMENT USE COUNT + POPJ P, + +LPTCL2: MOVEI A,100. + CAMLE A,LPTCC + POPJ P, ;NO ROOM FORGET IT + MOVEI A,15 + PUSHJ P,LPTIM + MOVEI A,14 + JRST LPTIM + LPTTAB: PUSHJ P,LPTS + LDB J,[300,,LINEPOS] + JUMPE J,CPOPJ + JRST .-3 + +LPTS: MOVEI A,40 + JRST LPTIM2 + +LPTLF: AOS J,LPTPPS ;LINE FEED, INCREMENT LINE # + CAIL J,LPTLPP ;END OF PAGE? +LPTFF: SETZM LPTPPS ;END OF PAGE CLEAR OUT PAGE POS (ENTRY FOR FF) + PUSHJ P,LPC + JRST LPC1 + +LPC: MOVE J,LINEPOS ;CR AND SPACE BACK OVER TO LINPOS + MOVE B,A + MOVEI A,15 + AOSN PCL + SKIPE LINEPOS + PUSHJ P,LPT.CR + CLEARM LPTBSF ;IN CASE WAS ALREADY AT BEG OF LINE + SOJL J,LPC2 + PUSHJ P,LPTS + JRST .-2 + +LPC2: MOVE A,B + POPJ P, + +EBLK + +LPTCC: *5-5 +LINEPOS: 0 ;LINE POSITION # CHARS PRINTED THIS LINE BEFORE CURRENT +LPTPPS: 0 ;PAGE POSITION (# LINES PRINTED BEFORE CURRENT) + +PCL: 0 ;INCREMENTED BY LF OR FF, SETOMED BY OHTER CONTROL CHARS + ;PROBABLY UNNECESSARY BUT NOT WORTH FLUSHING +LPTBSF: 0 ;-1 => BACKSPACES HAVE BEEN TYPED, CR AND SPACE OVER BEFORE MAKING INK + +LPTIP: 700,,LPTBO-1 +LPTOP: 700,,LPTBO-1 + +BBLK + +LPTCN: CAIN A,<15-40>&177 + JRST LPTCR ;CRR + CAIN A,<12-40>&177 + MOVEI A,400 ;LINE FEED + CAIN A,<14-40>&177 + MOVEI A,401 ;FORM FEED + CAIE A,177 ;SKIP IF LOOKS LIKE A LEFT ARROW + JRST LPTCN1 ;GO TO PRINT + HRRZ A,LPTOP ;LOAD OUPUT POINTER + CAIE A,LPTBE-1 ;SKIP IF CURRENT PNTR = END OF BUFFER + JRST LPENT3 ;REAL LEFT ARR + MOVE A,[350700,,LPTBO] + MOVEM A,LPTOP + JRST LPENT2 +] + +IFN NLPTP,[ +NLPT1: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + MOVE B,NLPTIP + TLNN B,760000 + JRST NLPTW ;MAY NOT BE ROOM +NLPTW1: IDPB A,NLPTIP + MOVE T,NLPTIP + CAMN T,NLPTEP + SUBI T,LPTBSZ + HRRM T,NLPTIP + TLNE T,760000 + POPJ P, + SOSGE NLPTBR + JRST 4,. +NLPTGO: CONO PI,LPTOFF + CONSO NLPT,7 + CONO NLPT,100+LPTCHN ;SET OUTPUT DONE + JRST LPTONJ + +NLPTW: SKIPG NLPTBR + PUSHJ P,UFLS + JRST NLPTW1 + +EBLK + +NLPTIP: 010700,,NLPTBO-1 +NLPTBO: BLOCK LPTBSZ +NLPTEP: 010700,,NLPTBO+LPTBSZ-1 +NLPTPP: NLPTBO ;OUTPUT PNTR (PI) +NLPTBR: LPTBSZ +NLPTBP: 004400,,NLPTBO-1 ;BLKT POINTER +NLPTBC: LPTBSZ ;BLKT CNT = MIN(# WDS TILL END OF BUF,NLPTBR) +NLPTOP: NLPTBO ;VALUE OF NLPTBP BEFORE BLKT CALL +NLFREE: -1 ;-1 => LPT IN USE RECENTLY. + ;0 => NOT IN USE SINCE LAST VSCLK. + ;1 => NOT SINCE NEXT-TO-LAST VSCLK. + ;=>2 => LPT MOTOR NOW OFF. + +BBLK + +BNLPTO: MOVE B,NLPTBP + MOVEM B,NLPTOP + PUSH P,[BNLPT1] + MOVE E,[444400,,1] + JSP B,BLKT + SETZ NLPTBP + NLPTBC + BNLPTG + BNLPT1 + @J + SKIPG NLPTBR + +BNLPT1: MOVE T,NLPTBP + MOVE W,T + CAMN T,[004400,,NLPTBO+LPTBSZ-1] + MOVE T,[004400,,NLPTBO-1] + MOVEM T,NLPTBP + EXCH T,NLPTOP + SUB T,W ;- # WORDS WRITTEN + ADDB T,NLPTBR ;DECREASE ROOM + JUMPL T,[JRST 4,.] + JRST NLPTGO + +BNLPTG: MOVE TT,NLPTBP + MOVE J,NLPTBR + MOVEI T,NLPTBO+LPTBSZ-1 + SUBI T,(TT) ;# WORDS UNTIL END OF BUFFER + CAMLE J,T + MOVE J,T + MOVEM J,NLPTBC + JRST POPJ1 + +NLPTCL: SKIPLE NLPTBR ;ENOUGH ROOM? + PUSHJ P,NLPTO3 + SETOM NLFREE + SETOM NLUSR + SETOM NLUSE + POPJ P, + +NLPDCL: MOVSI H,760000 + SKIPA A,[177] +NLPDC1: PUSHJ P,NLPTW1 + TDNE H,NLPTIP + JRST NLPDC1 + HRRZ A,NLPTIP + CAIN A,NLPTBO+LPTBSZ-1 + MOVEI A,NLPTBO-1 + HRLI A,004400 + MOVEM A,NLPTBP + MOVNI A,(A) + ADDI A,NLPTBO+LPTBSZ-1 + MOVE B,NLPTBR + CAMLE A,B + MOVE A,B + MOVEM A,NLPTBC + JRST NLPTCL +] + +IFN NTYP\OLPTP\NLPTP\PLTP\340P\PDP6P\STKP\PTRP,[ + +EBLK +LPTA: 0 +LPTB: 0 +LPTACS: BLOCK 15 + +LPTBRK: 0 +BBLK + MOVEM A,LPTA +IFN NTYP,[ ;A KLUDGE FOR THE PDP 11 ON DM + CONI NTY,A + TRNE A,7 ;NO PIA + TRNN A,200000 ;NO FLAG + CAIA + JRST NTYBRK ;AHH, FLAG AND PIA +] + +IFN OLPTP,[ + CONSZ OLPT,7 + CONSZ OLPT,10 + JRST .+2 + JRST LPENT1 ;LINE PRINTER +] +IFN NLPTP,[ + CONSZ NLPT,7 + CONSO NLPT,100 ;DONE + JRST .+2 + JRST NLPENT ;NEW LINE PRINTER +] +IFN 340P,[ + CONI DIS,A + TRNN A,77 + JRST LPTBR2 + CONSZ DIS,7400 + JUMPL A,SRECYC ;SPECIAL DISPLAY CHNL +] +LPTBR2: MOVEM B,LPTB +IFN PLTP,[ + CONSZ PLT,SDS+PDS + JRST PLTBRK ;PLOTTER +] +IFN PTRP,[ + CONSZ PTR,7 + CONSO PTR,10 + JRST .+2 + JRST PTRBRK + CONSZ PTP,10 + JRST PBRK1 ;PAPER TAPE PUNCH +] +IFN PDP6P,[ + CONSO DSDEV,7 + JRST .+3 + CONSZ DSDEV,10 + JRST DSDBRK ;INTERRUPT FROM OTHER PROCESSOR +] +IFN STKP,[ + CONSZ STK,7 + CONSO STK,10 + JRST .+2 + JRST STKINT ;STANFORD KEYBOARD +] +LPBKRT: MOVE A,LPTA + JRST 12,@LPTBRK + +LPTRT1: MOVS A,[C,,LPTACS] + BLT A,17 +LPTRT3: MOVE B,LPTB + MOVE A,LPTA + JRST 12,@LPTBRK +] ;END IFN OLPTP\ ETC. +.ELSE [ +EBLK +LPTBRK: 0 +BBLK + JRST 4,. +] + +IFN OLPTP,[ +LPENT3: MOVEI A,177 + JRST LPTCN1 + +LPTCR: CONO OLPT,10+LPTCHN ;PRINT LINE + AOS LPTCC + JRST LPBKRT + +LPENT1: MOVEI A,*5-5 + CAMG A,LPTCC + JRST LPTSTP +LPENT2: ILDB A,LPTOP + TRNE A,100 + JRST LPTCN +LPTCN1: DATAO OLPT,A ;OUTPUT CHARACTER + AOS A,LPTCC + CONSZ OLPT,10 + JRST LPBKRT + CAIGE A,*5-5 + JRST LPENT2 +LPTSTP: CONO OLPT,0 ;CLEAR PIA + MOVEI A,SCRTPC + SKIPGE LPTUSR + IORM A,SUPCOR ;LPT NOW IDLE + JRST LPBKRT + +EBLK + +LPTBO: BLOCK LPTBSZ-1 + -1 +LPTBE: + +BBLK + +STALPT: MOVE E,LINEPOS + DPB E,[130700,,D] + DPB A,[60300,,D] ;MODE + MOVE E,LPTCC + CAIG E,150. + TRO D,1_9. + CAIL E,30000 + TRO D,1_<9.+1> + POPJ P, + +LPTRS: CONO PI,LPTOFF + MOVEI A,5*-5 + MOVEM A,LPTCC + MOVE A,[700,,LPTBO-1] + MOVEM A,LPTIP + MOVEM A,LPTOP + SETZM LINEPOS + CONO PI,LPTON + JRST LPTRS2 + +] + +IFN NLPTP,[ +NLPENT: MOVE A,NLPTBR + CAIN A,LPTBSZ + JRST NLPTST + CAIL A,LPTBSZ + JRST 4,. + DATAO NLPT,@NLPTPP + AOS A,NLPTPP + CAIN A,NLPTBO+LPTBSZ + MOVEI A,NLPTBO + MOVEM A,NLPTPP + AOS NLPTBR + JRST LPBKRT + +NLPTST: CONO NLPT,200 ;CLEAR DONE AND PIA + MOVEI A,SCRTPC + SKIPGE NLUSR + IORM A,SUPCOR ;LPT NOW IDLE + JRST LPBKRT + +NLPTRS: CONO PI,LPTOFF + MOVE A,[010700,,NLPTBO-1] + MOVEM A,NLPTIP + MOVEI A,NLPTBO + MOVEM A,NLPTPP + MOVE A,[004400,,NLPTBO-1] + MOVEM A,NLPTBP + MOVEM A,NLPTOP + MOVEI A,LPTBSZ + MOVEM A,NLPTBR + MOVEM A,NLPTBC + CONO PI,LPTON + JRST NLPTO3 +] + +SUBTTL STANFORD KEYBOARD + +IFN STKP,{ +;3.4 => DON'T HANG ON IOT IF NO CHAR (RETURN -1 INSTEAD) +;3.5 = 1 => DON'T DO CHAR CONVERSION +; = 0 => CONVERT ACCORDING TO OTHER BITS +;3.6 = 1 => ITS MODE (CTRL DOES CTRL AND META IS 8TH BIT) +; = 0 => STANFORD MODE (400 = META, 200 = CTRL, AND ALL THE +; CHARS FROM 1-177 CAN BE GENERATED WITH TOP AND SHIFT.) +;3.7 = 1 => IF 3.5 = 0, 3.6 = 1, THEN DON'T INPUT META BIT + +STKO: TLNE C,3 ;BLOCK OR OUTPUT + JRST OPNL12 ;MODE NOT AVAILABLE + CONO PI,CLKOFF + SKIPL STKUSR + JRST OPNL10 ;DEVICE NOT AVAILABLE + MOVEM U,STKUSR + AOSE STKUSE + JRST 4,. ;CAN ONLY BE OPEN ONCE + CONO PI,CLKON + HRRZ A,UUAC(U) + MOVE A,CHNBIT(A) + ROT D,-2 + DPB D,[220400,,A] + MOVEM A,STKMSK + MOVE A,STKBP + MOVEM A,STKIP + MOVEM A,STKOP + SETZM STKBC + DATAI STK,A ;CLEAR DONE + CONO STK,LPTCHN + MOVEI A,STKDP + MOVEM A,(R) + JRST POPJ1 + +STKCLS: CONO STK,0 ;CLEAR PIA + SOSL STKUSE + JRST 4,. ;CAN ONLY BE OPEN ONCE + SETOM STKUSR + POPJ P, + +STKRS: CONO PI,LPTOFF + MOVE A,STKBP + MOVEM A,STKIP + MOVEM A,STKOP + SETZM STKBC + JRST LPTONJ + +STKI: MOVE TT,STKMSK + TLNE TT,1 + JRST STKI1 + PCLT + SKIPG STKBC + PUSHJ P,UFLS +STKI2: ILDB A,STKOP + SOS STKBC + TLNN TT,2 + JRST STKCV ;DO CONVERSION +STKI3: MOVE W,A + MOVE A,STKOP + CAMN A,STKEP + SUBI A,STKBL + HRRM A,STKOP + POPJ P, + +STKI1: SKIPLE STKBC + JRST STKI2 + JRST STTYI3 + +STKINT: MOVEM B,LPTB + DATAI STK,B + ANDI B,1777 ;CURRENTLY 10 BITS + MOVE A,STKBC + CAIL A,STKBS + JRST LPTRT3 ;NO ROOM. JUST IGNORE CHAR + IDPB B,STKIP + AOS STKBC + MOVE A,STKIP + CAMN A,STKEP + SUBI A,STKBL + HRRM A,STKIP + MOVE A,STKUSR + HRRZ B,STKMSK + AND B,MSKST2(A) + IORM B,IFPIR(A) + JRST LPTRT3 + +EBLK +STKBL==40 +STKBS==STKBL*3 +STKIP: 001400,,STKIB-1 +STKIB: BLOCK STKBL +STKEP: 001400,,STKIB+STKBL-1 +STKBP: 001400,,STKIB-1 +STKOP: 001400,,STKIB-1 +STKBC: 0 +STKMSK: 0 ;BIT FOR CHANNEL STK OPEN ON + ;3.1 => DON'T HANG ON IOTS MODE + ;3.2 => DON'T CONVERT CHARS + ;3.3 => ITS MODE + ;3.4 => DON'T INPUT META IN ITS MODE +BBLK + +STKCV: LDB B,[000600,,A] ;LOW 6 BITS + CAIN B,33 + JRST STKCV1 ;33 + CAIL B,35 + CAILE B,47 + JRST .+2 + JRST STKCV2 ;35-47 + CAIL B,74 + CAILE B,77 + JRST .+2 + JRST STKCV3 ;74-77 + TRNE A,400 + JRST STKCVT ;TOP IS ON + CAIG B,32 + JRST STKCV4 ;0-32 + CAIN B,34 ;SKIP IF 50-73 + JRST STKCVB ;34 +STKCVX: TLNN TT,4 ;SKIP ON ITS MODE + JRST STKCVY ;STANFORD MODE + ANDI A,1000 ;META BIT + LSH A,-2 + TLNN TT,10 ;SKIP ON DON'T INPUT META BIT + IORI B,(A) + MOVE A,B + JRST STKI3 + +STKCVY: LDB D,[110100,,A] ;META BIT + LSH D,8 ;IN 400 POSITION + ANDI A,200 ;CTRL BIT + IORI A,(D) + IORI A,(B) + JRST STKI3 + +STKCV1: MOVEI B,15 + JRST STKCVX + +STKCV2: MOVEI Q,-35(B) ;35-47 (-35) + IDIVI Q,5 + LDB B,STKBPT(J) + JRST STKCVX + +STKCV3: CAIE B,74 + JRST STKCV5 ;75-77 + MOVEI B,177 + JRST STKCVX + +STKCV5: MOVEI B,33 + JRST STKCVX + +STKCVT: CAIG B,32 ;TOP IS ON + JRST STKCT1 ;0-32 + CAIN B,34 + JRST STKCT2 ;34 + MOVEI Q,-50(B) ;50-73 (-50) + MOVE D,B + IDIVI Q,5 + LDB B,STKBP1(J) + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + CAIL D,52 + CAILE D,72 + TRZ B,100 ;50,51,73 + JRST STKCVX + +STKCT1: MOVE Q,B ;0-32 TOP ON + MOVE D,B + IDIVI Q,5 + LDB B,STKBP2(J) + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + CAIN D,12 + TRZ B,100 + JRST STKCVX + +STKCT2: MOVEI B,16 + JRST STKCVX + +STKCV4: TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCV6 + TRNE A,200 + JRST STKCVX ;ITS, CTRL +STKCV6: TRO B,100 + TRNN A,100 + TRO B,40 ;SHIFT WAS OFF + JRST STKCVX + +STKCVB: MOVEI B,134 + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + TRZ B,100 + JRST STKCVX + +DEFINE STKM A,B,C,D,E + A_29.+B_22.+C_15.+D_8+E_1 +TERMIN + +DEFINE STKM1 TBL + 350700,,TBL(Q) + 260700,,TBL(Q) + 170700,,TBL(Q) + 100700,,TBL(Q) + 010700,,TBL(Q) +TERMIN + +STKBPT: STKM1 STKTBL +STKTBL: STKM 12,0,0,40,0 + STKM 33,0,0,11,14 + STKM 13,0,0,0,0 + +STKBP1: STKM1 STKTB1 +STKTB1: STKM 133,135,26,174,41 + STKM 5,77,17,60,36 + STKM 22,23,20,21,44 + STKM 45,32,30,1,136 + +STKBP2: STKM1 STKTB2 +STKTB2: STKM 0,34,7,6,74 + STKM 100,76,33,75,47 + STKM 137,31,27,25,24 + STKM 173,176,4,43,35 + STKM 46,140,10,37,3 + STKM 42,2,0,0,0 +};IFN STKP + +SUBTTL INTERFACE (?) TO DM PDP11 ON NTY (REALLY WANT A CAIOS) +IFN NTYP,[ +IFN TK10P, .ERR YOU REALLY WILL LOSE WITH BOTH TTY AND 11 ON NTY +NTYOPN: PUSHJ P,NTYOP1 ;SET UP OPEN + POPJ P, ;OPEN LOST? + SKIPE NTYUSE ;IF THIS IS FIRST OPEN, DO SOME INITIALIZING + JRST POPJ1 + CONO NTY,0 ;STOP INTS + SETOM NTYOAC + MOVE A,[NTYIOI,,NTYIOR] + BLT A,NTYORM ;INITIALIZE ALL THE POINTERS AND COUNTERS + CONO NTY,620000+NTYCHN + JRST POPJ1 + +NTYOP1: ROT D,1 ;MODE BACK, TO GET INPUT & OUTPUT + JSP Q,STDOPN + 3,,NTYUSR + NTYIT,,NTYOT + 0,,0 ;NTYBIT,,NTYBOT + +NTYRS==CPOPJ + +NTYCLS: SOSL NTYUSE ;-1 MEANS FREE (USE STDCLS?) + POPJ P, + SETOM NTYUSE + SETOM NTYUSR + POPJ P, + +;MAIN PROGRAM ROUTINES FOR IOT/SIOT ... + +NTYBI==IOCR10 +NTYBO==IOCR10 + +NTYTO:: +NTYOPT: PCLT ;PUT OUTPUT INTO BUFFER + SKIPG C + SKIPA A,(C) + UMOVE A,(C) ;FETCH THE USERS BYTE + SKIPG NTYORM ;WAIT FOR ROOM + PUSHJ P,UFLS + IDPB A,NTYOIP + SOSGE A,NTYORM + JRST 4,. ;WENT BELOW ZRO? + AOSN NTYOAC + CONO NTY,10+NTYCHN ;NOT ACTIVE, START PI LEVEL + AOSGE NTYOIR + POPJ P, + MOVE A,[NTYOII,,NTYOIR] ;RING AROUND THE ROSY + BLT A,NTYOIP + POPJ P, +NTYTI:: +NTYIGT: MOVEI T,NTYIBS*4 + PCLT + CAMG T,NTYIRM + PUSHJ P,UFLS ;WAIT UNTIL A BYTE COMES IN + ILDB W,NTYIOP + AOS NTYIRM ;NOW MORE ROOM + AOSGE NTYIOR ;RING? + POPJ P, + MOVE B,[NTYIOI,,NTYIOR] ;REDO POINTERS + BLT B,NTYIOP + POPJ P, + +;INTERRUPT ROUTINES + +NTYBRK: TRC A,2000 ;DEVICE # + TRNE A,7000 + JRST NTYSEL ;STOPPED ON OTHER DEVICE + TRNE A,40 + JRST NTYIPT ;INPUT + TRNE A,20 + JRST NTYOGT ;OUTPUT +NTYRET: CONO NTY,620000+NTYCHN ;RESTART + JRST LPBKRT + +NTYSEL: TRC A,2000 ;HAVE TO KNOCK DOWN SOME OTHER FLAG + ANDI A,7000 + LSH A,3 + CONO NTY,400000+NTYCHN(A) + CONSZ NTY,40 + DATAI NTY,A ;CLEAR INPUT + CONSZ NTY,20 + CONO NTY,20+NTYCHN ;CLEAR OUTPUT + AOS NTYERR + JRST NTYRET + +NTYOGT: MOVEI A,NTYOBS*4 + CAMG A,NTYORM + JRST [SETOM NTYOAC + CONO NTY,20+NTYCHN + JRST NTYRET] + ILDB A,NTYOOP + AOS NTYORM + DATAO NTY,A + AOSGE NTYOOR + JRST NTYRET + MOVE A,[NTYOOI,,NTYOOR] + BLT A,NTYOOP ;ZAP THE POINTER AND COUNT (RING BUF) + JRST NTYRET + +NTYIPT: SOSG NTYIRM + CONO NTY,100+NTYCHN ;IF HDWE NOT IN, BUFFER WILL BE CLOBBERED + ;BUT ALSO, THE COUNT WILL BE NEG!!! + DATAI NTY,A + IDPB A,NTYIIP + AOSGE NTYIIR + JRST NTYRET + MOVE A,[NTYIII,,NTYIIR] + BLT A,NTYIIP ;RING THE BUFFER POINTERS + JRST NTYRET + +;DATA AREAS FOR THE NTY INTERFACE TO DM PDP 11 + +NTYIBS==1000 +NTYOBS==100 + +NTYIOI: -NTYIBS*4 ;STUFF TO INITIALIZE INPUT SIDE + 041000,,NTYIBF-1 +NTYIII: -NTYIBS*4 + 041000,,NTYIBF-1 + NTYIBS*4 + +NTYOOI: -NTYOBS*4 ;INITIALIZES OUTPUT SIDE + 041000,,NTYOBF-1 +NTYOII: -NTYOBS*4 + 041000,,NTYOBF-1 + NTYOBS*4 + +EBLK + +NTYIOR: -NTYIBS*4 ;RING COUNTER, INPUT BUFFER, OUTPUT PART +NTYIOP: 041000,,NTYIBF-1 ;BYTE POINTER, " " +NTYIIR: -NTYIBS*4 ;RING CTR, INPUT BUFFER, INPUT PART +NTYIIP: 041000,,NTYIBF-1 ;BYTE POINTER, " " +NTYIRM: NTYIBS*4 ;ROOM EMPTY IN IN BUFFER + +NTYOOR: -NTYOBS*4 ;RING CTR, OUTPUT BUFF, OUT PART +NTYOOP: 041000,,NTYOBF-1 ; BYT PTR, " " +NTYOIR: -NTYOBS*4 ;RING CTR, OUT BUFF, IN PART +NTYOIP: 041000,,NTYOBF-1 ;BYT PTR, " " +NTYORM: NTYOBS*4 ;ROOM IN THE OUTPUT BUFFER + +NTYIBF: BLOCK NTYIBS ;INPUT BUFFER +NTYOBF: BLOCK NTYOBS ;OUTPUT BUFFER + +NTYOAC: -1 ;FLAG, OUTPUT ACTIVE UNLESS -1 +NTYUSR: -1 +NTYUSE: -1 + +NTYERR: 0 + + BBLK +];NTYP + +SUBTTL PDP-10 TO PDP-11 INTERFACE AND XGP + +IFN TEN11P,[ +EBLK +T11MP: BLOCK 256. ;CONTENTS OF TEN11 MAP, -1 => CONFLICT PAGE +BBLK + ;ELSE 0 => AVAIL + ;4.9=1 => CONTENTS OF MAP WD EXCEPT 4.7-4.3 => USE COUNT +IFN XGP,XGPTP==376 ;PAGE NUMBER IN 10-11 RESERVED FOR CLK LEVEL XGP HACKS + +;PLACE WD IN A IN AVAIL 10-11 MAP ENTRY (RETURN IN RH B) +T11AD: SKIPE TEN11F + POPJ P, + MOVE C,A + JSP Q,T11FND ;SKIP UNLESS NO MAP ENTRIES AVAIL + JRST T11A1 ;WD ALREADY IN PAGE + MOVEI C,0 ;FIND FREE PAGE + JSP Q,T11FND + JRST T11A2 + POPJ P, ;NO FREE PGS AVAIL + +T11A1: LDB E,[350500,,T11MP(B)] + CAIN E,37 + JRST T11FN2 ;USAGE COUNT MAX FOR THAT ENTRY + AOS E + DPB E,[350500,,T11MP(B)] + JRST POPJ1 + + +T11A2: MOVEM A,T11MP(B) + MOVEM A,400000+T11CP*2000(B) ;STORE IN HARDWARE + JRST POPJ1 + +T11FND: MOVSI B,-256. +T11FN1: +IFN XGP,[ CAMN B,[-256.+XGPTP,,XGPTP] ;DON'T ALLOCATE SPECIAL XGP ENTRY TO OTHER USERS + JRST T11FN2 +] + MOVE E,T11MP(B) + TLZ E,174000 ;USE COUNT BITS + CAMN E,C + JRST (Q) ;FOUND IT +T11FN2: AOBJN B,T11FN1 + JRST 1(Q) ;CANT FIND IT + + +;DELETE REF TO T11 PAGE IN B +T11DL: SKIPE TEN11F + POPJ P, + MOVE E,T11MP(B) + AOJE E,CPOPJ ;REALLY CONFLICT PAGE + LDB E,[350500,,T11MP(B)] + SOJL E,T11DL1 ;DELETING LAST REF TO PAGE? + DPB E,[350500,,T11MP(B)] + POPJ P, + +T11DL1: CLEARM T11MP(B) + CLEARM 400000+T11CP*2000(B) + POPJ P, +] + +IFN TEN11P,[ + +;.CALL ADR +; LOSE +; WIN +;ADR/ SETZ +; SIXBIT /T11MP/ +; ARG 1 VIRT PAGE # +; ARG 2 DESIRED T11 MAP WORD + +NT11M: TDNE A,[-400] ;TEMP? TEN11 CALL A HAS USER PG + JRST OPNL33 ;INVALID ARG - BAD USER PAGE #. + SKIPE TEN11F + JRST OPNL7 ;DEVICE NOT READY. + PUSHJ P,UPLC + MOVE W,A + JUMPGE B,OPNL33 + TLZ B,174000 ;DONT ALLOW ANYTHING IN USAGE COUNT BITS + MOVE D,B + LDB E,Q + JUMPE E,NT11M1 ;PAGE MUST BE FREE OR ABS, OTHERWISE ERROR + CAIE E,-1 + JRST OPNL13 ;FILE ALREADY EXISTS + LDB B,T + ANDI B,PMRCM + LDB E,[.BP B] ;GET MOBY # + ANDI B,377 + CAIN E,T11CPA_-18. + PUSHJ P,T11DL + MOVEI B,0 + DPB B,Q + DPB B,T +NT11M1: MOVE R,Q + MOVE A,D + PUSHJ P,T11AD + JRST OPNL37 ;NO CORE AVAILABLE. + ADDI B,200000+<_8> ;ADDRESS CORRECT MOBY + TLNE A,200000 + TRO B,400000 ;WRITE PERMISSION + DPB B,T + MOVEI C,-1 + DPB C,R + LSH W,10. + ADDI W,2000 + CAMLE W,HUSRAD(U) + MOVEM W,HUSRAD(U) + JRST POPJ1 +] +.ELSE NT11M: JRST OPNL1 ;NO SUCH DEVICE. + IFN XGP,[ +;CLOCK LEVEL XGP CODE FOR FILLING IMAGE MODE BUFFERS +;ASSUMES XGP11P IS POINTER TO FIRST 11 RING NODE +;AND THAT THE 11 BUFFER RING STRUCTURE IS: + +; POINTER TO NEXT NODE OF BUFFER +; USE WORD (0=> EMPTY) +; POINTER TO BUFFER (ASSUMED TO BE 1K 10 STYLE, 2K 11 STYLE) + +; +;THE NODES AND THE BUFFERS MUST BEGIN ON EVEN PDP-11 WORDS +;I.E. 11 ADDRESSES ENDING WITH TWO ZEROES. + +;THIS CODE USES A SPECIAL 10-11 INTERFACE ENTRY +;NAMELY, XGPTP, AND THREE EXEC PAGES, XGPC WHICH POINTS TO +;THE LOW 2K OF PDP-11 CORE, USED FOR THE RING NODE POINTERS +;XGPUB WHICH POINTS TO THE CURRENTLY HACKED USER PAGE +;AND XGPB WHICH POINTS PERMANENTLY TO THE 10-11 PAGE CORRESPONDING +;TO XGPTP + +XGP11==1 ;PDP-11 RUNNING XGP +XGPCA==XGPC*2000+400000 ;EXEC ADR OF LOW PDP-11 CORE +XGPBA==XGPB*2000+400000 ;EXEC ADR OF BUFFER IN PDP-11 +XGPUBA==XGPUB*2000+400000 ;EXEC ADR OF CURRENT PAGE IN USER'S MAP +XGNTPG==117. ;MAX # TIED DOWN PAGES (WOULD YOU BELIEVE...) +X11BFP==102 ;LOC OF XGP BUFF HEAD IN 11 (PDP11 ADR 410) + +XGPCLK: PUSH P,A + PUSH P,B + MOVE A,XGPTM1 ;TIME FIRST PAGE LOCKED IN CORE + ADDI A,30.*60. ;1 MINUTE + CAMGE A,TIME ;WIN? + JSP Q,XGPFLS ;LOSE... + SKIPL XGPINI ;DON'T HACK UNTIL MAIN PGM HAS PAGES TIED DOWN + JRST POPBAJ + SPM XGPSPM ;SAVE OLD MAP +XGPC1: MOVE A,XGP11P ;GET POINTER TO FIRST PDP-11 BUFFER + MOVE A,XGPCA(A) ;GET CONTENTS FROM PDP-11 + LDB B,[242000,,A] ;GET NEXT RING POINTER + LDB A,[042000,,A] ;GET USE WORD + JUMPN A,POPBAJ ;BUFFERS FULL + TRNE B,3 + JSP Q,XGPFLS ;NEW BUF POINTER NOT ON EVEN WD BNDY + LSH B,-2 ;CONVERT TO 10 ADDRESS + SKIPE B + CAIL B,2000 ;IS IT WITHIN CONTROL PAGE? + JSP Q,XGPFLS ;FLUSH + EXCH B,XGP11P ;SETUP NEXT POINTER, GET BACK OLD ONE + MOVEM B,XGPOB ;SAVE OLD POINTER FOR HACKING BUFF FULL + MOVE B,XGPCA+1(B) ;GET POINTER TO 11 BUFFER + LDB B,[242000,,B] + TRNE B,3 + JSP Q,XGPFLS + LSH B,8 ;SETUP 10-11 ENTRY + IOR B,[600000+,,1777] ;R/W, PROT INFINITE + MOVEM B,400000+2000*T11CP+XGPTP ;GRONK INTO 10-11 INTERFACE + MOVEM B,T11MP+XGPTP ;FOR DEBUGGING ONLY + ILDB A,XGP10P ;GET POINTER TO NEXT 10 PAGE + CAIL A,TSYSM ;LOSE + JRST 4,. ;MAIN PGM HAS POINTER TO NXM + JUMPE A,XGPFIN ;HERE WE ARE DONE, I HOPE. DEUS GRATIUS + MOVE B,A ;SAVE MMSWP ENTRY # TO CLEAR OUT TIE DOWN + IORI A,600000 ;R/W + DPB A,[.XGPUB+EXEUMP] ;GRONK EXEC MAP + LPMR XGPSPM ;RESET ASSOC REGS + MOVE A,[XGPUBA,,XGPBA] + BLT A,XGPBA+1777 ;DO THE STUFF! + MOVSI A,-1 + ADDM A,MMSWP(B) ;CLEAR TIE DOWN, PHEW! + SKIPGE MMSWP(B) ;STOP BUGGY LOSSAGE + JRST 4,. + PUSHJ P,XGPBIT ;GET TABLE INFO + TDNN A,XGPMTB(B) + JRST 4,. ;UNTIED PAGE NOT TIED DOWN + ANDCAM A,XGPMTB(B) ;CLEAR THE BIT + MOVEI A,0 + DPB A,[.XGPUB+EXEUMP] ;CLEAR EXEC PAGE MAP + MOVE A,XGPOB ;GET OLD RING PTR + MOVEI B,30 ;CHANGE RH ONLY TO A 1 + MOVEM B,XGPCA(A) ;SET BUFFER FULL + JRST XGPC1 ;LOOP TO GET A NEW BUFFER + + + +XGPFIN: SETZM XGPINI + JSP Q,XGPFLS + +;MMSWP ENTRY IN B, +;RETURNS BIT IN A +;WD OF TABLE IN B +XGPBIT: MOVE A,B + IDIVI A,36. + MOVNS B + PUSH P,A + MOVSI A,400000 + LSH A,(B) + JRST POPBJ + +;CALLED FROM CORE ALLOCATOR WHEN FLUSHING PAGES +;OF A JOB WHICH HAVE LH OF MMSWP NON ZERO. + +XGPCFL: CAME U,XGPUSR ;ARE WE CONCERNED? + POPJ P, ;NOPE + PUSH P,A + PUSH P,B + MOVE B,TT ;B GETS MMSWP INDEX + PUSHJ P,XGPBIT ;GET INDEXES INTO XGPMTB + TRNN A,XGPMTB(B) ;IS THIS A PAGE BEING HACKED BY XGP? + JRST POPBAJ ;NOPE + ;FALLS THRU + +;XGPFLS IS CALLED AT THE CLOCK LEVEL IF ANYTHING GOES WRONG WITH ANYTING +;AND AT THE END OF THE RUN. +;IT FREES THE WORLD, AND FLUSHES THE XGP USER + +XGPFLS: MOVEM Q,XFLSPC + SETOM XGPUSR ;FLUSHES XGP, ALSO PREVENTS TIMING ERRORS IF XGPFLS CALLED + ;AT CLOCK LEVEL, SINCE IT WON'T BE ANY MORE + PUSH P,C + PUSH P,D + CLEARB A,B + MOVSI C,400000 + MOVSI D,-1 +XGPFL1: TDNN C,XGPMTB(B) + JRST XGPFL3 ;THIS PAGE NOT HACKED + ADDM D,MMSWP(A) ;UNTIE THIS PAGE + SKIPGE MMSWP(A) + JRST 4,. + ANDCAM C,XGPMTB(B) ;AND FLUSH THIS BIT +XGPFL3: ROT C,-1 ;MOVE ON TO NEXT BIT + SKIPGE C ;BEG OF NEW WORD? + AOS B ;YES, AOS XGPMTB INDEX + CAIGE A,TSYSM-1 ;FINISHED WITH ALL OF MMSWP ENTRIES? +XGPFL2: AOJA A,XGPFL1 ;NOPE, LOOP BACK FOR MORE FUN + POP P,D + POP P,C + JRST POPBAJ + + +;MAIN PROGRAM BUFFER TIE DOWN ROUTINES +;.CALL FOO +;FOO: SETZ +; SIXBIT /XGPIM/ +; SETZ POINTER TO [# OF PAGES,,FIRST PAGE] + +NXGPIM: XCTR XRW,[MOVES B,(A)] ;GET POINTER, AND CHECK FOR WRITE + JUMPL B,XCONT ;CONTINUING A PREVIOUS CALL + SKIPN TEN11F + SKIPL XGPUSR + POPJ P, ;LOSE + MOVEI C,X11BFP ;BUFF HEAD IN 11 DEFINED AS 1000 + MOVEM C,XGP11P + MOVE C,XGPCA(C) ;GET BUFF POINTER FROM 11 + JUMPE C,CPOPJ ;LOSE, THE 10-11 IS LOSING OR PGM LOSING + MOVE C,TIME + MOVEM C,XGPTM1 ;SET UP TIMEOUT ON PAGE LOCK + SETZM XGPINI ;SAY NOT ACTIVE + MOVEM U,XGPUSR ;AND BEING LOADED + SETZM XGPTAB + MOVE C,[XGPTAB,,XGPTAB+1] + BLT C,XGPTAB+LXTAB-1 ;CLEAR OUT OLD PAGE BUF TABLE + MOVE C,[441400,,XGPTAB] + MOVEM C,XGP10P ;SETUP BYTE POINTER TO PAGE LIST +XTIE: TLO B,400000 + UMOVEM B,(A) + HRRZ C,B + HRRZ E,B ;C,E GET PAGE # NEXT TO BE TIED DOWN + HLRZ D,B ;D GETS COUNT OF PAGES LEFT + LSH C,10. + UMOVE B,20(C) ;BRING IN THAT LOSING PAGE + PUSHJ P,SWTL + CIRPSW + TRZ D,400000 + CAIL D,XGNTPG ;MAX # PAGES TIED DOWN + JRST XLOSE + EXCH E,A + CAIL A,400 + JRST XLOSE ;PAGE OUT OF REASONABLE RANGE + PUSH P,A + PUSHJ P,UPLC ;FIND OUT PAGE MAP ENTRY + LDB B,Q + CAIN B,-1 + JRST XLOSE1 + LDB B,T + ANDI B,PMRCM + CAIL B,TSYSM + JRST 4,. + PUSHJ P,XGPBIT + CONO PI,CLKOFF ;CLOCK OFF TO PREVENT PAGES 1/2 TIED DOWN + TDNN A,XGPMTB(B) ;WE HAVE HIT THIS PAGE ALREADY + CAME U,XGPUSR ;TIMEOUT OR OTHER GROSS LOSSAGE + JRST XLOSE1 ;DON'T TIE THIS ONE DOWN, AND FLUSH ALL THE REST + IORM A,XGPMTB(B) ;SET BIT IN XGP MEM TABLE + LDB B,T + ANDI B,PMRCM + IDPB B,XGP10P ;PUT IN BUFFER LIST + MOVSI A,1 + ADDM A,MMSWP(B) ;TIE IT DOWN GOOD (FOR ALL YOU BONDAGE FREAKS) + CONO PI,CLKON + PUSHJ P,LSWPOP ;CIRPSW + POP P,B + SOJLE D,XBFIN ;WE ARE DONE TYING START XGPING + AOS B + HRL B,D + MOVE A,E ;NOW, LOOP FOR MORE CRUFTIES, OR +XCONT: CAME U,XGPUSR ;REENTER HERE IF THE MAD SWAPPER HAD US SWAPPED OUT + POPJ P, + JRST XTIE + +XLOSE1: CONO PI,CLKON ;CLEANUP AFTER LOSSAGE + SUB P,[1,,1] +XLOSE: PUSHJ P,LSWPOP ;CIRPSW + PUSH P,A + PUSH P,B + JSP Q,XGPFLS ;FLUSH THE LAST VESTIGE OF THIS ABORTIVE ATTEMPT TO CAUSE WINNAGE + +XBFIN: SETOM XGPINI ;THE WORST IS OVER, SIT BACK AND RELAX + MOVE A,[441400,,XGPTAB] + MOVEM A,XGP10P + JRST POPJ1 ;TELL HIM HE MAY EVEN WIN SOMEDAY + +XPLO: CONO PI,CLKOFF + PUSHJ P,XPLST + JRST XPLO1 + CONO PI,CLKOFF + PUSHJ P,XPLWT + PUSHJ P,UFLS + MOVE T,XPLU + SKIPE IOCHNM(T) + JRST XPLO2 + MOVE T,SV40(T) + CAME T,[.SLEEP 17,] +XPLO2: JRST OPNL10 + CONO PI,CLKON + MOVNI A,1 + MOVSI B,(SIXBIT /XPL/) + PUSHJ P,CLIO + POPJ P, + MOVE A,UTMPTR(U) + MOVE B,XPLU + MOVEM A,UTMPTR(B) + JRST POPJ1 + +XPLO1: PUSHJ P,UDELAY + JRST XPLO + +XPLST: SKIPL T,XPLU + PUSHJ P,XPLIN + JRST POPJ1 + HRROI A,XPL + CONO PI,UTCOFF + PUSHJ P,NUJBST + JRST UTCONJ + JRST UTCOJ1 + +XPLWT: SKIPGE T,XPLU + POPJ P, + PUSHJ P,XPLIN + SKIPGE IOCHNM(T) + JRST POPJ1 + MOVS Q,SV40(T) + CAIN Q,(.SLEEP 17,) + AOS (P) + POPJ P, + +XPLIN: PUSH P,U + CAML T,USRHI + JRST XPLIN1 + HLRE U,UNAME(T) + AOJN U,XPLIN1 + MOVSI U,(SIXBIT /XPL/) + CAME U,JNAME(T) +XPLIN1: AOS -1(P) + POP P,U + POPJ P, + +;VARIABLES AREA +EBLK + +XGPTAB: BLOCK XGNTPG/3+1 ;PAGE #'S OF XGP BUFS IN 12 BIT BYTES +LXTAB==.-XGPTAB +XGP11P: 0 ;POINTER TO 11 RING STRUCTURE (10 STYLE ADR INTO XGPC) +XGPOB: 0 ;TEMP FOR OLD XGP11P +XGP10P: 0 ;BYTE POINTER INTO XGPTAB FOR GETTING 10 BUFFERS +XGPMTB: BLOCK TSYSM/36.+1 ;BIT TABLE FOR KEEPING + ;TRACK OF AOSES OF MMSWP +XGPUSR: -1 ;XGP USER INDEX, -1 IF NONE +XGPINI: 0 ;IF -1, SIGNAL TO CLK CODE THAT ALL BUFFERS ARE NOW TIED DOWN. +XFLSPC: 0 ;PC OF LAST CALL TO XGPFLS +XGPSPM: BLOCK 8 ;STORAGE FOR PAGE MAP ENTRIES +XGPTM1: 0 ;TIME FIRST PAGE TIED DOWN +XPL: SIXBIT /XPL/ ;FILE + JNAME OF XPL INTERPRETER +XPLU: 0 ;INDEX OF LOADED XPL + +BBLK +] + +IFE XGP,NXGPIM: JRST OPNL1 ;NO SUCH DEVICE + +SUBTTL ROBOT ARM ROUTINES + +IFN ARMP,[ +NARMCH==11. + +AARMOVE: UMOVE A,(J) + JUMPGE A,CPOPJ + CAMGE A,[-100,,] + JRST ILUUO + CONO PI,CLKOFF + CAMN U,ARMUSR + JRST AARM1A + SKIPL ARMUSR + JRST ILUUO +; CONO TIPDEV,0 +; CONI TIPDEV,C +; JUMPE C,ILUUO ;DONT ALLOW ARM TO RUN WITHOUT TIPBRK +; DATAI TIPDEV,C +; TRNN C,1 +; JRST ILUUO ;WRIST DETENT OFF NORMAL- BARF +; CONO TIPDEV,TIPBCH + MOVEM U,ARMUSR +AARM1A: CONO PI,CLKON + MOVSI B,-NARMCH +AARM1: SETZM ARMDF(B) + SKIPN ARMF + SETOM DESTIN(B) ;NOT PREV IN USE, INITIALIZE + AOBJN B,AARM1 + SKIPN ARMF + SETOM OMPXIF + SKIPN ARMF + PUSHJ P,IMXON ;START IMX + SETOM ARMF ;ARM NOW IN USE + SETOM DLSRCH +ARML: UMOVE E,(A) ;PICK UP COMM + LDB C,[220400,,E] + JUMPE C,ARML1 ;NO INDEX + XCTR XRW,[HRRZ Q,(C)] + ADD E,Q + TLZ E,17 +ARML1: TLZE E,20 + XCTR XRW,[HRR E,(E)] + LDB D,[360600,,E] ;CHNL + LDB C,[300600,,E] ;OP + CAIGE D,NARMCH + CAIL C,NARMOP + JRST ARMLOS + PUSHJ P,@ARMOPT(C) + AOBJN A,ARML + ADF1: MOVSI D,-NARMCH +ADFL: SKIPL A,ARMDF(D) + JRST ADF2 + TLNE A,100000 + JRST .+3 + MOVE C,RMAXV(D) + MOVEM C,MAXV(D) +ADF2: AOBJN D,ADFL + SETZM DLSRCH + JUMPL B,POPJ1 + POPJ P, + +ARMLOS: SETZM DLSRCH + JRST ILUUO + +ARMOPT: ASDEST ;0 SET DEST + ASVEL ;1 SET VELOC + ATDEST ;2 COMPARE COMPUTED POSN + ATVEL ;3 COMPARE COMPUTED VELOC + AADST ;4 COMPARE ACTUAL POS + ARPOST ;5 READ CURRENT POSITION +NARMOP==.-ARMOPT + +ARPOST: LDB B,IMPXPP(D) ;READ POSITION + UMOVEM B,(E) + POPJ P, + +ASDEST: ANDI E,7777 + CAMGE E,DESMIN(D) + MOVE E,DESMIN(D) + CAMLE E,DESMAX(D) + MOVE E,DESMAX(D) + MOVEM E,DESTIN(D) + MOVSI E,600000 +ADFSET: IORM E,ARMDF(D) + POPJ P, + +ASVEL: ANDI E,7777 + CAMLE E,RMAXV(D) + MOVE E,RMAXV(D) + MOVEM E,MAXV(D) + MOVSI E,500000 + JRST ADFSET + +AADST: LDB C,IMPXPP(D) ;COMPARE ACTUAL POSITION + SUB C,DESTIN(D) + JRST ATD1 + +ATDEST: SKIPA C,DESTIN(D) ;COMPARE COMPUTED POSITION +ATVEL: SKIPA C,VELOC(D) ;COMPARE COMPUTED VELOCITY + SUB C,POST(D) +ATD1: MOVMS C + CAMLE C,E + TLO B,400000 + POPJ P, + +SERVO: MOVSI A,-NARMCH + AOSN OMPXIF + JRST SERVI +SERV1: MOVE T,DESTIN(A) + SUB T,POST(A) + SKIPN VELOC(A) + JUMPE T,SERVX +SERV1A: MOVN B,MAXV(A) + MOVE C,VELOC(A) + SUB C,MAXA(A) + CAMGE C,B + MOVE C,B + MOVE B,VELOC(A) + ADD B,MAXA(A) + CAMLE B,MAXV(A) + MOVE B,MAXV(A) + CAMG T,B + CAMGE T,C + JRST SERV2 + MOVM D,T + CAMLE D,MAXA(A) + JRST SERV2 +SERV3: MOVEM T,VELOC(A) + ADDB T,POST(A) + IOR T,OMPXP(A) + DATAO OMPX,T +SERVX: AOBJN A,SERV1 +SERVR: JRST ARMSVR + +SERV2: SKIPGE T + SKIPA D,C + MOVE D,B + SUB T,VELOC(A) + MOVM E,D + IMUL D,E + IDIV D,MAXA(A) + ASH D,-1 + CAMGE D,T + SKIPA E,B + MOVE E,C + MOVE C,E + XOR C,VELOC(A) + JUMPGE C,SERV2A + MOVE C,E + XOR C,T + JUMPGE C,SERV2A + SKIPA T,VELOC(A) +SERV2A: MOVE T,E + JRST SERV3 + +SERVI: LDB B,IMPXPP(A) ;INITIALIZE TO CURRENT ARM STATE + MOVEM B,POST(A) + SETZM VELOC(A) + SKIPGE DESTIN(A) + MOVEM B,DESTIN(A) + IOR B,OMPXP(A) + DATAO OMPX,B + AOBJN A,SERVI + JRST SERVR + +AARMOFF: CAME U,ARMUSR + POPJ P, + CONO TIPDEV,0 + SETZM ARMF + PUSHJ P,IMXCL1 + SETOM ARMUSR + POPJ P, + +AARMRS: CAME U,ARMUSR ;RESET ARM LOCK FLAGS + POPJ P, + MOVSI A,-NARMCH +AARMR1: SKIPL ARMLOK(A) + JRST AARMR2 + CONO PI,OMXOFF + SETOM DESTIN(A) ;RELOAD ARM COMM FROM CURRENT POS + CLEARM ARMLOK(A) + SETOM OMPXIF + CONO PI,OMXON +AARMR2: AOBJN A,AARMR1 + POPJ P, + + +TIPBRK: DATAI TIPDEV,B + TRNE B,1 ;WRIST DETENT + JRST TIPBR2 + SETOM ARMLOK+ARMVRT ;UNHAPPINESS +TIPBR2: EXCH B,TIPBR + XOR B,TIPBR + SKIPGE A,ARMUSR + JRST TIPBR1 + ANDI B,7 + LSH B,ATPSFT + IORM B,PIRQC(A) +TIPBR1: JRST OMXRET + + +EBLK + +;JOINT ASSIGN +;0-10 AMF SWING VERT HORIZ YAW TILT GRIP ROTATE EXTEND ROLL +;11-12 NEW VIDI FOCUS IRIS + +ARMVRT==1 ;CHNL # OF ARM VERT + +DESMIN: IRPS A,,0 41 233 0 0 0 0 0 0 0 0 + A +TERMIN +DESMAX: IRPS A,,7777 7777 7323 7777 7777 7777 7777 7777 7777 7777 7777 + A +TERMIN +DESTIN: BLOCK NARMCH ;-1 NOT COMMANDED + VAL OF POSITION COMMAND +POST: BLOCK NARMCH ;POSITION OF ARM AT PI LEVEL +VELOC: BLOCK NARMCH +MAXV: BLOCK NARMCH +ARMDF: BLOCK NARMCH ;4.9 VARIABLE CHANGED 4.5 POS VAR 4.7 VEL 4.6 ACC +ARMLOK: BLOCK NARMCH ;IF -1 AXIS LOCKED DO NOT ALLOW CHNG IN COMMAND + +MAXA: REPEAT NARMCH,14 +RMAXV: REPEAT NARMCH,140 + +OMPXP: IRPS A,,2 3 4 6 7 12 11 10 5 32 31 + A,, + TERMIN + +IMPXPP: IRPS A,,102 103 104 106 107 112 111 110 105 132 131 + 301400-140000*,,MPXBUF+A/3 + TERMIN + +ARMUSR: -1 ;-1 OR INDEX OF USER DOING ARMOVE +OMPXIF: 0 ;-1 => INITIALIZE DESTINS'S TO CURRENT ARM POSITION +ARMF: 0 ;-1 ARM IN USE, 0 NO ARMOV EXECUTED +TIPBR: 0 ;TIP BREAK REG LAST TIME READ IN +BBLK +] + +SUBTTL INPUT MULTIPLEXOR + +IFN IMXP,[ +APOTSE: CONI MPX,T + JUMPE T,ILUUO ;MPX NOT AVAIL + MOVE C,B +APOTS1: UMOVE A,(C) + ANDI A,377 ;GET IMPX CHNL + JUMPE A,CPOPJ ;CHNL 0 = END OF LIST + IDIVI A,3 ;COMPUTE MPXBUF INDEX + ADD A,MPXPT(B) ;FORM BYTE PTR + MOVSI B,-NPOTCH ;SET UP TN DELETE PREVIOUS POT CONN +PTS1: CAMN A,POTBPT(B) ;IS ENTRY FOR SAME CHNL + SKIPG POTUSR(B) ;AND ACTIVE + JRST PTS2 ;NO,KEEP LOOKING + CAME U,POTUSR(B) ;IS THIS USER THE ONE WHO MADE ENTRY + JRST ILUUO ;NO,ILLEGAL + PUSHJ P,NARK ;DEACTIVATE AND FREE ENTRY + +PTS2: AOBJN B,PTS1 ;TRY NEXT ENTRY + MOVEI B,400000 ;MASK FOR DELETE ONLY + XCTR XRW,[TDNE B,(C)] ;SKIP ON NEW ENTRY WANTED + JRST PTSR ;TRY FOR NEXT BLOCK + MOVSI B,-NPOTCH ;SET UP TO FIND FREE ENTRY +PTS3: SKIPL POTUSR(B) ;SKIP ON FREE +PTS4: AOBJN B,PTS3 ;TRY OTHER SLOTS + JUMPGE B,ILUUO ;NO SLOTS AVAIL + CONO PI,CLKOFF ;PREVENT OTHER GRABBERS + SKIPGE POTUSR(B) ;SKIP IF JUST TAKEN + JRST PTS5 ;OKAY FOR SURE + CONO PI,CLKON ;REENABLE + JRST PTS4 ;TRY ANOTHER + +PTS5: SETZM POTUSR(B) ;MARK TAKEN + AOS IMXNTO + AOS POTCON ;INCREMENT NUMBER SLOTS IN USE + PUSHJ P,IMXON ;START IMPX + CONO PI,CLKON ;AND ENABLE +PTS6: MOVEM A,POTBPT(B) ;SAVE PTR TO MPXBUF FOR MPX ROUTINE + XCTR XRW,[HRRZ A,1(C)] ;GET USER ADR + XCTRI XRW,[MOVES (A)] + JRST .+2 + JRST PTSL1 ;NO,LOSE + XCTR XRW,[HLL A,1(C)] ;GET BYTE FIELDS + TLNN A,777700 ;IF NONE SPECIFIED + TLC A,4400 ;ASSUME FULL WORD + TLZ A,77 ;FLUSH INDEX,INDIRECT + MOVEM A,POTVPT(B) ;SAVE AS USER MEM PTR FOR MPX ROUTINE +PTS7: UMOVE A,(C) + ANDI A,3 ;GET FLOAT + ABS BITS + MOVEI D,PUFLI ;ADDR OF FLOATING INCREMENTAL UPDATE + TRNN A,1 ;SKIP ON FLOATING + MOVEI D,PUFXI ;ADDR OF FIXED INCREMENTAL UPDATE + TRNE A,2 ;SKIP ON NOT ABSOLUTE + SOS D ;ABS ROUTINE STARTS ONE BEFORE INCREMENTAL + MOVEM D,POTUPD(B) ;SAVE ROUTINE ADDR FOR MPX ROUTINE +PTS8: XCTR XRW,[MOVN D,2(C)] ;GET LOWER LIMIT + MOVNM D,POTOFS(B) ;SAVE AS OFFSET FOR MPX ROUTINE + TRNE A,1 ;SKIP ON FIXED + JRST PTS9 ;GO SET FLOATING PARAMS + XCTR XRW,[ADD D,3(C)] ;UL-LL + ASH D,-2 ;SCALE MULTIPLIER + +PTS9R: MOVEM D,POTSCL(B) ;STORE SCALE FACTOR FOR MPX ROUTINE + LDB D,POTVPT(B) ;GET CURRENT VARIABLE VALUE + TRNE A,1 ;SKIP ON FIXED + JRST PTS10 ;COMPUTE FLOATING INCR VALUE + SUB D,POTOFS(B) ;D_VAL-LL FIXED + MOVSI E,200000 ;SET TO ROUND VALUE + ASHC D,-25. ;SCALE TO GET 12 BIT VALUE + DIV D,POTSCL(B) ;COMPUTE INCR VAL FOR VAR +PTS10R: HRROM D,POTVAL(B) ;STORE INCR VALUE FOR MPX ROUTINE + MOVEM U,POTUSR(B) ;STORE USER TO ACTIVATE MPX ROUTINE +PTSR: ADDI C,4 ;ADVANCE POINTER TO NEXT 4 WORD BLOCK + JRST APOTS1 ;GO SET MORE TABLE ENTRIES + +PTS9: FADR D,3(C) ;UL-LL IN FLOATING + FSC D,-12. ;SCALE DOWN FOR POT RANGE + JRST PTS9R ;RETURN WITH SCALE FACTOR + +PTS10: FSBR D,POTOFS(B) ;D_VAL-LL FLOATING + FDVR D,POTSCL(B) ;COMPUTE INCR VAL FLOATING + MULI D,400 ;FIX INCR VAL + TSC D,D ;WORK FOR BELOW LOWER LIMIT + ASH E,-243(D) ;VALUE IN E + MOVE D,E ;TO D LIKE FIXED + JRST PTS10R ;RETURN WITH INCR VALUE + + +PTSL1: PUSHJ P,NARK + PUSHJ P,TPFLT + JRST UUOTRO + +;POTS UPDATE CALLED BY MPX ROUTINE + +UPOTS: SPM UPTPGT + MOVSI A,-NPOTCH ;SET UP TO LOOP FOR ALL POT TABLE POSITIONS + SETZM UPUSR ;INDICATE NO USER SET UP +UPOT1: SKIPLE U,POTUSR(A) ;SKIP ON SLOT UNUSED OR IN PROCESS + JRST UPOT2 ;GO TRY TO UPDATE VAR +UPOTR: AOBJN A,UPOT1 ;TRY NEXT POT TABLE ENTRY + LPMR UPTPGT ;RESTORE MAP + JRST UPOTRT ;DONE + +UPOT2: CAMN U,UPUSR ;IS THIS USER LAST UPDATED + JRST UPOT3 ;YES, RELOCATION IS SETUP + MOVE T,USTP(U) ;TEST TO SEE IF + SKIPN UMAPS(U) ;MAP LOADED TO POINT TO OTHER USER + TLNE T,BUCSTP+BCSTOP ;USER BEING MOVED + JRST UPOTR ;YES DON'T UPDATE FOR HIM + MOVEM U,UPUSR ;SAVE AS LAST USER SET UP + LPMR UPGML(U) ;LOAD USERS MAP + UPOT3: LDB B,POTBPT(A) ;GET CURRENT ABS POSITION + HLRZ C,POTVAL(A) ;GET POS LAST TIME + TRNE C,400000 ;SKIP UNLESS FIRST TIME + JRST UPOT3A + MOVE T,B + SUB T,C + MOVMS T + CAMG T,PTNOIS + JRST UPOTR +UPOT3B: HRLM B,POTVAL(A) ;SAVE FOR NEXT TIME + SUB B,C ;GET AMOUNT OF INCREMENT + CAIL C,5252 ;SKIP IF NOT IN UPPER THIRD + JUMPG B,UPOT4 ;JUMP IF IN UPPER THIRD AND GOING UP + CAIGE C,2525 ;SKIP IF NOT IN LOWER THIRD + JUMPL B,UPOT5 ;JUMP IF IN LOWER THIRD AND GOING DOWN +UPOT6: HRRE C,POTVAL(A) ;GET PREV INCREMENTAL VALUE + ADD C,B ;UPDATE BY POT INCR + CAILE C,7777 ;IF NEW VALUE WOULD EXCEED 7777 + MOVEI C,7777 ;CLAMP IT TO 7777 + CAIGE C,0 ;IF NEW VALUE WOULD BE LESS THAN 0 + MOVEI C,0 ;CLAMP IT TO 0 + HRRM C,POTVAL(A) ;STORE NEW INCR VALUE + JSP B,@POTUPD(A) ;CALL ROUTINE TO COMPUTE NEW VARIABLE VALUE + HRRZ T,POTVPT(A) ;STORE VAR IN USER MEM + XCTRI XR,[MOVE B,(T)] + JRST .+2 + JRST INARK + MOVEI D,B + HLL D,POTVPT(A) + DPB C,D + XCTRI XW,[MOVEM B,(T)] ;STORE VAR IN USER MEM + JRST UPOTR + +INARK: SETOM POTUSR(A) ;THIS POT A LOSER, FLUSH + SOS POTCON + SOS IMPXF + SOSGE IMXNTO + DATAO DSDEVN,[MPX] + JRST UPOTR ;RETURN FOR MORE POTS + +UPOT4: HRREI C,-6(B) ;C_DELTA-6 + IMULI C,3 ;C_DELTA*3-22 + CAMLE C,B ;IF POT TURNED UP FAST + MOVEM C,B ;THEN BOOST INCREMENT + JRST UPOT6 ;RETURN TO STORE + +UPOT5: HRREI C,6(B) ;C_DELTA+6 + IMULI C,3 ;C_DELTA*3+22 + CAMGE C,B ;IF POT TURNED DOWN FAST + MOVEM C,B ;THEN DECREASE DECREMENT + JRST UPOT6 ;RETURN TO STORE + +PUFXA: HLRZ C,POTVAL(A) ;ABS ENTRY, USE DIRECT VALUE +PUFXI: MUL C,POTSCL(A) ;INCR ENTRY, SCALE VALUE + ASHC C,25. ;200000,,=FULL WORD + ADD C,POTOFS(A) ;OFFSET VALUE + JRST (B) ;RETURN WITH USER FIELD VALUE + +PUFLA: HLRZ C,POTVAL(A) ;ABS ENTRY FOR FLOAT PT +PUFLI: TLC C,232000 ;FLOAT POT VALUE + FAD C,C ;NORMALIZE + FMPR C,POTSCL(A) ;SCALE FLOATING VALUE + FADR C,POTOFS(A) ;ADD OFFSET + JRST (B) ;RETURN WITH NEW FLOATING VAR VALUE + +UPOT3A: MOVE C,B ;FIRST TIME USE CURRENT VALUE + JRST UPOT3B + + +NARK: SETOM POTUSR(B) ;TURN OFF AND FREE POT CHANNEL + SOS POTCON ;DECREMENT # OF SLOTS IN USE + JRST IMXCL1 ;FLUSH THIS USE OF MPX AND MAYBE DEASSIGN MPXR + +POTCLS: MOVEI A,NARK ;ON CLOSE FLUSH ALL ENTRIES FOR USER +POTCLA: MOVSI B,-NPOTCH ;SET UP TO TEST ALL ENTRIES FOR USER U +POTCL1: CAMN U,POTUSR(B) ;SKIP IF DIFFERENT USER + PUSHJ P,(A) ;FLUSH IT MAYBE + AOBJN B,POTCL1 ;TRY ALL SLOTS + POPJ P, ;DONE + +EBLK +POTUSR: REPEAT NPOTCH,-1 ;-1=FREE, 0=PROCESS, +=USER INDEX +POTBPT: BLOCK NPOTCH ;BYTE PTR INTO MPXBUF +POTVPT: BLOCK NPOTCH ;BYTE PTR INTO USER MEM INDEXED BY R +POTVAL: BLOCK NPOTCH ;DIRECT VALUE,,INCR VALUE +POTUPD: BLOCK NPOTCH ;ADDR OF ROUTINE TO COMPUTE NEW VALUE +POTSCL: BLOCK NPOTCH ;SCALE FACTOR FOR VARIABLE +POTOFS: BLOCK NPOTCH ;OFFSET FOR VARIABLE +MPXPT: REPEAT 3,301400-140000*.RPCNT,,MPXBUF ;POINTERS FOR 12 BIT MPX BYTES +UPUSR: 0 ;USER FOR WHOM RELOC SETUP AND NOT STOPPED +UPTPGT: BLOCK 8 ;SAVE MAP + +POTCON: -1 ;-1 + +PTNOIS: 3 ;IGNORE ANY CHANGE < OR = THIS AS POT NOISE +] + +SUBTTL 340 DISPLAY + +IFN 340P,[ +; +; DISPLAY INTERRUPT ROUTINE +; +DRECYC: 0 +; +BBLK +; + MOVEM A,LPTA + MOVE A,DRECYC + MOVEM A,LPTBRK + MOVE A,[B,,LPTB] + BLT A,LPTB+17-B+1-1 + JRST DRECY1 +SRECYC: MOVE A,[B,,LPTB] + BLT A,LPTB+17-B+1-1 + CONSZ DIS,2000 + JRST DSLTPB ;LIGHT PEN BREAK + SKIPGE 340MD + JRST SRCYRB ;RANDOM BREAK + CONSZ DIS,5000 + JRST SRCY4 +DRECY1: +; DATAI 710,A +; SUB A,LQTIM +; CAIL A,32000./2 +; JRST DISF2 ;MISSING CLOCK BREAK DUE TO DIS + HLRE A,DBLKOP + SKIPL A + TDZA A,A + MOVNS A + ADDB A,DWDS ;CREDIT BACK WDS NOT USED + JUMPL A,DISF2 + HRRZS DBLKOP + SKIPE 340MD + JRST SRCY3 ;IDS OR DIS +SRCY1: HRRZ A,LDISP + JUMPE A,ENDLIS + JSP B,DPFTCH + JUMPL A,SRCY2A ;SINGLE BLKO PNTR + MOVEM A,LDISP ;LIST + HLRZS A + JUMPE A,SRCY5 ;THIS ENTRY NULL + JSP B,DPFTCH + SKIPGE LMODE + JRST SRCY1A ;DSTRT +SRCY1C: JUMPGE A,SRCY5 + MOVEM A,LUBLKP ;SAVE FOR DEBUGGING + HLRO C,A + MOVNS D,C ;+ COUNT + LDB E,[1200,,A] ;WD WITHIN PG + ADD E,D + LSH E,-10. + AOS E + MOVE J,E ;SAVE # EXEC PGS REQD + SUBI E,N340PB + JUMPG E,SRCY2B ;CANT MAKE IT IN ONE WHACK + MOVN Q,E ;SAVE MAX ACCEPT STARTING EXEC PG # + HRLZS E + HRRZ C,A + CAIGE C,20 + JRST DISLOS + ANDI C,776000 ;USER PG # + MOVNI R,1 ;BEST STARTING PLACE SO FAR +SRCY2D: CAMN C,340DA(E) ;LOOK FOR PG SET UP TO RIGHT USER PG + JRST SRCY2F ;FOUND ONE +SRCY2I: AOBJN E,SRCY2D + HRRZ E,R + JUMPGE R,SRCY2C ;PARTIALLY SET UP PLACE FOUND + AOS 340DP + CAML Q,340DP ;NONE AVAIL, IS RING PNTR IN ACCEPTABLE AREA? + SKIPA E,340DP ;YES + CLEARB E,340DP ;NO RESET +SRCY2C: MOVE R,DDAD(E) + LSH R,-10. + DPB R,[121000,,A] ;SWITCH BLKO PNTR TO EXEC MD PG + MOVEM A,LDBLKP + MOVEM A,DBLKOP + HLRES A ;FOR GROSS DISPLAY LISTS + ADDM A,DWDS ;APPROX TO WDS TO DISPLAY + IDIVI A,1000. + SOS A ;QUOTIENT MAY BE ZERO + MOVEM A,DISDIE + MOVNI A,EWRT + ADDM A,DWDS + ADDI E,2 ;OFFSET FOR POINTER PAGES + MOVEI A,0 +SRCY2E: CAME C,A340P1(E) ;PG SET TO RIGHT ADR? + JRST SRCY2J ;NO SET UP +SRCY2K: ADDI C,2000 + AOS E + SOJG J,SRCY2E ;SET UP ALL PGS IN BLOCK + CONSZ DIS,5400 + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCYCX + +SRCY2J: JSP B,DDFTC + MOVEI B,-2(E) + MOVEM B,340DP + JRST SRCY2K + +SRCY2B: JRST DISLOS ;TEMP + +SRCY2F: MOVE D,J ;FIRST PAGE MATCHES, DO ENOUGH ADDITIONAL PAGES MATCH? + SOJLE D,SRCY2C ;ONLY ONE PAGE NEEDED. WINS + MOVEI TT,2000(C) + MOVEI R,1(E) +SRCY2H: CAME TT,340DA(R) + JRST SRCY2G ;NOT SET UP FOR WHOLE BLOCK + ADDI TT,2000 + AOS R + SOJG D,SRCY2H + JRST SRCY2C ;SET UP FOR WHOLE BLOCK. WIN + +SRCY2G: HRRZ R,E ;SAVE BEST SO FAR + JRST SRCY2I + DPFTCH: HRRZ C,A + CAIGE C,20 + JRST DISLOS + TRZ C,1777 + MOVSI E,-N340PB-2 +DPFTC2: CAME C,A340P1(E) ;PG SET UP TO RIGHT ADR? + JRST DPFTC1 ;NO + TRZ A,776000 ;YES RETCH REL ADR + XCTRI [MOVE A,@DPAP(E)] + JRST (B) ;NO FAULT + JRST 4,. ;SHOULD HAVE BEEN VERIFIED WHEN LOADED + +DPFTC1: AOBJN E,DPFTC2 ;LOOP ON ALL EXEC PNTR PAGES + MOVE E,340PP ;NONE SET UP SO SELECT ONE TO SET UP + AOS D,340PP ;INCR IT FOR NEXT TIME + CAILE D,1 + CLEARM 340PP ;RESET +DDFTC: SPM DPBS ;ENTRY FOR DATA PGS STORE MAP + SKIPGE U,DISUSR + JRST 4,. + SKIPL CIRPSW + JRST DDFTC2 ;MAP MIGHT CHANGE + SKIPGE A340P1(E) + JRST DDFTC3 + SETOM A340P1(E) ;WIPE OUT OLD ENTRY + LDB W,DPEP(E) ;PICK UP OLD PAGE + TRZN W,600000 ;NO ACCESS + JRST 4,. + ANDI W,PMRCM + CAIL W,TSYSM + JRST 4,. + MOVEI R,0 + DPB R,DPEP(E) + SKIPGE DDEXCF+340P1(E) + JRST DDFTC3 + LDB R,[MUR,,MEMBLT(W)] + CAIE R,MURUSR + JRST 4,. + MOVSI R,-1 + ADDM R,MMSWP(W) ;REDUCE COUNT OF EXEC REFS +DDFTC3: MOVE W,C ;SET PAGE IN E TO PNT TO ADR IN C + LSH W,-10. ;GET USR PG # + ROT W,-1 ;GET WD # AND SAVE WHICH HALF IN SIGN + ADDI W,UPGMP(U) + HLRZ R,(W) + SKIPGE W + HRRZ R,(W) ;PICKS UP PAGE ENTRY + HLRZ T,UPGCP-UPGMP(W) + SKIPGE W + HRRZ T,UPGCP-UPGMP(W) + TRNN R,600000 + JRST DDFTC1 ;NO ACCESS OR SWAPPED OUT + LDB Q,[PMRCAD,,R] + CAIN T,-1 + JRST DDFTC4 ;ABS PG + CAILE Q,TSYSM + JRST 4,. + SKIPGE MEMBLT(Q) + JRST DDFTC2 ;CAN'T SET UP EXEC PG POINTING TO THIS ONE + LDB TT,[MUR,,MEMBLT(Q)] + CAIE TT,MURUSR + JRST 4,. + CLEARM DDEXCF+340P1(E) + MOVSI TT,1 + ADDM TT,MMSWP(Q) ;AOS COUNT OF EXEC PGS +DDFTC5: MOVEM C,A340P1(E) + DPB R,DPEP(E) ;STORE USERS PG ENTRY IN EXEC MAP + LPMR DPBS ;RESET ASSOC REG + ANDI A,1777 ;FLUSH USER ADR EXCEPT WD IN PAGE + XCTRI [MOVE A,@DPAP(E)] ;REF PAGE TO MAKE SURE ITS THERE, ETC + JRST (B) + JRST 4,. + +DDFTC4: SETOM DDEXCF+340P1(E) ;INDICATE PAGE POINTING TO ABS PAGE + JRST DDFTC5 + +DDFTC1: JUMPE R,DISLOS ;MAP COMPLETELY 0 MUST BE ILM + JUMPE T,DISLOS ;ILM + MOVEM U,DISSWI + LDB W,[121000,,C] + MOVEM W,DISSPG ;RQ PG IN +DDFTC2: MOVNI A,3 ;HANG FOR 3 60THS + JRST DISF2A + +SRCY1A: JUMPGE A,SRCY1B + MOVEI A,-1(A) +SRCY1D: JSP B,DPFTCH + SOJA A,SRCY1C + +SRCY1B: TLNN A,777000 + JRST SRCY5 + HLRZ A,LDISP + JRST SRCY1D + +SRCY3: SOSGE DTIME + JRST DISF ;LIMIT REPETITION RATE + SKIPL NDSFMS ;SKIP ON FRAME HACK NOT ACTIVE + JSP B,ENDFM1 ;MAYBE STOP DISPLAY AFTER SPEC # OF FRAMES + MOVE A,IDBLKP + MOVEM A,DBLKOP + CONO DIS,100\SDCHN_3\DISCHN + SETOM DISDIE + JRST SRCYCX + +SRCY4: CONO DIS,200\SDCHN_3\DISCHN ;EDGE GRONK DIS AND KEEP GOING + JRST SRCYCX + +DISF2: MOVNI A,300. +DISF2A: MOVEM A,DTIME + SETOM DISON + JRST DISF3 + +DISF: SETOM DISON +DISF1: MOVEI A,1 + MOVEM A,DTIME +DISF3: CONO DIS,100 +DISF4: MOVEI A,DIS300-1 + MOVEM A,DBLKOP +SRCYCX: MOVE A,[JSR DBLKPB] +SRCYB1: MOVEM A,40+2*DISCHN +SRCYB2: JRST LPTRT1 + +DIS300: 3000 + 3000 + +DCRSTP: SKIPE 340MD ;STOP DISPLAY FOR CORE SHUFFLING + POPJ P, ;BUFFER NOT IN USER CORE SO NO ACTION +DCRST1: SETOM CDISOF + CONO DIS,0 + POPJ P, + +DCRRST: SKIPE 340MD ;DISPLAY RESTART + POPJ P, + SKIPL DISOFF + CONO DIS,SDCHN_3+DISCHN + CLEARM CDISOF + POPJ P, + +DSLTPB: DATAI DIS,LLTPSN + AOS LTPCNT + HRRZ A,LLTPSN + ADDM A,LTPCY + HLRZ A,LLTPSN + ADDM A,LTPCX + SKIPGE B,DISUSR + JRST 4,. + MOVEI A,%PILTP + AND A,MSKST(B) + IORM A,PIRQC(B) + CONO DIS,@LTPDCN + JRST SRCYCX + +EBLK + +DBLKP1: 0 +DBLKPB: 0 + +BBLK + MOVEM A,DBLKP1 + MOVE A,[BLKO DIS,DBLKOP] + MOVEM A,40+2*DISCHN + MOVE A,DBLKP1 + JRST 12,@DBLKPB + +SRCYRB: CONI DIS,A + SKIPGE A + CONO DIS,100 ;WOULD ASSIGN IF IDLE + MOVE A,[JSR DIGNOR] + JRST SRCYB1 + +EBLK + +DIGNOR: 0 + +BBLK + CONO DIS,0 + DATAO DSDEV,[DSNDIS] + JRST 12,@DIGNOR + +ENDLIS: SETOM DISDIE + MOVE A,DROOT + MOVEM A,LDISP + SOSGE DTIME + JRST DISF ;LIMIT REPETION RATE + SKIPL NDSFMS + JSP B,ENDFM1 ;HACK FRAME HACK + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCY1 + +ENDFM1: SKIPE NDSFMS ;STOP DISPLAY IF SPEC # OF FRAMES UP ELSE RETURN + SOSGE NDSFMS + JRST ENDFM2 ;STOP WORLD + JRST (B) + +ENDFM2: SETOM DISOFF + JRST DISF1 + +SRCY5: MOVNI A,EWRT/2 + ADDB A,DWDS + JUMPGE A,SRCY1 + JRST DISF2 + +DISLOS: SKIPE 340MD + JRST 4,. + SKIPGE A,DISUSR + JRST 4,DISF2A + MOVEI B,%PIDIS + IORM B,PIRQC(A) + MOVSI A,(SETZ) + JRST DISF2A ;DIE FOR A LONG TIME + +SRCY2A: SOSGE DTIME + JRST DISF + SKIPL NDSFMS + JSP B,ENDFM1 + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCY1C + + +SUBTTL 340 DISPLAY - .DSTART, .DSTRTL + +DISACR: CAME U,DISUSR + POPJ P, + SKIPE 340MD ;COME HERE IF PAGE BEING FLUSHED + EXEC PAGE POINTING TO IT + JRST 4,. ;SHOULD NOT BE SET UP TO USER PAGE + CONO PI,UTCOFF + SETOM A340P1-340P1(T) + SKIPGE DDEXCF(T) + JRST DISAC1 + ADDB J,MMSWP(TT) + SKIPGE J + JRST 4,. +DISAC1: SKIPGE DISOFF + JRST POPJ1 + PUSH P,T + PUSHJ P,DISZAP + POP P,T + JRST POPJ1 + +;ROUTINES TO START 340 DISPLAY WITH DIS BUFF IN USERS CORE +ADSTART: TDZA E,E ;CALL 10, +ADSTL: MOVNI E,1 ;CALL 12, + MOVEI A,0 + PUSHJ P,ADSDV + POPJ P, + SETOM DISOFF + CONO DIS,0 + CLEARM 340MD + MOVEM E,LMODE + HRRZ C,40 + MOVEM C,DROOT + MOVEM C,LDISP + SETZM DISOFF + PUSHJ P,DISZAP + JRST CLKOJ1 + +ANDIS: CAME U,DISUSR + POPJ P, + UMOVE A,(J) + JUMPL A,ANDIT1 ;WAIT FOR COMPLETION OF LAST NDIS + JUMPE A,ANDIT2 ;RETURN COUNT LEFT FROM LAST NDIS + MOVEM A,NDSFMS ;DISPLAY N TIMES AND THEN STOP + SKIPL DISOFF + JRST POPJ1 + SETOM DISDIE + CLEARM DISOFF + PUSHJ P,DISZAP + JRST POPJ1 + +ANDIT1: SKIPL DISOFF + PUSHJ P,UFLS + POPJ P, + +ANDIT2: MOVE A,NDSFMS + JRST APTUAJ + +SUBTTL 340 DISPLAY - .DSTOP, .DCLOSE, .LTPEN +ADSTOP: CAMN U,DISUSR ;OPER 16 + SKIPGE DISOFF + POPJ P, +ADCLB: PUSH P,B + PUSH P,C + MOVSI C,-1 + SETOM DISOFF + SETZM DBLINK + CONO DIS,0 + MOVEI A,1 + MOVEM A,DTIME + SETZM DISON + SETOM DISDIE + CONO PI,UTCOFF + MOVSI A,-N340CL +ADCLB1: SETOM A340P1(A) + LDB B,DPEP(A) + ANDI B,600000+PMRCM + SKIPGE DDEXCF+340P1(A) + JRST ADCLB2 ;POINTING TO EXEC PG + TRZE B,600000 + ADDM C,MMSWP(B) +ADCLB2: AOBJN A,ADCLB1 + CLEARM 340PP + CLEARM 340DP + CLEARM EXEUMP+.340P1 + REPEAT N340PB/2,CLEARM EXEUMP+.DPG0+.RPCNT + MOVE A,[JSR DIGNOR] + MOVEM A,40+2*DISCHN + CONO PI,UTCON + POP P,C + JRST POPBJ + +ADCL1: SOSE DISNTO + POPJ P, + JRST AIDS7 + +ADCLOSE: CAME U,DISUSR ;OPER 15 + POPJ P, + SKIPLE 340MD + JRST AIDS8 +AIDS7: PUSHJ P,ADCLB + PUSHJ P,ADCL2 + JFCL +AIDS9: SETOM 340MD + SETOM DISUSR + DATAO DSDEV,[DSNDIS] ;DEASSIGN DIS + POPJ P, + +AIDS8: MOVE A,U ;FLUSH CHNLS IN CASE OF .DCLOSE FROM DIS OR IDS + PUSHJ P,CHSCAA + PUSHJ P,ADSDV4 + JRST AIDS7 + +ALTPEN: MOVE C,B + CAME U,DISUSR ;CALL 14, + JRST ALTPP2 + XCTR XR,[SKIPL A,(C)] + JRST ALTPP1 + TLNN A,377777 + JRST .+3 + SKIPN LTPCNT + PUSHJ P,UFLS +ALTPP1: CONO PI,LPTOFF ;INHIBITS LPEN BREAKS + MOVE A,LDISP + XCTRI XW,[MOVEM A,4(C)] + SKIPA A,DBLKOP + JRST ALTPPL + TRZ A,400000 + LDB B,[121000,,A] + LDB B,[121000,,A340P1-340P1(B)] + DPB B,[121000,,A] + XCTRI XW,[MOVEM A,5(C)] + SKIPA B,C + JRST ALTPPL + HRLI B,LLTPSN + XCTRI XBW,[BLT B,3(C)] + JRST .+2 + JRST ALTPPL + SETZB A,LTPCNT + MOVEM A,LTPCY + MOVEM A,LTPCX + JRST LPTONJ + +ALTPP2: XCTR XW,[SETZM (C)] + XCTR XW,[SETZM 1(C)] + POPJ P, + +ALTPPL: CONO PI,LPTON + PUSHJ P,TPFLT + JRST ALTPEN + +SUBTTL 340 DISPLAY + +ADSDV: ;A HAS NEW 340MD + CONO PI,CLKOFF + CONI DIS,T ;DIS AVAILABLE + JUMPN T,ADSDV1 ;YES + CONO DIS,0 + CONI DIS,T + JUMPE T,ADSDVN ;DIS NOT AVAIABLE +ADSDV1: SKIPL T,DISUSR + CAMN U,DISUSR + JRST ADSDVY ;YES + CAME U,UMASTER + JRST ADSDVM ;MAYBE +ADSDV2: SKIPGE A,DISUSR ;TAKE AWAY DISPLAY + JRST ADSDV3 + PUSHJ P,RPCCK +ADSDV7: SKIPL DISUSR + SKIPG 340MD + JRST ADSDV3 + PUSH P,R + PUSHJ P,CHSCAA ;CHANGE 340 CHANNELS TO NUL DEV + PUSHJ P,ADSDV4 + POP P,R + SETZM DISNTO +ADSDV3: MOVE A,340MD +ADSDVY: SETZM DBLINK + SETOM NDSFMS ;TURN OFF FRAMER HACK + CAME A,340MD + JUMPE A,ADSDV5 ;SAME USER CLOBBERING HIS IDS OR DIS +ADSDV6: PUSHJ P,ADCLB + MOVEM U,DISUSR +ADCL2: SKIPGE A,340BF + JRST CLKOJ1 + LSH A,-10. + PUSHJ P,MEMR + SETOM 340BF + JRST CLKOJ1 + +ADSDV4: HRRZ Q,(R) + CAIG Q,DN340L + CAIGE Q,DN340B + POPJ P, ;NOT A 340 CH + CAIL Q,DN340C + SKIPA T,[NLODN] ;UNIT MODE + MOVEI T,NLBDN ;BLOCK MODE + SOS DISNTO + HRRM T,(R) + POPJ P, + +ADSDV5: SKIPGE 340MD + JRST ADSDV6 + MOVE A,DISUSR + JRST ADSDV7 + +ADSDVM: CAMN T,UMASTER + JRST ADSDVN ;CURRENT USER UMASTER + MOVE T,UTMPTR(U) + MOVE T,TTYTYP-USRRCE(T) ;GET BITS FOR NEW GUY IN LH OF T + HRR T,DISUSR + HRR T,UTMPTR(T) + HLR T,TTYTYP-USRRCE(T) + TRNE T,%TT3HP + JRST ADSEQ1 ;CURRENT USER HAS HIGH PRIORITY + TRNE T,%TT340 + JRST ADSEQ2 ;CURRENT USER NEAR 340 + TLNN T,%TT340+%TT3HP ;GIVE TO NEW GUY IF HE IS EITHER + JRST ADSEQ +ADSWIN: JRST ADSDV2 + +ADSEQ1: TLNN T,%TT3HP + JRST ADSDVN ;NO +ADSEQ: SKIPL TTYTBL(U) ;MAYBE + JRST ADSWIN +ADSDVN: JRST CLKONJ + +ADSEQ2: TLNE T,%TT3HP + JRST ADSWIN + TLNN T,%TT340 + JRST ADSDVN + JRST ADSEQ + +SUBTTL 340 DISPLAY AS ASCII DEVICE + +DISO: PUSHJ P,AIDS1 + JRST OPNL10 ;NOT AVAILABLE + AOS DISNTO + SETOM 340DMD + LDB B,[20200,,D] + AOS B + LSH B,4 + MOVEM B,CSCALE + LDB TT,[40200,,CSCALE] + MOVNS TT + MOVEI T,170. + LSH T,(TT) + TRZ T,7 + MOVEM T,DISCHS ;CHARS THAT WILL FIT THIS SIZE + MOVEI T,88. + LSH T,(TT) + MOVEM T,DISLNL ;LINES THAT WILL FIT + PUSHJ P,DSIZAP + MOVSI T,-1777 + HRR T,340BF + SOS T + MOVEM T,IDBLKP + SETZM DISOFF + PUSHJ P,DISZAP + SETOM 340T + JSP Q,OPSLD3 + DN340C,,DN340B + DN340H,,DN340W + +340FF: SKIPL 340T + JRST 340FF1 + MOVE A,TIME + MOVEM A,340T +340FF1: MOVE T,340T + ADDI T,30.*3 + CAML T,TIME + PUSHJ P,UFLS + SETOM 340T + PUSHJ P,ADCLB + PUSHJ P,DSIZAP + JRST DISZAP + +DSIZAP: SETZM DBLOAT + SETZM 340XMD + SETZM DBLINK + MOVE T,340BF + MOVEI A,34117 + IOR A,CSCALE + MOVEM A,(T) + PUSH T,[221700060000] + HRLI T,0600 + MOVEM T,340BFP + MOVE A,[403737403737] + MOVEI B,1(T) + HRLS B + AOS B + MOVEM A,1(T) + BLT B,1775(T) + MOVE A,DISLNL + MOVEM A,DISLNS + MOVE A,DISCHS + MOVNM A,DISCHC + MOVEI T,(HRRZ I,(A)) + HRLM T,AIDC1 + POPJ P, + + +340B: MOVEI E,340D + JRST NBTOCH + +340C: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +340D: CAIN A,^C + POPJ P, + CAIN A,^L + JRST 340FF + CAIN A,^T + JRST DSIZAP + SKIPE DISLNS + SKIPGE DBLOAT + POPJ P, + CAIN A,^B + JRST BLNKON + CAIN A,^E + JRST BLNKOF + SKIPE 340XMD + PUSHJ P,340D1 ;ENTER CHR MOD INF NOT ALREADY +340E: EBLK +AIDC1: HRRZ\HLRZ I,DISTBL(A) + BBLK + TRNN I,-100 + JRST 340FC ;NORMAL CHR + TRNN I,-200 + JRST 340K ;FAKE OUT 340 NON-SPACING CHRS + PUSHJ P,(I) ;ROUTINE DISPATCH (MAY SKIP OR SKIP TWICE) + JRST 340E ;WRONG CASE OR SOMETHING, TRY AGAIN +340F: IDPB I,340BFP +340F2: MOVE J,340BFP + ANDI J,1777 + CAIL J,1776 + SETOM DBLOAT + POPJ P, + +340FC1: SKIPL DISCHC ;DISPLAY IF COUNT NOT OUT BUT DONT INCR COUNT +340FC: AOSG DISCHC ;INCR COUNT + DISPLAY IF NOT OUT + JRST 340F + JRST 340F2 + +340HD1: SKIPN 340XMD ;ESCAPE TO PARAM MODE + PUSHJ P,340H1 +340D1: MOVEI I,74117 ;PARAM WD + IOR I,CSCALE + PUSHJ P,340F ;STORE PARAM WD + MOVEI I,6 + DPB I,[300600,,340BFP] ;SWITCH TO CHR MODE + SETZM 340XMD + POPJ P, + +340K: MOVEI I,40 ;SPACE TO MAKE SPACING + PUSHJ P,340FC1 + XCT AIDC1 ;GET NON-SPACING LETTER AND DISPLAY + JRST 340FC + +340W: JSP Q,WRDBT + XCTR XRW,[MOVSS (C)] + PUSHJ P,340H + XCTR XRW,[MOVSS (C)] +340H: SKIPGE DBLOAT + POPJ P, + SKIPN 340XMD + PUSHJ P,340H1 ;ENTER HALF WD MODE IF NOT ALREADY + UMOVE I,(C) ;PICK UP LOSERS HALF WD + JRST 340F + +340H1: MOVEI I,37 ;IN CHR MODE, EXCAPE + PUSHJ P,340F + LDB I,[360600,,340BFP] + JUMPE I,340H2 + CAIE I,22 + JRST 340H1 +340H2: MOVEI A,22 + DPB A,[300600,,340BFP] + SETOM 340XMD + POPJ P, + +BLNKON: MOVE A,DBLINK + CAIL A,DBLNKN + POPJ P, + PUSHJ P,340HD1 + MOVE B,340BFP + AND B,[770060,,1777] ;ADR OF PARAM WD TO BLINK INTEN OF + TLO B,300+B + MOVE A,DBLINK + MOVEM B,DBLNKB(A) + AOS DBLINK + MOVEI T,15. + PUSHJ P,CLQADD + BLINKB + JRST 340F2 + +BLNKOF: PUSHJ P,340HD1 + JRST 340F2 + +BLNKBR: SKIPN A,DBLINK + JRST CLQRET ;BLINKING TURNED OFF + SKIPL B,340BF + SKIPGE CDISOFF + JRST BLNKB3 + MOVE C,DBLNKF +BLNKB2: DPB C,DBLNKB-1(A) + SOJG A,BLNKB2 + SETCMM DBLNKF ;COMPLEMENT FLAG +BLNKB3: MOVEI T,15. ;1/4 SEC + MOVEI C,BLINKB + JRST CLQREE + +SUBTTL 340 DISPLAY + +AIDS1: MOVEI A,2 + PUSHJ P,ADSDV ;DETERMINE IF THIS LOSER SHOULD GET DISPLAY + POPJ P, +AIDS3: PUSHJ P,TCALL + JRST IOMQ + JRST AIDS2 ;NO MEM AVAIL + MOVEI B,MUDISB + MOVE T,A + LSH T,10. + MOVEM T,340BF + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,2 + MOVEM B,340MD + JRST POPJ1 + +AIDS2: SKIPG MEMFR + JRST AIDS9 + PUSHJ P,LOSSET + AIDS9 + PUSHJ P,UDELAY + PUSHJ P,LSWDEL + JRST AIDS3 + +IFN 0,[ +;INTERPRETIVE DISPLAY COMPILER + +IDISO: PUSHJ P,AIDS1 + JRST OPNL10 ;NOT AVAIL + AOS DISNTO + SETZM 340DMD + SETOM AISWS + HRLI T,442200 + MOVEM T,340BFP + MOVEI Q,10135 ;TURN OFF LP SCALE 1 INT 5 + IDPB Q,340BFP + MOVEI T,1_4 + MOVEM T,CSCALE + MOVEM T,VSCALE + MOVEM T,ISCALE + MOVSI A,(MOVE) ;DONT HACK CHR'S PER LINE + MOVEM A,DISCHS + MOVNM A,DISCHC + CONO DIS,500 + MOVEI A,DN340I + JRST OPNSLT + + +340I: MOVEM C,AIDPCP + UMOVE C,(C) + +AIDL: UMOVE R,(C) +AIDL2: TRNE R,1 + JRST AIDL1 ;NOT CHR MODE + MOVEI Q,(HRRZ I,(A)) + HRLM Q,AIDC1 + MOVE Q,CSCALE + IORI Q,60100 + PUSHJ P,AIDPY + MOVE J,[220600,,Q] +AIDCL: MOVE B,[440700,,R] +AIDC3: ILDB A,B +EBLK +AIDC1: HRRZ\HLRZ I,DISTBL(A) +BBLK + TRNN I,-100 + JRST AIDC5 + TRNN I,-200 + JRST AIDC7 + PUSHJ P,(I) + JRST AIDC1 +AIDC5: IDPB I,J + TLNN J,770000 + PUSHJ P,AIDC2 + TLNE B,760000 + JRST AIDC3 + AOS C + UMOVE R,(C) + MOVE I,UEXIT + CAMN I,[JRST ONEFLS] + JRST AIDC6 + TRNN R,1 + JRST AIDCL +AIDC6: MOVEI I,37 + IDPB I,J + TLNE J,770000 + JRST .-2 + PUSHJ P,AIDC2 + +AIDL1: MOVE B,UEXIT + CAMN B,[JRST ONEFLS] + JRST AIDI + LDB B,[30300,,R] + AOJA C,@AIDTB(B) + +AIDC7: MOVEI I,40 + PUSHJ P,AIDC4 + XCT AIDC1 + JRST AIDC5 + +AIDI: MOVE R,AIDPCP + UMOVEM C,(R) + SOS UUOH + JRST UUOE1 + +AIDTB: AIER1 + AIPT + AIVC + AIINC + AIOP + AIVC + REPEAT 2,AIER1 + +AIPT: LDB I,[251600,,R] ;PICK UP Y + SUB I,DWDB + MOVEI TT,220000 + DPB I,[1200,,TT] + LSH I,-10. + ANDI I,17 + MOVEM I,YFLD + LDB I,[61600,,R] ;X + SUB I,DWDL + MOVEI E,0 + TRNE R,2 + TRO E,2000 ;INTENSIFY + DPB I,[1200,,E] + LSH I,-10. + ANDI I,17 + MOVEM I,XFLD + MOVEI Q,20000 + PUSHJ P,AIDPY + MOVE Q,TT + PUSHJ P,AIDPY + MOVE Q,E + PUSHJ P,AIDPY + JRST AIDL + +AIDC4C: SKIPL DISCHC + POPJ P, + JRST AIDC4 +] +AIDC4B: AOSLE DISCHC + POPJ P, +AIDC4: +IFN 0,[ + SKIPGE 340DMD + JRST AIDC4A ;DIS + IDPB I,J + TLNE J,770000 + POPJ P, +AIDC2: PUSHJ P,AIDPY + MOVEI Q,0 + MOVE J,[220600,,Q] + POPJ P, +] +AIDC4A: IDPB I,340BFP + POPJ P, +IFN 0,[ +AIDPY: HRLS Q + DATAI DIS,AIDPIC + DATAO DIS,Q +AIDP1: MOVEI H,50 +AIDP1A: CONSZ DIS,DVEF+DHEF ;EDGE FLAGS + JRST DEGFS + CONSO DIS,200 + SOJG H,AIDP1A + JUMPE H,AIER2 + CONSZ DIS,DVEF+DHEF + JRST DEGFS + SKIPN XFLD + SKIPE YFLD + JRST AIDP2 +DEG4B: HRRZ H,340BFP + SUB H,340BF + CAIL H,1777 + JRST AIER3 + IDPB Q,340BFP +AIDP2: MOVEI Q,0 + POPJ P, + +DEGFS: DATAI DIS,DEGVCC + CONI DIS,H + LSH H,-15. + ANDI H,7 + CAIN H,4 ;VECTOR + JRST DEGVC + SKIPN XFLD + SKIPE YFLD + JRST DEG5A + MOVEI Q,400000 + CAIN H,3 + MOVEI Q,373737 + PUSH P,H + PUSHJ P,DEG4B ;LEAVING INSERT APPROPRIATE ESCAPE INSTEAD + POP P,H +DEG5A: CONO DIS,200 + MOVEI TT,50. + CONSO DIS,DVEF+DHEF+200 + SOJG TT,.-1 + JUMPE TT,AIER2 + CONSO DIS,200 + JRST DEG5A ;RIDE OUT TO FINAL EDGE + DATAI DIS,TT + XOR TT,AIDPIC + TRNN TT,1000 + JRST DEG5B + HRR TT,AIDPIC + TRNE TT,1000 + AOS XFLD + TRNN TT,1000 + SOS XFLD +DEG5B: TLNN TT,1000 + JRST DEG4 + HLL TT,AIDPIC + TLNN TT,1000 + SOS YFLD + TLNE TT,1000 + AOS YFLD + JRST DEG4 + +DEG5: MOVE TT,DEGVCC + CONSZ DIS,DVEF + JRST DEG1 +DEG3: CONSO DIS,DHEF + JRST DEG4 + TRNE TT,1000 + SOS XFLD + TRNN TT,1000 + AOS XFLD +DEG4: MOVEI TT,0 + DPB TT,[44000,,XFLD] + DPB TT,[44000,,YFLD] + CONSO DIS,200 + CONO DIS,200 ;CONTINUE + MOVEI TT,100. + CONSO DIS,200+DVEF+DHEF + SOJG TT,.-1 + JUMPE TT,AIER2 + SKIPN XFLD + SKIPE YFLD + JRST AIDP1 ;NOT COMING ON +DEG4F: DATAI DIS,TT + CAIN H,4 + MOVE TT,DEGVCC + PUSH P,Q ;COMING ON PRODUCE SETPOINT + PUSH P,H + MOVEI Q,20100 + IOR Q,@DEGSCT(H) + PUSHJ P,DEG4B + HLRZ Q,TT + IORI Q,220000 + PUSHJ P,DEG4B + HRRZ Q,TT + CONI DIS,H + LSH H,-15. + DPB H,[150300,,Q] + MOVE TT,(P) + CAIN TT,4 + JRST DEGVC1 +DEG4D: SUB P,[2,,2] + JRST AIDP1 + +DEGSCT: [0] + [0] + [0] + CSCALE + VSCALE + VSCALE + ISCALE + [0] + +DEG1: TLNE TT,1000 + SOS YFLD + TLNN TT,1000 + AOS YFLD + JRST DEG3 + +DEGVC: SETOM DEGVCF + SKIPN XFLD + SKIPE YFLD + JRST DEG5 ;NOT GOING OFF + CLEARM DEGVCF + HRRZ A,AIDPIC + HLRZ B,AIDPIC + PUSHJ P,DEG4C + CONSZ DIS,DVEF + SUBI B,2 + CONSZ DIS,DHEF + SUBI A,2 + SKIPGE A + MOVEI A,0 + SKIPGE B + MOVEI B,0 + DPB B,[100700,,Q] + DPB A,[700,,Q] + TRO Q,400000 + PUSHJ P,DEG4B + JRST DEG5 + +DEGVC1: SKIPN XFLD + SKIPE YFLD + SKIPLE DEGVCF + JRST .+2 + JRST DEG4D ;VECTOR TOTALLY OUT OF IT + IORI Q,100000 + PUSHJ P,DEG4B + POP P,H + POP P,Q + DATAI DIS,A + HLRZ B,A + HRRZS A + PUSHJ P,DEG4C + DPB B,[100700,,Q] + DPB A,[700,,Q] + MOVE A,DEGVCC + MOVEM A,AIDPIC + JRST AIDP1 + +DEG4C: HRRZ I,DEGVCC + SUB A,I + HLRZ I,DEGVCC + SUB B,I + MOVMS A + MOVMS B + CAIGE A,1000 + JRST .+3 + MOVNS A + ADDI A,2000 + CAIGE B,1000 + JRST .+3 + MOVNS B + ADDI B,2000 + LDB I,[40200,,VSCALE] + MOVNS I + ASH A,(I) ;GET X INC IN A + ASH B,(I) ;Y IN B + POPJ P, + +AIINC: MOVE Q,ISCALE + IORI Q,140100 + PUSHJ P,AIDPY + SETOM DDINCI + MOVEI Q,0 + MOVE B,[200400,,Q] +AIIN1: MOVE D,[440600,,R] +AIIN8: ILDB T,D + LDB E,[200,,T] ;LOAD COUNT + JUMPE E,AIIN5 ;NULL INCREMENT +AIIN7: TRNN T,4 ;SKIP ON INTENSIFY + JRST AIIN2 + SKIPG DDINCI ;SKIP ON SET TO INTENSIFY + JRST AIIN3 + +AIIN7A: LDB H,[30300,,T] + MOVE H,DINCT(H) + IDPB H,B + PUSHJ P,AIIN6 ;MAYBE START NEW WORD + SOJG E,AIIN7 + +AIIN5: TLNE D,700000 + JRST AIIN8 + UMOVE R,(C) + LDB H,[30300,,R] + TRNE R,1 + CAIE H,3 ;INC MODE + TROA Q,400000 + AOJA C,AIIN1 + PUSHJ P,AIIN6A + JRST AIDL2 + +AIIN6: TLNE B,770000 + POPJ P, + +AIIN6A: PUSHJ P,AIDPY + MOVEI Q,0 + SETOM DDINCI + MOVE B,[200400,,Q] + POPJ P, + +AIIN2: SKIPN DDINCI + JRST AIIN7A ;INTENSITY AGREES +AIIN3: SKIPL DDINCI + PUSHJ P,AIIN6A + HRRZM P,DDINCI + TRNE T,4 + TROA Q,200000 + CLEARM DDINCI + JRST AIIN7 + +AIVC: MOVE Q,VSCALE + IORI Q,100100 + LDB A,[251700,,R] ;DY + LDB B,[61700,,R] ;DX + TRNE A,40000 + ORCMI A,77777 + TRNE B,40000 + ORCMI B,77777 + MOVM E,A + MOVM TT,B + MOVE H,VSCALE + LSH H,-4 + ANDI H,3 + MOVNS H + LSH E,(H) + LSH TT,(H) + JUMPN E,.+2 + JUMPE TT,AIDL + PUSHJ P,AIDPY +AIVCL: MOVE H,E + MOVE J,TT +AIVC3: CAIG J,177 + CAILE H,177 + JRST AIVC2 + SUB E,H + DPB H,[100700,,Q] + SKIPGE A + TRO Q,1_<8+7> + SUB TT,J + DPB J,[700,,Q] + SKIPGE B + TRO Q,1_7 + TRNE R,1_1 + TRO Q,200000 + JUMPN E,.+3 + JUMPN TT,.+2 + TRO Q,400000 + PUSH P,A + PUSH P,B + PUSH P,E + PUSH P,TT + PUSHJ P,AIDPY + POP P,TT + POP P,E + POP P,B + POP P,A + JUMPN E,AIVCL + JUMPN TT,AIVCL + JRST AIDL + +AIVC2: LSH J,-1 + LSH H,-1 + JRST AIVC3 + +AIOP: LDB B,[60300,,R] + JRST @AIOPT(B) + +AIOPT: AIER5 + AIPSJ + AIPPJ + AIJMP + AIPSH + AIIPOP ;5 + AIPS + AIER5 + AIER5 + +AIPSJ: XCTR XRW,[AOS D,43] ;PICK UP PDL PNTR AND INCR + XCTR XRW,[MOVEM C,(D)] ;STORE RETURN PC +AIJMP: HLRZ C,R + JRST AIDL + +AIPPJ: UMOVE D,43 + XCTR XRW,[HRRZ C,(D)] + JUMPE C,AIEXT ;POPJ INTO 0 START SIGNAL + XCTR XRW,[SOS 43] + JRST AIDL + +AIEXT: SKIPL AISWS + JRST AIDST3 +AIDST: MOVEI Q,3000 + PUSHJ P,DEG4B + MOVE A,340BF + ADD A,[-2000-1,,-1] + MOVEM A,IDBLKP + MOVEM A,DBLKOP + MOVEI A,1 + MOVEM A,DTIME + SETZM DISOFF + CONO DIS,1100\DISCHN\SDCHN_3 +AIDST3: POPJ P, + +AIPSH: HLRZ TT,R + UMOVE TT,(TT) + XCTR XRW,[AOS D,43] + UMOVEM TT,(D) + JRST AIDL + +AIIPOP: HLRZ TT,R + XCTR XRW,[SOS D,43] + UMOVE E,1(D) + UMOVEM E,(TT) + JRST AIDL + +AIPS: LDB A,[140600,,R] + HLRZ B,R + CAIL A,AIMXP + JRST AIER7 + ANDI B,3 + LSH B,4 + XCT AIPST(A) + JRST AIDL + +AIPST: JRST AIER7 + HLLEM R,AISWS ;START MODE + MOVEM B,CSCALE + MOVEM B,ISCALE + MOVEM B,VSCALE + JRST AIPSA + HLRM R,DWDL + HLRM R,DWDB +AIMXP==.-AIPST + +AIPSA: MOVEM B,CSCALE + MOVEM B,ISCALE + MOVEM B,VSCALE + JRST AIDL +] +EBLK +XFLD: 0 ;HIGH ORDER BITS OF X COOR REG (LIGHT=0) +YFLD: 0 ; ... Y +CDISOF: 0 ;DISPLAY OFF IN CORE ALLOC +340BF: -1 ;POINTER TO 1K BLOCK FOR 340 BF (MEM ADR) +340BFP: 0 ;POINTER TO 340BF + DBLNKN==10. +DBLINK: 0 ;0=IDLE ;+N=NUM OF ENTRIES +DBLNKF: 0 ;BLINK FLAG, -1 MEANS START BLINK OFF +DBLNKB: BLOCK DBLNKN ;BYTE POINTER TO PARAMETER HW TO CHANGE +BLINKB: 0 ;CLOCK QUEUE BLOCK + -1 + JRST BLNKBR +AIDPCP: 0 ;USER LOCN WHERE TO STORE BACK PC IF NECC +CSCALE: 0 ;SCALE FOR CHR WRDS +ISCALE: 0 ;SCALE FOR INCREMENT +VSCALE: 0 ;SCALE FOR VECTOR WDS +DWDL: 0 ;14 BIT COOR OF LH 340 +DWDB: 0 ;14 BIT COOD OF BOT 340 +DEGVCF: 0 ;EDGE FLAG FOR VECT -1 UNLESS GOING AWAY +DEGVCC: 0 ;COORD AT EDGE +DDINCI: 0 ;-1 CURRENT INTENSITY NOT COMMITED (IN INCREMENT MODE) + ;+ => 1 - => 0 +AISWS: 0 ;SELECT DISPLAY START MODE -1 STARTS DISPLAY AFTER IOT +AIDPIC: 0 ;COORDINATES AT START OF AIDPY + +LLTPSN: 0 ;. TO .+3 BLTED TO USER +LTPCNT: 0 +LTPCY: 0 +LTPCX: 0 +LTPDCN: 200\SDCHN_3\DISCHN + +LDISP: 0 ;DISPLAY LINK POINTER +LMODE: 0 ;LISP LINK MODE FLAG +DISOFF: -1 ;-1 IF DIS NOT IN USE OR STOPPED DUE TO FRAME HACK +DTIME: 0 + +340MD: -1 ;MODE IN WHICH DISPLAY OPEN + ;-1 NOT DISPLAYING 0 .DSTART ETC 2 AS DIS OR IDS +340DMD: 0 ;0 IDS -1 DIS +340XMD: 0 ;IN DIS, 0=CH 1=IMAGE +DBLOAT: 0 +340T: 0 ;TIMER FOR DIS PAGE +LUBLKP: 0 ;LAST USER BLKO PNTR SET UP AT IN LEVEL, FOR DEBUGGING + +;START 340 EXECPG AREA + +A340P1: -1 ;USER ADR THAT EXEC PG SET UP FOR +A340P2: -1 +340DA: REPEAT N340PB,-1 +N340CL==.-A340P1 ;THIS BLOCK MUST BE CONSEC +340DP: 0 ;0=> N30PB-1 PNTR TO DATA PGS +340PP: 0 ;PNTR TO 340P1 OR P2 ALTNERATELY + +DPAP: 400000+340P1*2000(A) ;EXEC ADR TO REF PAGE + 400000+340P2*2000(A) +DDAD: REPEAT N340PB, 400000+*2000(A) + +DPEP: .340P1+EXEUMP ;BYTE PNTR TO EXEC MAP PAGE ENTRY + .340P2+EXEUMP +DDEP: REPEAT N340PB, CONC .DPG,\.RPCNT,+EXEUMP + +DPBS: BLOCK 8 ;SAVE PAGE BOX AT PI DIS LVL + +DROOT: 0 ;DIS RESTART POINTER TO LOSER CORE +DBLKOP: 0 ;TEMP DIS BLKO PTR +LDBLKP: 0 ;LAST +DISON: 0 ;-1 IF DIS STOPPED AFTER SPECIAL INT OR BLKO OVERFLOW + ;IE RESTART AFTER PASSAGE OF TIME +DISDIE: 0 ;0 ;-1 IF DIS HASNT DIED +DISTPR: 0 ;-1 TO TURN OFF DISPLAY +IDBLKP: 0 ;BLKO PNTR IF IN INTERP DISPLAY MODE +NDSFMS: -1 ;-1 NOT HACKING FRAME HACK ELSE NUMBER OF FRAMES REMAINING +DISNTO: 0 ;# TIMES DIS OR IDS OPEN +DWDS: 0 ;- # WDS SENT TO DIS-EWRT PER TRIP THRU SRECYC + ;RESET TO MDISWD EVERY 1/30 + ;IF <0 DISPLAY STOPS FOR 5 SEC -300.->DTIME + +DISCHS: 0 ;LENGTH OF LINE IN CURRENT SIZE +DISCHC: 0 ;-# CHR POS REMAINING +DISLNL: 0 ;# OF LINES WILL FIT CURRENT SIZE +DISLNS: 0 ;# LINES REMAINING +BBLK + +DEFINE LC A +A,,DISLC +TERMIN + +DEFINE UC A +DISUC,,A +TERMIN + +DEFINE AC A +A,,A +TERMIN + + + +ADISCR: MOVE I,DISCHS + MOVNM I,DISCHC + MOVEI I,34 + JRST POPJ1 + +DISALF: SOS DISLNS + MOVEI I,33 + JRST POPJ1 + +DSATB: MOVEI I,40 ;B + PUSHJ P,AIDC4B + LDB I,[300,,DISCHC] + SKIPG DISCHC + JUMPN I,DSATB + JRST POPJ2 + +DISBLB: MOVEI I,50 ;DOWN ARROW + PUSHJ P,AIDC4B + TRO A,100 ;CONVERT TO UC LETTER +DISUC: SKIPA I,[HRRZ I,35(A)] ;SWITCH TO UC +DISLC: MOVE I,[HLRZ I,36(A)] ;SWITCH TO LC + PUSHJ P,AIDC4 ;STORE CASE CODE + HLLM I,AIDC1 + POPJ P, + +ADISBS: MOVEI I,72 ;BACKSPACE + SOS DISCHC + JRST POPJ1 + +DISRUB: MOVEI I,"X&77 ;LC X + PUSHJ P,AIDC4 + MOVEI I,72 ;340 BACKSPACE + PUSHJ P,AIDC4 + MOVEI A,"O ;YES, A + POPJ P, ;LOOP BACK + +DISTBL: POPJ2,,POPJ2 ;IGNORE 0 + REPEAT 6,LC DISBLB + LC 63 ;BELL + LC ADISBS + AC DSATB + AC DISALF + LC DISBLB + LC DISBLB + AC ADISCR + REPEAT 33-16,LC DISBLB + LC 47 ;ALT MD (RT ARROW) + REPEAT 4,LC DISBLB + AC 40 + REPEAT 133-41,UC <.-DISTBL>&77 + LC 53 + LC 52 ;BACKSLASH + LC 54 + LC 100+67 + LC 60 + LC 100+66 + REPEAT 173-141,LC <.-DISTBL-140> + LC 55 + LC 62 ;VERTICAL BAR=174 + LC 56 + LC 43 ;TILDE=176 + LC DISRUB +IFN .-DISTBL-200,PRINTX /DISTBL LOSS/ + + +DINCT: 10 + 2 + 14 + 3 + 12 + 16 + 17 + 13 + + + +REPEAT NDOPL, CONC AIER,\.RPCNT+1,: JSP D,AIER + +AIER: HRRZ R,UUAC(U) + ADDI R,IOCHNM(U) + MOVEI D,1+1-AIER1(D) + LSH D,6+18. + IORM D,IOCHST-IOCHNM(R) + MOVE T,AIDPCP + UMOVEM C,(T) + JRST IOCERR +] + +IFN VIDP,[ +; +SUBTTL NEW VIDISECTOR ROUTINES +; +TVCO: HLRZ D,C + SKIPA Q,[TVCOBK] +NVIDI: MOVEI Q,NVDOBK + PUSH P,R + PUSH P,[NVIDI2] + JRST STDOP1 + +NVIDI2: JRST POPAJ + POP P,R + PUSHJ P,NVDGET + JRST NVIDI3 +NVIDI1: MOVEM A,(R) + CAIN Q,TVCOBK + AOS NTVCOS + CAIN Q,TVCOBK + TLNE C,1 ;ONLY DO IF TVC OUTPUT OPEN + PUSHJ P,TVCNOS + JRST POPJ1 + +NVIDI3: PUSHJ P,OPNL25 + JRST NVDCLS + +NVDOBK: 1,,NVDUSR + NVIDOP,,BNVIDO + +BNVIDI: JSP Q,WRDBT +NVIDIT: SKIPGE NVDIFL + PUSHJ P,UFLS + UMOVE B,(C) + MOVEM B,NVDCOR + CONO PI,OMXOFF + SETOM NVDIFL + PUSHJ P,NVDVS1 ;TURNS OMPCH ON + SKIPGE NVDIFL + PUSHJ P,UFLS + MOVE B,NVDCOR + UMOVEM B,(C) + POPJ P, + +RNVDIB: JSP Q,WRDBT +RNVDIU: SKIPN NVDCNT ;TVC INPUT + JRST RNVDO2 + XCTR XRW,[MOVES (C)] ;MAKE SURE GOING TO WIN + MOVE T,NVDOPT + CAMN T,NVDVPT + PUSHJ P,UFLS + MOVE B,(T) + SOS NVDCNT + UMOVEM B,(C) + AOS T,NVDOPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDOPT + POPJ P, + +TVCOBK: 3,,NVDUSR + DNVDIU,,DNVDOU + DNVDIB,,DNVDOB + +TVCCLS: SOSGE NTVCOS + PUSHJ P,TVCINI ;TRY TO AVOID GARBAGE PNT PART WAY VIDISECTED +NVDCLS: SOSGE NVDUSE + PUSHJ P,VIDFLS + POPJ P, + +TVCNOS: LDB A,[251700,,C] ;TVC OPEN ROUTINE +TVCN1: TRZ A,703000 ;DONT LET LOSER FOOL AROUND + IORI A,NVDCHN_15. + LDB B,[20300,,A] ;DCO + JUMPE B,TVCO3 + CAIN B,7 + JRST TVCO6 ;DCO DISABLED FOR DCL=7 + IMUL B,[-100] +TVCO4: ADDI B,1300 +TVCO7: MOVEM B,NVDDK ;DARK VALUE CORRECT FOR DCO + MOVE TT,A + XOR TT,TVCONO + TRNE T,340 + JRST TVCO5 ;CHANGE IN VIDI SELECTION STATUS +TVCO5A: MOVEM A,TVCONO + POPJ P, + +TVCO3: LDB T,[200,,A] ;CONF + CAIN T,3 + MOVNI B,100 ;IF CONF=3 & DCO=0 VALUE 100 LESS THAN PREDICTED ABOVE + JRST TVCO4 + +TVCO5: TRZ A,700000 ;CLEAR CHNL OUT OF TVCONO + CONO NVDX,(A) ;START RLYS + MOVEI T,2 + SKIPL TVQBLK+1 ;WAIT IF PREV RQ NOT SATISFIED + PUSHJ P,UFLS + PUSHJ P,CLQADD ;RQ LATER TRANSFER TO VIDD1 + TVQBLK + JRST TVCO5A + +TVCO6: LDB T,[200,,A] ;CONF + IMUL T,[-200] ;CALCULATE WHEN OVF HAPPENS + ADDI T,2000 + JRST TVCO7 + +TVCINI: CONO PI,OMXOFF + SETZM NVDCNT + MOVE T,NVDIPT + MOVEM T,NVDVPT + MOVEM T,NVDOPT + MOVE T,NVDBKR + CAIN T,1 + SETOM NVDBKR + JRST OMXONJ + +VIDFLS: SKIPL NVDUSE ;SKIP IF OPENS ON NVD, .VSCAN + POPJ P, + DATAO DSDEV,[DSNVID] ;DEASSIGN VIDI + SETOM NVDUSR + POPJ P, + +NVDGET: CONO NVDX,@TVCONO ;TRY TO ASSIGN BAT + CONI NVDX,TT + JUMPE TT,CPOPJ + JRST POPJ1 + + +NVDBRK: MOVE T,NVDBKR + JRST NVTAB(T) ;DISPATCH ON REASON FOR BREAK + + JRST NEWORK ;STARTUP OF SOME NEW FUNCTION +NVTAB: JRST SCNB1 ;NEW VSCAN POINT + JRST TVB1 ;NEW TVC POINT + JRST INVD1 ;NEW NVD PNT +; JRST DRET ;NEW DAEMON POINT + +TVB1: DATAI NVDX,@NVDVPT ;READ IN OF TV POINT + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,@NVDVPT] ;READ ALL RELAVENT INFO FROM BAT + TRNE T,3 + JRST TVB2 ;DCO OR OVFL + MOVE T,@NVDVPT + ANDI T,1777 + CAMLE T,NVDDK + JRST TVB2 ;DUE TO NOISE/PROB DARKER THAN DCO +TVB3: AOS T,NVDVPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDVPT ;INCREMENT TO NEXT POINT + JRST NEWORK + +TVB2: MOVE T,NVDDK + DPB T,[1200,,@NVDVPT] + DPB T,[240600,,@NVDVPT] ;PUT IN FLOATING PART + LSH T,-6 + DPB T,[330400,,@NVDVPT] + JRST TVB3 + +TVNEXT: MOVE T,NVDVPT + CAMN T,NVDIPT + JRST TVCFIN + MOVEI T,1 ;SET UP FOR NEXT TV POINT + MOVEM T,NVDBKR + MOVE T,NVDVPT + HLRZ T,@NVDVPT + CONO NVDX,@TVCONO + DATAO NVDX,T + EXCH T,VIDXOL + SUB T,VIDXOL + MOVMM T,VIDTEM + HRRZ T,@NVDVPT + DATAO NVDY,T + EXCH T,VIDYOL + SUB T,VIDYOL + MOVMS T + CAMGE T,VIDTEM + MOVE T,VIDTEM + CAIL T,1000 + JRST TVB5 + DATAO NVDT,[-4] +NVDBR4: JRST OMXRET + +TVB5: TLC T,232000 ;CALCULATE SETTLING TIME + FAD T,T + LDB T,[330400,,T] + DATAO NVDT,SETLL-10.(T) + JRST NVDBR4 + +SETLL: ;SETTLING TIME IN 10 MICROSEC + -6 ;DEFLECTING 512 - 1023 + -10 ;1024 - 2047 + -16 ;2048 - 4095 + -26 ;4096 - 8191 + -45 ;8192 - 16383 + -70 ;16384 + +RNVDOB: JSP Q,WRDBT +RNVDOU: MOVEI T,NVDLNG-1 ;TO PREVENT HANGUP AT PI ON WRAPAROUND + CAMG T,NVDCNT + JRST RNVDO2 + UMOVE B,(C) + MOVEM B,@NVDIPT + AOS NVDCNT + AOS T,NVDIPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDIPT + CONO PI,OMXOFF + SETOM TVFLG +NVDVS1: MOVE T,TVCONO + SKIPGE NVDBKR + CONO NVDX,2000(T) + JRST OMXONJ + +RNVDO2: POP P,T ;CALLED FROM RNVDI ALSO + ANDI T,-1 + CAIE T,WRDBRT + JRST IOCER9 + POPJ P, + +NEWORK:; SKIPGE DAEMFL +; JRST DNEXT + SKIPL SCNUSR ;DEFLECT FOR NEW VSCAN POINT + JRST SCNB2 + SKIPGE NVDIFL ;NVD + JRST INVD2 + SKIPGE TVFLG ;DEFLECT FOR NEW TVC POINT + JRST TVNEXT + SETOM NVDBKR ;NO MORE CROCKS FOR VIDISECTOR TO DO + MOVE T,TVCONO + TRZ T,703000 ;SAVE STATE OF VIDI SELECT + CONI NVDX,A + CONO NVDX,(T) + SKIPN A + DATAO DSDEV,[DSNVID] ;RE DEASSIGN VIDI IF WAS DEASSIGNED + ;(CONO DID CLEAR PIA, DONE, AND SET MODE FLOPS THO) + JRST OMXRET + +TVCFIN: SETZM TVFLG + JRST NEWORK + +INVD1: DATAI NVDX,NVDCOR + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,NVDCOR] + SETZM NVDIFL + JRST NEWORK + +INVD2: MOVEI T,2 + MOVEM T,NVDBKR + CONO NVDX,@TVCONO + HLRZ T,NVDCOR + DATAO NVDX,T + HRRZ T,NVDCOR + DATAO NVDY,T + DATAO NVDT,[-7] + JRST NVDBR4 + +SUBTTL NEW VIDISECTOR ROUTINES - .VSTST + +AVSTST: UMOVE A,(J) + CAME U,NVDUSR + JRST AVST4 + JUMPE A,AVST1 ;READ CURRENT STATE + JUMPL A,AVST2 +AVST3: SKIPL SCNUSR ;HANGUP TILL VSCAN FINISHED + PUSHJ P,UFLS +AVST2: +SCNSTP: CONO PI,OMXOFF ;FLUSH VSCAN ENTIRELY + SKIPGE SCNUSR + JRST OMXONJ ;ALREADY FINISHED + SETOM SCNUSR + SOSGE NVDUSE + SETOM NVDUSR + SKIPN NVDBKR ;IGNORE VSCAN POINT IN PROGRESS IF ANY + SETOM NVDBKR +VSLS2: PUSH P,A + PUSH P,B + PUSH P,W + MOVSI B,-1 + MOVSI W,-2 +SCNS2: LDB A,VEXT(W) + TRNN A,600000 + JRST SCNS4 + ANDI A,PMRCM + ADDM B,MMSWP(A) +SCNS4: MOVEI A,0 + DPB A,VEXT(W) + AOBJN W,SCNS2 + MOVE A,USER + SPM UPGML(A) + LPMR UPGML(A) + POP P,W + POP P,B + POP P,A + PUSHJ P,VIDFLS + JRST OMXONJ + +AVST4: JUMPE A,ILUUO + POPJ P, + +AVST1: SKIPGE SCNUSR + POPJ P, + MOVE A,NVDPTR + SUBI A,400000+VSB1*2000 + JRST APTUAJ + +;CHECK TO SEE IF MEM PROTECT STILL OK +SCNACR: CAMN U,SCNUSR + POPJ P, + AOS (P) + JRST SCNSTP + +;STOP SCAN +SCNSTC: CONO NVDX,0 + POPJ P, + +;RESTART SCAN AFTER STOP FOR SHUFFLING +SCNRST: CONO NVDX,NVDCHN_17 + POPJ P, + + +SUBTTL NEW VIDISECTOR ROUTINES - .VSCAN + +AVSCAN: XCTR XRW,[MOVES (C)] + XCTR XRW,[MOVES 12(C)] + SKIPL SCNUSR + PUSHJ P,UFLS + CONO PI,CLKOFF + CAME U,NVDUSR + SKIPGE NVDUSE + AOSA NVDUSE + JRST ILUUO + MOVEM U,NVDUSR + CONO PI,CLKON + PUSHJ P,NVDGET + JRST VSLOS +A.VS1: SETZM BATMXA + XCTR XRW,[HLRZ A,2(C)] + MOVEM A,NVDCNX + MOVEM A,NVDCN3 + XCTR XRW,[HRRZ A,2(C)] + MOVEM A,NVDCNY +IRPS XY,,X Y P X Y P,A12,,1 1 1 2 2 2,N,,3 6 11 4 7 12,YX,,X X X Y Y Y + UMOVE A,N(C) + IDIV A,NVDCN!YX + MOVEM A,BATD!XY!A12 +TERMIN +IRP XY,,[P,X,Y]ADR,,[[[1,,]],5(C),10(C)] + MOVE A,BATD!XY!1 + ADD A,BATD!XY!2 + ASH A,-1 +IFE .IRPCNT, ADD A,ADR +IFN .IRPCNT, XCTR XRW,[ADD A,ADR] + MOVEM A,BAT!XY!1 + MOVEM A,BAT!XY!2 + IFN .IRPCN,[IDIV A,BATP1 + MOVEM A,NVID!XY] +TERMIN + XCTR XRW,[HRRZ B,1(C)] + LDB A,[121000,,B] + CAIL A,376 + JRST VSLOS + MOVEI W,0 + PUSHJ P,VSMS1 + MOVEI W,1 + PUSHJ P,VSMS1 + SPM UPGML(U) + LPMR UPGML(U) + HRRZ R,B + ANDI R,776000 + ADDI R,4000-2000 + XCTR XRW,[HLRO D,1(C)] + MOVE A,NVDCNX + IMUL A,NVDCNY + JUMPLE A,VSLOS ;SIZE OF RASTOR + MOVNS D ;PLUS COUNT + CAMLE A,D + JRST VSLOS ;WON'T FIT + CAML A,R + JRST VSLOS ;WON'T FIT IN EXEC PGS + ADD A,B + MOVEM A,BATMXA + LDB A,[121000,,A] + PUSHJ P,UPLC + LDB A,T + TRC A,600000 + TRCE A,600000 ;SKIP ON R/W/F + JRST VSLOS ;TOP PAGE LOSES + ANDI B,1777 + ADDI B,400000+VSB1*2000 + MOVEM B,NVDPTR + XCTR XRW,[HRRZ A,(C)] + PUSHJ P,TVCN1 + MOVE A,[JRST SCNG1] + MOVEM A,SCNB1A + CONO PI,OMXOFF + MOVEM U,SCNUSR + MOVE A,TVCONO + SKIPGE NVDBKR + CONO NVDX,2000(A) + CONO PI,OMXON + XCTR XRW,[SKIPL (C)] + POPJ P, + JRST AVST3 + +VSLS3: PUSHJ P,LSWPOP +VSLOS: PUSHJ P,VSLS1 + JRST ILUUO + + +VPGLOS: PUSHJ P,VSLS1 + PUSHJ P,TPFLT + JRST UUOTRO + +VSLS1: SOSGE NVDUSE + SETOM NVDUSR + CONO PI,OMXOFF + JRST VSLS2 + +VSMS1: PUSHJ P,SWTL + CIRPSW + LDB A,[121000,,B] + ADD A,W + MOVEM A,VSMPG + PUSHJ P,UPLC + CONO PI,CLKOFF + LDB A,Q + JUMPE A,VSMS2 ;NO ACCESS + CAIN A,-1 + JRST VSLS3 + LDB A,T + TRNN A,600000 + JRST VSMS3 ;SWAPPED OUT + TRNN A,400000 + JRST VSLS3 ;RD ONLY + TRO A,200000 +VSMS2: DPB A,T ;CHANGE R/W/F TO R/W + LDB TT,VEXT(W) + DPB A,VEXT(W) + MOVSI Q,1 + ANDI A,PMRCM + SKIPE A + ADDM Q,MMSWP(A) + JUMPE TT,VSLS4 + ANDI TT,PMRCM + MOVSI Q,-1 + ADDM Q,MMSWP(TT) +VSLS4: PUSHJ P,LSWPOP + JRST CLKONJ + +VSMS3: PUSHJ P,LSWPOP + MOVE A,VSMPG + SOSGE NVDUSE + SETOM NVDUSR + PUSHJ P,CWAIT + SKIPL VIDSWI + MOVEM U,VIDSWI + MOVEM A,VIDSPG + SKIPL VIDSWI + PUSHJ P,UFLS + SUB P,[1,,1] + JRST AVSCAN + SCNB1: DATAI NVDX,@NVDPTR + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,@NVDPTR] + TRNE T,3 + JRST SCNB1C ;OVF OR DCO? + MOVE T,@NVDPTR + ANDI T,1777 + CAMG T,NVDDK ;OR VALUE GREATER THAN DCO LEVEL + JRST NEWORK +SCNB1C: MOVE T,NVDDK + DPB T,[1200,,@NVDPTR] + DPB T,[240600,,@NVDPTR] ;PUT IN FLOATING PART + LSH T,-6 + DPB T,[330400,,@NVDPTR] + JRST NEWORK + +SCNB2: CONO NVDX,@TVCONO ;SETUP FOR NEXT VSCAN POINT + DATAO NVDX,NVIDX + DATAO NVDY,NVIDY + MOVE T,NVIDX + EXCH T,VIDXOL + SUB T,VIDXOL + MOVMM T,VIDTEM + MOVE T,NVIDY + EXCH T,VIDYOL + SUB T,VIDYOL + MOVMS T + CAMGE T,VIDTEM + MOVE T,VIDTEM + CAIL T,1000 + JRST SCNT5 + DATAO NVDT,[-4] +SCNT4: CLEARM NVDBKR + EBLK +SCNB1A: JRST SCNG1 ;OR AOS (AOSA) NVDPTR + BBLK + JRST SCNS1 ;HOMO LINEAR FROB +SCNB1B: SOSG NVDCNX ;SIMPLE MINDED + JRST SCNB3 +IRPC X,,XY + MOVE T,BATD!X!1 + ADDB T,BAT!X!1 + HLRZM T,NVID!X +TERMIN +SCNBX: JRST OMXRET + +SCNT5: TLC T,232000 ;CALCULATE SETTLING TIME + FAD T,T + LDB T,[330400,,T] + DATAO NVDT,SETLL-10.(T) + JRST SCNT4 + +SCNB3: SOSG NVDCNY + JRST SCNB4 +IRPC X,,XY + MOVE T,BATD!X!2 + ADDB T,BAT!X!2 + MOVEM T,BAT!X!1 + HLRZM T,NVID!X +TERMIN + + MOVE T,NVDCN3 + MOVEM T,NVDCNX + JRST SCNBX + +SCNB4: SKIPL NVDCNY ;WAIT FOR LAST DATAO TO RETURN A POINT + JRST SCNBX + SETOM SCNUSR + SOSL NVDUSE + JRST NEWORK + SETOM NVDUSR + DATAO DSDEV,[DSNVID] ;DEASSIGN BAT + MOVSI B,-1 + MOVSI W,-2 +SCNB4B: LDB A,VEXT(W) + TRNN A,600000 + JRST SCNB4A + ANDI A,PMRCM + ADDM B,MMSWP(A) +SCNB4A: MOVEI A,0 + DPB A,VEXT(W) + AOBJN W,SCNB4B + JRST NEWORK + +SCNS1: MOVEM U,NVDTMU + SOSG NVDCNX + JRST SCNS3 +IRPC X,,PXY + MOVE T,BATD!X!1 + ADDB T,BAT!X!1 + IFN .IRPCN,[IDIV T,BATP1 + MOVEM T,NVID!X] +TERMIN + +SCNBX1: MOVE U,NVDTMU + JRST SCNBX + +SCNS3: SOSG NVDCNY + JRST SCNB4 +IRPC X,,PXY + MOVE T,BATD!X!2 + ADDB T,BAT!X!2 + MOVEM T,BAT!X!1 + IFN .IRPCN,[IDIV T,BATP1 + MOVEM T,NVID!X] +TERMIN + MOVE T,NVDCN3 + MOVEM T,NVDCNX + JRST SCNBX1 + +SCNG1: MOVSI T,(AOSA) + SKIPN BATDP1 + SKIPE BATDP2 + MOVSI T,(AOS) + HRRI T,NVDPTR + MOVEM T,SCNB1A + TLNN T,(AOSA-AOS) + JRST SCNS1 + JRST SCNB1B + + +SUBTTL NEW VIDISECTOR ROUTINES + +EBLK + +NVDIPT: NVDBUF ;POINTER TO INSERT IN BUF +NVDVPT: NVDBUF ;POINTER TO WORD BEING VIDISECTED +NVDOPT: NVDBUF ;POINTER TO WITHDRAW FROM BUF +NVDCNT: 0 ;NUMBER PTS IN BUF +NVDBUF: BLOCK NVDLNG +VIDSTRT: 0 +LBTCNO: 0 ;LAST CONO TO BAT +NVDIFL: 0 ;+=> RQ TO READ NVD PNT +NVDCOR: 0 ;NVD DEV, COORDINATES TO PI, READ DATA FROM PI +NTVCOS: -1 ;# TVC OPENS + +IRPC X,,XYP + IRPC N,,12 + BAT!X!!N: 0 + BATD!X!!N: 0 + TERMIN +TERMIN + +NVDCNX: 0 +NVDCNY: 0 +NVDCN3: 0 +NVIDX: 0 +NVIDY: 0 +BATMXA: 0 +NVDPTR: 0 +NVDTMU: 0 +SCNUSR: -1 ;USER IN CURRENT .VSCAN, -1 .VSCAN FREE +SCNREL: 0 +TVCONO: 0 ;CONO FOR TVC DEVICE AND VSCAN (NORM HAS CHNL BUT NOT IF IN VIDDLY) +NVDDK: 0 ;-1=>VID VALUE CORRESP TO DCO +TVFLG: 0 ;-1=>TVC WORK IN PROGRESS +NVDBKR: -1 ;REASON LAST POINT READ IN, DISPATCH ADDRESS FOR INTS + ;-1 NONE 0 VSCAN 1 TVC 2 NVD +TVQBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST VIDD1 +VIDXOL: 0 ;OLD VIDI CORDS +VIDYOL: 0 ;OLD VIDI CORDS +VIDTEM: 0 ;LARGEST DELTA +VSMPG: 0 +VEXT: .VSB1+EXEUMP + .VSB2+EXEUMP + +BBLK + +VIDD1: MOVEI A,NVDCHN_15. + IORB A,TVCONO ;RESTORE CHNLS TO TVCONO + CONO NVDX,2000(A) ;CAUSE EVENTUAL VIDI INT TO SEE IF ANYTHING YO DO + JRST CLQRET ;RETURN TO CLOCK ROUTINE +] + +SUBTTL VIDEO SWITCH AND VIDEO BUFFER ROUTINES + +;SYSTEM CALLS FOR HACKING THE VIDEO SWITCH AND VIDEO BUFFERS. + +IFE N11TYS,[ +NVDBF==OPNL1 +NVIDSW==OPNL1 +] + +IFN N11TYS,[ + +VBDFLS: PUSH P,B + PUSH P,T + PUSH P,I + PUSH P,Q + PUSH P,C + MOVSI B,-MXVBN ;FLUSH ALL BUFFERS ASSIGNED TO JOB IN U +VBDFL3: CAMN U,VBAST(B) + JRST VBDFL1 +VBDFL2: AOBJN B,VBDFL3 + SKIPE NVDBA(U) + JRST 4,. +VBDFL6: POP P,C + POP P,Q + POP P,I + POP P,T + POP P,B + POPJ P, + +VBDFL1: JSP Q,11CM1 + JRST VBDFL4 ;LOST.. + PUSH P,B + JSP Q,NVDBU2 ;FLUSH BUFFER + JFCL ;PDP11 TIMED OUT + JFCL ;PDP11 GAVE NEGATIVE REPLY + POP P,B + JRST VBDFL2 + +VBDFL5: CAMN U,VBAST(B) +VBDFL4: SETOM VBAST(B) + AOBJN B,VBDFL5 + CLEARM NVDBA(U) + JRST VBDFL6 + +;VIDBUF SYSTEM CALL - ASSIGN OR DEASSIGN VIDEO BUFFERS +NVDBF: JSP Q,11CM1 ;SET UP ACS, LOCK SWITCH. + JRST OPNL7 ;LOST + JUMPGE A,NVDBU1 ;JUMP IF DEASSIGN COMMAND + MOVSI C,2_<16.+4-18.> + JSP Q,NVDCMD ;TELL PDP11 TO ASSIGN BUFFER. + JRST OPNL7 ;PDP11 TIMED OUT + JRST OPNL6 ;PDP11 GAVE NEGATIVE REPLY + HRRZ A,C + CAIL A,MXVBN + JRST OPNL6 ;PDP11 HAS MORE VIDEO BUFFERS THAN WE DO + AOS NVDBA(U) ;WON + MOVEM U,VBAST(A) + JRST POPJ1 + +NVDBU1: MOVE B,A ;DEASSIGN VIDEO BUFFER + CAIGE B,MXVBN ;CHECK THAT VIDEO BUFFER IS LEGAL + CAME U,VBAST(B) ;AND BELONGS TO THIS JOB + JRST OPNL33 ;NOT LEGAL VIDEO BUFFER NO + JSP Q,NVDBU2 ;TELL PDP11 TO FREE THE BUFFER. + JRST OPNL7 ;TIMED OUT + JRST OPNL23 ;GAVE NEG REPLY + JRST POPJ1 ;WON + +EBLK +;TABLE OF VIDEO BUFFER ASSIGNMENTS. +VBAST: REPEAT MXVBN,-1 ;-1 => FREE, ELSE USR IDX. +11CVSR: -1 ? 0 ;SWITCH TO LOCK TO PROTECT 10-TO-11 COMMAND VARS. +BBLK + +;VIDSW SYSTEM CALL - SET VIDEO SWITCH. +NVIDSW: JSP Q,11CM1 ;LOCK SWITCH, ETC. + JRST OPNL7 + LSH A,4.+16. + LSH B,4.+16. + MOVEM A,1(I) + MOVEM B,2(I) + MOVSI C,1_<16.+4-18.> + JSP Q,NVDCMD + JRST OPNL7 ;TIMED OUT + JRST OPNL23 ;PDP11 DIDN'T FEEL LIKE SWITCHING THE SWITCH + JRST POPJ1 + +NVDBU2: SETOM VBAST(B) ;GIVE DEASSIGN COMMAND TO 11 + LSH B,4.+16. + MOVEM B,1(I) ;WHICH ONE TO DEASSIGN + SOSGE NVDBA(U) + JRST 4,. + MOVSI C,3_<16.+4-18.> +;GIVE COMMAND IN C TO PDP11, WAIT, RETURN (Q) IF 11 TIMES OUT, +;1(Q) IF 11 GIVES NEGATIVE REPLY AND 2(Q) IF SUCESSFUL +;IN ANY CASE, SWITCH IS UNLOCKED +;ASSUMES ARGS ALREADY SET UP, AND 11CVSR LOCKED. +NVDCMD: MOVEM C,(I) ;STORE COMMAND-TYPE, TELLING PDP11 TO GO. +NVDCM1: CAME C,(I) + JRST NVDCM2 ;IT'S FINISHED, WE WIN. + SOJG T,NVDCM1 ;LOOP FOR A WHILE, + PUSHJ P,LSWPOP + JRST (Q) ;FAIL - 11 TIMED OUT + +NVDCM2: MOVE C,1(I) ;RETURNED ARG IN CASE OF ASSIGN VIDEO BUFFER + LSH C,-4.-16. + SKIPGE (I) ;PDP11 FINISHED: DID COMMAND SUCCEED? + AOS Q ;YES SKIP EXTRA TIME + SETZM (I) + PUSHJ P,LSWPOP + JRST 1(Q) + +;LOCK SWITCH AND SET UP.. RETURN TO (Q) IF FAILS (SWITCH NOT LOCKED IN THAT CASE) +;RETURN TO 1(Q) IF SUCEEDS + +11CM1: SKIPL TT11P + JRST (Q) + PUSHJ P,SWTL + 11CVSR + LDB T,[061600,,TT11HA] + LDB I,[061600,,400000+TTPG0*2000(T)] + ADDI I,400000+TTPG0*2000 ;I HAS 10-TO-11 COMMAND BFR ADDR. + MOVSI T,1 ;# TIMES TO LOOP WAITING FOR 11 TO ACKNOWLEDGE +11CM2: SKIPG (I) + JRST 1(Q) ;11 READY FOR COMMAND. + SOJG T,11CM2 + PUSHJ P,LSWPOP + JRST (Q) ;TIMED OUT +] + +SUBTTL TABLET AND ROBOT CONSOLE + +IFN TABP,[ + +ITAB: IFE TABCLK,[ + SOSLE TABRTC + JRST ITAB6 + SKIPGE TABUSR + JRST ITAB7 + MOVE A,TABRTE + MOVEM A,TABRTC + CONO RBTCON,RTABC_3+TABCHN +] IFN TABCLK, CONO RBTCON,RTABC_3 + ROT A,36.*2 + DATAI RBTCON,A + JUMPL A,ITAB ;TRY AGAIN + LDB B,[400300,,A] + CAME B,TABLSZ + JRST ITAB2 + CAIN B,7 + JRST ITAB3 ;PEN OUT OF CONTACT + LDB B,[221400,,A] ;X + SUB B,TABLSX + MOVMS B + CAML B,TABDTA + JRST ITAB2 + LDB B,[1400,,A] + SUB B,TABLSY + MOVMS B + CAML B,TABDTA + JRST ITAB2 +ITAB3: AOS B,TABSMC + CAIL B,77 + JRST ITAB2 +ITAB5: IFN TABCLK,[ + MOVE T,TABRTE + MOVEI C,TABQBK + SKIPL TABUSR + JRST CLQREE + JRST CLQRET +] IFE TABCLK,[ + JRST OMXRET + +ITAB6: DATAI RBTCON,A ;FLUSH DATA + JRST OMXRET + +ITAB7: CONO RBTCON,0 + JRST OMXRET +] +ITAB2: MOVE B,TABSMC + DPB B,[140600,,TABLST] + SETZM TABSMC + HRRZM A,TABLSY + LDB B,[221400,,A] + MOVEM B,TABLSX + LDB B,[400300,,A] + MOVEM B,TABLSZ + EXCH A,TABLST + JUMPE A,ITAB5 ;JUST STARTING UP + MOVE B,TABCC + CAIL B,LTABBF + JRST ITAB4 ;FULL + MOVEM A,@TABIP + AOS TABCC + AOS B,TABIP + CAIL B,TABBFE + MOVEI B,TABBUF + MOVEM B,TABIP + JRST ITAB5 + +ITAB4: MOVSI B,(SETZ) ;SET DATA LOST + IORM B,TABLST + JRST ITAB5 + +] + +IFN RBTCP,[ + + ;ROBOT CONSOLE READ SWITCHES +ARBTC: UMOVE A,(J) + CONO PI,TABOFF + CONO RBTCON,RLTSWC_3+IFE TABCLK,TABCHN + ROT A,36.*2 + DATAO RBTCON,A + ROT A,36.*2 + DATAI RBTCON,A + CONO PI,TABON + UMOVEM A,(J) + POPJ P, + +;DATA FORM +;4.9 DATA LOST BEFORE THIS +;4.8-4.6 TAB "Z" +;4.5-4.4 USUSED +;4.3-3.1 TABLET X +;2.9-2.4 REPEAT COUNT +;2.4-1.1 TABLET Y + +TABO: PUSH P,[TABO1] + JSP Q,STDOPN + 1,,TABUSR + DTABUI,,DTABBI + +TABO1: POPJ P, ;OPEN LOST + SKIPE TABUSE ;OPEN WON + JRST POPJ1 ;NOT FIRST OPEN + LDB T,[250300,,C] + AOS T + MOVEM T,TABRTE ;TABLET RATE (IGNORE THIS MANY BETWEEN TAKES) + LDB T,[300600,,C] + MOVEM T,TABDTA ;DELTA FOR COORD TO BE DIFFERENT + PUSHJ P,TABCLR +IFE TABCLK, CONO RBTCON,RTABC_3+TABCHN +IFN TABCLK,[ PUSHJ P,CLQAD1 ;START UP CLOCK LEVEL + TABQBK +] JRST POPJ1 + +BTABI: UMOVE J,(C) ;INITIAL AOBJN PNT + JSP Q,WRDBT +UTABI: SKIPG TABCC ;TABLET .IOT + JRST TABI1 ;NO DATA AVAIL, SEE IF BEING ACCUMULATED +UTABI1: MOVE A,@TABOP + UMOVEM A,(C) + AOS T,TABOP + CAIL T,TABBFE + MOVEI T,TABBUF + MOVEM T,TABOP + SOS TABCC + POPJ P, + +TABI1: HRRZ T,(P) + CAIN T,WRDBRT + JRST TABI2 +TABI3: SKIPG TABCC + PUSHJ P,UFLS + JRST UTABI1 + +TABI2: XCTR XRW,[CAMN J,(H)] + JRST TABI3 ;NO WDS TRANSFERRED + SUB P,[1,,1] ;RETURN TO USER SOME HAVE BEEN TRANSFERRED + POPJ P, + +TABCLR: CONO PI,TABOFF + SETZM TABCC + MOVEI T,TABBUF + MOVEM T,TABIP + MOVEM T,TABOP + SETZM TABSMC + SETZM TABLST + CLEARM TABLSX + CLEARM TABLSY + CLEARM TABLSZ +IFE TABCLK, SETZM TABRTC + CONO PI,TABON + POPJ P, +EBLK + +TABBUF: BLOCK LTABBF +TABBFE: +TABOP: TABBUF ;OUTPUT PNTR (MP) +TABIP: TABBUF ;INPUT PNTR (PI) +TABCC: 0 ;ACTIVE WDS IN TAB BUFFER +TABSMC: 0 ;COUNT OF TIMES "SAME" DATA RECEIVED FOR TAB +TABLST: 0 ;LAST DATA +TABLSZ: 0 ;Z OF LAST DATA +TABLSX: 0 ;X +TABLSY: 0 ;Y +TABDTA: 0 ;DELTA FOR COORD TO BE DIFFERENT +TABRTE: 0 ;TABLET RATE (TAKE EVERY N'TH ONE) +IFN TABCLK,[TABQBK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST ITAB +] +IFE TABCLK,[ +TABRTC: 0 ;COUNT WITHIN TABRTE +] + BBLK +] + IFN IMXP,[ + +SUBTTL INPUT MULTIPLEXOR ROUTINES + +IMPXO: CONI MPX,T + JUMPE T,OPNL25 + TRNN D,2 + JRST IMPXO2 ;READ AT MN PRGM + SKIPGE IMPXF ;IMAGE (READ AT PI) + SETOM MPXWF + PUSHJ P,IMXON +IMPXO2: AOS IMXNTO + HLL A,C + JSP Q,OPSLD3 + IMXDN,,BIMXDN + IMPXDN,,BIMPXD + +IMXON: AOSGE IMPXF + JRST 4,. ;SHOULD NOT HAVE BEEN LESS THAN -1 + PUSHJ P,CLQAD1 ;START CLOCK LEVEL + MPXBLK + POPJ P, + +BIMPXS: JSP Q,WRDBT +IMPXS: SKIPGE MPXWF + PUSHJ P,UFLS + UMOVE A,(C) + ANDI A,377 + CAILE A,LCHN + JRST IMPXS1 +AIMXW5: IDIVI A,3 + LDB A,IMPXT(B) + UMOVEM A,(C) + POPJ P, + +IMPXCL: TRNE A,4 ;SKIP ON WAS READING AT MP +IMXCL1: SOS IMPXF ;WAS READING AT PI + SOSGE IMXNTO + DATAO DSDEVN,[MPX] + POPJ P, + +IMPXRS: SETOM MPXWF + POPJ P, + +IMPXT: 301400,,MPXBUF(A) + 141400,,MPXBUF(A) + 1400,,MPXBUF(A) + +BIMXS1: JSP Q,WRDBT +IMPXS1: UMOVE A,(C) + TDZE A,[-400] + JRST IOCER4 +AIMXW4: MOVE T,MPXWF + CAILE A,LCHN + MOVNI T,2 ;CHNL NOT READ IN BY PI HACK +AIMXW2: SKIPL IMXSW + PUSHJ P,UFLS + CAME T,MPXWF + AOJGE T,AIMXW3 ;PI FROB HAS CYCLED (MAYBE) + AOSE IMXSW + JRST AIMXW2 ;READING IMX AT PI + DATAO MPX,A ;SELECT CHNL + CONO MPX,0 ;START CONVERSION + MOVEI B,62 + CONSO MPX,10 + SOJG B,.-1 + JUMPE B,IMPXFE + XCTR XRW,[DATAI MPX,(C)] +IMX1: SETOM IMXSW + POPJ P, + +AIMXW3: SKIPGE MPXWF + JRST AIMXW4 ;IT WAS JUST SETOMMED + JRST AIMXW5 ;HAS BEEN READ IN BY PI HACK SO GOBBLE DATA + +IMPXFE: XCTR XRW,[SETOM (C)] + JRST IMX1 + +IMPXSR: AOSE IMXSW + JRST MPXRT1 ;USING IMX AT MN PRGM LVL + MOVE T,[<-LCHN>/3-1,,MPXBUF-1] + MOVEM T,MPXPTR ;SET UP BLKI POINTER + MOVE T,[BLKI MPX,MPXPTR] + MOVEM T,IMXLC ;SET UP DC INTERUPT LOCN + MOVE T,[JSR MPXCYC] + MOVEM T,IMXLC+1 ;SET UP DC INT LOC+1 + DATAO MPX,[0] ;READ STARTING WITH CHNL 0 + CONO MPX,140+DCCHN + MOVEI T,5 ;12TH SEC +IFN ARMP,SKIPN ARMF + SKIPL POTCON + MOVEI T,2 ;1/30 SEC, HAIRY POTS + JRST .+2 +MPXRT1: MOVEI T,1 ;LOST RETRY IN 1/60 + MOVEI C,MPXBLK + SKIPL IMPXF + JRST CLQREE ;RE-ENTER RQ + JRST CLQRET ;RETURN + +EBLK + +OMXNTO: -1 +IMXNTO: -1 +IMPXF: -1 ;-1 IF MPX NOT RUNNING +MPXWF: 0 +MPXBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST IMPXSR +MPXPTR: 0 +IMXST: 0 +IMXSW: -1 ;-1 IF IMX AVAIL +IMXTBB: LCHN +MPXBUF: BLOCK /3+1 +IMXTBE==.-1 + +IMXACS: BLOCK 20 +MPXCYC: 0 + +BBLK + + CONO MPX,0 + SETOM IMXSW + AOS MPXWF + MOVEM T,IMXST + MOVE T,[JSR MPXCYC] + MOVEM T,IMXLC + MOVE T,IMXST +; SKIPGE POTCON +; SKIPE ARMF +; JRST MPXCYG + JRST 12,@MPXCYC + +MPXCYG: MOVEM 17,IMXACS+17 + MOVEI 17,IMXACS + BLT 17,IMXACS+16 +IFN ARMP,[ + SKIPE ARMF + JRST SERVO +ARMSVR:] + SKIPL POTCON + JRST UPOTS +UPOTRT: MOVSI 17,IMXACS + BLT 17,17 + JRST 12,@MPXCYC +] + IFN OMXP,[ + +SUBTTL OUTPUT MULTIPLEXOR ROUTINES + +OMPXO: CONI OMPX,T + JUMPE T,OPNL25 + AOS OMXNTO + HLL A,C + JSP Q,OPSLD3 + OMPXDN,,BOMPXDN + OMXDN,,BOMXDN + +BOMXDS: +BOMPXS: JSP Q,WRDBT +OMXDS: +OMPXS: XCTR XRW,[DATAO OMPX,(C)] ;ZAP CHNL + POPJ P, + +OMPXCL: SOSGE OMXNTO + DATAO DSDEVN,[OMPX] + POPJ P, + +EBLK +OMXACS: BLOCK 20 + +OMPXBK: 0 +BBLK + MOVEM 17,OMXACS+17 + MOVEI 17,OMXACS + BLT 17,OMXACS+16 +IFN VIDP,[ + CONSZ NVDX,700000 + CONSO NVDX,1000 + JRST .+2 + JRST NVDBRK +] +IFN ARMP,[ + CONSZ TIPDEV,10 + JRST TIPBRK +] +IFN TABP,[ + CONSZ RBTCON,7 + CONSO RBTCON,10 + JRST .+2 + JRST ITAB +] +; MOVEI J,OMPCHN +; JSP E,SPUR ;SPURIOUS INT +OMXRET: MOVSI 17,OMXACS + BLT 17,17 + JRST 12,@OMPXBK +] + +SUBTTL MORSE CODE SENDER (COD DEVICE) + +IFN CODP,[ +; CODITC==CODBFL*5-1 ;WHEN TO TRY TO INTERRUPT + +CLKCOD: SETOM TT ;USED AS A FLAG + MOVE B,CODWD + LSH B,-1 +CLKCC3: CAIN B,1 + JRST CLKCC1 + LDB A,[100,,B] + EXCH A,LSTBIT + CAME A,LSTBIT + DATAO 70,LSTBIT + MOVEM B,CODWD + MOVE T,CODSPD + MOVEI C,CODTIM + JRST CLQTTR ;RE-ENTER OR NOT DEPENDING ON TT + +CLKCC1: MOVE A,CODCC + CAIL A,CODBFL*5 + JRST CLKCC5 +CLKCC8: AOS CODCC + ILDB B,CODPTR + MOVE A,CODPTR + CAMN A,[10700,,CODBUF+CODBFL-1] + HRRI A,CODBUF-1 + HRRM A,CODPTR + CAIL B,140 + JRST CLKCC2 + CAIGE B,40 + JRST CLKCC1 + MOVE B,CODTBL-40(B) + JRST CLKCC3 +CLKCC6: MOVE B,CDRUB + JRST CLKCC3 +CLKCC2: CAIN B,177 + JRST CLKCC6 + SUBI B,137 + MOVEM B,CODSPD + JRST CLKCC1 + +CLKCC5: +; CAIN A,CODITC +; JRST CLKCC7 + MOVEI B,2 + SETZM TT ;INDICATE IDLE + JRST CLKCC3 + +;CLKCC7: MOVE A,CODUSR ;GET INDEX OF USER +; MOVE B,CODITB ;GET CHANNELS OPEN MASK +; AND B,MSKST2(A) ;FIND OUT WHAT CODE CHANNELS ENABLED, +; MOVNM B,CODITD +; AND B,CODITD +; IORM B,IFPIR(A) ;AND REQUEST INTERRUPT ON LOWEST NUMBERED ONE +; JRST CLKCC8 ;SEND REMAINING CHARACTER(S) IN BUFFER + + ;RETURN HERE FROM STDOPN +CODO1: POPJ P, ;NON-SKIP RETURN + AOS (P) ;DO NOT CHANGE TO JRST POPJ1 AT END + MOVEI I,1 ;INDICATE "IOPOP" + + ;CODE DEVICE IOPUSH AND IOPOP ROUTINE (SETS INTERRUPT MASK) + +CODIOP: SUBI R,IOCHNM(U) ;GET "AC FIELD" (ROUTINES THAT NEED IT RESTORE R) + MOVE A,CHNBIT(R) ;SET UP INTERRUPT BIT + XCT CDPTBL(I) ;IORM OR ANDCAM TO CODITB + POPJ P, + +CDPTBL: ANDCAM A,CODITB ;IOPUSH AND CLOSE + IORM A,CODITB ;IOPOP AND OPEN + + ;COD CLOSE ROUTINE +CODCLS: MOVEI I,0 ;TO SIMULATE IOPUSH + PUSHJ P,CODIOP ;CLEAR RELEVANT INTERRUPT BIT + CONO PI,CLKOFF ;CLOSE, USE STANDARD SEQUENCE + SOSGE CODUSE + SETOM CODUSR + JRST CLKONJ + +SEND: SKIPGE C + SKIPA A,(C) + XCTR XRW,[MOVE A,(C)] ;UNIT OUTPUT + CAIA +BSEND: JSP E,NBTOCH ;BLOCK OUTPUT + ANDI A,177 + CAIN A,"S-100 + JRST CODSSS + SKIPE CODSSF + JRST CODSST + SKIPG CODCC ;WAIT FOR ROOM + PUSHJ P,UFLS + IDPB A,CODIPT + MOVE A,CODIPT + CAMN A,[10700,,CODBUF+CODBFL-1] + HRRI A,CODBUF-1 + HRRM A,CODIPT + SOS CODCC + MOVE T,CODSPD + PUSHJ P,CLQADD ;START UP CLOCK LEVEL + CODTIM + POPJ P, + +CODO: PUSH P,[CODO1] ;CODO1 SETS UP INTERRUPT BIT + JSP Q,STDOPN + 1,,CODUSR + CODDN,,CODBN + + +CODSSS: SETOM CODSSF + POPJ P, + +CODSST: SETZM CODSSF + SUBI A,137 + JUMPLE A,CPOPJ + MOVEM A,CODSPD + POPJ P, + +CODRS: CONO PI,CLKOFF + MOVEI A,CODBFL*5 + MOVEM A,CODCC + MOVE A,CODIPT + MOVEM A,CODPTR + JRST CLKONJ + +CODFIN: MOVE T,CODBFL*5 ;.CALL FINISH + CAMLE T,CODCC + PUSHJ P,UFLS + POPJ P, + +EBLK +CODITB: 0 ;MASK OF CHANNELS OPEN, 1.1=>0 +CODITD: 0 ;RANDOM SCRATCH LOCATION +CODWD: 2 ;CURRENT WORD +CODTIM: 0 ;CLOCK QUEUE BLOCK + -1 + JRST CLKCOD +CODSPD: 3 ;CODE SPEED (SET FROM CHARS >=140) WPM= 75./(CODSPD) +CODCC: CODBFL*5 +CODPTR: 440700,,CODBUF +CODIPT: 440700,,CODBUF +LSTBIT: 0 ;FLUSH 60 CPS CHIRPS +CODSSF: 0 + +CODBUF: BLOCK CODBFL +BBLK + +DEFINE GCODE A +BIT=1 +WRD=0 +IRPC B,,[A] +IFSE B,-,[WRD=WRD+7*BIT +BIT=BIT_4] +IFSE B,.,[WRD=WRD+BIT +BIT=BIT_2] +IFSE B, ,[BIT=BIT_2] +TERMIN +WRD+4*BIT +TERMIN + +CODTBL: 20 + GCODE -.-.- + GCODE .-..-. + GCODE -. .-. + REPEAT 2,1 + GCODE . ... + GCODE .----. + REPEAT 2,GCODE -.--.- + GCODE .-.- + GCODE . ... + GCODE --..-- + GCODE -....- + GCODE .-.-.- + GCODE -..-. + IRP A,,[-----,.----,..---,...--,....-,.....,-....,--...,---..,----.] + GCODE A + TERMIN + GCODE ---... + GCODE -.-.-. + 27727 ;K WITH LONG LAST DAH + GCODE -...- + GCODE ...-.- + GCODE ..--.. + GCODE ...-. + IRP A,,[.-,-...,-.-.,-..,.,..-.,--.,....,..,.---,-.-,.-..,--,-.,---,.--.,--.- +.-.,...,-,..-,...-,.--,-..-,-.--,--..] + GCODE A + TERMIN + GCODE -.--. + GCODE -.-..-.. + GCODE .-.-. + GCODE .-... + GCODE -.. . + +CDRUB: GCODE ........ + +EXPUNGE WRD,BIT + +] + IFN PLTP,[ + +SUBTTL CALCOMP PLOTTER ROUTINES + +PLOT: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +PLOT1: SKIPE A + CAIN A,EOFCH + POPJ P, + SKIPG PLBFS + JRST PLOTW1 +PLOTW2: IDPB A,PLPTR + MOVE A,PLPTR + CAMN A,[600,,PLBUF+LPLBUF-1] + HRRI A,PLBUF-1 + HRRM A,PLPTR + SOS PLBFS + AOSN PLON + CONO PLT,SDS+PLTCHN + POPJ P, + + PUSHJ P,PLOTW3 +PLOTW1: PUSHJ P,UFLS + JRST PLOTW2 + +PLOTW3: SKIPG T,PLBFS + POPJ P, + CAIL T,LPLBUF*5 + JRST POPJ1 + JRST POPJ3 + +BPLOT: MOVEI E,PLOT1 + JRST NBTOCH + +PLOTO: MOVEI Q,PLOTOC + PUSHJ P,STDOPN + POPJ P, + AOS (P) +PLOTEL: ;TELL WHO'S USING THE PLOTTER + BUG INFO,[PLOTTER USER],SIXBIT,UNAME(U),SIXBIT,JNAME(U) + POPJ P, + +PLOTOC: 1,,PLTUSR + PLTDN,,PLTBN + +PLTRS: MOVEI A,LPLBUF*6 + MOVE B,PLPTR + CONO PI,LPTOFF + MOVEM A,PLBFS + MOVEM B,PLIPTR + JRST LPTONJ + +PLTBRK: MOVE A,PLBFS + CAIN A,LPLBUF*6 + JRST PLSTP + AOS PLBFS + ILDB A,PLIPTR + MOVE B,PLIPTR + CAMN B,[600,,PLBUF+LPLBUF-1] + HRRI B,PLBUF-1 + HRRM B,PLIPTR + ANDI A,77 + LSH A,3 + TRO A,SDC+PDC+SD+PLTCHN + TRNE A,PUP+PDN + TRC A,SD#PD + CONO PLT,(A) + JRST LPTRT3 + + +PLSTP: CONO PLT,SDC+PDC + SETOM PLON + JRST LPTRT3 + +EBLK +PLBUF: BLOCK LPLBUF +PLON: -1 +PLPTR: 440600,,PLBUF +PLIPTR: 440600,,PLBUF +PLBFS: LPLBUF*6 +IPL: SIXBIT /IPL/ ;FILE NAME 2 OF IPL JOB (USED FOR LOADING ASO JNAME OF IPL JOB) +IPLU: 0 ;USER INDEX OF IPL JOB IF IT EXISTS OR -1 IF IPL BEING LOADED + +;INTERPRET PLOTTER OPEN ROUTINE +BBLK +IPLO: CONO PI,CLKOFF + PUSHJ P,IPLST ;INITIATE LOADING OF IPL JOB + JRST IPLO1 + PUSHJ P,PLOTEL + CONO PI,CLKOFF + PUSHJ P,IPLWT ;WAIT FOR IPL JOB TO FINISH LOADING + PUSHJ P,UFLS + MOVE T,IPLU ;INDEX OF IPL JOB + SKIPE IOCHNM(T) + JRST IPLO2 ;IPL JOB OPNS CLA ON CNNL 0 + MOVE T,SV40(T) + CAME T,[.SLEEP 17,] ;IPL JOB DOES SLEEP 17, WHEN READY +IPLO2: JRST OPNL10 ;DEVICE NOT AVAILABLE + CONO PI,CLKON + MOVE T,IPLU + MOVE A,UNAME(T) ;SET UP CLI OPEN + MOVSI B,(SIXBIT /IPL/) + PUSHJ P,CLIO + POPJ P, + MOVE A,UTMPTR(U) + MOVE B,IPLU + MOVEM A,UTMPTR(B) + JRST POPJ1 + +IPLO1: PUSHJ P,UDELAY + JRST IPLO + +IPLST: SKIPL T,IPLU ;MAKE SURE IPL JOB NOT ALREADY BEING LOADED + PUSHJ P,IPLIN ;MAKE SURE IPL JOB NOT ALREADY IN + JRST POPJ1 ;DONT LOAD + HRROI T,IPL + CONO PI,UTCOFF + PUSHJ P,NUJBST + JRST UTCONJ + JRST UTCOJ1 + +;ROUTINE TO SEE IF IPL JOB WINS. CLKOFF OR CLKBRK IN PROGRESS +IPLWT: SKIPGE T,IPLU ;CHECK IPL JOB LOADING FLAG + POPJ P, ;IPL JOB STILL LOADING WAIT + PUSHJ P,IPLIN ;SEE IF IPL JOB IN CORE + SKIPE IOCHNM(T) ;SEE IF IPL JOB IN USE + JRST POPJ1 ;LOSE + MOVE T,SV40(T) ;SEE IF IPL JOB READY + CAMN T,[.SLEEP 17,] ;IPL JOB DOES .SLEEP 17, WHEN READY + AOS (P) ;READY WIN + POPJ P, ;NOT READY YET, WAIT + +IPLIN: PUSH P,U ;ROUTINE TO SEE IF IPL JOB IN. C(T)=C(IPLU), CLKOFF OR CLKBRK IN PROGRESS + CAML T,USRHI + JRST IPLIN1 ;USER VARIABLES SLOT FLUSHED + HLRO U,UNAME(T) + AOJN U,IPLIN1 ;UNAME OF IPL JOB IS -1 (IN LH) + MOVSI U,(SIXBIT /IPL/) + CAME U,JNAME(T) +IPLIN1: AOS -1(P) ;IPL JOB NOT IN, SO SKIP + POP P,U + POPJ P, + +] +;UTC MUST BE OFF! +NUJBST: MOVEI TT,MXCZS ;ENTRY FROM ELSEWHERE TO DO SIMILAR THINGS + SKIPL DEDTIM ;SKIP IF SYS DEAD + CAMG TT,UTTYCT + POPJ P, ;RING BUFFER FULL, WAIT + MOVEM T,@UTTYI + AOS UTTYCT + AOS TT,UTTYI + CAIL TT,UTTYS+MXCZS + MOVEI TT,UTTYS + MOVEM TT,UTTYI + SETOM 1(T) ;SET JOB LOADING FLAG + JRST POPJ1 + +SUBTTL PDP-6 AS INFERIOR + +IFN PDP6P,[ +;.IPDP CH, +;INTERRUPT THE PDP6, I/O CH SHOULD HAVE PDP6 OPEN AS INFERIOR +;THIS CALL DOESNT SKIP OR INTERRUPT TO THE USER + +AIPDP: MOVSI T,%CLS6 + SKIPGE A,(R) + TDNN T,CLSTB(A) + POPJ P, + CONO PI,LPTOFF + CONI DSDEV,T + ANDI T,7 + CONO DSDEV,20(T) + JRST LPTONJ + +;PDP-6 DEVICE +;INTERRUPT FROM PDP6, MAYBE GENERATE IO CHANNEL USER INTERRUPT + +DSDBRK: CONO DSDEV,10 ;TURN OFF FLAG + ;ALSO KEEP IT FROM INTERRUPTING FOR A WHILE + ;GETS TURNED ON AT DISMISS, SETOM PICLR AND SLOW CLK + SKIPGE A,PDPISR + JRST LPTRT3 ;NO ONE WANTS AN INT + MOVE B,PDPMSK + AND B,MSKST2(A) + MOVNM B,PDPTMP + AND B,PDPTMP + IORM B,IFPIR(A) ;GENERATE USER INT + JRST LPTRT3 + + ;PDP6 .OPEN ROUTINE (GET HERE FROM USR OPEN) + +PDPO: SKIPL PDP6UP ;MAKE IT EASY TO MARK PDP6 AS DOWN. + JRST OPNL10 + TLNN C,20 + JRST PDPO1 ;DON'T TRY TO ENABLE INTERRUPTS + TLO C,400000 ;TRY TO ENABLE INTERRUPTS + SKIPL PDPISR + CAMN U,PDPISR + JRST PDPO1 + JRST OPNL12 + +PDPO1: PUSH P,U + PUSHJ P,PDPO2 + JRST POPUJ + AOS -1(P) + POP P,U + SKIPL (R) + JRST .+3 + AOS PDPISE + MOVEM U,PDPISR;GOT IT AS INFERIOR + PUSHJ P,LSWPOP ;RELEASE TREESW + MOVEI I,1 ;DO "IOPOP" INTO CHNL + +PDPIOP: SKIPL (R) + POPJ P, ;NOT OPEN TO INTERRUPT + SUBI R,IOCHNM(U) + MOVE A,CHNBIT(R) + ADDI R,IOCHNM(U) ;RESTORE R + XCT PDPIOT(I) + POPJ P, + +PDPIOT: ANDCAM A,PDPMSK + IORM A,PDPMSK + +PDPCLS: MOVEI I,0 ;CLOSE + PUSHJ P,PDPIOP ;=> DO "IOPUSH" +PDPCL1: CONO PI,CLKOFF + SOSGE PDPUSE + SETOM PDPUSR ;LAST CHANNEL CLOSED + SKIPL (R) + JRST CLKONJ ;NOT INTERRUPT ENABLED THIS CHNL + SOSGE PDPISE + SETOM PDPISR ;LAST CHANNEL CLOSED + JRST CLKONJ + + +PDPO3: MOVEI U,(A) ;MAKE U INDEX OF SUPERIOR +PDPO2: SKIPL A,SUPPRO(U) ;GET POINTER TO SUPERIOR, SKIP IF TOP LEVEL + JRST PDPO3 ;TRY AGAIN + HLRZ D,C + TLO C,200000 ;SIGNAL PDP6 TO UBI ETC + JSP Q,STDOPN + 3,,PDPUSR + PDPUII,,PDPUIO + PDPBII,,PDPBIO + +;.UCLOSE PDP6 +PDPUCL: MOVSI C,%CLS6 ;GET PDP6 CLSTB BIT + MOVEI R,IOCHNM(U) ;GET PNTR TO USER'S IO CHNL AREA + HRLI R,-20 ;MAKE AOBJN PNTR TO ALL CHNLS + PUSHJ P,PDPCCK ;CHECK CHNL + PUSHJ P,PDPCZP ;CLOSE CHNL IF PDP6 OPEN ON IT + AOBJN R,.-2 ;REPEAT FOR ALL CHNLS + HRLI R,-LUIOP/2 ;MAKE AOBJN PNTR TO IO PDL (ADR ALREADY THERE) + PUSHJ P,PDPCCK ;CHECK ENTRY FOR PDP6 + PUSHJ P,PDPPZP ;CLEAR ENTRY IF PDP6 CHNL + AOJ R, ;INCR TO SKIP IOCHST ENTRY + AOBJN R,.-3 ;REPEAT FOR WHOLE IO PDL + POPJ P, ;ALL PDP6 CHNLS THIS JOB SHOULD NOW BE CLOSED + +PDPCCK: HRRZ B,(R) ;GET CLSTB INDEX FROM IOCHNM + TDNN C,CLSTB(B) ;IF NOT PDP6 CHNL + AOS (P) ;SKIP CLOSING CHNL + POPJ P, + +;CLOSE PDP6 USER CHNL +PDPCZP: PUSHJ P,PDPCLS ;ADJUST PDP6 VARS + JRST STDCLX ;CLOBBER CHNL & RETURN + +;CLEAR PDP6 IO PDL ENTRY +PDPPZP: PUSHJ P,PDPCL1 ;ADJUST PDP6 VARS (EXCEPT PDPMSK) + SETZB A,(R) ;CLEAR SAVED IOCHNM + DPB A,[4000,,1(R)] ;CLEAR SAVED IOCHST (SAVING CHNL # FOR .IOPDL) + POPJ P, + PDPCLR: OFFSET 20-. ;ROUTINE TO BE MOVED + CONO PI,11577 ;CLEAR PI + CONO 655550 ;CLEAR PROCESSOR + DATAO 20,.+1 ;RELEASE DEVICES + SETZ ;CLEAR 0, ALSO BIT FOR DEASSIGNMENT (^) + HRRZI 1,1 ;BLT POINTER 0,,1 + BLT 1,41 ;CLEAR AC'S, SELF, AND 41 +PDPCLE==. + OFFSET 0 ;BACK TO NORMAL +EBLK + +PDPTMP: 0 ;TEMP FOR INT +PDPMSK: 0 ;MASK OF INT BITS OF CHNLS OPEN + +BBLK + +PDPRST: PUSHJ P,MP6LD + MOVE C,[400020,,400021] + XCTR XW,[CLEARM 400020] + XCTR XBRW,[BLT C,437777] + MOVE C,[PDPCLR,,400020] + XCTR XBW,[BLT C,400000+PDPCLE-1] + MOVE C,[JRST 20] + UMOVEM C,400041 + PUSHJ P,UDELAY + UMOVE A,400041 + JUMPE A,PDPRS2 ;JUMP ON ROUTINE WON, DON'T HAVE TO CLEAR IT OUT + XCTR XW,[CLEARM 400020] + MOVE C,[400020,,400021] + XCTR XBRW,[BLT C,400041] +PDPRS2: JRST MPLDZ +];IFN PDP6P + +SUBTTL DL10MP SYSTEM CALL + +IFN DL10P,[ +;.CALL DL10MP +; ARG 1 - PAGE # +;CREATES A READ/WRITE, UNENCACHED, ABSOLUTE PAGE AT THAT POINT +;IN THE USER'S MAP. THE PAGE CONTAINS THE DL10 CONTROL AREA. +; VAL 1 - AOBJN POINTER TO DL10 CONTROL AREA WITHIN PAGE +; VAL 2 - POINTER TO 3 WORDS USED FOR PDP11 EXAMINE/DEPOSIT COMMANDS +; VAL 3 - POINTER TO FIRST FREE WORD WITHIN DL10 CONTROL AREA + +DL10MP: TDNE A,[-400] + JRST OPNL33 ;PAGE NUMBER TOO BIG + PUSHJ P,UPLC + LDB C,Q ;GET CIRC POINTER + CAIE C,-1 + JUMPN C,OPNL13 ;PAGE SLOT ALREADY IN USE + BUG INFO,[DL10MP BY],SIXBIT,UNAME(U),SIXBIT,JNAME(U) + MOVEI C,600000+ ;SUITABLE PTW + DPB C,T + MOVEI C,-1 ;ABS CIRC PNTR + DPB C,Q + CLRPGM (U) + LSH A,10. ;USER'S VIRTUAL ADDRESS + ADDI A,2000 + CAMLE A,HUSRAD(U) + MOVEM A,HUSRAD(U) + SUBI A,2000- ;VIR ADDR OF START OF DL10 CONTROL AREA + HRLI A,-100 ;SIZE OF DL10 CONTROL AREA + MOVEI B,DL10XD-DL10AR(A) + MOVEI C,DLXEND-DL10AR(A) + JRST POPJ1 +];DL10P + +SUBTTL TRAP DEVICE + +;.CALL TRPOPN +; ARG 1 - SPEC +; ARG 2 - CHANNEL NUMBER IN THAT JOB TO BE OPENED AS TRAP DEVICE +; ARG 3 - IOCHNM WORD (ONLY LH IS USED) +; ARG 4 - IOCHST WORD +;THIS GIVES THE INFERIOR A TRAP DEVICE CHANNEL, WHICH GIVES +;A %PITRP INTERRUPT ON MOST OPERATIONS. THE INFERIOR SIGNALS +;ITS DESIRE TO GET SUCH A CHANNEL BY OPENING THE TRAP DEVICE, +;WHICH ALSO GIVES A %PITRP INTERRUPT. +;TRPOPN IS ALSO USEFUL FOR STORING ERROR CODES INTO IOCHST OF AN ALREADY-OPEN TRAP CHANNEL + +TRPOPN: TDNE B,[-NIOCHN] + JRST OPNL14 ;BAD CHANNEL NUMBER + MOVE J,A + JSP T,NCORUI + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 +];PDP6P + JSP T,NCORWR + JRST OPNL31 ;CAN'T MODIFY JOB + ADDI B,IOCHNM(J) ;GET IOCHNM WORD ADDRESS + HRRZ T,(B) + CAIE T,DNTRAP + JUMPN T,OPNL13 ;FILE ALREADY EXISTS (YOU MUST CLOSE THE CHANNEL FIRST) + HRRI C,DNTRAP + MOVEM C,(B) + MOVEM D,IOCHST-IOCHNM(B) + JRST LSWPJ1 ;UNLOCK DIELOK, TAKE SUCCESS RETURN diff --git a/src/system/itsdis.50 b/src/system/itsdis.50 new file mode 100755 index 00000000..73302f14 --- /dev/null +++ b/src/system/itsdis.50 @@ -0,0 +1,320 @@ + +;DEVICE CODES +DIS==130 ;DISPLAY PROCESSOR +DISMAP==134 ;MEM PROT & REL +LIPSH==(040000) +NWSTK==LIPSH 3, + +ADSTAR: CONO PI,CLKOFF ;TURN OFF CLOCK TO PREVENT POSSIBLE GOBBLING BY ANOTHER USER + PUSHJ P,DISCHK ;CHECK IF THIS USER OWNS THE DISPLAY + JRST CLKONJ ;RESTART THE CLOCK + SETZM E.SPGH ; QSWI1 switch + SETZM E.SCLS ; clear clobber switch + SKIPL DISUSR ; no user + CAMN U,DISUSR ; skips if different index + JRST NOCLBR ; dont untie pages + MOVEM U,E.SCLS ; else remember to untie + SKIPA ; and dont hack disusr +NOCLBR: MOVEM U,DISUSR ;GIVE IT TO HIM IF NO ONE ELSE OWNS IT + CONO PI,CLKON ;RESTORE THE CLOCK + CONO DIS,5010 ;SET STOP, CLEAR PIA + XCTR XR,[HRRZ A,(C)] ; causes pg ld, fetches droot + HRRM A,DSTADD ; remember for restarts + XCTR XR,[MOVE B,(A)] ; load display page + PUSHJ P,SWTL ; circular switch gobble + CIRPSW + LSH A,-10. ; page number + SKIPN E.SCLS ; clobbering old user index ? + JRST RDSCLB ; if not, skip it + MOVE U,DISUSR ; old useri + PUSHJ P,E.SCLB ; untie pages + MOVEI U,0 + EXCH U,E.SCLS ; clear switch, fetch new usri + MOVEM U,DISUSR +RDSCLB: PUSHJ P,UPLC ; users pg n into circular pointer + PUSHJ P,CHACK ; go in circles + SKIPL C ; 4.9 implies real core in loop + JRST NOTIED ; if not, dont tie down -- still swapped out + MOVE T,J ; MEMPNT INDEX + MOVE E,D ; MMP INDEX + PUSHJ P,E.SPG1 ; go tie it down +NOTIED: PUSHJ P,LSWPOP ; clear switch + ; now set up E&S dbrs + MOVEI T,UDBR1A(U) + HRLI T,_1 ;DBL left 1 relative to 10 + MOVEM T,E.SPM+2 + HRRI T,UDBR2A(U) + MOVEM T,E.SPM+3 + + ; now start (or restart if from E.SPGI) E&S + +RDSTAR: CONO DIS,515330 ;RESET THE WORLD + SETOM E.SSYS ;FLAG=MAP ON (USER MODE) + CONO DIS,515330 ;CLEAR 3D CLIPPER + MOVEI I,1000 ;SET COUNT FOR TIMEOUT + MOVE H,DSTADD ; fetch c(0) + MOVEM H,E.SPM ; store in status block + MOVSI H,140000 ; status bits -- map high and low + MOVEM H,E.SPM+1 ; set status + SKIPA H,[-ADSTN,,ADSTL-1] + BLKO DIS,H + CONSO DIS,604000 ;SKIP IF DONE OR ERROR + SOJG I,.-1 + JUMPL H,.-3 + JUMPE I,CPOPJ ;FAIL IF TIME OUT ON START + CONSZ DIS,600000 ;CHECK FOR EXECUTIVE ERRORS + JRST ADXIT ;GIVE INTERRUPT, NO SKIP + + AOS (P) +ADCON1: CONO DIS,400 ;RUN +ADXIT: CONO DIS,222010+DISCHN ;ALARM+MPV+STOP+PIA + POPJ P, + +ADSTPX: CONSZ DIS,1040 ;FAIL TO SKIP IF MEM OR SEL STOP + JRST ILUUO ;ERROR IF STOP +ADSTOP: CAME U,DISUSR ;SKIP IF USER OF SCOPE + JRST URET ;EXIT IF NOT SCOPE USER +ADSTPY: CONO DIS,5000 ; IOSTOP+STOP.INT.OFF + CONO DIS,300 ;LR.PROG+CLR.HIT + CONSO DIS,640000 ;SKIP IF PARITY, NXM, MPV ON + JRST E.SUSM ;MAP IS STILL ON + CONO DIS,400000 ;CLEAR MASTER STUFF (TURNS OFF MAP) + CONO DIS,400000 ;CLEAR 3D CLIPPER + + AOS E.SSYS ;REMEMBER PAGING IS OFF +E.SUSM: CONSO DIS,4000 ;SKIP IF STOPPED AND READY + PUSHJ P,UFLS ;ELSE WAIT UNTIL READY + POPJ P, + +ADCONT: PUSHJ P,ADSTPX ;ILLEGAL IF MEM OR SEL STOP + PUSHJ P,E.SFU ; force user mode if necessary + POPJ P,0 ; gross lossage (hardware) + JRST ADCON1 + +ADSTEP: PUSHJ P,ADSTPX ;ILLEGAL IF MEM OR SEL STOP + PUSHJ P,E.SFU ; Force User mode (reloads map and skips) + POPJ P,0 ; lossage if here + CONO DIS,40 + POPJ P, + +ADWORD: XCTR XR,[MOVE J,(J)] ; fetch c(AC) + PUSHJ P,ADSTOP ;MAKE SURE IT IS STOPPED + PUSHJ P,E.SFU ;RELOAD MAP IF NECESSARY + POPJ P,0 ;MAP NOT IN USER MODE + DATAO DIS,J + POPJ P, + +ADCLOS: CAME U,DISUSR + POPJ P, + CONO DIS,5010 ;STOP, PI OFF + SETZM E.SPGW ;CLEAR PAGE WAIT + PUSHJ P,SWTL ;LOCK CIRCULAR SWITCH + CIRPSW + PUSHJ P,E.SCLB + PUSHJ P,LSWPOP ;RESTORE SWITCH + SETOM DISUSR + POPJ P, + +DISCHK: MOVE B,UNAME(U) + SKIPL T,DISUSR + CAMN B,UNAME(T) + AOS (P) + +ADRSTA: ;READ STATE, WRITE STATE NOT IN. +ADSSTA: POPJ P, + +;E&S PAGER HAS TO REFERENCE 0 TO INITIALLIZE MAP. +;E&S FORCE USER MODE + +E.SFU: SKIPGE E.SSYS + JRST POPJ1 ;SKIP IF MAP OFF +E.SFU2: MOVSI T,140000 ;ENTRY FOR DCRRST + MOVEM T,E.SPM+1 ;RESETS STATUS + DATAO DIS,[NWSTK 1] ;STORE SP AT 0 + PUSHJ P,E.SWT ;CANNOT UFLS -- NWSTK MIGHT BE REISSUED + POPJ P,0 ;HARDWARE LOSSAGE + DATAO DIS,E.SPM ;OUTPUTS C(0) (RELOADS SP) + PUSHJ P,E.SWT + POPJ P,0 ;LOST + SETOM E.SSYS ;REMEMBER MAP ON + JRST POPJ1 + +E.SWT: PUSH P,J + MOVEI J,100 ;COUNT FOR TIMEOUT + CONSZ DIS,4000 ;STOPPED AND READY? ELSE SKIP + JRST POPJJ1 ;SKIP RET IF READY + CONSO DIS,640000 ;OTHER FLAVORS OF LOSSAGE + SOJG J,E.SWT+2 ;COUNT IF STILL OK + CONO DIS,10 ;STOP FOR GOOD + JRST POPJJ ;LOSES, NO SKIP RETURN + +ADSTL: 000501052405 ;LI DIR,052405(PROGM) + 300541,,[-1,,] ;LOCLA SELINT,[-1,,](1) + 300441,,[102521,,] ;LOCLA CDIR,[102521,,](1) + 302641,,[3777,,3777] ;LOCLSA VIEW,[3777,,3777](1) + 302701,,[377777377777] ;LOCLSA WIND,[377777377777](1) + 100,,0 ; (JMP 0) load page map and go +ADSTN==.-ADSTL +EBLK + +DSTADD: 000100,, ;JMP TO CODE (FILL IN ADDRESS) + +; E&S PAGE MAP STATUS BLOCK +E.SPM: 0 ; c(0) + 0 ; status word + 0 ; dbr low + 0 ; dbr high + +MXDISP==16. ; maximum number of tied pages +DISPGP: -MXDISP,,0 ; page pointer for mmp pages +DISSWP: BLOCK MXDISP ; MMSWP INDICES TIED +E.SPGW: 0 ; if non zero, E&S page wait page +E.SPGH: 0 ; flag for QSWI1 +E.SCLS: 0 ; if non zero, new userI flushing disusr +E.SSYS: 0 ; flag for pager on/off +E.SIST: 0 ; ststus word at last interrupt + +; counts for debugging + +E.SNTI: 0 ; # pages tied down (total during system run) +E.SNUT: 0 ; # pages untied (should = .-1 after dclose) + +E.SREL: 0 ; # times pages in DISSWP table were relocated + +; end of debug counts + + +DSTPCT: -1 ; STOP COUNT TO HANDLE REDUNDANT STOPS +DSCONI: 0 ;LAST CONI FROM DISPLAY +EBRKA: 0 ;INTERRUPT SAVE AC +EBRKU: 0 ; DITTO + +ESBRK: 0 ;HANDLE E&S INTERRUPT + +BBLK + + CONSO DIS,7 ;PI CHAN ASSIGNED? + JRST 12,@ESBRK ;NO, CANNOT INTERRUPT + CONI DIS,DSCONI + CONO DIS,10 ;DEASSIGN PI CHANNEL + MOVEM U,EBRKU ;SAVE AC'S + MOVEM A,EBRKA + MOVEI A,%PILTP ;GIVE "LTPEN" INT (CLASS 3) + CONSZ DIS,640040 ;PAR, NXM, MPV, SELECT + JRST E.SFLT ; check page fault +E.SUIN: SKIPL U,DISUSR + IORM A,PIRQC(U) +E.SPFR: MOVE A,EBRKA ;UNSAVE AC'S + MOVE U,EBRKU + JRST 12,@ESBRK ;RETURN + +E.SFLT: CONSZ DIS,200000 ; skip if not NXM (ie not fault) + SKIPL E.SPM+1 ; error bit set in status word ? + JRST E.SILM ; if not, real illegal mem + LDB U,[121000,,E.SPM+1] ; get page # + HRROM U,E.SPGW ; save for loading (LH is flag) + MOVE U,E.SPM+1 ; get status + MOVEM U,E.SIST ; save status for later (debugging) + LDB U,[330300,,U] ; access and pgerr + CAIE U,2 ; read write/first error + SKIPN U ; no access -- page fault + JRST E.SPFR ; gives a page fault +E.SILM: SETZM E.SPGW ; if not page fault, don't rq load + MOVEI A,%PIDIS; mem fault bits + JRST E.SUINT ; give user interrupt + +DCRSTP: CAMN U,DISUSR ;IS THIS U ON DIS + AOSE DSTPCT ; HERE IF THIS USER, SKIP IF FIRST CALL TO STOP + POPJ P, ;RETURN IF NOT + CONSO DIS,7 ; SKIP IF CURRENTLY RUNNING + POPJ P, ; RETURN IF NOT RUNNING NOW + CONI DIS,DSCONI ;SAVE STATE FOR RESTART + CONO DIS,5000 ;OTHERWISE STOP IT +DISSTQ: MOVEI TT,100 + CONSO DIS,4000 ;SKIP IF STOP ACTUALLY TAKES HOLD + SOJG TT,.-1 ;TIME-OUT LOOP + JUMPG TT,CPOPJ ;DID NOT TIME OUT, OK + CONO DIS,10 ;DISABLE DISPLAY (CLEAR PIA) + AOS DISSTQ ;CAUSE "SYSTEM CLOBBERED" ... ON SYS CONSOLE + POPJ P, + + +E.SLPM: PUSHJ P,DCRSTP ; stop before loading page map +DCRRST: CAMN U,DISUSR ;IS THE CURRENT U ON DISPLAY? + SOSL T,DSTPCT ; SKIP IF LAST START CALL, (FROM MORE THAN 1 STOP) + POPJ P, ;NO + AOSE T ;SKIP IF ONLY ONE STOP + JRST 4,. ;SOME ONE IS OUT OF PHASE! + MOVE T,DSCONI + CONSZ DIS,7 ;SKIP IF NOT RUNNABLE + TRNE T,4000 ;1=> WAS STOPPED + POPJ P, ;SO QUIT + PUSHJ P,E.SFU2 ; load E&S page map + POPJ P,0 ; lost somehow + CONO DIS,400 ;ELSE SET RUN + CONO DIS,2000 ;THEN ALLOW STOP INT + POPJ P, + + ; tie down hacks + +;E.SPCH checks MMSWP ind in T against DISSWP +; R0 if already there, R1 if not. ret index in H + +E.SPCH: MOVSI H,-MXDISP + CAMN T,DISSWP(H) + POPJ P,0 ; found + AOBJN H,.-2 ; look some more + JRST POPJ1 ; not found, skip + +E.SCLB: MOVSI H,-MXDISP + SKIPE T,DISSWP(H) ; VALID IF NON-ZERO + PUSHJ P,UNTIE ; UNTIE PAGE IN T (MMSWP INDEX) + AOBJN H,E.SCLB+1 + POPJ P,0 + +; UNTIE PG T/ MMSWP index +; H/ display table index + +UNTIE: AOS E.SNUT ; count unties + PUSH P,H + MOVSI H,-1 + ADDB H,MMSWP(T) ; sos # exec pgs + SKIPGE H ; if less than zero, untied an untied page + JRST 4,. ; exec pg count < 0 + POP P,H + SETZM DISSWP(H) ; clear table entries + POPJ P,0 + +; ties down page. T/ MMSWP ind. + +E.SPG1: SKIPL MEMBLT(T) ; frozen, so dont tie + PUSHJ P,E.SPCH ; skips if not there + POPJ P,0 ; dont tie + AOS E.SNTI ; count number of ties. + MOVSI H,1 + ADDM H,MMSWP(T) ; aos # exec pgs + MOVE H,DISPGP ; fetch dis pg pointer + AOBJN H,.+2 + MOVSI H,-MXDISP ; reset pointer if table full + MOVEM H,DISPGP ; update pointer + PUSH P,T ; now checks if slot in use + SKIPE T,DISSWP(H) + PUSHJ P,UNTIE ; untie page in T + POP P,T + MOVEM T,DISSWP(H) ; remember mmswp ind + POPJ P,0 + +; E.SPGI called from CFHPI on page in core after fault + +E.SPGI: SKIPGE U,DISUSR + JRST 4,. ; why here ? + HRRO I,CFHUVP ; user virtul page from CFH... + CAME I,E.SPGW ; is the sam as E&S rq ? + POPJ P,0 ; no, return + SETOM E.SPGH ; set flag for QSWI1 (read/write/first hack) + PUSHJ P,E.SPG1 ; tie down + SETZM E.SPGW ; clear page wait + PUSHJ P,RDSTART ; restart display + POPJ P,0 + POPJ P,0 ; skip return from rdstart if wins + \ No newline at end of file diff --git a/src/system/itsmsp.30 b/src/system/itsmsp.30 new file mode 100755 index 00000000..fb93252f --- /dev/null +++ b/src/system/itsmsp.30 @@ -0,0 +1,315 @@ +;.OPEN CHNL,PNTR1 + +;PNTR1: MODE,,(SIXBIT /NET/) +; PNTR2 +; MYNAME1 +; MYNAME2 + +;PNTR2: HISNAME1 +; HISNAME2 +; COUNT +; buffer + +;MODES=> BITS 3.1== READ FROM ANY +; 3.2== READ FROM SPECIFIC +; 3.3== SEND AND HANG +; 3.4== SEND IMMEDIATE +; 3.5== USE UNAME JNAME AS MY1 AND MY2 +; 3.6== USE UNAME AS HIS1 + +;OPEN FAILURES: +; 4 HIS NAME 1 & HIS NAME 2 WERE ZERO +; 6 TABLE FULL +; 7 ON WRITE, RELOCATION OF READ BUFFER FAILED +; 11 ATTEMPT TO SEND TO SELF +; 12 NOT A LEGAL MODE +; 20 SEND IMMEDIATE, GUY WASN'T THERE +; 22 BUFFER NOT IN YOUR CORE IMAGE + + +EBLK + +MSENTS==40 ;# OF ENTRIES IN THE TABLE + +MSUSER: BLOCK MSENTS ;USER INDEX +MSCHNL: BLOCK MSENTS ;USERS CHANNEL +MSBADR: BLOCK MSENTS ;RELATIVE ADDRR OF USER'S BUFR +MSBCNT: BLOCK MSENTS ;SIZE OF USERS BUFFER + +MSWRIT: BLOCK MSENTS ;SENDING NAME 1 +MSWRT2: BLOCK MSENTS ;SENDING NAME 2 +MSREAD: BLOCK MSENTS ;READING NAME 1 +MSRED2: BLOCK MSENTS ;READING NAME 2 + +MSPSW: -1 ;SWITCH FOR MSP VARIABLES + 0 ;EXTRA WORD, FOR SWTL ROUTINE + +BBLK + + IPCO: PUSHJ P,SWTL ;LOCK THE MSP SWITCH + MSPSW + TLNE C,1 ; read from any? + JRST MSRA ; yes + TLNE C,2 ; read from specific? + JRST MSRS ; yes + TLNE C,4 ; send and hang? + JRST MSSH ; yes + TLNE C,8 ; send immediate? + JRST MSSI ; yes + JRST OPNL12 ; none of the above + +; read from any (RA) and read from specific (RS) +MSRA: SETOM H ; H/-1 =>RA 0=>RS + SKIPA +MSRS: SETZM H + +; find first free user slot + MOVSI W,-MSENTS ; W/ slot index +MSR1: SKIPG MSUSER(W) ; is this slot free? + JRST MSR2 ; yes + AOBJN W,MSR1 + JRST OPNL6 ; no free slots, device full + +; W/ slot index of a free slot +MSR2: MOVEM U,MSUSER(W) ; occupies this slot +; make sure we have a legal buffer + HRRZ D,A ; relative address of second buffer + MOVEI E,3(D) ; E/ relative address of data area + XCTR XRW,[MOVES (D)] ;CHECK COUNT FETCH? + XCTR XRW,[MOVES TT,2(D)] ;CHECK ACTUAL COUNT PLACE + +; bufr ok, now put data in table + MOVEM E,MSBADR(W) ; stores buffer address + MOVEM TT,MSBCNT(W) + +; store sender name only if RS + JUMPL H,MSR3 + XCTR XR,[MOVE TT,(D)] ; his name 1 + XCTR XR,[MOVE I,1(D)] ; his name 2 + TLNE C,40 ; his1 = UNAME? + MOVE TT,UNAME(U) ; yes + SKIPA +MSR3: SETZB TT,I ; zero if RA + MOVEM TT,MSWRIT(W) + MOVEM I,MSWRT2(W) + +; 3.5 bit in C means use UNAME JNAME as myname1 and myname2 + TLNN C,20 ; skips if want default + JRST .+4 + MOVE TT,UNAME(U) + MOVE I,JNAME(U) + JRST .+3 + ; else me1 is in B and me2 is in SRN3(U) + MOVE TT,B + MOVE I,SRN3(U) + MOVEM TT,MSREAD(W) + MOVEM I,MSRED2(W) + + MOVEI TT,(R) ;GET CHANNEL + SUBI TT,IOCHNM(U) + MOVEM TT,MSCHNL(W) ;STORE FOR LATER INTERRUPT + + PUSHJ P,LSWPOP ;UNLOCK MSP SWITCH + +; now put tabl index in lh of IOCHNM(U)(R) + HRLZ A,W + JSP Q,OPSLD1 + MSPIO,,MSPIO ; attempted IOT will get IOCER 10. + ; send and hang (SH) and send immediate (SI) +MSSI: SETOM H ; H/-1=>SI 0=>SH + SKIPA +MSSH: SETZM H + +; validate his buffer specs + HRRZ D,A ; relative buffer address + MOVEI E,3(D) ; E/ relative data addr + XCTR XRW,[MOVES (D)] ;CHECK NAME + XCTR XRW,[MOVES Q,2(D)] ;CHECK COUNT + +; other data + ; E/ absolute data addr + ; Q/ count + XCTR XR,[MOVE T,(D)] ; T/ his name 1 + TLNE C,40 ; 3.6 bit means use UNAME + MOVE T,UNAME(U) ; yes + XCTR XR,[MOVE TT,1(D)] ; TT/ his name 2 + JUMPN T,.+3 ; T and TT can not both be zero + SKIPN TT + JRST OPNL4 + MOVEM TT,EPDL(U) ; EPDL(U)/ hisname2 + +; 3.5 bit in C means use UNAME JNAME as myname1 and myname2 + TLNN C,20 ; skips if wants default + JRST .+4 + MOVE TT,UNAME(U) + MOVE I,JNAME(U) + JRST .+3 + ; else myname1 is in B and myname2 is in SRN(U) + MOVE TT,B + MOVE I,SRN3(U) + MOVEM TT,EPDL3(U) ; EPDL3/ myname1 + MOVEM I,SRN4(U) ; SRN4/ myname2 + +; see if entry is in the table + PUSHJ P,MSSTBL + SKIPA ; no, will havee to wait + JRST MSS2 ; yes, service the transfer + JUMPL H,OPNL20 ; was an SI, lose +MSS1: XCTR XR,[MOVE T,(D)] ; in case it got munged + TLNE C,40 ; 3.6 bit means use UNAME + MOVE T,UNAME(U) + + +; wait for entry to appear in table +MSDM3: PUSH P,T ;LSWPOP CLOBBERS T + PUSHJ P,LSWPOP ;UNLOCK MSPSW FOR WAITING + MOVE T,(P) ;RESTOR T + SKIPA ; forces a call to ufls + PUSHJ P,MSSTBL + PUSHJ P,UFLS ; hang . . . . + PUSHJ P,SWTL ;RELOCK SWITCH NOW + MSPSW + POP P,T ;RESTORE T AFTER CLOBBERING BY SWTL + PUSHJ P,MSSTBL ; read has been done, get details + JRST MSS1 ; oops, must have been aborted + +; FALLS THRU IF MSSTBL SKIPS +; table index of the user is now in T +MSS2: MOVE H,T ; H/ table index + MOVE A,MSUSER(H) ; A/ user index + CAMN A,U + JRST [PUSHJ P,LSWPOP ;POP MSPSW + JRST OPNL11] + PUSHJ P,RPCLSR ; stop or i'll shoot + PUSHJ P,SOSSET ;SET TO SOS USTP(A) ON PCLSR + USTP(A) + +; get the absolute address of the read data buffer +MSS3: MOVE A,MSBADR(H) ; relative +;SET UP PAGE MAP FOR RECEIVER (USER IN MSUSER(H)) + PUSH P,R + MOVE J,MSUSER(H) ;USER TO RECEIVE + PUSHJ P,MPLDJ ;LOAD MAP +; fix count (sender cnt in Q, receiver cnt in MSBCNT(H)) + CAMG Q,MSBCNT(H) ; will it fit? + JRST MSS4 ; yes + XCTRI XRW,[SETOM -1(A)] ; no, indicate overflow will be lost + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + MOVE B,MSBCNT(H) ; B/ count + JRST MSS5 +MSS4: MOVE B,Q ; B/ count + MOVE TT,MSBCNT(H) + SUB TT,B + XCTRI XRW,[MOVEM TT,-1(A)] ; amount that will be xfered + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + +; if MSWRIT was zero (RA), fill it in +MSS5: SKIPN MSWRIT(H) + SKIPE MSWRT2(H) + JRST MSS6 + MOVE TT,EPDL3(U) + XCTRI XRW,[MOVEM TT,-3(A)] ; read's him1 + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + MOVE TT,SRN4(U) ; + XCTRI XRW,[MOVEM TT,-2(A)] ; read's him2 + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + +; RESTORE USER MAP TO CURRENT USER +MSS6: PUSHJ P,MPLDZ + POP P,R +; XFER => B/ CNT A/READ BUFR E/WRIT BUFR J/UNRELOCATED BUFFER (READ) + HRRM A,IOCHST-IOCHNM(R) ;STORE RECEIVER ADDRESS FOR UBO + MOVN W,B ;-COUNT + MOVSS W ;-COUNT,, + HRR W,E ;-COUNT,,ADR + MOVE C,[SETZ W] ;POINTER FOR UBO + MOVE A,MSUSER(H) ;GET OTHER USERS NUMBER FOR UBO + PUSHJ P,UBO ;USER BLOCK OUTPUT - DO WRITE TRANSFER + +; RESTART THE LOSER + PUSHJ P,LSWPOP ;UNDO RPCLSR (SOS USTP(MSUSR(H))) + MOVE A,MSUSER(H) ;GET TARGET USER + MOVE B,MSCHNL(H) ;CHANNEL HE OPENED + MOVE B,CHNBIT(B) ;BIT CORRESPONDING TO CHAN + TDNE B,MSKST2(A) ;SKIP IF NOT ENABLED + IORM B,IFPIR(A) ;SET HIS INTERRUPT + +; flush read entry from the table + SETZM MSCHNL(H) + SETZM MSREAD(H) + SETZM MSRED2(H) + SETZM MSWRIT(H) + SETZM MSWRT2(H) + SETZM MSBADR(H) + SETZM MSBCNT(H) + SETZM MSUSER(H) + + PUSHJ P,LSWPOP ;UNLOCK MSPSW + +; end open + SETOM A ; LH IOCHNM==-1 MEANS SEND (FOR CLOS) + JSP Q,OPSLD1 ;DOES POPJ BACK TO UUOH + MSPIO,,MSPIO +; (DOES NOT COME BACK) + +;HERE FOR FAILURE OF XCTRI WHILE MAP SET TO RECEIVER +MSS7: POP P,R ;RESTORE STACK + PUSHJ P,LSWPOP ;RESTART USER (SOS USTP) + PUSHJ P,TPFLT ;TAKE PAGE FAULT, CAUSE PAGE LOAD + PUSHJ P,MPLDZ ;RESTORE MY PAGE MAP + JRST MSS1 ;TRY AGAIN + +; FIND LOSER IN TABLE SKIP IF WINS +; IN => T/READ1 EPDL/READ2 EPDL3/WRITE1 SRN4/WRITE2 +; OUT => IF WINS, T/TABLE OFFSET +MSSTBL: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D + MOVSI A,-MSENTS + MOVE B,EPDL(U) ; B/ READ2 + MOVE C,EPDL3(U) ; C/ WRITE1 + MOVE D,SRN4(U) ; D/ WRITE2 +MSSTB1: CAMN T,MSREAD(A) + CAME B,MSRED2(A) + JRST MSSTB2 + SKIPN MSWRIT(A) ; if it was read from any + SKIPE MSWRT2(A) ; win if WRIT and WRT2 are both zero + JRST .+2 + JRST MSSTB3 + CAMN C,MSWRIT(A) + CAME D,MSWRT2(A) + JRST MSSTB2 +MSSTB3: HRRZ T,A + AOSA -4(P) +MSSTB2: AOBJN A,MSSTB1 + POP P,D + POP P,C + JRST POPBAJ + +; close routine +; A/ lf IOCHNM +; R/ addr of IOCHNM(USER)(CHNL) + +MSCLOS: TRNE A,400000 ; -1 means write + POPJ P, + CAIL A,MSENTS ; in bounds of table? + POPJ P, ; no + CAME U,MSUSER(A) ; is this still me? + POPJ P, + +; yes, make this a free slot + SETZM MSCHNL(A) + SETZM MSREAD(A) + SETZM MSRED2(A) + SETZM MSWRIT(A) + SETZM MSWRT2(A) + SETZM MSBADR(A) + SETZM MSBCNT(A) + SETZM MSUSER(A) + POPJ P, +  \ No newline at end of file diff --git a/src/system/kaimp.defs1 b/src/system/kaimp.defs1 new file mode 100755 index 00000000..c37b820f --- /dev/null +++ b/src/system/kaimp.defs1 @@ -0,0 +1,63 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Hardware description of AI-KA/ML/MC IMP interface, device "IMP". +; For a more detailed description, see AI Hardware Memo #10, +; "ARPA Network Interface". +; In particular, the "channel 1 multiplexing" feature of the ITS KA's +; is used, so that: +; When PI level 2 (NETCHN) is assigned, the IMP interface takes +; all interrupts on the normal channel (goes to IMPINT). +; When PI level 1 (IMPCHN) is assigned, +; IMPID+(-IMPLIW) => Pseudo channel 4, location 70 (IMPILC)-> various +; IMPOD => Pseudo channel 5, location 72 (IMPOLC)-> various +; else normal PI channel 1 (PI0LOC+2)-> IMPBRK + +; CONI bits - starred items cause interrupt on PIA channel + ; 1.1-1.3 => PIA +DEFSYM IMPID==10 ;* INPUT DONE - on when word avail for DATAI +DEFSYM IMPI32==20 ; Input in 32 bit mode +;DEFSYM IMPIB==40 ; Input Busy +DEFSYM IMPOD==100 ;* OUTPUT DONE - Word sent to IMP +;DEFSYM IMPO32==200 ; Output in 32 bit mode +;DEFSYM IMPOB==400 ; Output Busy +DEFSYM IMPERR==1000 ;* Imp Error (interrupt if IMPIC zero) +DEFSYM IMPR==2000 ;* Imp Ready (interrupt if IMPIC set) +;DEFSYM IMPIC==4000 ; Imp interrupt condition + ; (0 = int on IMPERR, 1= int on IMPR) +DEFSYM IMPHER==10000 ;* Host Error (interrupt if IMPIHE zero) +;DEFSYM IMPHR==20000 ; Host Ready +;DEFSYM IMPIHE==40000 ; Inhibit interrupt on Host Error (IMPHER) +DEFSYM IMPLW==100000 ;* Last Imp Word + +; CONO bits - starred flags are always copied directly to set states + ;* 1.1-1.3 => PIA set from these bits +DEFSYM IMPIDC==10 ; Clear Input Done +DEFSYM IMI32S==20 ; Set input to 32 bit mode +DEFSYM IMI32C==40 ; Clear input in 32 bit mode +DEFSYM IMPODC==100 ; Clear Output Done +DEFSYM IMO32S==200 ; Set output to 32 bit mode +DEFSYM IMO32C==400 ; Clear output in 32 bit mode +DEFSYM IMPODS==1000 ; Set Output Done +DEFSYM IMPIR==4000 ;* Copied to IMPIC; 1= Enable int on imp ready +DEFSYM IMPHEC==10000 ; Clear Host Error +;DEFSYM IMIIHE==40000 ;* Copied to IMPIHE + ; 1= Inhibit int on host error +DEFSYM IMPLHW==200000 ; Set Last Host Word + ; (do this before last DATAO of msg) +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/ksdefs.193 b/src/system/ksdefs.193 new file mode 100755 index 00000000..d5325fcc --- /dev/null +++ b/src/system/ksdefs.193 @@ -0,0 +1,561 @@ +; -*- Midas -*- This is the file AI:KSHACK;KSDEFS > + +;;; "Devices" + +PI==:4 ;Interrupts +PAG==:10 ;Paging + ..D010==:0 ;(For DDT) +.RD.==:20 ;Read various kludges. + ..D020==:0 +.WR.==:24 ;Write various kludges. + ..D024==:0 + +;;; XCTR and paging instructions + +UMOVE=:704^9 ;"BLKI 40," + ;Same as XCTR XR,[MOVE ...] + +UMOVEM=:705^9 ;"BLKI 50," + ;Same as XCTR XW,[MOVEM ...] + +XCTR=:103^9 ;XCT with mapping. +XCTRI=:102^9 ;Same, but page fails cause it to skip. Done by + ;software as on the KL. + ;;XCTR bits for the KS are theoretically the same as those on the KL. + ;;These values were generated by reading the documentation rather + ;;than by copying the bits for XCTR on MC. + XR==:4 + XW==:4 + XRW==:4 + XBYTE==:7 ;On MC-KL this is 5. The manual don't list 5 as a + ;reasonable value at all. The 2 bit causes the EA + ;calculation for the byte pointer to take place in + ;the user's context. Since ITS does the EA + ;calculation for byte pointers it XCTRs ahead of + ;time, perhaps it doesn't matter? + XBR==:1 + XBW==:4 + XBRW==:5 + XEA==:10 ; On MC-KL this is #o16. The processor manual for + ; the KL contains some waffling about how 10 won't + ; work and you should use 14 instead. The KS + ; manual is silent on this point. Seemingly no + ; bits other than 10 can effect an immediate + ; instruction. This option doesn't exist on the KA + ; and is used by ITS in only two places, both in + ; the KL-specific page fail code. One occurance is + ; commented out with the claim that it is buggy. + ; For the moment let us assume that this value will + ; just work on the KS. + +;;; Traditional instructions. + +RDAPR==:CONI 0, ;= 700240,, C(E) <- System flags + ;4.3 - 3.5 Flags enabled + ; (on KL 2.8 says the cache is being swept) + ;2.3 - 1.5 Flags set + ;1.4 Some flag is interrupting + ;1.3 - 1.1 PI level + +WRAPR==:CONO 0, ;= 700200,, System flags <- E + ; (on KL 2.8 Clears all IO devices) + ;2.7 - 2.4 Function to perform on flags: + ; 2.7 Enable + ; 2.6 Disable + ; 2.5 Clear + ; 2.4 Set + ;2.3 - 1.5 Flags to perform function upon: + ; 2.3 "Flag 24" + ; 2.2 KS interrupting the 8080 + ; 2.1 Power failure + ; 1.9 No memory + ; 1.8 Bad memory data + ; 1.7 Corrected memory data + ; 1.6 Interval done + ; 1.5 8080 interrupting the KS + ; (on KL flags are: + ; 2.3 S bus error + ; 2.2 No memory + ; 2.1 IO page failure + ; 1.9 MB parity + ; 1.8 Cache directory parity + ; 1.7 Address parity + ; 1.6 Power failure + ; 1.5 Cache sweep done) + ;1.3 - 1.1 PI level + +80INT==:12000 ;Interrupt 8080 from KS. + +RDPI==:CONI PI, ;= 700640,, C(E) <- PI status + ;3.7 - 3.1 interrupts requested with CONO PI, + ; (on KL 2.9 - 2.7 control parity) + ;2.6 - 1.9 Interrupt in progress + ;1.8 PI system is on + ;1.7 - 1.1 Levels turned on + +WRPI==:CONO PI, ;= 700600,, PI status <- E + ; (on KL 2.9 - 2.7 control parity) + ;2.5 Drop requests on selected levels + ;2.4 Clear PI system + ;2.3 Initiate interrupts on selected levels + ;2.2 Turn on selected levels + ;2.1 Turn off selected levels + ;1.9 Turn off PI system + ;1.8 Turn on PI system + ;1.7 - 1.1 Select level + +;;; More traditional looking instructions, sort of... + +APRID==:BLKI 0, ;= 700000,, C(E) <- Processor ID + ;4.9 - 4.1 Microcode options: + ; 4.5 ITS microcode + ; (on KL options are: + ; 4.9 Tops-20 Paging + ; 4.8 Extended addressing + ; 4.7 Exotic microcode + ; 4.5 ITS microcode) + ;3.9 - 3.1 Microcode version number + ;2.9 - 2.7 Hardware options: + ; None defined. + ; (on KL options are: + ; 2.9 50 Hz line frequency + ; 2.8 Cache + ; 2.7 Channel + ; 2.6 Extended KL10 + ; 2.5 Master Oscillator) + ;2.6 - 1.1 Processor serial number + +RDEBR=:CONI PAG, ;= 701240,, C(E) <- EBR +WREBR=:CONO PAG, ;= 701200,, EBR <- E + ;2.6 Tops-20 style + ;2.5 Enable pager (and traps) + ;2.2 - 1.1 EBR physical DEC page number + ;WREBR resets the cache and page table. + ; + ; In the ITS microcode setting bit 2.6 only effects + ; the style in which MUUOs are trapped. It should + ; never be set. + +RDUBR=:DATAI PAG, ;= 701040,, C(E) <- UBR +WRUBR=:DATAO PAG, ;= 701140,, UBR <- C(E) + ;4.9 Set AC blocks + ;4.7 Set UBR + ;4.3 - 4.1 Current ACs + ;3.9 - 3.7 Previous ACs + ;3.2 - 1.1 UBR physical base address + ;RDUBR always returns a word with 4.9 and 4.7 set. + ;WRUBR resets the cache and page table. + +CLRPT=:BLKO PAG, ;= 701100,, Clear page table entry + ;Invalidate the page table entry for the page + ;referenced by E and reset the cache. + ; + ;In the ITS microcode this will only invalidate the + ;page table entry for half page referenced by E. + +CLRCSH=:BLKI PAG, ;= 701000,, Clear Cache + ;In the ITS microcode only. + ;Resets the cache. + + +;;; Instructions for maintaining the DBRs. LPMR and SPM. + +LDBR1=:BLKI .WR., ;= 702400,, DBR1 <- E +SDBR1=:BLKI .RD., ;= 702000,, C(E) <- DBR1 +LDBR2=:DATAI .WR., ;= 702440,, DBR2 <- E +SDBR2=:DATAI .RD., ;= 702040,, C(E) <- DBR2 +LDBR3=:BLKO .WR., ;= 702500,, DBR3 <- E +SDBR3=:BLKO .RD., ;= 702100,, C(E) <- DBR3 +LDBR4=:DATAO .WR., ;= 702540,, DBR4 <- E +SDBR4=:DATAO .RD., ;= 702140,, C(E) <- DBR4 + ;LDBR1, LDBR2, LDBR3 and LDBR4 all reset the cache + ;and page table. someday they may be careful and + ;not reset the half of the page table they don't + ;effect. + +;;; And there is also the traditional: + +LPMR=:CONSO .WR., ;702740,, DBR1, DBR2, ... <- C(E, E+1, ...) +SPM=:CONSO .RD., ;702340,, C(E, E+1, ...) <- DBR1, DBR2, ... + ;The format of the block read and written by these + ;two instructions is: + ; (E) DBR1 + ; (E+1) DBR2 + ; (E+2) Quantum timer + ; (E+3) U.JPC (If this ucode supports it) + ; (E+4) E.JPC ( " " ) + ;LPMR resets the cache and page table. + +RDTIM=:CONO .RD., ;= 702200,, C(E, E+1) <- Time +WRTIM=:CONO .WR., ;= 702600,, Time <- C(E, E+1) + ; The time is a 71. bit unsigned number. The bottom + ; 12. bits cannot be set. The bottom 2 bits cannot + ; even be read. It increments at 4.1 MHz. The top + ; 59. bits (the ones you can set) thus measure + ; (almost) milliseconds. The top 69. bits (the + ; ones you can read) thus measure "short" + ; microseconds. The time wraps around every 18. + ; million years. To make the top 59. bits actually + ; measure milliseconds, the clock would have to run + ; at 4.096 MHz. However it -really- -does- run at + ; exactly 4.1 MHz! + +RDINT=:CONI .RD., ;= 702240,, C(E) <- Interval +WRINT=:CONI .WR., ;= 702640,, Interval <- C(E) + ;The interval is a 35. bit number in the same units + ;as the time. At the end of every interval the + ;interval done interrupt occurs (CONI APR, bit + ;1.5). The biggest interval you can set is about 2 + ;hours and 20 minutes. In the DEC microcode the + ;interval is effectively rounded up to the next + ;millisecond, so it is really only worth your while + ;to set the top 23. bits. In the ITS microcode all + ;bits of the interval are signifigant. Although + ;the length of a -single- interval cannot be + ;controlled more accurately than under the DEC + ;microcode, the average time between interval done + ;interrupts should converge to the full 35. bit + ;value. + +RDHSB=:CONSZ .RD., ;= 702300,, C(E) <- HSB base address +WRHSB=:CONSZ .WR., ;= 702700,, HSB base address <- C(E) + ;4.9 Base address is invalid. If this is set + ; nothing will be written anywhere when the + ; machine halts. + ;3.1 - 1.1 Physical address of first location in + ; which to store debugging info when the + ; machine halts. + ;In the ITS microcode, the initial HSB base address + ; is #o500. + ;When the machine halts it stores a halt code in + ; physical location 0 and the PC in location 1. + ; Then if 4.9 is not set (and the machine has not + ; just powered on) the contents of the 2901's + ; registers are dumped in the halt status block, + ; followed by the VMA. + +;;; Halt Codes + + ;CODES 0 TO 77 ARE "NORMAL" HALTS +; POWER=0 ;POWER UP +; HALT=1 ;HALT INSTRUCTION +; CSL=2 ;CONSOLE HALT + ;CODES 100 TO 777 ARE SOFTWARE ERRORS +; IOPF=100 ;I/O PAGE FAIL +; ILLII=101 ;ILLEGAL INTERRUPT INSTRUCTION +; ILLINT=102 ;BAD POINTER TO UNIBUS INTERRUPT VECTOR + ;CODES 1000 TO 1777 ARE HARDWARE ERRORS +; BW14=1000 ;ILLEGAL BWRITE FUNCTION (BAD DROM) +; NICOND 5=1004 ;ILLEGAL NICOND DISPATCH +; MULERR=1005 ;VALUE COMPUTED FOR 10**21 WAS WRONG + +;;; Halt Status Block definition + +IFNDEF HSB, HSB==:500 +HSBMAG=:HSB+0 +HSBPC=:HSB+1 +HSBHR=:HSB+2 +HSBAR=:HSB+3 +HSBARX=:HSB+4 +HSBBR=:HSB+5 +HSBBRX=:HSB+6 +HSBONE=:HSB+7 +HSBEBR=:HSB+10 +HSBUBR=:HSB+11 +HSBMASK=:HSB+12 +HSBFLG=:HSB+13 +HSBPI=:HSB+14 +HSBXWD1=:HSB+15 +HSBT0=:HSB+16 +HSBT1=:HSB+17 +HSBVMA=:HSB+20 + +;;; ITS I/O instructions. + +UBAQ==:1 ; QSK is on Unibus #1 +UBAI==:3 ; Everything else is on Unibus #3 + +IORDI=:710^9 ; C(AC) <- IO(UBAI,,E) +IORDQ=:711^9 ; C(AC) <- IO(UBAQ,,E) +IORD=:712^9 ; C(AC) <- IO(C(E)) +IOWR=:713^9 ; IO(C(E)) <- C(AC) +IOWRI=:714^9 ; IO(UBAI,,E) <- C(AC) +IOWRQ=:715^9 ; IO(UBAQ,,E) <- C(AC) + +IORDBI=:720^9 +IORDBQ=:721^9 +IORDB=:722^9 +IOWRB=:723^9 +IOWRBI=:724^9 +IOWRBQ=:725^9 + +;;; Byte packing and unpacking instructions. + +;;; These are new with microcode 262, but came from DEC. +;;; Variations of BLT that the convert format of each word moved. +;;; These are legal in user mode, too. Good thing DECUUO doesn't use them. +BLTBU=:716^9 ;Source 8-bit bytes, Destination Unibus format +BLTUB=:717^9 ;Source Unibus format, Destination 8-bit bytes + +;;; Future byte packing and unpacking instructions + +;;; =:730^9 +;;; =:731^9 +;;; =:732^9 +;;; =:733^9 +;;; =:734^9 +;;; =:735^9 +;;; =:736^9 +;;; =:737^9 + +;;; Format of ITS page fail word: + +%PF==:1,,525252 ;Left handed bits. +%PFUSR==:400000 ;4.9 Indicates user address space. +%PFNXI==:200000 ;4.8 Nonexistent IO register. +%PFNXM==:100000 ;4.7 Nonexistent memory. +%PFPAR==:040000 ;4.6 Uncorrectable memory error. + ; (AC0 in block 7 has the word unless 4.7 is + ; also set.) + ;4.5 +%PFWRT==:010000 ;4.4 Soft fault reference called for writing. +%PF2.9==:004000 ;4.3 - 4.2 Access bits for referenced page in soft +%PF2.8==:002000 ; fault. +%PFPHY==:001000 ;4.1 Address given was physical. + ;3.9 +%PFIO==:000200 ;3.8 Indicates an IO operation. + ;3.7 + ;3.6 +%PFBYT==:000020 ;3.5 Indicates a byte IO operation. + ;3.4 - 1.1 IO address + ; or + ;3.1 - 1.1 Memory address +$PFPNO==:121000 ;2.9 - 2.2 Virtual page number + +;;; Format of ITS page table entry: + + ;2.9 - 2.8 Access bits + ; 00 Inaccessible + ; 01 Read only + ; 10 Read/Write/First + ; 11 Read/Write +PMAGEM==:020000 ;2.5 Age bit +PMCSHM==:010000 ;2.4 Cache enable bit +PMRCM==:001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +PMUNSD==:146000 ;Unused bits + +;;; UPT Offsets +;;; In non-time sharing and at clock level in ITS UPT=EPT. + +UPTTR1==:421 ;Exec mode arith ovfl trap. +UPTTR2==:422 ;Exec mode pdl ov trap. +UPTTR3==:423 ;Exec mode trap 3 in non-one-proceed microcode. + +UPTUUO==:424 ;MUUO stored here. +UPTUPC==:425 ;MUUO old PC stored here. +UPTUCX==:426 ;MUUO context (from RDUBR (= DATAI PAG,)) stored here. + +;;; 427 ;Unused. + +UPTUEN==:430 ;MUUO new PC obtained from here in exec mode when + ;traps are not enabled. (MUUO as a trap + ;instruction for example.) +UPTUET==:431 ;MUUO new PC obtained from here in exec mode when + ;traps are enabled. + +UPT1PO==:432 ;One-proceed old PC stored here in one-proceed + ;microcode. +UPT1PN==:433 ;One-proceed new PC obtained from here in + ;one-proceed microcode. + +UPTUUN==:434 ;MUUO new PC obtained from here in user mode when + ;traps are not enabled. +UPTUUT==:435 ;MUUO new PC obtained from here in user mode when + ;traps are enabled. + +;;; 436 ;Unused. +;;; 437 ;Unused. + +;;; EPT Locations + +IFNDEF EPT, EPT==:0 ;Absolute location of EPT. + +PI0LOC=:EPT+40 ;PI0LOC+2*PICHN = Address of instr pair for PICHN. +IRP I,,[1,2,3,4,5,6,7] +PI!I!LOC=:PI0LOC+<2*I> +TERMIN + +EPTUIT=:EPT+100 ;EPTUIT+I contains address of the interrupt table + ; for unibus adapter I. Only adapters 1 and 3 ever + ; exist. + +EPTTR1=:EPT+421 ;Exec mode arith ovfl trap. +EPTTR2=:EPT+422 ;Exec mode pdl ov trap. +EPTTR3=:EPT+423 ;Exec mode trap 3 (1 proceed?). + +;;; When EPT = UPT the following are useful to have defined: + +EPTUUO=:EPT+UPTUUO +EPTUPC=:EPT+UPTUPC +EPTUCX=:EPT+UPTUCX +EPTUEN=:EPT+UPTUEN +EPTUET=:EPT+UPTUET +EPT1PO=:EPT+UPT1PO +EPT1PN=:EPT+UPT1PN +EPTUUN=:EPT+UPTUUN +EPTUUT=:EPT+UPTUUT + +;;; In the ITS microcode the three words used to deliver a page fail are +;;; determined from the current interrupt level. At level I, the page fail +;;; word is stored in EPTPFW+<3*I>, the old PC is stored in EPTPFO+<3*I>, +;;; and the new PC is obtained from EPTPFN+<3*I>. If no interrupts are in +;;; progress we just use EPTPFW, EPTPFO and EPTPFN. + +EPTPFW=:EPT+440 ;Page fail word stored here. +EPTPFO=:EPT+441 ;Page fail old PC stored here. +EPTPFN=:EPT+442 ;Page fail new PC obtained from here. + +IRP I,,[1,2,3,4,5,6,7] +EPTP!I!W=:EPTPFW+<3*I> +EPTP!I!O=:EPTPFO+<3*I> +EPTP!I!N=:EPTPFN+<3*I> +TERMIN + +;;; 8080 communication area + +8SWIT0=:30 ;Simulated switch 0. Set by 8080 SH command. +8KALIV=:31 ;Keep Alive & Status. +8CTYIN=:32 ;CTY input. +8CTYOT=:33 ;CTY output. +8KLKIN=:34 ;KLINIK user input word (from 8080). +8KLKOT=:35 ;KLINIK user output word (to 8080). +8RHBAS=:36 ;BOOT RH11 base address. +8QNUM=:37 ;BOOT Unit Number. +8BOOTP=:40 ;Magtape Boot Format and Slave Number. + +;;; 8080 front end (FE) filesystem format + +;;; Disk addresses for the 8080 are stored in 36-bit words in "FE format": +;;; (These fields are larger than those given in the DEC document because +;;; the cylinder field given there is too small! These numbers reflect the +;;; way that the 8080 manipulates 8 bit quantities instead.) +%88==:777700,,177400 +%88CYL==:100,, +$88CYL==:301400,, ; 4.9 - 3.7 Cylinder +%88TRK==:400 +$88TRK==:101000,, ; 2.7 - 1.9 Track +%88SEC==:1 +$88SEC==:001000,, ; 1.8 - 1.1 Sector + +;;; The 8080 looks for the "home sector" on cylinder 0, track 0, sector 1. +;;; If it fails to find it there it tries sector 10. The home sector is +;;; recognized by having SIXBIT /HOM/ in location 0. Location 103 of the +;;; home sector contains an FE format address of the first sector of the +;;; "FE directory", which is 1000 words (4 sectors) long. Odd numbered +;;; locations in the FE directory are not looked at by the 8080. Even +;;; numbered locations contain FE format addresses of the first sector of +;;; the various "FE files". The following are apparently the only FE files +;;; used by the 8080: +88RAM==:2 ; Microcode. Always 6 blocks long. + ; The rest are always 1000 words long. (1/2 block) +88BT==:4 ; Bootstrap used by BT command and autoboot. +88BT1==:6 ; Bootstrap used by BT1 command. +88B2==:12 ; Bootstrap used by B2 command. +88FI0==:22 ; First indirect file. Contains a sequence of + ; 8-bit bytes containing ASCII characters packed + ; backwards and right justified: + ; ------------------------------- + ; | 0's | 4th | 3rd | 2nd | 1st | + ; ------------------------------- + ; The 8080 stops on a zero byte (or perhaps 377?). + ; Lines must be no longer than 80 characters. + ; Lines are separated by a single ^M. + ; + ; Additional indirect files follow. FIn either + ; runs the file at 88FI0+n or at 88FI0+2*n, I can't + ; tell which. + +;;; Note that the only thing described here that doesn't fit inside a +;;; single ITS block is the microcode. All we need from the filesystem are +;;; the first 2 blocks (for the home sector and the alternate home sectors) +;;; and 6 contiguous blocks elsewhere (for the microcode). + +;;; External register addresses + +KSECCS==:100000 ;Memory Status Register (Controller 0) +%KE==:1,,520040 ; Left half bits. Right half unnamed. + ; [R=Read, W=Write, C=Cleared by writing a 1] +%KEHLD==:400000 ; 4.9 Error currently being held [R/C] +%KEUNC==:200000 ; 4.8 Uncorrectable error [R] +%KEREF==:100000 ; 4.7 Refresh error [R/C] +%KEPAR==:040000 ; 4.6 Parity error [R/W] +%KEENA==:020000 ; 4.5 ECC enabled [R] +%KEECC==:017700 ; 4.4 - 3.7 ECC bits [R] +%KEPWR==:000040 ; 3.6 Memory backup power is low [R/C] + ; 3.4 - 1.1 Error address [R] + ; 1.8 - 1.2 Force ECC bits if non-zero [W] + ; 1.1 Disable ECC [W] + +;; The 7 ECC bits are decoded as follows: The top bit is a parity bit for +;; the bottom 6. The bottom 6 are decoded: +;; +;; ECC code: Location of failing bit: +;; +;; 01 ECC 01 bit +;; 02 ECC 02 bit +;; 04 ECC 04 bit +;; 10 ECC 10 bit +;; 20 ECC 20 bit +;; 40 ECC 40 bit +;; 11 - 16 4.9 - 4.4 +;; 21 - 26 4.3 - 3.7 +;; 31 - 36 3.6 - 3.1 +;; 41 - 46 2.9 - 2.4 +;; 51 - 56 2.3 - 1.7 +;; 61 - 66 1.6 - 1.1 + +UBAPAG==:763000 ;(to 763077) UBA Paging RAM (One per Unibus) +UBALEN==:64. ;Length of UBA Paging RAM + ;When read: +%UP==:1,,525377 ; Left half bits. +%UPPAR==:020000 ; 4.5 RAM parity bit +%UPRPW==:010000 ; 4.4 Force read-pause-write +%UP16B==:004000 ; 4.3 Disable upper two bits on Unibus transfers +%UPFST==:002000 ; 4.2 Fast mode enable +%UPVAL==:001000 ; 4.1 Entry is valid +%UPPVL==:000400 ; 3.9 Parity is valid +$UPPAG==:121200,, ; 3.2 - 2.2 ITS page number + ; 2.1 ITS half page + ; 3.2 - 2.1 DEC page number + ;When written: +%UQ==:0,,537777 ; Right half bits +%UQRPW==:400000 ; 2.9 Force read-pause-write +%UQ16B==:200000 ; 2.8 Disable upper two bits on Unibus transfers +%UQFST==:100000 ; 2.7 Fast mode enable +%UQVAL==:040000 ; 2.6 Entry is valid + ; 2.2 - 1.2 ITS page number + ; 1.1 ITS half page + ; 2.2 - 1.1 DEC page number + +UBASTA==:763100 ;UBA Status Register (One per Unibus) + ; [R=Read, W=Write, C=Cleared by writing a 1, + ; *=Cleared by any write] +%UB==:0,,525270 ; Right half bits. +%UBTIM==:400000 ; 2.9 Unibus timeout [R/C] +%UBBAD==:200000 ; 2.8 Bad mem data (on NPR transfer) [R/C] + ; (Master will timeout instead if %UBDXF set) +%UBPAR==:100000 ; 2.7 KS10 bus parity error [R/C] +%UBNXD==:040000 ; 2.6 CPU addressed non-ex device [R/C] +%UBHIG==:004000 ; 2.3 Interrupt request on BR7 or BR6 (high) [R] +%UBLOW==:002000 ; 2.2 Interrupt request on BR5 or BR4 (low) [R] +%UBPWR==:001000 ; 2.1 Power low [R/*] +%UBDXF==:000200 ; 1.8 Disable tranfer on uncorrectable data [R/W] +%UBINI==:000100 ; 1.7 Issue Unibus init [W] +%UBPIH==:000070 ; 1.6 - 1.4 PI level for BR7 or BR6 (high) [R/W] +%UBPIL==:000007 ; 1.3 - 1.1 PI level for BR5 or BR4 (low) [R/W] + +UBAMNT==:763101 ;UBA Maintenance (One per Unibus) + ; 1.2 Spare maintenance bit (?) + ; 1.1 Change NPR address (?) diff --git a/src/system/ksnet.1 b/src/system/ksnet.1 new file mode 100755 index 00000000..ed9fea1d --- /dev/null +++ b/src/system/ksnet.1 @@ -0,0 +1,58 @@ +;;; Chaosnet interface on Unibus + +CAICSR=3,,764140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + $CALOS==110400 ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN==3,,764142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=3,,764142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=3,,764144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=3,,764146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=3,,764152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. diff --git a/src/system/lhdh.defs5 b/src/system/lhdh.defs5 new file mode 100755 index 00000000..89562dbb --- /dev/null +++ b/src/system/lhdh.defs5 @@ -0,0 +1,80 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; The ACC IMP interface on the KS implements two separate Unibus IO +; devices, for input and output. Both of these devices transfer data in +; 32-bit mode only over the Unibus via DMA. Because of the DMA data +; transfer the interrupt structure is trivial, and uses NETCHN only. +; +; Apparently the reset bits in the two CSRs are wired together, so +; resetting one side of the machine resets both. This action also drops +; the HOST READY line to the IMP. +; +; You must set %LHSE whenever hte HOST READY line is high, or the IMP +; will be allowed to freely throw away data. This is true across IMP +; message boundaries, and even if no input request is active. +; + +;ACC LH-DH IMP Interface Bits + +;Interrupt information +DEFSYM %LHVEC==250 ;Input side interrupt vector (non-standard) + ;Output side assumed to be %LHVEC+4 +DEFSYM %LHPRI==6 ;Interrupt priority (non-standard) + +DEFSYM %LHBAS==767600 ;Base of LH/DH Unibus register address space + +;Unibus Registers +DEFSYM %LHICS=:%LHBAS ;Control and Status, Input side +DEFSYM %LHIDB=:%LHBAS+2 ;Data Buffer, Input +DEFSYM %LHICA=:%LHBAS+4 ;Current Word Address, Input +DEFSYM %LHIWC=:%LHBAS+6 ;Word Count, Input + +DEFSYM %LHOCS=:%LHBAS+10 ;Control and Status, Output side +DEFSYM %LHODB=:%LHBAS+12 ;Data Buffer, Output +DEFSYM %LHOCA=:%LHBAS+14 ;Current Word Address, Output +DEFSYM %LHOWC=:%LHBAS+16 ;Word Count, Output + +;Bits in CSRs +; Bits common to input and output +DEFSYM %LHERR==1_15. ;Error present +DEFSYM %LHNXM==1_14. ;Non Existant Memory on DMA +DEFSYM %LHMRE==1_9. ;Master Ready Error (ready bounce during xfr) +DEFSYM %LHRDY==1_7. ;Device Ready (modifying LHDH regs allowed) +DEFSYM %LHIE==1_6. ;Interrupt Enable +DEFSYM %LHA17==1_5. ;Address bit 17 for extended unibus xfrs +DEFSYM %LHA16==1_4. ;Address bit 16 for extended unibus xfrs +DEFSYM %LHRST==1_1. ;Interface Reset +DEFSYM %LHGO==1 ;GO - Start DMA Transfer + +; Input side +DEFSYM %LHEOM==1_13. ;End-of-Message received from IMP +DEFSYM %LHHR==1_11. ;Host Ready (ACC's relay closed, debounced) +DEFSYM %LHINR==1_10. ;IMP not ready +DEFSYM %LHIBF==1_8. ;Input Buffer Full +DEFSYM %LHSE==1_3. ;Store Enable (0 == flush data instead) +DEFSYM %LHHRC==1_2. ;Host Ready Relay Control (1 to close relay) + +; Output side +DEFSYM %LHWC0==1_13. ;Output Word Count is zero +DEFSYM %LHOBE==1_8. ;Output Buffer Empty +DEFSYM %LHBB==1_3. ;Bus Back (loopback enable for testing) +DEFSYM %LHELB==1_2. ;Send EOM indication to IMP at end of xfr + ; (enable Last Bit Flag) +IFN $$TEMP,EXPUNG DEFSYM + diff --git a/src/system/mtape.197 b/src/system/mtape.197 new file mode 100755 index 00000000..edeed6e5 --- /dev/null +++ b/src/system/mtape.197 @@ -0,0 +1,1461 @@ +;******************************** +;** +;** TO BE DONE: +;** +;** RECORDS LONGER THAN 1K +;** AUTOMTAIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING +;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF +;** BE MORE FORGIVING OF CONTROLLER LOSSAGE +;** PASS .MTAPE TO JOB DEVICE +;** HAVE AN IGNORE ERRORS SWITCH +;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED +;** +;******************************** + + +IFN TM10A,TM10B==0 +IFE TM10A,TM10B==1 +IFN TM10A,INFORM IO BUSS MAG TAPE,1 +IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1 +MSCBL==8 ; COMMAND BUFFER LENGTH +MGQDLL==6 ; INTERUPT LEVEL PDL +IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB +MSEOFP==210100 ;HIGH BIT OF MNUMB IN MEMBLT IS EOF FLAG +MSCHN==140500 ;OTHER 5 BITS OF MNUMB IN MEMBLT IS DRIVE NUMBER + +MTXP==410300,, ;XPORT NUMBER +MUNITF==170300 ; UNIT FIELD IN MTC CONI +MNOPIN==10000 +MWRITE==4000 +MW3IN==14000 +MSPRR==7000 +MREAD==2000 +MSPFR==6000 +MSPFF==16000 +MSPRF==17000 +MREWND==1000 +MRWNDD==11000 +MWEOF==5000 +MGNRTY==10. ;NUMBER OF READ RETRIES + +SUBTTL MAG TAPE OPEN ROUTINE + +; C/ MODE,,DEV +; D/ MODE (ROT 1) 4.9=1=>OUTPUT +; I/ DEVICE NUMBER +; R/ IOCHNM WORD POINTER + +MAGTO: SKIPL W,I ; GET DEVICE + CAIL W,NMTCS ; TO BIG? + JRST OPNL1 ; NO SUCH DEVICE + MOVSI T,%MAREW + TDNE T,MSRAC(W) ; REWINDING + PUSHJ P,UFLS ; YES, THEN WAIT + CONO PI,CLKOFF ; DON'T WANT STATUS CHANGED FROM UNDER ME + SKIPGE MTUSE(W) ; CHECK FOR FIRST USER + JRST MAGTU1 ; FIRST + CAME U,MTUSR(W) ;SAME USER + JRST OPNL10 ; DIFFERENT USER IS ERROR + MOVE B,D + EQV B,MSCRW(W) + SKIPL B ; CHECK FOR SECOND OPEN IN SAME DIRECTION + JRST OPNL2 ; WRONG DIRECTION +MAGTU: MOVEM U,MTUSR(W) ; STORE USER + SETZM MSCRW(W) ; INDICATE READ UNTIL FOUND TO BE OTHERWISE + TLNE C,1 ; READ OR WRITE + SETOM MSCRW(W) ;INDICATE WRITE + AOS MTUSE(W) ;INDICATE 1 MORE USER + PUSHJ P,SOSSET + MTUSE(W) ; SOS IF PCLSRED + CONO PI,CLKON ; LET UM GET ME + PUSHJ P,MTSTAT ; GET CONIS OF 340 AND 344 IN I AND J + MOVE A,MSRAC(W) + TLNE A,%MAERR ; PI ERROR MEANS DEVICE NOT THERE + JRST MTOL1 + TRNN J,200040 + JRST OPNL7 ; DEVICE NOT ONLINE + SKIPN MSCRW(W) ;WRITING? + JRST MTOW1 + TRNE J,10 ; AND WRITE LOCKED + JRST OPNL26 ; DEVICE WRITELOCKED + SKIPE MSRAC(W) ; WRITING + TRNN J,4000 ;EOT? + JRST MTOW1 ; NO + MOVSI A,%MAETW+%MAERR ; IF WRITE AND EOT,MAKE .IOT GIVE IOC ERROR BUT LET OPEN WIN + IORM A,MSRAC(W) +MTOW1: TRNN J,400000 ; XPORT HUNG + JRST MTOW2 ; OK + TRNN J,20000 ; OK IF REWINDING + JRST OPNL7 ;DEVICE NOT WORKING +MTOW2: TLNN C,400 ; GET CORE DUMP MODE + JRST MTOW3 + TLNN C,300 + JRST MTOW3 + TLC C,300 + TLCE C,300 ; IBM AND DENSITY 800 BPI OK + JRST OPNL12 ; MODE NOT AVAILABLE +MTOW3: ;BY THIS POINT OPEN WILL WIN + PUSHJ P,LSWDEL ; RELEASE MTUSE SWITCH + MOVEI A,MTCCHN_3 ;SET UP MAG TAPE CONO +IFN TM10A, TRO A,1 ; DATA PI CHANNEL + LDB B,[300200,,C] ; GET DENSITY FROM OPEN + SKIPN B + MOVEI B,3 + SUBI B,1 ; CONVERT TO PROPER PARITY + DPB B,[060200,,A] + TLNN C,400 ; CORE DUMP + TRO A,20000 ; YES + TLNN C,40 ; PARITY CHECK + TRO A,40000 ; SET ODD PARITY + DPB W,[170300,,A] ; SET UNIT NUMBER + MOVEM A,MTCONO(W) ; STORE IT + LDB B,[330300,,C] ; GET WORDS PER BLOCK + TRC B,7 + MOVEI A,10 + LSH A,(B) ;NUMBER OF WORDS PER RECORD + MOVEM A,MTBLKS(W) ;BLOCKSIZE + LDB A,[230200,,C] ; GET MODE (BUT NOT READ/WRITE BIT) + HLR C,MTOPTB(A) ; GET INPUT DISPATCH + TLNE D,400000 ; OPEN FOR OUTPUT? + HRR C,MTOPTB(A);CHANGE TO OUTPUT IF SO + MOVEM C,(R) ;STORE IN IOCHNM + DPB W,[MTXP(R)] ; STORE XPORT NUMBER + JRST POPJ1 ; SKIP RETURN + +MTOPTB: MTUAIX,,MTUAOX + MTBIX,,MTBOX + MTUIIX,,MTUIOX + MTBIX,,MTBOX + +MAGTU1: SETZM MSBUFP(W) ; INDICATE NO BUFFERS ON CHAIN + SETZM MSNBOL(W) ; ANOTHER WAY OF SAYING ABOVE + SETZM MSMPRC(W) ; BUFFER WORDS REMAINING + SETZM MSMPRP(W) ; POINTER TO BUFFERS + SETOM MTMDN(W) ;NO BUFFER AT MP + SETOM MGCABN(W) ;NONE AT PI + SETZM MSRAC(W) + MOVEI A,2 + MOVEM A,MTCEFW(W) ; NUMBER OF EOF'S WRITTEN + MOVSI A,%MANWT + IORM A,MSRAC(W) ; INDICATE NOTHING WRITTEN ON TAPE + JRST MAGTU + +MTOL1: SETZM MSRAC(W) + JRST OPNL1 + +SUBTTL MAG TAPE INPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAI: MOVEI B,CHRKTI ;UNIT ASCII INPUT + MOVE E,[440700,,5] + JRST MTREAD + + SKIPA B,[SIOKT] +MTUII: MOVEI B,CHRKTI ;UNIT IMAGE + MOVE E,[444400,,1] + JRST MTREAD + +MTBI: MOVE E,[444400,,1] ;BLOCK INPUT + MOVEI B,BLKT +MTREAD: LDB W,[MTXP(R)] ; W <= XPT # + PUSHJ P,MTIECK + MOVEM P,MTPSAV(W) ; SAVE P FOR EOF RETURN + JSP B,(B) ;BLKT,CHRKT,SIOKT + MSMPRP(W) ;LOC OF NEXT WORD + MSMPRC(W) ;COUNT REMAINING + SETZ MTRBG ; GET NEW BUFFER (SETZ FOR CHRKT RETURN ON EOF) + MTRBD ; DISCARD BUFFER + JRST 4,. + PUSHJ P,MTRBFW ; FLUSH INSTRUCTION WAIT FOR BUFFERS TO COME FROM PI + +;MAG TAPE READ BUFFER GET ROUTINE +; BUFFER ASSUMED TO HAVE COME IN FROM PI LEVEL. (I.E. MTRBFW WAS CALLED) + +MTRBG: SKIPG MSNBOL(W) ;ANY BUFFER AVAILABLE? + JRST MTRBG3 ;NO, MUST BE ERROR OR EOF + CONO PI,UTCOFF + HLRZ A,MSBUFP(W) ; GET IN POINTER + HRRZ TT,MSBUFP(W) ; GET OUT POINTER + MOVEM TT,MTMDN(W) ; STORE BUFFER ACTIVE AT MP + CAMN A,TT ;IN = OUT? + JRST MTRBG1 ; YES + LDB T,[MLO,,MEMBLT(TT)] ; BACK POINTER TO NEXT BLOCK + HRRM T,MSBUFP(W) ;STORE NEW OUT POINTER + JRST MTRBG2 + +MTRBG1: SETZM MSBUFP(W) ;EMPTY BUFFER LIST +MTRBG2: SOS MSNBOL(W) ; ONE LESS BUFFER ON LIST + CONO PI,UTCON + LDB J,[MWC,,MEMBLT(TT)] ;WORD COUNT OF BLOCK + MOVEM J,MTBLKS(W) ;SAVE FOR MTAPE 13 + LSH TT,10. ;MAKE BLOCK NUMBER AN ADDRESS + MOVEM TT,MSMPRP(W) + JRST SIOBGX + +MTRBG3: SKIPGE MSRAC(W) .SEE %MAEOF + JRST [ MOVSI T,%MAEFA ;THE EOF IS NOW NO LONGER READ-AHEAD + ANDCAM T,MSRAC(W) ;TELL THE USER ABOUT IT + JRST POPJ2 ] + PUSHJ P,MTIECK + JRST 4,. ;BULLSHIT, WHY DID MTRBFW SKIP? + +;MAG TAPE READ BUFFER DISCARD ROUTINE +MTRBD: SKIPGE A,MTMDN(W) ; ANY BUFFERS + JRST MOVTWJ ;SET UP T FOR BUFFER WAIT,RETURN + CONO PI,UTCOFF ; SHUT UP WORLD + SETOM MTMDN(W) ; NO BUFFER ACTIVE AT M.P. + SETZM MSMPRC(W) + LDB TT,[MSEOFP,,MEMBLT(A)] ;GET EOF FLAG FROM PI + PUSHJ P,MGMEMR ;RETURN MEM, TURN UTCON + JUMPN TT,MTRBD2 ;EOF? +MOVTWJ: MOVE T,W ; T NEEDS CHANNEL NUMBER FOR BUFFER WAIT UFLUSH + POPJ P, ;ALSO MTRBG, MTRBFW RELY ON THIS SETTING T + +MTRBD2: MOVSI A,%MAEOF ; SET EOF + IORM A,MSRAC(W) + JRST MOVTWJ + +;MAG TAPE READ WAIT FOR DATA ROUTINE +MTRBFW: SKIPG MSNBOL(T) ; ANY FREE BUFFERS ON LIST? + SKIPGE MSRAC(T) .SEE %MAEOF + JRST POPJ1 ;INPUT AVAILABLE, OR AT EOF, UNHANG + MOVE TT,MSRAC(T) + TLNE TT,%MAERR ; CHECK FOR ERRORS + JRST POPJ1 ;WAKE UP SO YOU CAN GET YOUR IOC ERROR + TLNE TT,%MARAC ; IF NOT ALREADY DONE SO, SEND OUT A CALL FOR TAPE READ + POPJ P, + PUSH P,W ;THIS BEING DONE UNDER A UFLS. ONLY T GOOD + PUSH P,B + MOVE W,T + MOVEI B,MGREAD ;WHERE TO GO AT PI LEVEL + MOVEI T,MSCBL ;MAKE SURE THAT THERE IS ROOM IN THE RING BUFFER + CAMG T,MSCMDC(W) + JRST MTRBW2 ; NO ROOM, GO AWAY + MOVSI TT,%MARAC + IORM TT,MSRAC(W) ;READ IS ACTIVE NOW, OR WILL BE SHORTLY + PUSHJ P,MTCMD1 +MTRBW2: MOVE T,W + POP P,B + POP P,W + POPJ P, + +SUBTTL MAG TAPE OUTPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAO: MOVEI B,CHRKT ;UNIT ASCII OUTPUT + MOVE E,[440700,,5] + JRST MTWRIT + + SKIPA B,[SIOKT] +MTUIO: MOVEI B,CHRKT ;UNIT IMAGE OUTPUT + MOVE E,[444400,,1] + JRST MTWRIT + +MTBO: MOVE E,[444400,,1] ; BLOCK OUT + MOVEI B,BLKT +MTWRIT: LDB W,[MTXP(R)] ; GET XPORT NUMBER + PUSHJ P,MTIECK + HRLZI A,%MAETW ; END OF TAPE CHECK + TDNE A,MSRAC(W) + JRST IOCER9 + JSP B,(B) + SETZ MSMPRP(W) ;LOC OF WORD + MSMPRC(W) ; COUNT + SETZ MTWBFG ; GET NEW BUFFER + MTWBFD ; WRITE OUT BUFFERS + JRST 4,. + TRNA ;NO WAIT FOR BUFFER + +;MAG TAPE WRITE BUFFER GET ROUTINE + +MTWBFG: PUSHJ P,MTIECK + PUSHJ P,TCALL ; TURN OFF UTC + JRST IOMQ + POPJ P, ;GO BACK NO SKIP IF NO CORE + MOVEM A,MTMDN(W) ; STORE ACTIVE BUFFER NUMBER + MOVEI T,MUMGB + DPB T,[MUR,,MEMBLT(A)] ; TELL WORLD THAT IT IS A MAG TAPE BUFFER + DPB W,[MSCHN,,MEMBLT(A)] ; CHANNEL NUMBER + SETZM TT + DPB A,[121000,,TT] ;CONVERT BLOCK NUMBER TO ADDRESS IN TT + MOVE J,MTBLKS(W) ;GET WRITE BLOCK SIZE + JRST SIOBGX + +;MAG TAPE WRITE BUFFER DISCARD ROUTINE + +MTWBFD: PUSHJ P,MTIECK + SKIPGE A,MTMDN(W) + POPJ P, + MOVEI T,MSCBL + CAMG T,MSCMDC(W) + PUSHJ P,UFLS ; MAKE SURE ROOM IN COMMAND BUFFER EXISTS IN CASE OF PCLSRING + MOVE T,MTBLKS(W) ; DISCARD BUFFER. FIRST SEE HOW BIG IT IS + SUB T,MSMPRC(W) + CONO PI,UTCOFF ;CAN'T TOLERATE ANY HANKY PANKY + SETOM MTMDN(W) ;CLEAR IT + SETZM MSMPRC(W) ; CLEAR COUNT + JUMPE T,MEMR ; DON'T DO ANYTHING BUT RETURN BLOCK IF NO WORDS + DPB T,[MWC,,MEMBLT(A)] ; STORE WORD COUNT + SKIPG MSNBOL(W) ; LIST STARTED YET? + JRST MTWBD1 ;NO + HLRZ TT,MSBUFP(W) ; GET OLD IN POINTER + DPB A,[MLO,,MEMBLT(TT)] ;CHAIN BACK + SKIPA +MTWBD1: HRRM A,MSBUFP(W) ; START NEW LIST + HRLM A,MSBUFP(W) ; IN = OUT = (A) +MTWBD2: SETZM TT + DPB TT,[MLO,,MEMBLT(A)] ; INDICATE END OF LIST + AOS MSNBOL(W) ; ONE MORE BUFFER ON LIST + CONO PI,UTCON + PUSH P,B + MOVEI B,MGWRIT + PUSHJ P,MTCMD + MOVSI B,%MANWT + ANDCAM B,MSRAC(W) + SETZM MTCEFW(W) ; INDICATE SOMETHING WRITTEN + JRST POPBJ ; RETURN + +SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL + +;PUSHJ P,MTCMD + ;RH(W) HAS XPORT NUMBER + ;RH(B) HAS ADDR OF INTERUPT ROUTINE + +MTCMD: MOVEI T,MSCBL ; COMAND BUFFER LENGTH + CAMG T,MSCMDC(W) ;COMAND COUNT + PUSHJ P,UFLS ; WAIT FOR ROOM +MTCMD1: MOVE T,MTCMBP(W) ; GET POINTER TO RING BUFFER + AOBJN T,.+2 + SUB T,[MSCBL,,MSCBL] ; REACHED END OF BUFFER, RING IT + MOVEM B,(T) ; STORE COMMAND + MOVEM T,MTCMBP(W) ; STORE NEW POINTER + CONO PI,UTCOFF + AOS MSCMDC(W) ; INDICATE ONE MORE COMMAND + JRST MSTRTR ; START UP PI ROUTINE + +SUBTTL MTIECK - CHECK FOR IOC ERROR + +MTIECK: PUSH P,A ; CHECK FOR IOTERR + MOVE A,MSRAC(W) + TLNN A,%MAERR ; ERROR AT PI? + JRST POPAJ + SKIPLE MSCMDC(W) + PUSHJ P,UFLS ; LET PI CLEAR BEFORE MUNGING BUFFERS + SKIPL A,MTMDN(W) + PUSHJ P,MEMR + SETOM MTMDN(W) + SETZM MSMPRP(W) + SETZM MSMPRP(W) + PUSHJ P,MTCBFF ; FREE CHAIN + POP P,A + MOVE T,MGCMTS(W) ; GET CONI MTS, + TRNE T,440000 ; XPT HUNG,ILLOP + JRST IOCER1 + TRNE T,23600 ; PAR ERROR,R/C, RLI,DL,BT + JRST IOCER3 ; IRRECORVERABLE DATA ERROR + TRNE T,4000 ; EOT + JRST IOCER9 ; EOT, DEV FULL + MOVE A,MGEOFR(W) ; LOGICAL EOT + CAIL A,2 + JRST IOCER9 + JRST IOCER3 ; UNKNOWN, GIVE IRR DATA + +SUBTTL MAG TAPE .STATUS ROUTINE + +STAMTC: LDB W,[MTXP(R)] ; LOAD W + DPB A,[60300,,D] ; OPEN MODE + PUSHJ P,MTSTAT + LDB A,[.BP %MAETW_22,MSRAC(W)] ; EOT ON WRITE + LDB B,[.BP %MAETR_22,MSRAC(W)] ; EOT ON READ + IOR A,B + DPB B,[140100,,D] ;EOT + LDB A,[20100,,J] + TRC A,1 + DPB A,[150100,,D] ; 7 OR 9 + LDB A,[160100,,MTCONO(W)] + TRC A,1 + DPB A,[200100,,D] ;PARITY + LDB A,[60200,,MTCONO(W)] ; DENSITY + ADDI A,1 + CAIN A,3 + SETZM A ; 800 IS 00 + DPB A,[160200,,D] + LDB A,[.BP %MARCE_22,MSRAC(W)] ; READ COMPARE ERROR + DPB A,[130100,,D] + MOVE A,MTCONO(W) + TRNN J,4 ; 7 TRACK + TRNE A,20000 ; OR CORE DUMP + POPJ P, ; THEN DONE + TRO D,140000 ; IBM, 9 TRACK AND 800 BPI + POPJ P, + + +;RCHST ROUTINE FOR MAG TAPE + +RCHMGT: HLRZ E,(R) ;OPEN-MODE IS KEPT IN LH OF IOCHNM WORD - HOW CONVENIENT! + LDB J,[MTXP(R)] ;GET THE MAG TAPE DRIVE NUMBER + MOVSI J,'MT0(J) ;RETURN THAT DRIVE'S DEVICE NAME. + TRZ E,(.BM MTXP) ;CLEAR THE PLACE IN THE OPEN-MODE THAT HAS THE DRIVE #. + JRST POPJ1 ;SKIP SO THAT J OVERRIDES BUILT-IN DEVICE NAME. + + EBLK + +SUBTTL MAG TAPE STORAGE AREA + +MGVTC: 0 ; 1 SCRATCH WORD FOR VIRGIN TAPE CHECK +MGRWCD: BLOCK NMTCS ; REWIND COMMAND +MGEOTT: BLOCK NMTCS ; TIMEOUT FOR VIRGIN TAPE +MGJDTI: 0 ; WAIT FOR JOB DONE TIME OUT +MGEOFR: BLOCK NMTCS ; NUMBER OF EOFS SINCE LAST READ +MGNWRD: 0 ; NUMBER OF WORDS READ IN A PI LEVEL READ +MTPSAV: BLOCK NMTCS ; STORAGE TO RESTORE P ON EOF +MSRAC: BLOCK NMTCS ; MAG TAPE GENERAL GARBAGE + %MA==1,,525252 + %MAEOF==400000 ; 4.9 EOF ON READ + %MAETR==200000 ; 4.8 EOT ON INTERNAL READ + %MAETW==100000 ; 4.7 EOT ON WRITE + %MAERR==040000 ; 4.6 PI ERROR + %MARCE==020000 ; 4.5 READ COMPARE ERROR + %MACTH==014000 ; 4.4 CORE ALLOCATOR SAYS STOP + ; 4.3 " (WHY 2 BITS?) + %MASTP==002000 ; 4.2 STOP READ AHEAD + %MANWT==001000 ; 4.1 NOTHING WRITTEN ON TAPE YET + %MAEFA==000400 ; 3.9 EOF SEEN ON READ-AHEAD, USER HASN'T SEEN YET + %MAESO==000200 ; 3.8 EOF READ SINCE OPEN + %MAMSO==000100 ; 3.7 TAPE MOVED SINCE FIRST OPEN + %MAREW==000040 ; 3.6 REWINDING FLAG + %MARAC==000020 ; 3.5 READ ACTIVE FLAG +MGTBZY: -1 ; FLAG TO GET INTURPT STARTED +MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ; MAIN CONO STORAGE +MGUNIT: -1 ; UNIT EXPECTING INTERUPT +MGCMTS: BLOCK NMTCS ; PI CONI MTS STORAGE +MGCMTC: BLOCK NMTCS ; PI MTC STORAGE +MGWCW: 0 ; WAIT FOR CONTROL WORD WRITTEN FLAG +LMIOWD: 0 ; LAST MIOWD +MGERRC: BLOCK NMTCS ; ERROR COUNT +MTMFNC: BLOCK NMTCS ; .MTAPE FUNCTION STORAGE +MTMCNT: BLOCK NMTCS ; .MTAPE COUNT +MTMTAP: BLOCK NMTCS ; MTAPE CALL WORD +MTCEFW: BLOCK NMTCS ; NUMBER OF EOF'S WRITTEN AT CLOSE +MSCMDC: REPEAT NMTCS,0 ; NUMBER OF COMMANDS +MSBUFP: REPEAT NMTCS,0 ; MAG TAPE BUFFER POINTER IN,,OUT +MSCRW: BLOCK NMTCS ; -1=>OUTPUT 0=>INPUT +MSMPRC: BLOCK NMTCS ; WORDS LEFT IN BUFFER +MSMPRP: BLOCK NMTCS ;NEXT WORD IN BUFFER +MTMDN: REPEAT NMTCS,-1 ; BLOCK ACTIVE AT MP +MTUSE: REPEAT NMTCS,-1 ; NUMBER OF CHANNELS OPEN ON THIS MTAPE +MTUSR: REPEAT NMTCS,-1 ; USER INDEX OF XPORT +MSNBOL: BLOCK NMTCS ; NUMBER OF BUFFERS ON LIST +MGCABN: REPEAT NMTCS,-1 ; BUFFER ACTIVE AT PI LEVEL +MTBLKS: BLOCK NMTCS ; WRITE, BUFFER SIZE + ; READ, SIZE OF LAST RECORD READ +MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1 ;QDL POINTER +REPEAT NMTCS,[ + CONC MSCB,\.RPCNT,: BLOCK MSCBL ; COMMAND BUFFER + MGRCV ; TO RING BUFFER + + MGNCMD ; GET NEW COMMAND + CONC MGQD,\.RPCNT,: BLOCK MGQDLL + IFE .RPCNT,MSLCTB==.-MSCB0 ; LENGTH OF EACH TABLE +] +MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1 ; INPUT TO COMMAND TABLE +MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1 ; OUTPUT FROM COMAND TABLE +IFE KL10P,MIOWD: BLOCK 2 ; CHANNEL PROGRAM +IFN TM10A,[ +MGDBRK: 0 + CONO MTS,1 + JRST 12,@MGDBRK +];TM10A +MGEMTC: 0 ;CONI MTC, AT LAST ERROR +MGEMTS: 0 ;CONI MTS, AT LAST ERROR +BBLK + +SUBTTL MAG TAPE PI LEVEL + +;ROUTINES TO GET INTERUPT ROUTINES STARTED +MGXGO: MOVE Q,MGQDLP(W) ;GET QDLPOINTER + PUSHJ P,QPOPJ ;CALL ROUTINE . SHOULD FINISH WITH POPJ P,OR PUSHJ Q,CPOPJ + ;PUSHJ Q,CPOPJ IF ROUTINE WANTS TO RETURN + ;POPJ P, IF AT END OF COMAND. AND NEW IS TO BE GOTTEN + MOVEM Q,MGQDLP(W) ; STORE NEW QDL + POPJ P, + +MGRCV: MOVNI A,MSCBL+1 ;AT END OF COMAND LIST,RING IT + ADDM A,MGCMBP(W) ;RING THE BUFFER +MGNCM1: ILDB B,MGCMBP(W) ; GET NEW COMMAND + JRST (B) + +MGNCMD: AOBJN Q,MGNCM1 ; AT BOTTOM OF QDL, SIMULATE PUSHJ AND GET NEW COMMAND + JRST 4,. ;QDL POINTER CLOBBERED + +QPOPJ1: AOS (Q) +QPOPJ: POPJ Q, + +MSTRTR: CONO PI,UTCOFF ; GET MAGTAPE INTURPT STARTED + SETZM MGTBZY + CONO PI,MTCRQ + CONO PI,UTCON + POPJ P, + +;HERE FOR MAG TAPE FLAG CHANNEL INTERUPT +MGHBRK: SKIPGE W,MGUNIT ; LOAD UNIT + JRST MGUBRK ;NO ONE WANTS IT + LDB B,[MUNITF,,A] + CAME W,B ; UNITS AGREE + JRST 4,. ; WE MUST NOT MIX UNITS + MOVE J,C + PUSH P,[DSKEX] +IFN TM10B,[ + TLNE C,160 + JRST MGERR +];TM10B + TRNE C,40000 + JRST MGERR + JRST MGXGO + +MGSBRK: SETOM MGTBZY ;HERE FOR ANY RANDOM MP PI STARTUP + MOVEI B,NMTCS-1 + SKIPG MSCMDC(B) ;ANY COMMANDS IN BUFFER +MGSBK1: SOJGE B,.-1 + SKIPGE B ;LAST UNIT? + JRST DSKEX ; THEN GOTO DSKEX + MOVE W,B + PUSH P,B + MOVSI B,%MACTH + TDNN B,MSRAC(W) ; CORE ALLOCATOR SAYING GO AWAY + PUSHJ P,MGXGO ; START UP THAT ROUTINE + POP P,B + JRST MGSBK1 ; ANY MORE? + +MGUBRK: LDB W,[MUNITF,,A] ; WHO CAUSED INTERUPT? + MOVE B,MTCONO(W) + CONO MTC,(B) + CONO MTS,31 ; CLEAR INTERUPT + JRST DSKEX + +; ROUTINE TO WAIT FOR JOB DONE TO SET +MGWTJD: CONI MTS,J + TRNE J,440000 ;SKIP IF STARTED SUCCESSFULLY + JRST MGERR ;JOB-DONE ISN'T EVER GOING TO SET +MGWJD1: CONI MTS,J + SKIPN MGJDTI ; TIME OUT? + JRST MGWJD2 + MOVE T,TIME + CAML T,MGJDTI + JRST MGERR +MGWJD2: TRNN J,100 ; JOB DONE? + JRST MGOVER ; NOT SET + CONI MTS,J + CONI MTC,I ; GET CONI MTC + MOVEM J,MGCMTS(W) + MOVEM I,MGCMTC(W) + SKIPE MGWCW ; SHOULD I WAIT FOR CONTROL WORD WRITTEN + PUSHJ Q,MGWCWC ; CHECK TO SEE IF IT IS WRITTEN + SETZM MGWCW ;CLEAR FLAG + CONO MTS,30 ; CLEAR CHANNEL CONDITIONS + MOVE B,MTCONO(W) + CONO MTC,(B) ; RELESE MTC, CLEAR JOB DONE +IFN TM10B,[ + TLNE J,160 + POPJ Q, ;CHANNEL ERROR +] + TRNE J,463600 + POPJ Q, ; RANDOM OTHER NON PERFECTIONS, NOT NECESSARILY ERRORS + JRST QPOPJ1 ; SUCCESS + +; GET XPORT +MGGXPT: CONSO MTS,2 ; LOAD NEXT UNIT SET? + JRST MGOVER ; NO, WAIT FOR IT + MOVEM W,MGUNIT + MOVE T,TIME + ADDI T,10.*30. ; TIME OUT IN 10. SECONDS + MOVEM T,MGJDTI + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ; SELECT DRIVE + PUSHJ Q,MGWJD1 + JFCL ; WAIT FOR JOB DONE, BUT ALLOW ANY ERRORS + SETZM MGJDTI + POPJ Q, + +MGOVER: CONSZ MTS,440020 ; ANY PROBLEMS? + JRST MGERR ;TAPE HUNG, ILL FUNCTION, CHANNEL ERROR + SOS (Q) + POPJ P, + +;ERROR +MGERR: CONI MTS,MGEMTS + CONI MTC,MGEMTC + MOVSI T,%MARAC ;READ NOT ACTIVE, FOR SURE + ANDCAM T,MSRAC(W) + SETZM MSCMDC(W) ; NO COMMANDS + SETOM MGUNIT ; CLEAR UNIT WAIT FLAG + SETZM MGJDTI +IFN TM10B,[ + TLNE J,160 ; CHANNEL ERROR? + BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD +];TM10B + SKIPL A,MGCABN(W) ; ANY PI BUFFERS? + PUSHJ P,IMEMR + SETOM MGCABN(W) + HRLZI B,%MAERR ; PI ERROR + IORM B,MSRAC(W) ; STORE IN STATUS WORD + MOVE Q,[-MGQDLL,,MGQD0-1] + MOVE T,MSLCTB + IMUL T,W + ADD Q,T ; RESTORE Q + PUSH P,Q + MOVE Q,[-MSCBL-1,,MSCB0-1] + ADD Q,T + MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMMND POINTERS + MOVE Q,[4400,,MSCB0-1] + ADD Q,T + MOVEM Q,MGCMBP(W) + MOVSI B,%MAREW + ANDCAM B,MSRAC(W) ; CLEAR REWINDING + SKIPN MSCRW(W) ; DONE IF READING + JRST POPQJ + SKIPN MSNBOL(W) ; ANY BUFFERS ON LIST? + JRST POPQJ +MGERR1: HRRZ A,MSBUFP(W) + PUSHJ P,MTICL1 + PUSHJ P,IMEMR + SOSLE MSNBOL(W) ; ANY MORE + JRST MGERR1 + SETZM MSBUFP(W) ;EMPTY LIST + JRST POPQJ + +MGWCWC: +IFN TM10B,[ + SKIPE MICWA+1 ; CONTROL WORD WRITTEN? + POPJ Q, + CONO MTS,4 ; TELL IT TO WRITE IT +MGWCW1: SKIPE MICWA+1 + JRST MGWCW2 ; DONE + PUSHJ Q,CPOPJ ; WAIT + JRST MGWCW1 + +MGWCW2: MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) ;RESTORE STATUS + TLO J,10 ;SET CONTROL WORD WRITTEN +] ;END OF IFN TM10B + POPJ Q, + +IFN TM10A,[ +MGDCSI: SKIPA A,[BLKI MTC,MIOWD] +MGDCSO: MOVE A,[BLKO MTC,MIOWD] + MOVEM A,MAGLOC + MOVE A,[JSR MGDBRK] + MOVEM A,MAGLOC+1 + POPJ Q, +] ;END OF IFN TM10A + +SUBTTL MAG TAPE PI LEVEL WRITE + +MGWRIT: PUSHJ Q,MGGXPT ; GET XPORT + TRNE J,600010 ; WRITE LOCKED,HUNG OR REWINDING + JRST MGERR + MOVEM W,MGUNIT ; SET UNIT + MOVSI A,%MACTH ; CORE ALLOC WANT QUIT TEMPORARLY + TDNE A,MSRAC(W) + JRST MGWRT4 + HRRZ A,MSBUFP(W) ; GET BUFFER POINTER + HLRZ B,MSBUFP(W) ; IN POINTER + SOS MSNBOL(W) ; ONE LESS BUFFER + MOVEM A,MGCABN(W) ; BUFFER ACTIVE AT PI + SKIPN MSCRW(W) ; WRITING + JRST 4,. + CAME A,B ; IN = OUT + JRST MGWRT1 + SETZM MSBUFP(W) ; EMPTY BUFFER LIST + JRST MGWRT2 + +MGWRT1: LDB B,[MLO,,MEMBLT(A)] ; BACK POINTER + HRRM B,MSBUFP(W) ; NEW OUT POINTER +MGWRT2: LDB B,[MWC,,MEMBLT(A)] ; WORD COUNT + MOVNS B ; NEGATE + HRLZS B ; FORM COUNT +IFN KL10P, LSH B,4 ; SHIFT IF KL10 DATA CHANNEL +IFN KL10P, MOVE R,A ; SAVE CORE PAGE NUMBER FOR CACHE SWEEP + LSH A,10. ; FORM WORD POINTER + SUBI A,1 + HRRM A,B ; CHANNEL POINTER IN B +IFN TM10B, DATAO MTS,[MICWA] ; SET TO GO TO MAG TAPE +IFN TM10A, PUSHJ Q,MGDCSO + MOVEM B,MIOWD + MOVEM B,LMIOWD ; LAST MIOWD + SETZM MIOWD+1 ; TELL CHANNEL TO STOP +IFN KL10P,[ + PUSHJ P,CSHSWP ; UNLOAD BUFFER FROM CACHE INTO CORE + CAI +] + MOVE B,MTCONO(W) + CONO MTC,MWRITE(B) ; DO IT + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGWBT ; WRITE BLANK TAPE AND TRY AGAIN +MGWRT3: MOVE A,MGCABN(W) ; GET BUFFER NUMBER + HRLZI B,%MAETW+%MAERR ; END OF TAPE CHECK + TRNE J,4000 ; END POINT + IORM B,MSRAC(W) ; TELL MP + LDB T,[MUR,,MEMBLT(A)] + CAIE T,MUMGB ; DO I OWN BLOCK + JRST 4,. + SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI + PUSHJ P,IMEMR ; GIVE BACK BUFFER + MOVSI A,%MAMSO + IORM A,MSRAC(W) ; TAPE MOVEMENT + JRST MGCMDR + +MGWBT: +IFN TM10B, SETZM MIOWD ; WRITE BLANK TAPE OVER POSSIBLE BAD SPOT +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] + TRNE J,644010 ; BAD TYPES OF ERRORS + JRST MGERR + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ; REVERSE 1 RECORD + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGERR ; ERROR + MOVE B,LMIOWD + MOVEM B,MIOWD ; RESTORE MIOWD + MOVE B,MTCONO(W) + CONO MTC,14000(B) ; WRITE WITH EXTENDED EOR + PUSHJ Q,MGWTJD ; WAIT + JRST MGWBT ; INFINITE RETRIES ; JRST MGERR ; ERRORS + JRST MGWRT3 + +MGWRT4: PUSHJ Q,CPOPJ ; WAIT A WHILE + JRST MGWRIT + +SUBTTL MAG TAPE PI LEVEL READ + +MGREAD: PUSHJ Q,MGGXPT ; GET XPORT +MGRD0: TRNE J,600000 ; UNIT HUNG OR REWINDING OR EOT + JRST MGERR + MOVE B,MGEOFR(W) ; EOF'S READ + CAIL B,2 + JRST MGERR + MOVEM W,MGUNIT ; STORE UNIT NUMBER + SKIPE MSCRW(W) ; MAKE SURE READING + JRST 4,. + MOVSI B,%MACTH ; CORE ALLOCATOR WANT OUT + TDNN B,MSRAC(W) + PUSHJ P,IOMQ + JRST MGROVR ; WAIT FOR IT + MOVEM A,MGCABN(W) ; STORE ACTIVE BUFFER AT PI LEVEL + MOVEI B,MUMGB + DPB B,[MUR,,MEMBLT(A)] ; CLAIM BLOCK + HRREI B,-MGNRTY ; NUMBER OF RETRIES + MOVEM B,MGERRC(W) ; STORE ERROR COUNT +IFN KL10P, MOVE R,A + LSH A,10. ; FORM ADDRESS + SUBI A,1 +IFE KL10P, HRLI B,-2000 +IFN KL10P, HRLI B,-2000_4 + HRR B,A + MOVEM B,LMIOWD ; STORE LAST IOWD FOR RETRY +IFN TM10B, DATAO MTS,[MICWA] ; SET CHANNEL STARTING ADDRESS +IFN TM10A, PUSHJ Q,MGDCSI +IFN TM10B, SETZM MICWA+1 + SETZM MIOWD+1 +MGRD1: MOVEM B,MIOWD ; CHANNEL COMMAND + MOVEI B,2000 + MOVEM B,MGNWRD ; ASSUME AT FIRST THAT THE RECORD TO BE READ HAS 2000 WORDS +IFN KL10P,[ + PUSHJ P,CSHSWP ; ENSURE NO RESIDUE OF THIS PAGE IN CACHE + CAIA +] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ; DO IT +IFN TM10B, SETOM MGWCW ; TELL IT TO WAIT FOR CONTROL WORD WRITTEN + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGRERR +MGRD2: SKIPG A,MGCABN(W) + BUG ;BUFFER SHOULDN'T BE -1, WOULD SCREW UP MEMBLT + SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI + HLRZ T,MSBUFP(W) ;LAST BUFFER IN + SETZM B + DPB B,[MLO,,MEMBLT(A)] ; BACK POINTER IS 0 + SKIPG MSNBOL(W) + HRRM A,MSBUFP(W) ; ONE BUFFER MEANS IN = OUT + HRLM A,MSBUFP(W) ; NEW IN POINTER + SKIPLE MSNBOL(W) + DPB A,[MLO,,MEMBLT(T)] ; CHAIN BACK BUFFERS + AOS C,MSNBOL(W) ; ONE MORE BUFFER ON LIST (COUNT TO C) + MOVE B,MGNWRD + DPB B,[MWC,,MEMBLT(A)] ; NUMBER OF WORDS IN BUFFER + TRNE J,10000 ;EOF? + JRST [ MOVSI B,%MAESO+%MAEFA ;YES + IORM B,MSRAC(W) + SETO B, + DPB B,[MSEOFP,,MEMBLT(A)] + AOS A,MGEOFR(W) + CAIL A,2 + JRST MGRD4 ; LOGICAL EOT, SPACE BACK OVER IT + JRST .+2 ] + SETZM MGEOFR(W) ; NO EOF + MOVSI A,%MAMSO + IORB A,MSRAC(W) ; TAPE MOVEMENT + TRNE J,4000 ; EOT? + JRST MGRD3 + TRNN J,10000 ;IF NO EOF, NOT 6 BUFFERS YET, + CAIL C,6 + JRST MGRD5 + TLNN A,%MASTP + JRST MGRD0 ; AND NO REQUEST TO STOP, KEEP READING +MGRD5: MOVSI A,%MASTP+%MARAC ;GIVE UP FOR NOW, CLEAR READ ACTIVE + ANDCAM A,MSRAC(W) + JRST MGCMDR ;MP LEVEL WILL SEND NEW READ COMMAND WHEN READY + +MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;PHYSICAL EOT + DPB B,[420100,,MSRAC(W)] .SEE %MAETR ; INDICATE EOT ON READ + JRST MGRD5 ; RETURN + +MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT + ANDCAM A,MSRAC(W) + JRST MGSPRF + +MGRERR: +IFN TM10B,[ + TLNE J,160 + JRST MGERR ; CHANNEL ERROR +] + TRNE J,642000 + JRST MGERR + TRNE J,20600 + JRST MGMRT ; DATA TYPE OF ERROR OR OVERRUN, MAYBE TRY AGAIN +;RECORD LENGTH ERROR, ADJUST MGNWRD +IFN TM10B, HRRZ A,MICWA+1 +IFN TM10A, HRRZ A,MIOWD + HRRZ B,LMIOWD + SUB A,B +IFN TM10B, SOS A ; CHANNEL FUNNYNESS + CAIN A,1 ; POS EOF IS ALL + JRST MGRER2 +MGRER1: MOVEM A,MGNWRD + JRST MGRD2 + +MGRER2: TRNE J,14000 ; 1 WORD, EOF? EOT? + SETZM A ; YES, THIS RECORD HAS ZERO LENGTH, IT JUST CARRIES MSEOFP + JRST MGRER1 + +MGMRT: AOSL MGERRC(W) + JRST MGERR ; TOO MANY ERRORS +IFN TM10B, SETZM MIOWD +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ; REVERSE RECORD + PUSHJ Q,MGWTJD + JRST MGERR ; NO ERRORS ALLOWED +IFN TM10A, PUSHJ Q,MGDCSI ; PUT BACK PI 1 BLKI + MOVE B,LMIOWD + JRST MGRD1 ; TRY AGAIN + +MGROVR: PUSHJ Q,CPOPJ + JRST MGREAD + +SUBTTL MAG TAPE PI LEVEL SPACE + +MGSPCF: PUSHJ Q,MGGXPT ; GET XPORT SPACE FORWARD + TRNE J,600000 + JRST MGERR +MGSPC: MOVEM W,MGUNIT + MOVE B,MGRWCD(W) ; GET COMMAND + ADD B,MTCONO(W) +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + CONO MTC,(B) ; DO IT + PUSHJ Q,MGWTJD + JRST MGERR ; NO RETRIES + TRNN J,10000 ; EOF + SETZB B,MGEOFR(W) + TRNE J,10000 + AOS B,MGEOFR(W) + CAIL B,2 ;TOO MANY EOF'S + JRST MGSPRF +MGCMDR: SOS MSCMDC(W) ; GENERAL EXIT ROUTINE + SETOM MGUNIT + SKIPG MSCMDC(W) + POPJ P, ; NO MORE + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ; INTERUPT WHEN UNIT READY + MOVEM W,MGUNIT ; RESTORE UNIT NUMBER + PUSHJ Q,MGWTJD + JRST MGERR + SETOM MGUNIT + POPJ Q, ; MORE + +MGSPFR: MOVEI B,MSPFR ; SPACE FOR RECORD + MOVEM B,MGRWCD(W) + MOVSI B,%MAMSO + IORM B,MSRAC(W) ; TAPE MOVEMENT + JRST MGSPCF + +MGSPFF: MOVSI B,%MAESO + TDZE B,MSRAC(W) + JRST MGCMDR ; EOF ALREADY READ DURING THE READ + AOS MSCMDC(W) ;SO IT WILL RETURN + MOVEI B,MSPFR + MOVEM B,MGRWCD(W) + PUSHJ Q,MGSPCF + SKIPE MGEOFR(W) + JRST MGCMDR ; EOF READ ON SPACE RECORD. DONE + MOVEI B,MSPFF + MOVEM B,MGRWCD(W) + JRST MGSPCF + +MGSPRR: MOVEI B,MSPRR + MOVEM B,MGRWCD(W) + MOVSI B,%MAMSO + IORM B,MSRAC(W) + JRST MGSPCR + +MGSPCR: PUSHJ Q,MGGXPT ; SPACE REVERSE + TRNE J,600000 ; ERR + JRST MGERR + TRNE J,100000 ; BOT + JRST MGCMDR ; THEN DO NOTHING + MOVEM W,MGUNIT + MOVE B,MGRWCD(W) + ADD B,MTCONO(W) +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + CONO MTC,(B) + PUSHJ Q,MGWTJD + JRST MGERR + TRNE J,10000 + SOSGE MGEOFR(W) ; ONE LESS EOF + SETZM MGEOFR(W) + JRST MGCMDR + +MGSPRF: MOVEI B,MSPRF ; REVERSE FILE + MOVEM B,MGRWCD(W) + MOVSI A,%MAESO ; EOF READ IN FORWARD DIRECTION + TDNN A,MSRAC(W) + JRST MGSPCR + AOS MSCMDC(W) ; YES DO IT TWICE + PUSHJ Q,MGSPCR + MOVSI B,%MAESO + ANDCAM B,MSRAC(W) ; TURN OFF FLAG + JRST MGSPCR ; SECOND TIME + +MGRWD1: PUSHJ Q,MGGXPT ; REWIND + MOVEM W,MGUNIT + MOVE B,MGRWCD(W) ; GET COMMAND + ADD B,MTCONO(W) + CONO MTC,(B) + PUSHJ Q,MGWTJD ; WAIT + JRST MGERR + SETZM MGEOFR(W) + MOVSI A,%MAMSO + ANDCAM A,MSRAC(W) ;CLEAR TAPE MOTION +MGRWD2: TRNN J,200000 ; STILL REWINDING? + JRST MGRWD3 ; NO + PUSHJ Q,CPOPJ ; WAIT + CONI MTS,J + MOVEM J,MGCMTS(W) + JRST MGRWD2 + +MGRWD3: MOVE T,TIME ;WAIT 1 SECOND MORE + ADDI T,30. ;THIS IS AN ATTEMPT TO FIX A HARDWARE BUG + MOVEM T,MGJDTI +MGRWD4: MOVE T,TIME + CAML T,MGJDTI + JRST [ SETZM MGJDTI + POPJ Q, ] + PUSHJ Q,CPOPJ + JRST MGRWD4 + +MGRWND: MOVEI B,MREWND ; NORMAL REWIND + CAIA +MGRWDM: MOVEI B,MRWNDD ; REWIND AND DISMOUNT + MOVEM B,MGRWCD(W) + PUSHJ Q,MGRWD1 + MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) + JRST MGCMDR + +MGSEOT: PUSHJ Q,MGGXPT ; SKIP TO LOGICAL EOT + TRNE J,600000 + JRST MGERR + MOVEM W,MGUNIT + TRNE J,100000 ; BOT? + JRST MGVTCK ; VIRGIN TAPE CHECK +MGNVT: MOVE B,MTCONO(W) +IFN TM10A,[ + PUSHJ Q,MGDCSO + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] +IFN TM10B, SETZM MIOWD + CONO MTC,MSPRR(B) ; SPACE REVERSE FIRST + PUSHJ Q,MGWTJD ; WAIT + JRST MGERR + SETZM MGEOFR(W) + AOS MGEOFR(W) +MGEOT2: MOVE B,MTCONO(W) + CONO MTC,MSPFF(B) ; SKIP FORWARD FILE + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAETR ; EOT CHECK + TRNE J,4000 + IORM B,MSRAC(W) ; TELL MP + MOVE B,MTCONO(W) +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] +IFN TM10B, SETZM MIOWD + CONO MTC,MSPFR(B) ; SPACE FORWARD RECORD + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAETR ; EOT AGAIN + TRNE J,4000 + IORM B,MSRAC(W) ; TELL MP + TRNN J,10000 ; EOF ALSO? + JRST MGEOT2 ; NO, TRY AGAIN + MOVE B,MTCONO(W) ; YES, NOW GO BACK OVER LAST + CONO MTC,MSPRF(B) + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAEOF+%MAETR ; TELL MP,EOF + IORM B,MSRAC(W) + JRST MGCMDR + +MGVTCK: MOVE T,TIME + ADDI T,60. ; TWO SECOND TIME OUT + MOVEM T,MGEOTT(W) ; EOT TIME +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ; DO READ, WAIT EITHER FOR JOB DONE OR TIME OUT +MGVTC1: CONI MTS,J + MOVEM J,MGCMTS(W) + TRNE J,100 ; J D? + JRST MGNVT ; NOT VIRGIN TAPE + TRNE J,440000 + JRST MGERR ; ERRORS? + MOVE T,MGEOTT(W) + CAMG T,TIME ; TIME UP? + JRST MGVT ; YES + PUSHJ Q,CPOPJ ; WAIT + JRST MGVTC1 + +MGVT: MOVE B,MTCONO(W) + CONO MTS,31 + CONO MTC,MNOPIN(B) ; NO-OP WAIT FOR JOB DONE + PUSHJ Q,MGWTJD + JFCL ; SEE IF I CARE IF THERE ARE ERRORS + MOVEI B,MREWND + MOVEM B,MGRWCD(W) + PUSHJ Q,MGRWD1 ; REWIND + SETZM MGEOFR(W) + AOS MGEOFR(W) + JRST MGCMDR ; RETURN + +MGMEOT: PUSHJ Q,MGGXPT + TRNE J,600000 + JRST MGERR + MOVEM W,MGUNIT + SKIPE MTCEFW(W) ;HOW MANY EOF WRITTEN? + JRST MGMET1 + AOS MSCMDC(W) ; SO WILL RETURN + AOS MTCEFW(W) + PUSHJ Q,MGWEOF +MGMET1: MOVE A,MTCEFW(W) + SOSLE A + JRST MGMET2 + AOS MSCMDC(W) + AOS MTCEFW(W) + PUSHJ Q,MGWEOF +MGMET2: MOVE A,MSRAC(W) + TLNE A,%MANWT ; BACK OVER LAST? + JRST MGMET3 ; NO + AOS MSCMDC(W) ; SO IT WILL RETURN + PUSHJ Q,MGSPRF +MGMET3: MOVSI A,%MANWT + IORM A,MSRAC(W) + JRST MGCMDR ; DONE + +; WRITE EOF +MGWEOF: PUSHJ Q,MGGXPT + TRNE J,600010 + JRST MGERR + MOVEM W,MGUNIT + MOVE B,MTCONO(W) + CONO MTC,MWEOF(B) + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI A,%MAMSO + IORM A,MSRAC(W) ; TAPE MOVEMENT + JRST MGCMDR ; RETURN + +MGSTAT: PUSHJ Q,MGGXPT ; GETS STATUS + JRST MGCMDR + +MGW3IN: PUSHJ Q,MGGXPT + TRNE J,600010 + JRST MGERR + MOVEM W,MGUNIT +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MW3IN(B) ; WRITE THE RANDOM WORD PRECEEDED BY 3 INCHES OF BLANK TAPE + PUSHJ Q,MGWTJD + JFCL ; ALLOW BAD TAPE ERROR + JRST MGSPRR ; NOW SPACE RECORD REVERSE OVER THE ONE WORD + +SUBTTL .MTAPE UUO + +;.MTAPE AC, +; AC/ CHNM,COMMAND +; COMMAND/ COUNT,,FUNCTION + +AMTAPE: XCTR XR,[HLRZ R,(J)] + TRNE R,-NIOCHN + JRST ILUUO + HRRZM R,UUAC(U) ; SO THAT ERRORS WILL BE REPORTED ON THE + ; CORRECT CHANNEL + ADDI R,IOCHNM(U) ; FORM IOCHNM POINTER + HRRZ A,(R) ; A: CLSTB/IOTTB index + CAIL A,MTUAIX ; Min index for tape + CAILE A,MTBOX ; Max + POPJ P, ; Laconic error reportage. + LDB W,[MTXP(R)] ; GET XPORT NUMBER + CAME U,MTUSR(W) ; SAME USER + POPJ P, ; NO + UMOVE J,(J) + MOVEM J,MTMTAP(W) ; SAVE J + HRRZ A,MTMTAP(W) + PUSHJ P,MTIECK + UMOVE A,(A) + HRRZM A,MTMFNC(W) ;STORE FUNCTION + HLREM A,MTMCNT(W) ;AND COUNT + SKIPN MTMCNT(W) ;A COUNT OF ZERO ALWAYS MEANS ONE, FOR COMPATIBILITY + AOS MTMCNT(W) ; WITH THE OLD CODE. + HRRZS A + CAIL A,NMTAPC ; LEGAL COMMAND + POPJ P, ; NO + AOS (P) ; SKIP RETURN + JRST @MTAPDT(A) + +MTAPDT: MTHANG ;0 HANG TILL TAPE MOTION DONE + MTRWND ;1 REWIND + MTRWDM ;2 REWIND AND DISMOUNT + MTWEOR ;3 WRITE EOR IF APPROPRIATE + MTW3IN ;4 WRITE 3 INCHES OF BLANK TAPE + MTWEOF ;5 WRITE EOF + MTSPR ;6 SPACE RECORDS + MTSPF ;7 SPACE FILES + MTSPEOT ;10 SPACE TO EOT + MTSTOP ;11 STOP ALL COMMAND ASSOCIATED WITH THIS COMMAND + MTSBKS ;12 SET BLOCK SIZE (TO COUNT) + MTRBKS ;13 READ BLOCK SIZE (TO AC) +NMTAPC==.-MTAPDT + +MTSBKS: MOVE A,MTMCNT(W) ;DESIRED BLOCKSIZE + CAIL A,4 ;CHECK REASONABLENESS + CAILE A,2000 + SOSA (P) ;FAIL IF TOO BIG OR TOO SMALL + MOVEM A,MTBLKS(W) ;OK, CHANGE WRITE-BUFFER SIZE + POPJ P, + +MTRBKS: MOVE A,MTBLKS(W) + JRST APTUAJ + +MTHANG: SKIPLE MSCMDC(W) ; HANG UNTILL ALL MOTION FINISHED + PUSHJ P,UFLS + JRST MTIECK + +MTRWND: MOVEI B,MGRWND ; REWIND +MTRWD1: SKIPE MSCRW(W) + JRST MTSOSP + MOVSI A,%MAREW + IORM A,MSRAC(W) + JRST MTCMD + +MTRWDM: MOVEI B,MGRWDM ; REWIND AND DISMOUNT + JRST MTRWD1 + +;"WRITE END OF RECORD" - THIS IS REALLY THE FORCE SYSTEM CALL, OR SHOULD BE. +MTWEOR: SKIPG MTMDN(W) ; ANY BUFFERS STARTED + POPJ P, ; NO + SKIPE MSCRW(W) ; WRITING + JRST MTWBFD ; DISCARD BUFFER +MTSOSP: SOS (P) ; NOT WRITING, ERROR + POPJ P, + +MTWEOF: SKIPN MSCRW(W) ; WRITING? + JRST MTSOSP ; NO + PUSHJ P,MTWEOR + MOVEI B,MGWEOF ; WRITE EOF + AOS MTCEFW(W) + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) ; SOMETHING WRITTEN + JRST MTCMD + +MTW3IN: SKIPN MSCRW(W) ; WRITING? + JRST MTSOSP + MOVEI B,MGW3IN + SETZM MTCEFW(W) + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) + JRST MTCMD + +;SPACE RECORDS, +=FORWARD, -=BACK +MTSPR: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING + JRST MTSOSP + PUSHJ P,MTFLRA ;FLUSH READ-AHEAD, FIND OUT HOW FAR OFF WE ARE + ADD B,C ;NUMBER OF RECORDS TAPE IS AHEAD OF USER (EOF=RECORD) + MOVNS B ;SUBTRACT THIS FROM USER'S REQUEST + ADDB B,MTMCNT(W) + JUMPE B,CPOPJ ;IF COUNT IS NOW ZERO, WE ARE DONE +MTSPR1: PUSHJ P,MTCNTR ;UPDATE USER'S COPY IN CASE PCLSR + JUMPG B,MTSPFR ; SPACE FORWARD + MOVEI B,MGSPRR ; SPACE REVERSE + PUSHJ P,MTCMD + AOSGE B,MTMCNT(W) + JRST MTSPR1 ;MORE + POPJ P, + +MTSPFR: MOVEI B,MGSPFR + PUSHJ P,MTCMD + SOSLE B,MTMCNT(W) + JRST MTSPR1 ;MORE + POPJ P, + +;THIS ROUTINE FLUSHES READAHEAD. CALL BEFORE DOING A SPACING OPERATION +;THIS DOESN'T ACTUALLY UNDO THE EFFECT ON THE DRIVE +;OF THE READ-AHEAD. IT DOES MAKE SURE THAT READ-AHEAD'S EFFECT CAN'T +;CHANGE, THEN RETURNS IN B THE NUMBER OF RECORDS AHEAD (NON-NEGATIVE) +;AND IN C THE NUMBER OF EOF'S AHEAD (0 OR 1). IF CALLED TWICE IT WILL +;RETURN ZERO THE SECOND TIME. BE SURE TO UPDATE YOUR PARAMETERS. +MTFLRA: PUSHJ P,MTCNTR ;FIRST, ENSURE WRITEABILITY, MUSTN'T PCLSR IN MTCNTR LATER + MOVSI B,%MASTP + MOVSI T,%MARAC + IORM B,MSRAC(W) ;IF READ IS ACTIVE, TELL IT TO STOP + TDNE T,MSRAC(W) ;AWAIT CESSATION OF READ + PUSHJ P,UFLS ;IF THIS PCLSR'S OUT WITH %MASTP SET, NO GREAT HARM DONE. + ANDCAM B,MSRAC(W) ;THEN TURN OFF %MASTP, THINGS ARE NOW QUIET + SKIPLE MSCMDC(W) ;BEFORE MESSING WITH BUFFERS, WAIT FOR PI TO QUIESCE + PUSHJ P,UFLS + MOVE B,MSNBOL(W) ;NUMBER OF BUFFERS = NUMBER OF RECORDS + LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 IF PAST EOF WHICH THE USER DOESN'T KNOW ABOUT + MOVSI T,%MAEFA ;NOW GET RID OF THE READ-AHEAD + ANDCAM T,MSRAC(W) + JRST MTCBFF + +MTSPF: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING + JRST MTSOSP + PUSHJ P,MTFLRA ;FLUSH READ-AHEAD + MOVN B,C ;NUMBER OF FILES TAPE IS AHEAD OF USER + ADDB B,MTMCNT(W) + JUMPE B,CPOPJ ;DONE +MTSPF1: PUSHJ P,MTCNTR ;UPDATE USER'S COUNT IN CASE OF PCLSR + JUMPG B,MTSPFF ; SPACE FORWARD FILES + MOVEI B,MGSPRF + PUSHJ P,MTCMD + AOSGE B,MTMCNT(W) + JRST MTSPF1 ;MORE + POPJ P, + +MTSPFF: MOVEI B,MGSPFF + PUSHJ P,MTCMD + SOSLE B,MTMCNT(W) + JRST MTSPF1 ;MORE + POPJ P, + +MTCNTR: HRRZ A,MTMTAP(W) + MOVE T,MTMFNC(W) + HRL T,MTMCNT(W) + UMOVEM T,(A) + POPJ P, + +MTSTAT: SKIPLE MSCMDC(W) ; WAIT TILL ALL COMMANDS DONE + PUSHJ P,UFLS + MOVEI B,MGSTAT ; GET CONI'S + PUSHJ P,MTCMD ; GIVE TO PI + SKIPLE MSCMDC(W) ; WAIT TILL DONE + PUSHJ P,UFLS + MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) + POPJ P, + +MTSPEOT: MOVEI B,MGSEOT ; SPACE TO LOGICAL EOT + JRST MTCMD ;NOTE THIS IS INDEPENDENT OF READ-AHEAD + +MTSTOP: CONO PI,UTCOFF ;THIS DOESN'T DEAL WITH READ-AHEAD, PROBABLY OK + SETZM MSCMDC(W) ;NO MORE COMANDS + MOVE Q,[-MGQDLL,,MGQD0-1] + MOVE T,MSLCTB + IMUL T,W + ADD Q,T + MOVEM Q,MGQDLP(W) ; RESTORE Q + MOVE Q,[-MSCBL-1,,MSCB0-1] + ADD Q,T + MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMAND POINTERS + MOVE Q,[4400,,MSCB0-1] + ADD Q,T + MOVEM Q,MGCMBP(W) + SKIPL A,MTMDN(W) + PUSHJ P,IMEMR ; RELEASE MP BUFFER + SETOM MTMDN(W) + SETZM MSMPRP(W) + SETZM MSMPRC(W) ; SO BLKT WON'T GET UNHAPPY + PUSHJ P,MTCBFF ; FLUSH BUFFER LIST + CAME W,MGUNIT ; SAME UNIT? + JRST UTCONJ + SETOM MGUNIT ; SO INTERUPT WILL GO AWAY + CONI MTC,I ; SEE WHAT DRIVE IS BEING TALKED TO + LDB B,[MUNITF,,I] + CAME W,B + JRST UTCONJ ; IF NOT SAME UNIT, DON'T DO ANYTHING + MOVE B,MTCONO(W) + CONO MTS,31 ; STOP THE TAPE + CONO MTC,(B) ; CLEAR INTERUPTS + SKIPGE A,MGCABN(W) ; ANY BUFFERS ACTIVE AT PI + JRST UTCONJ ; NO + PUSHJ P,IMEMR ; RETURN IT + SETOM MGCABN(W) + JRST UTCONJ + +SUBTTL MAG TAPE CLOSE ROUTINES + +MTOCL: LDB W,[MTXP(R)] + SOSL MTUSE(W) + POPJ P, ; NOT ONLY CHANNEL OPEN + AOS MTUSE(W) ; INCASE PCLSRED + MOVSI A,%MAERR ;ERROR? + TDNE A,MSRAC(W) + PUSHJ P,MTOCL3 +; MOVEI T,MSCBL-4 +; CAMG T,MSCMDC(W) +; PUSHJ P,UFLS ; WAIT FOR ROOM FOR THREE COMMANDS + SKIPL MTMDN(W) ; MAG TAPE OUTPUT CLOSE + PUSHJ P,MTWBFD ; WRITE OUT BUFFERS +; MOVEI B,MGWEOF ; WRITE OUT TWO EOF(S) +; SKIPE MTCEFW(W) +; JRST MTOCL2 ; MAY HAVE BEEN PCLSRED +;MTOCL1: PUSHJ P,MTCMD +; AOS MTCEFW(W) ; ONE MORE CLOSE EOF WRITTEN +;MTOCL2: MOVE A,MTCEFW(W) +; SOSG A ; DON'T WRITE EOF IF PCLSRED +; PUSHJ P,MTCMD ; DO IT TWICE +; SKIPG A +; AOS MTCEFW(W) +; MOVEI B,MGSPRF +; MOVE A,MSRAC(W) +; TLNN A,1000 +; PUSHJ P,MTCMD ; NOW BACK UP OVER ONE +; MOVSI A,1000 +; IORM A,MSRAC(W) + MOVEI B,MGMEOT ; MAKE EOT + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) ; NOW WAIT TILL DONE + PUSHJ P,UFLS + MOVEI A,1 + MOVEM A,MGEOFR(W) + SKIPL MTMDN(W) ;ANY ACTIVE BUFFERS + JRST 4,. + SKIPL MGCABN(W) + JRST 4,. + SKIPE MSNBOL(W) + JRST 4,. + SETOM MTUSR(W) + SETOM MTUSE(W) + SETZM MSRAC(W) + POPJ P, + +MTOCL3: SKIPL A,MTMDN(W) + PUSHJ P,MEMR ; IF BUFFER AROUND,FLUSH IT + SETOM MTMDN(W) + SETZM MSMPRC(W) + POPJ P, + +MTICL: LDB W,[MTXP(R)] + SOSL MTUSE(W) ; LAST USER + POPJ P, + AOS MTUSE(W) + MOVEI T,1 + CAMGE T,MSCMDC(W) ; ALLOW ONE COMMAND IF REWINDING + PUSHJ P,UFLS ; ALL COMMANDS DONE + MOVE T,MSRAC(W) + TLNE T,%MAREW ; REWINDING? + JRST MTICL3 ; YES + SKIPLE MSCMDC(W) ; NO, WAIT TILL COMMAND DONE + PUSHJ P,UFLS +MTICL3: SKIPL MGCABN(W) ; ANY PI BUFFERS LEFT + JRST 4,. + PUSHJ P,MTRBD ;GET RID OF M.P. BUF, IF ANY + SETOM MTUSR(W) + PUSHJ P,MTCBFF ; FREE BUFFERS + SOS MTUSE(W) + MOVE T,MSRAC(W) + TLNE T,%MAREW ; DON'T HAVE TO SKIP TO EOF IF REWINDING + JRST MTICL2 + MOVSI A,20 + TDNE A,(R) ;CHECK TO SKIP TO EOF + JRST MTICL2 + MOVSI A,%MAMSO + TDNN A,MSRAC(W) ;TAPE MOVEMENT + JRST MTICL2 ; NO + SKIPE MGEOFR(W) ;NO TIMING CONFLECT HERE SINCE WE WAITED FOR PI TO CLEAR + JRST MTICL2 ;NOTE THAT THIS DISPOSES OF A READ-AHEAD EOF. + PUSHJ P,MTSTAT + MOVE B,MGCMTS(W) + TRNE B,100000 + JRST MTICL2 + MOVEI B,MGSPFF + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) + PUSHJ P,UFLS +MTICL2: MOVSI T,%MAREW + ANDM T,MSRAC(W) ;CLEAR ALL BUT REWINDING + POPJ P, ; NO, DONE + +MTCBFF: SKIPN MSNBOL(W) ;ANY BUFFERS ON CHAIN? + POPJ P, + HRRZ A,MSBUFP(W) ;YES, FREE ONE + PUSHJ P,MTICL1 ; FIX CHAIN + PUSHJ P,MEMR ; RETURN BUFFER + SOSLE MSNBOL(W) ;ANY MORE? + JRST MTCBFF + SETZM MSBUFP(W) ;EMPTY LIST + POPJ P, + +MTICL1: LDB T,[MLO,,MEMBLT(A)] ; GET BACK POINTER + HRRM T,MSBUFP(W) + POPJ P, diff --git a/src/system/ncp.9 b/src/system/ncp.9 new file mode 100755 index 00000000..22a2c60a --- /dev/null +++ b/src/system/ncp.9 @@ -0,0 +1,2761 @@ +SUBTTL ARPANET NCP variables and tables + +EBLK +IMPMQS==13. ;MESSAGE QUEUE SIZE (LENGTH WORD, 6-WORD LEADER, 6-WORD TEXT) +;MAIN PROGRAM CONTROL MESSAGE VARIABLES +IMPMPU: -1 ;-1 => FREE + 0 ;SWTL THREAD +IMPMPL: -1 ;LINK WORD FOR CONTROL LINK QUEUE +IMPMPC: BLOCK IMPMQS ;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT + +;PI CONTROL MESSAGE VARIABLES +IMNPIC==NNETCH+3 ;NUMBER OF BLOCKS IN PI CONTROL QUEUE +;HOPEFULLY THIS IS ENOUGH. THE CODE RESPONDS VERY UNGRACEFULLY TO THIS +;QUEUE FILLING UP. IN PARTICULAR, WHEN IT HOLDS UP INPUT IT CAN CAUSE +;A DEADLOCK BY PREVENTING ITSELF FROM SEEING A CONTROL-LINK RFNM IT +;NEEDS IN ORDER TO SEND SOMETHING THAT'S IN THE QUEUE AND FREE UP SOME +;SPACE. FURTHERMORE THE IMP IS UNGRACEFUL AND WILL SOMETIMES REFUSE TO +;READ INPUT FROM US (EVEN IN THE MIDDLE OF A MESSAGE) UNTIL WE READ +;INPUT FROM IT. BUT WE DO THE SAME THING WHEN THIS QUEUE FILLS UP. +;FURTHERMORE SOMETIMES THE CORE JOB WILL WAIT FOR A NETWORK +;TRANSMISSION TO COMPLETE SO IT CAN MOVE A NETWORK BUFFER, HANGING THE +;ENTIRE SYSTEM. THE CORE-JOB WILL UNHANG AFTER THE IMP TIMES OUT AND +;FLASHES ITS READY LINE (SEE IMPBER). +;** BUT SOMETIMES THE IMP NEVER TIMES OUT AND SO THE SYSTEM IS HUNG ** + +IMPCQ: REPEAT IMNPIC-1,[ + .+IMPMQS+1 ;POINTER TO NEXT FREE OR NEXT IN QUEUE + BLOCK IMPMQS ;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT +] + -1 + BLOCK IMPMQS +IMPNCQ: -1 ;NEXT ENTRY TO BE SENT. -1 IF NONE +IMPLCQ: -1 ;POINTER TO LAST ENTRY IN CONTROL QUEUE +IMFFCQ: IMPCQ ;POINTER TO FIRST FREE. -1 IF NONE +IMFCQL: IMNPIC ;NUMBER FREE CONTROL QUEUE ENTRIES LEFT + +;PENDING RFC QUEUE +IMNPQ==20 ;NUMBER OF PENDING QUEUE ENTRIES +;(0) POINTER TO NEXT IN CHAIN OR NEXT FREE. -1 IF NONE +;(1) LOCAL SOCKET NUMBER +;(2) FOREIGN SOCKET NUMBER +;(3) 4.9 = 1 => RTS = 0 => STR +; 1.1-1.8 = LINK NUMBER OR BYTE SIZE +; 1.9-2.7 = FOREIGN HOST NUMBER +; 3.1-3.9 = TIME RFC RECEIVED, IN SECONDS MOD 512. + IMPPQ ;IMPBPQ-1 IS BEGINNING OF GETSYS BLOCK, THIS WORD FOR UNRELOCATION +IMPBPQ: -1 ;BEGINNING OF PENDING QUEUE. -1 IF EMPTY +IMPPQ: REPEAT IMNPQ-1,[ + .+4 + BLOCK 3 +] + -1 + BLOCK 3 +IMPEPQ: -1 ;END OF PENDING QUEUE. -1 IF EMPTY (IMPEPQ IS END FOR GETSYS BLOCK) +IMFFPQ: IMPPQ ;FIRST FREE PENDING QUEUE ENTRY. -1 IF NONE + +;SOCKET TABLE + +IMSOKB: IMPSTL ;BEGIN OF GETSYS BLOCK, LENGTH STORED HERE + +IMSOC1: REPEAT IMPSTL,0 ;0 => FREE + ;>0 MEANS ALLOCATED, NOT SET UP YET + ;4.9 = 1 => SOCKET IN USE + ;4.8 = 1 => CHNL TRYING TO BE CLOSED + ;3.1-4.7 = MASK FOR CHANNEL SOCKET IS OPEN ON. + ;RH = USER INDEX + +IMSOC2: BLOCK IMPSTL ;1.1-4.5 = LOCAL SOCKET NUMBER + ;4.6-4.9 0 (MAKES COMPARISONS EASIER) +IMSOC3: BLOCK IMPSTL ;1.1-4.5 = FOREIGN SOCKET NUMBER + ;4.6-4.9 = 0 +IMSOC4: BLOCK IMPSTL ;3.1-3.8 = LINK NUMBER + ;3.9-4.7 = FOREIGN HOST NUMBER (IMPHTB INDEX) + ; 377 MEANS NOT USING ANY HOST + ;4.8 = SET BY RCV CLS - MAKES MATCH USING IMSCHD FAIL + ;4.9 = SEND THIS BUFFER NOW + .SEE %NS ;RH = SOCKET STATE +IMSOC5: BLOCK IMPSTL ;1.1 - 1.9 => TTY # OF STY, IF CONNECTED TO ONE. + ;2.1-2.9 = CLOSE-REASON + ;3.1-3.8 = CONNECTION BYTE SIZE + ;3.9 => ASCII MODE - 7 BIT + ;4.1 => ASCII MODE - 8 BIT + ;4.2 => 1 BIT BYTES + ;4.3 => NET INT (INR\INS) RECEIVED + ;4.4 => HAVE BEGUN COUNTING THE CLOSE TIME-OUT. + ;4.5 => CLOSED WHILE IN RFNM WAIT, EXPECT ANOTHER RFNM + ;4.6 => CONNECTED DIRECTLY TO A STY. + ;4.7 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION + ;4.8 => STY WANTS WAKEUP AT 1/2 SEC CLK + ;4.9 => TRANSFER IN 32 BIT MODE +IMSOC6: BLOCK IMPSTL ;RH => BUFFER ADDRESS + ;4.9 => LOCKED BY CORE JOB + ;4.8 => ACTIVE AT PI LEVEL + ;4.7 => INPUT OCCURRED WHILE BUFFER LOCKED + ;3.1-3.8 => IOBFT INDEX (377 IF USING BIG BUFFER) +IMSOC7: BLOCK IMPSTL ;BIT ALLOCATION +IMSOC8: BLOCK IMPSTL ;MESSAGE ALLOCATION +IMSC7I: BLOCK IMPSTL ;AMT TO INCREASE BIT ALLOCATION BY IN NEXT ALLOC MSG (INPUT) + ;FOR OUTPUT, HAS NUMBER OF BITS IN BUFFER +IMSC8I: BLOCK IMPSTL ;AMT TO INCREASE MESSAGE ALLOCATION BY NEXT ALLOC MSG (INPUT) +IMSOCT: BLOCK IMPSTL ;TIME WHEN FIRST MESS PUT INTO BUF + ;(DURING INPUT HAS NUMBER OF DATA BYTES LEFT IN CUR MSG) + ;(DURING CLOSE HAS TIME TIME-OUT STARTED) +IMSMPP: BLOCK IMPSTL ;MAIN PROGRAM POINTER, ILDB OR IDPB FOR NEXT BYTE +IMSMPC: BLOCK IMPSTL ;MAIN PROGRAM COUNTER, FOR OUTPUT HAS NUMBER OF DATA + ; BYTES OF ROOM LEFT IN BUFFER. FOR INPUT HAS TOTAL + ; NUMBER OF DATA BYTES IN BUFFER. +IMSPIP: BLOCK IMPSTL ;INTERRUPT LEVEL POINTER, FOR OUTPUT ILDB TO GET NEXT + ; BYTE OUT AT P.I. LEVEL. FOR INPUT POINTS TO WHERE + ; HEADER WORD OF NEXT MESSAGE IN WILL BE STORED. +IMSBFE: BLOCK IMPSTL ;BYTE POINTER TO LAST BYTE IN BUFFER + ;USE CAILE X,@IMSBFE(I) TO CHECK A WORD ADDRESS +IMSOKE==.-1 ;END OF BLOCK FOR GETSYS CALL + +BBLK + +IMSCLN: 221000,,IMSOC4(I) ;LINK NUMBER +IMSCBS: 221000,,IMSOC5(I) ;BYTE SIZE +IMSCLS: 111100,,IMSOC5(I) ;CLOSE REASON +IMSCFH: 321000,,IMSOC4(I) ;FOREIGN HOST +IMSCHD: 222100,,IMSOC4(I) ;FOREIGN HOST AND LINK NUMBER + ; EXTRA BIT, SET WHEN RCV CLS +IMSCHL: 222000,,IMSOC4(I) ;FOREIGN HOST AND LINK WITHOUT EXTRA BIT + +NTRFCL: SIXBIT /NETRFC/ ;FOR ICP ON ANY SOCKET < 1000 +EBLK + 0 + +NETSRS==1000 ;SMALLEST USER RECEIVE SOCKET NUMBER +NRSOC: NETSRS ;NUMBER OF NEXT RECEIVE SOCKET TO BE GENERATED +NETOSW: -1 ;SWITCH LOCKED AT NET OPEN + 0 +NETHSW: -1 ;SWITCH LOCKED IF HACKING HOST TABLE (IMPHTB) + 0 +NETLST: 0 ;LIST OF USERS IN NETWORK OPEN CODE + +;INPUT BUFFER FORMAT: +;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG. +;MAY CONTAIN SEVERAL MESSAGES. EACH CONSISTS OF A HEADER WORD CONTAINING +; THE NUMBER OF BYTES IN THE MESSAGE, FOLLOWED BY THE BYTES, FOLLOWED BY +; UNUSED BITS UP TO THE NEXT WORD BOUNDARY. THIS WEIRD FORMAT IS USED +; TO AVOID HAVING TO DO BYTE OPERATIONS AT P.I. LEVEL. +;A HEADER WORD OF -1 MEANS THAT THAT MESSAGE HAS NOT YET BEEN STORED. +;IMSPIP(I) ALWAYS CONTAINS THE ADDRESS OF A HEADER WORD OF -1. +;IMSMPP(I) HAS A BYTE POINTER TO THE NEXT DATA BYTE TO BE READ. +;P.I. LEVEL CAN STORE A MESSAGE INTO THE PART OF THE BUFFER FROM +;@IMSPIP TO @IMSMPP-1. +;IMSOCT(I) HAS THE NUMBER OF BYTES THAT MAIN PROGRAM LEVEL CAN +; READ BEFORE IT GETS TO THE END OF THE CURRENT MESSAGE AND HAS +; TO CHECK THE NEXT HEADER. +;IMSMPC(I) HAS THE TOTAL NUMBER OF DATA BYTES IN ALL THE MESSAGES +; IN THE BUFFER. + +;OUTPUT BUFFER FORMAT: +;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG. +;IT SIMPLY CONTAINS A STRING OF BYTES. +;IMSMPP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE OUTPUT WILL BE DEPOSITED. +;IMSPIP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE SENT OUT AT P.I. +; LEVEL WILL COME FROM. P.I. LEVEL TRIES TO KEEP EVERYTHING ALIGNED ON +; WORD BOUNDARIES SO THAT IT DOESN'T HAVE TO DO BYTE OPERATIONS. +;IMSMPC(I) HAS THE NUMBER OF BYTES THAT MP LEVEL MAY STORE BEFORE RUNNING +; INTO OLD BYTES THAT HAVEN'T YET BEEN TRANSMITTED. +;IMSOCT(I) IS SET TO THE TIME THE FIRST BYTE IS PUT INTO THE BUFFER. +; IT IS CLEARED WHENEVER THE BUFFER GETS EMPTIED. + +BBLK + +SUBTTL ARPANET NCP Main Prog system call routines + +;NET .CALL RCHST/RFNAME +NETRCH: MOVEI W,8 ;WE RETURN 8 VALUES. + HRRE I,A + JUMPL I,NETRC3 ;NET WENT DOWN AFTER THIS CHANNEL WAS OPENED. + MOVE B,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVE C,IMSOC3(I) ;FOREIGN SOCKET NUMBER + LDB TT,IMSCFH ;FOREIGN HOST FOR 4TH WORD. + CAIN TT,377 + TDZA D,D ; 377 MEANS NOT USING ANY HOST +IFN 1,[ + JRST [MOVE D,A + MOVE A,IMPHTN(TT) ; Get host addr + TLO A,(NW%ARP) ; Make full HOSTS3 format + CALL CVH2NA ; Convert to HOSTS2 for compatibility + EXCH A,D + JRST .+1] +] ;IFN 1 +IFN 0,[ + TDZA Q,Q + MOVE Q,IMPHTN(TT) + LDB D,[112000,,Q] ;TRANSLATE NEW HOST NUMBER TO OLD + ANDI Q,377 ;IF IT WILL FIT IN OLD NOTATION + CAIGE D,100 + CAIL Q,4 + SKIPA D,IMPHTN(TT) + DPB Q,[060200,,D] +] ;IFN 0 + + LDB Q,IMSCBS ;GET BYTE SIZE FOR HERE AND BELOW +;FOLLOWING LINE HAS BEEN PUNTED, AN INCOMPATIBLE CHANGE +; DPB Q,[111100,,D] ;INTO 2.9-2.1 OF 4TH WORD + MOVE A,IMSOC5(I) ;RANDOM WORD + TLNE A,4000 ;SKIP IF 4.3 BIT OFF (NETWRK INT) + TLO D,400000 ;SET FOR USER + PUSHJ P,NETRC1 ;GET TIME IMP GOING DOWN, + HRR TT,IMSOC4(I) ;MERGE IN SOCKET STATE. + IMUL Q,IMSMPC(I) ;MULTIPLY BYTE SIZE BY BYTES AVAIL TO GET BITS AVAIL + LDB I,IMSCLS ;CLS REASON + POPJ P, + +NETRC3: MOVEI I,%NCNCP ;GIVE CLOSE REASON THAT OUR NCP WENT DOWN. +NETRC1: SKIPG TT,IMPDWN+1 ;SYS TIME AT WHICH IMP IS GOING DOWN + JRST NETRC2 + SUB TT,TIME ;(TIME TIL IMP DOWN -1=NOT. 0=DOWN, +=GOING DOWN, N/30. SEC) + SKIPG TT + MOVEI TT,1 ;IF SET TO GO DOWN, AND TIME "PASSED", SAY SOON IF NOT ALREADY DOWN +NETRC2: HRLZS TT + POPJ P, + +;NET .CALL STATUS - SOCKET STATE IN BITS 2.4-2.9 +STANET: TRNN A,400000 ;SKIP IF NET WENT DOWN ON THIS LOSER + SKIPA E,IMSOC4(A) ;GET STATE + MOVEI E,0 ;IF NCP WENT DOWN, STATE IS "CLOSED" + DPB E,[140600,,D] + POPJ P, + +;NET .CALL RESET - ONLY RESETS "INT FM NETWORK" BIT (INR/INS) +NETRS: HLRZ A,(R) ;GET LH IOCHNM + MOVSI B,4000 ;4.3 BIT + TRNN A,400000 ;SKIP IF SET TO -1 (NET WENT DOWN ON THIS CHAN) + ANDCAM B,IMSOC5(A) ;CLEAR BIT + POPJ P, + +;NET .CALL IOPUSH/IOPOP - ALTER THE CHANNEL-OPEN MASK IN IMSOC1. +NETIOP: HRRZ T,UUAC(U) + IMUL I,CHNBIT(T) ;PUSHING => 0; ELSE BIT FOR CHANNEL BEING POPPED. + HLRZ T,(R) ;GET SOCKET TABLE IDX + TRNN T,400000 ;SKIP IF NET WENT DOWN ON THIS LOSER + DPB I,[222000,,IMSOC1(T)] ;STORE MASK AWAY. + POPJ P, + +;NET .CALL WHYINT +;RESULTS ARE %WYNET, SOCKET STATE, BYTES AVAIL, CLS REASON +NETWHY: HRRE I,A ;GET IMSOC INDEX + MOVEI A,%WYNET ;FIRST RESULT IS DEVICE CODE + SETZB B,C ;SET UP RESULTS 2-4 IN CASE NCP WENT DOWN + MOVEI D,%NCNCP + JUMPL I,POPJ1 ;RETURN IF NCP WENT DOWN ON THIS LOSER + HRRZ B,IMSOC4(I) ;SECOND RESULT IS SOCKET STATE + MOVE Q,IMSOC5(I) + TLNE Q,4000 + TLO B,400000 ;SIGN OF SECOND RESULT SET IF NETWRK INT + TLNE Q,40000 ;DIRECT CONNECTED? + TDZA C,C ;YES, NO BYTES AVAILABLE FOR INPUT + MOVE C,IMSMPC(I) ;THIRD RESULT IS BYTES AVAILABLE + LDB D,IMSCLS ;FOURTH RESULT IS CLOSE REASON + JRST POPJ1 + +;AIDS TO NETWORK OPEN AND NETHST CALLS + +;SET THINGS UP AND ALLOCATE AN IMSOC INDEX. +;SKIP RETURNS WITH NETLST AND IMSOC1(I) LOCKED. +;OR, RETURNS NO-SKIP WITH NOTHING LOCKED AND AN ERROR SIGNALLED. +NETO00: PUSHJ P,LSTSET ;ADD THIS JOB TO LIST OF NET OPENERS + NETLST + PUSHJ P,SWTL ;GET AN IMSOC ENTRY TO GC-PROTECT OUR IMPHTB ENTRY + NETOSW + MOVSI I,-IMPSTL + SKIPE IMSOC1(I) + AOBJN I,.-1 + JUMPG I,OPNL6 ;DEVICE FULL + MOVEI H,377 ;NO HOST YET + DPB H,IMSCFH + HRRZM U,IMSOC1(I) ;IMSOC1 POSITIVE MEANS ALLOCATED BUT NOT INITED YET + PUSHJ P,LSWPOP ;NETOSW + PUSHJ P,LOSSET ;RETURN IMSOC ENTRY IF PCLSR + NETIRT + JRST POPJ1 + +;LOSSET ROUTINE TO RETURN IMSOC ENTRY +NETIRT: MOVE T,AC0S+I(U) + HRRZ A,U + CAME A,IMSOC1(T) + JRST 4,. + SETZM IMSOC1(T) + POPJ P, + +;SUBROUTINE TO OPEN UP COMMUNICATIONS WITH THE DESIRED HOST. +;ENTER WITH HOST NUMBER IN SRN3(U), SKIP-RETURN WITH HOST +;UP AND IMPHTB INDEX IN H AND IMSCFH. OR NON-SKIP RETURN WITH ERROR SIGNALLED. +NETOR: MOVE T,SRN3(U) ;USER-SPECIFIED HOST NUMBER + JSP J,STDHST ;STANDARDIZE, OPNL25 IF IT IS NO GOOD + CONO PI,NETOFF + PUSHJ P,FNDHST ;H GETS HOST TABLE INDEX + JRST OPNL6 ;DEVICE FULL (HOST TABLE FULL) + DPB H,IMSCFH ;PROTECT IN IMSOC4 + CONO PI,NETON + PUSHJ P,SWTL ;POSSIBLY SEND RST TO HOST OPENING CONNECTION TO + NETHSW + LDB J,IMHSBT ;GET STATUS + SOJG J,NETORS ;-1 => DOWN, 0 => RST SENT, 1 => UP + JUMPE J,NETOR1 ;WAIT FOR REPLY + PUSHJ P,NETOW ;WAIT FOR IMPMPC TO BE FREE + LDB W,[051100,,TIME] + DPB W,[221100,,IMPHTB(H)] + MOVEI J,1 + DPB J,IMHSBT ;MARK AS SENT + AOS IMRFCT + PUSHJ P,STHSTM ;STORE HOST#, LINK 0 , MESSAGE TYPE 0 + MOVE W,[8_24.+1_8] ;BYTE SIZE = 8, BYTE COUNT = 1 + MOVEM W,IMPMPC+6 + MOVE W,[12._28.] ;RST + MOVEM W,IMPMPC+7 + MOVEI W,1 + HRRM W,IMPMPC ;MESSAGE LENGTH + PUSHJ P,IMPMPQ ;SEND IT OUT +NETOR1: PUSHJ P,LSWPOP ;NETHSW + PCLT + MOVSI T,1000 + TDNE T,IMPHTB(H) ;RRP -> 2000, DOWN -> 0000 + PUSHJ P,UFLS + LDB J,IMHSBT ;GET STATUS + SOJL J,OPNL41 ;HOST DOWN + JUMPE J,NETOR ;TRY ALL THIS AGAIN + JRST POPJ1 ;HOST UP + +NETORS: PUSHJ P,LSWPOP ;NETHSW + JRST POPJ1 ;HOST IS UP + +;NETWORK OPEN + +; .OPEN CH,BLK +; ERROR RETURN +; NORMAL RETURN + +;BLK: MODE BITS,,(SIXBIT /NET/) +; LOCAL SOCKET NUMBER (1.1-4.5) +; FOREIGN SOCKET NUMBER (1.1-4.5) +; FOREIGN HOST NUMBER + +;BLK: 3.1-3.3 => STANDARD ASCII/IMAGE, UNIT/BLOCK, INPUT/OUTPUT +; 3.4 = 1 => GENERATE UNIQUE LOCAL RECEIVE (SEND) SOCKET NUMBER +; 3.4 = 0 => USE LOCAL SOCKET NUMBER SPECIFIED IN BLK+1 +; 3.5 => OPEN SOCKET IN LISTEN MODE +; 3.6 => IF IMAGE MODE, USE BYTE SIZE IN 4.1-4.6 +; IF ASCII MODE, USE 8 BIT BYTES RATHER THAN 7 +; 3.7 => USE BIG BUFFER (2000 WORDS INSTEAD OF 200) +; 3.8 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION +; 4.1-4.6 = BYTE SIZE IN IMAGE MODE + + +;OPEN CODE +NETO: SKIPN IMPUP + JRST NETOUP + SKIPL IMPUP + JRST OPNL7 ;DEVICE NOT READY + CONO PI,NETOFF + SKIPN IMPTCU + AOS IMPTCU + CONO PI,NETON + MOVSI I,SCLIMP + IORM I,SUPCOR ;HAVE SYS JOB BRING UP THE NETWORK + PCLT + SKIPE IMPTCU ;WAIT WHILE IT TRIES TO COME UP + PUSHJ P,UFLS + SKIPE IMPUP + JRST OPNL7 ;LOSE IF NOT UP BY NOW +NETOUP: TLZ A,740000 ;IGNORE EXTRA BITS IN SOCKET NUMBERS + TLZ B,740000 + PUSHJ P,NETO00 ;INITIALIZE THINGS + POPJ P, ;NETWORK NOT UP OR FULL + TLNE C,20 ;SKIP IF NOT LISTEN + JRST NETO10 + PUSHJ P,NETOR ;DO RESET STUFF, OPEN COMMUNICATIONS WITH HOST + POPJ P, ;HOST DOWN OR ILLEGAL + MOVE J,B ;CHECK GENDER OF FOREIGN SOCKET + ROT J,-1 + XOR J,D + JUMPGE J,OPNL2 ;WRONG DIRECTION +;DROPS THROUGH + ;DROPS IN +NETO10: PUSHJ P,SWTL ;ONLY ONE PROCESS AT A TIME COMPARING SOCKET NUMBERS + NETOSW + TLNN C,20 ;SKIP IF LISTEN + PUSHJ P,NETOW ;GOBBLE MP CONTROL LINK BLOCK (FOR NETOS) + TLNN C,10 + JRST NETO1 ;USE SOCKET NUMBER GIVEN IN WORD 2 + MOVEI A,10 ;ADVANCE SYSTEM UNIQUE SOCKET NUMBER + ADDB A,NRSOC + SUBI A,10 ;UNIQUE RECEIVE SOCKET NUMBER + SKIPGE D ;SKIP IF OPEN IS FOR READ (RECEIVE) + IORI A,1 ;MAKE INTO SEND SOCKET + JRST NETO6 + +NETO1: MOVE J,A ;USER SPECIFIED SOCKET NUMBER + ROT J,-1 ;J 4.9: 0 => RECEIVE 1 => SEND + EQV J,D ;D 4.9: 0 => READ 1 => WRITE + JUMPGE J,OPNL2 ;WRONG DIRECTION + MOVE J,A + CAIL A,NETSRS ;SKIP IF SPECIAL SOCKET + TRZA J,7 ;J HAS BASE OF SOCKET GROUP + MOVNI J,1 ; OR -1 IF NOT IN A GROUP + MOVSI Q,-IMPSTL + MOVEI E,0 +NETO2: SKIPL W,IMSOC1(Q) + JRST NETO3 ;NOT HOOKED UP + CAMN A,IMSOC2(Q) + JRST NETO2A ;DUPLICATE LOCAL SOC # + MOVE T,IMSOC2(Q) + TRZ T,7 + CAMN J,T + JRST NETO4 ;JUMP IF PART OF SOCKET GROUP +NETO3: AOBJN Q,NETO2 + SKIPL J ;SKIP IF NOT PART OF A SOCKET GROUP + JUMPE E,OPNL23 ;FOUND NO EVIDENCE THAT THIS GUY OWNS THIS GROUP + JRST NETO6 ;WINNING + +NETO2A: TLNN W,200000 ;SKIP IF BEING CLOSED + JRST OPNL13 ;NO, GIVE ERROR + TLNN C,20 + PUSHJ P,LSWPOP ;POP MP CONTROL LINK BLOCK + PUSHJ P,LSWPOP ;NETOSW + MOVSI T,200000 + PCLT + TDNE T,IMSOC1(Q) + PUSHJ P,UFLS ;WAIT TILL CLOSED + JRST NETO10 ;TRY AGAIN + +NETO4: CAIE U,(W) + JRST OPNL23 ;SOMEONE ELSE HAS IT + MOVNI E,1 ;OK IF NO OTHER CONFLICTS + JRST NETO3 + +;HERE WITH SUITABLE LOCAL SOCKET IN A +NETO6: TLNN C,4 ;SKIP IF IMAGE MODE + JRST NETOC ;ASCII MODE + MOVEI TT,36. + TLNN C,40 ;SKIP IF BYTE SIZE SUPPLIED + JRST NETOB + LDB E,[330600,,C] ;USE USER SUPPLIED BYTE SIZE + IDIVI E,36. ;TT GETS BYTE SIZE MOD 36. + JUMPN TT,NETOB + MOVEI TT,36. ;36 BITS ANYWAY +NETOB: PUSH P,TT + MOVEI E,36. + IDIV E,TT ;36/BS + JUMPE TT,NETOB1 ;EXACT + MOVEI E,32. + IDIV E,(P) ;32/BS + JUMPE TT,[MOVEI TT,400000 ;32BIT MODE FLAG + JRST NETOB1] + MOVEI TT,2000 ;FUNNY BYTESIZE FLAG +NETOB1: POP P,E ;BS + ADD TT,E ;FLAGS+BS + JRST NETOA + +NETOC: MOVEI TT,400410 ;7 BIT + TLNE C,40 + MOVEI TT,401010 ;8 BIT +NETOA: TLNE C,200 + TRO TT,100000 ;DON'T BUFFER MORE OUTPUT THAN ALLOCATION + HRLZM TT,IMSOC5(I) ;STORE FLAGS AND BC, CLEAR CLOSE REASON + MOVEM A,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVEM B,IMSOC3(I) ;FOREIGN SOCKET NUMBER + SETZM IMSOCT(I) ;IF INPUT, NOT IN MIDDLE OF A MESSAGE + MOVEI W,%NSRFS + TLNE C,20 ;3.5 LISTEN + MOVEI W,%NSLSN + DPB H,[321000,,W] ;DON'T CHANGE HOST NUMBER FIELD OF IMSOC4 + MOVEM W,IMSOC4(I) ;SET INITIAL STATE, CLEAR FLAGS + SKIPE IMSOC6(I) ;SKIP IF HAVEN'T ASSIGNED BUFFER YET + JRST 4,. + PUSH P,A + PUSH P,B + PUSH P,D +NETOE1: TLNN C,100 ;LAST PLACE TO PCLSR (REALLY NETMW) + JRST NETOE7 + PUSHJ P,TCALL ;GET FULL-PAGE BUFFER + JRST IOMQ + JRST NETMW + MOVEI W,MUNET + DPB W,[MUR,,MEMBLT(A)] + DPB I,[MNUMB,,MEMBLT(A)] + LSH A,10. + MOVE W,A ;BUFFER START ADDRESS + HRLI W,377 ;NOT AN IOBFT-TYPE BUFFER + MOVEI A,1777(A) ;BUFFER END ADDRESS + JRST NETOE4 + +NETOE7: MOVEI D,NFNETC(I) + PUSHJ P,TCALL + JRST IUTCO1 ;GET 200-WD BUFFER + JRST NETMW ;NO MEM AVAIL + LDB W,[IOSA,,IOBFT(A)] + LSH W,6 ;STARTING ADDRESS + HRL W,A ;IOBFT INDEX + MOVEI A,177(W) ;BUFFER END ADDRESS +NETOE4: MOVEM A,IMSBFE(I) ;(LH WILL BE STORED LATER) + MOVEM W,IMSOC6(I) +;CLEAR THE BUFFER FOR EASE IN DEBUGGING. COMMENT USED TO CLAIM +;THAT CLEARING IT WAS NECESSARY IN ORDER TO OUTPUT CORRECT HEADERS, +;BUT THAT WAS FRAUDULENT SINCE HEADERS NEVER COME FROM THE BUFFER. + MOVEI D,1(W) + HRLI D,(W) + SETZM (W) + BLT D,(A) + POP P,D + POP P,B + POP P,A +;DROPS THROUGH + ;DROPS IN + + MOVSI Q,000100 ;SET UP THE VARIOUS BYTE POINTERS + LDB TT,IMSCBS ;TO POINT TO END OF BUFFER + MOVE E,IMSOC5(I) ;SO ILDB WILL GET FIRST BYTE IN BUFFER + TLNN E,2000 ;SKIP IF ONE BIT BYTES + DPB TT,[300600,,Q] ;OTHERWISE USE USER BYTE SIZE + SKIPGE E + TLO Q,040000 ;32 BIT WORD ENDS 4 BITS OVER + HRR Q,IMSBFE(I) + MOVEM Q,IMSMPP(I) + MOVEM Q,IMSPIP(I) + MOVEM Q,IMSBFE(I) + MOVE T,C ;GET 3.5 BIT OF C INTO + LSH T,13. ;4.9 OF T + JUMPL D,NETOE5 ;JUMP IF SENDER + SETOM (W) ;NULL FIRST HEADER WORD + TLO Q,440000 ;-> LEFT END OF WORD + HRR Q,W + MOVEM Q,IMSPIP(I) ;SET PI PNTR TO POINT TO FIRST MESSAGE HEADER + SETZM IMSMPC(I) ;NO INPUT BYTES AVAILABLE YET + MOVEI TT,20. ;MESSAGE ALLOCATION ALWAYS 20 + MOVEM TT,IMSOC8(I) + HRRZ TT,IMSBFE(I) ;COMPUTE BIT ALLOCATION + SUBI TT,2*20.(W) ;TT := # WORDS IN BUFFER, -1 FOR LUCK, -2 FOR EACH MSG + SKIPGE IMSOC5(I) ; (-1 FOR HEADER WORD, AND -1 FOR BREAKAGE) + IMULI TT,32. ;CONVERT TO # BITS + SKIPL IMSOC5(I) + IMULI TT,36. + LDB Q,IMSCBS ;BREAKAGE WAS OVER-ESTIMATED BY 1 BYTE PER MSG + IMULI Q,20. + ADD TT,Q + MOVEM TT,IMSOC7(I) ;STORE CORRECT BIT ALLOCATION + SETZM IMSC8I(I) + SETZM IMSC7I(I) + MOVEI Q,2(I) ;LINK # + DPB Q,IMSCLN ;STORE IN LINK # FIELD + JRST NETOE6 + +NETOE5: SETZM IMSOC7(I) ;INITIALIZE SENDER'S ALLOCATIONS + SETZM IMSC7I(I) + SETZM IMSOC8(I) + HRRZ TT,IMSBFE(I) + SUBI TT,(W) ;# BUFFER WORDS, -1 FOR LUCK + SKIPGE IMSOC5(I) ;SKIP IF 36BIT + IMULI TT,32. ;ALLOW 32 BITS PER WORD + SKIPL IMSOC5(I) + IMULI TT,36. ;OR 36 BITS PER WORD + LDB E,IMSCBS + IDIVM TT,E ;CONVERT TO NUMBER OF BYTES + MOVEM E,IMSMPC(I) ;THAT MANY ARE FREE AT FIRST +NETOE6: PUSHJ P,IMPSPQ ;SEARCH PENDING QUEUE (LEAVES UTCOFF) + JRST NETOG ;NOTHING THERE + JUMPGE T,NETOH ;JUMP IF NOT LISTENING STATE + MOVE W,2(Q) ;FOREIGN SOCKET NUMBER + MOVEM W,IMSOC3(I) + LDB H,[101000,,3(Q)] ;FOREIGN HOST IMPHTB INDEX + DPB H,IMSCFH + SKIPA W,[%NSRFC] +NETOH: MOVEI W,%NSOPN + HRRM W,IMSOC4(I) + JUMPGE D,NETOD1 ;JUMP IF RECEIVER + SKIPL W,3(Q) ;SKIP IF RTS, GET LINK # + JRST 4,. ;HE SENT STR + DPB W,IMSCLN ;STORE LINK NUMBER +NETOD: HRRZ Q,UUAC(U) ;CHANNEL OPEN ON + MOVE Q,CHNBIT(Q) + PUSHJ P,IMPUIM ;INTERRUPT SELF + JRST NETOG ;GO FINISH THE OPEN + +NETOD1: SKIPGE W,3(Q) ;SKIP IF STR, GET BYTE SIZE + JRST 4,. ;HE SENT RTS + ANDI W,377 + LDB Q,IMSCBS + CAMN W,Q + JRST NETOD ;BYTE SIZES DIFFER, LOSE + PUSHJ P,IMPBRT ;RETURN THE BUFFER + JRST OPNL22 ;SELF-CONTRADICTORY OPEN? + +NETOG: HRRZ W,UUAC(U) + MOVS W,CHNBIT(W) + TLO W,400000 ;IN USE + HRR W,U ;SETZ+<,,> + MOVEM W,IMSOC1(I) ;WE ARE NOW FULLY SET UP TO THIS SOCKET + CONO PI,NETON + TLNN C,20 ;SKIP IF LISTENING TYPE SOCKET + PUSHJ P,NETOS ;SEND RFC (CAN'T HANG, ALREADY GOT NETOW) + PUSHJ P,LSWPOP ;UNLOCK NETOSW, NOW THAT IMSOC1 4.9 IS SET + PUSHJ P,LSWDEL ;UNLOCK IMSOC1(I) + PUSHJ P,LSWPOP ;REMOVE FROM LIST OF NETWORK OPENS IN PROGRESS + HRLZ A,I ;LEFT HALF OF IOCHNM GETS SOCKET INDEX + HLRZS C + JSP Q,OPSLC7 + NETDUI,,NETDUO + NETDBI,,NETDBO + NETDUI,,NETDUO + NETDBI,,NETDBO + +;GOBBLE MAIN PROGRAM CONTROL LINK BLOCK + +NETOW: JUMPL U,NETOW1 ;FROM STYNET CLOCK LEVEL + PCLT + SKIPGE IMPHTB(H) ;SKIP IF NOT RFNM WAIT ON LINK 0 + PUSHJ P,UFLS + PUSHJ P,SWTL ;GRAB CONTROL LINK BLOCK + IMPMPU + SKIPL IMPHTB(H) ;DID CTL LINK TO THIS HOST GET BACK INTO RFNM WAIT? + POPJ P, ;NO, OK + PUSHJ P,LSWPOP ;YES, RELEASE RESOURCE WHILE AWAITING RFNM + JRST NETOW + +;FROM NETIDC (AT CLOCK INTERRUPT LEVEL) +NETOW1: SKIPL IMPHTB(H) + AOSE IMPMPU + CAIA ;INPUT CAN'T BE READ YET. + POPJ P, + CONO PI,NETOFF + PUSHJ P,IMPUIN ;REACTIVATE SO WILL CHECK AGAIN + SUB P,[2,,2] ;THROW THROUGH NETI6, NETID + JRST NETOJ1 ;TAKE NO-INPUT-AVAILABLE EXIT + +;WAIT FOR MEMORY SO CAN ALLOCATE BUFFER + +NETMW: PCLT + MOVEI T,3 + CAMG T,LMEMFR + JRST [ PUSHJ P,UDELAY ;MAYBE MEMORY FROZEN, GIVE CORE JOB + JRST NETOE1 ] ;A CHANCE TO PCLSR US, THEN TRY AGAIN + CAMLE T,LMEMFR ;SKIP WHEN MORE THAN 3K FREE + PUSHJ P,UFLS + JRST NETOE1 + +;SEND RFC AND MAYBE ALLOCATE. IMSOC INDEX IN I, HOST INDEX IN H. + +NETOS: PUSHJ P,STHSTM ;STORE HOST ADDRESS IN IMPMPC+n, ALSO MESSAGE TYPE + MOVE J,[8_24.+13._8] ;BYTE SIZE = 8, BYTE COUNT = 13. + MOVEM J,IMPMPC+6 + MOVEI J,1_4 ;3 NOPS + RTS + SKIPGE D ;SKIP IF INPUT + MOVEI J,2_4 ;3 NOPS + STR + MOVEM J,IMPMPC+7 + LSH A,4 ;LOCAL SOCKET NUMBER + MOVEM A,IMPMPC+10 + LSH B,4 ;FOREIGN SOCKET NUMBER + MOVEM B,IMPMPC+11 + MOVEI TT,2(I) ;LINK NUMBER FOR RECEIVE SOCKET + SKIPGE D + LDB TT,IMSCBS ;BYTE SIZE FOR SEND SOCKET + LSH TT,28. + HRRZ J,IMSOC4(I) + CAIE J,%NSRFC + CAIN J,%NSOPN ;SKIP IF CONNECTION NOT YET OPEN + JUMPGE D,NETOS2 ;JUMP IF CONNECTION OPEN AND READ + MOVEM TT,IMPMPC+12 + MOVEI TT,4 ;TEXT LENGTH +NETOS3: HRRM TT,IMPMPC + JRST IMPMPQ + +NETOS2: MOVEI J,<4_8>+2(I) ;NOP + ALL + LINK # + LSH J,4 + IOR TT,J + MOVEM TT,IMPMPC+12 + MOVE TT,IMSOC8(I) ;SEND MESSAGE ALLOC + LSH TT,16.+4 + MOVEM TT,IMPMPC+13 + MOVE TT,IMSOC7(I) ;SEND BIT ALLOC + LSH TT,16.+4 + MOVEM TT,IMPMPC+14 + MOVE TT,[8_24.+22._8] ;BYTE COUNT = 22. + MOVEM TT,IMPMPC+6 + MOVEI TT,6 ;MESSAGE LENGTH + JRST NETOS3 + +;.NETAC CH, ;ACCEPT CONNECTION +;ERROR RETURN +;NORMAL RETURN + +ANETAC: JSP T,NETCHK + HRRZ T,IMSOC4(I) ;SOCKET STATE + CAIE T,%NSRFC + JRST OPNL41 ;NOT IN RFC RECEIVED STATE + LDB H,IMSCFH + PUSHJ P,NETOW ;GET IMPMPC + MOVE A,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVE B,IMSOC3(I) ;FOREIGN SOCKET NUMBER + MOVE D,A + ROT D,-1 + PUSHJ P,NETOS ;SEND RFC (AND MAYBE ALL) + CONO PI,NETOFF + HRRZ T,IMSOC4(I) + MOVEI TT,%NSOPN + CAIN T,%NSRFC + HRRM TT,IMSOC4(I) ;CONNECTION OPEN + JRST NETOJ1 + +NETCHK: HRRZ A,(R) + CAIL A,NETDUI + CAILE A,NETDBO + JRST OPNL34 ;NOT A NETWORK CHANNEL + HLRE I,(R) ;SOCKET TABLE INDEX + JUMPGE I,(T) + JRST OPNL41 ;OTHER END OF PIPELINE GONE (NET WENT DOWN) + +;.NETS CH, ;SEND BUFFER NOW +;RETURN + +NETFRC: JSP T,NETCHK ;ENTRY FROM .CALL FORCE + MOVE T,IMSOC2(I) + TRNN T,1 + JRST OPNL2 ;NOT SEND SOCKET + CONO PI,NETOFF + MOVE T,IMSMPP(I) + CAMN T,IMSPIP(I) + JRST NETOJ1 ;BUF EMPTY + MOVSI TT,400000 ;TURN ON SEND BUFFER BIT + IORM TT,IMSOC4(I) + PUSHJ P,IMPOST ;TURNS NETON + JRST POPJ1 + +NETFIN: HRRZ TT,IMSBFE(I) ;ENTRY FROM .CALL FINISH (NETFRC HAS BEEN CALLED) + SUB TT,IMSOC6(I) .SEE NETOE5 ;FOR COMMENTS FOR THIS CODE + HRRZS TT + SKIPGE IMSOC5(I) + IMULI TT,32. + SKIPL IMSOC5(I) + IMULI TT,36. + LDB T,IMSCBS + IDIVM TT,T ;T NOW HAS SIZE OF OUTPUT BUFFER IN BYTES + CAME T,IMSMPC(I) ;WAIT FOR BUFFER TO EMPTY OUT + PUSHJ P,UFLS + MOVEI T,%NSRFN ;WAIT FOR RFNM + HLL T,IMSOC4(I) ;4.9 IS KNOWN TO BE OFF NOW! + CAMN T,IMSOC4(I) + PUSHJ P,UFLS + JRST POPJ1 + +;.NETINT CH, ;SEND NETWORK INTERRUPT "INR" OR "INS" + ;INR FROM RECEIVER TO SENDER (LOCAL SOCKET EVEN, FOREIGN ODD) + ;INS FROM SND TO RCV ( -", -") +;ALSO .CALL NETINT, ARG 1 IS CH + +NNETINT:JSP T,NETCHK + AOSA (P) ;GOING TO WIN, SKIP RETURN +ANETINT: JSP T,NETCHK ;I<- SOCKET TABLE INDEX + LDB H,IMSCFH ;HOST INDEX FOR NETOW + PUSHJ P,NETOW ;WAIT FOR IMPMPU + MOVEI A,1 ;SET COUNT + MOVEM A,IMPMPC + PUSHJ P,STHSTM ;STORE HOST ADDRESS + MOVE A,[8_24.+2_8] ;BYTE SIZE 8, COUNT 2 + MOVEM A,IMPMPC+6 + MOVE A,IMSOC2(I) ;LCL SOCK # + MOVSI B,7_10. ;INR + TRNE A,1 ;SKIP IF RCV + MOVSI B,8_10. ;INS + LDB A,IMSCLN ;LINK # + DPB A,[241000,,B] + MOVEM B,IMPMPC+7 + JRST IMPMPQ ;QUE IT, START OUTPUT (IMPOST) + +;STORE HOST ADDRESS FROM H INTO LEADER IN IMPMPC. BASHES W, Q. +STHSTM: MOVEI Q,IMPMPL + HRLM H,IMPMPC ;ALSO SAVE HOST INDEX FOR PI LEVEL +;STORE HOST ADDRESS FROM H INTO LEADER IN (Q), BASHES W. +STHSTP: MOVE W,IMPHTN(H) ;FOREIGN HOST NUMBER +IFN 1, DPB W,[103000,,3(Q)] ; Store host address +IFN 0,[ DPB W,[301000,,3(Q)] ;STORE HOST NUMBER + LSH W,-9 + DPB W,[102000,,3(Q)] ;STORE IMP NUMBER +] ;IFN 0 + MOVSI W,17_10. ;NEW-FORMAT FLAG + MOVEM W,2(Q) ;MESSAGE TYPE 0 (LINK, ETC. ARE ALWAYS ZERO) + POPJ P, + +;.CALL NETBLK ;WAIT FOR STATE TO CHANGE OR TIME OUT +; ARG 1 - CHANNEL +; ARG 2 - STATE +; ARG 3 - TIME, AS IN .SLEEP (OPTIONAL) (WRITTEN BACK) +; VAL 1 - NEW STATE +; VAL 2 - TIME LEFT + +ANETBLK:JSP T,NETCHK + MOVE T,I ;SAVE INDEX IN T + HRL T,B ;STATE ALSO + CAIGE W,3 ;SKIP IF 3 ARGS (TIME GIVEN) + JRST ANETB3 ;USE DEFAULT TIME + TLNE C,1000 ;SKIP IF POINTER, RATHER THAN IMMEDIATE + JRST ANETB5 + XCTR XRW,[MOVES B,(C)] ;GET TIME FROM USER (CHECK WRITE ALSO) + JUMPL B,ANETB1 ;NEG MEANS ALREADY ABS TIME + MOVNS B ;MAKE NEG + SUB B,TIME ;-TIME TO GO TO +ANETB1: UMOVEM B,(C) ;STORE NEG TIME FOR PCLSR + MOVNS B ;MAKE + +ANETB4: MOVEM B,EPDL(U) ;ALSO USED IN B LATER + PUSHJ P,ANETB2 ;SKIP IF STATE CHANGE OR TIMEOUT + PUSHJ P,UFLS + SUB B,TIME ;HOW MUCH USED? + HRRZ A,IMSOC4(I) ;RETURN STATE + JRST POPJ1 + +ANETB2: HLR A,T ;DESIRED STATE + XOR A,IMSOC4(T) ;CURRENT STATE + TRNE A,-1 ;SKIP IF STILL MATCH + JRST POPJ1 + MOVE A,EPDL(U) ;SAVED TIME HERE + CAMG A,TIME + AOS (P) ;TIME OUT! + POPJ P, + +ANETB3: HRLOI B,377777 ;NO TIME SUPPLIED, USE INFINITY + JRST ANETB4 + +ANETB5: HRRZ B,C ;IMMEDIATE TIME SUPPLIED + ADD B,TIME ;(TIMEOUT WILL RESTART ON EACH PCLSR, TOO BAD) + JRST ANETB4 + +IFE INETP,[ +;.CALL STYNET +;ARG 1 - STY CHANNEL +;ARG 2 - NET INPUT CHANNEL TO CONNECT STY OUTPUT TO, OR -1 TO DISCONNECT +;ARG 3 - NET OUTPUT CHANNEL TO CONNECT STY INPUT TO +;ARG 4 - CHARS TO SEND WHEN OUTPUT .RESET HAPPENS ON STY'S TTY +; UP TO 3 8-BIT CHARACTERS, LEFT JUSTIFIED. + +NSTYNT: TLNN R,%CLSST + JRST OPNL34 ;1ST ARG NOT A STY CHANNEL. + HLRZ I,(R) ;GET TTY # OF STY + HRRES B ;ALLOW IMMEDIATE -1 + JUMPGE B,NSTYN2 ;JUMP IF CONNECTING. + PUSHJ P,NSTYN0 ;DISCONNECT + JRST OPNL41 ;WASN'T CONNECTED + JRST POPJ1 + +;VARIOUS ROUTINES CALL HERE WITH THE TTY# OF A STY IN I, TO DISCONNECT THE +; STY FROM THE NETWORK. NOTE THIS ROUTINE MUST NOT CHANGE U AND MUST NOT +; LSWCLR, SINCE IT COULD BE CALLED FROM IODCL VIA STYCLS OR NETCLS. + +NSTYN0: MOVSI B,%SSNET ;DISCONNECTING BOTH SIDES. + CONO PI,NETOFF + TDNN B,STYSTS-NFSTTY(I) + POPJ P, ;THIS STY NOT CONNECTED? + ANDCAB B,STYSTS-NFSTTY(I) ;MARK AS NO LONGER CONNECTED + MOVE C,STYNTL-NFSTTY(I) ;REMOVE THIS STY FROM ACTIVATION LIST + MOVEI D,STYNTA-STYNTL+NFSTTY +NSTYN1: CAMN I,STYNTL-NFSTTY(D) ;FIND THE STY THAT POINTS TO THIS ONE, + MOVEM C,STYNTL-NFSTTY(D) ;AND PATCH US OUT OF THE LIST. + SKIPE D,STYNTL-NFSTTY(D) ;SEARCH WHOLE LIST TILL FIND WHO POINTS TO US. + JRST NSTYN1 + SETOB C,STYNTL-NFSTTY(I) + EXCH C,STYNTI-NFSTTY(I) ;MARK THIS STY AS HAVING NO CONNECTION, GET SOCKET INDICES +IFN CHAOSP,[ + TLNE B,%SSCHA + JRST [ MOVSI B,%SSCHA ;DISCONNECT FROM CHAOS NET + ANDCAM B,STYSTS-NFSTTY(I) + MOVSI B,%CFSTY + TDNN B,CHSSTA(C) + JRST 4,. ;CHAOS DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,CHSSTA(C) + JRST NETOJ1 ] +];CHAOSP + MOVE B,[40000,,777] + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) ;AND MARK SOCKETS WE WERE CONNECTED TO AS DISCONNECTED + MOVSS C + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) + JRST NETOJ1 + +NSTYN2: MOVE Q,I ;SAVE TTY # OF STY + MOVEI E,1 + MOVE A,B ;DECODE THE NETWORK INPUT CHANNEL + JSP T,CHNDCD +IFN CHAOSP,[ + HRRZ A,(R) + CAIE A,CHAIDN + CAIN A,CHAODN + JRST [ HLRZ I,(R) ;CONNECT TO CHAOS NET + CONO PI,NETOFF + MOVSI B,%CFSTY + TDNE B,CHSSTA(I) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + MOVSI C,%SSNET+%SSCHA + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + IORM B,CHSSTA(I) ;OK, HOOK UP + DPB Q,[$CFTTN,,CHSSTA(I)] + JRST NSTYN3 ] +];CHAOSP + JSP T,NETCHK ;TEST LEGALITY; OPNL IF LOSES + TDNE E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF IT'S AN OUTPUT CHANNEL + MOVE B,I ;SAVE INPUT IMSOC INDEX + MOVE A,C ;DECODE OUTPUT CHANNEL + JSP T,CHNDCD + JSP T,NETCHK + TDNN E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF INPUT SOCKET + CONO PI,NETOFF + MOVE E,[40000,,777] + TDNN E,IMSOC5(B) ;ERROR IF EITHER CHANNEL ALREADY CONNECTED + TDNE E,IMSOC5(I) + JRST OPNL23 ;"FILE LOCKED" + MOVSI C,%SSNET + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;SIMILAR ERROR IF STY ALREADY CONNECTED + HRR E,Q ;GET 40000,,TTY # + IORM E,IMSOC5(I) + IORM E,IMSOC5(B) ;MARK SOCKETS AS CONNECTED +NSTYN3: SKIPGE STYNTL-NFSTTY(Q) ;HALT IF STY'S VARS ARE NOT CORRECT FOR A + SKIPL STYNTI-NFSTTY(Q) ;NON-CONNECTED STY. + JRST 4,. + IORM C,STYSTS-NFSTTY(Q) ;ALL ERROR CAUGHT, SO MARK STY CONNECTED. + HRL B,I ;PUT INPUT IMSOC IDX,, OUTPUT IMSOC IDX + MOVSM B,STYNTI-NFSTTY(Q) ;INTO THE STY + TRZ D,7777 ;STORE THE OUTPUT RESET CHARACTERS - AT MOST 3 + MOVEM D,STYORC-NFSTTY(Q) +IFN CHAOSP,[ ;ACTIVATE IN CASE HAS UNREAD INPUT + TLNN C,%SSCHA + PUSHJ P,IMPUIN + TLNE C,%SSCHA + PUSHJ P,CHINTI +];CHAOSP +.ELSE PUSHJ P,IMPUIN + JRST NETOJ1 +] ;IFE INETP + +SUBTTL ARPANET MP I/O ROUTINES + +IFE INETP,[ +;CALL STYNTC AT CLOCK LEVEL TO PROCESS ALL NECESSARY TRANSFERS OF DATA +;BETWEEN CONNECTED STYS AND NET SOCKETS + +STYNTC: CONO PI,NETOFF + SKIPN I,STYNTA ;GET HEAD OF ACTIVATE LIST + JRST NETONJ ;EMPTY + SETZM STYNTA ;COPY LIST IN CASE A STY IS PUT BACK ON + CONO PI,NETON +STYNT7: MOVE A,STYNTL-NFSTTY(I) ;GET NEXT ON LIST + MOVEM A,STYNTB ;SAVE FOR NEXT TIME AROUND LOOP + SETOM STYNTL-NFSTTY(I) ;THIS ONE IS NO LONGER ON ACTIVATE LIST + MOVE A,STYSTS-NFSTTY(I) + TLNN A,%SSNET + JRST 4,. ;STY CLAIMS NOT TO BE CONNECTED?? + MOVE R,I ;SAVE TTY # +IFN CHAOSP,[ + TLNE A,%SSCHA + JRST STYCHA ;CONNECTED TO CHAOS NET +];CHAOSP +] ;IFE INETP +IFN INETP,STYNCP: + + SKIPGE TTYOAC(I) + JRST STYNT1 ;NO OUTPUT, CHECK FOR INPUT +;HANDLE OUTPUT TO NET + HRRZ I,STYNTI-NFSTTY(I) ;GET IMSOC IDX OF OUTPUT CHANNEL + MOVSI A,40000 + TDNN A,IMSOC5(I) + JRST 4,. ;SOCKET CLAIMS NOT TO BE CONNECTED?? +STYNT5: CONO PI,NETOFF ;INCLUDES TTYOFF + PUSHJ P,NSOSE0 ;CAN WE OUTPUT TO NET NOW? + JRST STYNT6 ;NO, WAIT TILL LATER, PI LVL WILL REACTIVATE WHEN STATE CHANGES + LDB T,IMSCBS ;SINCE THIS IS PI LEVEL, + MOVE Q,IMSOC7(I) ;NO POINT IN SENDING MORE OUTPUT THAN ALLOCATED + SUB Q,IMSC7I(I) + IDIVM Q,T ;T GETS NUMBER OF BYTES ALLOCATED AND NOT BUFFERED + CAMLE E,T + MOVE E,T + JUMPLE E,STYNT6 ;NO ALLOC, SEND NOTHING + EXCH R,I ;BEFORE EXCH, R HAS TTY #, I HAS NET IMSOC IDX + MOVEM D,DBBBP ;SET UP BUFFER-POINTING VARS FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;OUTPUT THROUGH THOSE POINTERS, INTO THE NET CHNL BUFFER + SETZM TYPNTF + POP P,R + EXCH I,R + MOVE D,DBBBP + MOVE E,DBBCC + MOVE Q,DBBCC1 + PUSHJ P,NSOFIN ;FIGURE OUT HOW MANY CHARS WERE TYPED, AND UPDATE SOCKET. + JRST STYNT4 ;MORE ROOM IN BUFFER => MAYBE TYPE SOME MORE. + JRST STYNT6 ;ELSE TRY INPUT FROM NET, BUT SEND WHATEVER WE GOT + +STYNT4: SKIPL TTYOAC(R) ;MORE OUTPUT IN TTY BUFFER? + JRST STYNT5 ;YES, PROCESS IT +STYNT6: PUSHJ P,NSOFN1 ;NO, BE SURE NET BUFFER GETS SENT SOON + +;HERE TO TRY TO HANDLE INPUT FROM NET +STYNT1: HLRZ I,STYNTI-NFSTTY(R) ;INPUT IMSOC INDEX + MOVSI A,40000 + TDNN A,IMSOC5(I) + JRST 4,. ;SOCKET CLAIMS NOT TO BE CONNECTED? +STYNT2: PUSHJ P,NETIDC ;GET CHAR FROM NET SOCKET + JRST STYNT3 ;GOT CHAR IN W + JRST STYNT8 ;NO CHAR AVAIL, HANDLE OTHER STYS + ;2 SKIPS => GIVE UP, SPECIAL CHARACTER SEEN, OR BAD STATE + PUSHJ P,IMPUIP ;WAKE UP THE TELNET SERVER + MOVE I,R ;DISCONNECT THE STY AND SOCKETS + PUSHJ P,NSTYN0 + JRST 4,. +IFE INETP,[ +STYNT8: SKIPE I,STYNTB ;GET NEXT STY FROM COPIED ACTIVATION LIST + JRST STYNT7 + POPJ P, +] ;IFE INETP +.ELSE JRST STYNT8 + +STYNT3: EXCH I,R ;HERE IF GET CHAR FROM NET IN W. I GETS TTY #. + PUSH P,R + PUSH P,I + MOVE A,W + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL. + CONO PI,TTYON + POP P,R ;TTY #; POP IN REVERSE ORDER TO UNDO THE EXCH + POP P,I ;IMSOC IDX + JRST STYNT2 ;TRY TO GET ANOTHER INPUT CHARACTER. + +;STYNTC'S INTERFACE TO NET INPUT IOT. +;I HAS IMSOC IDX OF INPUT SOCKET. +;1 SKIP => NO DATA AVAILABLE. +;2 SKIPS => TELNET CONTROL CHARACTER FOUND, SO DISCONNECT STY AND +;INTERRUPT THE USER PROGRAM. +NETIDC: MOVNI U,1 ;U=-1 TELLS NETI IT CAME FROM HERE + HRRZ H,IMSOC4(I) ;CHECK SOCKET STATE + CAIN H,%NSOPN + JRST POPJ1 ;NO DATA + CAIGE H,%NSCLI ;SKIP IF IN ONE OF THE TWO INPUT AVAILABLE STATES + JRST POPJ2 ;STATE IS ABNORMAL, SO DISCONNECT FROM STY. + JRST NETID ;ELSE TRY AN IOT. + +;NETWORK UNIT INPUT. +NETI: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,IOCER1 +NETIB: MOVE A,IMSOC5(I) ;ENTER HERE FROM BLOCK-MODE INPUT + TLNE A,40000 + JRST IOCR10 ;CAN'T IOT AT M.P. LEVEL WHILE SOCKET CONNECTED TO A STY. +NETID: MOVE A,IMSC8I(I) + LDB B,IMSCBS + IMUL B,IMSMPC(I) + ADD B,IMSOC7(I) ;TOTAL NUMBER OF BITS YET TO BE READ + CAIGE A,8. ;IF MESS REALL OF 8 OR MORE + CAMG B,IMSC7I(I) ;OR BIT REALL SATISFIES "DOUBLE BUFFERING" CRITERION + PUSHJ P,NETI6 ;THEN SEND ALLOCATE + JUMPL U,NETI4 ;JUMP IF READING INPUT TO GIVE DIRECTLY TO A STY +NETI0: CONO PI,NETOFF ;DON'T ALLOW INTO IMPUIN WHILE CHECKING STATE, #BITS + HRRZ A,IMSOC4(I) + JUMPE A,NETIB1 ;CONNECTION CLOSED + CAIE A,%NSINP + CAIN A,%NSCLI + JRST .+3 + CAIE A,%NSOPN + JRST IOCR10 ;SOCKET IN BAD STATE + PCLT + SKIPG IMSMPC(I) ;WAIT FOR BITS TO ARRIVE + PUSHJ P,UFLS + CONO PI,NETON ;NETON IN CASE DIDN'T UFLS + SKIPG IMSMPC(I) ;DID THEY? + JRST NETI0 ;NO, STATE MUST HAVE CHANGED, CHECK IT AGAIN + +NETI4: SOSL IMSOCT(I) ;TAKE BYTE + JRST NETI4A + MOVE A,IMSMPP(I) ;END OF MESSAGE, FIND ADDRESS OF NEXT HEADER WORD + MOVEI A,1(A) ;WHICH IS IN NEXT WORD AFTER LAST BYTE LOADED + CAILE A,@IMSBFE(I) + HRRZ A,IMSOC6(I) ;WRAP AROUND + SOSGE B,(A) ;GET HEADER WORD, COUNT DOWN FOR BYTE ABOUT TO TAKE + JRST 4,. ;NO MESSAGE, ALTHOUGH IMSMPC > 0 + MOVEM B,IMSOCT(I) ;SAVE # BYTES LEFT IN THIS MESSAGE + HLL A,IMSBFE(I) ;SET UP BYTE POINTER LH TO LAST BYTE IN WORD + MOVEM A,IMSMPP(I) ; SO ILDB WILL GET FIRST DATA BYTE OF THIS MSG + AOS IMSC8I(I) ;INCREASE MESSAGE ALLOCATION +NETI4A: MOVE TT,IMSMPP(I) ;CHECK FOR WRAP-AROUND + MOVE H,IMSOC5(I) + TLNE H,2000 + JRST NETI2 ;JUMP IF ONE BIT BYTES + CAMN TT,IMSBFE(I) + JRST [ HRRZ TT,IMSOC6(I) + HLL TT,IMSPIP(I) ;B.P. TO FIRST BYTE IN BUFFER + JRST .+1 ] + ILDB W,TT + JRST NETI3 + +NETI2: LDB E,IMSCBS ;BITS PER BYTE + MOVEI W,0 +NETI1: CAME TT,IMSBFE(I) + JRST NETI1A + HRRZ TT,IMSOC6(I) ;WRAP AROUND + HLL TT,IMSPIP(I) +NETI1A: ILDB A,TT + LSH W,1 + IORI W,(A) + SOJG E,NETI1 +;DROPS THROUGH + ;DROPS IN + +NETI3: TRNN W,200 ;IS THIS A TELNET CONTROL CHAR (>= 200)? + JRST NETI3A + JUMPL U,[AOS IMSOCT(I) ;YES; IF DIRECT-CONNECTED TO A STY, BREAK CONNECTION. + JRST POPJ2] ; WITHOUT GOBBLING THAT CHARACTER + TLNE H,400 ;IF 7-BIT ASCII MODE, REPLACE CHARACTER BY ^@. + SETZ W, +NETI3A: MOVEM TT,IMSMPP(I) + LDB TT,IMSCBS + ADDM TT,IMSC7I(I) ;INCREASE BIT ALLOCATION + CONO PI,NETOFF ;WHILE CHANGING STATE + SOSLE IMSMPC(I) ;ONE LESS BYTE IN BUFFER + JRST NETONJ ;OK, THERE IS MORE IN BUFFER + MOVNI E,1 ;YES, STATE IS CHANGING. + HRRZ A,IMSOC4(I) + CAIN A,%NSCLI + MOVEI E,%NSCLS + CAIN A,%NSINP + MOVEI E,%NSOPN ;NO INPUT AVAILABLE + JUMPL E,[JRST 4,.] ;WAS IN SOME RANDOM STATE + CAIN E,%NSCLS + PUSHJ P,IMPUIP ;IF STATE CHANGING TO "CLOSED", GIVE USER AN INTERRUPT. + HRRM E,IMSOC4(I) + JRST NETONJ + +;COME HERE WHEN INPUT IOT FINDS THAT CONNECTION IS CLOSED +NETIB1: CONO PI,NETON + LDB D,IMSCLS + CAIE D,%NCFRN + JRST IOCR10 ;ABNORMAL CLOSURE, GIVE IOCER INSTEAD OF EOF + MOVE TT,IMSOC5(I) + POP P,D ;GET OUR RETURN ADDRESS. + ANDI D,-1 + CAIE D,AIOT3 ;IF WE ARE NOT DOING A UNIT MODE IOT, + JRST 1(D) ;JUST RETURN WITH 1 SKIP. + TLNN TT,1400 ;SKIP IF ASCII MODE + JRST IOCER2 ;EOF IN IMAGE MODE IS IOCERROR. + HRROI W,EOFCH ;EOF IN ASCII MODE RETURNS ^C. + JRST 1(D) + +NETI6: HRRZ H,IMSOC4(I) ;SEND ALL MSG + CAIE H,%NSINP + CAIN H,%NSOPN + CAIA + POPJ P, ;CLOSED, DON'T SEND ALLOCATE + LDB H,IMSCFH ;HOST INDEX FOR NETOW + PUSHJ P,NETOW ;GOBBLE MAIN PROG CONTROL LINK BLOCK + MOVEI J,2(I) ;LINK # + IORI J,<4_8> ;SEND ALLOC + LSH J,16. + ADD J,IMSC8I(I) + LSH J,4 + MOVEM J,IMPMPC+7 + MOVE J,IMSC7I(I) + LSH J,4 + MOVEM J,IMPMPC+10 + PUSHJ P,STHSTM ;STORE HOST ADDRESS, MESSAGE TYPE + MOVE J,[8_24.+8_8] + MOVEM J,IMPMPC+6 + MOVEI J,2 + HRRM J,IMPMPC ;TEXT LENGTH + SETZB A,TT + EXCH A,IMSC8I(I) + EXCH TT,IMSC7I(I) + ADDM A,IMSOC8(I) + ADDM TT,IMSOC7(I) + JRST IMPMPQ + +;UNIT MODE NETWORK OUTPUT (DOESN'T CLOBBER C) + JRST NETSIO ;SIOT VECTOR +NETW: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,IOCER1 + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +NETWB: CONO PI,NETOFF ;BYTE TO OUTPUT IN A. HERE FROM BLOCK MODE. + HRRZ B,IMSOC4(I) + CAIE B,%NSOPN + CAIN B,%NSRFN + JRST .+2 + JRST IOCR10 + SKIPG IMSMPC(I) ;SKIP IF ROOM TO PUT BYTE IN BUF + JRST [ MOVSI B,400000 + IORM B,IMSOC4(I) ;SET TO SEND IT NOW + IFN DMIMP,CONSZ FI,70 + PUSHJ P,IMPIOS + SKIPG IMSMPC(I) ;WAIT FOR AT LEAST ONE BYTE OF ROOM + PUSHJ P,UFLS + CONO PI,NETON + SKIPG IMSMPC(I) + JRST NETWB ;NO ROOM, STATE MUST HAVE CHANGED + JRST .+1] + MOVE E,IMSOC5(I) + MOVE T,IMSOC7(I) + TLNE E,100000 + CAML T,IMSC7I(I) + JRST NETW4 + MOVSI B,400000 ;ALLOCATION USED UP (AND FEATURE ENABLED) + IORM B,IMSOC4(I) ;SEND BUFFER NOW + PUSHJ P,IMPOST + CAMN T,IMSOC7(I) ;WAIT FOR DATA TO GO OUT OR ALLOC TO COME IN + PUSHJ P,UFLS + JRST NETWB ;TRY AGAIN + +NETW4: MOVE T,IMSMPP(I) ;GET POINTER + MOVE E,TIME + CAMN T,IMSPIP(I) ;SKIP UNLESS BUFFER EMPTY + MOVEM E,IMSOCT(I) ;SET TIME FOR FIRST BITS INTO BUF + LDB B,IMSCBS ;BYTE SIZE + MOVE E,IMSOC5(I) ;FLAGS + CONO PI,NETOFF ;WANT TO MUNG POINTERS WITHOUT PI INTERFERENCE + TLNE E,2000 ;SKIP IF BYTES FIT EXACTLY IN WORD + TLNN T,770000 ;SKIP IF NOT AT RIGHT END OF WORD + JRST NETW2 ;IDPB, CHECK FOR POINTER WRAP + LDB TT,[360600,,T] ;GET BYTE POS + CAML TT,B ;SKIP IF BYTE SPLITS ACROSS WORDS + JRST NETW1 ;JUST DO IDPB + DPB TT,[301400,,T] ;SET BYTE TO STORE IN RIGHT OF THIS WORD + SUB TT,B ;=> -(# OVERFLOW BITS) + ROT A,(TT) ;HIGH PART OF BYTE IN RIGHT END OF A + DPB A,T ;STORE PART BYTE + AOS T,IMSMPP(I) ;INCR TO NEXT WORD + MOVEI E,(T) + CAILE E,@IMSBFE(I) + HRR T,IMSOC6(I) ;WRAP + MOVEM A,@T ;STASH REST OF BYTE IN LEFT PART OF NEXT WORD + ADDI TT,36. ;SET TO NEW POSITION + DPB TT,[360600,,T] ;NEW BYT POS + MOVEM T,IMSMPP(I) ;STORE UPDATED PTR + JRST NETW3 ;WRAP UP + +;DEPOSIT A BYTE WHICH MAY WRAP AROUND + +NETW2: CAME T,IMSBFE(I) + JRST NETW1 ;NO WRAP + HRR T,IMSOC6(I) + TLO T,440000 + MOVEM T,IMSMPP(I) + +;DEPOSIT BYTE KNOWN TO FIT IN WORD + +NETW1: IDPB A,IMSMPP(I) ;STORE IT + +;COUNT THE BITS NOW + +NETW3: SOS IMSMPC(I) ;1 BYTE LESS FREE + LDB T,IMSCBS + ADDM T,IMSC7I(I) + JRST NETONJ + +;NETWORK OUTPUT SIOT +NETSIO: CONO PI,NETOFF + PUSHJ P,NSOSET ;SET UP FOR FAST SIOT + JRST NSIOT1 ;CHANNEL ISN'T SET UP FOR IT => USE NORMAL SIOT LOOP. + PUSH P,B + PUSH P,C +NETSO0: XCTR XRW,[MOVES B,@-1(P)] ;COPY ARGS + XCTR XRW,[MOVES C,@(P)] +NETSO1: IBP B .SEE NSIOOL ;FOR WHY THIS HAIR IS NEEDED + XCTRI XR,[MOVE TT,(B)] + SKIPA T,B + JRST NETSO3 ;PAGE FAULT, CLEAN UP IMSMPP BEFORE TAKING IT + HRRI T,TT + LDB TT,T + IDPB TT,D + SOS E + UMOVEM B,@-1(P) ;UPDATE USER'S ARGS + XCTR XRW,[SOSLE C,@(P)] + JUMPG E,NETSO1 ;LOOP IF BOTH USER AND SYSTEM WILLING + SKIPL E + SKIPGE C + JRST 4,. ;WENT TOO FAR!! + PUSHJ P,NSOFIN ;FINISH UP HACKING NET CHANNEL. + JRST NETSO2 ;OUTPUT BUFFER HAS MORE ROOM + JUMPLE C,PPBAJ1 ;NO ROOM BUT DON'T WANT ANY MORE ANYWAY, SO RETURN + SKIPG IMSMPC(I) ;NO ROOM, WAIT FOR SOME + PUSHJ P,UFLS ;NOTE ANY STATE CHANGE WILL UNHANG + POP P,C ;NOW TRY TO SIOT SOME MORE + POP P,B + MOVE D,IOTTB(H) ;RESTORE D IN CASE GOES TO NSIOT1 + JRST NETSIO + +NETSO3: PUSHJ P,NSOFIN ;TOOK PAGE FAULT, CLEAN UP + JFCL + PUSHJ P,TPFLT +NETSO2: JUMPLE C,PPBAJ1 ;BUFFER HAS ROOM BUT NO DESIRE TO SEND ANY MORE, RETURN + CONO PI,NETOFF + PUSHJ P,NSOSE0 ;SET UP TO SEND MORE + JRST IOCR10 ;STATE MUST HAVE GONE BAD + JRST NETSO0 ;OK, SEND MORE + +;SET UP FOR NET OUTPUT SIOT, OR (NSOSE0) FOR DIRECT OUTPUT FROM STY. +;AT ENTRY, A HAS LH(IOCHNM). +;CALL WITH NETOFF, AND DON'T TURN IT BACK ON BEFORE CALLING NSOFIN, +;BECAUSE WE HAVE A COPY OF IMSMPP IN D, AND PI LEVEL MIGHT BE TRYING TO MUNG IT. +;SETS D TO POINTER, E TO COUNT OF CHARS OF SPACE, AND Q TO COPY OF COUNT. +;SETS I TO IMSOC IDX. CLOBBERS T AND TT. +;NO SKIP => CAN'T USE FAST SIOT, OR CAN'T DO DIRECT OUTPUT AT THIS MOMENT. +;IN THAT CASE, D HASN'T BEEN CLOBBERED YET. +NSOSET: HRRE I,A + JUMPL I,IOCER1 +NSOSE0: MOVE E,IMSOC5(I) + HRRZ T,IMSOC4(I) + CAIE T,%NSOPN + CAIN T,%NSRFN ;STATE BAD, OR BYTES CROSS WORD BOUNDARIES, + TLNE E,2000 + JRST NETONJ ;IMPLIES CAN'T WIN THIS WAY. + SKIPG E,IMSMPC(I) + JRST NSOFN1 ;JUMP IF BUFFER FULL, SET SEND BUFFER AND NETONJ + MOVE D,IMSMPP(I) + CAME D,IMSBFE(I) + JRST NSOSE2 + HRR D,IMSOC6(I) ;IF BUFFER STORING PTR POINTS AT END OF BUFFER, + TLO D,440000 ;WRAP AROUND. +NSOSE2: LDB Q,IMSCBS + MOVEI TT,36. + SKIPGE IMSOC5(I) + MOVEI TT,32. + IDIVM TT,Q ;GET # BYTES/WD OF CONNECTION. + HRRZ TT,IMSBFE(I) + SUBI TT,(D) + IMUL TT,Q ;# BYTES BETWEEN POINTER AND END OF BUFFER. + LDB T,[360600,,D] + LDB Q,IMSCBS + IDIVM T,Q ;# BYTES NOT STORED IN WORD POINTER POINTS AT + ADD TT,Q ;THEY ARE AVAILABLE, TOO. + CAML E,TT + MOVE E,TT ;GET MINIMUM OF FULL BYTES AND BYTES AFTER THE POINTER. + MOVE T,TIME + MOVE Q,IMSMPP(I) + CAMN Q,IMSPIP(I) ;SKIP IF BUFFER NOT EMPTY + MOVEM T,IMSOCT(I) ;TIME FOR FIRST BITS INTO BUF. + CAILE E,600 ;DON'T LEAVE NETOFF FOR MORE THAN ONE CLOCK TICK OR SO + MOVEI E,600 + MOVE Q,E ;ORIGINAL E. (FOR NSOFIN) + JRST POPJ1 + +;FINISH UP AFTER NET OUTPUT SIOT OR DIRECT OUTPUT FROM STY. +;SKIP IF BUFFER FULL +;ASSUME Q,I LEFT OVER FROM NSOSET, AND D,E ADVANCED BY STORING CHARS. +NSOFIN: PI2SAF ;NETOFF SHOULD STILL BE IN EFFECT FROM NSOSET + SUBM E,Q ;- <# BYTES XFERED> + JUMPE Q,NETONJ ;IF OUTPUT NO BYTES, DON'T CHANGE IMSMPP (IMPORTANT!) + MOVEM D,IMSMPP(I) ;UPDATE STORING POINTER OF SOCKET BUFFER + LDB TT,IMSCBS + IMUL TT,Q + MOVNS TT + ADDM TT,IMSC7I(I) ;INCREASE COUNT OF BITS IN BUFFER + ADDB Q,IMSMPC(I) ;UPDATE COUNT OF FREE SPACE IN BUFFER. + JUMPG Q,.+2 ;ANY SPACE LEFT => NO SKIP. + AOS (P) + JUMPG E,NETONJ ;ONLY SEND BUFFER IF CALL OUTPUT ALL IT COULD +NSOFN1: MOVSI TT,400000 ;SEND BUFFER NOW. + IORM TT,IMSOC4(I) + JRST IMPOST ;TURNS NETON + +NETBO: HRRE I,A + JUMPL I,IOCER1 + XCTR XRW,[MOVES D,(C)] ;TAKE TRAP GETTING POINTER IF SWAPPED OUT + MOVE E,IMSOC5(I) + TLNE E,1400 ;SKIP IF IMAGE MODE + JRST NETBOA ;ASCII MODE + JUMPGE D,CPOPJ ;TRANSFER NO WORDS +NETBO1: UMOVEM D,(C) + UMOVE A,(D) + PUSHJ P,NETWB + UMOVE D,(C) + AOBJN D,NETBO1 + UMOVEM D,(C) + POPJ P, + +NETBOA: TLNN E,400 ;SKIP IF 7 BIT + JRST NETBA8 + MOVEI E,NETBOR + JRST NBTOCH + +NETBOR: PUSH P,D + PUSH P,TT + PUSHJ P,NETWB + POP P,TT + POP P,D + MOVEI E,NETBOR + POPJ P, + +NETBA8: XCTR XRW,[MOVES D,(C)] + LDB TT,[410300,,D] + CAIGE TT,4 ;ONLY 4 BYTES PER WORD (3 < CNT < 8) + POPJ P, + SKIPA TT,NETCHT-4(TT) +NTBA8A: UMOVEM D,(C) + UMOVE W,(D) + ILDB A,TT + PUSH P,TT + PUSHJ P,NETWB + POP P,TT + UMOVE D,(C) + ADD D,[700000,,] ;ADVANCE CHAR CNT + JUMPL D,NTBA8A ;GO TO NEXT CHAR + MOVE TT,NETCHT+3 + ADD D,[400001,,1] ;INCR TO NEXT WORD + JUMPL D,NTBA8A + UMOVEM D,(C) + POPJ P, + +NETCHT: REPEAT 4,<44-<3-.RPCNT>*10>_12.+1000,,W + +NETBI: HRRE I,A + JUMPL I,IOCER1 + XCTR XRW,[MOVES D,(C)] ;ENSURE POINTER WILL BE WRITABLE + MOVE E,IMSOC5(I) + TLNE E,1400 ;SKIP IF IMAGE MODE + JRST NETBIA ;ASCII MODE +NETBI1: UMOVEM D,(C) ;STORE BACK POINTER + XCTR XRW,[MOVES (D)] ;ENSURE BYTE WILL BE WRITABLE + PUSH P,C + PUSHJ P,NETIB ;GET NEXT BYTE + CAIA ;NORMAL RETURN. + JRST POP1J ;NO INPUT AVAIL. + POP P,C + UMOVE D,(C) + UMOVEM W,(D) + AOBJN D,NETBI1 + UMOVEM D,(C) + POPJ P, + +NETBIA: TLNN E,400 ;SKIP IF 7 BIT ASCII + JRST NTBIA8 + MOVEI E,NETBIR + JRST INBTCH + +NETBIR: PUSHJ P,NETI + JRST [ MOVEI E,NETBIR ;INPUT IN W + POPJ P, ] + MOVE E,[600000,,NETBCC] ;NO INPUT AVAIL + JRST POPJ1 + +NETBCC: MOVEI H,EOFCH + JRST POPJ2 + +NTBIA8: HRRZS E ;8-BIT ASCII BLOCK MODE + XCTR XRW,[MOVES D,(C)] + LDB TT,[410300,,D] + CAIGE TT,4 + POPJ P, + SKIPA TT,NETCHT-4(TT) +NTBI8A: UMOVEM D,(C) + XCTR XRW,[MOVES (D)] + JUMPL E,NTBI8B + PUSH P,C + PUSH P,TT + PUSHJ P,NETIB + JRST [ MOVEI E,0 + JRST NETBI5 ] ;NORMAL RETURN - BYTE IN W. + MOVSI E,600000 ;NO BYTES AVAIL - SOCKET CLOSED. +NETBI5: MOVE H,W + POP P,TT + POP P,C + UMOVE D,(C) + LDB W,[410300,,D] + CAIN W,7 + TLNN E,200000 + JRST NTBI8C + POPJ P, +NTBI8C: UMOVE W,(D) + IDPB H,TT + UMOVEM W,(D) + ADD D,[700000,,] + JUMPL D,NTBI8A + MOVE TT,NETCHT+3 + ADD D,[400001,,1] + SKIPL E + JUMPL D,NTBI8A + UMOVEM D,(C) + POPJ P, + +NTBI8B: MOVEI H,EOFCH + UMOVE D,(C) + JRST NTBI8C + +NETCLS: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,CPOPJ + MOVE T,IMSOC2(I) + TRNN T,1 ;SKIP IF SEND SOCKET + JRST NETCL2 + MOVSI T,400000 + IORM T,IMSOC4(I) ;CAUSE BUFFER TO BE SENT + PUSHJ P,IMPOST +NETCL2: MOVSI B,600000 + CONO PI,CLKOFF + IORM B,IMSOC1(I) ;MARK CHANNEL TO BE CLOSED + AOS IMNCS + HRRZ R,UUAC(U) + MOVE A,CHNBIT(R) + TDNE A,MSKST2(U) + ANDCAM A,IFPIR(U) + MOVE I,IMSOC5(I) ;IF CHANNEL CONNECTED TO A STY, + TLNN I,40000 + JRST CLKONJ + ANDI I,777 ;DISCONNECT THEM. + PUSHJ P,NSTYN0 + JRST 4,. + JRST CLKONJ + +;SEARCH PENDING QUEUE FOR LOCAL SOCKET NUMBER IN A, +;T 4.9 = 1 => LISTENING, 4.9 => 0 => ALSO CHECK +;FOREIGN SOCKET NUMBER IN B AND FOREIGN HOST NUMBER (IMPHTB INDEX) IN H +;SKIPS IF ENTRY IS FOUND. RETURNS ENTRY TO FREE LIST. +;Q GETS ADDRESS OF ENTRY BLOCK. RETURN WITH NETOFF + +IMPSPQ: CONO PI,NETOFF +IMSPQP: SKIPGE Q,IMPBPQ ;BEGINNING OF QUEUE + POPJ P, ;QUEUE EMPTY + MOVNI J,1 ;PREVIOUS ENTRY +IMSPQL: CAME A,1(Q) ;SKIP IF SAME LOCAL SOCKET NUMBER + JRST IMSPQ1 ;TRY NEXT + JUMPL T,IMSPQW ;WIN IF LISTENING SOCKET + LDB W,[101000,,3(Q)] ;FOREIGN HOST IMPHTB INDEX + CAMN W,H ;SKIP IF WRONG FOREIGN HOST + CAME B,2(Q) ;SKIP IF FOREIGN SOCKET NUMBER AGREES + JRST IMSPQ1 ;TRY NEXT +IMSPQW: SKIPGE W,(Q) ;FOUND IT + MOVEM J,IMPEPQ ;PATCH OUT OF THE QUEUE + SKIPGE J + MOVEI J,IMPBPQ + MOVEM W,(J) + MOVE W,IMFFPQ ;ADD TO FREE LIST + MOVEM W,(Q) + MOVEM Q,IMFFPQ + JRST POPJ1 + +IMSPQ1: MOVE J,Q ;PREVIOUS ENTRY + SKIPL Q,(Q) ;NEXT ENTRY + JRST IMSPQL ;LOOP + POPJ P, ;NOT FOUND + +SUBTTL ARPANET CLOCK LEVEL + +OVHMTR IMP ;NETWORK INTERRUPT LEVEL (NOT STYNET STUFF) + +;HERE TO TIME OUT THE RFC QUEUE +IMFCT1: CONO PI,NETOFF + SKIPGE Q,IMPBPQ + JRST NETONJ ;... IF QUEUE IS EMPTY + MOVNI J,1 ;J HAS PTR TO PREV ELT OF LIST, FOR IMSPQW TO PATCH (DELQ). +IMFCT2: LDB E,[221100,,3(Q)] ;TIME IN 16/15'THS, MOD 512., THAT RFC WAS RECEIVED + LDB TT,[051100,,TIME] ;TIME, IN SAME UNITS, NOW. + CAMLE E,TT ;MAKE SURE THE SUB TT,E GIVES A POSITIVE ANSWER. + ADDI TT,1_9 ;WE ASSUME THAT TIME >= TIME OF RECEIPT. + SUB TT,E + CAIGE TT,IMFCTO_<-5> + JRST IMFCT3 ;THIS RFC HASN'T TIMED OUT - LOOK AT NEXT + PUSHJ P,IMSPQW ;IT HAS - FLUSH IT + JFCL + JRST IMFCT1 ;AND START AGAIN LOOKING FOR RFC'S TO FLUSH + +IMFCT3: MOVE J,Q + SKIPL Q,(Q) + JRST IMFCT2 + JRST NETONJ ;END OF QUEUE + +;FLUSH CLOSED NETWORK CHANNELS (CALLED AT HALF SEC CLOCK) +IMPCCL: MOVSI I,-IMPSTL +IMPCCR: CONO PI,NETON + MOVSI T,200000 +IMPCCZ: TDNN T,IMSOC1(I) ;LOOK FOR CHANNELS NO LONGER OPEN. + AOBJN I,IMPCCZ + JUMPL I,IMPCCA + POPJ P, + +IMPCCA: CONO PI,NETOFF + MOVE B,IMSOC6(I) + TLNE B,600000 ;ACTIVE AT PI LEVEL OR LOCKED BY CORE JOB + JRST IMPCCS + HRRZ B,IMSOC4(I) ;DISPATCH ON SOCKET STATE. + JRST @IMPCCT(B) + +IMPCCT: OFFSET -. +%NSCLS::IMPCC1 +%NSLSN::IMPCC1 +%NSRFC::IMPCC2 +%NSRCL::IMPCC1 +%NSRFS::IMPCC2 +%NSOPN::IMPCC5 +%NSRFN::IMPCC6 +%NSCLW::IMPCC7 +%NSCLI::IMPCC1 +%NSINP::IMPCC2 + OFFSET 0 + +;IMP BUFFER RETURN +IMPBRT: SKIPN IMSOC6(I) + POPJ P, ;NO BUF?? + LDB A,[221000,,IMSOC6(I)] + CAIE A,377 + JRST IMBRT1 + LDB A,[121000,,IMSOC6(I)] + PUSHJ P,IMEMR + CAIA +IMBRT1: PUSHJ P,IBRTN + SETZM IMSOC6(I) + POPJ P, + +IMPCC1: PUSHJ P,IMPBRT + MOVSI A,20000 + TDNE A,IMSOC5(I) + JSP T,IMPC5D ;WAITING FOR FINAL RFNM + SETZM IMSOC1(I) + SOS IMNCS ;WE HAVE FINISHED CLOSING ONE SOCKET +IMPCCS: AOBJN I,IMPCCR ;WE CLOSED ONE, OR GAVE UP ON ONE; LOOK AT NEXT + JRST NETONJ ;OR WE'RE FINISHED LOOKING AT ALL. + +IMPCC2: PUSHJ P,IMPBRT + SKIPLE T,IMFCQL + CAIG T,2 ;SKIP IF MORE THAN 2 FREE + JRST IMPCCS ;NOT ENUF PI CONTROL QUEUE BLOCKS AVAIL + LDB A,IMSCFH ;GET HOST# + SKIPGE IMPHTB(A) ;SKIP IF NO RFNM WAIT ON LINK 0 + JRST IMPCCS ;NOT NOW! + PUSH P,IMPCSH + MOVEM A,IMPCSH + JSP T,IMSTCM + 12.,,3 ;12. BYTES, 3 WORDS + JRST 4,. ;NO SLOTS AVAIL. CHECKED BEFORE + MOVEI H,3_4 ;3 NOPS + CLS + MOVEM H,10(Q) + MOVE H,IMSOC2(I) ;LOCAL SOCKET + LSH H,4 ;MOVE INTO 32 BIT FIELD + MOVEM H,11(Q) + MOVE H,IMSOC3(I) ;FOREIGN SOCKET + LSH H,4 + MOVEM H,12(Q) + PUSHJ P,IMWCQ ;SEND CLS + POP P,IMPCSH + MOVEI H,%NSCLW + HRRM H,IMSOC4(I) + MOVE H,TIME + MOVEM H,IMSOCT(I) ;TIME CLS SENT + JRST IMPCCS + +IMPCC5: MOVE H,IMSOC2(I) + TRNN H,1 ;SKIP IF SEND SOCKET + JRST IMPC5B ;RECEIVE SOCKET + MOVE A,IMSPIP(I) + CAMN A,IMSMPP(I) ;IS THERE STILL DATA TO SEND? AT MP LEVEL + CAMN I,IMPOPI ;OR PI LEVEL? OR RFNM WAIT? +IMPCC6: JSP T,IMPC5D ;YES, SEND IT AND GET RFNM BEFORE SENDING CLS +IMPC5B: MOVEI H,%NSRFS ;NO, OK TO SEND A CLS NOW. + HRRM H,IMSOC4(I);SET STATE SO WILL LOOP BACK TO IMPCC2 + JRST @IMPCCT(H) + +IMPC5A: IORM H,IMSOC5(I) + MOVE H,TIME + MOVEM H,IMSOCT(I) + JRST IMPCCS + +IMPC5D: MOVSI H,10000 + TDNN H,IMSOC5(I) + JRST IMPC5A ;TIME-OUT NOT ALREADY STARTED - START IT. +IMPC7A: MOVE H,TIME ;ALREADY STARTED, OVER YET? + SUB H,IMSOCT(I) + CAIG H,IMPCTO ;SKIP IF TIMED OUT + JRST IMPCCS ;NOT YET + JRST (T) + +IMPCC7: JSP T,IMPC7A ;IF CLOSE TIME-OUT ISN'T UP, GIVE UP TO IMPCCS. + JRST IMPCC1 ;ELSE FLUSH. + +;HERE FROM 1/2 SECOND CLOCK IF IMNAS IS NON-ZERO. +;WE WAKE UP ANY STYNET CHANNELS THAT NEED IT. +IMPAAA: SOS IMNAS ;DECREASE NEED-THIS-ROUTINE COUNT + MOVSI I,-IMPSTL +IMPAA1: MOVSI T,200000 + TDNN T,IMSOC5(I) + AOBJN I,.-1 + JUMPGE I,CPOPJ + CONO PI,NETOFF + ANDCAM T,IMSOC5(I) + PUSHJ P,IMPUIN + CONO PI,NETON + JRST IMPAA1 + +SUBTTL ARPANET NCP INPUT INTERRUPT LEVEL + +;GET HERE PI IN PROG ON NETCHN +;IMP HAS NETCHN PIA, TT HAS CONI WORD, A HAS LAST WD OF CONTROL LINK MSG +;PROCESS THE CONTROL LINK HOST-HOST PROTOCOL OPCODES. +IMPBK3: AOS B,IMBLKI ;STORE LAST WORD AS IF BLKI HAD + MOVEM A,(B) + MOVEI B,-IMPINB+1(B) ;B HAS NUMBER OF WORDS READ + CAMGE B,IMPNIW + JRST IMPCIS ;MESSAGE IS SHORT + MOVE A,IMPCBC ;NUMBER OF BYTES + MOVE B,[441000,,IMPINB] ;8 BIT BYTE POINTER TO MESSAGE + SETZM IMPNEA + SETZM IMPNRA +IMPBKL: SOJL A,IMPIR1 ;LOOP HERE TO PROCESS CONTROL MESSAGE + MOVE H,IMPCSH ;RESTORE HOST INDEX + ILDB C,B + CAIL C,IMPCDL + JRST IMPCIG ;ILLEGAL OPCODE + AOS IMPCMR(C) ;COUNT CTL MSG RCD + JRST @IMPCDT(C) ;DISPATCH ON OPCODE + +IMPCIG: BUG INFO,[NET: NEW CTL MSG FM HST ],OCT,IMPHTN(H),[COD=],OCT,C,[CT=],OCT,A + JRST IMPIR1 + +IMPCIS: MOVE H,IMPCSH + BUG INFO,[NET: SHORT CTL MSG FM HST ],OCT,IMPHTN(H) + AOS IMNSCM + JRST IMPIR1 + +IMPCDT: IMPBKL ;NOP ( 0) + IMPRFC ;RTS ( 1) + IMPRFC ;STR ( 2) + IMPCLS ;CLS ( 3) + IMPALL ;ALL ( 4) + IMPCIG ;GVB ( 5) + IMPCIG ;RET ( 6) + IMPINR ;INR ( 7) + IMPINS ;INS (10) + IMPECO ;ECO (11) + IMPCIG ;ERP (12) + IMPERM ;ERR (13) + IMPRST ;RST (14) + IMPRRP ;RRP (15) + IMPCIG ;RAR (16) + IMPCIG ;RAS (17) + IMPCIG ;RAP (20) + IMPNXR ;NXR (21) + IMPNXR ;NXS (22) +IMPCDL==.-IMPCDT + +IMSHRT: MOVNS A + BUG INFO,[NET: SHORT CTL MSG HST ],OCT,IMPHTN(H),[COD=],OCT,C,[MISSING],OCT,A + JRST IMPIR1 + +IMPNXR: ILDB C,B ;LINK NUMBER FOR NXR OR NXS + SOJA A,IMPBKL ;JUST IGNORE IT, USELESS ANYWAY + +;RFC RECEIVED C HAS OPCODE +IMPRFC: SUBI A,9 ;MUST BE AT LEAST 9 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB D,B ;D GETS 32 BIT FOREIGN SOCKET NUMBER +REPEAT 3,[ + LSH D,8 + ILDB T,B + IORI D,(T) +] + ILDB E,B ;E GETS 32 BIT LOCAL SOCKET NUMBER +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + ILDB R,B ;LINK NUMBER OR BYTE SIZE + MOVE Q,E + EQVI Q,(C) ;Q 1.1 = 1 IF E 1.1 = C 1.1 + ANDI Q,1 + JUMPE Q,IMPRF3 ;WRONG DIRECTION RFC + CAIE C,2 ;SKIP IF STR + JRST IMPRF5 + CAILE R,36. ;SKIP IF STR AND BYTE SIZE < 37 + JRST IMREFU ;REFUSE CONNECTION +IMPRF5: PUSHJ P,IMPLLS ;LOOK FOR LOCAL SOCKET (RET INDEX IN I) + JRST IMPRFQ ;NO SUCH SOCKET. QUEUE IT + HRRZ W,IMSOC4(I) ;SOCKET STATE + CAIE W,%NSLSN ;SKIP IF LISTENING + JRST IMPRF4 + MOVEM D,IMSOC3(I) ;STORE FOREIGN SOCKET NUMBER + DPB H,IMSCFH ;STORE FOREIGN HOST INDEX + MOVEI Q,%NSRFC + HRRM Q,IMSOC4(I) ;RFC RECEIVED STATE + CAIN C,2 ;SKIP IF RTS + JRST [ LDB Q,IMSCBS ;STR, CHECK CONNECTION BYTE SIZE + CAME Q,R + JRST IMCLDA + JRST .+2 ] + DPB R,IMSCLN ;RTS, STORE LINK # + PUSHJ P,IMPUIN ;INTERRUPT USER +IMRFCX: LDB Q,IMHSBT + CAIN Q,1 + SOS IMRFCT + MOVEI Q,2 + DPB Q,IMHSBT ;MARK HOST UP + JRST IMPBKL + +IMPRF3: BUG INFO,[NET: WRONG DIR RFC HST ],OCT,IMPHTN(H),[OP ],SIXBIT,[(C)[SIXBIT /RTS STR/]-1],[SOK],OCT,E + JRST IMPBKL + +IMPRF4: CAIE W,%NSRFS ;SKIP IF IN RFC SENT STATE + JRST IMPRFQ ;QUEUE IT + LDB Q,IMSCFH + CAMN Q,IMPCSH + CAME D,IMSOC3(I) ;FROM CORRECT FOREIGN SOCKET? + JRST IMREFU ;NO, REFUSE + AOS IMSOC4(I) ;PUT INTO STATE 5 - OPEN + CAIE C,1 ;SKIP IF RTS + JRST IMPRF2 ;STR + DPB R,IMSCLN ;STORE LINK # +IMPRF1: PUSHJ P,IMPUIN ;INTERRUPT USER + JRST IMPBKL + +IMPRF2: LDB Q,IMSCBS + CAME Q,R + JRST IMCLDA ;BYTE SIZES DIFFER, REFUSE + JSP T,IMSTCM + 8,,2 ;TEXT: 8 BYTES, 2 WORDS + JRST [ AOS IMNANS + JRST IMPRF1 ] + MOVEI H,2(I) + LSH H,16. ;LINK # + IOR H,IMSOC8(I) ;MSG ALLOC + LSH H,4 + TLO H,(4_28.) ;ALL + MOVEM H,10(Q) + MOVE H,IMSOC7(I) ;BIT ALLOC + LSH H,4 + MOVEM H,11(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + JRST IMPRF1 + +IMPRFQ: CAIL E,NETSRS ;IF < 1000, START JOB "NETRFC" + JRST IMRFQ5 + MOVE T,IMPHTN(H) +; CAIE T,+_9 + CAME T,[IMPUS3-NW%ARP] ; Compare with our own host (minus net #) + SKIPL NETUSW + CAIA + JRST IMREFU ;REFUSE CONNECTION + HRROI T,NTRFCL + PUSHJ P,NUJBST ;LOAD SERVER + JRST IMREFU ;RING BUFFER FULL +IMRFQ5: SKIPGE Q,IMFFPQ ;SKIP IF ANY FREE SLOTS + JRST IMRFQ1 ;CLS OLDEST + MOVE W,(Q) + MOVEM W,IMFFPQ ;NEW FIRST FREE +IMRFQ9: SETOM (Q) ;END OF QUEUE + MOVEM E,1(Q) ;LOCAL SOCKET NUMBER + MOVEM D,2(Q) ;FOREIGN SOCKET NUMBER + CAIE C,2 ;SKIP IF STR + TLO R,400000 ;MARK AS RTS + MOVEM R,3(Q) ;LINK NUMBER OR BYTE SIZE + DPB H,[101000,,3(Q)] ;FOREIGN HOST INDEX + LDB W,[051100,,TIME] ;STORE TIME OF RECEIPT, IN 16/15 MOD 512. + DPB W,[221100,,3(Q)] + SKIPGE W,IMPEPQ ;END OF QUEUE + JRST IMRFQ2 ;QUEUE EMPTY + MOVEM Q,(W) ;PUT IN AT END OF QUEUE + MOVEM Q,IMPEPQ ;NEW END OF QUEUE + JRST IMRFCX + +IMRFQ2: MOVEM Q,IMPEPQ ;END OF QUEUE + MOVEM Q,IMPBPQ ;AND BEGINNING OF QUEUE + JRST IMRFCX + +IMRFQ1: MOVE J,IMPBPQ ;BEGINNING OF PENDING QUEUE + MOVE E,1(J) ;LOCAL SOCKET + MOVE D,2(J) ;FOREIGN SOCKET + PUSH P,IMPCSH + LDB H,[101000,,3(J)] ;FOREIGN HOST INDEX + MOVEM H,IMPCSH + PUSHJ P,IMPSCL ;SEND CLS + JRST IMRFQ3 ;NO BUFFERS AVAILABLE + AOSA IMNRFC ;# RFCS CLOSED +IMRFQ3: AOS IMNRFI ;# RFCS IGNORED + POP P,IMPCSH + MOVE H,IMPCSH + MOVE Q,IMPBPQ ;FLUSH FIRST ENTRY ON PENDING QUEUE + MOVE W,(Q) + MOVEM W,IMPBPQ + JRST IMRFQ9 + +IMREFU: PUSHJ P,IMPSCL ;SEND CLS + AOS IMNCNS ;CAN'T + AOS IMNRFI + JRST IMPBKL + +IMPCLS: SUBI A,8 ;MUST BE AT LEAST 8 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB D,B ;D GETS 32 BIT FOREIGN SOCKET NUMBER +REPEAT 3,[ + LSH D,8 + ILDB T,B + IORI D,(T) +] + ILDB E,B ;E GETS 32 BIT LOCAL SOCKET NUMBER +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + PUSHJ P,IMPLC ;LOOK FOR CONNECTION + JRST IMCLSQ ;LOOK IN QUEUE + MOVSI W,200000 ;SET CLS RCD BIT + IORB W,IMSOC4(I) ;RH IS STATE FOR DISPATCH + JRST @IMCLDT(W) + +IMCLDT: OFFSET -. +%NSCLS::IMPCLI +%NSLSN::IMPCLI +%NSRFC::IM2CLS +%NSRCL::IMPCLI +%NSRFS::IM4CLS +%NSOPN::IM5CLS +%NSRFN::IM6CLS +%NSCLW::IM7CLS +%NSCLI::IMPCLI +%NSINP::IMECLS + OFFSET 0 + +IM4CLS: HLLZS IMSOC4(I) .SEE %NSCLS + MOVEI W,%NCRFS + JRST IMCLDB + +IMECLS: MOVEI W,%NSCLI + JRST IMCCLS + +IMCLDA: HLLZS IMSOC4(I) .SEE %NSCLS + MOVEI W,%NCBYT ;BYTE MISMATCH + JRST IMCLDB + +IM6CLS: MOVSI W,20000 ;CLSED DURING RFNM WAIT + IORM W,IMSOC5(I) +IM5CLS: TDZA W,W .SEE %NSCLS +IM2CLS: MOVEI W,%NSRCL +IMCCLS: HRRM W,IMSOC4(I) ;CHANGE STATE + MOVEI W,%NCFRN +IMCLDB: DPB W,IMSCLS ;CLS REASON + PUSHJ P,IMPUIN ;INTERRUPT USER +IMCLQ2: PUSHJ P,IMPSCL ;SEND CLS + AOS IMNCNS + JRST IMPBKL + +IMPSCL: JSP T,IMSTCM ;SEND A CLS TO LOCAL SOCKET IN E AND FOREIGN SOCKET IN D (CLOBBERS D AND E) + 12.,,3 ;TEXT: 12 BYTES, 3 WORDS + POPJ P, + MOVEI H,3_4 ;3 NOPS + CLS + MOVEM H,10(Q) + LSH E,4 + MOVEM E,11(Q) ;LOCAL SOCKET NUMBER + LSH D,4 + MOVEM D,12(Q) ;FOREIGN SOCKET NUMBER + PUSHJ P,IMWCQ ;SEND CLS + JRST POPJ1 + +IMPCLI: AOS IMNCLI + JRST IMPBKL + +IM7CLS: HLLZS IMSOC4(I) .SEE %NSCLS + JRST IMPBKL + +IMCLSQ: PUSH P,A + PUSH P,B + MOVE A,E ;LOCAL SOCKET NUMBER + MOVEI T,0 + MOVE B,D ;FOREIGN SOCKET NUMBER + PUSHJ P,IMSPQP ;SEARCH PENDING QUEUE + JRST IMCLQ1 ;NOT THERE + MOVE E,A + POP P,B + POP P,A + JRST IMCLQ2 ;SEND HIM A CLS + +IMCLQ1: POP P,B + POP P,A + JRST IMPCLI ;CAN'T FIND HIM. IGNORE + +IMPALL: SUBI A,7 ;MUST BE AT LEAST 7 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB R,B ;LINK # + ILDB D,B + LSH D,8 + ILDB T,B + IORI D,(T) ;D GETS MESSAGE ALLOCATION + ILDB E,B ;E GETS BIT ALLOCATION +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + MOVE T,IMPCSH ;FOREIGN HOST + LSH T,8 + IOR R,T ;HEADER (HOST AND LINK #) + MOVEI W,1 ;TO TEST DIRECTION OF SOCKET + MOVSI I,-IMPSTL +IMPAL2: LDB T,IMSCHD ;FOREIGN HOST AND LINK NUMBER + SKIPGE IMSOC1(I) ;SKIP IF SLOT NOT IN USE + CAME T,R ;SKIP IF HEADER AGREES + JRST IMPAL1 + TDNE W,IMSOC2(I) ;SKIP IF NOT SEND + JRST IMPAL3 +IMPAL1: AOBJN I,IMPAL2 + ANDI R,377 + BUG INFO,[NET: IGNORED ALLOC HST ],OCT,IMPHTN(H),[LNK],OCT,R + AOS IMNALI + JRST IMPBKL ;IGNORE + +IMPAL3: SKIPL D + SKIPGE E + JRST 4,. + LDB T,IMSCBS ;GET BYTESIZE + IDIV E,T ;TRUNCATE TO 0 MODULO BYTESIZE + IMUL E,T ;(CLOBBER TT) + SKIPL IMSOC8(I) + SKIPGE IMSOC7(I) + JRST 4,. + ADDB D,IMSOC8(I) ;INCREASE ALLOCATIONS + ADDB E,IMSOC7(I) + MOVE Q,IMSOC5(I) + TLNE Q,140000 ;ACTIVATE IF USER (OR DIRECT CONN) CHECKING ALLOC + PUSHJ P,IMPUIN + MOVE T,IMSPIP(I) + CAME T,IMSMPP(I) ;SKIP IF OUTPUT BUFFER EMPTY + PUSHJ P,IMPIOS ;THIS GUY MAY HAVE STUFF TO GO OUT + JRST IMPBKL + +IMPLLS: MOVSI I,-IMPSTL ;LOOK FOR SOCKET IN E + MOVSI W,200000 +IMPLL2: TDNN W,IMSOC1(I) + SKIPL IMSOC1(I) ;NOT IN USE + JRST IMPLL1 + CAME E,IMSOC2(I) ;SKIP IF RIGHT LOCAL SOCKET NUMBER +IMPLL1: AOBJN I,IMPLL2 + JUMPL I,POPJ1 ;RETURN SOCKET TABLE INDEX IN RH OF I + POPJ P, ;NOT FOUND + +;INTERRUPT USER ASSOCIATED WITH CHANNEL IN I +IMPUIN: MOVSI U,200000 + TDNE U,IMSOC1(I) + POPJ P, ;CHNL BEING CLOSED + MOVE U,IMSOC5(I) + TLNE U,40000 + JRST IMPUIS ;JUMP IF SOCKET IS CONNECTED TO A STY. +IMPUIP: HRRZ U,IMSOC1(I) ;USER INDEX + LDB Q,[222000,,IMSOC1(I)] ;MASK FOR CHANNEL OPEN ON +IMPUIM: AND Q,MSKST2(U) ;ONLY ENABLED CHANNELS. + PUSH P,T ;VALIDATE THE USER INDEX + MOVEI T,LUBLK + IDIVM U,T + IMULI T,LUBLK + CAMN T,U + CAML U,USRHI + JRST 4,. + MOVSI T,(SETZ) ;PCLSR SO IT GETS IOC ERROR IF NEEDFUL + IORM T,PIRQC(U) ; EVEN IF IT DOESN'T HAVE NORMAL INTERRUPTS ENABLED + POP P,T + IORM Q,IFPIR(U) ;GEN SECOND WORD INTERRUPT + POPJ P, + +IMPUIS: PI2SAF ;HERE FOR INT. ON SOCKET CONNECTED TO A STY: + ANDI U,777 + SKIPL STYNTL-NFSTTY(U) + POPJ P, ;ALREADY ACTIVATED + MOVE Q,STYNTA ;PUT THAT STY ON THE XFER ACTIVATION LIST. + MOVEM Q,STYNTL-NFSTTY(U) + MOVEM U,STYNTA ;THEN RETURN. DON'T ACTUALLY INTERRUPT THE JOB; + POPJ P, ;IF ANYTHING FUNNY HAS HAPPENED, STYNTC WILL INTERRUPT. + +;LOOK FOR CONNECTION: LOCAL SOCKET IN E, FOREIGN SOCKET IN D, FOREIGN HOST IN H +IMPLC: MOVSI I,-IMPSTL +IMPLC2: SKIPGE IMSOC1(I) ;NOT IN USE + CAME E,IMSOC2(I) ;LOCAL SOCKET NUMBER + JRST IMPLC1 + LDB T,IMSCFH + CAMN D,IMSOC3(I) ;FOREIGN SOCKET NUMBER + CAME H,T +IMPLC1: AOBJN I,IMPLC2 + JUMPL I,POPJ1 + POPJ P, + +IMPINR: SOJL A,IMSHRT ;SHORT COUNT + ILDB D,B ;LINK # + DPB H,[101000,,D] ;CONCAT HOST&LINK + MOVSI I,-IMPSTL + LDB E,IMSCHD ;GET HOST FOR SOCKET + CAME D,E + AOBJN I,.-2 ;SEARCH FOR MATCHING HOST&LINK + JUMPGE I,IMPILS ;NOT FOUND +NCPIRS: HRRZ E,IMSOC4(I) ;STATE + MOVE E,CHNBIT(E) ;BIT TO CORRESPOND + TRNN E,1_%NSRFC+1_%NSRFS+1_%NSOPN+1_%NSRFN+1_%NSCLW+1_%NSINP + ;OK STATES RFCRCV, RFCSNT, OPEN, RNMWT, CLSSNT, DATA + JRST IMPILS ;IN BAD STATE + TRNE E,1_%NSCLW ;IGNORE INT IF CLSSNT STATE (NOT ERROR) + JRST IMPBKL + MOVSI D,4000 + IORM D,IMSOC5(I) ;INT FLAG 4.3 BIT OF IMSOC5(SOCK) + PUSHJ P,IMPUIN ;INT TO USER + JRST IMPBKL + +IMPINS: SOJL A,IMSHRT ;SHORT + ILDB D,B ;LINK + MOVEI I,-2(D) ;0,1 -> 777776,777777 ILLEGAL LINKS + CAIGE I,IMPSTL ;CHECK IN RANGE 2 TO IMPSTL+1 + SKIPL IMSOC1(I);AND IN USE + JRST IMPILS ;BAD LINK + LDB T,IMSCFH + CAMN T,IMPCSH ;SKIP IF HOST NOT MATCHED BY MSG + JRST NCPIRS +IMPILS: BUG INFO,[NET: BAD INT CTL MSG HST ],OCT,IMPHTN(H),[LNK ],OCT,D,[IMSOC4],OCT,IMSOC4(I) + JRST IMPBKL ;NOTE- I MAY BE -1 OR -2 OR UP TO 256, IF LNK BAD, IGNORE + +IMPECI: AOS IMPNEI ;WILL EVENTUALLY GIVE JOB TO MAIN PROG + JRST IMPBKL + +IMPECO: ILDB D,B ;GET 8 BIT DATA TO ECHO + SOJL A,IMSHRT + SKIPE IMPNEA + JRST IMPECI ;ONLY ONE TO A CUSTOMER + JSP T,IMSTCM + 2,,1 ;TEXT: 2 BYTES, 1 WORD + JRST IMPECI + LSH D,20. ;DATA TO BE ECHOED + TLO D,(10._28.) ;ERP + MOVEM D,10(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + AOS IMPNEA + JRST IMPBKL + +IMPERM: SUBI A,11. ;COUNT BYTES + MOVE C,TIME + MOVEM C,IMPERB + MOVE C,IMPHTN(H) ;REAL HOST NUMBER + MOVEM C,IMPERB+1 + MOVE C,[441100,,IMPERB+2] + MOVEI D,11. ;BYTES TO COPY + ILDB T,B ;COPY BYTES FROM THEIR MSG + IDPB T,C + SOJG D,.-2 + BUG INFO,[NET: ERR MSG FM HST ],OCT,IMPERB+1,[MSG],OCT,IMPERB+2,OCT,IMPERB+3 + ;ONLY PRINTS FIRST 8 BYTES OF ERR INFO + JUMPGE A,IMPBKL ;IF COUNT OK, GET MORE + JRST IMSHRT ;SHORT COUNT + +IMPRSI: AOS IMPNRI + JRST IMPBKL + +IMPRST: MOVE T,IMPHTN(H) +; CAIE T,+_9 ;IF RST FROM OURSELVES, JUST SEND RRP + CAME T,[IMPUS3-NW%ARP] + PUSHJ P,IMPRSR + SKIPE IMPNRA + JRST IMPRSI + JSP T,IMSTCM + 1,,1 ;TEXT: 1 BYTE, 1 WORD + JRST IMPRSI + MOVSI D,(13._28.) ;RRP + MOVEM D,10(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + PUSHJ P,IMPIOS + AOS IMPNRA + JRST IMPBKL + +IMPRSR: MOVSI I,-IMPSTL ;LOOK FOR USERS OF THIS HOST + MOVSI TT,200000 +IMPRS2: TDNN TT,IMSOC1(I) ;GUY GOING AWAY ANYHOW + SKIPL IMSOC1(I) + JRST IMPRS1 + LDB C,IMSCFH ;FOREIGN HOST + CAME C,IMPCSH + JRST IMPRS1 ;WRONG HOST + HRRZ C,IMSOC4(I) + MOVEI D,%NSCLS + CAIN C,%NSINP + MOVEI D,%NSCLI ;INPUT STILL AVAILABLE + HRRM D,IMSOC4(I) + MOVEI D,%NCRST + DPB D,IMSCLS ;CLS REASON IS RST + PUSHJ P,IMPUIN ;INTERRUPT USER +IMPRS1: AOBJN I,IMPRS2 + ;IF HOST CAN SEND A RST, IT IS UP, BUT DON'T + ;REALLY CONSIDER IT UP UNTIL RRP, RTS, OR STR IS RECEIVED + ;I DON'T KNOW WHY IT'S DONE THIS WAY + POPJ P, + +IMPRRP: LDB J,IMHSBT + SOJL J,IMPRR1 + JUMPG J,IMPBKL ;ALREADY UP, MAYBE BECAUSE OF PRIOR RTS,STR + MOVEI J,2 + DPB J,IMHSBT ;MARK HIM UP + SOS IMRFCT + JRST IMPBKL + +IMPRR1: BUG INFO,[NET: RRP W-O RST HST],OCT,IMPHTN(H) + JRST IMPBKL + +;GET CONTROL QUEUE SLOT +IMGCQS: SKIPG IMFCQL ;SKIP IF ANY LEFT + JRST IMGCQL ;NONE + SKIPG Q,IMFFCQ ;POINTER TO SLOT + JRST 4,. + MOVE W,(Q) + MOVEM W,IMFFCQ ;PATCH OUT OF FREE LIST + SETOM (Q) + SOS W,IMFCQL ;NUMBER FREE LEFT + CAIN W,1 ;SKIP IF MORE THAN ONE LEFT + SETOM IMPHI ;SET FLAG TO HOLD UP INPUT + JRST POPJ1 + +IMGCQL: AOS IMNPIL + POPJ P, + +IMWCQ: PUSHJ P,IMWPCQ + JRST IMPIOS ;START OUTPUT + +;ADD BLOCK IN Q TO OUTPUT CONTROL QUEUE, BASHES W +IMWPCQ: SETOM (Q) + SKIPGE W,IMPLCQ + JRST IMWCQ1 ;CONTROL QUEUE EMPTY + AOSE (W) + JRST 4,. ;END OF QUEUE DIDN'T POINT TO -1 + MOVEM Q,(W) + MOVEM Q,IMPLCQ + POPJ P, + +IMWCQ1: MOVEM Q,IMPLCQ + MOVEM Q,IMPNCQ + POPJ P, + +;ADD MAIN PROGRAM BLOCK TO PI QUEUE (CALL AT MP LEVEL) +IMPMPQ: MOVSI Q,777 + IORM Q,IMPMPU+1 ;NOT LOCKED BY THIS JOB ANY MORE + SKIPL U ;SKIP IF CALLED FROM DIRECT-CONNECT CLOCK LEVEL + PUSHJ P,LSWDEL ;PI LEVEL WILL UNLOCK + CONO PI,NETOFF + MOVEI Q,IMPMPL + PUSHJ P,IMWPCQ + CONO PI,NETON + JRST IMPOST + +;CALL BY JSP T,IMSTCM +;SET UP STANDARD PI CONTROL MESSAGE +;BYTE COUNT,,TEXT LENGTH +;ERROR RETURN + +IMSTCM: PUSHJ P,IMGCQS ;GET CONTROL QUEUE SLOT IN Q + JRST 1(T) ;NONE AVAILABLE + MOVSI H,17_10. ;MESSAGE TYPE = 0, LINK # = 0, NEW FMT + MOVEM H,2(Q) + MOVE H,IMPCSH ;GET IMP AND HOST + MOVE H,IMPHTN(H) +IFN 1, DPB H,[103000,,3(Q)] ; Store host addr +IFN 0,[ DPB H,[301000,,3(Q)] ;STORE HOST + LSH H,-9 + DPB H,[102000,,3(Q)] ;STORE IMP +] ;IFN 0 + HLRZ H,(T) ;BYTE COUNT + LSH H,8 + IOR H,[8_24.] ;BYTE SIZE = 8 + MOVEM H,7(Q) + HRLZ H,(T) + HRR H,IMPCSH + MOVSM H,1(Q) ;HOST INDEX,,TEXT LENGTH + JRST 2(T) ;NORMAL RETURN (NOTE THAT H HAS BEEN RESTORED TO IMPCSH) + +;RECEIVED LEADER OF REGULAR MESSAGE NOT ON CONTROL LINK +;THE HOST-HOST LEADER WORD (WD 6) HAS NOT YET BEEN DATAI'ED. +;SWITCH TO 32-BIT MODE FIRST IF NECESSARY. +IMPRMD: +IFN INETP,[ + CAIE B,IMPILB+4 ; Verify that NCP leader is next word + JRST IMPLD3 ; Barf... +] + MOVE D,IMPCSH + LSH D,8 + MOVE I,IMPCLN + IOR D,I ;HEADER + SUBI I,2 ;SOCKET TABLE INDEX + JUMPL I,IMPRM7 ;BAD LINK # + SKIPGE A,IMSOC1(I) + TLNE A,200000 ;SKIP IF NOT BEING CLOSED + JRST IMPRM7 ;SOCKET DOESNT EXIST OR BEING CLOSED + MOVEI A,1 + CAIGE I,IMPSTL + TDNE A,IMSOC2(I) ;SKIP IF RECEIVER + JRST IMPRM7 ;BAD LINK # OR MESSAGE FOR A SENDER + LDB C,IMSCHD ;HEADER + CAME D,C ;SEE IF HEADERS AGREE + JRST IMPRM7 ;NOPE, I.E. FROM WRONG HOST OR CLOSED + HRRZ D,IMSOC4(I) + CAIE D,%NSOPN + CAIN D,%NSINP + JRST IMPRMA + JRST IMPRM7 +IMPRMA: SKIPGE IMSOC6(I) ;SKIP IF NOT LOCKED BY CORE JOB + JRST IMPRMP ;LOCKED, COME BACK LATER +IFN KAIMP,[ + SKIPL IMSOC5(I) ;SKIP IF 32 BIT TRANSFER + CONO IMP,IMI32C ;SET 36 BIT INPUT + SKIPGE IMSOC5(I) ;SKIP IF NOT 32 BIT TRANSFER + CONO IMP,IMI32S ;SET 32 BIT INPUT +]IFN DMIMP,[ + SKIPL IMSOC5(I) ;SKIP IF 32BIT + CONO FI,FII32C ;SET 36BIT + SKIPGE IMSOC5(I) ;SKIP IF 36 BIT + CONO FI,FII32S ;SET 32 BIT +] + DATAI IMP,IMPILB+5 ;GET THE HEADER WORD + LDB A,IMCBBP + MOVEM A,IMPCBS + LDB B,IMSCBS ;Check for fraudulent byte size + CAME A,B + JRST IMPRMZ ;Discard message + LDB B,IMBCBP + MOVEM B,IMPCBC + MOVEM B,IMPNBI ;SAVE BYTE COUNT FOR LATER + SOSGE IMSOC8(I) + JRST IMRMAF ;MESSAGE ALLOCATION EXCEEDED + JUMPE B,IMPIRT ;ZERO LENGTH MESSAGE + IMUL A,B ;BIT COUNT + MOVN D,A + ADDB D,IMSOC7(I) ;REMAINING BIT ALLOCATION + JUMPL D,IMRMAH ;BIT ALLOCATION EXCEEDED + TRNE TT,IMPLW + JRST IMRMAG ;MESSAGE IS SHORT + MOVSI D,200000 + IORB D,IMSOC6(I) ;ACTIVE AT PI LEVEL + SKIPGE IMSOC5(I) + IDIVI A,32. + SKIPL IMSOC5(I) + IDIVI A,36. + SKIPE B + ADDI A,1 ;NUMBER OF WORDS MESSAGE WILL TAKE + HRRZ B,IMSPIP(I) ;ADDRESS WHERE MESSAGE HEADER WILL GO + SKIPL (B) + JRST 4,. ;HEADER WORD SHOULD BE -1 + HRRZ C,IMSBFE(I) ;GET ADDRESS OF LAST WORD IN BUFFER + CAML B,C + MOVEI B,-1(D) ;HEADER IS LAST IN BUFFER, SO DATA IS FIRST + MOVE E,B ;RH(BLKI POINTER) IN E + ADD A,B ;ADDRESS WHERE LAST WORD OF MESSAGE WILL GET STORED + SETZM IMNWSI ;ASSUME WILL ONLY NEED ONE BLKI + CAMG A,C + JRST IMPRM8 ;JUMP IF NO WRAP +;DROPS THROUGH + ;DROPS IN + SUB B,C ;- # WDS TO READ FIRST TIME + SUB A,C ;+ # WDS TO READ SECOND TIME + SKIPGE B + SKIPG A + JRST 4,. ;SCREW + MOVN C,A ;NEG OF REMAINING WORD COUNT + MOVSS C ;TO LEFT HALF FOR BLKI POINTER + HRRI C,-1(D) ;RING AROUND TO BEGIN OF BUFFER + MOVEM C,IMNWSI ;STORE FOR INTCHN BLKI RUNOUT (FLAG IF -) + ADD C,A ;ADR+COUNT + HRRZM C,IMPNIW ;EXPECTED END OF BLKI + SKIPA A,B +IMPRM8: SUBM B,A ;A GETS - # WORDS TO READ + MOVE B,E + HRL B,A ;BLKI POINTER + SUB E,A ;EXPECTED LAST WORD + SKIPE IMNWSI ;IF DOING 2 BLKIS, EXPECTED END ALREADY STORED + SKIPA E,IMPNIW + MOVEM E,IMPNIW ;EXPECTED LAST BLKI ADDRESS + HRRZ A,IMSPIP(I) ;SEE IF CLOBBERING GOOD-DATA PART OF BUFFER + CAIL A,@IMSMPP(I) ;SKIP IF MPP > PIP + JRST [ CAIG E,(A) + CAIGE E,@IMSMPP(I) + JRST IMPRMT + JRST 4,. ] + CAIGE E,@IMSMPP(I) + CAIG E,(A) + JRST 4,. +IMPRMT: HRRZ A,IMSOC6(I) ;SEE IF CLOBBERING CORE NOT PART OF BUFFER + CAIL E,(A) + CAILE E,@IMSBFE(I) + JRST 4,. + HRRZM I,IMPIPI ;THIS SOCKET NOW ACTIVE AT P.I. LEVEL + MOVEI C,%ISIND ; New state = reading NCP data message + JRST IMPRM9 ; Start reading + +IMPRMP: MOVSI D,100000 ;SET INPUT HELD UP BY CORE JOB + IORM D,IMSOC6(I) +IFN KAIMP,[ + MOVE D,IMPPIA + MOVEM D,IMPSVP + SETZM IMPPIA ;TURN OFF NETWORK FOR A WHILE +] +IFN DMIMP,CONO FI,FIIN+0 ;SET PIA TO 0 FOR A WHILE, CORE JOB WILL GET BACK + JRST IMPRET + +IMRMAH: AOSA IMNBAE +IMRMAF: AOS IMNMAE + JRST IMPIRT + +IMPRM7: AOSA IMNMNC +IMRMAG: AOS IMNMSS + JRST IMPIRT + +; Got Last Imp Word (in A) of regular NCP data message +; Comes here from IMPBKX. + +IMPRMB: MOVE I,IMPIPI + MOVE B,IMBLKI + CAMN B,IMPNIW + JRST IMPRMC ;ONE EXTRA WORD OF IMP PADDING, IGNORE IT + ADD B,[1,,1] ;ADDR TO NEXT WORD, COUNT TO ZERO + CAME B,IMPNIW + JRST IMPRMY + MOVEM A,(B) ;STORE LAST WORD +IMPRMC: MOVE E,IMPNBI ;# BYTES IN + ADDM E,IMSMPC(I) ;MAKE AVAIL TO M.P. + MOVEM E,@IMSPIP(I) ;STORE HEADER + AOS E,IMPNIW ;WORD AFTER MSG WILL BE NEXT HEADER + CAILE E,@IMSBFE(I) + HRRZ E,IMSOC6(I) ;WRAP + HRRM E,IMSPIP(I) ;LEAVE LH OF IMSPIP ALONE + CAIN E,@IMSMPP(I) + JRST 4,. ;BUFFER 1 WORD TOO SMALL? + SETOM (E) + MOVEI E,%NSINP + HRRM E,IMSOC4(I) ;INPUT AVAILABLE + PUSHJ P,IMPUIN ;INTERRUPT USER + MOVSI D,200000 ;CLEAR ACTIVE AT P.I. LEVEL + ANDCAM D,IMSOC6(I) + SETOM IMPIPI + JRST IMPIR1 + +IMPRMY: HRRZ E,IMPNIW ;NOT ENDING WHERE IT'S SUPPOSED TO + SUBI E,(B) ;E GETS NUMBER OF MISSING WORDS + MOVE H,IMPCSH + BUG INFO,[NET: MSG FM HST ],OCT,IMPHTN(H),[SHORT ],DEC,E,[WDS, BC],DEC,IMPCBC + JRST IMPRMC ;PRETEND HOST TRANSMITTING GARBAGE + +IMPRMZ: MOVE H,IMPCSH + BUG INFO,[NET: HST ],OCT,IMPHTN(H),[SENT BYTE SIZE ],DEC,A,[SHOULD BE],DEC,B + JRST IMPIRT ;Discard message + +SUBTTL ARPANET NCP OUTPUT INTERRUPT LEVEL + +;HERE ON COMPLETION OF TRANSMISSION OF CONTROL MESSAGE + +IMPOB6: SETZM IMPOS + SKIPN A,IMPSVQ + JRST IMPRET ;THAT WAS A NOP + HLRZ B,1(A) ;HOST TABLE INDEX + MOVSI D,400000 + IORM D,IMPHTB(B) ;SET RFNM WAIT BIT + AOS IMRFCT + LDB D,[051100,,TIME] + DPB D,[221100,,IMPHTB(B)] ;STORE TIME TOO + HLRZ T,A + HRRZS A + MOVE B,(A) + MOVEM B,(T) + JUMPGE B,IMOB7A + CAME A,IMPLCQ + JRST 4,. ;IMPLCQ GAVE WRONG LAST MESS NO. + MOVEM T,IMPLCQ + CAIN T,IMPNCQ + SETOM IMPLCQ +IMOB7A: CAIN A,IMPMPL ;SKIP IF NOT MAIN PROG BLOCK + JRST [ SETOM IMPMPU + JRST IMPRET ] + MOVE B,IMFFCQ + CAIN B,(A) + JRST 4,. ;MAKING INFINITE LOOP + MOVEM B,(A) + MOVEM A,IMFFCQ + AOS A,IMFCQL + SKIPGE B,IMPHI ;RETURN IF INPUT NOT HELD UP + CAIG A,1 ;SKIP IF INPUT HELD UP AND NOW ENOUGH FREE + JRST IMPRET + SETZM IMPHI + AOJE B,IMPRET ;INPUT WAS NOT YET SUCCESSFULLY HELD UP + AOJN B,[JRST 4,.] ;IMPHI SHOULD HAVE BEEN -2 + AOS IMPNUH + MOVE TT,IMSTAS ;GET OLD CONI + TRNE TT,IMPLW +IFN KAIMP,[ + CONO IMP,IMI32C + DATAI IMP,A +];KAIMP +IFN DMIMP,[ + CONO FI,FII32C + MOVE A,IMPSUS +];DMIMP + TRNE TT,IMPLW ;RESUME INPUT + JRST IMPBKV + SKIPE IMPIS + JRST 4,. + JRST IMSTRT + +;HERE ON COMPLETION OF TRANSMISSION OF DATA MESSAGE + +IMPOBG: SETZM IMPOS + MOVE I,IMPOPI + HRRZ Q,IMSOC4(I) + CAIN Q,%NSOPN + AOS IMSOC4(I) .SEE %NSRFN ;PUT INTO RFNM WAIT STATE + MOVSI A,20000 + CAIN Q,%NSCLS + IORM A,IMSOC5(I) + MOVSI Q,200000 + ANDCAB Q,IMSOC6(I) ;NO LONGER ACTIVE AT P.I. LEVEL + SETOM IMPOPI + MOVN A,IMPNBT ;BITS SENT + ADDM A,IMSC7I(I) ;DECREASE BITS IN BUFFER + ADDB A,IMSOC7(I) ;DECREASE ALLOCATION + SKIPL A ;SKIP IF ALLOC LOST + SOSGE IMSOC8(I) ;SKIP IF MSG ALLOC DIDN'T LOSE + JRST 4,. ;LOST + MOVE Q,IMSOC5(I) + TLNN Q,140000 ;INTERRUPT USER IF DIRECT CONNECT (CHEAP), DEPEND ON ALLOC, + SKIPN IMSMPC(I) ; OR IF OUTPUT BUFFER WAS FULL, + PUSHJ P,IMPUIN ; SINCE HE MAY WANT TO SEND MORE + MOVE A,IMPNBO ;# BYTES FREED IN BUFFER BY REMOVAL OF MSG + ADDM A,IMSMPC(I) ;SPACE USED BY MESSAGE NOW FREE + MOVE A,IMPNPT ;UPDATE IMSPIP + HRRZ Q,IMSOC6(I) ;VALIDATE THIS + CAILE Q,(A) + JRST 4,. ;POINTS BEFORE BUFFER + HRRZ Q,IMSBFE(I) + CAIGE Q,(A) + JRST 4,. ;POINTS AFTER BUFFER + MOVEM A,IMSPIP(I) ;.. + JRST IMPRET + +;OUTPUT A DATA MESSAGE. + +IMPOBD: MOVE T,TIME + SUB T,IMSOCT(I) + SKIPL IMSOC4(I) ;SKIP IF WANT TO SEND THIS BUFFER + CAIL T,30.*2 ;SKIP IF BUFFER FIRST WRITTEN LESS THAN 2 SEC AGO + JRST IMOBD1 + JRST IMPOBA ;DON'T SEND NOW, GO BACK AND LOOK FOR OTHERS + +IMOBD1: MOVE TT,IMSPIP(I) + CAMN TT,IMSMPP(I) ;SKIP IF ANY BITS TO SEND + JRST IMPOBA ;NO + SKIPE IMSOC7(I) ;SKIP IF NO BITS ALLOCATED + SKIPN IMSOC8(I) ;SKIP IF MSG ALLOCATED + JRST IMPOBA ;NO BITS OR NO MSGS ALLOWED + MOVSI Q,200000 + IORB Q,IMSOC6(I) ;ACTIVE AT PI LEVEL + +;CODE TO SEND OUT A BUFFER OR PARTIAL BUFFER +;ON ENTRY - I/ SOCKET TABLE INDEX +; Q/ BUFFER POINTER FROM IMSOC6 +; TT/ BYTE POINTER TO FIRST BYTE TO SEND +;SETS UP - T/ WORD SIZE (32 OR 36) +; E/ FLAGS FROM IMSOC5 +; B/ BYTE SIZE +; C/ # BITS TO SEND + + SETZM IMPNBO + MOVE T,IMSMPP(I) + MOVEM T,IMOB0Z ;SAVE FOR DEBUGGING + MOVEI T,32. + SKIPL E,IMSOC5(I) ;SKIP IF IN 32BIT MODE + MOVEI T,36. ;SET 36BIT + LDB B,IMSCBS ;BYTE SIZE + HRRZ C,IMSMPP(I) ;COMPUTE # OF BYTES TO SEND + SUBI C,(TT) + JUMPL C,[MOVE D,IMSBFE(I) ;WRAPS AROUND + SUB D,Q + ADDI C,1(D) ;SO ADD # WDS IN BUFFER + JRST .+1] + IMUL C,T ;FIRST GUESS AT NUMBER OF BITS + LDB A,[360600,,TT] ;GETS POSITION FIELD OF BYTE PTR + LDB D,[360600,,IMSMPP(I)] + SUBM A,D ;CORRECTION TO NUMBER OF BITS + ADD C,D ;C NOW HAS NUMBER OF SENDABLE BITS IN BUFFER + SKIPL E ;SKIP IF 32BIT + JUMPN A,IMOB5A ;36BIT - JUMP IF NOT 0 (MIDDLE OF WORD) + CAILE A,4 ;32BIT - SKIP IF 4, OR 36BIT 0 - SKIP IF NOT MID-WORD + JRST IMOB5B ;32BIT MID-WORD - SEND PART OR REST OF WORD + CAME TT,IMSBFE(I) ;AT RIGHT OF WORD, IS IT LAST WORD? + AOSA TT ;NO, ADVANCE TO NEXT + HRR TT,Q ;YES, WRAP AROUND TO FIRST + TLO TT,440000 ;SWITCH FROM RIGHT OF WORD TO LEFT OF WORD + CAMG C,IMSOC7(I) ;SKIP IF TOO BIG FOR ALLOCATE + CAILE C,8000. ;FITS IN ALLOCATE, SKIP IF FITS IN IMP MESSAGE + JRST IMOB1 ;MUST SEND LESS THAN ALL THE BITS IN BUFFER +IMOB0F: MOVE D,IMSMPP(I) ;SENDING WHOLE BUFFER + LDB J,[360600,,D] ;ADVANCE IMSMPP TO NEXT WORD BOUNDARY + ADDI J,-36.(T) ;RH(J) := # BITS TO ADVANCE TO WORD BOUNDARY + MOVNI J,(J) + IDIV J,B + ADDM J,IMSMPC(I) ;SUBTRACT FROM FREE THE BYTES SKIPPED OVER + MOVNM J,IMPNBO ;BUT RETURN TO FREE AFTER TRANSMISSION + HLL D,IMSBFE(I) ;NOW ADVANCE IMSMPP TO RIGHT END OF WORD + MOVEM D,IMSMPP(I) ;AND IMSPIP WILL GET SET EQUAL TO IMSMPP +IMOB0A: MOVEM D,IMPNPT ;ILDB -> FIRST BYTE TO SEND OUT NEXT TIME + JUMPLE C,[JRST 4,.] ;SOMEBODY COMPUTED BAD # BITS + MOVE A,C + IDIV C,B ;C := # BYTES GETTING SENT + JUMPN D,[JRST 4,.] ;LOSS, TRYING TO SEND PARTIAL BYTE + ADDM C,IMPNBO ;# BYTES TO RETURN TO FREE AFTER MSG SENT + MOVEM A,IMPNBT ;# BITS TO SUBTRACT FROM ALLOCATION THEN +;DROPS THROUGH + ;DROPS IN +;NOW SET UP BUFFER HEADER FOR IMP MESSAGE IN IMOLDR +; TT -> FIRST WORD TO SEND +; A NUMBER OF BITS TO SEND +; C NUMBER OF BYTES +; B BYTE SIZE +; T WORD SIZE +; E FLAGS + + LDB H,IMSCFH ;HOST TABLE INDEX + MOVEI Q,IMOLDR-2 ;HACK HACK + PUSHJ P,STHSTP ;STORE HOST NUMBER, MESSAGE TYPE 0 + LDB Q,IMSCLN ;LINK NUMBER + DPB Q,[001000,,IMOLDR+1] + LDB Q,[221000,,IMSOC6(I)] ;GET BUFFER TYPE + MOVEI D,4 + CAIN Q,377 + MOVEI D,7 + DPB D,[400400,,IMOLDR+1] ;STORE HANDLING TYPE, DEPENDING ON BUFFER SIZE + DPB B,[201000,,C] ;STORE SIZE IN SAME WD AS COUNT + LSH C,8 + MOVEM C,IMOLDR+5 ;HOST-HOST HEADER - 00,SIZE,BYTE-COUNT,0000 +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;36BIT MODE FOR HEADER, AND NO PIA YET + DATAO IMP,IMOLDR ;OUTPUT THE FIRST LEADER WORD + SETZM IMOPNT ;START AT BEGINNING OF IMOLST + MOVE B,[-5,,IMOLDR] ;SEND REST OF LEADER + MOVEM B,IMOLST + MOVEI B,3 + SKIPGE E + MOVEI B,2 + MOVEM B,IMOMOD ;SEND DATA IN 32 OR 36 BIT MODE AS APPROPRIATE + ADDI A,-1(T) ;ROUND UP IF NOT EXACT + IDIV A,T ;# WDS TO SEND + MOVEI D,-1(TT) ;FIRST WORD TO SEND MINUS ONE + ADDI D,(A) ;LAST WORD TO SEND + CAIG D,@IMSBFE(I) ;SKIP IF WRAP + JRST IMOB7 + HRRZ B,IMSBFE(I) ;COMPUTE # TO SEND FIRST TIME + SUBI B,-1(TT) ;B GETS PLUS NUMBER TO SEND FIRST TIME + SUBM B,A ;A GETS MINUS NUMBER TO SEND SECOND TIME + MOVNI C,(B) + HRLI C,-1(TT) ;C GETS SWAPPED BLKO POINTER FOR FIRST TIME + MOVE Q,IMSOC6(I) ;POINTER TO BUFFER +IFN KAIMP,[ + MOVEI B,3 ;SEND LAST WORD SEPARATELY + MOVEM B,IMOBK2 + AOJE A,.+3 +] HRLI A,-1(Q) ;BLKO POINTER FOR SECOND TIME + MOVSM A,IMOBK2 +IFN KAIMP,[ + MOVNI A,(A) + ADDI A,-1(Q) + HRROM A,IMOBK3 ;STORE BLKO POINTER TO LAST WORD +] + JRST IMOB8 + +IMOB7: MOVSI C,3 ;NO WRAP, SO NO SECOND BLKO + MOVSM C,IMOBK2 +IFN KAIMP,[ + SOS D + HRROM D,IMOBK3 ;DO LAST WORD SEPARATELY + SOJE A,IMOB8 ;SPECIAL CASE LAST WORD IS ONLY WORD +] + MOVNI C,(A) ;MAKE BLKO POINTER + HRLI C,-1(TT) +IMOB8: MOVSM C,IMOBK1 + MOVSI TT,400000 ;TURN OFF "SEND ME" + ANDCAM TT,IMSOC4(I) + HRRZM I,IMPOPI ;SAVE INDEX FOR BLKO RUNOUT + AOS IMPMSS+0 + MOVEI C,%ISOND ;STATE FOR "END OF DATA" + JRST IMOB9 + +;BUFFER CANNOT BE SENT AS 1 MSG. GRT ALLOC OR 8000 BITS. + +IMOB1: MOVE C,IMSOC7(I) ;ALLOC + CAILE C,8000. + MOVEI C,8000. ;C := MIN(BITS IN BUFFER, ALLOC, MAX IMP MSG SIZE) + TLNE E,2000 ;SKIP IF BYTES EXACTLY FIT IN WORD + JRST IMOB3 ;MUST SEND MULTI WORDS + CAMGE C,T ;SKIP IF ALLOC GEQ WDSIZ + JRST IMOB2 ;MUST SEND PART WORD + IDIV C,T ;#WDS + MOVE D,C + IMUL C,T ;#BITS IN THOSE WDS +IMOB1A: ADDI D,-1(TT) ;LAST WORD OUTPUT + CAIG D,@IMSBFE(I) + JRST .+3 + SUBI D,@IMSBFE(I) ;WRAP AROUND + ADDI D,-1(Q) + HLL D,IMSBFE(I) ;PUT IN BYTE PART (RIGHT END OF WORD) + JRST IMOB0A ;BUILD HEADER AND OUTPUT + +;SEND PART OF WORD BECAUSE ALLOC IS TOO SMALL + +IMOB2: MOVE D,TT ;-> FIRST BYTE TO BE SENT + MOVNI A,-36.(C) ;36-BITS SENT + DPB A,[360600,,D] ;IS NEXT BYTE TO GO + JRST IMOB0A + +;SEND PARTIAL BUFFER OF BYTES WHICH DO NOT FIT EXACTLY IN WORDS (E.G. 7BIT BYTES) +;MUST SEND A "QUANTUM" WHICH FOR LAZINESS' SAKE IS 36 BYTES + +IMOB3: MOVEI A,36. ;#BITS IN A WORD + IMUL A,B ;#BITS IN A QUANTUM + IDIV C,A ;# QUANTA + JUMPE C,IMOB4 ;NOT ENOUGH ALLOC FOR EVEN 1 QUANTUM, SORRY CHARLIE + MOVE D,C + IMUL C,A ;#BITS TO SEND + IMUL D,B ;#WDS TO SEND (36 BYTES TAKE WDS) + JRST IMOB1A + +;NEED MORE ALLOCATE TO SEND A BUFFER FOR THIS ODD-SIZE CONNECTION + +IMOB4: MOVSI T,200000 + ANDCAM T,IMSOC6(I) ;CLEAR "ACTIVE AT PI LEVEL" BIT + JRST IMPOBA ;MAYBE TRY ANOTHER ONE + +;SENDING REST OF PARTIAL WORD (PI PTR NOT AT WORD BOUNDARY) +;A/ BITS LEFT IN WORD + +IMOB5A: SKIPA C,A ;36BIT GETS WHOLE WD +IMOB5B: HRREI C,-4(A) ;32BIT GETS 4 LESS + MOVNI J,-36.(A) ;# BITS SHIFT TO LEFT JUSTIFY + HRRZ D,TT + CAIN D,@IMSMPP(I) ;IF WHOLE REST OF BUFFER IS IN THIS WORD + JRST [ LDB D,[360600,,IMSMPP(I)] + SUB A,D ;A := NUMBER OF BITS TO SEND + MOVE C,(TT) ;ALIGN BITS TO BE SENT IN LEFT OF WORD + LSH C,(J) + MOVEM C,(TT) + MOVE C,A + JRST IMOB0F ] ;RE-ALIGN POINTERS TO WORD BOUNDARY + CAMLE C,IMSOC7(I) ;SKIP IF WILL FIT IN ALLOC + JRST IMOB6 ;MUST SEND BYTES NOT LEFT JUST IN WD, AND MORE TO RIGHT + MOVE D,(TT) ;GET WORD + LSH D,(J) ;LEFT JUSTIFY + MOVEM D,(TT) + MOVE D,TT + HLL D,IMSBFE(I) ;ADVANCE PI POINTER TO END OF THIS WORD + JRST IMOB0A ;BUILD HDR & SEND + +;SEND MIDDLE PART OF WORD. BECAUSE OF SMALL ALLOCATES, THE LEFT END OF THE +; WORD WAS SENT AND ALSO THERE IS NOT ENOUGH ALLOCATE TO SEND THE REST +; OF THE ONE WORD. THIS MIGHT NEVER OCCUR EXCEPT FOR 8 BIT BYTES. +;MUST MOVE GOOD BITS TO LEFT END OF WORD, WITHOUT DISTURBING BITS TO THE RIGHT + +IMOB6: MOVE C,IMSOC7(I) ;CAN ONLY SEND ALLOC BITS + SUB A,C ;POS OF LO BIT TO PICK UP + DPB A,[360600,,TT] ;POS IN BYTE PTR + MOVE D,TT ;SAVE ADVANCED PI PNTR + DPB C,[300600,,TT] ;STORE AS SIZE OF BYTE + LDB R,TT ;GET BYTE + MOVNI A,-36.(C) ;POS OF LO BIT TO STORE + DPB A,[360600,,TT] ;POS IN B PTR + DPB R,TT ;STORE BYTE AWAY + JRST IMOB0A ;SEND THE BYTE(S) + +OVHMTR UUO ;YET MORE RANDOM UUOS diff --git a/src/system/net.32 b/src/system/net.32 new file mode 100755 index 00000000..a8793d9b --- /dev/null +++ b/src/system/net.32 @@ -0,0 +1,501 @@ +;; For ITS network stuff, the following parameters are defined: +; +; NETP - General network code (net independent, both CHAOS, NCP, TCP, etc) +; INETP - Internet Protocol code. Must have IMPP or some other device. +; NCPP - Include NCP code (IMPP must be on) +; TCPP - Include TCP code (INETP must be on) + +; CHAOSP - Include CHAOS net code +; - other CHAOS stuff, all independent of internet stuff. + +NE%UNT==:<1_32.> ; Escape bit indicating non-Internet address +NW$BYT==:301400 ; Byte pointer to network number (approx!) +NE%STR==:<1_33.> ; Escape bit indicating string-type address + +DEFINE HOSTN A,B,C,D +.RADIX 10.,<<<<+B>_8>+C>_8>+D,!TERMIN + +; HOSTS3 full word network # values for certain networks + +NW%CHS==:> +NW%ARP==:<12_24.> +NW%LCS==:<22_24.> +NW%AI==:HOSTN 128,52,0,0 + +DEFINE GETNET AC,(ADDR) ; Macro to extract net number +IFNB [ADDR] MOVE AC,ADDR + TLNN AC,(17_32.) ; Check for non-Internet type addrs + TLNN AC,(1_31.) ; Internet address, see if class A net + TDZA AC,[77,,-1] ; Unternet or class A, zap low 3 octets + TLNN AC,(1_30.) ; Class B or C, see which. + TRZA AC,177777 ; Class B network, zap low 2 octets + TRZ AC,377 ; Class C net, only zap 1 low octet +TERMIN + +;;; Misc defs +CALL== +RET== +CALRET== + + OVHMTR NET + +IFN IMPP,[ ; ARPAnet IMP interface code +IFN KAIMP,[ +$INSRT IMPOLD +] +IFN KSIMP,[ +$INSRT IMP +] +] + + OVHMTR NET + +IFN NCPP,[ ; Old Arpanet NCP protocol code +$INSRT NCP +] + OVHMTR NET + +IFN INETP,[ ; Internet Protocol code +$INSRT INET +] + + OVHMTR NET + +IFN TCPP,[ ; Transmission Control Protocol code +$INSRT TCP +] + + OVHMTR UUO + +IFN CHAOSP,[ ; CHAOSnet interface and protocol code +$INSRT CHAOS +] + OVHMTR UUO + +SUBTTL General Network System Calls + +; .CALL NETRFC - Get a pending Request For Connection for a specific network +; Arg 1 - SIXBIT name of network +; Arg 2 - optional network-dependent arg +; (for CHAOS, points to packet buffer) +; Val 1 - network-dependent value +; For TCP and ARPNCP, this is ,, +; Control bits: + %NQREF==:1 ; Arg 2 is previously returned identifier, + ; refuse connection and flush from queue. + +NETRFC: MOVE C,CTLBTS(U) ; Set up control bits in C +IFN TCPP,[ + CAMN A,[SIXBIT /TCP/] + JRST TCPRQ +] +IFN CHAOSP,[ + CAMN A,[SIXBIT /CHAOS/] + JRST [ TRNE C,%NQREF ; If refusing conn, + JRST OPNL12 ; Ignore, can't handle yet. "Mode not avail" + CAIGE W,2 ; Must have a 2nd arg + JRST OPNL30 ; "Too few args" + MOVE A,B ; Fake out old CHAOSQ call + JRST CHAOSQ] +] +IFN NCPP,[ ; NOP for now +; CAMN A,[SIXBIT /ARPNCP/] +; JRST IMPRQ +] + JRST OPNL33 ; No match, say "meaningless args". + +; .CALL NETBLK - Wait for net channel state to change, or time out. +; Arg 1 - Channel (comes in R) +; Arg 2 - Undesired state +; Arg 3 - Optional timeout (as in .SLEEP), written back unless immediate +; Val 1 - New state +; Val 2 - Time left + +NETBLK: HRRZ T,(R) ; Get IOCHNM RH = device index + HLRZ I,(R) ; Get LH = often connection index +IFN NCPP,[ + CAIL T,NETDUI + CAILE T,NETDBO + CAIA + JRST [MOVE T,[HRRZ A,IMSOC4] + JRST NETBLI] +] ;NCPP +IFN CHAOSP,[ + CAIE T,CHAIDN + CAIN T,CHAODN + JRST [MOVE T,[HRRZ A,CHSSTA] + JRST NETBLI] +] ;CHAOSP +IFN TCPP,[ + CAIN T,TCPDUI + JRST [ MOVE T,[HLRZ A,XBSTAU] + JRST NETBLI] + CAIN T,TCPDUO + JRST [ MOVE T,[HRRZ A,XBSTAU] + JRST NETBLI] +] ;TCP + JRST OPNL34 ; Not a net chan, say "Wrong Type Device". + + +; T/ Instruction to XCT (not indexed) to get state in A +; Entry at NETBLI adds (I) to the instruction. + +NETBLI: ADDI T,(I) ; Provide "index" for instruction. +NETBL0: CAIGE W,3 + JRST [ HRLOI D,377777 ; No time given, use infinity + JRST NETBL4 ] + TLNE C,1000 ; Skip if pointer rather than immediate + JRST [ HRRZ D,C ; Get immediate time + ADD D,TIME + JRST NETBL4 ] + XCTR XRW,[MOVES D,(C)] ; Get time, check writeability + JUMPGE D,[ MOVNS D ; Relative time, make negative absolute + SUB D,TIME + JRST .+1 ] + UMOVEM D,(C) ; Store back absolute time + MOVNS D ; Make positive +NETBL4: MOVEM D,AC0S+D(U) ; Save absolute time to wait until + MOVEM B,AC0S+B(U) ; Save undesired state + PUSHJ P,NETBL2 ; Skip if state change or timeout + PUSHJ P,UFLS + MOVE B,D + SUB B,TIME ; How much used? + XCT T ; Return new state + JRST POPJ1 + +NETBL2: XCT T ; Get current state + CAME A,AC0S+B(U) ; Skip if still match + JRST POPJ1 + MOVE A,AC0S+D(U) ; Timeout time + CAMG A,TIME + AOS (P) + POPJ P, + +SUBTTL Utilities - CVTH2A, CVTH3A + + +; CVH2NA - Convert network host address in A to HOSTS2 format. +; A/ net address (any format) +; Returns A + +CVH2NA: PUSH P,B + LDB B,[301400,,A] ; Get high 12 bits of net address + CAIGE B,70 ; If less than lowest HOSTS2-fmt value + JUMPN B,CVH2N3 ; then must be HOSTS3, go convert. + CAIL B,1000 ; If any of high 3 bits set, + JRST CVH2N3 ; then it's a HOSTS3 strange-fmt number. + JUMPN B,CVH2N2 + CAILE A,377 ; Zero network, so must be ARPA net + JRST CVH2N1 ; Not just 8 bits, just add net number. + + ; Old-style 8-bit Arpanet host number + LSHC A,-6. + ROT B,6. + DPB B,[112000,,A] +CVH2N1: TLO A,(12_33) + JRST POPBJ + + ; Probably HOSTS2 format number +CVH2N2: JRST POPBJ ; For now, that's good enough. + + ; HOSTS3 format number, convert it. +CVH2N3: CAIN B,12 ; Arpa net? + JRST [ LSHC A,-16. + ANDI A,377 + ROT B,16. + DPB B,[112000,,A] + TLO A,(12_33) + JRST POPBJ] + CAIN B,7+ ; Chaos net? + JRST [ ANDI A,177777 ; Yup, fix it up. + TLO A,(7_33) + JRST POPBJ] + CAIN B,22 ; LCS net? + JRST [ LSHC A,-8. + ANDI A,-1 + LSH A,2 + LSHC A,8. + TLO A,(22_33) + JRST POPBJ] + + ; Not a known net, but try to do something plausible. + ANDCM A,[-1_24.] ; Preserve low 24 bits + DPB B,[331100,,A] ; put net # into HOSTS2 field. + POP P,B + RET + +; CVH3NA - Convert network host address in A to HOSTS3 (Internet) format. +; A/ net address (any format) +; Returns A + +CVH3NA: PUSH P,B + LDB B,[301400,,A] ; Get high 12 bits of net address + CAIGE B,70 ; If less than lowest HOSTS2 value, + JUMPN B,CVH3N3 ; it's already HOSTS3 format! (unless zero) + CAIL B,1000 ; If any of high 3 bits were set, + JRST CVH3N3 ; it must be a HOSTS3 strange-fmt addr. + JUMPN B,CVH3N2 ; If not zero, then must assume HOSTS2 fmt. + + ; Old-format 8-bit Arpanet host number, or HOSTS2 with zero net. + CAILE A,377 + JRST CVH3N6 ; If greater than 8 bits, assume HOSTS2, zero net. + LSHC A,-6 ; Put 10 bits spacing between host/imp #s. + LSH B,-<2+8.> + LSHC A,<2+8.+6> + TLO A,(12_24.) ; and add ARPA network number. + JRST CVH3N3 + + ; HOSTS2 format number +CVH3N2: TRZE B,7 ; Zap low 3 bits to ensure correct comparison + JRST CVH3N5 ; If any were set, can't be Chaosnet. + CAIN B,7_3 ; Chaos net? + JRST [ ANDI A,177777 ; Yes, kill all but bottom 16 bits + TLO A,(NE%UNT+<7_24.>) ; Add Chaos net # + JRST CVH3N3] +CVH3N5: CAIN B,12_3 ; Arpa net? +CVH3N6: JRST [ LSHC A,-9. + ANDI A,177777 + ROT B,9. + DPB B,[201000,,A] + TLO A,(12_24.) + JRST CVH3N3] + CAIN B,22_3 ; LCS net? + JRST [ LSHC A,-8. + LSH A,-2 + ANDI A,377 + LSHC A,-8. + TLO A,(22_24.) + JRST CVH3N3] + + ; No match, assume it's HOSTS3. + +CVH3N3: POP P,B + RET + +;.CALL STYNET +;ARG 1 - STY CHANNEL +;ARG 2 - NET INPUT CHANNEL TO CONNECT STY OUTPUT TO, OR -1 TO DISCONNECT +;ARG 3 - NET OUTPUT CHANNEL TO CONNECT STY INPUT TO +;ARG 4 - CHARS TO SEND WHEN OUTPUT .RESET HAPPENS ON STY'S TTY +; UP TO 3 8-BIT CHARACTERS, LEFT JUSTIFIED. + +NSTYNT: TLNN R,%CLSST + JRST OPNL34 ;1ST ARG NOT A STY CHANNEL. + HLRZ I,(R) ;GET TTY # OF STY + HRRES B ;ALLOW IMMEDIATE -1 + JUMPGE B,NSTYN2 ;JUMP IF CONNECTING. + PUSHJ P,NSTYN0 ;DISCONNECT + JRST OPNL41 ;WASN'T CONNECTED + JRST POPJ1 + +;VARIOUS ROUTINES CALL HERE WITH THE TTY# OF A STY IN I, TO DISCONNECT THE +; STY FROM THE NETWORK. NOTE THIS ROUTINE MUST NOT CHANGE U AND MUST NOT +; LSWCLR, SINCE IT COULD BE CALLED FROM IODCL VIA STYCLS OR NETCLS. + +NSTYN0: MOVSI B,%SSNET ;DISCONNECTING BOTH SIDES. + CONO PI,NETOFF + TDNN B,STYSTS-NFSTTY(I) + POPJ P, ;THIS STY NOT CONNECTED? + ANDCAB B,STYSTS-NFSTTY(I) ;MARK AS NO LONGER CONNECTED + MOVE C,STYNTL-NFSTTY(I) ;REMOVE THIS STY FROM ACTIVATION LIST + MOVEI D,STYNTA-STYNTL+NFSTTY +NSTYN1: CAMN I,STYNTL-NFSTTY(D) ;FIND THE STY THAT POINTS TO THIS ONE, + MOVEM C,STYNTL-NFSTTY(D) ;AND PATCH US OUT OF THE LIST. + SKIPE D,STYNTL-NFSTTY(D) ;SEARCH WHOLE LIST TILL FIND WHO POINTS TO US. + JRST NSTYN1 + SETOB C,STYNTL-NFSTTY(I) + EXCH C,STYNTI-NFSTTY(I) ;MARK THIS STY AS HAVING NO CONNECTION, GET SOCKET INDICES +IFN CHAOSP,[ + TLNE B,%SSCHA + JRST [ MOVSI B,%SSCHA ;DISCONNECT FROM CHAOS NET + ANDCAM B,STYSTS-NFSTTY(I) + MOVSI B,%CFSTY + TDNN B,CHSSTA(C) + JRST 4,. ;CHAOS DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,CHSSTA(C) + JRST NETOJ1 ] +];CHAOSP +IFN TCPP,[ + TLNE B,%SSTCP + JRST [ MOVSI B,%SSTCP ; Disconnect from TCP connection + ANDCAM B,STYSTS-NFSTTY(I) ; Flush STY's "connect" bit + MOVSI B,(XB%STY) + TDNN B,XBUSER(C) ; Make sure TCP thinks connected + BUG ; It isn't?? + ANDCAM B,XBUSER(C) + JRST NETOJ1] +] ;TCPP +IFN NCPP,[ + MOVE B,[40000,,777] + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) ;AND MARK SOCKETS WE WERE CONNECTED TO AS DISCONNECTED + MOVSS C + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) + JRST NETOJ1 +] ;NCPP +.ELSE BUG + +; Here to set up STY connection. + +NSTYN2: MOVE Q,I ;SAVE TTY # OF STY + MOVEI E,1 + MOVE A,B ;DECODE THE NETWORK INPUT CHANNEL + JSP T,CHNDCD + HRRZ A,(R) +IFN CHAOSP,[ + CAIE A,CHAIDN + CAIN A,CHAODN + JRST [ HLRZ I,(R) ;CONNECT TO CHAOS NET + CONO PI,NETOFF + MOVSI B,%CFSTY + TDNE B,CHSSTA(I) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + MOVSI C,%SSNET+%SSCHA + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + IORM B,CHSSTA(I) ;OK, HOOK UP + DPB Q,[$CFTTN,,CHSSTA(I)] + JRST NSTYN3 ] +];CHAOSP +IFN TCPP,[ + CAIE A,TCPDUI + CAIN A,TCPDUO + JRST [HLRZ I,(R) ; Connect to TCP, get TCB index + CONO PI,NETOFF + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) + JRST OPNL23 ; TCB Already connected, say "File Locked" + MOVSI C,%SSNET+%SSTCP + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ; STY already connected, say "File Locked" + DPB Q,[XB$STY (I)] ; Store TTY # to connect TCB. + JRST NSTYN3] +] ;TCPP +IFN NCPP,[ + JSP T,NETCHK ;TEST LEGALITY; OPNL IF LOSES + TDNE E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF IT'S AN OUTPUT CHANNEL + MOVE B,I ;SAVE INPUT IMSOC INDEX + MOVE A,C ;DECODE OUTPUT CHANNEL + JSP T,CHNDCD + JSP T,NETCHK + TDNN E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF INPUT SOCKET + CONO PI,NETOFF + MOVE E,[40000,,777] + TDNN E,IMSOC5(B) ;ERROR IF EITHER CHANNEL ALREADY CONNECTED + TDNE E,IMSOC5(I) + JRST OPNL23 ;"FILE LOCKED" + MOVSI C,%SSNET + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;SIMILAR ERROR IF STY ALREADY CONNECTED + HRR E,Q ;GET 40000,,TTY # + IORM E,IMSOC5(I) + IORM E,IMSOC5(B) ;MARK SOCKETS AS CONNECTED +] ;NCPP + +NSTYN3: SKIPGE STYNTL-NFSTTY(Q) ;HALT IF STY'S VARS ARE NOT CORRECT FOR A + SKIPL STYNTI-NFSTTY(Q) ;NON-CONNECTED STY. + JRST 4,. + IORM C,STYSTS-NFSTTY(Q) ;ALL ERROR CAUGHT, SO MARK STY CONNECTED. + HRL B,I ;PUT INPUT IMSOC IDX,, OUTPUT IMSOC IDX + MOVSM B,STYNTI-NFSTTY(Q) ;INTO THE STY + TRZ D,7777 ;STORE THE OUTPUT RESET CHARACTERS - AT MOST 3 + MOVEM D,STYORC-NFSTTY(Q) + + ;ACTIVATE IN CASE HAS UNREAD INPUT +IFN NCPP,[ + TLNN C,%SSCHA+%SSTCP + PUSHJ P,IMPUIN +] ;NCPP +IFN CHAOSP,[ + TLNE C,%SSCHA + PUSHJ P,CHINTI +];CHAOSP +IFN TCPP,[ + TLNE C,%SSTCP + PUSHJ P,TCPUII +] ;TCPP + JRST NETOJ1 + +SUBTTL Clock interrupt level code + +; NETCLK - Slow net clock. Called at clock level every 1/2 sec. +; Can clobber all ACs + +NETCLK: +IFN CHAOSP, PUSHJ P,CHACLK ; Run Chaos net 1/2-second clock +IFN TCPP, PUSHJ P,TCPCLK ; Run TCP 1/2-sec clock + SETCMB A,NETCL1 ; Flip the 1 sec switch + JUMPE A,CPOPJ ; Return unless time for 1-sec clock +IFN INETP,CALL IPFCLK ; Run IP reassembly timeout every 1 sec + RET +EBLK +NETCL1: 0 ; Flip-flop to get 1-sec ticks +BBLK + +; STYNTC - Called at clock level every 1/60 sec to process all +; necessary transfers of data between STYs and associated +; net connections + +STYNTC: CONO PI,NETOFF + SKIPN I,STYNTA ;GET HEAD OF ACTIVATE LIST + JRST NETONJ ;EMPTY + SETZM STYNTA ;COPY LIST IN CASE A STY IS PUT BACK ON + CONO PI,NETON +STYNT7: MOVE A,STYNTL-NFSTTY(I) ;GET NEXT ON LIST + MOVEM A,STYNTB ;SAVE FOR NEXT TIME AROUND LOOP + SETOM STYNTL-NFSTTY(I) ;THIS ONE IS NO LONGER ON ACTIVATE LIST + MOVE A,STYSTS-NFSTTY(I) + TLNN A,%SSNET + JRST 4,. ;STY CLAIMS NOT TO BE CONNECTED?? + MOVE R,I ;SAVE TTY # + +IFN CHAOSP,[ + TLNE A,%SSCHA + JRST STYCHA ;CONNECTED TO CHAOS NET +];CHAOSP +IFN TCPP,[ + TLNE A,%SSTCP + JRST STYTCP +] ;TCPP +IFN NCPP,[ + JRST STYNCP +];NCPP + +STYNT8: SKIPE I,STYNTB ;GET NEXT STY FROM COPIED ACTIVATION LIST + JRST STYNT7 + POPJ P, + +;SUBROUTINE TO STANDARDIZE HOST NUMBER, OPNL25 IF NO GOOD +;PROCESSES HOST NUMBER IN T, MUNGS H, CALLED BY JSP J,STDHST +STDHST: +IFN 1,[ + EXCH A,T + CALL CVH3NA ; Convert # to HOSTS3 fmt + EXCH A,T + LDB H,[301400,,T] ; Get high 12 bits (net #) + CAIE H,12 ; Should be ARPA net + JRST OPNL25 + TDZ T,[NW%ARP+<377_8.>] ; Flush the net # and logical host field + JRST (J) +] ;IFN 1 +IFN 0,[ + LDB H,[331000,,T] ;GET NETWORK-NUMBER FIELD + CAIE H,12 ;ONLY 12 OR 0 IS ACCEPTABLE + JUMPN H,OPNL25 + TDNE T,[400600,,400] ;MAKE SURE OTHER RANDOM BITS AREN'T ON + JRST OPNL25 + TLZ T,777000 ;CLEAR NETWORK NUMBER + JUMPE T,OPNL25 ;0 IS NOT ACCEPTABLE + CAIL T,400 ;SKIP IF OLD-STYLE HOST NUMBER + JRST (J) + LDB H,[060200,,T] ;GET HOST FIELD + ANDI T,77 ;GET IMP FIELD + EXCH H,T + DPB H,[112000,,T] ;RECOMBINE + JRST (J) +] ;IFN 0 diff --git a/src/system/ni1010.defs2 b/src/system/ni1010.defs2 new file mode 100755 index 00000000..8ecde7eb --- /dev/null +++ b/src/system/ni1010.defs2 @@ -0,0 +1,98 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Junk for Interlan NI1010A Unibus Ethernet Interface + +;Interrupt information +DEFSYM %ILVEC==300 ;Input side interrupt vector (non-standard) + ;Output side assumed to be %LHVEC+4 +DEFSYM %ILPRI==5 ;Interrupt priority (should be 6, but + ; hard to change to anything but 4!) + +DEFSYM %ILBAS==764000 ;Base of NI1010A Registers in UB space + +;Unibus Registers +DEFSYM %ILCSR=:%ILBAS ;Control and Status Register +DEFSYM %ILBAR=:%ILBAS+2 ;Buffer Address Register +DEFSYM %ILBCR=:%ILBAS+4 ;Byte COunt Register + +;Bitz +;CSR bits +DEFSYM %ILEUA==:140000 ;Extended UB address field +DEFSYM %ILCMD==:37400 ;Command Function Code +DEFSYM %ILCD==:200 ;Command Done +DEFSYM %ILCIE==:100 ;Command Interrupt Enable +DEFSYM %ILRD==:40 ;Receive DMA done +DEFSYM %ILRIE==:20 ;Receive Interrupt Enable +DEFSYM %ILSTS==:17 ;Command Status Code + +;Commands (in %ILCMD field of CSR) +DEFSYM %ILSML==400 ;Module Loopback (through interface) +DEFSYM %ILSIL==1000 ;Set Internal Loopback +DEFSYM %ILCLM==1400 ;Clear loopback mode +DEFSYM %ILSPR==2000 ;Promiscuous Receive Mode +DEFSYM %ILCPR==2400 ;Clear Promiscuous Receive Mode +DEFSYM %ILSRE==3000 ;Set Receive-on-error bit +DEFSYM %ILCRE==3400 ;Clear Receive-on-error bit +DEFSYM %ILOFL==4000 ;Go Offline +DEFSYM %ILONL==4400 ;Go Online +DEFSYM %ILROD==5000 ;Run onboard diagnostics +DEFSYM %ILSIS==6000 ;Set Insert-source-address mode +DEFSYM %ILCIS==7000 ;Clear Insert-source-address mode +DEFSYM %ILDPA==7400 ;Set physical address to default +DEFSYM %ILSRM==10000 ;Receive all multicast packets +DEFSYM %ILCRM==10400 ;Clear Receive all multicast packets +DEFSYM %ILRRS==14000 ;Report and reset statistics +DEFSYM %ILRCD==14400 ;Report Collision Delay Times +DEFSYM %ILRCV==20000 ;Supply Receive Buffer +DEFSYM %ILLXD==24000 ;Load Transmit Data +DEFSYM %ILLXS==24400 ;Load Transmit Data and Send +DEFSYM %ILLGA==25000 ;Load Group Addreses +DEFSYM %ILDGA==25400 ;Delete Group Adresses +DEFSYM %ILLPA==26000 +DEFSYM %ILFRQ==30000 ;Flush Receive BAR/BCR Queue +DEFSYM %ILRST==37400 ;Reset + +;Error codes. Found in %ILSTS field of CSR +DEFSYM %ILEOK==0 ;Success +DEFSYM %ILERT==1 ;Success, with retries +DEFSYM %ILEBC==2 ;Illegal Command +DEFSYM %ILEIC==3 ;Invalid Command +DEFSYM %ILERE==4 ;Receiver Error +DEFSYM %ILEBB==5 ;Buffer Size Too Big +DEFSYM %ILEFS==6 ;Frams Size Too Small +DEFSYM %ILEEC==10 ;Excessive Collisions +DEFSYM %ILEBA==12 ;Buffer Not Word Aligned +DEFSYM %ILENX==17 ;Non-eXistant Memory + +;Diagnostic codes. Results from %ILROD command +DEFSYM %ILDOK==0 ;No Problem +DEFSYM %ILDCE==1 ;ROM/RAM Checksum Error +DEFSYM %ILDDE==2 ;DMA Circuitry Failed +DEFSYM %ILDXE==3 ;Transmit Circuitry Failed +DEFSYM %ILDRE==4 ;Receive Circuitry Failed +DEFSYM %ILDLE==5 ;Loopback checks failed + +;Frame status bits, returned in frame status byte +; at the top of each received packet. +DEFSYM %ILFCE==1 ;CRC Error in packet +DEFSYM %ILFAE==2 ;Alignment Error +DEFSYM %ILFFL==4 ;1+ frames lost just before + +IFN $$TEMP,EXPUNG DEFSYM + \ No newline at end of file diff --git a/src/system/nmtape.30 b/src/system/nmtape.30 new file mode 100755 index 00000000..7011a974 --- /dev/null +++ b/src/system/nmtape.30 @@ -0,0 +1,2432 @@ +;******************************** +;** +;** TO BE DONE: +;** +;** RECORDS LONGER THAN 1K +;** AUTOMATIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING +;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF +;** BE MORE FORGIVING OF CONTROLLER LOSSAGE +;** PASS .MTAPE TO JOB DEVICE +;** HAVE AN IGNORE ERRORS SWITCH +;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED +;** +;******************************** + +;Do not be deceived by the TM10 conditionals. This file is only good +; for a TM03/RH11 on a KS10. See MTAPE for anything else. Barf. + +IFE TM10A+TM10B+TM03S,.ERR NO MAGTAPE CONTROLLER TYPE SELECTED +IFN TM10A,INFORM IO BUSS MAG TAPE,1 +IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1 +IFN TM03S,INFORM RH11/TM03 MAG TAPE,1 + +IFN TM10P,[ +$INSRT TM10 +] +IFN TM03S,[ +$INSRT TM03S +] +$INSRT T20MAC + +MSCBL==8 ;Command buffer length +MGQDLL==10. ;PI level PDL length +IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB +MSEOFP==210100 ;High bit of MNUMB in MEMBLT is EOF flag +MSCHN==140500 ;Other 5 bits of MNUMB is drive number + +MTXP==410300,, ;BP to set/get transport number from IOCHNM +MUNITF==170300 ;BP to set/get unit field in MTC CONI + +IFN TM10P,[ +;Tape controller commands +MNOPIN==10000 ;NOP and interrupt when idle +MWRITE==4000 ;Write data +MW3IN==14000 ;Write data and long EOR gap +MSPRR==7000 ;Space in reverse direction +MREAD==2000 ;Read data +MSPFR==6000 ;Space in forward direction +MSPFF==16000 ;Space forward to EOF +MSPRF==17000 ;Space reverse to EOF +MREWND==1000 ;Rewind +MRWNDD==11000 ;Rewind and unload +MWEOF==5000 ;Write EOF mark +] + +MGNRTY==10. ;Number of retries on read + +;Modes in OPEN call +; +%MMOUT==1,,0 ;Open for output, 0=>input +%MMBLK==2,,0 ;Block mode, 0=>unit mode +%MMIMG==4,,0 ;Image mode, 0=>Ascii +%MMCNK==10,,0 ;"Chunk" mode, 0=>stream mode +%MMNSE==20,,0 ;No skip to EOF on close, 0=>do skip +%MMEP==40,,0 ;Even parity, 0=>odd +%MMDEN==300,,0 ;Density select + ; 00=> "Default" - 1600 for KS/TU77 + ; 01=> 800 BPI + ; 10=> 1600 BPI + ; 11=> 6250 BPI +%MM32B==400,,0 ;"IBM" mode, write 8-bit bytes from LH 32 bits + ; 0=> core dump +%MMRSZ==7000,,0 ;Record Size + ; Ranging binarily from 0=>1024. to 7=>8. bytes + + +EBLK + +SUBTTL MAG TAPE STORAGE AREA + +MGVTC: 0 ;Scratch word for virgin tape check +MGJDTI: 0 ;"Wait for job done" time out value +MGNWRD: 0 ;Number of words read in a PI level read +MGTBZY: -1 ;Flag to get interrupt started +MGSFTI: 0 ;Software interrupt in progress +MGUNIT: -1 ;Unit expecting interrupt +MGWCW: 0 ;"Wait for control word written" flag +LMIOWD: 0 ;Last MIOWD + +MSRAC: BLOCK NMTCS ;Transport software status flags + %MA==1,,525252 + %MAEOF==400000 ;4.9 EOF seen on read - must be 4.9 + %MAETR==200000 ;4.8 EOT on internal read + %MAETW==100000 ;4.7 EOT on write + %MAERR==040000 ;4.6 PI level got an error + %MARCE==020000 ;4.5 Read compare error + %MACTH==014000 ;4.4 Core allocator says stop + ;4.3 " (WHY 2 BITS?) + %MASTP==002000 ;4.2 Stop read ahead + %MANWT==001000 ;4.1 Nothing written on tape yet + %MAEFA==000400 ;3.9 EOF seen on read-ahead, user hasn't seen + %MAESO==000200 ;3.8 EOF read since open + %MAMSO==000100 ;3.7 Tape moved since first open + %MAREW==000040 ;3.6 "Tape is rewinding" flag + %MARAC==000020 ;3.5 Read active flag + %MAMOL==000010 ;3.4 Transport on line + %MAWSW==000004 ;3.3 Wants software (timing) interrupts +MGERRC: BLOCK NMTCS ;Error count +MTCEFW: BLOCK NMTCS ;Number of EOF's written at close +MGEOFR: BLOCK NMTCS ;Number of EOF's since last read +MTPSAV: BLOCK NMTCS ;Storage to restore P on EOF +MSCMDC: REPEAT NMTCS,0 ;Number of commands in command list +MGSPCD: BLOCK NMTCS ;Spacing operation command +MGSCNT: BLOCK NMTCS ;Spacing operation count +MGEOTT: BLOCK NMTCS ;Timeout for detecting virgin tape +MSBUFP: REPEAT NMTCS,0 ;Mag tape MP<->PI buffer queue in,,out +MSNBOL: BLOCK NMTCS ;Number of buffers on list +MSCRW: BLOCK NMTCS ;R/W flag, -1=>output 0=>input +MSMPRC: BLOCK NMTCS ;Words left in buffer +MSMPRP: BLOCK NMTCS ;Next word in buffer +MTMDN: REPEAT NMTCS,-1 ;Block active at MP +MGCABN: REPEAT NMTCS,-1 ;Buffer active at PI level +MTUSE: REPEAT NMTCS,-1 ;Number of channels open on this transport +MTUSR: REPEAT NMTCS,-1 ;User index of transport user +MTBLKS: BLOCK NMTCS ;If write, buffer size + ;If read, size of last record read +MTMFNC: BLOCK NMTCS ;.MTAPE function storage +MTMCNT: BLOCK NMTCS ;.MTAPE count +MTMTAP: BLOCK NMTCS ;MTAPE call word + +MGCMTS: BLOCK NMTCS ;PI level status info (CONI MTS or similar) +MGCMTC: BLOCK NMTCS ;PI level controller info (CONI MTC or similar) + + IFN TM10P,[ +MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ;Prototype CONO word for each transport + ] + IFN TM03S,[ +MTSELW: BLOCK NMTCS ;Select word (TC reg val) for each transport + MTSELM==3777 ;density/format/parity/unit bits mask +MTWTFC: BLOCK NMTCS ;-10 word count to tape frame conversion factor + ] + +;Build table of QDL (PI level stack) pointers +MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1 + +;Built storage for command lists and PI level stacks +REPEAT NMTCS,[ + CONC MSCB,\.RPCNT,: + BLOCK MSCBL ;Space for command list + MGRCV ;Fake "command", causes list to wrap around + + MGNCMD ;Function on botton of Q PDL, gets new command + CONC MGQD,\.RPCNT,: + BLOCK MGQDLL ;Space for PI level stack + + IFE .RPCNT,MSLCTB==.-MSCB0 ;Length of each table +] + +;Build table of pointers for adding commands to command list +MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1 + +;Build table of bytepointers for removing commands from command list +MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1 + +;It is depressing to discover that the DUMP program sucks these directly +; out of the running ITS. If you change what's in here fix DUMP too. + +MGEMTC: 0 ;CONI MTC, at last error +MGEMTS: 0 ;CONI MTS, at last error + +IFE TM10B,[ +MIOWD: BLOCK 2 ;Channel program +] +IFN TM10A,[ +MGDBRK: 0 + CONO MTS,1 + JRST 12,@MGDBRK +];TM10A + +BBLK + + +;Random Macros + +;Enqueue and Dequeue buffers from the lists used to pass buffers between +; main program and PI level. Assumes W has a valid transport number... + +DEFINE MTENQB REG,TEMP=TT + SKIPG MSNBOL(W) ;;Any buffers on list already? + IFSKP. + HLRZ TEMP,MSBUFP(W) ;;Yes, get old tail pointer + DPB REG,[MLO,,MEMBLT(TEMP)] ;;Add new one onto end of list + ELSE. + HRRM REG,MSBUFP(W) ;;No, make new buffer head of list + ENDIF. + HRLM REG,MSBUFP(W) ;;New buffer is tail in any event + SETZM TEMP + DPB TEMP,[MLO,,MEMBLT(REG)] ;;Indicate end of list + AOS MSNBOL(W) ;;Increment count of buffers on list +TERMIN + +DEFINE MTDEQB REG,TEMP=TT + HRRZ REG,MSBUFP(W) ;;Get head of buffer list + HLRZ TEMP,MSBUFP(W) ;;Get tail + CAMN REG,TEMP ;;Tail == head? + IFSKP. + LDB TEMP,[MLO,,MEMBLT(REG)] ;;No, get next buffer on list + HRRM TEMP,MSBUFP(W) ;;Make it the new head of list + ELSE. + SETZM MSBUFP(W) ;;Only one buffer, list is now empty + ENDIF. + SOS MSNBOL(W) ;;Decrement count of buffers on list +TERMIN + +IFN TM03S,[ +;Macros for testing various status bits as set up by MGGXPT and friends +IRP OP,,[NN,NE,NA,O,OE,ON,OA,Z,ZE,ZN,ZA,C,CE,CN,CA] + DEFINE TT!OP REG,#MSK + ...TSF==0 + IFSE REG,CS1,[ + TL!OP I,MSK + ...TSF==-1 + ] + IFSE REG,CS2,[ + TR!OP I,MSK + ...TSF==-1 + ] + IFSE REG,FS,[ + TL!OP J,MSK + ...TSF==-1 + ] + IFSE REG,ERR,[ + TR!OP J,MSK + ...TSF==-1 + ] + IFE ...TSF,.ERR Invalid register name REG given in TTxxx macro + TERMIN +TERMIN +];IFN TM03S + SUBTTL MAG TAPE OPEN ROUTINE + +; C/ MODE,,DEV +; D/ MODE (ROT 1) 4.9=1=>OUTPUT +; I/ DEVICE NUMBER +; R/ IOCHNM WORD POINTER + +MAGTO: SKIPL W,I ;Get device + CAIL W,NMTCS ;Too big? + JRST OPNL1 ;No such device + MOVSI T,%MAREW + TDNE T,MSRAC(W) ;Rewinding? + PUSHJ P,UFLS ;Yes, wait for completion + CONO PI,CLKOFF ;Don't want transport status changed under me + SKIPL MTUSE(W) ;See if we are the first opener + IFSKP. ;First opener. Initialize database for device + SETZM MSBUFP(W) ;Indicate no buffers on chain + SETZM MSNBOL(W) ;Another way of saying above + SETZM MSMPRC(W) ;Buffer words remaining + SETZM MSMPRP(W) ;Pointer to buffers + SETOM MTMDN(W) ;No buffer at MP level + SETOM MGCABN(W) ;No buffer owned by PI code + SETZM MSRAC(W) ;Initialize transport software status word + MOVEI A,2 + MOVEM A,MTCEFW(W) ;Number of EOF's written + MOVSI A,%MANWT + IORM A,MSRAC(W) ;Indicate nothing written on tape + ELSE. ;Not first opener. Check legality of this open + CAME U,MTUSR(W) ;Same user as previous open? + JRST OPNL10 ;Different user, report error + MOVE B,D ;Check direction of open + EQV B,MSCRW(W) ;Same as previous direction? + SKIPL B ;Yes, OK + JRST OPNL2 ;No, wrong direction + ENDIF. + MOVEM U,MTUSR(W) ;Store user + SETZM MSCRW(W) ;Indicate read until found to be otherwise + TLNE C,1 ;Read or write? + SETOM MSCRW(W) ;Indicate write + AOS MTUSE(W) ;Indicate 1 more user + PUSHJ P,SOSSET + MTUSE(W) ;SOS if PCLSR'd + CONO PI,CLKON ;Let um (em?) get me (who's em?) + PUSHJ P,MTSTAT ;Get transport status in standard form + MOVE A,MSRAC(W) + TLNE A,%MAERR ;PI error means device not there + JRST MTODNP ;Go report error +IFN TM03S,[ + TTNN FS,%TMSFP ;Formatter present? + JRST MTODNP ;No, can't win + TTNN FS,%TMSOL ;Slave on line? + JRST MTODOL ;No, lose +] +IFN TM10P,[ + TXNN J,%T1STH ;Transport hung, by chance? + JRST MTOW1 ;No, proceed + TXNN J,%T1SRW ;OK if rewinding + JRST OPNL7 ;Device not working +] +MTOW1: SKIPN MSCRW(W) ;Writing? + JRST MTOW2 ;No... +IFN TM10P,TXNE J,%T1SWL ;Yes. Write locked? +IFN TM03S,TTNE FS,%TMSWL + JRST OPNL26 ;Yes, device writelocked error +IFN TM10P, TXNN J,%T1SET ;At EOT? +IFN TM03S, TTNN FS,%TMSET + JRST MTOW2 ;No + MOVSI A,%MAETW+%MAERR ;If write and EOT, make .IOT give IOC error, + ; but let open win + IORM A,MSRAC(W) + +MTOW2: TXNE C,%MMDEN ;Density specified explicitly? + JRST MTOW3 ;Yes, go check for validity +IFN TM10P,MOVEI A,1 ;No, pick one. Use 800 for TM10 +IFN TM03S,MOVEI A,2 ;Use 1600 for TM03 + DPB A,[.BP %MMDEN,C] ;Set value + JRST MTOW4 ;Done and assumed correct + +MTOW3: LDB A,[.BP %MMDEN,C] ;Get density from open +IFN TM10P,[ + CAIE A,1 ;800 is the only currently OK speed for TM10 + JRST OPNL12 + IFN 0,[ +;You need something like this if you arrange to allow non-800 TM10 speeds + TXNN C,%MM32B ;32-bit compatible mode requested? + JRST MTOW4 ;No, core dump + CAIN A,1 ;Density specified as 800? + JRST MTOW4 ;Yes, we can do that + JRST OPNL12 ;32-bit and not 800BPI, controller can't do it + ] +];IFN TM10P +IFN TM03S,[ + CAIN A,3 ;Specified 6250? + JRST OPNL12 ;Yep, loser. Else OK +] + +;Here on successful open. +; Set up CONO or select word, IOCHNM word, blocksize +; +MTOW4: PUSHJ P,LSWDEL ;Release MTUSE switch +IFN TM10P,[ + MOVEI A,MTCCHN_3 ;Start building CONO word. Set control PI level +IFN TM10A,TRO A,1 ;Add in data PI level for non-DF10 controller + LDB B,[.BP %MMDEN,C] ;Get density from open + CAIE B,1 ;800 BPI + BUG INFO,[ILLEGAL TM10 TAPE SPEED SETTING, USING 800BPI] + MOVEI B,%T1D80 ; Yep. + DPB B,[.BP %T1CDS,A] ;Set density field of CONO word + TXNN C,%MM32B ;32-bit mode specified? + TXO A,%T1CCD ;No, set core dump mode in CONO + TXNN C,%MMEP ;User wants even parity? + TXO A,%T1COP ;No, set odd parity + DPB W,[.BP %T1CNU,A] ;Set unit number field of CONO + MOVEM A,MTCONO(W) ;Save assembled CONO word +];IFN TM10P +IFN TM03S,[ + MOVE A,W ;Get unit number being initialized + TXNN C,%MM32B ;User asked for industry compatible? + IFSKP. ;Yes... + MOVEI B,4 ;Set word-to-frame conversion factor + MOVEM B,MTWTFC(W) + MOVEI B,%TMFIC ;Set mode in budding select word + ELSE. ;Core dump... + MOVEI B,5 ; takes 5 tape frames per word + MOVEM B,MTWTFC + MOVEI B,%TMFCD ;Set CD format in select word + ENDIF. + DPB B,[.BP %TMTFS,A] ;Set format in select word + TXNE C,%MMEP ;User wants even parity? + TXO A,%TMTEP ;Yes, set even parity flag + LDB B,[.BP %MMDEN,C] ;Get density from open + CAIE B,1 ;800 BPI specified? + SKIPA B,[%TMD16] ;Anything else, use 16 + MOVEI B,%TMD08 ;800, use that + DPB B,[.BP %TMTDS,A] ;Set density in select word + MOVEM A,MTSELW(W) ;Set select word for this unit +];IFN TM03S + LDB B,[.BP %MMRSZ,C] ;Get record size from open call + TRC B,7 ;Convert to power of two + MOVEI A,10 ;Minimum record size is 10 (8.) words + LSH A,(B) ;Blocksize = minimum * 2^power + MOVEM A,MTBLKS(W) ;Save blocksize in words + LDB A,[.BP <%MMBLK\%MMIMG>,C] + ;Use unit/block and ascii/image bits as index + HLR C,MTOPTB(A) ;Get input dispatch routine from table + TLNE D,400000 ;Remember D? Skip if user opened in input mode + HRR C,MTOPTB(A) ;OK, get output dispatch routine instead + MOVEM C,(R) ;Save routine in IOCHNM word + DPB W,[MTXP(R)] ;Set transport number in IOCHNM word + JRST POPJ1 ;Skip return means success + +;Here if device is not present +MTODNP: SETZM MSRAC(W) ;Too bad. Clear status word and report error + JRST OPNL1 + +;Here if device off line +MTODOL: SETZM MSRAC(W) + JRST OPNL7 + +;Table of I/O routines +; +MTOPTB: MTUAIX,,MTUAOX ;Unit Ascii + MTBIX,,MTBOX ;Block Ascii + MTUIIX,,MTUIOX ;Unit Image + MTBIX,,MTBOX ;Block Image + + + +SUBTTL MAG TAPE CLOSE ROUTINES + +;MTOCL - CLOSE TAPE OPEN FOR OUTPUT + +MTOCL: LDB W,[MTXP(R)] ;Set up transport number + SOSL MTUSE(W) ;Decrement transport use counter + POPJ P, ;Not only channel open, all done + AOS MTUSE(W) ;Consistant state in case PCLSR'd + MOVSI A,%MAERR + TDNE A,MSRAC(W) ;See if error has occurred + PUSHJ P,MTOCL3 ;Yes, clean up a few things + + SKIPL MTMDN(W) ;Is there a partially processed buffer? + PUSHJ P,MTWBFD ;Yes, write it to tape + + MOVEI B,MGMEOT ;Queue a "Write EOT" command to PI level + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) + PUSHJ P,UFLS ;Wait till done. + MOVEI A,1 + MOVEM A,MGEOFR(W) + SKIPGE MTMDN(W) ;Active buffer at MP level? + IFSKP. + MOVE A,MTMDN(W) + BUG PAUSE,[MT: MP BUF REMAINS AT CLOSE],OCT,A + PUSHJ P,MEMR + ENDIF. + SKIPGE MGCABN(W) ;Active buffer at PI level? + IFSKP. + MOVE A,MGCABN(W) + BUG PAUSE,[MT: PI BUF REMAINS AT CLOSE],OCT,A + PUSHJ P,MEMR + ENDIF. + SKIPN MSNBOL(W) ;Any buffers on buffer queue? + IFSKP. + BUG PAUSE,[MT:],DEC,MSNBOL(W),[BFRS QUEUED AT CLOSE] + PUSHJ P,MTCBFF + ENDIF. + SETOM MTUSE(W) ;Nobody is using this transport + SETOM MTUSR(W) ;No user associated with this transport + SETZM MSRAC(W) ;reset transport software status word + POPJ P, + +MTOCL3: SKIPL A,MTMDN(W) ;Have a buffer active at MP level? + PUSHJ P,MEMR ;Flush it if so + SETOM MTMDN(W) + SETZM MSMPRC(W) ;Say no words left in current buffer + POPJ P, + +;Close routine for MT open for input + +MTICL: LDB W,[MTXP(R)] ;Set up channel data pointer + SOSL MTUSE(W) ;Last user? + POPJ P, ;No, nothing to do + AOS MTUSE(W) ;Yes, save state for possible PCLSR + MOVEI T,1 ;This crock is because we want to allow + CAMGE T,MSCMDC(W) ; one outstanding command if rewinding + PUSHJ P,UFLS ;Wait till one or less outstanding command + MOVE T,MSRAC(W) ;Get transport software status + TLNE T,%MAREW ;Is it rewinding? + IFSKP. + SKIPLE MSCMDC(W) ;No, wait till no outstanding commands + PUSHJ P,UFLS + ENDIF. + SKIPGE MGCABN(W) ;Any PI-level buffers left? + IFSKP. + MOVE A,MGCABN(W) + BUG PAUSE,[MT: PI INPUT BUF LEFT AT CLOSE],OCT,A + PUSHJ P, MEMR + ENDIF. + PUSHJ P,MTRBD ;Release any MP-level buffers + SETOM MTUSR(W) ;Reset user identifier + PUSHJ P,MTCBFF ;Free some buffers ?whose+++ + SOS MTUSE(W) ;Decrement use count + MOVE T,MSRAC(W) ;Get transport software status again + TLNE T,%MAREW ;Are we rewinding? + JRST MTICL2 ;Yes, don't have to skip to EOF + MOVSI A,(%MMNSE) + TDNE A,(R) ;Check if user wants skip to EOF + JRST MTICL2 ;No, forget it + MOVSI A,%MAMSO + TDNN A,MSRAC(W) ;Has tape moved at all since open? + JRST MTICL2 ;No... + SKIPE MGEOFR(W) ; + JRST MTICL2 ;Note that this disposes of a read-ahead EOF. + PUSHJ P,MTSTAT +IFN TM10P,[ + MOVE B,MGCMTS(W) + TXNE B,%T1SBT ;BOT? + JRST MTICL2 +] +IFN TM03S,[ + TTNN FS,%TMSOL ;Still online? + JRST MTICL2 ;No, can't very well skip to EOF + TTNE FS,%TMSBT + JRST MTICL2 +] + MOVEI B,MGSPFF ;Space forward to end of file + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) ;Wait till command done + PUSHJ P,UFLS + +MTICL2: MOVSI T,%MAREW + ANDM T,MSRAC(W) ;Clear all software status except rewinding + POPJ P, ;Done + +;Free a chain of IO buffers pointed to by MSBUFP(W) +; Count of buffers is in MSNBOL(W) +; +MTCBFF: SKIPN MSNBOL(W) ;Any buffers on chain? + POPJ P, ;No, fine + DO. + HRRZ A,MSBUFP(W) ;Yes, get pointer + LDB T,[MLO,,MEMBLT(A)] ;Get pointer to next buffer + HRRM T,MSBUFP(W) ;Write that in chain header + PUSHJ P,MEMR ;Return buffer to IO pool + SOSLE MSNBOL(W) ;Any more to do? + JRST TOP. ;Yes, loop back for more + ENDDO. + SETZM MSBUFP(W) ;Zero buffer list pointer + POPJ P, + + + +SUBTTL MAG TAPE INPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAI: MOVEI B,CHRKTI ;Unit ASCII input + MOVE E,[440700,,5] + JRST MTREAD + + SKIPA B,[SIOKT] +MTUII: MOVEI B,CHRKTI ;Unit image input + MOVE E,[444400,,1] + JRST MTREAD + +MTBI: MOVE E,[444400,,1] ;Block input + MOVEI B,BLKT + +MTREAD: LDB W,[MTXP(R)] ;W <= Transport number + PUSHJ P,MTIECK ;Check for tape errors first + MOVEM P,MTPSAV(W) ;Save P for EOF return + JSP B,(B) ;IO Routine. BLKT,CHRKT,SIOKT + MSMPRP(W) ;Pointer to next word + MSMPRC(W) ;Count of words remaining + SETZ MTRBG ;Get new buffer (SETZ for CHRKT return on EOF) + MTRBD ;Discard buffer + JRST 4,. ;Unused + PUSHJ P,MTRBFW ;Code to wait for new buffer from PI level + +;Get a new buffer for I/O code. +; This routine assumes that there is a buffer ready to get +; (i.e. MTRBFW was called) +; +MTRBG: SKIPG MSNBOL(W) ;Any buffers on list? + JRST MTRBG3 ;No, must be error or EOF + CONO PI,UTCOFF ;Stop I/O for a bit + MTDEQB TT,A ;Dequeue buffer into TT using A as temp + MOVEM TT,MTMDN(W) ;Remember buffer active at MP level + CONO PI,UTCON ;Turn I/O back on + LDB J,[MWC,,MEMBLT(TT)] ;Get word count from buffer + MOVEM J,MTBLKS(W) ;Save for .MTAPE 13 + LSH TT,10. ;Convert buffer number into address + JRST SIOBGX ;TT/address, J/word count /E unchanged + +;Here if no buffer ready, error or EOF assumed +; +MTRBG3: SKIPL MSRAC(W) .SEE %MAEOF ;EOF flag set in transport status? + IFSKP. + MOVSI T,%MAEFA ;The EOF is now no longer read-ahead + ANDCAM T,MSRAC(W) ;So remember that fact + JRST POPJ2 ;Double skip to tell I/O code about EOF + ENDIF. + PUSHJ P,MTIECK ;Not EOF. Check for error conditions + BUG HALT,[TAPE READ BUFFER VANISHED] ;No error, shoulda been a buffer + +;MAG TAPE READ BUFFER DISCARD ROUTINE +MTRBD: SKIPGE A,MTMDN(W) ;Have an active MP buffer? + JRST MOVTWJ ;Set up T for buffer wait, return + CONO PI,UTCOFF ;Stop IO for a bit + SETOM MTMDN(W) ;No active MP buffer + SETZM MSMPRC(W) ;No data in nonexistant buffer + LDB TT,[MSEOFP,,MEMBLT(A)] ;Get EOF flag from PI level + PUSHJ P,MGMEMR ;Return buffer, enable UTC + JUMPN TT, [ MOVSI A,%MAEOF ;EOF seen? + IORM A,MSRAC(W) ;Record EOF in software status + JRST .+1 ] +MOVTWJ: MOVE T,W ;T gets transport number for bfr wait UFLS + POPJ P, ;Also MTRBG, MTRBFW rely on this setting T + + +;MAG TAPE READ WAIT FOR DATA ROUTINE +; Called under a UFLS by system IO code to wait for data to arrive. +; Note T, not W, has transport number. T must be set up by some +; previous routine +; +MTRBFW: MOVE TT,MSRAC(T) ;Get software status of transport + TLNN TT,%MAEOF\%MAERR ;PI code reports EOF or error? + SKIPLE MSNBOL(T) ;Or are any buffers available for reading? + JRST POPJ1 ;SOme interesting condition, unhang + TLNE TT,%MARAC ;Have we asked for a tape read yet? + POPJ P, ;Yes, nothing to do but wait, wait, wait + PUSH P,W ;This being done under a UFLS. only T good + PUSH P,B + MOVE W,T ;Set up transport number in usual place + MOVEI B,MGREAD ;What we want the PI level to do + MOVEI T,MSCBL ;Make sure that there is room in command list + CAMG T,MSCMDC(W) ;If there is room, + IFSKP. ; we will request a read operation + MOVSI TT,%MARAC + IORM TT,MSRAC(W) ;Read is active now, or will be shortly + PUSHJ P,MTCMD1 ;Queue up command request for PI level + ENDIF. ;If no room for command, all we can do is wait + MOVE T,W ;Fix up T for UFLS + POP P,B ;Clean up everything else + POP P,W + POPJ P, + +SUBTTL MAG TAPE OUTPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAO: MOVEI B,CHRKT ;Unit ASCII output + MOVE E,[440700,,5] + JRST MTWRIT + + SKIPA B,[SIOKT] +MTUIO: MOVEI B,CHRKT ;Unit image output + MOVE E,[444400,,1] + JRST MTWRIT + +MTBO: MOVE E,[444400,,1] ;Block output + MOVEI B,BLKT + +MTWRIT: LDB W,[MTXP(R)] ;Get transport number + PUSHJ P,MTIECK ;Check for tape errors first + HRLZI A,%MAETW + TDNE A,MSRAC(W) ;PI code think it hit EOT? + JRST IOCER9 ;Yep, go lose + JSP B,(B) + SETZ MSMPRP(W) ;Pointer to next word + MSMPRC(W) ;Count + SETZ MTWBFG ;Get new buffer + MTWBFD ;Write out buffer to tape + JRST 4,. + TRNA ;No wait for buffer routine needed + +;MAG TAPE WRITE - BUFFER GET ROUTINE + +MTWBFG: PUSHJ P,MTIECK ;Check for tape errors + PUSHJ P,TCALL ;Turn off UTC + JRST IOMQ ;Try to get buffer + POPJ P, ;Return noskip if no buffers available + MOVEM A,MTMDN(W) ;Store active buffer number + MOVEI T,MUMGB + DPB T,[MUR,,MEMBLT(A)] ;Tell world that it is a mag tape buffer + DPB W,[MSCHN,,MEMBLT(A)] ;Store channel number in buffer header + SETZM TT + DPB A,[121000,,TT] ;Convert block number in A to address in TT + MOVE J,MTBLKS(W) ;Get block size of write + JRST SIOBGX + +;MAG TAPE WRITE - BUFFER FINISHED ROUTINE +; General IO code has filled a buffer or otherwise finished with it. +; Queue the buffer for writing if there is anything in it. + +MTWBFD: PUSHJ P,MTIECK ;Check for tape errors + SKIPGE A,MTMDN(W) ;Have an active buffer? + POPJ P, ;No, nothing to do + MOVEI T,MSCBL ;See if there is any room in command list + CAMG T,MSCMDC(W) + PUSHJ P,UFLS ;Wait for room in command list + MOVE T,MTBLKS(W) ;Get blocksize we are writing + SUB T,MSMPRC(W) ;Subtract number of words remaining in buffer + CONO PI,UTCOFF ;Lock up while frobbing buffer lists + SETOM MTMDN(W) ;Clear active buffer + SETZM MSMPRC(W) ;Clear free word in buffer count + JUMPE T,MEMR ;Nothing in buffer, just return block + DPB T,[MWC,,MEMBLT(A)] ;Store word count + MTENQB A ;Queue buffer on to-PI list + CONO PI,UTCON ;Finished mucking with buffer list + PUSH P,B + MOVEI B,MGWRIT ;Issue a write request to PI level + PUSHJ P,MTCMD + MOVSI B,%MANWT + ANDCAM B,MSRAC(W) ;Note that we have written something to tape + SETZM MTCEFW(W) ;Note no EOF's written at end of tape + JRST POPBJ ;Restore B and return + +SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL + +;PUSHJ P,MTCMD + ;RH(W) has transport number + ;RH(B) has address of PI level routine to execute + +MTCMD: MOVEI T,MSCBL ;Pending command list length + CAMG T,MSCMDC(W) ;Count of commands currently in list + PUSHJ P,UFLS ;Wait for room in pending command list + CONO PI,UTCOFF ;Grab machine, keep count accurate +MTCMD1: MOVE T,MTCMBP(W) ;Get pointer to next slot in command list + AOBJN T,MTCMD2 ;Increment slot and check for wraparound + SUB T,[MSCBL,,MSCBL] ;Reached end of list, ring it +MTCMD2: MOVEM B,(T) ;Store new command + MOVEM T,MTCMBP(W) ;Store new pointer + AOS MSCMDC(W) ;Indicate one more command in list + JRST MSTRTR ;Go start up PI routine + +SUBTTL MTIECK - CHECK FOR IOC ERROR + +;PUSHJ P,MTIECK + ;Returns +1 if no error + ;Gives IOC error to user if error - never returns. + +MTIECK: PUSH P,A + MOVE A,MSRAC(W) ;Get transport software status + TLNN A,%MAERR ;PI level report an error? + JRST POPAJ ;No, all is OK + SKIPLE MSCMDC(W) ;Wait for PI level to finish cleaning up + PUSHJ P,UFLS ; before throwing away buffers + SKIPL A,MTMDN(W) ;Have an active MP-level buffer? + PUSHJ P,MEMR ;Yes, throw it away + SETOM MTMDN(W) ;No active MP buffer + SETZM MSMPRP(W) ;No place to get/put next character + SETZM MSMPRC(W) ;No room to do it anyway + PUSHJ P,MTCBFF ;Free any buffers waiting for MP processing + POP P,A + MOVE T,MGCMTS(W) ;Get transport status data from PI level +IFN TM10P,[ + TRNE T,%T1STH\%T1SIO ;Transport hung or illegal operation? + JRST IOCER1 ;Yes, report device error + TRNE T,%T1SPE\%T1SRC\%T1SRL\%T1SDL\%T1SBT ;Gruesome errors + JRST IOCER3 ;Report irrecoverable data error + TRNE T,%T1SET ;(Real) End of Tape? + JRST IOCER9 ;Device Full error +];IFN TM10P +IFN TM03S,[ + MOVE I,MGCMTC(W) ;Get controller transport status from PI level + MOVE J,MGCMTS(W) + TTNE CS1,%TM1MP ;Control bus parity error? + JRST IOCER1 + TTNN CS1,%TM1TE ;Transfer error? Could be TM03 or RH11 + IFSKP. + TTNE CS2,%TM2DL\%TM2UP\%TM2NF\%TM2NM\%TM2PE\%TM2MT\%TM2MP + JRST IOCER1 ;Non-data errors + TTNN FS,%TMSES ;Formatter error? + IFSKP. + TTNE ERR,%TMEUS\%TMECT\%TMENX\%TMEMD\%TMEFS\%TMEMC\%TMERM\%TMEIR\%TMEIF + JRST IOCER1 ;Fatal formatter errors + TTNE ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEIC + JRST IOCER3 ;Non-recoverable data errors + ENDIF. + ENDIF. + TTNE FS,%TMSET ;End of tape? + JRST IOCER9 +];IFN TM03S + MOVE A,MGEOFR(W) ;Check for logical EOT + CAIL A,2 ;Read two EOF's since last record? + JRST IOCER9 ;Yes, report EOT + JRST IOCER3 ;No, give irrecoverable data error for now + +SUBTTL MAG TAPE .STATUS ROUTINE +;Building a status word in D. +;Routine sets: +; 1.7-1.9 open modes +; 2.3 BOT +; 2.4 EOT +; 2.5 9 track (0 = 7 track) +; 2.6 IBM mode (0 = coredump) +; 2.7 Transport idle (no pending command) +; 2.8 EOF (last thing seen was a tape mark) +; +STAMTC: +;Open modes + LDB W,[MTXP(R)] ;Get transport number + DPB A,[60300,,D] ;Open mode + PUSHJ P,MTSTAT ;Get tape status from transport +;EOT? + LDB A,[.BP %MAETW_22,MSRAC(W)] ;EOT on write + LDB B,[.BP %MAETR_22,MSRAC(W)] ;EOT on read + IOR A,B + DPB B,[140100,,D] ;Tape at EOT? +IFN TM10P,[ +;7 or 9 track drive? + LDB A,[20100,,J] ;Get 7/9 track bit + TRC A,1 + DPB A,[150100,,D] ;7 or 9 track drive + .ERR Missing TM10 .STATUS code at STAMTC +] +IFN TM03S,[ +;A bunch of new stuff. BOT? + SETZ A, + TTNE FS,%TMSBT ;Transport is at BOT? + SETO A, + DPB A,[130100,,D] ;BOT. +;7 or 9 track drive? + SETOM A ;TM03 is always 9-track + DPB A,[150100,,D] ;7 or 9 track drive +;Core dump or 32 bit mode? + MOVE A,MTWTFC(W) ;Get word to frame conversion. 4 or 5 + TRC A,1 ;Flip last bit. Last bit now on iff 32bit mode + DPB A,[160100,,D] ;Sorry. +;Formatter busy? + SETO A, + SKIPLE MSCMDC(W) ;Idle if no pending commands + SETZ A, + DPB A,[170100,,D] +;EOF last thing seen? + SETZ A, + TTNE FS,%TMSTM ;Last thing seen was a tape mark? + SETO A, + DPB A,[200100,,D] ;EOF. +];IFN TM03S + POPJ P, + +;RCHST ROUTINE FOR MAG TAPE + +RCHMGT: HLRZ E,(R) ;Get open mode from IOCHNM word + LDB J,[MTXP(R)] ;Get the mag tape drive number + MOVSI J,'MT0(J) ;Return that drive's device name + TRZ E,(.BM MTXP) ;Clear drive # field in OPEN modes + JRST POPJ1 ;Skip so that J overrides built-in device name + + +SUBTTL MAG TAPE PI LEVEL + +;Request magtape interrupt from MP-level software +; Must be called with I/O interrupts off (CONO PI,UTCOFF) +; This is called every 1/2 second by the ITS slow clock routine +; +MSTRTR: SETZM MGTBZY ;No busy tapes, flag software interrupt + CONO PI,MTCRQ ;Request interrupt on magtape channel + CONO PI,UTCON ;Reenable IO interrupt system + POPJ P, ;That is all + +;Handle tape interrupt requested by software or other nonspecific cause +; Get here via non-vectored MTCCHN interrupt on the KS +; +MGSBRK: AOS MGTBZY ;Note interrupt level is busy + SETOM MGSFTI ;Note software interrupt in progress + MOVEI B,NMTCS-1 ;Loop over all transports + SKIPG MSCMDC(B) ;Any commands in command list? +MGSBK1: SOJGE B,.-1 ;No, try next transport + SKIPGE B ;Found command or finished scan. Which? + JRST MGSBK2 ;Finished scanning. Go check other things + MOVE W,B ;Have a command. Set up transport number + PUSH P,B ;Save B over call to command routine + MOVSI B,%MACTH + TDNN B,MSRAC(W) ;Core allocator saying go away? + PUSHJ P,MGXGO ;No, go start requested routine + POP P,B ;Restore transport count + JRST MGSBK1 ;Loop back for another transport + +MGSBK2: SETZM MGSFTI ;Clear software interrupt flag + JRST MGEX ;That's all for now +;This probably should check for lost IE bits on TM03 + +;Handle interrupt caused by specific hardware conditions +; Get here via vectored interrupt on the KS +; + +IFN TM10P,[ +; A - result of CONI MTC, +; C - result of CONI MTS, +; +MGHBRK: SKIPGE W,MGUNIT ;Get unit we are expecting interrupt on + JRST MGUBRK ;None? Probably MP level bailed out. Punt. + LDB B,[MUNITF,,A] ;Get unit that controller is squacking about + CAME W,B ;Same unit? + BUG HALT,[MT PI CODE LOST TRANSPORT] + MOVE J,C + PUSH P,[MGEX] ;Cause POPJ P, in handler to dismiss interrupt +IFN TM10B,[ + TXNE C,%T1SCP\%T1SNM\%T1SDP ;Check for DF10 errors + JRST MGERR ;Yes, go to error routine +];TM10B + TXNE C,%T1SIO ;Illegal operation error? + JRST MGERR ;Yes, go to error routine + JRST MGXGO ;No, go handle interrupt + +;Here to unbreak on unexpected hardware interrupt +; +MGUBRK: LDB W,[MUNITF,,A] ;Who's the loser, anyway + MOVE B,MTCONO(W) ;Get prototype CONO word for that transport + CONO MTC,(B) ;Select offending unit + CONO MTS,31 ;Clear interrupt, DF10, stop any op in progress + JRST MGEX ;Go dismiss interrupt +];IFN TM10P + +IFN TM03S,[ +;Check for active unit. If none, go directly to inactive slave +;polling code. If active unit,check that controller is talking about +;this unit, then jump to its routine (MGXGO). When that finishes, +;see if controller is still showing attention, and check status +;of other transports if so. +; +;Well, almost. + + EBLK +MGHBRK: 0 + BBLK + JSR UTCSAV ;Save AC,s set up interrupt P PDL + AOS MGTBZY ;Note interrupt level is alive + SKIPGE W,MGUNIT ;Some transport waiting for an interrupt? + JRST MGNOUW ;Nope, either Slave Status Change or lossage + IORDI B,%TMTC ;Get transport the TM03 is thinking about + ANDI B,7 + CAME B,W ;Same as the one we were waiting for? + BUG HALT,[MT PI CODE LOST TRANSPORT] + PUSHJ P,MGXGO ;Go jump into this unit's handler + +MGNOUW: +IFN NMTCS-1,[ +.ERR Missing multi-transport code at MGNOUW! +If more than one unit, have to see if this is an interrupt caused by a +SSC (slave status change), and if so poll all the inactive units and +update their software status (rewinding, on/off line, etc.) With only +one transport we currently avoid this by keeping the unit active +(MGUNIT set) as long as it is doing *anything*, and giving it all the +hardware interrupts. See rewind code, too. +];IFN NMTCS-1 + JRST MGEX ;Go dismiss interrupt +];IFN TM03S + +;Interrupt level control flow +; +; Each transport maintains the current state of its PI-level action +; routines on a seperate (per-transport) PDL with its SP in Q. This +; allows you to save the current state, dismiss the interrupt, and +; resume where you left off when the next interrupt for this transport +; arrives. +; +; Subroutine linkage between routines handling a per-drive PI-level +; action is with PUSHJ Q,xxx and POPJ Q, +; +; The MP level queues commands for the PI level to process on a per- +; transport queue at MGSBx (x=unit number) +; +; Ths general interrupt code transfers to the per-drive actions by +; jumping to MGXGO, which will load Q from the saved state of the +; current drive and start up whatever it finds there. This may be +; the MGNCMD routine, which will start a new command, or it may be +; the middle of an in-progress PI-level command handler. +; +; PI-level action routines can relinquish control in several ways: +; +; PUSHJ Q, CPOPJ will dismiss the current interrupt, arranging for +; control to return to the instruction following the PUSHJ when the +; next interrupt for this unit occurs. +; +; JRST MGOVER will dismiss the current interrupt, arranging for the +; currently executing subroutine to be restarted "from the top" when +; the next interrupt for this unit occurs. +; +; A simple POPJ P, will dismiss the current interrupt, arranging for +; the routine that called this one to be started at the point immediately +; after the call when the next interrupt comes in. This is generally not +; useful except from first-level action routines, where a POPJ P, will +; indicate that you have finished handling the current command and cause +; the next interrupt to fetch and start execution of a new command from the +; queued command list by transferring to MGNCMD. Got that? + +;Transfer control to whatever the per-transport code wants to do. +; +MGXGO: MOVE Q,MGQDLP(W) ;Getsaved Q PDL pointer for current transport + PUSHJ P,QPOPJ ;"Return" to whatever is on top of Q PDL, + ; arranging for POPJ P, to return to here + + MOVEM Q,MGQDLP(W) ;Save current Q PDL for next time + POPJ P, ;Return, dismissing this interrupt + +;Dismiss interrupt, arranging for next interrupt to restart routine +; we are currently executing (rather than either continuing here or +; starting a new command) +; +MGOVER: +IFN TM10P,[ + CONSZ MTS,%T1STH\%T1SIO\%T1SCE ;Tape hung/ill op/DF10 error, + JRST MGERR ; go handle error condition +] + SOS (Q) ;Decrement address at top of Q PDL, now + ; points to PUSHJ Q, instruction so + ; that we will get called again from MGXGO + ; at next interrupt dispatch + POPJ P, ;Return to P PDL caller, dismissing interrupt + + +;This routine is always the last "command" in a transport command list +; Wraps the command list BP around the the beginning of the list, +; then gets and executes the next command. +; +MGRCV: MOVNI A,MSCBL+1 ;Get negative length of command list + ADDM A,MGCMBP(W) ;Wrap command extraction pointer back to start +MGNCM1: ILDB B,MGCMBP(W) ;Get new command from list + JRST (B) ;And jump to it + +;This code is always the first (bottom) thing in a transport's Q PDL +; It is therefore executed whenever MGXGO transfers control to the +; Q PDL and there is no command in progress. +; +MGNCMD: AOBJN Q,MGNCM1 ;Got here w/ POPJ Q,. Fake PUSHJ to restore Q, + ; then go get the next command + + BUG ;Q PDL pointer clobbered + +QPOPJ1: AOS (Q) +QPOPJ: POPJ Q, + + +;WAIT FOR JOB DONE BIT TO SET +; Called from PI-level command routines to wait for end of command. +; Called with PUSHJ Q,MGWTJD +; +; Returns +1 to caller if unusual termination +; +2 to caller if operation terminated normally +; +; I,J contain tape status: +; On TM10, I=CONI MTC, +; J=CONI MTS +; On TM03S, I=%TMCS1,,%TMCS2 (controller status), +; J=%TMFS,,%TMERR (formatter status) + +IFN TM10P,[ +MGWTJD: CONI MTS,J ;Get transport status + TXNE J,%T1STH\%T1SIO ;Transport hung or Illegal operation? + JRST MGERR ;Yes, job-done isn't ever going to get set +MGWJD1: CONI MTS,J ;Get status again + SKIPN MGJDTI ;Is there a time out set? + IFSKP. + MOVE T,TIME ;Yes, check it. Get current time + CAML T,MGJDTI ;Smaller than specified timeout time? + JRST MGERR ;No, lose + ENDIF. + TXNN J,%T1SJD ;JOB-DONE bit set? + JRST MGOVER ;No, we want to wait for it + CONI MTS,J ;Job Done. Get status + CONI MTC,I ;Get CONI MTC + MOVEM J,MGCMTS(W) ;Save for MP level + MOVEM I,MGCMTC(W) +IFN TM10B,[ + SKIPE MGWCW ;Want to wait for control word? + PUSHJ Q,MGWCWC ;Check to see if it is written + SETZM MGWCW ;Clear wait-for-control-word request flag +] + CONO MTS,30 ;Clear channel conditions + MOVE B,MTCONO(W) + CONO MTC,(B) ;Release mtc, clear job done bit +IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP ;Check for channel errors + POPJ Q, ;Channel error, return nonskip +] + TXNE J,%T1STH\%T1SIO\%T1SPE\%T1SRC%\T1SRL\%T1SDL\%T1SBT + POPJ Q, ;Random other things, not necessarily errors + JRST QPOPJ1 ;Success +];IFN TM10P +IFN TM03S,[ +MGWTJD: +MGWJD1: IORDI T,%TMCS1 ;Get controller status + TXNN T,%TM1GO ;Go bit still set? + JRST MGWJD2 ;No, command is finished. Go check errors + SKIPE T,MGJDTI ;Is there a time out set? Get it if so. + CAML T,TIME ;Past timeout time + JRST MGOVER ;No timeout or not timed out yet, go wait + JRST MGERR ;Timed out. Go check transport + +;Here if action has terminated. Set up status bits before returning +MGWJD2: HRLZ I,T ;%TMCS1,,? + IORDI T,%TMCS2 + HRR I,T ;I = %TMCS1,,%TMCS2 + IORDI J,%TMERR + IORDI T,%TMFS + HRL J,T ;J = %TMFS,,%TMERR - I,J now in standard form + MOVEM J,MGCMTS(W) ;Save for MP level + MOVEM I,MGCMTC(W) + TTNE CS1,%TM1MP ;Massbus control parity error + JRST MGERR ;Who knows what the transport is doing + TTNN CS1,%TM1TE ;Controller error? + TTNE FS,%TMSES ;Formatter error? + POPJ Q, ;Yes, return +1 for closer examination + JRST QPOPJ1 ;Success +];IFN TM03S + +;Select the transport given by W +; Returns +1 with transport selected, status in I,J +; May dismiss and wait for a while first +; +MGGXPT: +IFN TM10P,[ + CONSO MTS,%T1SNU ;Can controller select new unit right now? + JRST MGOVER ;No, wait for it + MOVE T,TIME + ADDI T,10.*30. ;Time out in 10. seconds + MOVEM T,MGJDTI ;Set up job-done timeout + MOVEM W,MGUNIT ;Note unit waiting for hardware interrupt + MOVE B,MTCONO(W) ;Get CONO word for new unit + CONO MTC,MNOPIN(B) ;NOP, but interrupt when new drive is ready + PUSHJ Q,MGWJD1 ;Wait for job done + JFCL ;Ignore any errors + SETZM MGJDTI ;No more timeout + SETOM MGUNIT ;Not waiting any more + POPJ Q, ;Return to caller +];IFN TM10P +IFN TM03S,[ + IORDI T,%TMFS ;Get current formatter status + TXNN T,%TMSES\%TMSSC ;Showing error or slave status change? + IFSKP. ;Yes, clear errors before going ahead + IOWRI W,%TMTC ;Select slave + MOVEI A,10. ;Try 10 times to clear drive + MOVEI B,%TMCLR + DO. + IOWRI B,%TMCS1 ;Write drive clear command + IORDI T,%TMFS ;Get status + TXNN T,%TMSES ;Still have error + JRST ENDLP. ;No, done + SOJG A,TOP. ;Retry up to 10 times + JRST MGERR ;Else give up + ENDDO. + ENDIF. + MOVE T,MTSELW(W) ;Get desired settings + IOWRI T,%TMTC ;Tell TM03 + MOVEI T,%TMNOP ;You may need this to set status values + IOWRI T,%TMCS1 ; but I'm not really sure + IORDI T,%TMCS1 + PUSHJ Q,MGWJD2 ;Go set status registers appropriately + JFCL ;Maybe should check non-existant slave? + POPJ Q, +];IFN TM03S + +;MGERR - HANDLE TAPE ERROR +; +;Called from PI level command routines which detect a tape or controller error +; Flags error in software status word, records error status in MGExxx. +; Flushes command in progress by resetting Q PDL to base. +; Flushes commands in PI-level command queue by resetting queue pointers. +; Flushes any buffers which might be queued for writing. +; Returns to P PDL, to wait for new commands. + +MGERR: +IFN TM10P,[ + CONI MTS,MGEMTS ;Get transport status for MP level analysis + CONI MTC,MGEMTC +] +IFN TM03S,[ + IORDI T,%TMCS1 ;Get controller and transport status into + HRLM T,MGEMTC ; standard form + IORDI T,%TMCS2 + HRRM T,MGEMTC + IORDI T,%TMFS + HRLM T,MGEMTS + IORDI T,%TMERR + HRRM T,MGEMTS + MOVE I,MGEMTC ;Get status to standard place for macros + MOVE J,MGEMTS +];IFN TM03S + MOVSI T,%MARAC ;Read not active, for sure + ANDCAM T,MSRAC(W) + SETZM MSCMDC(W) ;No commands active + SETOM MGUNIT ;Clear unit wait flag + SETZM MGJDTI ;No job-done timeout +IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP ;Channel error? + BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD +];TM10B +IFN TM03S,[ + .ERR UBA errors? More gentle cleanup? + TTNE CS1,%TM1MP\%TM1TE ;Cbus parity or transfer error? + TTNE FS,%TMSES ;And no formatter error? + SKIPA ;Yes and yes (no) (what?). Controller error + BUG INFO,[MTAPE: RH11 ERROR, STATUS=],OCT,MGEMTC,[TM STATUS=],OCT,MGEMTS + TTNE FS,%TMSES ;Formatter error? + BUG INFO,[MTAPE: FORMATTER ERROR, STATUS=],OCT,MGEMTS + PUSHJ P,TMINIC ;Go reinit controller +];IFN TM03S + SKIPL A,MGCABN(W) ;Any buffers owned by PI routines? + PUSHJ P,IMEMR ;Yes, give them back to system + SETOM MGCABN(W) ;No PI buffer any more + HRLZI B,%MAERR ;Flag error detected by PI level + IORM B,MSRAC(W) ;Store in transport status word + MOVE Q,[-MGQDLL,,MGQD0-1];Reset Q PDL to base of this unit's stack, + MOVE T,MSLCTB ; thus flushing whatever command is in progress + IMUL T,W ;Find offset to base of Q PDL for this unit + ADD Q,T ;Add to prototype unit 0 QDP pointer, + PUSH P,Q ; and save it away + MOVE Q,[-MSCBL-1,,MSCB0-1] ;Get command list input pointer + ADD Q,T ;Offset it to this unit's command queue, + MOVEM Q,MTCMBP(W) ;And save it as new MP (input) queue pointer + MOVE Q,[4400,,MSCB0-1] ;Get new command list output pointer + ADD Q,T ;Offset correctly for this unit, + MOVEM Q,MGCMBP(W) ;And save as PI (output) command queue pointer + MOVSI B,%MAREW ;Does initting xport stop TM03 rewind? + ANDCAM B,MSRAC(W) ;Say not rewinding + SKIPN MSCRW(W) ;If reading, + JRST POPQJ ; we're done. Restore Q and exit + SKIPN MSNBOL(W) ;Writing. Any buffers on list? + JRST POPQJ ;No, restore Q and exit + DO. ;Here to free buffers on IO list + HRRZ A,MSBUFP(W) ;Get buffer pointer from head of chain + LDB T,[MLO,,MEMBLT(A)] ;Get back pointer (next buffer) + HRRM T,MSBUFP(W) ;Make next buffer head of chain + PUSHJ P,IMEMR ;Free current buffer + SOSLE MSNBOL(W) ;Decrement count, check for more + JRST TOP. ;More, loop back + ENDDO. + SETZM MSBUFP(W) ;Mark list as empty + JRST POPQJ ;Restore Q and return + +IFN TM10B,[ +;Wait for control word to get written +; +MGWCWC: SKIPE MICWA+1 ;Control word written? + POPJ Q, ;Yes, return to caller + CONO MTS,4 ;No, tell DF10 to write it +MGWCW1: SKIPE MICWA+1 ;Written yet? + JRST MGWCW2 ;Good, done + PUSHJ Q,CPOPJ ;Not written. Dismiss interrupt and wait + JRST MGWCW1 ;We're back. See if written yet. + +MGWCW2: MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) ;Restore status + TLO J,10 ;Set control word written + POPJ Q, ;Return to caller +];IFN TM10B + +IFN TM10A,[ +MGDCSI: SKIPA A,[BLKI MTC,MIOWD] +MGDCSO: MOVE A,[BLKO MTC,MIOWD] + MOVEM A,MAGLOC + MOVE A,[JSR MGDBRK] + MOVEM A,MAGLOC+1 + POPJ Q, +];IFN TM10A + +IFN TM03S,[ +;Note this one's called on P PDL +TMINIC: IORDI A,%TMTC ;Get TC reg value + ANDI A,MTSELM ;Keep interesting bits only + IORDI B,%TMCS2 ;Get CS2 + ANDI B,7 ;Keep selected "drive" (TM03) number only + MOVEI T,%TM2CC + IOWRI T,%TMCS2 ;Clear controller logic + IOWRI B,%TMCS2 ;Reselect TM03 + IOWRI A,%TMTC ;Reselect transport + MOVX T,%TMCLR ;Do a formatter clear command + IOWRI T,%TMCS1 + POPJ P, +];IFN TM03S + + +SUBTTL MAG TAPE PI LEVEL WRITE + +MGWRIT: PUSHJ Q,MGGXPT ;Select desired transport +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Write locked, hung or rewinding? + JRST MGERR ;Not a good thing +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line? + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +] + MOVSI A,%MACTH + TDNE A,MSRAC(W) ;Core alloc want quit temporarly? + JRST [ PUSHJ Q,CPOPJ ;OK, wait a while + JRST MGWRIT ] ;Then go back and try again + MOVEM W,MGUNIT ;Set unit + HRREI B,-MGNRTY ;Number of retries + MOVEM B,MGERRC(W) ;Store error count + MTDEQB A ;Get buffer to write off list + MOVEM A,MGCABN(W) ;Note this buffer active at PI + LDB B,[MWC,,MEMBLT(A)] ;Get word count from buffer + MOVNS B ;B -> -COUNT + HRLZS B ;B -> -COUNT,,0 +IFN KL10P,LSH B,4 ;Shift if KL10 data channel +IFN KL10P,MOVE R,A ;Save core page number for cache sweep +IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE + LSH A,10. ;Convert buffer number to memory address + SUBI A,1 ;Address - 1 +] + HRRM A,B ;B -> -COUNT,,ADDRESS-1; an IO word +IFN TM10B,DATAO MTS,[MICWA] ;Tell DF10 where IO channel program is +IFN TM10A,PUSHJ Q,MGDCSO ; + MOVEM B,MIOWD ;Put IO word where controller looks + MOVEM B,LMIOWD ;Remember what we're about to do +IFN TM10P,SETZM MIOWD+1 ;Stop after one operation +IFN KL10P,[ + PUSHJ P,CSHSWP ;Unload buffer from cache into core + CAI +] +MGWRT2: +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get prototype CONO word + CONO MTC,MWRITE(B) ;Perform WRITE operation +] +IFN TM03S,[ + HLRE A,MIOWD ;Get PDP10 word count + ASH A,1 ; * 2 + IOWRI A,%TMWC ; = number of unibus words to transfer + HLRE A,MIOWD ;Get PDP10 word count again + IMUL A,MTWTFC(W) ;Convert to tape frame count + IOWRI A,%TMFC ;Set tape frames to write + HRRZ A,MIOWD ;Get ITS page to transfer to + LSH A,1 ;Convert ITS pg # to DEC pg # + TXO A,%UQVAL ;Valid mapping, I should hope + IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping + TXO A,1 ;Next DEC page number + IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping + MOVEI A,IUTPG_14 ;Unibus address to DMA to + IOWRI A,%TMBA ;Tell controller + MOVX A,%TM1IE\%TMWRT ;Write, enable interrupts + IOWRI A,%TMCS1 ;Start controller +] + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGWERR ;Error, go attempt to repair + +;Here if tape written OK +MGWRT3: MOVE A,MGCABN(W) ;Get buffer number + HRLZI B,%MAETW+%MAERR ;End of tape check +IFN TM10P,TXNE J,%T1SET ;Controller says we're at EOT? +IFN TM03S,TTNE FS,%TMSET + IORM B,MSRAC(W) ;Tell MP + LDB T,[MUR,,MEMBLT(A)] ;Get buffer flavor from buffer + CAIE T,MUMGB ;Still a magtape buffer? + BUG HALT,[MT BUF CHANGED INTO SOME OTHER KIND??] + SETOM MGCABN(W) ;No buffer active at PI anymore + PUSHJ P,IMEMR ;Return buffer to system + MOVSI A,%MAMSO ;Note tape has moved since open + IORM A,MSRAC(W) + ;JRST MGCMDR ;Falls through + +;General exit routine for most PI-level command handlers +; Check command queue for more commands. +; If no further commands, dismiss interrupt. +; If further commands queued, wait for this one to finish, then fetch +; and begin processing of next command. +; +MGCMDR: SOS MSCMDC(W) ;Decrement command count + SETOM MGUNIT ;Reset active unit + SKIPG MSCMDC(W) ;Any more commands? + JRST MGCMR1 ;No. Go see about other units +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ;Tell controller to interupt when unit ready + MOVEM W,MGUNIT ;Set up unit number again for MGWTJD + PUSHJ Q,MGWTJD ;Go wait for unit to finish current command + JRST MGERR ;Oops + SETOM MGUNIT ;No unit waiting any more +];IFN TM10P + POPJ Q, ;Return on Q PDL. Most likely this will + ; transfer control to MGNCMD routine at + ; base of PDL, which will fetch and execute + ; next command. + +MGCMR1: +IFN NMTCS-1,[ +;Ought to check other transports for commands to start. +; For now, will get started by 1/2 second timeout, if nothing else. + .ERR Unfinished multi-transport code at MGCMR1 +];IFN NMTCS-1 + POPJ P, ;No more, return on P to dismiss interrupt + + + +;CONTROLLER DETECTED ERROR ON WRITE OPERATION +; Retry, or give up, or write some blank tape and then try again, +; depending on the type of error. +; +MGWERR: +IFN TM10P,[ +IFN TM10B,SETZM MIOWD ;Seems to do one record anyway +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;Specify one record to space back cmd. +] + TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SET\%T1SWL ;Bad types of errors + JRST MGERR ;OK, give up + AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ;Space reverse one record + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGERR ;Error + MOVE B,LMIOWD ;Get last operation's IOWD + MOVEM B,MIOWD ;We're going to try it again + MOVE B,MTCONO(W) ;Get prototype CONO + CONO MTC,14000(B) ;Write with extended EOR gap + PUSHJ Q,MGWTJD ;Wait for completion + JRST MGWBT ;Lost again, retry some more + JRST MGWRT3 ;Worked, return to normal write sequence +];IFN TM10P +IFN TM03S,[ + TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX\%TMEOI + JRST MGERR ;Fatal errors + TTNN FS,%TMSOL ;On line? + JRST MGERR ;This isn't so good either + TTNE ERR,%TMEFC\%TMENG\%TMEMD\%TMEIC\%TMECE\%TMECS\%TMEFL + JRST MGWER1 ;Error which retrying might fix + +;Formatter seems happy. Check channel status before returning +; Currently this only catches the case where there was an RH11 error +; but no TM03 error, and thus should always end up jumping to MGERR. +; Formatter errors on which it might be OK to get here are %TMECE, +; %TMECS, %TMEFL, but someone needs to test this... + TTNE CS1,%TM1TE ;Transfer error? + TTNE FS,%TMSES ;And not formatter error? + CAIA + JRST MGERR ;Just lose for now + BUG INFO,[MT: ACCEPTING QUESTIONABLE WRITE OPERATION] + JRST MGWRT3 + +;Retry errors +MGWER1: AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up + BUG INFO,[MT: RETRYING WRITE OPERATION] + PUSHJ P,TMINIC ;Hit controller with hammer + MOVEI B,1 + MOVEM B,MGSPCD(W) ;1 record + PUSHJ Q,MGSPCR ;Reselect transport space back a record + TTNE FS,%TMSTM ;Stopped on EOF? + SOSGE MGEOFR(W) ;Yes, one less EOF in front of us + SETZM MGEOFR(W) ;But never less than zero + PUSHJ P,TMINIC ;Hit controller with hammer again + PUSHJ Q,MGGXPT ;Set up transport again + MOVEI B,%TMER3\%TM1IE + IOWRI B,%TMCS1 ;Erase a few inches of tape + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGERR ;Can't get anything right... + MOVE B,LMIOWD ;Get last operation's IOWD + MOVEM B,MIOWD ;We're going to try it again + JRST MGWRT2 ;Go back to write code and retry operation +];IFN TM03S + + +SUBTTL MAG TAPE PI LEVEL READ + +MGREAD: PUSHJ Q,MGGXPT ;Select desired transport +MGRD0: +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SET ;Unit hung, rewinding, or EOT + JRST MGERR ;Seems so, report error +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVE B,MGEOFR(W) ;EOF's seen since last read + CAIL B,2 ;Apparent logical EOT? + JRST MGERR ;Yes, can't read anything + SKIPE MSCRW(W) ;Make sure open for reading + BUG HALT,[MT: CHN NOT OPEN FOR READING] + MOVSI B,%MACTH ;Core allocator wants to wait? + TDNN B,MSRAC(W) ;Check in status word + PUSHJ P,IOMQ ;No, get a buffer + JRST [PUSHJ Q,CPOPJ ;Wanted to wait some or failed, + JRST MGREAD ] ; wait a while, then start over + MOVEM A,MGCABN(W) ;Note active buffer at PI level + MOVEI B,MUMGB + DPB B,[MUR,,MEMBLT(A)] ;Note buffer belongs to mag tape code + MOVEM W,MGUNIT ;Set active unit number + HRREI B,-MGNRTY ;Number of retries + MOVEM B,MGERRC(W) ;Store error count +IFN KL10P, MOVE R,A ;Get page for cache flush routine +IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE + LSH A,10. ;Convert buffer number to memory address + SUBI A,1 ;address-1 +] +IFE KL10P,HRLI B,-2000 ;Get count half of IOWD +IFN KL10P,HRLI B,-2000_4 ;The KL is, of course, different + HRR B,A ;-count,,address-1 + MOVEM B,LMIOWD ;Remember IOWD for possible retry +IFN TM10B,[ + DATAO MTS,[MICWA] ;Tell DF10 where the channel program is + SETZM MICWA+1 ;Stop after one operation +] +IFN TM10A,PUSHJ Q,MGDCSI +IFN TM10P,SETZM MIOWD+1 +MGRD1: MOVEM B,MIOWD ;Save IOWD where channel expects it + MOVEI B,2000 ;Assume for now that the record has 2K words + MOVEM B,MGNWRD ;Set up word count +IFN KL10P,[ + PUSHJ P,CSHSWP ;Ensure no residue of this page in cache + CAIA +] +IFN KS10P,CLRCSH ;KS needs cache invalidated on read +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get prototype CONO word + CONO MTC,MREAD(B) ;Issue READ command +] +IFN TM03S,[ + HLRE A,MIOWD ;Get PDP10 word count + ASH A,1 ; * 2 + IOWRI A,%TMWC ; = number of unibus words to transfer + SETZ A, ;Set FC to zero + IOWRI A,%TMFC ;Set tape frames to write + HRRZ A,MIOWD ;Get ITS page to transfer to + LSH A,1 ;Convert ITS pg # to DEC pg # + TXO A,%UQVAL + IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping + TXO A,1 ;Next DEC page number + IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping + MOVEI A,IUTPG_14 ;Unibus address for DMA + IOWRI A,%TMBA ;Tell controller + MOVX A,%TM1IE\%TMRDF ;Read forward, enable interrupts + IOWRI A,%TMCS1 ;Start controller +];IFN TM03S +IFN TM10B,SETOM MGWCW ;Tell MGWTJD to wait for control word written + PUSHJ Q,MGWTJD ;Wait for command to complete + JRST MGRERR ;Error, go do something. May be retry, correct + ; MGNWRD if frame count error, or give up +IFN TM03S,[ +;Get true record size for TM03, which doesn't give a FC error on READ +MGRD1A: TTNE FS,%TMSTM ;Read a tape mark? + JRST [ SETZM MGNWRD ;Read a tape mark. No data, just EOF + JRST MGRD2 ] + IORDI A,%TMFC ;Get record size in tape frames + ADD A,MTWTFC(W) ;Round up to PDP10 words. + SUBI A,1 ;Add frames_per_word - 1 + IDIV A,MTWTFC(W) ;Get record size in PDP10 words + MOVEM A,MGNWRD +];IFN TM03S +;Here if OK or error handler has fixed things up +MGRD2: MOVE A,MGCABN(W) ;Get buffer we just wrote + SETOM MGCABN(W) ;No buffer active at PI level + MTENQB A ;Queue buffer up for MP level + MOVE B,MGNWRD ;Get number of words we read + DPB B,[MWC,,MEMBLT(A)] ;Set number of words in buffer +IFN TM10P,TXNE J,%T1SEF ;Read an EOF? +IFN TM03S,TTNE FS,%TMSTM ; i.e. a tape mark? + IFSKP. + SETZM MGEOFR(W) ;No. Note no EOFs read since last record + ELSE. + MOVSI B,%MAESO+%MAEFA ;EOF seen since open, EOF read ahead + IORM B,MSRAC(W) ;Note this in transport status word + SETO B, + DPB B,[MSEOFP,,MEMBLT(A)] ;Set EOF flag in this buffer + AOS A,MGEOFR(W) ;Count EOFs + CAIL A,2 ;Enough for EOT? + JRST MGRD4 ;Logical EOT, space back over it + ENDIF. + MOVSI A,%MAMSO + IORB A,MSRAC(W) ;Note tape movement +IFN TM10P,TXNE J,%T1SET ;Real EOT reached? +IFN TM03S,TTNE FS,%TMSET + JRST MGRD3 + MOVE C,MSNBOL(W) ;Get count of buffers on list +IFN TM10P,TXNN J,%T1SEF ;EOF? +IFN TM03S,TTNN FS,%TMSTM + +; CAIL C,6 ; or read ahead six records? + JFCL ;Or just for the hell of it + + JRST MGRD5 ;Yes, stop reading + TLNN A,%MASTP ;Somebody request we stop? + JRST MGRD0 ;No, go back and read another record + ;Yes, fall through to terminate read +;Here to terminate read command +; +MGRD5: MOVSI A,%MASTP+%MARAC ;Clear read active, any read stop request + ANDCAM A,MSRAC(W) + JRST MGCMDR ;Go to standard command return routine + +;Controller saw a real EOT +; +MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;Fake EOF + DPB B,[420100,,MSRAC(W)] .SEE %MAETR ;Indicate EOT on read + JRST MGRD5 ;Terminate read + +;Here if logical EOT (two EOF's in a row) +; Back up till between the two EOF's +; +MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT + ANDCAM A,MSRAC(W) + JRST MGSPRF ;Space reverse one file + +;Error detected on read. +; Analyze error, retry read if it might help +; +MGRERR: +IFN TM10P,[ + IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP + JRST MGERR ;Channel error, forget it + ] + TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SRC ;Hard error? + JRST MGERR ;Yes, abandon read + TXNE J,%T1SPE\%T1SDL%T1SBT ;Parity, data-late, or bad tape? + JRST MGMRT ;Yes, a read retry might fix it + TXNN J,%T1SRL ;Record length error? + JRST MGERR ;No, who knows what is going on + +;Here if record length error. Adjust MGNWRD to reflect data actually read +; +IFN TM10B,HRRZ A,MICWA+1 +IFN TM10A,HRRZ A,MIOWD ;Get final control word + HRRZ B,LMIOWD ;Get original IOWD + SUB A,B ;Calculate words read +IFN TM10B,SOS A ;Channel funnyness + CAIE A,1 ;Length of 1 may just be EOF indication + IFSKP. + TXNE J,%T1SEF\%T1SET ;1 word, EOF? EOT? + SETZM A ;Yes, zero length record, just carries MSEOFP + ENDIF. + MOVEM A,MGNWRD ;Save new record length + JRST MGRD2 ;Go process as potentially correctly read data +];IFN TM10P +IFN TM03S,[ + TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX + JRST MGERR ;Fatal errors + TTNN FS,%TMSOL ;On line? + JRST MGERR ;This isn't so good either + TTZ ERR,%TMEFC\%TMENG ;Ignore NSG, Frame count error + TTNE FS,%TMSPE ;Phase encoded (1600BPI) mode? + TTZ ERR,%TMECE\%TMECS ;If so, ignore errors hardware already fixed + TTZN ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEMD\%TMEIC ;Retryable? + JRST MGRER1 ;Nothing retrying will help + TTNE FS,%TMSTM ;Tape mark? + JRST MGRER2 ;Yes, no point in retrying + JRST MGMRT ;OK, go retry read + +;Formatter seems happy. Check channel status before returning +MGRER1: TTNE ERR,177777 ;Sanity check. Shouldn't be any errors left + JRST MGERR + TTNE CS1,%TM1TE ;Transfer error? + TTNE FS,%TMSES ;And not formatter error? + CAIA + JRST MGERR ;Just lose for now +MGRER2: JRST MGRD1A + +];IFN TM03S + + +;Retry a read operation +; +MGMRT: AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up +IFN TM10P,[ + IFN TM10B,SETZM MIOWD + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + ] + MOVEM A,MIOWD ;One record + PUSHJ Q,MGDCSO + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ;Back up one record + PUSHJ Q,MGWTJD ;Wait till done + JRST MGERR ;No errors allowed + IFN TM10A,PUSHJ Q,MGDCSI ;Put back PI 1 BLKI +];IFN TM10P +IFN TM03S,[ +;This could be more refined + PUSHJ P,TMINIC ;Hit controller with hammer + PUSHJ Q,MGGXPT ;Set up transport again + SETO A, + IOWRI A,%TMFC ;1 record + MOVEI A,%TM1IE\%TMSPR ;Space backwards command + IOWRI A,%TMCS1 ;Do it + PUSHJ Q,MGWTJD ;Wait till finished + JRST MGERR ;Give up if error +];IFN TM03S + MOVE B,LMIOWD ;Get IOWD from last command + JRST MGRD1 ;Try operation again + + +SUBTTL MAG TAPE PI LEVEL SPACING COMMANDS +;Space forward and space reverse are completely under conditionals + +IFN TM03S,[ + +;Space forward MGSPCD(W) records +MGSPCF: PUSHJ Q,MGGXPT ;Acquire transport + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + MOVEM W,MGUNIT ;Note active transport + MOVN A,MGSPCD(W) ;Get -count + IOWRI A,%TMFC ;Tell controller + MOVEI A,%TMSPF ;Get command + TXO A,%TM1IE ;Turn on interrupts + IOWRI A,%TMCS1 ;Start controller + PUSHJ Q,MGWTJD ;Wait till command completes + IFNSK. ;Error? + TTNE CS1,%TM1MP ;Control parity err? + JRST MGERR ;Yes, nothing else valid + TTNE FS,%TMSES ;Formatter errors? + IFSKP. + PUSHJ P, TMINIC ;No formatter errors, ignore RH errors + ELSE. + TTNN ERR,%TMEFC ;Frame count error? + JRST MGERR ;Nope, must be important + PUSHJ P,TMINIC + ENDIF. + ENDIF. + POPJ Q, + +;Space forward record +MGSPFR: MOVEI B,1 ;Do one record + MOVEM B,MGSPCD(W) ;Set count + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCF ;Do spacing op + TTNN FS,%TMSTM + SETZB B,MGEOFR(W) ;Count EOFs since last record. None here + TTNE FS,%TMSTM + AOS B,MGEOFR(W) ;Saw one. + CAIL B,2 ;Saw two? + JRST MGSPRR ;Back up over last one... + JRST MGCMDR ;Clean up and leave + +;Space forward file +MGSPFF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF + TDZE B,MSRAC(W) + JRST MGCMDR ;EOF already read during the read, done + MOVEI B,1 ;Do one record + MOVEM B,MGSPCD(W) ;Set count + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCF ;Space forward one record + TTNN FS,%TMSTM + IFSKP. ;Saw a TM + AOS B,MGEOFR(W) ;Saw one. + CAIL B,2 ;Saw two? + JRST MGSPRR ;Yes, back up over last one, and leave + JRST MGCMDR ;No, OK, but we're done + ENDIF. + SETZB B,MGEOFR(W) ;No tape mark, reset count of EOFs seen +MGSPF1: MOVEM B,MGSPCD(W) ;Set count to 0 (B zero from above) + PUSHJ Q,MGSPCF ;Do it + TTNE FS,%TMSTM ;Saw a EOF? + IFSKP. ;No.. + TTNE FS,%TMSET ;Saw an EOT? + JRST MGERR ;Really shouldn't happen + JRST MGSPF1 ;Else go look for TM again + ENDIF. + AOS MGEOFR(W) ;Saw one. + JRST MGCMDR ;EOF read. done + +;Space reverse MGSPCD(W) records +MGSPCR: PUSHJ Q,MGGXPT ;Set up transport and get status + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSBT ;At BOT? + POPJ Q, + MOVEM W,MGUNIT ;Save selected transport + MOVN A,MGSPCD(W) ;Get -count + IOWRI A,%TMFC ;Tell controller + MOVEI A,%TMSPR ;Space Reverse command + TXO A,%TM1IE ;Turn on interrupts + IOWRI A,%TMCS1 ;Start controller + PUSHJ Q,MGWTJD ;Wait till command completes + IFNSK. ;Error? + TTNE CS1,%TM1MP ;Control parity err? + JRST MGERR ;Yes, nothing else valid + TTNE FS,%TMSES + IFSKP. + PUSHJ P,TMINIC + ELSE. + TTNN ERR,%TMEFC ;Frame count error? + JRST MGERR ;Nope, must be important + PUSHJ P,TMINIC + ENDIF. + ENDIF. + POPJ Q, + +;Space reverse one record +MGSPRR: MOVEI B,1 + MOVEM B,MGSPCD(W) ;1 record + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCR + TTNE FS,%TMSTM ;Stopped on EOF? + SOSGE MGEOFR(W) ;Yes, one less EOF in front of us + SETZM MGEOFR(W) ;But never less than zero + JRST MGCMDR ;Leave through general exit + +;Space reverse fill +MGSPRF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF + TDNN B,MSRAC(W) + JRST MGSPR2 ;No, we can just do command +MGSPR1: MOVEI B,1 + MOVEM B,MGSPCD(W) + PUSHJ Q,MGSPCR ;Skip back 1 record, should backup over EOF + TTNN FS,%TMSTM ;Tape mark seen? + JRST MGSPR1 ;Well, apparently not + MOVSI B,%MAESO + ANDCAM B,MSRAC(W) ;Turn off EOF-read-ahead flag +MGSPR2: SETZ B, + MOVEM B,MGSPCD(W) ;Space backwards the maximum number of records + PUSHJ Q,MGSPCR ;Do it + TTNN FS,%TMSBT ;BOT? + TTNE FS,%TMSTM ;Tape mark seen? + JRST MGCMDR ;Yes or Yes, all done + JRST MGSPR2 ;No, go back and try to find one. + +];End TM03S way back + + ;Rewind commands +; +MGRWND: +IFN TM10P,MOVEI B,MREWND ;Normal rewind +IFN TM03S,MOVEI B,%TMREW + CAIA +MGRWDM: +IFN TM10P, MOVEI B,MRWNDD ;Rewind and dismount +IFN TM03S, MOVEI B,%TMUNL + MOVEM B,MGSPCD(W) ;Set up command + PUSHJ Q,MGRWD1 ;Call action routine + JRST MGCMDR + +;Action routine for rewind commands +MGRWD1: PUSHJ Q,MGGXPT +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVEM W,MGUNIT + MOVE B,MGSPCD(W) ;Get desired command +IFN TM10P,[ + ADD B,MTCONO(W) + CONO MTC,(B) +] +IFN TM03S,[ + TXO B,%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD ;Start controller and wait till done + IFNSK. + TTNE FS,%TMSES + JRST MGERR ;Oops. + ENDIF. + SETZM MGEOFR(W) ;Seen no EOFs since last record + +;Here after rewind command has started. +; Two possibilities: Tape is rewound already, or controller is finished +; but tape is still rewinding. +IFN TM10P,[ +MGRWD2: TXNN J,%T1SRW ;Slave still rewinding tape? + JRST MGRWD3 ;No, at BOT + PUSHJ Q,CPOPJ ;Wait some. + CONI MTS,J ;Get status again + MOVEM J,MGCMTS(W) ;Update in memory + JRST MGRWD2 ;Go see if we're done yet. + +;Here when tape has rewound +MGRWD3: MOVE T,TIME ;Wait 1 second more + ADDI T,30. ;This is an attempt to fix a hardware bug + MOVEM T,MGJDTI +MGRWD4: MOVE T,TIME + CAML T,MGJDTI ;Check time + JRST MGRWD5 ;Finished waiting, go clean up + PUSHJ Q,CPOPJ ;No, wait some more + JRST MGRWD4 + +MGRWD5: MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved + SETZM MGJDTI ;Clear timeout + POPJ Q, +];IFN TM10P +IFN TM03S,[ +;This could be a lot smarter; should dismiss the command completely +; after rewind is started, and just scan for rewinding transports +; when a SSC interrupt is received. This change is also necessary +; to make multiple slaves work right; currently the rewinding unit +; holds active unit (MGUNIT) until the rewind is completed. +MGRWD2: TTNN FS,%TMSPP ;Transport still rewinding? + JRST MGRWD3 ;No, go finish up + PUSHJ Q,CPOPJ ;Dismiss interrupt, wait a while + PUSHJ Q,MGGXPT ;Get right slave, set up status + JRST MGRWD2 + +MGRWD3: MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved + POPJ Q, +];IFN TM03S + +;SKIP TO LOGICAL EOT +; +MGSEOT: PUSHJ Q,MGGXPT ;Get transport +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW ;Hung or rewinding? + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVEM W,MGUNIT ;Set active unit +IFN TM10P,TXNE J,%T1SBT ;BOT? +IFN TM03S,TTNE FS,%TMSBT + JRST MGVTCK ;Yep, do virgin tape check + +;Not at BOT +; Do we have enough CONDITIONALS yet? +MGNVT: +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get CONO word + IFN TM10A,[ + PUSHJ Q,MGDCSO + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;Tell it to move one record + ] + IFN TM10B,SETZM MIOWD + CONO MTC,MSPRR(B) ;Space reverse first +];IFN TM10P +IFN TM03S,[ + SETO B, ;Space backwards one record + IOWRI B,%TMFC + MOVEI B,%TMSPR\%TM1IE + IOWRI B,%TMCS1 +];IFN TM03S + PUSHJ Q,MGWTJD ;Wait till done + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + SETZM MGEOFR(W) + AOS MGEOFR(W) ;Claim to have seen one EOF +MGEOT2: +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTC,MSPFF(B) ;Skip forward to EOF + PUSHJ Q,MGWTJD + JRST MGERR +] +IFN TM03S,[ + AOS MSCMDC(W) ;Kludge so MGSPFF will return here. + PUSHJ Q,MGSPFF ;Space forward file +] + MOVSI B,%MAETR ;See if we hit real EOT +IFN TM10P, TXNE J,%T1SET +IFN TM03S, TTNE FS,%TMSET + IORM B,MSRAC(W) ;Yep, tell MP +IFN TM10P,[ + MOVE B,MTCONO(W) + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;One record + ] + IFN TM10B,SETZM MIOWD + CONO MTC,MSPFR(B) ;Space forward one record +] +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC + MOVEI B,%TMSPF\%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI B,%MAETR ;Check for real EOT again +IFN TM10P,TXNE J,%T1SET +IFN TM03S,TTNE FS,%TMSET + IORM B,MSRAC(W) +IFN TM10P,TXNN J,%T1SEF ;Is this another EOF? +IFN TM03S,TTNN FS,%TMSTM ;(i.e. a tape mark) + JRST MGEOT2 ;No, not at logical EOT. Go try again +IFN TM10P,[ + MOVE B,MTCONO(W) ;Yes, at logical EOT, Back up over 1 EOF + CONO MTC,MSPRF(B) ;Space back one file +] +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC + MOVEI B,%TMSPR\%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI B,%MAEOF+%MAETR ;Tell MP at EOF, EOT + IORM B,MSRAC(W) + JRST MGCMDR + +;Check for virgin tape +MGVTCK: MOVE T,TIME + ADDI T,60. ;Set a two second timeout + MOVEM T,MGEOTT(W) ; before we must see an EOT +IFN TM10P,[ + IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] + ] + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO + ] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ;Read record. will time out if no EOF marks +MGVTC1: CONI MTS,J + MOVEM J,MGCMTS(W) + TXNE J,%T1SJD ;Job done? + JRST MGNVT ;Yep, not virgin tape + TXNE J,%T1STH\%T1SIO ;Transport hung or illegal operation? + JRST MGERR ;Yes, give up + MOVE T,MGEOTT(W) ;Get the timeout value + CAMG T,TIME ;Time up? + JRST MGVT ;Yes, it's a new tape + PUSHJ Q,CPOPJ ;Wait a while + JRST MGVTC1 ;Go back and check again +];IFN TM10P +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC ;Do one record + MOVEI B,%TMSPF\%TM1IE ;Space forward command + IOWRI B,%TMCS1 + +MGVTC1: IORDI T,%TMCS1 ;Get status + TXNN T,%TM1GO ;Still going? + IFSKP. ;Yep. + MOVE T,MGEOTT(W) ;Get the timeout value + CAMG T,TIME ;Time up? + JRST MGVT ;Yes, it's a new tape + PUSHJ Q,CPOPJ ;Wait a while + JRST MGVTC1 ;Go back and check again + ENDIF. + TXNE T,%TM1TE\%TM1MP ;Controller error? + JRST MGERR ;Yes, bad + IORDI T,%TMFS ;Get formatter status + TXNE T,%TMSES ;Formatter error? + JRST MGNVT ;No error, not a new tape + IORDI T,%TMERR ;Get formatter error register + TXNE T,%TMEFC ;Frame Count error? + JRST MGNVT ;Yes, that is probably an OK tape + JRST MGERR ;Not FC, must be a real problem +];IFN TM03S + +;Virgin tape. Abort operation in progress, rewind tape +MGVT: +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTS,31 ;Clear controller + CONO MTC,MNOPIN(B) ;Start new command to clear things out + PUSHJ Q,MGWTJD + JFCL ;Ignore errors +] +IFN TM03S,[ + PUSHJ P,TMINIC +] +IFN TM10P,MOVEI B,MREWND ;Do a rewind +IFN TM03S,MOVEI B,%TMREW + MOVEM B,MGSPCD(W) + PUSHJ Q,MGRWD1 + SETZM MGEOFR(W) ;No EOFs seen + AOS MGEOFR(W) ;??? + JRST MGCMDR ;Done + +;Write EOT mark (two EOF's) on tape +; +MGMEOT: PUSHJ Q,MGGXPT +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +];IFN TM03S + MOVEM W,MGUNIT ;Note active unit + SKIPE MTCEFW(W) ;Check # of EOF's already written + IFSKP. ;None. Need to write two + AOS MSCMDC(W) ;Kludge so MGWEOF will return here. + AOS MTCEFW(W) ;Increment EOF count + PUSHJ Q,MGWEOF ;Write an EOF + ENDIF. + MOVE A,MTCEFW(W) ;Get EOF count + SOSLE A ;Check for at least two EOF's written + IFSKP. ;No, need one more on tape + AOS MSCMDC(W) ;Again, force MGWEOF to return + AOS MTCEFW(W) ;Incr EOF count + PUSHJ Q,MGWEOF ;Write EOF + ENDIF. + MOVE A,MSRAC(W) ;Get transport software status + TLNE A,%MANWT ;Are we supposed to back up over last EOF? + IFSKP. + AOS MSCMDC(W) ;Yes. Force MGSPRF to return, then... + PUSHJ Q,MGSPRF ; ...do space reverse file command + ENDIF. + MOVSI A,%MANWT ;Note what we've done + IORM A,MSRAC(W) + JRST MGCMDR ;Leave through general exit routine + +;Write one EOF mark on tape +; +MGWEOF: PUSHJ Q,MGGXPT ;Set up transport for IO +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR ; ..lose +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +] + MOVEM W,MGUNIT ;Remember active unit +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get CONO word for this unit + CONO MTC,MWEOF(B) ;Execute Write EOF function +] +IFN TM03S,[ + MOVEI B,%TM1IE\%TMWTM ;Write tape mark, enable interrupts + IOWRI B,%TMCS1 ;Do it +] + PUSHJ Q,MGWTJD ;Wait around till command is complete + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI A,%MAMSO + IORM A,MSRAC(W) ;Note tape movement in software status + JRST MGCMDR ;Return through general exit routine + +;Get transport and controller status +; +MGSTAT: PUSHJ Q,MGGXPT + JRST MGCMDR + +;Write some blank space +; +MGW3IN: PUSHJ Q,MGGXPT +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +];IFN TM03S + MOVEM W,MGUNIT ;Note active transport +IFN TM10P,[ +;TM10 can't just write blank space, it has to write blank space followed +; by a data record + IFN TM10B,[ + SETZM MIOWD ;Tell TM10 to write 1-word record + DATAO MTS,[MICWA] + ] + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] ;1-word record + MOVEM A,MIOWD + PUSHJ Q,MGDCSO + ] + MOVE B,MTCONO(W) + CONO MTC,MW3IN(B) ;Write date record preceeded by 3-in gap +];IFN TM10P +IFN TM03S,[ + MOVEI B,%TM1IE\%TMER3 ;Erase 3 inches command, enable interrupts + IOWRI B,%TMCS1 ;Do it +];IFN TM03S + PUSHJ Q,MGWTJD ;Wait... + JFCL ;Ignore errors (really should check kind) +IFN TM10P,JRST MGSPRR ;Now space record reverse over the bogus record +IFN TM03S,JRST MGCMDR ;TM03 does it right + + +SUBTTL .MTAPE UUO + +;.MTAPE AC, +; AC/ CHNM,,COMMAND +; COMMAND/ COUNT,,FUNCTION + +;Called with J/ AC field from UUO + +AMTAPE: XCTR XR,[HLRZ R,(J)] ;Get IO channel from user + TRNE R,-NIOCHN ;Legal channel? + JRST ILUUO ;Lose + HRRZM R,UUAC(U) ;Cause errors to report on the correct channel + ADDI R,IOCHNM(U) ;Form IOCHNM pointer + HRRZ A,(R) ; A: CLSTB/IOTTB index + CAIL A,MTUAIX ; Min index for tape + CAILE A,MTBOX ; Max + POPJ P, ; Laconic error reportage. + LDB W,[MTXP(R)] ;Get transport number + CAME U,MTUSR(W) ;Same user? + POPJ P, ;No, give up + UMOVE A,(J) ;Get Channel,,Command from user + MOVEM A,MTMTAP(W) ;Save it + HRRZS A ;Get user address of Count,,Function word + PUSHJ P,MTIECK ;Check transport for error states + UMOVE A,(A) ;Get Count,,Function from user + HRRZM A,MTMFNC(W) ;Store function + HLREM A,MTMCNT(W) ; and count + SKIPN MTMCNT(W) ;Count of zero always means one, for + AOS MTMCNT(W) ; compatibility with the old code. + HRRZS A ;Just Function + CAIL A,NMTAPC ;Command in range? + POPJ P, ;No... + AOS (P) ;Command OK, skip return + JRST @MTAPDT(A) ;Go do command + +MTAPDT: MTHANG ;0 Hang till tape motion done + MTRWND ;1 Rewind + MTRWDM ;2 Rewind and dismount + MTWEOR ;3 Write EOR if appropriate + MTW3IN ;4 Write 3 inches of blank tape + MTWEOF ;5 Write EOF + MTSPR ;6 Space records + MTSPF ;7 Space files + MTSPEOT ;10 Space to EOT + MTSTOP ;11 Abort all operations immediately + MTSBKS ;12 Set block size (to COUNT) + MTRBKS ;13 Read block size (to AC) +IFN 0,[ + MTRTSW ;14 Read Transport Information (to AC) + MTRTEW ;15 Read Tape Error Word (to AC) +] +NMTAPC==.-MTAPDT + +;Set block size for write +; +MTSBKS: MOVE A,MTMCNT(W) ;Desired blocksize + CAIL A,4 ;Check reasonableness + CAILE A,2000 + SOSA (P) ;Fail if too big or too small + MOVEM A,MTBLKS(W) ;OK, change write-buffer size + POPJ P, + +;Read current write blocksize +; +MTRBKS: MOVE A,MTBLKS(W) ;Get current write block size + JRST APTUAJ ;Return it + +;Hang until all motion finished +; +MTHANG: SKIPLE MSCMDC(W) ;Check count of queued commands + PUSHJ P,UFLS ;Wait if there are any + JRST MTIECK ;Done, check for errors and return + +;Rewind, Rewind and dismount +; +MTRWND: SKIPA B,[MGRWND] ;Get "REWIND" PI level command +MTRWDM: MOVEI B,MGRWDM ; or "REWIND and DISMOUNT" if appropriate + SKIPE MSCRW(W) ;Writing? + JRST MTSOSP ;Yes, error. Go undo skip rtn and exit + MOVSI A,%MAREW ;Note rewinding in software status + IORM A,MSRAC(W) + JRST MTCMD ;Go queue command for PI level + + +;"Write End of Record" +; This is really the FORCE system call, or should be. +; +MTWEOR: SKIPG MTMDN(W) ;MP level have an active buffer? + POPJ P, ;No, nothing to do + SKIPE MSCRW(W) ;Writing? + JRST MTWBFD ;Yes, go write buffer to tape +MTSOSP: SOS (P) ;Not writing, error. Undo skip return + POPJ P, ;Return + +;Write EOF +; +MTWEOF: SKIPN MSCRW(W) ;Writing? + JRST MTSOSP ;No, can't write EOF. Take error exit + PUSHJ P,MTWEOR ;Flush current buffer, if any + MOVEI B,MGWEOF ;Get PI level EOF routine + AOS MTCEFW(W) ;Increment count of EOF's written + MOVSI TT,%MANWT ;Flag something written on tape + ANDCAM TT,MSRAC(W) + JRST MTCMD ;Queue MGWEOF command for PI level + +;Write blank tape +; +MTW3IN: SKIPN MSCRW(W) ;Error if tape not open for write + JRST MTSOSP + MOVEI B,MGW3IN ;Get PI level command + SETZM MTCEFW(W) ;No EOF's since last record + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) ;Note written something to tape + JRST MTCMD ;Go queue command for PI + +;Space records, +=forward, -=back +; +MTSPR: SKIPE MSCRW(W) ;Not allowed if writing + JRST MTSOSP + PUSHJ P,MTFLRA ;Flush read-ahead, find out how far off we are + ADD B,C ;Get records tape is ahead of user (EOF=record) + MOVNS B ;Subtract this from user's request + ADDB B,MTMCNT(W) ;Adjust count + JUMPE B,CPOPJ ;If count is now zero, we are done +MTSPR1: PUSHJ P,MTCNTR ;Update user's copy in case PCLSR + JUMPG B,MTSPFR ;Space forward + MOVEI B,MGSPRR ;Get SPACE REVERSE command + PUSHJ P,MTCMD ;Queue it + AOSGE B,MTMCNT(W) ;Increment count, check if done + JRST MTSPR1 ;More + POPJ P, ;No more + +MTSPFR: MOVEI B,MGSPFR ;Get SPACE FORWARD command + PUSHJ P,MTCMD ;Queue it + SOSLE B,MTMCNT(W) ;Decr count, check if done + JRST MTSPR1 ;More + POPJ P, + +;This routine flushes readahead. Call before doing a spacing operation +; this doesn't actually undo the effect on the drive of the read-ahead. +; It does make sure that read-ahead's effect can't change, then returns +; in B the number of records ahead (non-negative) and in C the number of +; EOF's ahead (0 or 1). If called twice it will return zero the second +; time. Be sure to update your parameters. +; +MTFLRA: PUSHJ P,MTCNTR ;Make sure user space is writable first + MOVSI B,%MASTP + MOVSI T,%MARAC + IORM B,MSRAC(W) ;Tell PI-level read routine to stop reading + TDNE T,MSRAC(W) ;Wait until PI level actually stops + PUSHJ P,UFLS + ANDCAM B,MSRAC(W) ;Turn off %MASTP, things are now quiet + SKIPLE MSCMDC(W) ;Make sure PI level is completely inactive + PUSHJ P,UFLS ;Wait if necessary + MOVE B,MSNBOL(W) ;Get # bufs on read list (='s # records ahead) + LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 if EOF read ahead + MOVSI T,%MAEFA ;Clear read-ahead EOF + ANDCAM T,MSRAC(W) + JRST MTCBFF ;Go flush read-ahead buffers + +;Space files, + = forward, - = back +MTSPF: SKIPE MSCRW(W) ;Not allowed if writing + JRST MTSOSP + PUSHJ P,MTFLRA ;Flush read-ahead + MOVN B,C ;Number of files tape is ahead of user + ADDB B,MTMCNT(W) ;Adjust desired count + JUMPE B,CPOPJ ;If now zero we are done +MTSPF1: PUSHJ P,MTCNTR ;Update user's count in case of PCLSR + JUMPG B,MTSPFF ;Go do forward if needed + MOVEI B,MGSPRF ;Get space reverse file command + PUSHJ P,MTCMD ;Queue it + AOSGE B,MTMCNT(W) ;Done? + JRST MTSPF1 ;Nope + POPJ P, + +MTSPFF: MOVEI B,MGSPFF ;Get space forward file command + PUSHJ P,MTCMD ;Do it + SOSLE B,MTMCNT(W) ;Count down + JRST MTSPF1 ; till done + POPJ P, + +;Update user's FUNCTION,,COUNT word in case he's PCLSR'd +; +MTCNTR: HRRZ A,MTMTAP(W) + MOVE T,MTMFNC(W) + HRL T,MTMCNT(W) + XCTR XW,[MOVEM T,(A)] + POPJ P, + +;Get Controller status words to I,J +; +MTSTAT: SKIPLE MSCMDC(W) ;Wait till commands queued to PI level are done + PUSHJ P,UFLS + MOVEI B,MGSTAT ;GET STATUS command + PUSHJ P,MTCMD ;Give to PI + SKIPLE MSCMDC(W) ;Wait till done + PUSHJ P,UFLS + MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) + POPJ P, + +;Go to EOT +; +MTSPEOT:MOVEI B,MGSEOT ;Get SPACE-TO-LOGICAL-EOT command + JRST MTCMD ;Queue it. Note read-ahead doesn't matter here + +;Stop whatever we are doing right now +; Very brute-force - throws away all pending commands, read-ahead buffers, etc. +; +MTSTOP: CONO PI,UTCOFF ;We are going to mess with buffer lists + SETZM MSCMDC(W) ;Poof, no more commands + MOVE Q,[-MGQDLL,,MGQD0-1] ;Reset Q PDL pointer to base of stack + MOVE T,MSLCTB + IMUL T,W + ADD Q,T + MOVEM Q,MGQDLP(W) + MOVE Q,[-MSCBL-1,,MSCB0-1] ;Reset command queue input pointer + ADD Q,T + MOVEM Q,MTCMBP(W) + MOVE Q,[4400,,MSCB0-1] ;Reset command queue output pointer + ADD Q,T + MOVEM Q,MGCMBP(W) + SKIPL A,MTMDN(W) ;Buffer active at MP level? + PUSHJ P,IMEMR ;Yes, release it + SETOM MTMDN(W) ;No buffer active at MP level + SETZM MSMPRP(W) ;Zero MP pointer into current buffer + SETZM MSMPRC(W) ;Zero count of available words in buffer + PUSHJ P,MTCBFF ;Flush any buffers queued for PI level + CAME W,MGUNIT ;Is interrupt level waiting for this unit? + JRST UTCONJ ;No, all set + SETOM MGUNIT ;Yes, say no unit waiting for interrupt. + ;(Makes interrupt go away w/out doing anything) +IFN TM10P,[ + CONI MTC,I ;See what drive controller thinks it's using + LDB B,[MUNITF,,I] + CAME W,B ;Same as the drive we're clearing? + JRST UTCONJ ;If not same unit, don't do anything + MOVE B,MTCONO(W) ;Yes, abort operation in progress + CONO MTS,31 ;Stop the tape + CONO MTC,(B) ;Clear interupts +];IFN TM10P +IFN TM03S,[ + IORDI B,%TMTC + ANDI B,7 ;Get selected transport + CAME W,B ;Same? + JRST UTCONJ + PUSHJ P,TMINIC ;Yes, go reinit controller +];IFN TM03S + SKIPGE A,MGCABN(W) ;Any buffers active at PI level? + JRST UTCONJ ;No + PUSHJ P,IMEMR ;Yes, return buffer to system + SETOM MGCABN(W) ;Say no buffer active at PI level + JRST UTCONJ ;Leave + + + + diff --git a/src/system/rh10.defs26 b/src/system/rh10.defs26 new file mode 100755 index 00000000..15f68e27 --- /dev/null +++ b/src/system/rh10.defs26 @@ -0,0 +1,230 @@ +.AUXIL + +;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. +;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. + +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +];IF Not DEFined DEFSYM +.ELSE $$TEMP==0 + + +;DISK PHYSICAL PARAMETERS (RH10 CONTROLLER) + +DEFSYM NCYLS==406. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS==411.-NCYLS ;# CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==19. ;# TRACKS/CYLINDER +DEFSYM NSECS==20. ;# SECTORS/TRACK +DEFSYM SECBLK==8 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ;# BLOCKS/CYLINDER +DEFSYM NBLKS==NCYLS*NBLKSC ;# BLOCKS NORMALLY USED +DEFSYM XBLKS==XCYLS*NBLKSC ;# BLOCKS FOR HACKS +DEFSYM TBLKS==NBLKS+XBLKS ;TOTAL BLOCKS + +DEFSYM NTUTBL==2 ;2 BLOCKS PER TUT +DEFSYM DECADE==NBLKSC ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + ;DECADE SIZE = CYLINDER SIZE FOR KLFEDR'S SAKE +DEFSYM DSK=270 ;I/O DEVICE NUMBER OF RH10 + +;CONI - LEFT HALF (ERROR BITS ONLY) + +DEFSYM %HID22==4000,, ;4.3 1=>22-BIT DATA CHANNEL, 0=>18-BIT +DEFSYM %HIILF==400,, ;3.9 ILLEGAL FUNCTION CODE IN CONTROL REGISTER +DEFSYM %HISDE==200,, ;3.8 SELECTED DRIVE PREVIOUS ERROR NOT RESET +DEFSYM %HIDPE==4,, ;3.3 CHANNEL DATA PARITY ERROR +DEFSYM %HICPE==2,, ;3.2 CHANNEL CONTROL WORD PARITY ERROR +DEFSYM %HINXM==1,, ;3.1 CHANNEL NXM ERROR + +;CONI - RIGHT HALF + +DEFSYM %HIBPE==400000 ;2.9 DATA BUSS PARITY ERROR +DEFSYM %HIEXC==200000 ;2.8 "EXCEPTION" IN DRIVE DURING DATA TRANSFER +DEFSYM %HICER==100000 ;2.7 CHANNEL ERROR (OR OF 3 BITS IN LH) +DEFSYM %HICWW==040000 ;2.6 CONTROL WORD HAS BEEN WRITTEN +DEFSYM %HIOVR==020000 ;2.5 OVER-RUN (MEMORY DATA LATE) +DEFSYM %HIDRE==010000 ;2.4 DRIVE RESPONSE ERROR - NO RESPONSE FROM DRIVE +DEFSYM %HIILC==004000 ;2.3 ILLEGAL COMMAND OR REGISTER ACCESS ERROR +DEFSYM %HIPWR==002000 ;2.2 POWER FAIL +DEFSYM %HICOV==000200 ;1.8 CONTROL BUS OVER-RUN +DEFSYM %HIRAE==000100 ;1.7 REGISTER ACCESS ERROR (ONLY IF INTR ENB) +DEFSYM %HIATN==000040 ;1.6 ATTENTION (INTERRUPTS) +DEFSYM %HIBSY==000020 ;1.5 CONTROL BUSY WITH DATA TRANSFER +DEFSYM %HIDON==000010 ;1.4 DATA TRANSFER DONE, NORMAL OR ERROR + ;1.1-1.3 PIA AS USUAL +DEFSYM %HIERR==736300 ;CONI ERROR BITS + +;CONO + + ;2.7-2.9 CLEAR CORRESPONDING ERROR BITS +DEFSYM %HOWCW==040000 ;2.6 WRITE CONTROL WORD + ;2.3-2.5 CLEAR CORRESPONDING ERROR BITS +DEFSYM %HORST==002000 ;2.2 RESET THE CONTROLLER + ;1.8 CLEARS CORRESPONDING ERROR BIT +DEFSYM %HORAE==000100 ;1.7 ENABLE RAE TO INTERRUPT +DEFSYM %HOATN==000040 ;1.6 ENABLE ATTENTION TO INTERRUPT +DEFSYM %HOSTP==000020 ;1.5 STOP DATA TRANSFER, CLR BSY, SET DONE + ;1.4 CLEARS CORRESP BIT (DONE) + ;1.1-1.3 SET PIA +DEFSYM %HOCLR==734210 ;CONO TO CLEAR ALL ERROR BITS + +;CONTROLLER REGISTER NUMBERS (LH OF DATAO) + +DEFSYM %HRLOD==1_13 ;4.3 BIT TO SAY "LOAD SELECTED REGISTER" +DEFSYM %HRCTL==40_14 ;CONTROL REGISTER +DEFSYM $HCDRV==.BP <7,,> ;3.1-3.3 DRIVE SELECT FIELD +DEFSYM $HCICWA==.BP 077700 ;1.7-2.6 INITIAL CONTROL WORD ADDR + ;AS USUAL, 1.7 IS REALLY THE WRITE EVEN PARITY BIT + ;1.1-1.6 FUNCTION CODE (%HMxxx) AND GO BIT +DEFSYM %HRBUF==50_14 ;DATA BUFFER REGISTER (MAINTENANCE) +DEFSYM %HRIAD==44_14 ;INTERRUPT ADDRESS REGISTER + ;3.2 1=>KI-10 MODE, 0=>KA-10 MODE + ;1.1-1.9 9-BIT VECTOR ADDRESS (KI) +DEFSYM %HRRAE==54_14 ;REGISTER ACCESS ERROR REGISTER + ;DATAI 1.1-1.8 RAE DRIVE 0-7 + ;DATAO 1.1-1.8 CLEAR THAT BIT +DEFSYM %HRCBF==74_14 ;CHANNEL BUFFER + +;COMMANDS +; COMMANDS THAT DO I/O ARE PUT IN %HRCTL ALONG WITH $HCICWA +; OTHER COMMANDS ARE STORED INTO %HRDCL +; IN EITHER CASE $HCDRV SAYS WHICH DRIVE + +DEFSYM %HMNOP==0 ;NO OPERATION +DEFSYM %HMUNL==3 ;UNLOAD (DOES PACK FLY OFF?) +DEFSYM %HMREC==7 ;RECALIBRATE +DEFSYM %HMCLR==11 ;DRIVE CLEAR (RESET ERRORS ETC.) +DEFSYM %HMRLS==13 ;DRIVE RELEASE (DUAL PORT) +DEFSYM %HMSRC==31 ;SEARCH (FOR R.P.S.) +DEFSYM %HMWCH==51 ;WRITE CHECK -- DOESN'T WORK (DEC BRAIN DAMAGE) +DEFSYM %HMWCF==53 ;WRITE CHECK FORMAT (HEADER AND DATA) -- DOESN'T WORK +DEFSYM %HMWRT==61 ;WRITE DATA +DEFSYM %HMWHD==63 ;WRITE HEADER AND DATA (FORMAT THE PACK) +DEFSYM %HMRED==71 ;READ DATA +DEFSYM %HMRHD==73 ;READ HEADER AND DATA +DEFSYM %HMSEK==5 ;SEEK TO CYLINDER +DEFSYM %HMOFS==15 ;OFFSET HEADS SLIGHTLY +DEFSYM %HMCEN==17 ;RETURN HEADS TO CENTERLINE +DEFSYM %HMACK==23 ;ACKNOWLEDGE MOUNTING OF PACK (REQUIRED BEFORE I/O) +DEFSYM %HMRDP==21 ;"READ-IN PRESET" + +;STANDARD FIELDS IN DRIVE REGISTERS + + ;3.1-3.3 DRIVE NUMBER ($HCDRV) +DEFSYM %HDCBT==002000 ;4.2 CONTROL BUS TIMEOUT +DEFSYM %HDPAR==001000 ;4.1 MASS BUS CONTROL PARITY ERROR +DEFSYM %HDDLT==000400 ;3.9 DATA LATE (NEED 3 US BETWEEN DATAO AND DATAI) +DEFSYM %HDILC==000200 ;3.8 ILLEGAL COMMAND +DEFSYM %HDERR==003600 ;ALL BITS FOR ERRORS IN TALKING TO DRIVE + ;DRIVE-DEPENDENT DATA IS IN LOW 16 BITS (1.1-2.7) + +;DRIVE REGISTERS (NUMBER IN LH OF DATAO) + +DEFSYM %HRDCL==0_14 ;DRIVE CONTROL REGISTER + ;1.1-1.6 COMMAND (%HMxxx) 1.1=GO BIT +DEFSYM %HCDVA==1_11. ;2.3 DRIVE AVAILABLE + +DEFSYM %HRSTS==1_14 ;STATUS REGISTER + ;1.1-1.6 BITS ON DURING HEAD LOAD SEQUENCE +DEFSYM %HSVV==100 ;1.7 VOLUME VALID. SET BY %HMACK, CLEARED BY + ; DRIVE TURN ON. 0 => PACK MAY HAVE BEEN CHANGED +DEFSYM %HSRDY==200 ;1.8 DRIVE READY +DEFSYM %HSDPR==400 ;1.9 "DRIVE PRESET" = CONNECTED TO THIS CONTROLLER +DEFSYM %HSPGM==1000 ;2.1 "PROGRAMMABLE" = EITHER CTRLR CAN CONNECT +DEFSYM %HSLST==2000 ;2.2 LAST SECTOR TRANSFERRED +DEFSYM %HSWRL==4000 ;2.3 WRITE LOCK +DEFSYM %HSMOL==10000 ;2.4 MEDIUM ON-LINE +DEFSYM %HSPIP==20000 ;2.5 POSITIONING IN PROGRESS +DEFSYM %HSERR==40000 ;2.6 BIT ON %HRER1, %HRER2, OR %HRER3 +DEFSYM %HSATN==100000 ;2.7 ATTENTION - ERROR, POSITIONING COMPLETE, + ; STARTUP COMPLETE, OR DRIVE AVAILABLE + +DEFSYM %HRER1==2_14 ;ERROR REGISTER 1 + ;GENERALLY THESE BITS ARE ONLY RESET BY %HMCLR + ;1.1 ILLEGAL COMMAND IN %HRDCL + ;1.2 ATTEMPT TO ACCESS NON-EXISTENT DRIVE REGISTER + ;1.3 ATTEMPT TO WRITE IN DRIVE REGISTER WHILE DRIVE BUSY + ;1.4 PARITY ERROR ON MASSBUS + ;1.5 FORMAT ERROR (PACK & CPU NOT BOTH 16- OR BOTH 18-BIT) + ;1.6 WRITE CLOCK FAIL +DEFSYM %H1ECH==100 ;1.7 ECC HARD ERROR (NOT 11-BIT BURST) + ;1.8 HEADER COMPARE ERROR + ;1.9 HEADER CRC ERROR + ;2.1 ADDRESS OVERFLOW + ;2.2 INVALID ADDRESS +DEFSYM %H1WLK==4000 ;2.3 ATTEMPT TO WRITE WHILE WRITE-LOCKED + ;2.4 DRIVE TIMING ERROR. MAY DE-FORMAT THE TRACK. + ;2.5 OPERATION NOT COMPLETE (3 REVS NO ACTION) + ;2.6 DRIVE UNSAFE - WRITE LOCK OR FIELD SERVICE +DEFSYM %H1ECC==100000 ;2.7 DATA CHECK, ECC COMPUTATION INITIATED +DEFSYM %H1SOF==110730 ;SOFT ERRORS + +DEFSYM %HRMNT==3_14 ;MAINTENANCE REGISTER (SEE RP04 MAINT MANUAL) + +DEFSYM %HRATN==4_14 ;ATTENTION SUMMARY REGISTER (NOT REALLY PER-DRIVE) + ;1.1-1.8 %HSATN DRIVES 0-7 + ;CLEARED BY ACCESSING DRIVE OR WRITING A 1 + +DEFSYM %HRADR==5_14 ;DESIRED SECTOR/TRACK ADDRESS +DEFSYM $HATRK==.BP 17400 ;TRACK 0-22 OCTAL +DEFSYM $HASEC==.BP 37 ;SECTOR 0-23 OCTAL (128 WORDS EACH) + ;NOTE THESE FIELDS ARE 8-BITS EACH + +DEFSYM %HRLAH==7_14 ;LOOK AHEAD (READ ONLY) + ;NUMBER OF 64'THS OF A SECTOR + +DEFSYM %HRTYP==6_14 ;DRIVE TYPE (RO) + ;1.1-1.9 DRIVE TYPE NUMBER (20 FOR "RP04") + ;2.3 DUAL-PORT DRIVE + ;2.5 MOVING HEAD + ;2.6 TAPE + ;2.7 NOT BLOCK ADDRESSED + +DEFSYM %HRSER==10_14 ;DRIVE SERIAL NUMBER (RO) + +DEFSYM %HROFS==11_14 ;HEAD OFFSET + ;1.1-1.8 OFFSET CODE + ;1.9-2.7 MISC CRUFTIES + +DEFSYM %HRCYL==12_14 ;DESIRED CYLINDER ADDRESS + ; 0 TO 410 DECIMAL + +DEFSYM %HRCCY==13_14 ;CURRENT CYLINDER ADDRESS + +DEFSYM %HRER2==14_14 ;ERROR REGISTER 2 + ;MISC UNSAFE CONDITIONS IN DRIVE + +DEFSYM %HRER3==15_14 ;ERROR REGISTER 3 + ;1.1-1.7 MORE MISC UNSAFES IN DRIVE +DEFSYM %H3SKI==40000 ;2.6 SEEK INCOMPLETE +DEFSYM %H3OFC==100000 ;2.7 OFF CYLINDER + +DEFSYM %HRPOS==16_14 ;ECC POSITION + ;LOCATION OF ERROR BURST WITHIN SECTOR + +DEFSYM %HRPAT==17_14 ;ECC PATTERN + ;11-BIT ERROR BURST + +;DF10-C CHANNEL DEFINITIONS (22-BIT- (KI-) MODE) + +DEFSYM $DFCAD==002600,, ;CURRENT ADDRESS - 1 (IN CONTROL WORD) +DEFSYM $DFWC==261600,, ;- WORD COUNT (IN CONTROL WORD) +DEFSYM $DFLAD==002600,, ;LAST DATA ADDRESS (IN STORED CONTROL WD) +DEFSYM $DFCWA==261600,, ;LAST CONTROL WORD ADDRESS (IN STORED CONTROL WORD) + + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rh11.defs48 b/src/system/rh11.defs48 new file mode 100755 index 00000000..f3d1b631 --- /dev/null +++ b/src/system/rh11.defs48 @@ -0,0 +1,289 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; For now, must have a disk type defined to get the correct register +; definitions. + +IFNDEF RP06P,RP06P==0 +IFNDEF RP07P,RP07P==0 +IFNDEF RM03P,RM03P==0 +IFNDEF RM80P,RM80P==0 + +IFN RP06P+RP07P+RM03P+RM80P-1,.FATAL Only one disk type allowed in RH11 DEFS + + +;;; Disk RH11 Interrupt vector: +DEFSYM PHVEC==254 ; Interrupts occur on level 6 + ; (high priority) on UBA #1. + +;;; Disk RH11 Unibus register addresses: + +DEFSYM %HRCS1=:776700 ;CTRL AND STATUS 1. + DEFSYM %HXSC== 1_15. ; Special Condition + DEFSYM %HXTRE==1_14. ; Transfer Error + DEFSYM %HXMCP==1_13. ; Mass I/O Control Bus Parity Error + DEFSYM %HXDVA==1_11. ; Drive Available + DEFSYM %HXPSE==1_10. ; Port Select + DEFSYM %HXA17==1_9. ; UB Address Extension Bit 17 + DEFSYM %HXA16==1_8. ; UB Address Extension Bit 16 + DEFSYM %HXRDY==1_7. ; Ready + DEFSYM %HXIE== 1_6. ; Interrupt Enable + DEFSYM $HXCMD==.BP 77 ; Bits 1-5 specify commands. + DEFSYM %HXGO== 1_0. ; GO bit + +;;; Commands with bit 0 (GO) included: + +DEFSYM %HMNOP==0 ; No Operation +DEFSYM %HMUNL==3 ; Unload ("Standby" -- the pack doesn't fly off). +DEFSYM %HMREC==7 ; Recalibrate +DEFSYM %HMCLR==11 ; Drive clear (reset errors etc.) +DEFSYM %HMRLS==13 ; Drive release (dual port) +DEFSYM %HMSRC==31 ; Search (for r.p.s.) +DEFSYM %HMWCH==51 ; Write Check (?doesn't work) +DEFSYM %HMWCF==53 ; Write Check Format, Header and Data (?doesn't work) +DEFSYM %HMWRT==61 ; Write Data +DEFSYM %HMRED==71 ; Read Data +DEFSYM %HMWHD==63 ; Write Header And Data (format the pack) +DEFSYM %HMRHD==73 ; Read Header and Data +IFN RP07P,[ +DEFSYM %HMWTD==65 ; Write Track Descriptor +DEFSYM %HMRTD==75 ; Read Track Descriptor +] +DEFSYM %HMSEK==5 ; Seek to Cylinder +DEFSYM %HMOFS==15 ; Offset Heads Slightly + ; Just sets %HSOFS on RP07 +DEFSYM %HMCEN==17 ; Return Heads To Centerline + ; Just clears %HSOFS on RP07 +DEFSYM %HMACK==23 ; Acknowledge mounting of pack (required before I/O) + ; No-op on RP07 +DEFSYM %HMRDP==21 ; Read-In Preset + +DEFSYM %HRWC=:776702 ;WORD COUNT. + +DEFSYM %HRBA=:776704 ;UNIBUS ADDRESS. + +DEFSYM %HRADR=:776706 ;DESIRED ADDRESS. + DEFSYM $HATRK==.BP 37400 ; Track + DEFSYM $HASEC==.BP 00177 ; Sector + ;; These are the sizes on the RP07 -- other drives are smaller. + ;; This is OK, as most places calculate this as Track_8+Sector + +DEFSYM %HRCS2=:776710 ;CTRL AND STATUS 2. + DEFSYM %HYDLT==1_15. ; Data Late + DEFSYM %HYWCE==1_14. ; Write Check Error + DEFSYM %HYPE== 1_13. ; Parity Error + DEFSYM %HYNED==1_12. ; Non-existant Drive + DEFSYM %HYNEM==1_11. ; %HRBA is NXM during DMA + DEFSYM %HYPGE==1_10. ; Program Error + DEFSYM %HYMXF==1_9. ; Missed Transfer + DEFSYM %HYMDP==1_8. ; Mass Data Bus Parity Error + DEFSYM %HYOR== 1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %HYIR== 1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %HYCLR==1_5. ; Controller Clear + DEFSYM %HYPAT==1_4. ; Parity Test + DEFSYM %HYBAI==1_3. ; Unibus Address Increment Inhibit + DEFSYM $HYDSK==.BP 7 ; Bits 2-0 are the Unit Select. + +DEFSYM %HRSTS=:776712 ;DRIVE STATUS. + DEFSYM %HSATN==1_15. ; Attention Active + DEFSYM %HSERR==1_14. ; Error + DEFSYM %HSPIP==1_13. ; Positioning In Progress + DEFSYM %HSMOL==1_12. ; Medium On-Line + DEFSYM %HSWRL==1_11. ; Write Locked + DEFSYM %HSLST==1_10. ; Last Sector Transferred + DEFSYM %HSPGM==1_9. ; Programmable + DEFSYM %HSDPR==1_8. ; Drive Present + DEFSYM %HSRDY==1_7. ; Drive Ready + DEFSYM %HSVV== 1_6. ; Volume Valid +; These are RP04-only bits in %HRSTS +; DEFSYM %HSDE1==1_5. ; Difference Equals 1 +; DEFSYM %HSL64==1_4. ; Difference Less Than 64 +; DEFSYM %HSGRV==1_3. ; Go Reverse +; DEFSYM %HSDIG==1_2. ; Drive To Inner Guard Band +; DEFSYM %HSF20==1_1. ; Drive Forward 20in/sec +; DEFSYM %HSF5== 1_0. ; Drive Forward 5in/sec +IFN RP07P,[ + DEFSYM %HSILS==1_2. ; Interleaved Sectors + DEFSYM %HSWRN==1_1. ; Early Warning + DEFSYM %HSOFS==1_0. ; Offset Mode +] + +DEFSYM %HRER1=:776714 ;ERROR 1. + DEFSYM %H1ECC==1_15. ; Data Check + DEFSYM %H1UNS==1_14. ; Unsafe + DEFSYM %H1OPI==1_13. ; Operation Incomplete + DEFSYM %H1DTE==1_12. ; Drive Timing Error + DEFSYM %H1WLK==1_11. ; Write Lock Error + DEFSYM %H1IAE==1_10. ; Invalid Address Error + DEFSYM %H1AOE==1_9. ; Address Overflow Error + DEFSYM %H1CRC==1_8. ; Header CRC Error + DEFSYM %H1HCE==1_7. ; Header Compare Error + DEFSYM %H1ECH==1_6. ; ECC Hard Error + DEFSYM %H1WCF==1_5. ; Write Clock Fail + DEFSYM %H1FER==1_4. ; Format Error + DEFSYM %H1PAR==1_3. ; Parity Error + DEFSYM %H1RMR==1_2. ; Register Modification Refused + DEFSYM %H1ILR==1_1. ; Illegal Register + DEFSYM %H1ILF==1_0. ; Illegal Function + +DEFSYM %HRATN=:776716 ;ATTENTION SUMMARY. + ; Each bit 7-0 corresponds to a drive asserting ATA. + +DEFSYM %HRLAH=:776720 ;LOOK AHEAD. + ; 2.2 - 1.7 Sector Count. + ; 1.6 - 1.5 Encoded Extension Field. + +DEFSYM %HRBUF=:776722 ;DATA BUFFER. + +DEFSYM %HRMNT=:776724 ;MAINTENANCE. + +DEFSYM %HRTYP=:776726 ;DRIVE TYPE. + ; 2.7 NOT BLOCK ADDRESSED + ; 2.6 TAPE + ; 2.5 Moving Head (better be a 1!!) + ; 2.3 Drive Request Required + ; 1.9 - 1.1 Drive Type Number: + ; RP04 = 20, RP05 = 21, + ; RP06 = 22, RM03 = 24, + ; RM80 = 26, RP07 = 42 + +DEFSYM %HRSER=:776730 ;SERIAL NUMBER. + +DEFSYM %HROFS=:776732 ;OFFSET. + ; 2.9-2.8 Unused + ; 2.7 Sign Change (RP06 only) + ; 2.7 Command Modifier (RP07 only) + ; Must be set before %HMWHD, %HMWTD or %HMRTD + ; 2.6 Move Track Descriptor (RP07 only) + ; 0 = 128. bit track descriptor + ; 1 = 344. bit track descriptor + ; 2.4 Format Bit (1=16, 0=18) + ; 2.3 ECC Inhibit + ; 2.2 Header Compare Inhibit + ; 2.1 Skip Sector Inhibit (RM 16bit only) + ; 1.9 Unused + ; + ; 1.8 - 1.1 Unused on RP07 + ; RP07 doesn't support offsets + ; + ; RP06 Offsets + ; 1.8 - 1.1 Offset Info + ; +400 u" 00010000 + ; -400 u" 10010000 + ; +800 u" 00100000 + ; -800 u" 10100000 + ; +1200 u" 00110000 + ; -1200 u" 10110000 + ; Centerline 00000000 + ; + ; RMxx Offsets + ; 1.1-1.7 Unused + ; 1.8 Offset Direction + ; 0 - Away from spindle + ; 1 - Towards spindle + +DEFSYM %HRCYL=:776734 ;DESIRED CYLINDER. + +IFN RP06P,[ + +DEFSYM %HRCCY=:776736 ;CURRENT CYLINDER. + +DEFSYM %HRER2=:776740 ;ERROR 2. + DEFSYM %H2NHS==1_10. ; No Head Selection + DEFSYM %H2WRU==1_8. ; Write Ready Unsafe + +DEFSYM %HRER3=:776742 ;ERROR 3. + DEFSYM %H3OFC==1_15. ; Off Cylinder + DEFSYM %H3SKI==1_14. ; Seek Incomplete (also sets UNS+ATA+PIP+RDY) + DEFSYM %H3DCL==1_6. ; DC power low (or perhaps AC?) + DEFSYM %H3ACL==1_5. ; AC power low (or perhaps DC?) + ; (the documentation is confused about + ; which is which.) + +];RP06P + +IFN RP07P,[ + +DEFSYM %HRCCY=:776736 ;CURRENT CYLINDER. + +DEFSYM %HRER2=:776740 ;ERROR 2. + DEFSYM %H2PRG==1_15. ; Program Error + DEFSYM %H2CRM==1_14. ; Control ROM parity error + DEFSYM %H2H88==1_13. ; 8080 in drive is hung + ;; DEC unimaginatively calls the following three bits + ;; READ/WRITE UNSAFE 1, 2 and 3. + DEFSYM %H2WU3==1_12. ; Write current when no write in progress + DEFSYM %H2WU2==1_11. ; More than one head selected + DEFSYM %H2WU1==1_10. ; No write transitions during a write + DEFSYM %H2WOV==1_9. ; Write Overrun + DEFSYM %H2WRU==1_8. ; Write Ready Unsafe + DEFSYM $H2COD==.BP 377 ; Error Code + ;; Error codes are: + ;; 012 Seek operation too long. + ;; 013 Guard band detected during seek operation. + ;; 014 Seek operation overshoot. + ;; 104 Guard band detection failure during recalibrate operation. + ;; 105 Reference gap or guard band pattern detection failure during + ;; recalibrate operation. + ;; 106 Seek error during recalibrate operation. + ;; 112 Heads have attempted to land on guard band during recalibrate + ;; operation. + +DEFSYM %HRER3=:776742 ;ERROR 3. + DEFSYM %H3BDS==1_15. ; Bad Sector + DEFSYM %H3SKI==1_14. ; Seek Incomplete (see error code in ER2) + DEFSYM %H3DSE==1_13. ; Defect Skip Error + DEFSYM %H3WCF==1_12. ; Write Current Failure + DEFSYM %H3LCF==1_11. ; Logic Control Failure + DEFSYM %H3LBC==1_10. ; Loss of Bit Clock + DEFSYM %H3LCE==1_9. ; Loss of Cylinder Error + DEFSYM %H3X88==1_8. ; 8080 in drive failed to respond to a command + DEFSYM %H3DCK==1_7. ; Device Check + DEFSYM %H3WHD==1_6. ; Index Unsafe (Bad %HMWHD) + DEFSYM %H3DCL==1_5. ; DC Low voltage + DEFSYM %H3SDF==1_4. ; Serdes Data (data buffer timing) Failure + DEFSYM %H3PAR==1_3. ; Data Parity Error during write operation + DEFSYM %H3SYB==1_2. ; Sync Byte error + DEFSYM %H3SYC==1_1. ; Sync Clock failure + DEFSYM %H3RTM==1_0. ; Run timeout + +];RP07P + +IFN RM03P\RM80P,[ +; RM has no Current Cylinder Register, the Error 2 Register is +; in a different place with different bits, and there is no +; Error 3 register + +DEFSYM %HRER2=:776742 ;ERROR 2. + DEFSYM %H2BSE==1_15. ; Bad Sector (sector marked bad on disk) + DEFSYM %H2SKI==1_14. ; Seek Incomplete (also sets UNS+ATA+PIP+RDY) + DEFSYM %H2OPE==1_13. ; Drive address plug was removed + DEFSYM %H2IVC==1_12. ; Invalid Command (really drive not valid) + DEFSYM %H2LSC==1_11. ; LSC Sucks + DEFSYM %H2LBC==1_10. ; Loss of Bitcheck (hardware lossage) + DEFSYM %H2DVC==1_7 ; Device Check (generic hardware lossage) + DEFSYM %H2SSE==1_5 ; Skip Sector found (can't happen in 18bit) + DEFSYM %H2DPE==1_3 ; Data Parity Error in controller + +];RM03P\RM80P + +DEFSYM %HRPOS=:776744 ;ECC POSITION. + +DEFSYM %HRPAT=:776746 ;ECC PATTERN. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rm03.defs5 b/src/system/rm03.defs5 new file mode 100755 index 00000000..2704e416 --- /dev/null +++ b/src/system/rm03.defs5 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RM03 + +DEFSYM NCYLS==820. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==823.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==5 ; # TRACKS/CYLINDER +DEFSYM NSECS==30. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 14814, so it takes 2 blocks to TUT an +; RM03. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==2 ; 2 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rm80.defs4 b/src/system/rm80.defs4 new file mode 100755 index 00000000..14b354c9 --- /dev/null +++ b/src/system/rm80.defs4 @@ -0,0 +1,45 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RM80 + +; The RM80 actually has 561 cylinders, but it appears that the onboard +; microprocessor diagnostics may scribble on the last two cylinders, so +; we just leave them out of this. + +DEFSYM NCYLS==556. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==559.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==14. ; # TRACKS/CYLINDER +DEFSYM NSECS==30. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 29172, so it takes 3 blocks to TUT an +; RM80. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==3 ; 3 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp06.defs1 b/src/system/rp06.defs1 new file mode 100755 index 00000000..11dd4dac --- /dev/null +++ b/src/system/rp06.defs1 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RP06 + +DEFSYM NCYLS==812. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==815.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==19. ; # TRACKS/CYLINDER +DEFSYM NSECS==20. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 38305, so it takes a little more than 3 +; blocks to TUT an RP06. This leaves plenty of room for the extra words at +; the beginning of the TUT. +DEFSYM NTUTBL==4 ; 4 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp07.defs1 b/src/system/rp07.defs1 new file mode 100755 index 00000000..222a2a64 --- /dev/null +++ b/src/system/rp07.defs1 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RP07 + +DEFSYM NCYLS==627. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==630.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==32. ; # TRACKS/CYLINDER +DEFSYM NSECS==43. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 108360, so it takes 9 blocks to TUT an +; RP07. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==9 ; 9 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp10.defs16 b/src/system/rp10.defs16 new file mode 100755 index 00000000..c5e0de32 --- /dev/null +++ b/src/system/rp10.defs16 @@ -0,0 +1,106 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + +;DISK PHYSICAL PARAMETERS + +DEFSYM NCYLS==200. ;# CYLINDERS NORMALLY USED (RP02) +DEFSYM MCYLS==400. ;# CYLINDERS NORMALLY USED (RP03) +DEFSYM XCYLS==3 ;# EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==20. ;# TRACKS/CYLINDER +DEFSYM NSECS==10. ;# SECTORS/TRK +DEFSYM SECBLK==8 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ;# BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ;TOTAL # REG BLKS (RP02) +DEFSYM MBLKS==MCYLS*NBLKSC ;TOTAL # REG BLKS (RP03) +DEFSYM XBLKS==XCYLS*NBLKSC ;# XTRA BLKS +DEFSYM TBLKS==MBLKS+XBLKS ;TOTAL BLKS + +DEFSYM NTUTBL==1 ;1 BLOCK PER TUT +DEFSYM DECADE==20. ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS +DEFSYM DPC==250 ;I/O DEVICE NUMBER + +;DISK COMMANDS + +DEFSYM DREADC==000000,, ;READ DATA +DEFSYM DWRITC==100000,, ;WRITE DATA + ;OP CODE 2 UNUSED +DEFSYM DWRITH==300000,, ;WRITE HEADER AND DATA (FORMAT PACK) +DEFSYM DSEEKC==400000,, ;POSITION HEADS +DEFSYM DEASEC==500000,, ;CLEAR ATTENTIONS +DEFSYM DNOOPC==600000,, ;SELECT DRIVE +DEFSYM DRCALC==700000,, ;RECALIBRATE DRIVE + +;BYTE POINTERS FOR ABOVE COMMANDS + +DEFSYM DUNFLD==360300,, ;UNIT FIELD (ALL COMMANDS) +DEFSYM DCYL==261000,, ;CYLINDER FIELD (READ,WRIT,WRITH,SEEK) +DEFSYM DCYLXB==200100,, ;EXTRA BIT OF CYLINDER FIELD FOR RP03 +DEFSYM DSURF==210500,, ;SURFACE FIELD (READ,WRIT,WRITH) +DEFSYM DSECT==140400,, ;SECTOR FIELD (READ,WRIT,WRITH) + + ;DATAI FIELDS + + +DEFSYM DUNFLI==410300,, ;UNIT FIELD +DEFSYM DCYLI==311000,, ;CYLINDER FIELD +DEFSYM DCYLXI==130100,, ;EXTRA BIT OF CYLINDER FIELD + +DEFSYM SKINC==100,, ;SEEK INCOMPLETE +DEFSYM ONCYL==40,, ;ON CYLINDER +DEFSYM ONLINE==20,, ;ON LINE +DEFSYM FUNSAF==10,, ;FILE UNSAFE +DEFSYM NSCHDR==4,, ;NO SUCH DRIVE +DEFSYM RDONLY==2,, ;READ ONLY +DEFSYM NOWRIH==1, ;WRITE HEADER LOCKOUT + +DEFSYM RP03BT==2000 ;SELECTED DRIVE IS AN RP03 +DEFSYM SECTI==140500,, + +DEFSYM ALLATT==776 + +;CONO INFORMATION + +DEFSYM DCLEAR==175710 ;CLEAR ALL ERROR CONDITIONS + + +;CONI INFORMATION + +DEFSYM PARER== 4000 +DEFSYM SRCER== 40000 +DEFSYM HRDER==130000 +DEFSYM PROER==402300 +DEFSYM WRTER== 1000 +DEFSYM ALLER==577300 +DEFSYM DONE==10 +DEFSYM BUSY==20 + +;DF10 CHANNEL INFORMATION + +DEFSYM $DFCAD==002600,, ;CURRENT ADDRESS - 1 (IN CONTROL WORD) + ;ALSO BITS 4.7-4.9 HAVE 1'S COMPLEMENT OF MA 3.1-3.3 +DEFSYM $DFWC==261600,, ;- WORD COUNT (IN CONTROL WORD) +DEFSYM $DFLAD==002600,, ;LAST DATA ADDRESS (IN STORED CONTROL WD) +DEFSYM $DFCWA==261600,, ;LAST CONTROL WORD ADDRESS (IN STORED CONTROL WORD) + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/salv.311 b/src/system/salv.311 new file mode 100755 index 00000000..0b55c2d9 --- /dev/null +++ b/src/system/salv.311 @@ -0,0 +1,6685 @@ +;;; -*- Mode:MIDAS -*- +.SEE COPY ;COPY BLOCK TO BLOCK +.SEE DUP ;DUPLICATE ENTIRE DISC PACK +.SEE TRAN ;LOAD FROM MAG TAPE UNIT 5 +.SEE UCOP ;COPY UDIRS FROM DRIVE TO DRIVE +.SEE ZAP ;ZERO DIR BLOCKS, WRITE OUT EMPTY TUT,MFD, WRITE READIN BLOCK +.SEE SPKID ;SET PACK ID IN TUT +.SEE DSKTST ;SIMPLE DISK TEST (WRITE THEN READ) +.SEE SEKTST ;DISK TEST WHICH SEEKS BACK AND FORTH (DOES NO WRITING) +.SEE MARK ;FORMAT PACK +.SEE MARK69 ;FINISH FORMATTING PACK +.SEE MFDR ;TRY TO RECONSTRUCT MFD FROM USER DIRS +.SEE CHKR ;SALVAGER +.SEE GOGO ;SALVAGER - (AUTO FOR ALL DRIVES) +.SEE GETSTS ;GET CONTROLLER AND CURRENT DRIVE STATUS +.SEE RDHEAD ;READ HEADER FROM TRACK +.SEE LISTF ;PRINT USER DIRECTORY ON LPTR +.SEE UNLOCK ;TEST & UNLOCK A BLOCK +.SEE REMAP ;REMAP PACK #S AND FIX UFDS + +.SEE PUNCH ;VARIABLE TO BE SET NON-ZERO IF COPYING OF TTY OUTPUT TO PAPER TAPE IS WANTED +.SEE HCRASH ;VARIABLE TO BE SET NON-ZERO IF DUP'ING A DISK AFTER HEAD CRASH +.SEE NOQUES ;IF NON-ZERO, NO QUESTIONS IN GOGOX MODE +.SEE FERRS ;COUNT OF CORRECTABLE ERRORS +.SEE CERRS ;COUNT OF ECC-CORRECTED ERRORS (RP04 ONLY) +.SEE DUPRER ;COUNT OF BLOCKS THAT COULDN'T BE READ IN `DUP' +.SEE DUPWER ;COUNT OF BLOCKS THAT COULDN'T BE WRITTEN IN `DUP' + +IF1, TITLE SALVATION +IF2,[ PRINTX/SALVATION / + .TYO6 .FNAM2 + PRINTX/ +/] + +DEFINE SUBTTL A/ +TERMIN + +;AC'S + +ZR=0 +A=1 +B=2 +C=3 +D=4 +N=5 +I=6 +Q=7 +H=10 +TT=11 +T=12 +W=13 +U=14 +J=15 +K=16 +P=17 + +SUBTTL CONFIGURATION + +DEFINE IFCE A,B +IFE SIXBIT/A/-SIXBIT/B/,TERMIN ;SUBSTITUTE FOR IFSE THAT IGNORES CASE + +;OPTIONS + +IF1,[ +PRINTX /Run under time-sharing? / +.TTYMAC TS + IRPS Z,,[YES Y AYE DA JA] + IFCE Z,TS,{ + ITS==1 + IRPS ZZ,,[DC10P RP10P RH10P OLPTP NLPTP TTLPTP KL10P] + ZZ==0 + TERMIN + .ISTOP + } + TERMIN +TERMIN + +IFNDEF ITS,[ ;run stand alone +ITS==0 +PRINTX /Which machine? / +.TTYMAC MCHN + IFCE MCHN,AIKA,[ + FIRSPK==1 ;first pack that must be mounted in gogo mode + LASTPK==5 ;last pack that must be mounted in gogo mode + NUDSL==440. + DC10P==1 + RP10P==0 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 ;R.I.P. + NLPTP==0 + TTLPTP==0 + TCMXH==55. + LIGHTS==4 ;PI + ];AIKA + IFCE MCHN,ML,[ + FIRSPK==2 + LASTPK==3 + NUDSL==250. + DC10P==0 + RP10P==1 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 + NLPTP==0 ;rest in pieces + TTLPTP==0 + TCMXH==55. + LIGHTS==4 ;PI + ];ML + IFCE MCHN,DM,[ + FIRSPK==17. + LASTPK==21. + NUDSL==200. + DC10P==0 + RP10P==1 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 + NLPTP==0 + TTLPTP==100 + TCMXH==55. + LIGHTS==4 ;PI + ];DM + IFCE MCHN,MC,[ + SA==105*2000 ; MC system is big, need to push SALV higher. + FIRSPK==0 + LASTPK==1 + NUDSL==500. + DC10P==0 + RP10P==0 + RH10P==1 + T300P==3 ;UNIT 3 IS FIRST T-300 UNIT + KL10P==1 + OLPTP==0 + NLPTP==0 + TTLPTP==0 ;NO LPT AT ALL + TCMXH==100. ;LA36 + LIGHTS==500 ;KL-UDGE + NDRIVE==6 ;8 DOESN'T FIT IN 128K + NUNITS==6 + ];KL +TERMIN +IFNDEF FIRSPK, .FATAL UNKNOWN MACHINE "MCHN" +];IFNDEF ITS + +;Formerly we knew number of units, now these are set to maximum and at run +; time we find out which units are present and on-line with the right packs. +IFNDEF NDRIVE, NDRIVE==8 ;# physical units +IFNDEF NUNITS, NUNITS==8 ;# virtual units + +IFE NUNITS-NDRIVE,[ ;Hack for virtual units in pre-Calcomp AI-KA system. + DEFINE UNTMES A/ + TYPE A + TERMIN +] +IFN NUNITS-NDRIVE,[ + DEFINE UNTMES A/ + DEFINE ZZQ UNIT + TYPE A + TERMIN + ZZQ [VIRTUAL UNIT] + TERMIN +] + +;MACROS FOR CONDITIONALIZATION + +DEFINE TS +IFN ITS!TERMIN + +DEFINE NTS +IFE ITS!TERMIN + +DEFINE DC +IFN DC10P!TERMIN + +DEFINE RP +IFN RP10P!TERMIN + +DEFINE RH +IFN RH10P!TERMIN + +DEFINE KA +IFE KL10P!TERMIN + +DEFINE KL +IFN KL10P!TERMIN + +DEFINE INSIRP I,[X] +IRPS Z,,X + I,Z +TERMIN +TERMIN + +DEFINE INFORM A,B,C,D,E,F,G +PRINTX \A!B!C!D!E!F!G +\ +TERMIN + +DEFINE CONC A,B +A!B!TERMIN + +DEFINE STRA C/ + MOVE A,[440700,,[ASCIZ \C\]] +TERMIN + +DEFINE LPR B/ + JSR LOUTST + [ASCIZ \B\] +TERMIN + +DEFINE TYPE TXT/ + JSR TOUTST + [ASCIZ \TXT\] +TERMIN + +TS INFORM Runs under time-sharing on any machine +DC INFORM Systems Concepts disk control +RP INFORM DEC RP10 disk control +RH INFORM DEC RH10 disk control + INFORM Number of drives=,\ndrives +; INFORM Number of virtual units=,\nunits +KA INFORM KA-10 +KL INFORM KL-10 +IFN OLPTP, INFORM Old LPT Interface +IFN NLPTP, INFORM New LPT Interface +IFN TTLPTP, INFORM LPT on MTY line number ,\TTLPTP&77 +TS, T300P==0 +IFN T300P, INFORM Support for Trident T-300 via PDP-11 +];IF1 + +MEMSIZ==1000000 +IFNDEF SA,SA==100*2000 + +NLPT=464 ;device code of ML lpt +MTY==400 ;device code of scanner + +APR==0 +PI==4 +KA, TTY==120 +KA, PTP==100 +IFN T300P, DLB==60 ;DL-10 +.ALSO DLC==64 + +X=PUSHJ P, + +NTS,[ LOC SA + JRST GOGO ;make easy to start from ITS core load +SALVRT: 0 ;system may JSR here + JRST SALVAG +];NTS + +;DISK PHYSICAL PARAMETERS + +DC,[ + .INSRT SYSTEM;DC10 > +] +RP,[ + .INSRT SYSTEM;RP10 > +] +RH,[ + .INSRT SYSTEM;RH10 > +] +TS, NTUTBL==4 ;MAXIMUM NUMBER OF BLOCKS PER TUT ON ANY ITS + +;FILE SYSTEM PARAMETERS + +.INSRT SYSTEM;FSDEFS > + +IFN T300P,[ + + ;DL10 COMMUNICATIONS AREA IN NON-ENCACHED LOW CORE +DL10AR==500 ;ACTUAL STORAGE LAYOUT DEFINED IN ITS AND IN T300 DEFS + + .INSRT SYSTEM;T300 > +MXTUTB==NTUTB1 ;MAXIMUM OF NTUTBL AND NTUTB1 +];T300P +.ELSE MXTUTB==NTUTBL + +DC,[ +DEFINE QCOPY A,B +DCOPY A(-_2&37774)!TERMIN +];DC + +;DEFINE CHANNEL PROGRAM AREA + +NTS,[ +KL,[ + .INSRT SYSTEM;EPT > + +ZZ==. + LOC EPTDDT + JRST MEMSIZ-4000 ;FOR 'DDT' COMMAND IN KLDCP +LOC ZZ + +PAG==10 +..D010==0 +SWPIA=701440,,0 +SWPUO=701740,,0 +SWPIO=701640,,0 +SWPUA=701540,,0 +];KL +KA,[ +SLVICWA=20 +SLVIOWD=22 +];KA +];NTS + +TS,[ +TYIC==1 +TYOC==2 +LPTC==3 +QIN==4 +] + +IF2,[ +TS,[ NBLKS==10000. ;FAKE + TBLKS==10000. ;FAKE + MFDBLK==-1 ;JUST TO AVOID UNDEF SYM ERROR, VALUE NEVER USED +; TUTBLK==-1 ;.. +];TS +];IF2 + +SUBTTL COPY BLOCK TO BLOCK + +NTS,[ + +COPY: JSR INIT + PUSHJ P,CRR + UNTMES COPY BLOCK FROM UNIT # + PUSHJ P,NTYI + JRST COPY + CAIL A,NUNITS + JRST COPY + MOVEM A,FROM + MOVE I,A + PUSHJ P,RESET +CP1: PUSHJ P,CRR + TYPE BLOCK # + PUSHJ P,OTYI + CAIL A,TBLKS + JRST CP1 + MOVEM A,FMBLK +CP2: PUSHJ P,CRR + UNTMES ONTO UNIT # + PUSHJ P,NTYI + JRST CP2 + CAIL A,NUNITS + JRST CP2 + MOVEM A,TOU + MOVE I,A + PUSHJ P,RESET + PUSHJ P,CRR +CP3: TYPE BLOCK # + PUSHJ P,OTYI + PUSHJ P,CRR + CAIL A,TBLKS + JRST CP3 + MOVEM A,TOBLK + MOVEI A,TUT + MOVE J,FMBLK + MOVE I,FROM + PUSHJ P,READ + JUMPL T,CPERR +COPYB: MOVEI A,TUT ;HANDY PLACE FOR A BREAKPOINT + MOVE J,TOBLK + PUSHJ P,WRITT + JRST DDT + +DTYI: MOVEI B,0 ;DECIMAL TYPEIN +DTYI1: X NTYI + JRST DTYI2 + IMULI B,10. + ADD B,A + JRST DTYI1 + +DTYI2: MOVE A,B + POPJ P, + +OTYI: MOVEI B,0 ;OCTAL TYPEIN +OTYI1: X NTYI + JRST DTYI2 + LSH B,3 + ADD B,A + JRST OTYI1 + +CPERR: TYPE READ ERROR + X CRR + JRST DDT + + SUBTTL TEST AND UNLOCK SOME BLOCKS + +UNLOCK: JSR INIT + X CRR + UNTMES UNLOCK BLOCKS ON UNIT # + X NTYI + JRST UNLOCK + CAIL A,NUNITS + JRST UNLOCK + MOVEM A,FROM + MOVE I,A + X RESET +UNLK1: X CRR + TYPE BLOCK # + X OTYI + PUSHJ P,UNLOCB + JFCL + JRST UNLK1 ;USE ^Z TO GET OUT + +;UNLOCK A BLOCK, NUMBER IN A, UNIT IN FROM + +UNLOCB: INSIRP PUSH P,[J K Q D B TT] + MOVE J,A + MOVEM J,FMBLK + SETZM CYLBUF ;ZERO OUT IN CASE CAN'T READ + MOVE A,[CYLBUF,,CYLBUF+1] + BLT A,CYLBUF+4000-1 + MOVE I,FROM + MOVEI A,CYLBUF + PUSHJ P,READ + JUMPGE T,UNLK2 + TYPE READ ERROR + X CRR + X GSTS + TYPE PROCEED? + X Y.OR.N + JRST UNLOCX +UNLK2: MOVE A,[RXWDS,,WXWDS] + BLT A,WXWDS+4-1 + MOVEI A,CYLBUF + X WRITE + JUMPL T,WRERR + MOVEI A,CYLBUF+2000 + X READ + JUMPL T,[TYPE READ-BACK ERROR + X CRR + X GSTS + JRST UNLOCX] + MOVSI T,-2000 +UNLK3: MOVE TT,CYLBUF(T) + CAME TT,CYLBUF+2000(T) + JRST [ TYPE READ-BACK COMPARE ERROR + X CRR + JRST UNLOCX] + AOBJN T,UNLK3 + + MOVEI A,TUT + X RDTUT + JUMPL T,CPERR + MOVE J,FMBLK + MOVEI B,TUT + X TUTPNT + JUMPE J,[ TYPE CAN'T ACCESS TUT + X CRR + JRST UNLOCX ] + MOVEI B,1 ;SAFEST ... NEXT SALVAGE WILL PUT CORRECT VALUE + DPB B,J + MOVEI A,TUT + X WRTUT + JUMPL T,WRERR + AOS -6(P) ;WINNING, SKIP RETURN +UNLOCX: INSIRP POP P,[TT B D Q K J] + POPJ P, + +WRERR: TYPE WRITE ERROR + JRST CRDDT + +SUBTTL DUP - COPY ENTIRE PACK + +DUP1A: PUSHJ P,CRR +DUP1: UNTMES FROM UNIT # + PUSHJ P,NTYI + JRST DUP1A + CAIL A,NUNITS + JRST DUP1A + MOVE I,A + PUSHJ P,RESET +DUP2: MOVEM A,FROM +TO: PUSHJ P,CRR + UNTMES ONTO UNIT # + PUSHJ P,NTYI + JRST TO + CAIL A,NUNITS + JRST TO + MOVEM A,TOU + X CRR + UNTMES COPY FROM UNIT # + MOVE A,FROM + X DPT + UNTMES ONTO UNIT # + MOVE A,TOU + X DPT + TYPE , OK? + X Y.OR.N + JRST DDT + MOVE I,TOU + PUSHJ P,RESET + POPJ P, + +DUP: JSR INIT + SETZM USRDS' + SETZM USWRTS' + SETZM DUPRER + SETZM DUPWER +RH, SETZM CERRS + TYPE DUPLICATE DISK + PUSHJ P,DUP1 + MOVE I,FROM +DC, MOVE A,QTRAN(I) +DC, DPB A,[DUNFLD CYLRIR] +RP, MOVE I,TOU +.ELSE [ MOVE A,PKNUM(I) + MOVE I,TOU + CAME A,PKNUM(I) + JRST DUPLUZ +]DC, MOVE A,QTRAN(I) +DC, DPB A,[DUNFLD CYLRIW] + MOVEI J,NCYLS+XCYLS-1 ;DETERMINE HOW MANY CYLINDERS THIS DRIVE +RP,[ MOVSI A,(DNOOPC) + DPB I,[DUNFLD A] ;SELECT DESTINATION DRIVE + DATAO DPC,A + DATAI DPC,B + MOVE I,FROM + DPB I,[DUNFLD A] ;SELECT SOURCE DRIVE + DATAO DPC,A + DATAI DPC,A + XOR A,B + TRNE A,2000 + JRST [ TYPE CAN'T COPY RP02 TO RP03 OR VICE VERSA + JRST CRDDT ] + TRNE B,2000 + MOVEI J,MCYLS+XCYLS-1 ;DRIVES ARE RP03S, MORE CYLINDERS TO COPY +];RP +IFN T300P,[ + CAIL I,T300P + JRST T3DUP ;HAVE TO DO IT THE SLOW WAY + MOVE I,FROM + CAIL I,T300P + JRST [ TYPE CAN ONLY GO T-300 TO T-300 + JRST CRDDT ] +];T300P + MOVEI A,CYLBUF +DLUP: MOVE I,FROM + PUSHJ P,READCY + JUMPL T,DLUP1 ;LOST, TRY BLOCK AT A TIME + MOVE I,TOU + PUSHJ P,WRITCY + JUMPL T,DLUP1 +DLUP2: SOJGE J,DLUP +DC, MOVEI T,CYLRIR ;COPY READ-IN BLOCK +DC, PUSHJ P,RW0 +RH,[ SKIPN A,CERRS + JRST DDT + X TDPT + TYPE ECC-CORRECTED ERRORS. + JRST CRDDT +] +.ELSE JRST DDT + +DUPLUZ: TYPE PACK # DFRS + PUSHJ P,CRR + JRST DDT + +IFN T300P,[ +T3DUP: MOVE I,FROM + CAIGE I,T300P + JRST [ TYPE CAN ONLY GO T-300 TO T-300 + JRST CRDDT ] + TYPE THIS WILL TAKE A WHILE... + X CRR + MOVEI J,NBLKS1+XBLKS1-1 +T3DUP1: MOVEI A,CYLBUF + MOVE I,FROM + X READ + JUMPL T,CPERR + MOVE I,TOU + X WRITE + JUMPL T,WRERR + SOJGE J,T3DUP1 + JRST CRDDT +];T300P + +IFE RH10P,[ ;BLOCK AT A TIME +DLUP1: PUSH P,J + IMULI J,NBLKSC + CLEARM DLUPT +DLUP3: MOVE I,FROM + MOVEI A,CYLBUF + PUSHJ P,READ + JUMPL T,DLUPE1 + MOVE I,[RXWDS,,WXWDS] +DLUPEW: BLT I,WXWDS+4-1 + PUSHJ P,WRITT + JUMPL T,DLUPE2 +DLUPEX: AOS TT,DLUPT + CAIGE TT,NBLKSC + AOJA J,DLUP3 + POP P,J + JRST DLUP2 +] +RH,[ ;SECTOR AT A TIME ON RP04 SO GET EXTRA SECTORS +DLUP1: MOVEI T,NHEDS*NSECS + MOVEM T,DLUPT +DLUP3: SOS W,DLUPT ;NEXT SECTOR (GOING BACKWARDS THROUGH CYLINDER) + IDIVI W,NSECS ;TRACK IN W, SECTOR IN U + LSH W,8 + IOR W,U + HRL W,J ;NOW W HAS DISK ADDRESS + MOVEM W,RHPGA + MOVE U,[-200,,CYLBUF-1] + MOVEM U,RHIOW + MOVE I,FROM + MOVEI TT,%HMRED + MOVEM TT,RHCMD + PUSHJ P,RW1 + JUMPL T,DLUPE1 +DLUPEW: MOVE I,TOU + MOVEI TT,%HMWRT + MOVEM TT,RHCMD + PUSHJ P,RW1 + JUMPL T,DLUPE2 +DLUPEX: SKIPE DLUPT + JRST DLUP3 + JRST DLUP2 +];RH + +DLUPT: 0 + +DLUPE1: AOS DUPRER + SKIPE HCRASH + JRST DLUPE4 ;SPEED IS OF THE ESSENCE, DON'T TYPE ANYTHING + TYPE Read error on block # + PUSHJ P,DLUPE3 +DLUPE4: SETZM CYLBUF ;COULDN'T READ THE BLOCK, SUBSTITUTE ALL ZEROS + MOVE A,[CYLBUF,,CYLBUF+1] + BLT A,CYLBUF+2000-1 + MOVE I,[DLUPE5,,WXWDS] ;WITH SPECIAL EXTRA WORDS + JRST DLUPEW ;RESUME DLUP AT WRITE + +DLUPE3: MOVE A,I + X DPT + MOVEI A,"- + X TYO +IFE RH10P, MOVE A,J +IFN RH10P,[ + HLRZ A,RHPGA ;CYLINDER + IMULI A,NBLKSC + LDB W,[101000,,RHPGA] ;HEAD + IMULI W,NSECS + LDB U,[001000,,RHPGA] ;SECTOR + ADD W,U + IDIVI W,SECBLK + ADD A,W ;INACCURATE IF UNUSED SECTOR AT END OF CYLINDER +];RH10P + PUSHJ P,DPT + PUSHJ P,CRR + JRST GSTS ;HARDWARE STATUS + +DLUPE2: AOS DUPWER + SKIPE HCRASH + JRST DLUPEX ;SPEED IS OF THE ESSENCE, DON'T TYPE ANYTHING + TYPE Write error on block # + PUSHJ P,DLUPE3 + JRST DLUPEX + +;SUITABLE EXTRA WORDS FOR BLOCKS THAT COULDN'T BE READ + +DLUPE5: 0 ;WORD COUNT=2000, LAST BLOCK=0 + SIXBIT /??????/ ;DUMMY DIRECTORY + SIXBIT /(DISK)/ + SIXBIT/LOSSAG/ + +DC,[ SUBTTL CYLINDER I/O, DC10 +READCY: SKIPA T,[DREADC+DUNENB] ;READ CONTINUOUS +WRITCY: MOVSI T,(DWRITC+DUNENB) ;WRITE CONTINUOUS + MOVE TT,QTRAN(I) + DPB TT,[DUNFLD T] + MOVE TT,J + SKIPGE QTRAN(I) + ADDI TT,NCYLS+XCYLS + DPB TT,[DCYL T] + DPB TT,[DCYL CYLCM3] +CYL1: SKIPLE TT,PKNUM(I) + JRST CYL2 + PUSH P,T + PUSHJ P,RESET + POP P,T + JRST CYL1 + +CYL2: CAIL J,NCYLS + MOVEI TT,0 + DPB TT,[DPKID T] + DPB TT,[DPKID CYLCM3] + MOVEM T,CYLCOM + DPB A,[DCCA CYLCM1] + DPB A,[DCCA CYLCM2] + MOVEI T,CYLCOM +RW0: HRRM T,DGO + JRST RW1 ;TRY TRANSFER UNTIL SUCCEEDS + +CYLCOM: 0 + DALU+DLDBWC+DLLB -2004*NBLKSC(3) ;LOAD WORD COUNT WITH -2004*NO. OF BLOCKS/CYL +CYLCM1: DCOPY . +CYLCM3: DRCC ;READ COMPARE CONTINUOUS + DALU+DLDBWC+DLLB -2004*NBLKSC(3) +CYLCM2: DCCOMP . + DHLT + +CYLRIR: DREAD+DUNENB + DCOPY CYLBUF(-LRIBLK_2&37774) +CYLRIW: DWRITE+DUNENB + DCOPY CYLBUF(-LRIBLK_2&37774) + DHLT +];DC + +RP,[ SUBTTL CYLINDER I/O, RP10 & RH10 CONTROLS + +;RP10 CYLINDER I/O ALWAYS SUCCEEDS. IF PROBLEMS OCCUR, GOES SECTOR +;AT A TIME, TYPING OUT WHAT IS GOING ON, ZEROING SECTORS THAT CAN'T BE READ, +;THEN RETURNS CLAIMING TO HAVE WON. +READCY: SKIPA T,DRD +WRITCY: MOVE T,DWR + MOVEM T,RPIOOP + MOVEM J,RPIOCY + SETZM RPIOHD + SETZM RPIOSC + MOVEM A,RPAOBJ + MOVNI T,NBLKSC*2000 + HRLM T,RPAOBJ +RPCY0: PUSHJ P,RPIO + JUMPGE T,CPOPJ ;WON +IFN 0,[ ;I DON'T THINK THIS CODE WORKS + SKIPE HCRASH + POPJ P, + MOVE T,RPIOOP + CAMN T,DWR + JRST [ TYPE WRITE ERROR ON BLOCK + JRST .+3 ] + TYPE READ ERROR ON BLOCK + PUSH P,A + PUSH P,B + MOVE A,I + X DPT + TYPE - + MOVE A,RPIOHD + IMULI A,NSECS + ADD A,RPIOSC + IDIVI A,SECBLK + MOVE B,RPIOCY + IMULI B,NBLKSC + ADD A,B + X DPT + X CRR + POP P,B + POP P,A + PUSHJ P,GSTS ;EXPLAIN WHAT HAPPENED TO THIS SECTOR + MOVE T,RPIOOP ;IF READ, ZERO THE BUFFER + HRLZ TT,RPAOBJ ;IF WAS REALLY IN SECTOR AT A TIME MODE + CAMN T,DRD + CAIE TT,-200 + JRST RPCY1 + MOVE TT,RPAOBJ + SETZM (TT) + HRLZ T,TT + HRRI T,1(TT) + BLT T,177(TT) +RPCY1: AOS T,RPIOSC ;ADVANCE TO NEXT SECTOR + CAIGE T,NSECS + JRST RPCY2 + SETZM RPIOSC + AOS T,RPIOHD + CAIL T,NHEDS + POPJ P, ;MUST BE DONE +RPCY2: MOVE T,[200,,200] + ADDB T,RPAOBJ + JUMPL T,RPCY0 ;GO DO THE REST OF THE CYLINDER +];IFN 0 + POPJ P, ;HMM, MUST BE DONE +];RP + +RH,[ ;CYLINDER I/O, RH10 CONTROL + +READCY: SKIPA TT,[%HMRED] +WRITCY: MOVEI TT,%HMWRT +IFN T300P,[ + CAIL I,T300P + JRST 4,. ;NOT CODED YET + SETZM T3IOP +];T300P + MOVEM TT,RHCMD + HRLZM J,RHPGA ;SET ADDRESS TO START OF CYLINDER + MOVEI T,-1(A) ;SET UP IOWD TO TRANSFER WHOLE CYLINDER + HRLI T,-200*NHEDS*NSECS ;- NUMBER OF WORDS TO TRANSFER + MOVEM T,RHIOW + JRST RW1 +];RH + +SUBTTL TRAN - LOAD FROM MAG TAPE + +MAGOP: AOSE ITAPE + JRST MTR1 + HRROI A,MAGHD + PUSHJ P,MREAD + MOVE A,MAGHD + TRNE A,-1 + JRST MBDTHD + CAMGE A,[-LTHBLK,,] + JRST MBDTHD + ADD A,[1,,THBLK+1] + PUSHJ P,MREAD + TYPE TAPE # + HLRZ A,THTPN + PUSHJ P,TDPT + PUSHJ P,CRR + +MTR1: HRROI A,MAGHD + PUSHJ P,MREAD + JUMPE T,CPOPJ ;EOF + MOVE A,MAGHD + TRNE A,-1 + JRST MBADHD + CAMGE A,[-LMHBLK,,0] + JRST MBADHD + ADD A,[1,,MHBLK+1] + PUSHJ P,MREAD + SETZM LNKFLG + HLRZ B,MHPKN + JUMPE B,POPJ1 ;NOT A LINK + SETOM LNKFLG + MOVE A,[-3,,LNKNM1] ;READ LINK INFO + PUSHJ P,MREAD + JRST POPJ1 + +MBADHD: LPR BAD HEADER + PUSHJ P,LCRR + PUSHJ P,IGFIL + JRST MTR1 + +MBDTHD: TYPE BAD TAPE HEADER + JRST CRDDT + +TRAN: PUSHJ P,REW +TRAN1: JSR INIT + PUSHJ P,CRR + MOVEI I,0 +TRAN2: SKIPGE QACT(I) + PUSHJ P,RESET + CAIGE I,NUNITS-1 + AOJA I,TRAN2 + MOVEI A,5 ;READS FROM TAPE UNIT 5 + PUSHJ P,DUP2 + MOVEI A,TUT + MOVE I,TOU + PUSHJ P,RDTUT + JUMPL T,READC + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READT + +TNAML: PUSHJ P,MAGOP + JRST MREOT + MOVE A,MHFN1 ;DON'T RELOAD DIRECTORIES! + MOVE B,MHFN2 + CAMN A,[SIXBIT/.FILE./] + CAME B,[SIXBIT/(DIR)/] + CAIA + JRST TIGNF + CAMN A,[SIXBIT/M.F.D./] + CAME B,[SIXBIT/(FILE)/] + SKIPA A,MHSNM + JRST TIGNF + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + MOVE A,MHFN1 + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + MOVE A,MHFN2 + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + CLEARM FERRS + MOVE B,MHSNM + MOVE A,MFD+MDNAMP + SETZM IBLK +TMLKP: CAIL A,2000 + JRST TNEWU + SKIPN C,MFD+MNUNAM(A) + JRST TMLKZ + CAMN B,C + JRST TOLDU +TMLKL: ADDI A,LMNBLK + JRST TMLKP + +TMLKZ: MOVEM A,IBLK + JRST TMLKL + +TOLDU: HRREI J,-2000(A) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEM J,UFDTA + MOVEI A,NUSRD + PUSHJ P,READT + CAME B,NUSRD+UDNAME + JRST 4,. + JRST TOLDUR + +TNEWU: MOVE A,[NUSRD,,NUSRD+1] + SETZM NUSRD + BLT A,NUSRD+1777 + MOVEM B,NUSRD+UDNAME + MOVEI A,2000 + MOVEM A,NUSRD+UDNAMP + SKIPE A,IBLK + JRST .+3 + MOVNI A,LMNBLK + ADDB A,MFD+MDNAMP + MOVEM B,MFD+MNUNAM(A) + HRREI J,-2000(A) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEM J,UFDTA +TOLDUR: + MOVE B,MHFN1 + MOVE C,MHFN2 + MOVE A,NUSRD+UDNAMP + SETZM IBLK +TULKP: CAIL A,2000 + JRST TNEWF + MOVSI T,UNCDEL + TDNE T,NUSRD+UNRNDM(A) + JRST TULKD + SKIPN T,NUSRD+UNFN1(A) + JRST TULKZ + CAME B,T + JRST TULKL + CAMN C,NUSRD+UNFN2(A) + JRST TOLDF +TULKL: ADDI A,LUNBLK + JRST TULKP + +TULKZ: SKIPN NUSRD+UNFN2(A) +TULKD: MOVEM A,IBLK + JRST TULKL + +TOLDF: LPR EXISTS + PUSHJ P,LCRR +TIGNF: PUSHJ P,IGFIL + JRST TNAML + +IGFIL: MOVE A,[-2000,,FDBUF] + PUSHJ P,MREAD + SKIPN EOUF + JRST IGFIL + CLEARM EOUF + POPJ P, + +TNEWF: SKIPE A,IBLK + JRST TNEWCK + MOVNI A,LUNBLK + ADDB A,NUSRD+UDNAMP +TNEWCR: MOVE T,NUSRD+UDESCP + IDIVI T,6 + CAIL T,-UDDESC(A) + JRST 4,. + MOVEM B,NUSRD+UNFN1(A) + MOVEM C,NUSRD+UNFN2(A) +DC, MOVEM B,WXWDS+XWFN1 +DC, MOVEM C,WXWDS+XWFN2 + MOVE B,NUSRD+UDNAME +DC, MOVEM B,WXWDS+XWSYSN +DC, SETZM WXWDS+XWBWC + MOVE B,NUSRD+UDESCP + DPB B,[UNDSCP NUSRD+UNRNDM(A)] + MOVE B,MHDATE + MOVEM B,NUSRD+UNDATE(A) + SETOM NUSRD+UNREF(A) + MOVE B,TUT+QPKNUM + DPB B,[UNPKN NUSRD+UNRNDM(A)] + MOVEI A,NUSRD+UNRNDM(A) + HRLI A,(UNWRDC) + MOVEM A,TRNDEP' ;DPB WC OF LAST BLOCK LATER + SETZM CBYT' + SETZM OBLKS' + SETZM IBLK' + SETZM LBLK' + SKIPE LNKFLG + JRST TRNLNK ;JUMP IF APPENDING LINK +TBLKL: +TBLKL1: MOVE A,[-2000,,FDBUF] + PUSHJ P,MREAD + JUMPE T,TBLKL2 +DC, DPB T,[XWAWC WXWDS+XWBWC] + DPB T,TRNDEP ;STORE WORD COUNT IN DIRECTORY + MOVE T,LBLK +DC, DPB T,[XWBLK WXWDS+XWBWC] + AOS IBLK + PUSHJ P,WRBLK +TBLKL2: SKIPN EOUF + JRST TBLKL + SETZM EOUF + JRST TBDON + +TNEWCK: SKIPN NUSRD+UNFN1(A) + SKIPE NUSRD+UNFN2(A) + JRST 4,. + JRST TNEWCR + +TBDON: PUSHJ P,EBYT + MOVEI J,UDWPH + SKIPN LBLK + PUSHJ P,BYDEP +TBDON1: MOVEI J,0 + PUSHJ P,BYDEP + JRST TMDON + +TRNLNK: MOVE A,LNKSNM + PUSHJ P,TRNLK1 + MOVE A,LNKNM1 + PUSHJ P,TRNLK1 + MOVE A,LNKNM2 + PUSHJ P,TRNLK1 + JRST TBDON1 + +TRNLK1: MOVE K,A + MOVEI A,6 +TRNLK2: MOVEI J,0 + LSHC J,6 + JUMPE J,TRNLK4 + CAIE J,': + CAIN J,'; + JRST [ PUSH P,J + MOVEI J,': + PUSHJ P,BYDEP + POP P,J + JRST .+1 ] + PUSHJ P,BYDEP + SOJG A,TRNLK2 + POPJ P, + +TRNLK4: MOVEI J,'; + JRST BYDEP + +READFN: SKIPA I,FROM +READT: MOVE I,TOU + PUSHJ P,READ +READC: JUMPL T,[JRST 4,.] + POPJ P, + +WRBLK: MOVE J,TUT+QTUTP + AOS TUT+QTUTP + CAML J,TUT+QLASTB + JRST WRLUZ + MOVEM J,LBLK + SETZM TUTLUZ + MOVEI B,TUT + PUSHJ P,TUTPNT + LDB B,J + JUMPN B,WRBLK + MOVEI B,1 + DPB B,J + MOVE J,LBLK + MOVEI A,FDBUF + PUSHJ P,WRITT + SUB J,OBLKS + ADDM J,OBLKS + CAIN J,1 + JRST WRBC + PUSHJ P,EBYT + CAIG J,UDWPH-UDTKMX + JRST WRBS + MOVE J,OBLKS + LSHC J,-NXLBYT*6 + MOVEI U,NXLBYT+1 + ADDI J,UDWPH+1 +WRBL: PUSHJ P,BYDEP + LSHC J,6 + SOJG U,WRBL + POPJ P, + +WRLUZ: SETCMB J,TUTLUZ' + JUMPE J,WRLUZ1 + MOVE J,TUT+QSWAPA + CAMGE J,TUT+QFRSTB + MOVE J,TUT+QFRSTB + MOVEM J,TUT+QTUTP + JRST WRBLK + +WRLUZ1: TYPE DISK FULL + SKIPN NOLPT + X LCRR + JRST CRDDT + +WRBS: ADDI J,UDTKMX-1 +BYDEP: MOVE T,NUSRD+UDESCP + AOS NUSRD+UDESCP + IDIVI T,6 + ADDI T,UDDESC + CAML T,NUSRD+UDNAMP + JRST 4,. + ADDI T,NUSRD + HLL T,QBTBL(W) + DPB J,T + POPJ P, + +WRBC: AOS J,CBYT + CAIGE J,UDTKMX + POPJ P, +EBYT: PUSH P,J + SKIPN J,CBYT + JRST POPJJ + PUSHJ P,BYDEP + SETZM CBYT +POPJJ: POP P,J + POPJ P, + + +TMDON: MOVE J,[WXWDS,,WXWDS+1] + SETZM WXWDS + BLT J,WXWDS+3 + MOVE A,TUT+QTUTP + IDIVI A,NBLKSC + IMULI A,NBLKSC + MOVEM A,TUT+QTUTP + MOVEI A,TUT + MOVE I,TOU + PUSHJ P,WRTUT + MOVEI I,0 +TMDON2: SKIPL QACT(I) + JRST TMDON1 + MOVE J,MFDBK + MOVEI A,MFD + PUSHJ P,WRITE + MOVE J,UFDTA + MOVEI A,NUSRD + PUSHJ P,WRITE +TMDON1: CAIGE I,NUNITS-1 + AOJA I,TMDON2 + SKIPN FERRS + LPR OK + PUSHJ P,LCRR + JRST TNAML + +SUBTTL UCOP - COPY DIRECTORIES FROM DRIVE TO DRIVE + +UCOP: JSR INIT + TYPE COPY DIRS + PUSHJ P,DUP1 + MOVEI A,D0 + MOVE J,MFDBK + PUSHJ P,READFN + PUSHJ P,WRITT + MOVEI Q,2000 +UCOPL: SUBI Q,LMNBLK + CAMGE Q,D0+MDNAMP + JRST DDT + SKIPN B,D0(Q) + JRST UCOPL + HRREI J,-2000(Q) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEI A,OUSRD + PUSHJ P,READFN + CAME B,OUSRD+UDNAME + JRST 4,. + PUSHJ P,WRITT + JUMPL T,WRERR + JRST UCOPL + +SUBTTL SPKID - SET PACK ID IN TUT + +SPKID: JSR INIT + CAIA +SPKID0: X CRR + UNTMES SET PACK ID ON UNIT # + X NTYI + JRST SPKID0 + CAIL A,NUNITS + JRST SPKID0 + X CRR + MOVE I,A + PUSHJ P,RESET + MOVEI A,TUT + PUSHJ P,RDTUT + JUMPL T,ZAPLUZ + TYPE PACK NO= + MOVE A,TUT+QPKNUM + X TDPT + TYPE , CHANGE ID FROM + MOVE A,TUT+QPAKID + X T6B + TYPE TO + X SIXIN + X CRR + JUMPE B,ZAPLUZ + MOVEM B,TUT+QPAKID + MOVEI A,TUT + PUSHJ P,WRTUT + JUMPL T,ZAPLUZ + JRST DDT + SUBTTL REMAP - REASSIGN PACK#S AND FIX UFDS + +REMAPP: REPEAT 40, -1 ;INDEX BY PACK #. LH=NEW PACK #, RH=DISK ADDR OFFSET + +REMAP: JSR INIT + UNTMES REMAP THE COPY OF THE UFDS ON UNIT # + PUSHJ P,NTYI + JRST REMAP + X CRR + CAIL A,NUNITS + JRST REMAP + MOVE I,A + MOVEI A,MFD ;GET MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE Q,MFD+MDNAMP +REMAP1: CAIL Q,2000 ;NEXT UFD + JRST CRDDT + SKIPN B,MFD+MNUNAM(Q) + JRST REMAP9 + MOVEM B,USRNAM + MOVE J,Q + SUBI J,2000 + IDIVI J,LMNBLK + ADD J,NUDS ;UFD BLOCK NUMBER + MOVEI A,OUSRD + PUSHJ P,READ + JUMPL T,CPERR + CAME B,OUSRD+UDNAME + JRST CPERR + MOVE K,OUSRD+UDNAMP +REMAP2: CAIL K,2000 ;NEXT FILE + JRST REMAP6 + MOVSI C,UNLINK + TDNE C,UNRNDM+OUSRD(K) + JRST REMAP5 ;DON'T MANGLE LINKS + LDB C,[UNDSCP UNRNDM+OUSRD(K)] + IDIVI C,UFDBPW + HLL C,QBTBLI(D) + ADDI C,UDDESC+OUSRD ;C HAS DESC POINTER + LDB D,[UNPKN UNRNDM+OUSRD(K)] ;D HAS PK # + SKIPGE A,REMAPP(D) ;GET MAPPING + JRST 4,. ;LOSER FORGOT TO PATCH IT IN + HLRZ D,A ;GET NEW PACK # + DPB D,[UNPKN UNRNDM+OUSRD(K)] ;CHANGE IT + HRRE D,A ;D HAS BLOCK # OFFSET +REMAP3: MOVE H,C + ILDB A,C ;GET DESC + JUMPE A,REMAP5 ;EOF + CAIG A,UDWPH + JRST REMAP3 ;DOESN'T DEPEND ON ABS DISK ADDRESSES + ANDI A,37 ;MASK OUT LOAD-ADDR-BIT +REPEAT NXLBYT,[ + LSH A,UFDBYT + ILDB B,C + ADD A,B +] + ADD A,D ;RELOCATE THE ADDRESS + REPEAT 6,JFCL ;PATCH AREA + MOVE C,H ;GET BACK B.P. TO START OF LOAD-ADDR DESCRIPTOR + MOVE H,[_36+UFDBYT_30+A] +REPEAT NXLBYT+1,[ + ILDB B,H +IFE .RPCNT, ADDI B,40 + IDPB B,C +] + JRST REMAP3 + +REMAP5: ADDI K,LUNBLK + JRST REMAP2 + +REMAP6: MOVEI A,OUSRD + PUSHJ P,WRITE + JUMPL T,WRERR +REMAP9: ADDI Q,LMNBLK + JRST REMAP1 + +SUBTTL ZAP - ZERO DIR BLOCKS, WRITE EMPTY TUT & MFD + +ZAP: JSR INIT + X CRR + UNTMES INIT DIRS ON UNIT # + PUSHJ P,NTYI + JRST ZAP + CAIL A,NUNITS + JRST ZAP + PUSHJ P,CRR + MOVEM A,TOU + MOVE I,A +RP,[ TYPE PACK NO = + X DTYI ;IF RP, NO PK # IN HARDWARE, GET IT FROM HUMAN + X CRR + MOVEM A,PKNUM(I) +] PUSHJ P,RESET ;IF DC OR RH, WILL USE PACK # FROM HARDWARE + MOVE A,[WXWDS-1,,WXWDS] + BLT A,WXWDS+3 + SETZM MFD ;INIT ALL BLOCKS TO ZERO + MOVE A,[MFD,,MFD+1] + BLT A,MFD+1777 + MOVN J,NUDS ;GET AOBJN PTR TO UFD BLOCKS + HRLZ J,J +KL, ADD J,[2,,2] ;PROTECT KLDCP? + MOVEI A,MFD +ZAPL: PUSHJ P,WRITE + JUMPL T,ZAPLUZ + AOBJN J,ZAPL + +DC,[ CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP DZAP] + CONSZ DC0,DSSACT + JUMPA .-1 + CONSO DC0,DSSERR +];DC + JRST MARK69 + +ZAPLUZ: TYPE LOSE + JRST CRDDT + +DC,[ +DZAP: DWRITE ;ZERO READ-IN BLOCK + DCSKIP (-LRIBLK_2&37774) + DHLT +];DC + + SUBTTL SIMPLE DISK TESTS + +;THIS ONE JUST WRITES A SINGLE BLOCK, READS IT BACK, AND CHECKS THAT IT'S THE SAME. +DSKTST: JSR INIT + SETOM HCRASH ;DON'T DO ERROR RETRY + TYPE TEST UNIT # + X NTYI + JRST DSKTST + X CRR + CAIL A,NUNITS + JRST DSKTST + MOVE I,A + TYPE GOT A SCRATCH PACK ON UNIT # + X TOPT + TYPE ? + X Y.OR.N + JRST CRDDT +DSKTS0: X RESET + MOVEI J,NBLKSC*15. ;RANDOMLY USE CYLINDER 15. + MOVSI A,-2000 + MOVEI B,1 ;FIRST PART OF PATTERN IS FLOATING 1S +DSKT0A: MOVEM B,D0(A) + LSH B,1 + SKIPE B + AOBJN A,DSKT0A + HRROI B,-2 ;NEXT IS FLOATING 0S +DSKT0B: MOVEM B,D0(A) + JUMPGE B,DSKT0C + LSH B,1 + AOS B + AOBJN A,DSKT0B +DSKT0C: MOVEM A,D0(A) ;REST IS AN ADDRESS PATTERN + AOBJN A,DSKT0C + MOVEI A,D0 + X WRITE + JUMPL T,WRERR +DSKTS1: MOVEI A,D1 + X READ + PUSHJ P,TYIPSE + MOVSI B,-2000 +DSKT1A: MOVE A,D1(B) + CAMN A,D0(B) +DSKTS2: AOBJN B,DSKT1A + JUMP DSKTS4 ;CHANGE TO JUMPA FOR NO TYPEOUT + JUMPGE B,DSKTS3 ;JUMP IF COMPARED ALL + HRRZ A,B + X TOPT + TYPE / + MOVE A,D0(B) + X THWO + X TSPAC + MOVE A,D1(B) + X THWO + X TSPAC + MOVE A,D0(B) + XOR A,D1(B) + X THWO + X CRR + JRST DSKTS2 + +DSKTS3: JUMPGE T,DSKTS1 ;AFTER PRINTING COMPARISON, IF DISK NOTICED ERROR + X GSTS ; ALSO PRINT THAT + JRST DSKTS1 + +DSKTS4: DATAO LIGHTS,[0] + JUMPGE B,DSKTS1 + MOVE A,B + XOR A,CYLBUF(B) + DATAO LIGHTS,A + JRST DSKTS2 + +;SEEK TEST. THIS LOOPS OVER ALL HEADS, AND OPTIONALLY LOOPS OVER DIFFERENT +; LENGTH SEEKS. IT DOESN'T WRITE, BUT IS A TEST OF SEEKING AND SEARCHING. +;SETOM HCRASH IF YOU WANT TO DO NO ERROR RETRIES ON READ/SEARCH ERRORS +;(SEEK INCOMPLETES WILL ALWAYS BE RETRIED.) + +SEKTST: JSR INIT + TYPE SEEK TEST UNIT # + X NTYI + JRST SEKTST + X CRR + CAIL A,NUNITS + JRST SEKTST + MOVE I,A + X RESET + TYPE ALWAYS DO FULL LENGTH SEEKS? + SETZM SEKINC + MOVEI A,10.*NBLKSC + X Y.OR.N + MOVEM A,SEKINC' ;IF NO, DO DECREASING LENGTH SEEKS +SEKTS0: +RP,[ + MOVSI A,(DNOOPC) ;DETERMINE HOW MANY CYLINDERS THIS DRIVE + DPB I,[DUNFLD A] + DATAO DPC,A + DATAI DPC,B + MOVEI A,*NBLKSC ;RP02 + TRNE B,2000 + MOVEI A,*NBLKSC ;RP03 +];RP +.ELSE MOVEI A,*NBLKSC +IFN T300P,[ + CAIL I,T300P + MOVEI A,*NBLKC1 ;T-300 +];T300P + MOVEM A,SEKCY2' + SETZM SEKCY1' +SEKTS1: SETZM SEKHDN' ;RESET HEAD +SEKTS2: MOVE J,SEKCY1 ;BLOCK ADDRESS OF OUTER CYLINDER + ADD J,SEKHDN ;SELECT A BLOCK ON THE DESIRED HEAD + MOVEI A,CYLBUF + X READ ;READ IT + SKIPGE T +SEKTS3: X GSTS ;JFCL THIS IF YOU DON'T WANT ERROR MESSAGES + MOVE J,SEKCY2 ;BLOCK ADDRESS OF INNER CYLINDER + ADD J,SEKHDN ;SELECT SAME HEAD + MOVEI A,CYLBUF + X READ + SKIPGE T + XCT SEKTS3 + PUSHJ P,TYIPSE + MOVEI J,NSECS/SECBLK ;ADVANCE TO NEXT HEAD + ADDB J,SEKHDN + CAIGE J,NBLKSC ;SKIP IF TOUCHED ALL HEADS + JRST SEKTS2 + MOVN B,SEKINC ;YES, CHANGE CYLINDERS + ADDB B,SEKCY2 + MOVE C,SEKINC + ADDB C,SEKCY1 + CAMG C,B + JRST SEKTS1 + JRST SEKTS0 ;RECYCLE + +THWO: PUSH P,A + PUSH P,B + TLNN A,-1 + JRST THWO1 + HLRZS A + X TOPT + TYPE ,, + HRRZ A,-1(P) +THWO1: X TOPT + POP P,B + POP P,A + POPJ P, + DC,[ + SUBTTL DC-10 PACK FORMATTING +MARK: JSR INIT + X CRR + UNTMES FORMAT PACK ON UNIT # + PUSHJ P,NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + PUSHJ P,CRR + HRRZ TT,QTRAN(A) + CONO DC1,(TT) ;SETUP DRIVE # FOR LATENCY TIMER + MOVEM A,TOU + MOVE I,A + PUSHJ P,RECAL + CONSO DC1,DFUNSF\DOFFL + JRST MARK1 + TYPE DRIVE OK? + JRST CRDDT + +MARK1: MOVE A,[DSPC+DSCWIM+DSWIDX+DSWNUL] + MOVEM A,CYLBUF + MOVEI D,CYLBUF+1 + PUSHJ P,RDLAT ;READ LATENCY TIMER + JUMPE A,.-1 +MARK1A: CONI DC1,A + CONI DC1,C + LDB A,[DSLAT A] + LDB C,[DSLAT C] + CAME A,C + JRST MARK1A + JUMPN A,[MOVE B,A + JRST MARK1A] +IFN 0,[ ;THIS HARDWARE HAS BEEN BROKEN FOR YEARS + PUSH P,B + MOVE A,B + IDIVI A,10. ;NO. OF MILLISECONDS + PUSH P,B + PUSHJ P,TDPT + MOVEI A,". + PUSHJ P,TYO + POP P,A + ADDI A,"0 + PUSHJ P,TYO + TYPE MILLISECONDS ROTATION TIME + PUSHJ P,CRR + POP P,B + CAIGE B,254. ;LIKELY JUST NO INDEX ON THIS PACK + JRST MARK1B + TYPE TOO DAMN LONG TO BE CREDIBLE, USING 24.5 MS. + PUSHJ P,CRR +];IFN 0 + MOVEI B,245. +MARK1B: IMULI B,1000 ;CONVERT TO NUMBER OF BITS/TRACK + IDIVI B,36. ;NO. OF WORDS PER SECTOR + AOJ B, + MOVEM B,MAXT' + SETZ A, + PUSHJ P,STOBLK ;ENOUGH ONES TO WIPE OUT THIS TRACK + MOVE J,MAXT + IDIVI J,NSECS + CAIL K,NSECS/2 + AOJ J, ;INTER-SECTOR GAP LENGTH + SUBI J,3+3+7+3011 ;HEADER CODE+HEADER DATA+"ONES"+BLOCK+CHECKSUM + MOVEI Q,NSECS +MARK1C: MOVEI B,(D) + HRLI B,HBLK ;SETUP COPYS FOR HEADER PREAMBLE,DATA,POSTAMBLE + ADDI D,3 + BLT B,-1(D) + MOVNI B,-NSECS(Q) + IMULI B,3 + ADDI B,DHEDR + HRRM B,-2(D) ;POINT COPY TO THIS SECTORS ENCODED DATA + MOVEI B,103. ;103 BLOCKS OF 10 ZEROS (ENCODED) + MOVE A,[QCOPY EZERS,15.,] + PUSHJ P,STBLK + SOJLE Q,MARK1D + MOVE B,J ;ENOUGH ONES TO FILL OUT REMAINING PART OF SECTOR + PUSHJ P,STOBLK + JRST MARK1C + +;SETUP STUFF FOR POSSIBLY WRITING READIN BLOCK +MARK1D: MOVE A,[QCOPY EONES,3,] + MOVEM A,(D) + AOJ D, + MOVSI A,(DOPR+DOHXFR) + MOVEM A,(D) + MOVEM D,RIWP' + ADDI D,2 + MOVE B,J + SUBI B,3+3+7+LRIBLK*3/2+3 ;HEADER+LRIBLK+CHECKSUM + LSH B,-1 + SUBI B,3*3 + PUSHJ P,STOBLK + MOVEI B,(D) + HRLI B,WRTRI + ADDI D,5 + BLT B,-1(D) + MOVSI A,(DJMP) ;PATCH JUMP AROUND RIBLK CODE, WILL BE CLOBBERED FOR BLOCK 0 ONLY + ADDI A,(D) + MOVE B,RIWP + MOVEM A,1(B) + MOVEI B,(D) + MOVEM B,ENDP' + AOS ENDP + HRLI B,RCBLK + ADDI D,5 + BLT B,-1(D) + MOVEI B,-3(D) ;PATCH AOJN .-1 ADDRESS + HRRM B,-2(D) + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVE I,TOU + MOVEM A,PKNUM(I) + MOVE I,[440300,,RIHEDR] ;ENCODE READIN HEADER + PUSHJ P,ENCI + MOVEI I,RIHED0 + PUSHJ P,HCOMP + MOVEI J,/NSECS-1 + MOVEM J,TRKN' + ;SO FAR +;WRITE IMAGE COMMAND - (START AT SECTOR PULSE) +;COPY ;ENOUGH TO WIPE OUT FULL TRACK +;(THEN FOR EACH SECTOR): + +;HEADER PREAMBLE +; ONES FOLLWED BY SINGLE ZERO +; 8 BYTES OF 10101 +; TWO 28 BIT HEADER WORDS +; A SERIES OF ONES FOLLWED BY 01 +;ENCODED ZEROS FOR DATA BLOCK (2004) WORDS + 2 WORDS CHECKSUM +;ENOUGH ENCODED ONES TO FILL OUT REST OF SECTOR (EXCEPT ON LAST SECTOR) + +;AFTER LAST SECTOR +;A FEW ONES +; NORMALLY: FOR BLOCK 0: +;RIWP: HANG FOR END OF TRANSFER WRITE ONES +; JUMP AROUND WRITE READIN WRITE ONES +; READIN HEADER PREAMBLE +; READIN HEADER +; READIN HEADER POSTAMBLE +; READIN BLOCK +; ONES TO PAD OUT REST OF TRACK +; DALU SETUP CONTROL COUNTER +;ENDP: READ COMPARE COMMAND +; COPY 4 WORDS ZEROS +; AOJN CC,.-1 +; HALT + +MARK2: MOVEI K,5 + MOVEM K,NTRYS' + SETZM DHED0 + CAIL J,NBLKS/NSECS + JRST MARK2C + MOVE I,TOU + MOVE A,PKNUM(I) + DPB A,[DPKID DHED0] ;PACK ID FOR HEADER + DPB A,[DPKID @ENDP] ;PACK ID FOR READ-COMPARE COMMAND + JUMPN J,MARK2C + MOVE B,RIWP + MOVE A,[QCOPY EONES,3,] + MOVEM A,(B) + MOVEM A,1(B) +MARK2C: IDIVI J,NHEDS + PUSH P,J + MOVE W,TOU + SKIPGE QTRAN(W) + ADDI J,NCYLS+XCYLS ;OFFSET IF DOUBLE SIZE PHYSICAL PACK +IRP A,,[CYLBUF,@ENDP,DHED0] ;SETUP INITIAL WRITE-IMAGE COMMAND + DPB J,[DCYL A] ; " READ-COMPARE COMMAND + DPB K,[DSURF A] ; " HEADER WORD +TERMIN + POP P,J ;VIRTUAL CYLINDER # + MOVEI W,0 + DPB W,[DHNXAD DHED1] + MOVEI W,1 ;END OF TRACK + CAIN K,NHEDS-1 + MOVEI W,2 ;END OF CYLINDER + CAIE J,NCYLS-1 + CAIN J,NCYLS+XCYLS-1 + TRO W,1 ;END OF DISK + MOVE I,[440300,,DHEDR] + PUSHJ P,ENCI + MOVEI I,DHED0 + MOVEI Q,NSECS +MARK2B: CAIN Q,1 ;PUT IN INCREMENT CODE + DPB W,[DHNXAD DHED1] + PUSHJ P,HCOMP ;ENCODE HEADERS + AOS DHED0 + SOJG Q,MARK2B +MARK2A: CONO DC0,DCCSET\DCDENB + DATAO DC0,[DJMP CYLBUF] + MOVE A,[DWLUP,,14] + BLT A,16 + JRST 14 ;WAIT IN AC'S FOR DISC, THEN FALL THRU +MARK2D: CONSO DC0,DSSERR + JRST MARK4 + CONSZ DC1,DCPERR\DNXM\DDOBSY + JRST MARK3A + CONSZ DC1,DPROT + JRST MARK3B + CONSZ DC1,DOFFL\DFUNSF + JRST MARK3C + CONSO DC1,DWTHER\DCKSER\DOVRRN\DRCER\DRLNER + JRST MARK3D +MTROV: SOSLE NTRYS + JRST MARK2A + CONSZ DC1,DOVRRN + JRST MARK3A + TYPE DISK BAD + JRST CRDDT + +DWLUP: CONSZ DC0,DSSACT + JRST 14 + JRST MARK2D + +MARK3A: TYPE MACHINE LOSSAGE + JRST CRDDT + +MARK3B: TYPE NOT WRT ENABLED + JRST CRDDT + +MARK3C: TYPE DRIVE LOSSAGE + JRST CRDDT + +MARK3D: TYPE CONTROLLER LOSSAGE + JRST CRDDT + +MARK4: SOSL J,TRKN + JRST MARK2 +];DC + +;INITIALIZE MFD AND TUT +; TOU AND PKNUM+n MUST BE ALREADY SET UP + +MARK69: MOVE I,TOU + X MFDINN + TYPE SWAPPING ALLOC = + PUSHJ P,OTYI + PUSHJ P,CRR + X TUTINI + MOVE A,PKNUM(I) + MOVEM A,TUT+QPKNUM + TYPE PACK # = + X TDPT + X CRR + TYPE PACK ID = + PUSHJ P,6TYI + PUSHJ P,CRR + MOVEM B,TUT+QPAKID + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,WRITT + JUMPL T,WRERR + MOVE A,TUT+QSWAPA ;SET UP FREE SPACE POINTER + CAMGE A,NUDS + MOVE A,NUDS + ADDI A,NBLKSC-1 ;JUST IN CASE QSWAPA NOT ON CYLINDER BOUNDARY + IDIVI A,NBLKSC + IMULI A,NBLKSC + MOVEM A,TUT+QTUTP + MOVEI A,TUT + PUSHJ P,WRTUT + JUMPL T,WRERR + JRST DDT + +6TYI: MOVE C,[440600,,B] + MOVEI B,0 +6TYL: PUSHJ P,TYI + SUBI A,40 + JUMPLE A,CPOPJ + TLNE C,770000 + IDPB A,C + JRST 6TYL + DC,[ +HCOMP: SETOM HPAR' + MOVEI J,(I) + HRLI J,-2 +HCOMP1: MOVEI B,14. + MOVE A,(J) + XORM A,HPAR + LSH A,-2 + SOJG B,.-2 + AOBJN J,HCOMP1 + + MOVE B,(I) + PUSHJ P,ENCH + MOVE B,HPAR + ANDI B,3 + LSH B,20. + XORB B,1(I) + PUSHJ P,ENCH + MOVSI B,770000 +HCOMP2: TDNN B,DSKBP + POPJ P, + PUSHJ P,ENCDO + JRST HCOMP2 + +ENCO: SKIPA A,C1 +ENCZ: MOVEI A,0 +ENC: ANDI A,1 + HRRZ T,ENCS' + JRST @ENCT(T) + +ENCT: ENC1 + ENC2 + ENC1 + ENCZ2 + +ENCDO: SKIPA A,[3] +ENCDZ: MOVEI A,0 +ENCD: ANDI A,3 + HRRZ T,ENCS + JRST @ENCDT(T) + +ENCDT: ENC2A + [JRST 4,.] + ENCZ2A + [JRST 4,.] + +ENC1: HRLM A,ENCS +ENC1A: AOS ENCS + POPJ P, + +ENC2: ROT A,-1 + HLR A,ENCS + ROT A,2 + JRST ENC2B +ENC2A: LSH A,1 + AOS ENCS +ENC2B: JUMPE A,ENC1A +C1: TRO A,1 + IDPB A,DSKBP' +ENC3: SETZM ENCS + POPJ P, + +ENCZ2: ROT A,-1 + HLR A,ENCS + JRST .+2 +ENCZ2A: ROT A,-1 + ASH A,2 + TRO A,2 + IDPB A,DSKBP + ROT A,2 + TRO A,5 + IDPB A,DSKBP + JRST ENC3 + +ENCH: LSH B,36.-28. + SKIPA C,[14.] +ENCW: MOVEI C,18. + LSHC A,2 + PUSHJ P,ENCD + SOJG C,.-2 + POPJ P, + +ENCI: MOVEM I,DSKBP + SETZM ENCS + POPJ P, + +RDLAT: CONI DC1,A ;READ LATENCY TIMER INTO A + LDB A,[DSLAT A] +RDLAT2: MOVEM A,T + CONI DC1,A + LDB A,[DSLAT A] + CAME A,T + JRST RDLAT2 + POPJ P, + +STBLK: MOVEM A,(D) ;STORE C(A) IN B WORDS AT D + SOJLE B,[AOJA D,CPOPJ] + HRLI D,1(D) + ADDI B,1(D) + MOVS D,D + EXCH B,D + BLT B,-1(D) + POPJ P, + +STOBLK: MOVE A,[QCOPY EONES,LOBLK,] + IDIVI B,LOBLK + JUMPE B,STOBL3 ;LESS THAN ONE BLOCK NEEDED?? + JUMPE C,STOBL2 + CAIL C,3 + JRST STOBL2 + SOJ B, + ADDI C,LOBLK +STOBL2: PUSHJ P,STBLK +STOBL3: CAIGE C,3 + MOVEI C,3 + MOVNI C,(C) + DPB C,[DCWC A] + MOVEM A,(D) + AOJA D,CPOPJ + +HBLK: QCOPY PREAMB,3, ;NORMAL HEADER + QCOPY .,3, + QCOPY POSTMB,7, + +WRTRI: QCOPY PREAMB,3, ;READIN HEADER, DATA BLOCK + QCOPY RIHEDR,3, + QCOPY POSTMB,7, + QCOPY EZERS,, + QCOPY EONES,3, + +RCBLK: DALU+DLCC+DLLB -401*NSECS(3) ;READ COMPARE "LOOP" FOR DATA WORDS + DRCC + QCOPY ZERS,4 + DJMP+DAOJNC . + DHLT + +LOBLK==60 + +DHED0: 0 +DHED1: -2004&37777 +DHEDR: BLOCK 3*NSECS + + +RIHED0: 0 +RIHED1: -LRIBLK&37777 +RIHEDR: BLOCK 3 + +EZERS: REPEAT LRIBLK*3/2+3,252525252525 + +EONES: REPEAT LOBLK+3,-1 + +PREAMB: -1 ;ONES + -26 ;ONES...0.1010 + 655326553265 ;1.10101.10101.10101.10101.10101.10101.10101 + +POSTMB: REPEAT 6,-1 ;ONES...01 + -3 + +ZERS: BLOCK 4 +];DC + +RH,[ + SUBTTL RH-10 PACK FORMATTING + +MARK: JSR INIT + SETZM CERRS +KL,[ SWPUA ;TURN THE CACHE OFF + CONSZ APR,200000 + JRST .-1 + CONI PAG,A + TRZ A,600000 + CONO PAG,(A) +];KL + X CRR + UNTMES FORMAT PACK ON UNIT # + X NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + X CRR + MOVE I,A + MOVEM I,TOU + SETOM MARKF + PUSHJ P,RESET + SETZM MARKF + TYPE ARE YOU SURE YOU WANT TO FORMAT PACK ON DRIVE # + X TOPT + TYPE ? + X TYI + X CRR + CAIE A,"Y + JRST DDT + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVEM A,PKNUM(I) + MOVSI A,%HRSER ;GET DRIVE SERIAL NUMBER + PUSHJ P,RHGET + JRST RHMKER + HRLZ D,A + TLZ D,600000 ;FIRST "KEY" WORD IS SERIAL NO OF DRIVE FORMATTED ON + HRR D,PKNUM(I) ;SECOND "KEY" WORD IS I.T.S. PACK NUMBER + SETZB A,B ;GENERATE PATTERN FOR SURFACE +RHFMP1: MOVEM B,CYLBUF(A) ;CYL 0 TRACK 0 SECTOR (B) IS FIRST HEADER WORD + MOVEM D,CYLBUF+1(A) ;PUT DRIVE SERIAL NUMBER IN 3.1-4.7 OF HDR WD 2 + ADDI A,2 + SETZB C,H ;FILL SECTOR WITH WORST CASE PATTERN +RHFMP2: MOVE T,RHWC(H) + MOVEM T,CYLBUF(A) + AOS H + CAIL H,RHWCL + MOVEI H,0 + AOS A + CAIGE C,200-1 + AOJA C,RHFMP2 + CAIGE B,NSECS-1 ;DO NEXT SECTOR + AOJA B,RHFMP1 + CAIE A,202*NSECS + JRST 4,. ;WRONG AMOUNT OF CRUFT GENERATED + MOVE A,[-202*NSECS_4,,CYLBUF-1] ;SET UP IOWD + MOVEM A,SLVIOWD + SETZM SLVIOWD+1 + MOVEI A,SLVIOWD + MOVEM A,SLVICWA + JRST RHFMT0 ;GO FORMAT + +RHWC: 726666666676 ;RP04 10-MODE WORST CASE PATTERN + 555555555753 + 333333337266 + 666666765555 + 555557533333 + 333372666666 + 667655555555 + 573333333333 +RHWCL==.-RHWC + +RHMKER: TYPE DISK ERROR + X CRR + PUSHJ P,GSTS + JRST DDT + +RHFMT0: MOVEI J,NCYLS+XCYLS +RHFMT1: SOJL J,RHFMT4 ;LOOP ON CYLINDERS + MOVEI K,NHEDS +RHFMT2: SOJL K,RHFMT1 ;LOOP ON SURFACES + MOVEI B,NSECS ;ADJUST THE HEADER WORDS + MOVEI C,0 +RHFMT3: DPB J,[221100,,CYLBUF(C)] + DPB K,[100500,,CYLBUF(C)] + ADDI C,202 + SOJG B,RHFMT3 + MOVSI A,%HRADR ;SET UP ADDRESS IN DRIVE + DPB K,[$HATRK A] + PUSHJ P,RHSET + JRST RHMKER + MOVSI A,%HRCYL ;LEAVE CYLINDER NUMBER IN RH10 "DIB" LIGHTS + HRR A,J + PUSHJ P,RHSET + JRST RHMKER + SETZM SLVICWA+1 + MOVSI A,%HRCTL ;SET UP WRITE HEADERS AND DATA COMMAND + HRRI A,%HMWHD + MOVEI B,SLVICWA + DPB B,[$HCICWA A] + PUSHJ P,RHSET + JRST RHMKER + CONSO DSK,%HIDONE + JRST .-1 + CONSZ DSK,%HIERR + JRST RHMKER + JRST RHFMT2 + +RHFMT4: TYPE FORMATTING COMPLETE, VERIFICATION BEGINS + X CRR + MOVEI J,NCYLS+XCYLS-1 +RHFMT5: MOVEI A,CYLBUF + PUSHJ P,READCY + JUMPGE T,RHFMT6 + TYPE CYLINDER + MOVE A,J + X TOPT + TYPE IN ERROR + X CRR + X GSTS + X CRR + JRST RHFMT9 + +RHFMT6: SETZB A,H ;VERIFY DATA. RELIES ON SECTOR SIZE BEING +RHFMT7: MOVE B,CYLBUF(A) ; A MULTIPLE OF RHWCL + CAME B,RHWC(H) + PUSHJ P,RHFMT8 + ADDI H,1 + CAIL H,RHWCL + MOVEI H,0 + CAIGE A,200*NSECS + AOJA A,RHFMT7 +RHFMT9: SOJGE J,RHFMT5 + SKIPN A,CERRS + JRST RHFMTX + X TDPT + TYPE ECC-CORRECTED ERRORS DURING VERIFICATION. +RHFMTX: X CRR + JRST MARK69 ;HARDWARE FORMATTED, DO SOFTWARE + +RHFMT8: PUSH P,A + TYPE WORD + X TOPT + TYPE OF CYLINDER + MOVE A,J + X TOPT + TYPE CORRECT + MOVE A,RHWC(H) + X TOPT + TYPE ACTUAL + MOVE A,B + X TOPT + X CRR + JRST POPAJ +];RH + +RP,[ + SUBTTL RP-10 PACK FORMATTING + +MARK: JSR INIT +KL,[ SWPUA ;TURN THE CACHE OFF + CONSZ APR,200000 + JRST .-1 + CONI PAG,A + TRZ A,600000 + CONO PAG,(A) +];KL + X CRR + UNTMES FORMAT PACK ON UNIT # + X NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + X CRR + MOVE I,A + MOVEM I,TOU + SETOM MARKF + PUSHJ P,RESET + SETZM MARKF + MOVSI A,(DNOOPC) ;DETERMINE TYPE OF DRIVE + DPB I,[DUNFLD A] + DATAO DPC,A + DATAI DPC,A + MOVEI B,"2 + MOVEI C,NCYLS+XCYLS + TRNN A,2000 + JRST .+3 + MOVEI B,"3 + MOVEI C,MCYLS+XCYLS + MOVEM C,LAST + TLNE A,1 + JRST [ TYPE WRITE HEADER LOCKOUT SWITCH IS ON + JRST CRDDT ] + TYPE ARE YOU SURE YOU WANT TO FORMAT PACK ON RP0 + MOVE A,B + X TYO + TYPE # + MOVE A,I + X TOPT + TYPE ? + X TYI + X CRR + CAIE A,"Y + JRST DDT + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVEM A,PKNUM(I) + SETZB A,B ;GENERATE TEMPLATE TRACK +RPFMP1: MOVEI T,31. ;SYNC ZONE OF 30 ZERO WORDS + SETZM CYLBUF(A) + AOS A + SOJG T,.-2 + AOS CYLBUF-1(A) ;AND ONE WORD CONTAINING 1 IN BIT 35 + MOVEM B,CYLBUF(A) ;THEN ADDRESS WORD +REPEAT 4,SETZM CYLBUF+1+.RPCNT(A) ;THEN ADDR PARITY WORD AND 3 ZERO WORDS SYNC + ADDI A,5 + MOVE T,RPWC ;THEN 128 DATA WORDS OF WORST CASE PATTERN + MOVEM T,CYLBUF(A) + MOVSI T,CYLBUF(A) + HRRI T,CYLBUF+1(A) + BLT T,CYLBUF+177(A) + ADDI A,200 + CAIGE B,NSECS-1 ;DO NEXT SECTOR + AOJA B,RPFMP1 + CAIE A,244*NSECS + JRST 4,. ;WRONG AMOUNT OF CRUFT GENERATED + MOVE A,[-244*NSECS,,CYLBUF-1] ;SET UP IOWD + MOVEM A,SLVIOWD + SETZM SLVIOWD+1 + MOVEI A,SLVIOWD + MOVEM A,SLVICWA + JRST RPFMT0 ;GO FORMAT + +RPMKER: TYPE DISK ERROR + X CRR + PUSHJ P,GSTS + JRST DDT + +RPFMT0: MOVE J,LAST ;HIGHEST CYLINDER # + 1 +RPFMT1: SOJL J,RPFMT4 ;LOOP ON CYLINDERS + MOVEI K,NHEDS +RPFMT2: SOJL K,RPFMT1 ;LOOP ON SURFACES + MOVEI B,NSECS ;ADJUST THE HEADER WORDS + MOVEI C,0 +RPFMT3: DPB J,[121100,,CYLBUF+37(C)] + DPB K,[050500,,CYLBUF+37(C)] + MOVE D,CYLBUF+37(C) ;COMPUTE HEADER PARITY WORD + MOVEI T,36. + MOVSI TT,(SETZ) ;ODD PARITY +RPFMTP: TRNE D,1 + TLC TT,(SETZ) + ROT D,1 + SOJG T,RPFMTP + MOVEM TT,CYLBUF+40(C) + ADDI C,244 + SOJG B,RPFMT3 + MOVSI A,300000 ;WRITE FORMAT + ADDI A,SLVICWA + DPB J,[DCYL A] + ROT J,-8 ;EXTRA BIT FOR RP03 + DPB J,[DCYLXB A] + ROT J,8 + DPB K,[DSURF A] + DPB I,[DUNFLD A] + MOVEM J,RPIOCY + PUSHJ P,SEEK + JRST RPMKER + DATAO DPC,A + CONSO DPC,DONE + JRST .-1 + CONSZ DPC,ALLER + JRST RPMKER + JRST RPFMT2 + +RPFMT4: TYPE FORMATTING COMPLETE, VERIFICATION BEGINS + X CRR + SOS J,LAST +RPFMT5: MOVEI A,CYLBUF + PUSHJ P,READCY + JUMPGE T,RPFMT6 + TYPE CYLINDER + MOVE A,J + X TOPT + TYPE DOESN'T READ -- GIVING UP ON IT. + X CRR + X GSTS + X CRR + JRST RPFMT9 + +RPFMT6: SETZB A,H ;VERIFY DATA. + MOVE D,RPWC + LSH D,1 ;CONTROL DROPS ONE BIT DURING WRITE FORMAT +RPFMT7: MOVE B,CYLBUF(A) + CAME B,D + PUSHJ P,RPFMT8 + CAIGE A,200*NSECS + AOJA A,RPFMT7 +RPFMT9: SOJGE J,RPFMT5 + X CRR + JRST MARK69 ;HARDWARE FORMATTED, DO SOFTWARE + +RPFMT8: PUSH P,A + TYPE WORD + X TOPT + TYPE OF CYLINDER + MOVE A,J + X TOPT + TYPE CORRECT + MOVE A,RPWC + X TOPT + TYPE ACTUAL + MOVE A,B + X TOPT + X CRR + JRST POPAJ + +RPWC: 714533,,462556 ;WORST CASE PATTERN +];RP +CONSTA +];NTS + NTS,[ +SUBTTL MFDR - RECONSTRUCT MFD FROM UFDS + +MFDR: MOVEI P,PDL + PUSHJ P,CRR ;RECONSTRUCT MFD BY GETTING NAMES FROM UFD'S + UNTMES RECONSTRUCT MFD FROM UNIT # + PUSHJ P,NTYI + JRST MFDR + MOVE I,A + PUSHJ P,MFDINN + SETOM IMNFLG + MOVEI J,0 +MFDR1: MOVEI A,TUT + PUSHJ P,READ + JUMPL T,MFDRL + MOVE B,TUT+UDESCP ;LOOK LIKE LEGIT UFD? + TLNE B,-1 + JRST MRUFDL ;SHOULD BE F.S. PNTR + CAIL B,<2000.-11.>*6 + JRST MRUFDL + MOVE B,TUT+UDNAMP + SKIPE TUT+UDNAME ;USER NAME + TLNE B,-1 + JRST MRUFDL ;PNTR TO BEG OF NAME AREA + MOVEI B,(J) ;CONVERT BLOCK NO TO MFD INDEX + SUB B,NUDS + LSH B,1 + ADDI B,2000 + MOVE C,TUT+UDNAME ;USER NAME + MOVEM C,MFD(B) + AOSN IMNFLG + MOVEM B,MFD+MDNAMP + JRST MRUFDW + + +MFDRL: JRST 4,.+1 +MRUFDL: JFCL +MRUFDW: + ADDI J,1 + CAMGE J,NUDS + JRST MFDR1 + TYPE WRITE? + PUSHJ P,TYI + CAIE A,"Y + JRST DDT +MFDWR: MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,WRITE + JRST DDT +];NTS + +IMNFLG: 0 + +SUBTTL INITIALIZE MFD + +MFDINN: CLEARM MFD + MOVE A,[MFD,,MFD+1] + BLT A,MFD+1777 + MOVE A,[SIXBIT /M.F.D./] + MOVEM A,MFD+MDCHK + MOVE A,NUDS + MOVEM A,MFD+MDNUDS + MOVEI A,2000 + MOVEM A,MFD+MDNAMP + POPJ P, + +SUBTTL INITIALIZE TUT + +;DRIVE NUMBER IN I, SWAPPING ALLOC IN A + +TUTINI: CLEARM TUT + MOVE B,[TUT,,TUT+1] + BLT B,TUT+<2000*MXTUTB>-1 + MOVEM A,TUT+QSWAPA + MOVE K,A + CAMGE K,NUDS + MOVE K,NUDS ;K HAS BASE OF FILE AREA + MOVEI J,NBLKS ;DETERMINE HOW MANY BLOCKS THIS DRIVE +RP,[ MOVSI A,(DNOOPC) + DPB I,[DUNFLD A] ;SELECT DRIVE + DATAO DPC,A + DATAI DPC,A + TRNE A,2000 + MOVEI J,MBLKS ;RP03 HAS MORE BLOCKS +];RP +IFN T300P,[ + CAIL I,T300P + MOVEI J,NBLKS1 +];T300P + MOVEM J,TUT+QLASTB ;LAST REGULAR BLOCK IS LAST TUT'ED +IFN T300P,[ + MOVEI A,<2000*NTUTBL-LTIBLK>*TUTEPW + CAIL I,T300P + MOVEI A,<2000*NTUTB1-LTIBLK>*TUTEPW + SUB J,A +];T300P +.ELSE SUBI J,<2000*NTUTBL-LTIBLK>*TUTEPW ;SUBTRACT MAX NUMBER OF TUTABLE BLOCKS + CAMLE J,K ;IS THERE ROOM FOR ALL OF FILE AREA? + JRST 4,. ;NOPE + SKIPGE J + MOVEI J,0 + MOVEM J,TUT+QFRSTB + MOVEI A,TUT +TUTFIL: MOVEI K,TUTLK ;ENTER HERE FROM SALV1, A -> TUT + MOVSI D,440000+TUTBYT_6 + ADDI D,LTIBLK(A) + MOVE B,NUDS + SUB B,QFRSTB(A) + JUMPLE B,TUTI1A +TUTI1: IDPB K,D ;MARK OUT USER DIR AREA + SOJG B,TUTI1 + +TUTI1A: MOVEI B,(A) + MOVSI D,-LSBTAB +TUTI2: SKIPGE J,SBTAB(D) + JRST TUTI3 ;NOT REALLY THERE + PUSHJ P,TUTPNT + MOVEI K,TUTLK + DPB K,J ;MARK OUT BLOCK +TUTI3: AOBJN D,TUTI2 + MOVE D,NTBL(I) ;MARK OUT TUT (SIZE VARIES) +TUTI4: MOVE J,MFDBK + SUB J,D + PUSHJ P,TUTPNT + MOVEI K,TUTLK + DPB K,J + SOJG D,TUTI4 + POPJ P, + +;TUTPNT - ROUTINE TO ACCESS THE TUT +; CALL WITH BLOCK NUMBER IN J, POINTER TO TUT IN B +; RETURNS WITH BYTE POINTER IN J (0 IF BLOCK NOT TUT'ED) +; K IS CLOBBERED +; +;TUTPNN - SAME BUT CALL WITH DISK NUMBER IN I, CLOBBERS B TO NEW TUT ADDR +; +;TUTPNO - SAME BUT CALL WITH DISK NUMBER IN I, CLOBBERS B TO OLD TUT ADDR + +TUTPNN: SKIPA B,QNTUTO(I) + +TUTPNO: MOVE B,QOTUTO(I) + +TUTPNT: CAMGE J,QLASTB(B) + CAMGE J,QFRSTB(B) + TDZA J,J + CAIA + POPJ P, ;BLOCK NOT TUT'ED, RETURN J=0 + SKIPGE QPKNUM(B) + JRST [ TYPE OLD FORMAT TUT? + JRST ERRDDT ] + SUB J,QFRSTB(B) + IDIVI J,TUTEPW + HLL J,QTTBL(K) + ADDI J,LTIBLK(B) + POPJ P, + SUBTTL MAIN SALVAGER + +GOGO: JRST GOGO0 ;VECTOR OF MYSTERIES +SALVAG: JRST GOGO1 ;(IN CASE UP CREEK WITHOUT SYMBOL TABLE) +CHKR: JRST CHKR0 +NTS,[ + JFCL LPBUST ;-> LPT BUSTED FLAG + JFCL NOQUES ;-> NO QUESTIONS FLAG + JFCL GOODUN ;-> ONLY ROUTINE THAT KNOWS WHICH ARE "RIGHT" PACKS + JFCL GETSTS ;-> ROUTINE TO TYPEOUT CURRENT DISK STATUS + JFCL DSKTST ;-> SIMPLE READ/WRITE TEST + JFCL SEKTST ;-> SIMPLE SEEK TEST (READ ONLY) + JFCL DUP ;-> DISK COPYING ROUTINE + JFCL HCRASH ;-> AS FAST AS POSSIBLE FLAG +];NTS + +GOGO1: JSR INIT + SETOM NOQUES ;IF STARTED BY BEG$G IN ITS, BE FAST. + JRST GOGO2 ;(NO ROUTINE TYPEOUT) + +GOGO0: JSR INIT +GOGO2: SETOM GOGOX ;AUTOMATIC MODE + TYPE SALVAGER. + MOVE A,[.FNAM2] + X T6B + X CRR + MOVEI A,NUNITS-1 + SETOM QACT(A) ;ALL UNITS ACTIVE + SOJGE A,.-1 + PUSHJ P,ACTUN ;ACTIVATE ALL UNITS THAT ARE ON-LINE + PUSHJ P,GOODUN ;MAKE SURE ALL PACKS THAT SHOULD BE MOUNTED ARE + MOVEM I,MDSK ;FIRST ACTIVE UNIT IS DSK TO GET MFD FROM + MOVEM I,UDSK ;.. DSK TO GET UFD'S FROM + PUSHJ P,DRPHAS ;VERIFY THAT DIRECTORIES ON ALL PACKS ARE IN PHASE + SETZM CKFLSW ;DON'T CHECK ALL BLOCKS + JRST SALV1 + +CHKR0: JSR INIT ;ASK QUESTIONS MODE + TYPE SALVAGER. + MOVE A,[.FNAM2] + PUSHJ P,T6B + PUSHJ P,CRR + MOVEI A,NUNITS-1 + SETZM QACT(A) + SOJGE A,.-1 + TYPE ACTIVE UNITS ARE: +CHKR1: PUSHJ P,NTYI + JRST CHKR2 + CAIGE A,NUNITS + SETOM QACT(A) + JRST CHKR1 + +CHKR2: PUSHJ P,CRR + PUSHJ P,ACTUN +CHKR3: UNTMES USE MFD FROM UNIT: + PUSHJ P,NTYI + JRST CHKR3 + CAIGE A,NUNITS + SKIPN QACT(A) + JRST CHKR3 + MOVEM A,MDSK + PUSHJ P,CRR + PUSHJ P,DRPHAS ;VERIFY THAT DIRECTORIES ON ALL PACKS ARE IN PHASE + SETZM CKFLSW + SETZM CKFIX +DC, TYPE CHECK FILES FOR CLOBBERED BLOCKS? +.ELSE TYPE READ ALL BLOCKS OF ALL FILES? + PUSHJ P,TYI + CAIN A,"Y + SETOB A,CKFLSW + PUSHJ P,CRR + JUMPGE A,CHKR4 +DC,[ TYPE FIX POINTERS THEN? + SETOM CKFIX + X Y.OR.N + SETZM CKFIX +];DC +CHKR4: UNTMES GET USR DIRS FROM UNIT: + PUSHJ P,NTYI + JRST CHKR4 + CAIGE A,NUNITS + SKIPN QACT(A) + JRST CHKR4 + PUSHJ P,CRR + MOVEM A,UDSK + JRST SALV1 + +ACTUN: MOVEI C,NUNITS-1 +ACTUN2: SKIPN QACT(C) + JRST ACTUN1 + MOVE I,C + PUSHJ P,RESET + SKIPN QACT(C) ;STILL THERE? + JRST ACTUN1 + MOVE I,C + MOVE A,QOTUTO(I) + PUSHJ P,RDTUT + JUMPL T,ACTUE1 + MOVE I,QOTUTO(C) + MOVE A,QPKNUM(I) + ANDI A,37 + MOVEM A,QPKN(C) + SKIPE NOQUES + JRST ACTUN1 + TYPE UNIT # + MOVE A,C + PUSHJ P,DPT + TYPE ID IS + MOVE A,QPAKID(I) + PUSHJ P,T6B + TYPE PK # + MOVE A,QPKNUM(I) + PUSHJ P,TDPT +IFN DC10P+RH10P,[ + MOVE A,PKNUM(C) + CAMN A,QPKNUM(I) + JRST ACTUN4 +IFN T300P,[ + CAIL C,T300P + JRST ACTUN4 ;PKNUM NOT REALLY SET UP +];T300P + TYPE (HARDWARE SAYS + PUSHJ P,TDPT + TYPE ) +ACTUN4: ] + SKIPN A,QTRSRV(I) + JRST ACTUN5 + CAMN A,[-1] + JRST [ TYPE (RESERVED) + JRST ACTUN5 ] + PUSHJ P,TSPAC + PUSHJ P,SIXTYP + TYPE : +ACTUN5: PUSHJ P,CRR +ACTUN1: SOJGE C,ACTUN2 + SETOM ACTIVE + POPJ P, + +ACTUE1: TYPE Error reading TUT block + PUSHJ P,CRR + PUSHJ P,GSTS + JRST ERRDDT + +ACTUE3: TYPE Error reading MFD block + PUSHJ P,CRR + PUSHJ P,GSTS + JRST ERRDDT +ACTIVE: 0 ;-1 IF ALREADY HAVE RESET DRIVES + +;MAKE SURE ALL NECESSARY PACKS ARE MOUNTED +GOODUN: +NTS,[ MOVEI A,FIRSPK ;AND RETURN MASTER DISK # IN I +GOODN1: MOVEI C,NUNITS-1 +GOODN2: SKIPE QACT(C) + CAME A,QPKN(C) + SOJGE C,GOODN2 + JUMPL C,GOODN3 ;THIS PACK MISSING + CAIGE A,LASTPK + AOJA A,GOODN1 + MOVEI A,LASTPK-FIRSPK+1 ;NUMBER OF PRIMARY PACKS + MOVEI C,NUNITS-1 ;SCAN FOR SECONDARY PACKS +GOODN4: SKIPN QACT(C) + JRST GOODN5 + MOVE B,QOTUTO(C) + SKIPE B,QTRSRV(B) + CAMN B,[-1] + JRST GOODN5 + ADDI A,1 ;THIS SECONDARY PACK IS OK TO HAVE MOUNTED +GOODN5: SOJGE C,GOODN4 +];NTS + MOVEI C,NUNITS-1 ;AND FIND MASTER DISK (LOWEST NUMBERED ACTIVE UNIT) + SKIPE QACT(C) ;ALSO COMPUTE GOOD PACKS - ALL PACKS IN A + JRST [ MOVE I,C + SOJA A,.+1 ] + SOJGE C,.-2 +NTS, JUMPGE A,CPOPJ +NTS, TYPE EXTRA PACKS MOUNTED. +NTS, JRST ERRDDT +TS, POPJ P, + +GOODN3: TYPE PACK # + X TDPT + TYPE NOT MOUNTED + JRST ERRDDT + +TS, DRPHAS: POPJ P, +NTS,[ +;CHECK THAT DIRECTORIES ARE IN PHASE ON ALL PACKS +DRPHAS: MOVEI I,NUNITS-1 +DRPHS1: SKIPN QACT(I) ;FIRST, GET ALL THE MFDS + JRST DRPHS2 + MOVE J,MFDBK + MOVE A,QNTUTO(I) + PUSHJ P,READ + JUMPL T,ACTUE3 +DRPHS2: SOJGE I,DRPHS1 + MOVE I,MDSK ;GET MASTER DISK'S ASCENDING DIRECTORY NUMBER + MOVE A,@QNTUTO(I) .SEE MDNUM + MOVE B,A + SUBI B,1 + MOVEI I,NUNITS-1 ;SEE IF ALL OTHERS ARE THE SAME, OR AT MOST 1 LESS +DRPHS3: SKIPE QACT(I) + JRST [ CAMG B,@QNTUTO(I) .SEE MDNUM + CAMGE A,@QNTUTO(I) .SEE MDNUM + JRST DRPHS6 + JRST .+1 ] + SOJGE I,DRPHS3 + POPJ P, + +DRPHS6: TYPE DIRECTORIES OUT OF PHASE. + X CRR + MOVEI I,0 +DRPHS4: SKIPN QACT(I) + JRST DRPHS5 + UNTMES UNIT # + HRRZ A,I + X TOPT + TYPE PACK # + MOVE A,QPKN(I) + X TDPT + TYPE , MDNUM= + MOVE A,@QNTUTO(I) .SEE MDNUM + X TOPT + X CRR +DRPHS5: CAIGE I,NUNITS-1 + AOJA I,DRPHS4 + TYPE VERIFY THAT THE PROPER PACKS ARE MOUNTED. IF YOU AREN'T SURE, + X CRR + TYPE GET HELP. IF THEY ARE PROPER, AND ONE IS JUST COMING ON-LINE + X CRR + TYPE AFTER BEING OFF FOR A WHILE, YOU WILL HAVE TO UCOP TO IT. + SKIPE GOGOX + JRST ERRDDT + JRST CRR +];NTS + +SALV1: SETZM MFDWRT ;-1 IF MFD MODIFIED (DIRECTORIES DELETED) + SETZM SHARED + MOVEI I,NUNITS-1 +SALV2: SKIPN QACT(I) + JRST SALV3 + HRRZ B,QNTUTO(I) ;ZERO OUT NEW TUT + HRL B,B + SETZM (B) + MOVE A,B + AOS B + BLT B,2000*MXTUTB-1(A) + HRRZ B,QNTUTO(I) ;COPY RANDOM INFO FROM OLD TUT TO NEW + HRL B,QOTUTO(I) + MOVE A,B + BLT A,LTIBLK-1(B) + HRRZ A,QNTUTO(I) + PUSHJ P,TUTFIL ;FILL IN BLOCKS AREA OF TUT +SALV3: SOJGE I,SALV2 + MOVE I,MDSK + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE A,MFD+MDNUDS + CAME A,NUDS + JRST [ TYPE Wrong NUDSL version = + X TDPT + JRST ERRDDT] + MOVE A,MFD+MDCHK + CAME A,[SIXBIT /M.F.D./] + JRST [ TYPE MFD check word garbaged? + X T6B + X CRR + SKIPN GOGOX + X CONTIN + JRST ERRDDT + JRST .+1] + MOVE Q,MFD+MDNAMP + ADDI Q,MFD +MFDLUP: CAIL Q,MFD+2000 + JRST MFDFIN + SKIPN A,MNUNAM(Q) + JRST MFDLU1 + PUSHJ P,USRLUP + SKIPN LFILES + PUSHJ P,DELUSR +MFDLU1: ADDI Q,LMNBLK + JRST MFDLUP + +DELUSR: MOVE A,MNUNAM(Q) + CAMN A,[SIXBIT /.LPTR./] + POPJ P, + PUSHJ P,T6B + TYPE ; NO FILES, USER DIRECTORY DELETED + PUSHJ P,CRR + SETZM MNUNAM(Q) + SETOM MFDWRT + POPJ P, + +USRLUP: MOVEM A,USRNAM + SETZM UFDLOS + SETZM UFDSEE ;-1 IF ANY ERROR OCCURS, PRINT WHOLE UFD + SETZM LFILES + MOVE J,Q + SUBI J,MFD+2000 ;MAP MFD ENTRY INTO UFD BLOCK + IDIVI J,LMNBLK ; -Nth USER DIRECTORY + ADD J,NUDS ;END OF USER DIR AREA - N + PUSH P,Q + PUSH P,UDSK ;SAVE UFD DISK, MIGHT CHANGE IF UFD IS BAD + MOVEM J,DBLK + MOVE I,UDSK +USRLU1: MOVEI A,OUSRD ;COME BACK TO HERE ON TRY NEXT DRIVE + PUSHJ P,READ + JUMPL T,USRLE2 + MOVE Q,OUSRD+UDNAME + CAME Q,USRNAM + JSR USRLE4 + MOVE Q,[OUSRD,,NUSRD] + BLT Q,NUSRD+1777 ;COPY OLD FOR GARBAGE CHECK + MOVEI Q,2000-LUNBLK+OUSRD + MOVEI J,OUSRD + ADD J,UDNAMP(J) ;LOWEST FILE NAME BLOCK + CAIG J,OUSRD+2000 + CAIGE J,OUSRD+UDDESC + JRST USRLE3 ;NAME POINTER OUTSIDE BLOCK! (try next drive) + MOVE T,OUSRD+UDESCP + IDIVI T,6 + ADDI T,OUSRD+UDDESC + CAML T,J + JRST USRLE7 ;NAME AND DESCRIPTOR AREAS OVERLAP (try next drive) + PUSH P,J ; FILE NAME POINTER + +;PER FILE LOOP +DIRL1: CAMGE Q,J + JRST USRFIN + SETOM FILEER ; PRINT FILE NAME ONLY ON FIRST ERROR + SETZM BADFIL ; SET IF BAD RETRIEVAL DISCOVERED + MOVEM Q,LASTQ + SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + CAIA + JRST DIRLUP + AOS LFILES + LDB C,[UNPKN UNRNDM(Q)] + LDB A,[UNDSCP UNRNDM(Q)] + CAML A,OUSRD+UDESCP + JRST DIRLE1 ;POINTS OUTSIDE DESC AREA (ignore) + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] + MOVEI ZR,0 + LDB B,A + JUMPN B,DIRLE2 ;NOT PRECEEDED BY ZERO (ignore) +DIRL2: MOVE N,A + MOVEI J,0 + ILDB B,A + JUMPE B,DIRLE3 ;POINTS TO ZERO (ignore) +DIRL3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST LINK + SETZM NOTUT + PUSHJ P,FINDPK ;FIND WHICH PACK + SKIPL C + SKIPN QACT(C) + SETOM NOTUT ;FILE ON UNMOUNTED PACK, DON'T HACK TUT + MOVEM C,FUNIT + SETZM LSTBLK + SETZM ADRSET +TRLUP: MOVE TT,N + ADDI TT,NUSRD-OUSRD + IDPB ZR,TT + ILDB B,N + JUMPE B,DIRLUP + CAIN B,UDWPH ; WRITE PLACE HOLDER, OR NULL FILE + JRST TRLUP + CAIL B,UDWPH + JRST LOAD + CAILE B,UDTKMX + JRST SKIPF + JRST TLUP + +TLUP: AOS Q +TLUP1: MOVE A,Q + SKIPN ADRSET + JRST DIRLE4 ;NO STARTING BLOCK (ignore untill jmp) + SKIPE NOTUT ;IF NOT ON ACTIVE UNIT, SKIP FILE + JRST CKFL3 + MOVE D,QOTUTO(C) + CAML A,QLASTB(D) + JRST DIRLE5 ;BLOCK OFF DSK (ignore block) + CAMGE A,QFRSTB(D) + JRST DIRLE5 + CAMGE A,NUDS + JRST DIRLE6 ;POINTS TO UFDS (ignore block) +CKFL2A: MOVSI D,-LSBTAB + CAMN A,SBTAB(D) + JRST DIRLE6 ;SPECIAL BLOCK + AOBJN D,.-2 + MOVE D,MFDBK + SUB D,NTBL(C) + CAML A,D + CAMLE A,MFDBK + CAIA + JRST DIRLE6 ;TUT +NTS,[ SKIPGE CKFLSW + PUSHJ P,CKFL +];NTS + MOVEM Q,LSTBLK + SKIPN NOTUT + SKIPN ADRSET + JRST CKFL3 + MOVE D,J ;SEE IF BLOCK LOCKED + SUBI D,NTUT0-OTUT0 ;(LOCK BYTES NOT IN NEW TUT YET) + ILDB D,D + CAIN D,TUTLK + PUSHJ P,DIRLEB + ILDB D,J + SKIPE D + JSR DIRLE7 ;SHARED BLOCK + CAIGE D,TUTMNY + AOS D + DPB D,J + MOVE K,J + SUBI K,NTUT0-OTUT0 + LDB D,K + JUMPE D,DIRLE9 +CKFL3: SOJG B,TLUP + JRST TRLUP + +OLDFIL: SETOM UFDSEE ;PRINT WHOLE UFD LATER + AOSE FILEER + JRST CKFL2A + TYPE !!! Over-writing user-directory area block + MOVE A,Q + X DPT + TYPE , BY + X PNTNAM + JRST CKFL2A + + +CKFL: PUSH P,J + PUSH P,I + SETOM XWDSEE + MOVE J,A + MOVEI A,FDBUF + MOVE I,C + PUSHJ P,READ +CKFLBP: JUMPL T,CKFLE1 +CKFL4: +DC,[ MOVE A,RXWDS+XWSYSN + CAME A,USRNAM + JRST CKFLE2 +CKFL5: LDB A,[XWBLK RXWDS] + CAME A,LSTBLK + JRST CKFL6 +CKFL6A: SKIPE CKFIX ;FIX ERRORS? + SKIPGE XWDSEE ;ANY ERRORS? + JRST CKFL7 + LDB A,[XWAWC RXWDS] + DPB A,[XWAWC WXWDS] + MOVE A,LSTBLK + DPB A,[XWBLK WXWDS] + MOVE A,USRNAM + MOVEM A,WXWDS+XWSYSN + MOVE Q,LASTQ + MOVE A,UNFN1(Q) + MOVEM A,WXWDS+XWFN1 + MOVE A,UNFN2(Q) + MOVEM A,WXWDS+XWFN2 + MOVEI A,FDBUF + PUSHJ P,WRITE + MOVEI A,FDBUF + PUSHJ P,READ + JUMPL T,CKFLE1 + LPR RETRIEVAL NOW: + PUSHJ P,LPTXWD + SETOM XWDSEE + JRST CKFL4 +];DC +CKFL7: POP P,I + POP P,J + POPJ P, + +CKFLE1: PUSHJ P,PNTNAM + TYPE ERROR READING BLOCK +CKFLE3: MOVE A,J + PUSHJ P,DPT + PUSHJ P,CRR + PUSHJ P,PNTXWD + PUSHJ P,GSTS + JRST CKFL4 +DC,[ +CKFLE2: JRST CKFL6A ;JFCL THIS IF YOU HATE ARCHIVES + AOS BADFIL + PUSHJ P,LPTNAM + X LTAB + X LPTXWD + X LTAB + LPR Retrieval User-name differs + LDB A,[XWBLK RXWDS] + CAMN A,LSTBLK + JRST [ X LCRR + JRST CKFL6A] + LPR , + JRST CKFLE4 + +CKFL6: JRST CKFL6A ;JFCL THIS IF YOU HATE ARCHIVES + AOS BADFIL + PUSHJ P,LPTNAM + X LTAB + X LPTXWD + X LTAB +CKFLE4: LPR Chain pointer wrong, Last block= + MOVE A,LSTBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + JRST CKFL6A +];DC + +LOAD: SETOM ADRSET ;B HAS BYTE WHERE UDWPH < BYTE <=77 + ANDCMI B,20 ;DM FUNNY BITS + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +LOAD1: MOVE TT,N + ADDI TT,NUSRD-OUSRD + IDPB ZR,TT + ILDB B,N + LSH J,6 + ADD J,B + SOJG K,LOAD1 + MOVE Q,J + SKIPE NOTUT + JRST LOAD2 ;THIS DRIVE NOT ACTIVE + MOVE I,C + PUSHJ P,TUTPNN ;GET POINTER TO NEW TUT + ADD J,[TUTBYT_14,,] ;BACK UP FOR ILDB +LOAD2: MOVEI B,1 + JRST TLUP1 + +SKIPF: SUBI B,UDTKMX + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST TLUP + +LINK: MOVE TT,N + ADDI TT,NUSRD-OUSRD + PUSHJ P,LTYPE + JRST DIRLEC + PUSHJ P,LTYPE + JRST DIRLEC + PUSHJ P,LTYPE + JRST DIRLUP + ILDB B,N + JUMPE B,DIRLUP + JRST DIRLE8 ;LINK NOT FOLLOWED BY ZERO (ignore) + +LTYPE: MOVEI B,6 +LTYPE2: IDPB ZR,TT + ILDB A,N + JUMPE A,CPOPJ ;NON SKIP RETURN IF FOLLOWED BY ZERO + CAIN A,': + JRST [ ILDB A,N + IDPB ZR,TT + JRST LTYPE3] + CAIE A,'; +LTYPE3: SOJG B,LTYPE2 + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + +DIRLUP: SKIPN BADFIL + JRST DIRLP1 + TYPE BAD RETRIEVAL: + X PNTNAM +DIRLP1: MOVE Q,LASTQ + MOVE J,(P) + MOVSI A,UNMARK + ANDCAM A,UNRNDM(Q) + SUBI Q,LUNBLK + JRST DIRL1 + +FINDPK: PUSH P,B ;MAP PACK NUMBER IN C, TO UNIT NUMBER + MOVEI B,NUNITS-1 + CAMN C,QPKN(B) + JRST FINDP1 + SOJGE B,.-2 + SETOM C + POP P,B + POPJ P, + +FINDP1: HRRZ C,B + POP P,B + POPJ P, + +USRLE2: TYPE USR DIRECTORY READ ERROR + SETOM FLAG' ;HARDWARE ERROR +USRL2A: PUSHJ P,TSPAC + MOVE A,USRNAM + PUSHJ P,SIXTYP + MOVEI A,"; + PUSHJ P,TYO + PUSHJ P,CRR + SKIPE FLAG + PUSHJ P,GSTS ;PRINT CONTROLLER STATUS + SKIPE GOGOX + JRST ERRDDT + TYPE TRY NEXT DRIVE? + PUSHJ P,TYI + CAIE A,"Y + JRST CRDDT + PUSHJ P,CRR + MOVE I,UDSK +USRL2B: AOS I + CAIL I,NUNITS + SUBI I,NUNITS + SKIPN QACT(I) + JRST USRL2B + MOVEM I,UDSK ;WILL GET POPED BEFORE NEXT USER + SETOM UFDLOS ;CAUSE DIR TO BE WRITTEN ON ALL DRIVES + MOVE J,DBLK + JRST USRLU1 + +USRLE3: TYPE User directory name-pointer scrambled + SETZM FLAG + JRST USRL2A + +USRLE7: TYPE Name area, descriptor area overlap + SETZM FLAG + JRST USRL2A + +USRLE4: 0 ;USR NAME IN DIR DIFFERS + TYPE USER NAME IN DIRECTORY DIFFERS + PUSHJ P,TSPAC + MOVE A,USRNAM + PUSHJ P,T6B + TYPE ; BLOCK + MOVE A,DBLK + X DPT + UNTMES , UNIT + MOVE A,I + PUSHJ P,DPT + TYPE , DIR HAS + X TSPAC + MOVE A,OUSRD+UDNAME + X T6B + PUSHJ P,CRR + SKIPE GOGOX + JRST ERRDDT + TYPE CORRECT IT? (MFD ENTRY TAKEN AS GOOD) + PUSHJ P,TYI + X CRR + CAIE A,"Y + JRST ERRDDT + MOVE A,USRNAM + MOVEM A,OUSRD+UDNAME + MOVEI A,OUSRD + PUSHJ P,WRITE + JRST @USRLE4 + +USRLE5: SETOM UFDSEE + SKIPN GARBF + PUSHJ P,PGARBF + LPR , POINTER= + MOVE A,Q + PUSHJ P,LOPT + LPR , GARBAGE IS + MOVE A,NUSRD(Q) + ANDCAM A,OUSRD(Q) ;CLEAR OUT THE GARBAGE + PUSHJ P,LOPT + PUSHJ P,LCRR + AOJA Q,GARB6 + +PGARBF: LPR GARBAGE IN FREE AREA + PUSHJ P,LCRR + MOVE A,USRNAM + PUSHJ P,L6B + LPR ; Block # + MOVE A,DBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDLOS + SETOM GARBF + POPJ P, + +USRLE6: SETOM UFDSEE + SKIPN EXGARB + PUSHJ P,PEXGAR + MOVE A,J + PUSHJ P,LOPT + PUSHJ P,LSPAC + MOVE A,B + PUSHJ P,LOPT + PUSHJ P,LCRR + MOVE TT,Q + SUBI TT,NUSRD-OUSRD + DPB ZR,TT + JRST GARB3 + +PEXGAR: LPR EXTRA GARBAGE IN UFD + PUSHJ P,LCRR + MOVE A,USRNAM + PUSHJ P,L6B + LPR ; Block # + MOVE A,DBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDLOS + SETOM EXGARB + POPJ P, + + +PNTNAM: PUSH P,NOLPT + SETOM NOLPT + X LPTNAM + POP P,NOLPT + POPJ P, + +LPTNAM: PUSH P,A ;DIRLE5 ETC. + MOVE A,USRNAM + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + CAIA +LPTFIL: PUSH P,A ;AVOID PDL SCREWAGE + PUSH P,B + PUSH P,C + MOVE B,LASTQ + MOVE A,UNFN1 (B) + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,UNFN2(B) + PUSHJ P,L6B + LDB C,[UNPKN UNRNDM(B)] + LPR PACK + MOVE A,C + X LDPT + X FINDPK ;FIND PACK FILE IS ON + JUMPL C,LPTFI1 + LPR , UNIT # + MOVE A,C + X LDPT +LPTFI1: PUSHJ P,LCRR + INSIRP POP P,[C B A] + POPJ P, + +PNTXWD: PUSH P,NOLPT + SETOM NOLPT + X LPTXWD + POP P,NOLPT + POPJ P, + +LPTXWD: +DC,[ + PUSH P,A + LPR Extra words: Block # + MOVE A,UNIT + X LDPT + MOVEI A,"- + X LTYO + MOVE A,BLK + X LOPT + X LSPAC + MOVE A,RXWDS+XWSYSN + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + MOVE A,RXWDS+XWFN1 + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,RXWDS+XWFN2 + PUSHJ P,L6B + LPR , Chain pointer= + LDB A,[XWBLK RXWDS] + PUSHJ P,LOPT + LPR , active wd cnt= + LDB A,[XWAWC RXWDS] + PUSHJ P,LOPT + PUSHJ P,LCRR + POP P,A +];DC + SETZM XWDSEE .SEE CKFL6A + POPJ P, + DIRLE1: PUSHJ P,LPTNAM + LPR DESC POINTS OUT OF DESC AREA + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRLUP + +DIRLE2: PUSHJ P,LPTNAM + LPR FILE NOT PRECEEDED BY ZERO + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRL2 + +DIRLE3: PUSHJ P,LPTNAM + LPR FILE POINTS TO ZERO + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRL3 + +DIRLE4: PUSHJ P,LPTNAM + LPR STARTING ADDRESS NOT SET +DIRL4A: X LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST CKFL3 + +DIRLE5: PUSHJ P,LPTNAM + LPR BLOCK POINTS OFF DSK + X LOPT + JRST DIRL4A + +DIRLE6: PUSHJ P,LPTNAM + LPR BLOCK IN RESERVED AREA + X LOPT + JRST DIRL4A + +DIRLE7: 0 + PUSHJ P,LPTNAM + LPR SHARES BLOCK WITH SOME OTHER FILE + X LCRR + AOS SHARED ;SHARED BLOCK FLAG +; SKIPN NOLPT +; SETOM UFDSEE + SETZM SALVRT ;NO AUTOMATIC SYS START + JRST @DIRLE7 + +DIRLEC: PUSHJ P,LPTNAM + LPR LINK NOT THREE NAMES + JRST DIRLED + +DIRLE8: PUSHJ P,LPTNAM + LPR LINK NOT FOLLOWED BY A ZERO +DIRLED: PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRLUP + +DIRLE9: SKIPE NOQUES + JRST CKFL3 + LPR FILE UNPROTECTED IN OLD TUT - + X LPTNAM + LPR Block + MOVE A,Q + X LOPT + X LCRR + JRST CKFL3 + +DIRLEB: PUSHJ P,LPTNAM + LPR FILE CONTAINS LOCKED BLOCK + MOVE A,Q + X LOPT + SETZM SALVRT ;NO AUTO SYS STARTUP + JRST LCRR + +USRFIN: CLEARM GARBF + CLEARM EXGARB + CLEARB ZR,J + MOVE Q,[440600,,NUSRD+UDDESC] +GARB2: CAML J,OUSRD+UDESCP + JRST USRFN2 +GARB4: ILDB B,Q + JUMPN B,USRLE6 ;GARBAGE IN DESCRIPTOR AREA (clear out) +GARB3: AOJA J,GARB2 + +USRFN2: TLNE Q,770000 + JRST GARB4 + MOVEI Q,-NUSRD+1(Q) ;FIRST WORD ABOVE DESCRIPTOR AREA +GARB6: CAML Q,NUSRD+UDNAMP + JRST GARB5 + SKIPN NUSRD(Q) + AOJA Q,GARB6 + JRST USRLE5 ;GARBAGE IN NAME AREA (clear out) + +GARB5: SKIPE UFDSEE + PUSHJ P,UFDPR + SKIPN UFDLOS + JRST USRFN5 + SKIPE NOQUES + JRST GARB5A + TYPE UFD NEEDS UPDATE - WRITE? + X Y.OR.N + JRST USRFN5 +GARB5A: MOVEI A,OUSRD + MOVEI I,NUNITS-1 + MOVE J,DBLK +GARB7: SKIPE QACT(I) + PUSHJ P,WRITE + SOJGE I,GARB7 +USRFN5: POP P,J + POP P,UDSK + POP P,Q + POPJ P, + + +SUBTTL LISTF - DUMP OUT USER DIRECTORY +LISTF: JSR INIT + SKIPL ACTIVE ;ALREADY DID RESET + X ACTUN + X CRR + TYPE USER?= + X SIXIN + X CRR + JUMPE B,DDT + MOVEI I,NUNITS-1 + SETOM FUNIT +LISTF3: SKIPN QACT(I) + JRST LISTF2 + MOVEM I,FUNIT + MOVE A,QNTUTO(I) + PUSHJ P,RDTUT + JUMPL T,[TYPE ERROR READING TUT # + MOVE A,I + X DPT + X CRR + X GSTS + X CONTIN + JRST DDT + JRST .+1] +LISTF2: SOJGE I,LISTF3 + MOVEM B,USRNAM + MOVEI A,MFD + MOVE J,MFDBK + SKIPGE I,FUNIT ;USE FIRST ACTIVE UNIT + JRST LISTF4 ;NO DISKS ACTIVE?? + X READ + JUMPL T,[TYPE ERROR READING MFD + X CRR + X GSTS + X CONTIN + JRST DDT + JRST .+1] + MOVE D,USRNAM + MOVE Q,MFD+MDNAMP +LISTF1: CAIL Q,2000 + JRST [ TYPE USER NOT FOUND - + MOVE A,D + X T6B + JRST CRDDT] + CAME D,MFD(Q) + JRST [ ADDI Q,LMNBLK + JRST LISTF1] + SUBI Q,2000 + IDIVI Q,LMNBLK + HRRZ J,Q + ADD J,NUDS + MOVEM J,DBLK + MOVE I,FUNIT ;USE FIRST ACTIVE UNIT + MOVEI A,OUSRD + X READ + JUMPL T,[TYPE ERROR READING USER DIRECTORY + X CRR + X GSTS + X CONTIN + JRST CRDDT + JRST .+1] + X USEE0 + JRST CRDDT + +CONTIN: TYPE CONTINUE? + X TYI + X CRR + CAIN A,"Y + AOS (P) + POPJ P, + +LISTF4: TYPE NO ACTIVE UNIT TO GET DIR FROM + JRST CRDDT + +UFDPR: SETZM SALVRT ;NO AUTO SYS STARTUP + SKIPN NOLPT + JRST [ TYPE Errors in directory + MOVE A,OUSRD+UDNAME + X T6B + X CRR + JRST .+1 ] +USEE0: MOVE Q,OUSRD+UDNAME + PUSHJ P,LFORM + LPR USER DIRECTORY: + MOVE A,Q + X L6B + MOVEI A,"; + X LTYO + X LCRR + MOVEI J,OUSRD + ADD J,UDNAMP(J) + CAIG J,OUSRD+2000 + CAIGE J,OUSRD+UDDESC + JRST [ LPR UFD NAME AREA POINTER OUT OF RANGE + JRST USEEF ] + MOVE T,OUSRD+UDESCP + IDIVI T,6 + ADDI T,OUSRD+UDDESC + CAML T,J + JRST [ LPR DESCRIPTOR FREE POINTER OVERLAPS NAME AREA + JRST USEEF ] + MOVEM J,LAST + MOVEI Q,OUSRD+2000-LUNBLK +USEE1: CAMGE Q,LAST ;PER FILE LOOP + JRST USEEF + MOVEM Q,LASTQ + SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + CAIA + JRST USEELP + X LPTFIL + LDB C,[UNPKN UNRNDM(Q)] + X FINDPK + MOVEM C,FUNIT ;KLUDGE KLUDGE (LOOKS AT TUTS) + LDB A,[UNDSCP UNRNDM(Q)] + CAML A,OUSRD+UDESCP + JRST [ LPR FILE DESCRIPTOR POINTER POINTS OUTSIDE DESCRIPTOR AREA + JRST USEELY ] + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] + LDB B,A + X LTAB + X USBYTE + LPR (INITIAL ZERO) + JUMPN B,[ LPR - IS NOT PRESENT + JRST USEELY ] + X LCRR +USEE2: MOVE N,A + MOVEI J,0 + ILDB B,A ;PEEK AT NEXT BYTE + JUMPE B,[X USBYTE + LPR (FIRST BYTE SHOULD BE NON-ZERO) + JRST USEELY] ;SHOULD BE NON-ZERO + LDB A,[UNDSCP UNRNDM(Q)] + X LOPT ;SHOW DESC ADDR BEFORE FIRST DESC BYTE +USEE3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST USLINK + ;FALLS THROUGH + SETZM ADRSET +USLUP: ILDB B,N + X LTAB + X USBYTE + JUMPE B,[LPR (STOP) + X LCRR + JRST USEELP] + CAIN B,UDWPH + JRST [ LPR (WRITE-PLACE-HOLDER) + X LCRR + JRST USLUP] + CAIL B,UDWPH + JRST USLOAD + CAILE B,UDTKMX + JRST USSKIP + LPR (TAKE-N BLOCKS) +USLP1: AOS Q +USLP2: MOVE A,Q + X LOPT + X LSPAC + SKIPGE TT,FUNIT + JRST USLP3 ;PACK NOT MOUNTED + MOVE TT,QOTUTO(TT) + CAMGE Q,QLASTB(TT) + SKIPN ADRSET + JRST USLPE ;BAD BLOCK + ILDB TT,J ;TUT ENTRY + CAMGE Q,NUDS + JRST USLPE + MOVSI D,-LSBTAB + CAMN Q,SBTAB(D) + JRST USLPE + AOBJN D,.-2 + MOVE A,FUNIT + MOVE D,MFDBK + SUB D,NTBL(A) + CAML Q,MFDBK + CAMLE Q,D + CAIA + JRST USLPE ;OVERLAPS TUT OR MFD + + SKIPL FUNIT ;FILE NOT ON ACTIVE UNIT + CAIN TT,1 + JRST USLP3 + LPR ?? TUT= + MOVE A,TT + X LDPT + LPR ?? +USLP3: SOJG B,USLP1 + X LCRR + JRST USLUP +USLPE: LPR ?? BAD BLOCK # ?? + JRST USLP3 + +USEELP: MOVE Q,LASTQ + SUBI Q,LUNBLK + JRST USEE1 + +USLOAD: SETOM ADRSET + ANDCMI B,20 ;DM FUNNY BITS + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +USLOD1: ILDB B,N + X USBYTE + LSH J,6 + ADD J,B + SOJG K,USLOD1 + MOVE Q,J + SKIPGE I,FUNIT + TDZA J,J ;NO TUT + PUSHJ P,TUTPNO ;GET POINTER TO OLD TUT + ADD J,[TUTBYT_14,,] ;BACK UP FOR ILDB + LPR (JUMP + MOVE A,Q + X LOPT + LPR ) + MOVEI B,1 + JRST USLP2 + +USSKIP: SUBI B,UDTKMX + LPR (SKIP + MOVE A,B + X LOPT + LPR ) + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST USLP1 + +USLINK: X LTAB + LPR (LINK) + X USLINP + JRST USLIN3 + MOVEI A,"; + X LTYO + X USLINP + JRST USLIN3 + X LSPAC + X USLINP + ADD N,[060000,,] ;ENDS WITH ZERO, RE-READ THE ZERO BYTE + X LCRR + ILDB B,N + X LTAB + X USBYTE + LPR (ZERO) + JUMPE B,USLIN4 + LPR ?? NO END ZERO ?? +USLIN4: X LCRR + JRST USEELP + +USLIN3: LPR ?? ENDS EARLY ?? + JRST USLIN4 + +USLINP: MOVEI B,6 +USLIN2: ILDB A,N + JUMPE A,CPOPJ ;NON SKIP RETURN IF FOLLOWED BY ZERO + CAIN A,'; + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + CAIN A,': ;QUOTE CHAR + ILDB A,N + ADDI A,40 + X LTYO + SOJG B,USLIN2 + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + +USBYTE: PUSH P,A + PUSH P,B + LDB A,[30300,,(P)] + ADDI A,"0 + X LTYO + LDB A,[300,,(P)] + ADDI A,"0 + X LTYO + X LSPAC + POP P,B + POP P,A + POPJ P, + +USEELY: X LCRR +USSELP: MOVE Q,LASTQ + SUBI Q,LUNBLK + JRST USEE1 + +USEEF: X LCRR + X LFORM + POPJ P, + +SUBTTL MAIN SALVAGER - WRITE MFD & TUT + +MFDFIN: MOVEI I,0 +MFDFN0: SKIPE QACT(I) + PUSHJ P,TUTCMP + CAIGE I,NUNITS-1 + AOJA I,MFDFN0 + SKIPN MFDWRT + JRST SHARCK ;MFD DIDN'T HAVE ANY CHANGES +MFDWR0: SKIPE NOQUES + JRST MFDWR1 + TYPE WRITE OUT CHANGES IN MFD? + X Y.OR.N + JRST SHARCK +MFDWR1: MOVE J,MFDBK + MOVEI I,NUNITS-1 +MFDWR2: MOVEI A,MFD + SKIPE T,QACT(I) + PUSHJ P,WRITE + JUMPGE T,MFDWR3 + PUSHJ P,GSTS ;ERROR WRITING MFD + SKIPN GOGOX + JRST MFDWR0 + JRST ERRDDT + +MFDWR3: SOJGE I,MFDWR2 + JRST SHARCK + +TUTCMP: SETZM TUTDFR ;FIRST SEE IF ANY DIFFERENCES + SETZM TTDFPS + SETZM NLKBKS' + SETZM TUTCHG ;MAKE SUMMARY TABLE OF DIFFERENCES + MOVE Q,[TUTCHG,,TUTCHG+1] + BLT Q,TUTCHG+-1 + MOVE Q,QTTBLI + HRR Q,QNTUTO(I) ;NEW B.P. + ADDI Q,LTIBLK + MOVE J,Q + HRR J,QOTUTO(I) ;OLD B.P. + MOVE TT,QFRSTB(J) ;BLOCK NUMBER + MOVE B,QLASTB(J) + SOS B + MOVEM B,TUTHIB' ;HIGHEST BLOCK # + ADDI J,LTIBLK +TUTC1: ILDB B,Q + ILDB D,J + CAMN B,D + JRST TUTC2 + CAIN D,TUTLK + JRST [ MOVE B,D ;IF LOCKED, STAY LOCKED + DPB B,Q + AOS NLKBKS ;COUNT BLOCKS LOCKED DUE TO DISK ERRORS + SKIPN GOGOX + PUSHJ P,LCKRPT ;IN CHKR MODE, REPORT LOCKED BLOCKS + JRST TUTC2 ] + PUSHJ P,TUTC4 +TUTC2: CAMGE TT,TUTHIB + AOJA TT,TUTC1 + SKIPN NOQUES + SKIPN A,NLKBKS + JRST TUTC3 + X TDPT + UNTMES LOCKED BLOCKS ON UNIT # + HRRZ A,I + X DPT + X CRR +TUTC3: SKIPN TUTDFR + POPJ P, ;NO DIFFERENCES THIS TUT + JRST TUTCM0 ;DIFFERENCES, GO HANDLE + +TUTC4: IMULI B,TUTMAX + ADD B,D + MOVE T,QOTUTO(I) ;DON'T LIST TUT CHANGES IN SWAPPING AREA + CAML TT,NUDS + CAML TT,QSWAPA(T) + AOS TUTCHG(B) + AOS TUTDFR + POPJ P, + +TUTCM0: SKIPE NOQUES ;HERE WHEN TUT HAS DIFFERENCES + JRST TUTCM3 ;IF NO QUESTIONS, JUST WRITE + MOVEI A,TUTMAX*TUTMAX-1 ;SEE IF ANY TUT DIFFERENCES NOT IN SWAPPING AREA + SKIPN TUTCHG(A) + SOJGE A,.-1 + JUMPL A,TUTCM4 ;NONE, GO ASK IF SHOULD WRITE + SETZM LINPOS ;OTHERWISE, SUMMARIZE TUT DIFFERENCES + TYPE TUT # + HRRZ A,I + X DPT + MOVEI B,TUTMAX-1 +TUTSM1: MOVEI D,TUTMAX-1 +TUTSM2: MOVE A,B + IMULI A,TUTMAX + ADD A,D + SKIPN A,TUTCHG(A) + JRST TUTSM3 + X TSPAC + X TDPT + X TSPAC + MOVE A,B + X DPT + TYPE _ + MOVE A,D + X DPT + MOVE A,LINPOS + CAIGE A,60. + JRST TUTSM3 + X CRR + SETZM LINPOS +TUTSM3: SOJGE D,TUTSM2 + SOJGE B,TUTSM1 + TYPE , PRINT? + X Y.OR.N + JRST TUTCM4 + +;HERE TO PRINT OUT THE TUT + + SETZM TUTDFR + MOVE Q,QTTBLI + HRR Q,QNTUTO(I) ;NEW B.P. + ADDI Q,LTIBLK + MOVE J,Q + HRR J,QOTUTO(I) ;OLD B.P. + MOVE TT,QFRSTB(J) ;BLOCK NUMBER + MOVE B,QLASTB(J) + SOS B + MOVEM B,TUTHIB' ;HIGHEST BLOCK # + ADDI J,LTIBLK +TUTCM1: ILDB B,Q + ILDB D,J + CAME B,D + JRST TUTDF1 +TUTCM2: CAMGE TT,TUTHIB + AOJA TT,TUTCM1 + + SKIPE TTDFPS + X LCRR + X LFORM ;SOMETHING PRINTED, ADVANCE LPT PAPER +TUTCM4: TYPE TUT # + HRRZ A,I + X DPT + TYPE NEEDS UPDATING - WRITE? + X Y.OR.N + POPJ P, +TUTCM3: + MOVE A,QNTUTO(I) + PUSHJ P,WRTUT + JUMPGE T,CPOPJ + PUSHJ P,GSTS ;ERROR WRITING TUT + SKIPN GOGOX + JRST TUTCM4 + JRST ERRDDT + +TUTMAX=1_TUTBYT + +TUTCHG: BLOCK TUTMAX*TUTMAX + +TUTDF1: MOVE T,QOTUTO(I) + CAML TT,NUDS + CAML TT,QSWAPA(T) + CAIA + JRST TUTCM2 ;IN SWAPPING AREA, IGNORE + PUSHJ P,NEWOLD + PUSH P,[TUTCM2] + AOSL TTDFPS + JRST TUTDF7 ;NO MORE ROOM ON LINE + MOVEI A,40 ;PRINT MULTIPLE FROBS PER LINE + PUSHJ P,LPTR ;SO THE LINE PRINTER WILL GO FASTER + JRST LPTR + +NEWOLD: SKIPN TUTDFR + PUSHJ P,TUTTYP + MOVE A,TT + PUSHJ P,LOPT + PUSHJ P,LSPAC + MOVE A,B + PUSHJ P,LOPT + MOVEI A,"_ + PUSHJ P,LPTR + MOVE A,D + JRST LOPT + +TUTTYP: SETOM TUTDFR + PUSHJ P,LCRR + LPR TUT DIFFERENCES FOR DRIVE # + HRRZ A,I + PUSHJ P,LOPT +TUTDF7: MOVNI A,5 ;START NEW LINE, ROOM FOR 5 BLOCKS IF TTY + SKIPN NOLPT + MOVNI A,9 ;OR 9 IF LPT + MOVEM A,TTDFPS + JRST LCRR + +LCKRPT: TYPE LOCKED BLOCK + HRRZ A,I + X TDPT + MOVEI A,"- + X TYO + MOVE A,TT + X TOPT + X CRR + POPJ P, + +SUBTTL TRACK DOWN SHARED BLOCKS + +SHARCK: SKIPN SHARED + JRST CRDDT ;NO SHARED TRACKS, WE ARE DONE + TYPE SHARED BLOCKS + PUSHJ P,LCRR + LPR LOOKING FOR SHARED BLOCKS + PUSHJ P,LCRR + MOVE I,MDSK + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE Q,MFD+MDNAMP + ADDI Q,MFD +SMFDLP: CAIL Q,MFD+2000 + JRST SHRCKF ;DONE + SKIPN A,MNUNAM(Q) + JRST SMFDL1 + PUSHJ P,SUSRLP +SMFDL1: ADDI Q,LMNBLK + JRST SMFDLP + +SHRCKF: SKIPN GOGOX + JRST CRDDT + JRST ERRDDT + +SUSRLP: HRREI J,-MFD-2000(Q) ;CONVERT MFD INDEX TO BLOCK NUMBER + ASH J,-1 + ADD J,NUDS + MOVEM A,USRNAM + PUSH P,Q + MOVE I,UDSK + PUSH P,UDSK +SUSRL1: MOVEI A,OUSRD + PUSHJ P,READ + JUMPL T,SUSRE2 + MOVEI Q,2000-LUNBLK+OUSRD + MOVEI J,OUSRD + ADD J,UDNAMP(J) + PUSH P,J +SDIRL1: CAMGE Q,J + JRST SUSRFN + MOVEM Q,LASTQ + SKIPE A,UNFN1(Q) + JRST .+3 + SKIPN UNFN2(Q) + JRST SDIRLP + LDB C,[UNPKN UNRNDM(Q)] + LDB A,[UNDSCP UNRNDM(Q)] + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] +SDIRL2: MOVE N,A + MOVEI J,0 + ILDB B,A +SDIRL3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST SDIRLP + PUSHJ P,FINDPK + SKIPL C + SKIPN QACT(C) + JRST SDIRLP + CAIG B,UDWPH ; A LOAD FIRST THING + JRST SDIRLP + +STRLUP: ILDB B,N + JUMPE B,SDIRLP + CAIN B,UDWPH + JRST STRLUP + CAIL B,UDWPH + JRST SLOAD + CAILE B,UDTKMX + JRST SSKIPF + JRST STLUP + +STLUP: AOS Q +STLUP1: ILDB D,J + CAIE D,1 + PUSHJ P,SPNT + SOJG B,STLUP + JRST STRLUP + +SLOAD: ANDCMI B,20 ;DM FUNNY BIT + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +SLOAD1: ILDB B,N + LSH J,6 + ADD J,B + SOJG K,SLOAD1 + MOVE Q,J + MOVE I,C + PUSHJ P,TUTPNN ;GET PNTR TO TUT + ADD J,[TUTBYT_14,,] ;COMPENSATE FOR ILDB + MOVEI B,1 + JRST STLUP1 + +SSKIPF: SUBI B,UDTKMX + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST STLUP + +SPNT: MOVE A,USRNAM + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + EXCH Q,LASTQ + MOVE A,UNFN1(Q) + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,UNFN2(Q) + PUSHJ P,L6B + PUSHJ P,LSPAC + HRRZ A,C + PUSHJ P,LDPT + MOVEI A,"- + PUSHJ P,LTYO + MOVE A,LASTQ + PUSHJ P,LOPT + LPR , TUT= + MOVE A,D + X LDPT + PUSHJ P,LCRR + EXCH Q,LASTQ + POPJ P, + +SUSRE2: TYPE USER DIRECTORY PARITY ERROR + PUSHJ P,TSPAC + TYPE BLOCK # + MOVEM J,DBLK + MOVE A,J + PUSHJ P,DPT + UNTMES UNIT # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,CRR + PUSHJ P,GSTS + SKIPE GOGOX + JRST ERRDDT + TYPE TRY NEXT DRIVE? + X Y.OR.N + JRST ERRDDT + MOVE I,UDSK +SUSR2B: AOS I + CAIL I,NUNITS + SUBI I,NUNITS + SKIPN QACT(I) + JRST SUSR2B + MOVEM I,UDSK + MOVE J,DBLK + JRST SUSRL1 + +SUSRFN: POP P,J + POP P,UDSK + POP P,Q + POPJ P, + +SDIRLP: MOVE Q,LASTQ + SUBI Q,LUNBLK + MOVE J,(P) + JRST SDIRL1 + +POPBAJ: POP P,B +POPAJ: POP P,A + POPJ P, + +SUBTTL INITIALIZATION + +INIT: 0 + MOVEI P,PDL +NTS,[ KA,[ + CONO 675550 ;RESET APR + CONO PI,710000 ;RESET PI + MOVE TT,[JSR UUOHLT] ;HALT ON UUO + SKIPN 41 + MOVEM TT,41 + MOVEI A,SA ;MAKE SURE ALL NECESSARY MEMORY IS PRESENT +INIT0: MOVE B,(A) + CONSZ 10000 + JRST [ TYPE NXM IN SALV MEM + JRST ERRDDT ] + ADDI A,2000 + CAIGE A,THEEND + JRST INIT0 +];KA +KL,[ + SETZM DTEOPR ;BTB IF QUIT OUT AND RESTART + CONO APR,267760 ;I/O RESET, CLEAR + DISABLE ALL FLAGS + CONO PI,010000 ;CLEAR P.I. SYSTEM + CONSZ PAG,400000 + JRST .+4 ;JUMP IF CACHE LOOK ENABLE + SWPIA ;IF CACHE OFF, INVALIDATE IT BEFORE TURNING ON + CONSZ APR,200000 + JRST .-1 + MOVEI TT,SALVPF ;SET TO HALT ON PAGE FAIL (E.G. PARITY ERROR) + MOVEM TT,PFNPC + CONO PAG,600000+EPT/1000 ;SET UP EPT, ENABLE CACHE, DISABLE PAGING AND TRAPS + DATAO PAG,[100000,,400000+EPT/1000] ;UPT=EPT + MOVEI TT,UUOHLT + SKIPN EPT+430 ;HALT ON KERNEL UUO + MOVEM TT,EPT+430 + MOVEI A,SA ;MAKE SURE ALL NECESSARY MEMORY IS PRESENT +INIT0: MOVE B,(A) + CONSZ 2000 + JRST [ TYPE NXM IN SALV MEM + JRST ERRDDT ] + ADDI A,1000 + CAIGE A,THEEND + JRST INIT0 +RH, CONI DSK,TT +RH, TLNN TT,(%HID22) +RH, JRST [ TYPE DF10 IN KA MODE?? +RH, JRST ERRDDT ] +IFN T300P,[ ;TURN ON DL10 TO ACCESS T-300 + CONO DLC,400000 ;MR CLR + CONO DLB,1 ;TURN OFF EXCESS LIGHTS + CONO DLB,2 ;.. + CONO DLB,3 ;.. + CONO DLB,DL10AR ;64 WORDS FOR PDP11 #0 AT DL10AR + DATAO DLC,[200001,,] ;KA INTERRUPT MODE + CONO DLC,100020 ;ENB PDP11 PORT #0 NO INTERRUPTS +];T300P +];KL +DC, SETZM ENCS +RH, SETZM MARKF +RP,[ DATAI DPC,A + TLNN A,NOWRIH + JRST [ TYPE [WRITE HEADERS ENABLED] + X CRR + JRST .+1 ] +];RP + SETOM DRIVE ;ALL DRIVES ASSUMED TO BE ON-LINE + MOVE A,[DRIVE,,DRIVE+1] + BLT A,DRIVE+NDRIVE-1 + MOVEI A,SLVIOWD ;SET UP CHANNEL PROGRAM AREA + MOVEM A,SLVICWA + SETZM SLVIOWD+1 + SETZM SLVICWA+1 +];NTS + SETZM GOGOX + SETZM NOQUES + MOVEI A,NUNITS-1 + SETOM QPKN(A) ;TUT NOT IN YET + SOJGE A,.-1 +TS,[ + .OPEN TYIC,[SIXBIT / $TTY/] + .VALUE + .OPEN TYOC,[SIXBIT / !TTY/] + .VALUE + .CORE _-10.+1 + .VALUE + MOVE A,[SQUOZE 0,NQS] + .EVAL A, + .VALUE + MOVEM A,NQS + MOVE A,[SQUOZE 0,QACT] + .EVAL A, + .VALUE + MOVEM A,SQACT + MOVE A,[SQUOZE 0,NUDSL] + .EVAL A, + .VALUE + MOVEM A,NUDS + MOVE A,[SQUOZE 0,MFDBLK] + .EVAL A, + .VALUE + MOVEM A,MFDBK + MOVE B,[SQUOZE 0,NTUTBL] + .EVAL B, + .VALUE + MOVEI C,NUNITS-1 + MOVEM B,NTBL(C) + SOJGE C,.-1 + CAILE B,MXTUTB + .VALUE ;NOT ASSEMBLED FOR BIG ENOUGH TUTS + MOVE B,[SQUOZE 0,T300P] ;NEED KLUDGES FOR 2 SIZES OF TUT + .EVAL B, + MOVEI B,0 + JUMPE B,INI03 + MOVE C,[SQUOZE 0,NTUTB1] + .EVAL C, + .VALUE + CAILE C,MXTUTB + .VALUE ;TOO BIG + MOVEM C,NTBL(B) + CAIGE B,NUNITS-1 + AOJA B,.-2 +INI03: MOVE A,[SQUOZE 0,NBLKS] + .EVAL A, + .VALUE + MOVEM A,SNBLKS + SUBI A,1 + MOVEM A,SNBLKS-1 +];TS + + ;BRING UP THE LPT + + SETOM NOLPT ;ASSUME THE WORST + SKIPE LPBUST + JRST LPTDWN + SETOM LPFRST' ;FLAG LPT NOT USED YET + +TS,[ TYPE WANT LPT? + PUSHJ P,TYI + X CRR + SETOM LPBUST ;ASK ONLY ONCE + CAIN A,"Y + .OPEN LPTC,[.UAO,,'LPT] + JRST LPTDWN + SETZM NOLPT + SETZM LPBUST +];TS +;DROPS THROUGH + ;DROPS IN +NTS,[ +IFN OLPTP,[ ;BRING UP AI-KA LPT +LPTUP3: CONO LPT,10 + DATAO LPT,[440] + MOVEI A,200000 +LPTUP1: SOJLE A,LPTUP2 + CONSZ LPT,10 + JRST LPTUP1 + SETZM NOLPT + JRST LPTDWN +];IFN OLPTP + +IFN NLPTP,[ ;BRING UP ML LPT +LPTUP3: SETOM LPTBFC + MOVE A,[<.BYTE 7 ? 15 ? 15 ? 15 ? 15 ? 15>] + MOVEM A,LPTBUF + CONO NLPT,200 + CONO NLPT,1000 ;IMAGE MODE + DATAO NLPT,[23*2] ;MOTOR ON + + MOVEI A,200000 ;1 SECOND +LPTUP1: SOJLE A,LPTUP2 + CONSO NLPT,100 ;IS IT ON? + JRST LPTUP1 + SETZM NOLPT ;WELL, YES + CONO NLPT,200 + CONO NLPT,100 ;SET OUTPUT DONE + JRST LPTDWN ;ITS UP +];IFN NLPTP + +IFN TTLPTP,[ ;BRING UP LPT ATTACHED VIA MTY +LPTUP3: MOVEI A,200000 +LPTUP1: SOJLE A,LPTUP2 + CONI MTY,B + TRNN B,40 ;ANY INPUT? + JRST LPTUP1 + LDB B,[140500,,B] + DATAI MTY,C + CAIE B,TTLPTP&77 + JRST LPTUP1 ;NOT FROM LPT + + SETZM NOLPT ;IS FROM LPT -> WIN + MOVEI B,TTLPTP_14 ;LINE NUMBER IN RIGHT PLACE + CONO MTY,10(B) ;SET OUTPUT DONE + JRST LPTDWN +];IFN TTLPTP + +IFN OLPTP+NLPTP+TTLPTP,[ + ;ROUTINE TO ASK IF UP +LPTUP2: TYPE LPT DOWN (Y OR N) +IFN OLPTP, TYPE [MAYBE NEEDS RESET BUTTON PUSHED] + PUSHJ P,TYI + X CRR + CAIN A,"Y + JRST LPTUP4 + CAIN A,"N + JRST LPTUP3 ;"N", CHECK IT AGAIN + JRST LPTUP2 + +LPTUP4: SETOM LPBUST +];IFN OLPTP+NLPTP+TTLPTP +];NTS + +LPTDWN: JRST @INIT + +NTS,[ +UUOHLT: +KA, 0 + JRST 4,. ;HERE IF UUO IN STAND-ALONE MODE (ELSE HALT IN ITS) +];NTS + +SUBTTL LPT & TTY I/O + +LDPT: PUSH P,A + PUSH P,B + JUMPGE A,LDPT0 + MOVEI A,"- + PUSHJ P,LTYO + MOVN A,-1(P) +LDPT0: PUSHJ P,LDPT1 + JRST POPBAJ + +LDPT1: IDIVI A,10. + HRLM B,(P) + SKIPE A + PUSHJ P,LDPT1 + JRST LDPT2 + +LOPT: PUSH P,A + PUSH P,B + PUSHJ P,LOPT1 + JRST POPBAJ + +LOPT1: LSHC A,-35. ;IN CASE NEGATIVE + LSH B,-1 + DIVI A,8 + HRLM B,(P) + SKIPE A + PUSHJ P,LOPT1 +LDPT2: HLRZ A,(P) + ADDI A,"0 +;DROPS IN +LTYO: +LPTR: +LPTR1: SKIPE NOLPT + JRST TYLPT ;TYPE ON TTY INSTEAD + + PUSH P,A + AOSE LPFRST + JRST LPTR2 + TYPE (INFO ON LPT) + X CRR +LPTR2: + +IFN OLPTP,[ +OLP1: CAIN A,12 ;SUPPRESS LF, MAKE CR=CR-LF + JRST POPAJ + CAIN A,15 + JRST [ CONO LPT,10 + MOVEI A,440 + JRST .+1] + CAIN A,14 + MOVEI A,441 + CAIN A,33 + MOVEI A,"$ + CAIL A,"a + CAILE A,"z + CAIA + SUBI A,40 ;LOWER CASE -> UPPER CASE + SUBI A,40 + PUSH P,B + HRLZI B,2 ;3 SECOND TIMEOUT + CONSZ LPT,10 + SOJG B,.-1 + JUMPLE B,OLP2 +OLP3: DATAO LPT,A + JRST POPBAJ + +OLP2: X CRR + TYPE HIT RESET BUTTON ON LPT + X CRR + HRLZI B,15 ;20 SECOND TIMEOUT + CONSZ LPT,10 + SOJG B,.-1 + JUMPLE B,OLP2 + JRST OLP3 +];IFN OLPTP + +TS,[ .IOT LPTC,A + JRST POPAJ +];TS + +IFN NLPTP,[ ;SEND CHARACTER TO NLPT + PUSH P,B + SOSLE LPTBFC ;MORE TO GO + JRST LPTR0 ;YES +LPTR01: MOVEI B,5 ;NO, NEW WORD + MOVEM B,LPTBFC + MOVE B,[440700,,LPTBUF] + MOVEM B,LPTBFP + MOVEI B,-1 ;TIMEOUT FOR DEAD LPT + CONSO NLPT,100 + SOJG B,.-1 + DATAO NLPT,LPTBUF + +LPTR0: IDPB A,LPTBFP ;BUFFER 5 AT A TIME + CAIL A,12 + CAILE A,14 ;LF OR FF, FORCE BUFFER NOW + JRST POPBAJ + MOVEI A,15 +LPTR00: SOSG LPTBFC + JRST LPTR01 + IDPB A,LPTBFP + JRST LPTR00 + + ;NLPT BUFFERING CRUFT +LPTBUF: -1 ;5 CHAR LPT BUFFER +LPTBFC: 5 ;COUNT OF CHARS LEFT IN BUF +LPTBFP: @. ;BYTE POINTER INTO LPT BUFFER + +LPTFIN: SKIPL LPFRST ;DO NOTHING IF NEVER OUTPUT TO LPT + SKIPGE NOLPT ;WAS LPT INIT'ED? + POPJ P, ;NO, DON'T HANG + MOVE A, [<.BYTE 7 ? 15 ? 14 ? 15 ? 15 ? 15>] + MOVEI B, 15 +LPTFN0: SOSG LPTBFC + JRST LPTFN1 + IDPB B, LPTBFP + JRST LPTFN0 + +LPTFN1: CONSO NLPT,100 ;WAIT FOR THAT TO HAPPEN + JRST .-1 + DATAO NLPT, LPTBUF + CONSO NLPT,100 ;WAIT FOR THAT TO HAPPEN + JRST .-1 + DATAO NLPT, A + POPJ P, +];IFN NLPTP + +IFN TTLPTP,[ +; call with ascii char in A +; saves and restores all AC's + + ANDI A,177 ;MASK TO 7 BIT ASCII + CAIGE A,40 ;SKIP IF NOT CTL CHAR + CAIN A,14 ;SKIP IF NOT FF + JRST LPTOP ;PRINT LITERALLY FF, GRAPHICS + CAIN A,15 ;SKIP IF NOT CR + JRST LPCR ;JUMP TO CR ROUT + CAIN A,12 ;SKIP IF NOT LF + JRST LPLF ;JUMP TO LF ROUT + CAIN A,11 ;SKIP IF NOT TAB + JRST LPTAB ;JUMP TO TAB ROUT + MOVEI A,"^ ;HERE FOR RANDOM CTL CHAR + PUSHJ P,LPTO ;PUT OUT ^FOO + MOVE A,(P) ;RETREIVE CHAR + ADDI A,100 ;MAKE IT A 'LETTER' +LPTOP: PUSHJ P,LPTO + JRST POPAJ + +LPCR: SKIPE LPTPOS ;SKIP IF STILL AT LEFT MARGIN + PUSHJ P,LPTO ;ELSE PUT OUT CR + SETZM LPTPOS ;MARK 'AT LEFT MARGIN' + SETOM LPCRLF ;MARK LF AFTER CR + MOVEI A,12 ;LF + JRST LPTOP ;OUTPUT IT + +LPLF: AOSE LPCRLF ;SKIP IF THIS LF AFTER CR + JRST LPTOP ;ELSE PUT IT OUT + JRST POPAJ + +LPTAB: MOVEI A,40 ;SPACES FOR TAB + PUSHJ P,LPTO + MOVE A,LPTPOS ;CHECK POS + TRNE A,7 ;SKIP IF POS = 0 MOD 8 + JRST LPTAB ;ELSE PUT ANOTHER SPACE + JRST POPAJ + +LPTO: CAIL A,40 ;SKIP FOR CTL CHAR NOT COUNTED + AOS LPTPOS ;COUNT CHAR + PUSH P,A + PUSH P,B + MOVEI A,-1 ;TIMER FOR FLAG +LPWAIT: SOJLE A,LPTOUT + CONI MTY,B ;GET STATUS + TRNE B,40 ;SKIP IF NO INPUT FLAG + JRST FLSINP ;ELSE JUMP TO FLUSH INPUT + TRNN B,10 ;SKIP IF OUTPUT FLAG + JRST LPWAIT ;ELSE LOOP + LDB B,[140500,,B] ;GET SUBDEV # + CAIE B,TTLPTP&77 ;SKIP IF THIS IS LPT # + JRST FLSOUT ;ELSE FLUSH +LPTOUT: MOVEI B,TTLPTP_14 ;GET LPT NO IN SUBDEV POSITION + CONO MTY,(B) ;SELECT SUBDEV + POP P,B ;RESTORE AC + MOVE A,(P) ;GET CHAR + LSH A,35 ;PUT IN FUNNY POSITION + DATAO MTY,A ;PUT OUT 1 CHAR + JRST POPAJ + +FLSINP: DATAI MTY,B ;READ INPUT + JRST LPWAIT ;AND IGNORE + +FLSOUT: LSH B,14 ;SHIFT TO SELECT + CONO MTY,200(B) ;RESET FLAG, IT'S NOT LPT + JRST LPWAIT + +LPTPOS: 0 ;PRINT POSITION FROM LEFT MARGIN +LPCRLF: 0 ;# CHARS AFTER LAST CR, -1 IF TO IGNORE LF +];IFN TTLPTP + +TYLPT: CAIN A,14 + JRST CRR ;NO FF ON TTY + JRST TYO + +SIXTYP: +T6B: PUSH P,B ;OUTPUT SIXBIT IN A + PUSH P,A + LSHC A,-36. +T6B1: LSHC A,6 + ADDI A,40 + PUSHJ P,TYO + MOVEI A,0 + JUMPN B,T6B1 + POP P,A +POPBJ: POP P,B + POPJ P, + +SIXLPT: +L6B: PUSH P,B ;OUTPUT SIXBIT IN A + PUSH P,A + MOVE B,[440600,,(P)] ;ALWAYS OUTPUTS SIX COLUMNS +L6B1: ILDB A,B ;CAN YOU GUESS WHY? WIN A KEWPIE DOLL! + ADDI A,40 + PUSHJ P,LPTR + TLNE B,770000 + JRST L6B1 + POP P,A + POP P,B + POPJ P, + +SLPT: PUSH P,B + MOVE B,A +SL1: ILDB A,B + JUMPE A,POPBJ + PUSHJ P,LPTR + JRST SL1 + +DPT: +TOPT: PUSH P,A + PUSH P,B + MOVEI B,8 + MOVEM B,ORADIX + PUSHJ P,TDPT1 + JRST POPBAJ + +TDPT: PUSH P,A + PUSH P,B + MOVEI B,10. + MOVEM B,ORADIX' + PUSHJ P,TDPT1 + JRST POPBAJ + +TDPT1: LSHC A,-35. ;IN CASE NEGATIVE + LSH B,-1 + DIV A,ORADIX + HRLM B,(P) + SKIPE A + PUSHJ P,TDPT1 + HLRZ A,(P) + ADDI A,"0 + JRST TYO + +LTAB: +IFN OLPTP,[ + PUSHJ P,LSPAC ;OLD LPT LACKS TABS + PUSHJ P,LSPAC + PUSHJ P,LSPAC + JRST LSPAC +];IFN OLPTP + +.ELSE [ PUSH P,A + MOVEI A,11 ;NLPT HAS HARDWARE TABS + JRST L1 +];ELSE + +LCRR: PUSH P,A + MOVEI A,15 + PUSHJ P,LPTR + MOVEI A,12 + PUSHJ P,LPTR + JRST POPAJ + +LSPAC: PUSH P,A + MOVEI A,40 +L1: PUSHJ P,LPTR + POP P,A + POPJ P, + +LFORM: PUSH P,A + MOVEI A,14 + PUSHJ P,LPTR + JRST POPAJ + +LOUTST: 0 + PUSH P,A + PUSH P,B + HRRZ B,@LOUTST + HRLI B,440700 +LOUT2: ILDB A,B + JUMPE A,LOUT1 + X LPTR + JRST LOUT2 + +LOUT1: POP P,B + POP P,A + AOS LOUTST + JRST 2,@LOUTST + +TOUTST: 0 + PUSH P,A + PUSH P,B + HRRZ B,@TOUTST + PUSHJ P,OUTSTR + AOS TOUTST + POP P,B + POP P,A + JRST 2,@TOUTST + +OUTSTR: HRLI B,440700 +OUTST1: ILDB A,B + JUMPE A,CPOPJ + PUSHJ P,TYO + JRST OUTST1 + +ERRDDT: PUSHJ P,CRR + TYPE *** ERROR *** SYSTEM MAY NOT BE BROUGHT BACK UP +CRDDTE: NTS, SETZM SALVRT ;CAN'T RETURN TO SYSTEM +CRDDT: PUSHJ P,CRR + +DDT: +NTS,[ +IFN NLPTP, PUSHJ P,LPTFIN ;UNBUFFER LINE PRINTER + SKIPE SALVRT + JRST @SALVRT + TYPE DDT + SKIPN MEMSIZ-4000 + JRST 4,. ;NO DDT LOADED? + JRST MEMSIZ-4000 +];NTS +TS,[ .VALUE [ASCIZ\:DDT +\] + JRST DDT +];TS + +CRR: PUSH P,A + PUSHJ P,CRR1 + SETZM LINPOS' + JRST POPAJ + +CRR1: MOVEI A,15 + PUSHJ P,TYO + MOVEI A,12 + JRST TYO + +TSPAC: PUSH P,A + MOVEI A,40 + X TYO + JRST POPAJ + +TYO: +TS, .IOT TYOC,A +NTS,[ +KA,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,A + SKIPN PUNCH + JRST TYO0 + CONSZ PTP,20 ;WAIT FOR NOT BUSY + JRST .-1 + DATAO PTP,A +TYO0: +];KA +KL,[ + PUSH P,A + ANDI A,177 + PUSHJ P,DTEXIO + POP P,A +];KL +];NTS + AOS LINPOS + POPJ P, + +KL,[ ;DTE20 COMMUNICATION ROUTINE ... COPIED FROM DEC "SUBRTN" PROGRAM + +DTEXIO: SETZM DTEFLG + MOVEM A,DTECMD + SETZM DTEF11 + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SETZM DTEFLG + MOVE A,DTEF11 + POPJ P, +];KL + +NTYI: PUSHJ P,TYI ;INPUT DIGIT, SKIP IF WIN + CAIL A,"0 + CAILE A,"9 + POPJ P, + SUBI A,"0 +POPJ1: AOS (P) + POPJ P, + +SIXIN: PUSH P,C +SIXI1: MOVE C,[440600,,B] + SETZ B, +SIXIL: X TYI + CAIL A,140 + JRST [ TYPE XXX + JRST SIXI1] + CAIG A,40 + JRST SIXIX + CAIN A,"; + JRST SIXIL + SUBI A,40 + TLNE C,770000 + IDPB A,C + JRST SIXIL + +SIXIX: POP P,C + POPJ P, + +TYI: ;INPUT CHAR INTO A +TS, .IOT TYIC,A +NTS,[ +KA,[ + CONSO TTY,40 + JRST .-1 + DATAI TTY,A +];KA +KL,[ + MOVEI A,3400 ;"DDT MODE" INPUT + PUSHJ P,DTEXIO + JUMPE A,.-2 +];KL +];NTS + ANDI A,177 + CAIL A,"a ;MIGHT NOT BE KSR-35 + CAILE A,"z + CAIA + SUBI A,40 + CAIN A,^Z + JRST CRDDTE + JRST TYO + +;RETURN TO DDT IF CHARACTER TYPED +TYIPSE: PUSHJ P,TYIP + POPJ P, + PUSHJ P,TYI + JRST DDT + +;SKIP IF INPUT AVAILABLE +TYIP: PUSH P,A +TS,[ .LISTEN A, + SKIPE A +];TS +NTS,[ +KA, CONSZ TTY,40 +KL,[ MOVEI A,3400 + PUSHJ P,DTEXIO + SKIPE A +];KL +];NTS + AOS -1(P) + POP P,A + POPJ P, + +Y.OR.N: PUSH P,A ;YES OR NO, SKIP IF YES +YORN1: X TYI + X CRR + CAIE A,"Y + CAIN A,"N + JRST YORN2 + TYPE (Y OR N) + JRST YORN1 ;TELETYPE KEYBOARD LOSSAGE? + +YORN2: CAIN A,"Y + AOS -1(P) + JRST POPAJ + +SUBTTL MAG TAPE I/O + +NTS,[ MTC==340 ;MAG TAPE CHANNEL FOR FUNCTIONS + MTS==344 ;MAG TAPE CHANNEL FOR STOPPING AND STATUS + +;SHIFTS FOR FIELDS IN CONO MTC, + UNITNO==15. + PARITY==14. + CDUMP==13. + FUNC==9. + DENSTY==6. + + 800BPI==2 + + MAGCOM=5_+1_+800BPI_+1_ + +;FUNCTIONS + NOOP1=0_+MAGCOM ;CLEAR INTERRUPT FLAGS + NOOP2=10_+MAGCOM ;INTERRUPT WHEN TRANSPORT IDLE + REWIND=1_+MAGCOM ;REWIND + REED=2_+MAGCOM ;READ + SPACR=7_+MAGCOM ;SPACE REVERSE + +;FLAGS + JOBDON==100 + DATREQ==1 + EOFF==10000 + EOTF==4000 +;NOTE - TM10B HAS DATA PIA (CONI MTC, 1.1-1.3) STUCK AT 7 + +REW: CLEARM EOFCNT + CLEARM MAGBFP + CLEARM SHORTL + CONO MTC,NOOP1 ;CLEAR INTERRRUPT FLAGS + CONO MTC,REWIND ;INITIATE REWIND + CONSO MTS,JOBDON ;WAIT FOR REWIND TO BEGIN + JRST .-1 + CONO MTC,NOOP2 ;SET JOB DONE WHEN TRANSPORT IDLE + CONSO MTS,JOBDON ;WAIT FOR JOB DONE + JRST .-1 + SETOM ITAPE + POPJ P, ;REWIND DONE +ITAPE: 0 + +MREAD: MOVEI T,0 + PUSH P,B +MREAD7: SKIPGE B,MAGBFP + JRST MREAD5 + SKIPN EOFLG + JRST MREAD1 + SETZM EOFLG + SETOM EOUF + JRST POPBJ + +MREAD1: MOVEI B,10. + MOVEM B,MTRYS +MERR2: MOVE B,[-2000,,MAGBUF] + MOVEM B,MAGBFP + SETZM SLVIOWD + CONO MTC,NOOP1 ;CLEAR FLAGS + CONSO MTC,7 ;IS THIS A TM10B? + JRST MREADA ;NO +KA, MOVE B,[-2000,,MAGBUF-1] ;YES SET UP CHANNEL PROGRAM +KL, MOVE B,[-2000_4,,MAGBUF-1] + MOVEM B,SLVIOWD + SETZM SLVICWA+1 + SETZM SLVIOWD+1 + DATAO MTS,[SLVICWA] +KL,[ SWPUA ;UNLOAD THE CACHE + PUSH P,A + MOVE A,[CONSZ APR,200000] + MOVE B,[JRST A] + MOVE C,[POPJ P,] + PUSHJ P,A + POP P,A +] +MREADA: CONO MTC,REED +MREAD2: CONSO MTS,DATREQ+EOFF+JOBDON+EOTF ;WAIT FOR NEXT DATA REQUEST + JRST .-1 + MOVEI C,20. + SOJG C,. + CONI MTS,C + TRNE C,EOTF + JRST MREOT + TRNN C,JOBDON + JRST MREAD3 + TRNN C,EOFF + JRST MREAD6 + AOS EOFCNT + SETOM EOFLG + CLEARM SHORTL + JRST MREAD9 + +MREAD6: SETOM SHORTL +MREAD9: CONSZ MTC,7 ;SKIP IF TM10A + JRST MREADB + HLLZS B + MOVNS B + ADDM B,MAGBFP + JRST MREAD4 + +MREADB: HRRZ B,SLVICWA+1 + JUMPE B,.-1 + MOVNI B,1-MAGBUF(B) + SKIPE EOFLG + MOVSI B,0 ;EOF MARK => NO WORDS READ + HRLM B,MAGBFP + JRST MREAD4 + +MREAD3: TRNE C,DATREQ + CONSZ MTC,7 ;SKIP IF TM10A + JRST MREAD2 ;TM10B OR NO DATA REQUEST + DATAI MTC,(B) + SKIPE SHORTL + JRST 4,. + AOBJN B,MREAD2 +MREAD4: CONO MTS,1 + CONSO MTS,JOBDON + JRST .-1 + CONSZ MTS,440000 ;X HUNG + ILL OP + JRST 4,MERR +MREAD8: CONSO MTS,20600 + JRST MREAD7 +MERR: SOSG MTRYS + JRST MERR1 + SETZM SLVIOWD +KL,[ SWPUO 0 + CONSZ APR,200000 + JRST .-1 +] + CONO MTC,NOOP1 + CONO MTC,SPACR + CONSZ MTC,7 ;SKIP IF TM10A + JRST .+4 + CONSO MTS,DATREQ + JRST .-1 + DATAO MTC, + CONO MTS,1 + CONSO MTS,JOBDON + JRST .-1 + JRST MERR2 + +MERR1: AOS FERRS ;IGNORE ERR + JRST MREAD7 + +MREAD5: HLRE C,B + CAMG B,A + HLRE C,A + HRLZS B + HRR B,A + MOVNS C + HRLS C + ADDI C,-1(A) + BLT B,(C) + HLRS C + ADD A,C + ADDM C,MAGBFP + ADDI T,(C) + JUMPGE A,POPBJ + JRST MREAD7 + +MREOT: CONO MTS,1 ;STOP TAPE IF STILL MOVING + CONO MTC,NOOP1 + LPR EOT + X LCRR + JRST DDT +];NTS + +SUBTTL TYPE CONTROLLER AND DRIVE STATUS +TS,[ +GSTS: POPJ P, +];TS + +DC,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: INSIRP PUSH P,[A B C D T] + CONI DC0,D + MOVEI C,DC0STS + TYPE CONTROLLER STATUS: + PUSHJ P,TYPSTS + CONI DC1,D + MOVEI C,DC1STS + PUSHJ P,TYPSTS + CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP GETUNT] + CONSZ DC0,DSSACT + JRST .-1 + TYPE CURRENT UNIT= + LDB A,[DUNFLD GOTUNT] + DPB A,[DUNFLD STOSTS] + PUSHJ P,TDPT + TYPE ,DRIVE STATUS: + PUSHJ P,CRR + DATAO DC0,[DJMP STOSTS] + CONSZ DC0,DSSACT + JRST .-1 + MOVE D,STATUS + LSH D,-15. + MOVEI C,DRVSTS + PUSHJ P,TYPSTS + TYPE CYLINDER= + LDB A,[101100,,STATUS] + PUSHJ P,TOPT + PUSHJ P,CRR + INSIRP POP P,[T D C B A] + POPJ P, + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLRZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + ;DC +DEFINE STS A,B/ +A,,[ASCIZ \B\] +TERMIN + +DC0STS: STS 4000,ERROR-FLG + STS 1000,ATTENTION + STS 200,RUN + STS 100,ACTIVE + 0 + +DC1STS: STS 4000,INTERNAL-PARITY-ERROR + STS 2000,RECORD-LENGTH + STS 1000,READ-COMPARE + STS 400,OVERRUN + STS 200,CHECKSUM/DECODER + STS 100,BARK!! + STS 40,FILE-UNSAFE/SEEK-INCOMPLETE/END-OF-DISC + STS 20,OFF-LINE/MULTIPLE-SELECT + STS 10,RDG-KEY/PROTECT/READONLY + STS 4,DATAO-WHILE-BUSY + STS 2,NON-EX-MEM + STS 1,CORE-PARITY-ERROR + 0 + +DRVSTS: STS 4,UNIT-SELECTED + STS 10,ON-LINE + STS 20,READY + STS 40,SEEK-INCOMPLETE + STS 100,READ-ONLY + STS 200,UNSAFE + STS 400,WRITE-CURRENT-SENSED(?) + 0 + +GETUNT: DJSR .+1 +GOTUNT: 0 + DHLT + +STOSTS: DSDRST+DUNENB STATUS(74) + DHLT +STATUS: 0 +];DC + +RP,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: INSIRP PUSH P,[A B C D T] + TYPE DISK STATUS: + CONI DPC,D + MOVEI C,CNLSTS + TLNE D,-1 + PUSHJ P,TYPSTS + MOVSS D + MOVEI C,CNISTS + PUSHJ P,TYPSTS + DATAI DPC,D + TLC D,1 ;REVERSE SENSE OF WRITE HEADER LOCKOUT SWITCH + MOVEI C,DTISTS + PUSHJ P,TYPSTS + TYPE CURRENT UNIT= + LDB A,[DUNFLI D] + PUSHJ P,TDPT + TYPE , CYLINDER= + LDB A,[DCYLI D] + TRNE D,.BM DCYLXI + ADDI A,400 + PUSHJ P,TOPT + TYPE , LAST ADDRESSED CYL= + MOVE A,RPIOCY + X TOPT + TYPE , SURF= + MOVE A,RPIOHD + X TOPT + TYPE , SEC= + MOVE A,RPIOSC + X TOPT + PUSHJ P,CRR + INSIRP POP P,[T D C B A] + POPJ P, + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLLZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + + ;RP +DEFINE STS A,B/ +A,,[ASCIZ \B\] +TERMIN + +; CONI STATUS TABLE (RH) + +CNISTS: STS 400000,SEARCH DONE + STS 200000,END OF CYLINDER + STS 100000,POWER FAILURE + STS 040000,SEARCH ERROR + STS 020000,OVERRUN + STS 010000,NXM + STS 002000,DRIVE NOT READY + STS 001000,WRITE PROTECT + STS 000400,DATAO WHEN BUSY + STS 000200,SECTOR ADDRESS ERROR + STS 000100,SURFACE ADDRESS ERROR + STS 000020,BUSY + STS 000010,DONE + 0 + +; CONI STATUS TABLE (LH) + +CNLSTS: STS 000010,CONTROL WORD PARITY ERROR + STS 000004,SECTOR PARITY ERROR + STS 000002,MEMORY WORD PARITY ERROR + STS 000001,DISK WORD PARITY ERROR + 0 + +; DATAI STATUS TABLE (LH) + +DTISTS: STS 000100,SEEK INCOMPLETE + STS 000040,ON CYLINDER + STS 000020,DISK ON-LINE + STS 000010,FILE UNSAFE + STS 000004,NON EXISTENT DRIVE + STS 000002,DRIVE IS READ-ONLY + STS 000001,WRITE HEADER LOCKOUT OFF!! + 0 +];RP + +RH,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: +IFN T300P,[ + SKIPE T3IOP + JRST T3STS ;LAST OPERATION WAS REALLY TO T-300 +];T300P + INSIRP PUSH P,[A B C D T I K] + TYPE CONTROLLER STATUS: + CONI DSK,D + MOVEI C,CNLSTS + TLNE D,-1 + PUSHJ P,TYPSTS + MOVSS D + MOVEI C,CNISTS + PUSHJ P,TYPSTS + TYPE CURRENT REGISTER: + DATAI DSK,D + PUSHJ P,TYPRGN + MOVE A,D + PUSHJ P,TOPT ;TYPE REG NO, STATUS, AND CONTENTS IN OCTAL + JUMPL D,GSTS0 ;DO FOLLOWING ONLY FOR DRIVE REGS + MOVEI A,", + PUSHJ P,TYO + MOVEI C,DIBSTS + PUSHJ P,TYPSTS + CAIA ;DON'T GIVE BLANK LINE +GSTS0: PUSHJ P,CRR + TYPE CURRENT DRIVE= + LDB A,[$HCDRV D] + PUSHJ P,TDPT + PUSHJ P,CRR + MOVEI I,NUNITS-1 ;CONVERT BACK TO VIRTUAL UNIT + CAME A,QTRAN(I) ;TO MAKE RHGET HAPPY + SOJGE I,.-1 + JUMPL I,GSTS3 ;FOO!! ADDRESSING NON EXISTENT DRIVE + + MOVSI K,-LGSTSR ;DISPLAY DRIVE REGS SPEC'ED IN TABLE +GSTS1: MOVE D,GSTSRT(K) + PUSHJ P,TYPRGN ;TYPE REG NAME + HRRZ C,D ;C -> STATUS BIT TABLE + HLLZ A,D ;A := REG NUMBER + PUSHJ P,RHGET ;GET CONTENTS OF REG + JRST GSTSER ;?? + PUSHJ P,TOPT ;GIVE CONTENTS IN OCTAL + PUSHJ P,TSPAC + MOVS D,A ;AND SYMBOLICLY + PUSHJ P,TYPSTS + AOBJN K,GSTS1 +GSTS3: INSIRP POP P,[K I T D C B A] + POPJ P, + +GSTSER: TYPE BARF: + MOVE D,A + MOVEI C,DIBSTS + PUSHJ P,TYPSTS + JRST GSTS3 ;DON'T TRY ANY MORE REGS + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLLZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + +TYPRGN: LDB A,[360600,,D] ;TYPE NAME OF REGISTER ADDRESSED BY D + ROT A,-1 + MOVE B,RHRGTB(A) + JUMPL A,.+2 + MOVSS B + PUSHJ P,OUTSTR + MOVEI A,"= + JRST TYO + +;TABLE OF DRIVE REGISTERS THAT NEED TO BE DISPLAYED +; LH = REG ADDR, RH = STATUS BITS TABLE ADDR + +GSTSRT: %HRDCL,,[0] + %HRSTS,,STSSTS + %HRCYL,,[0] + %HRCCY,,[0] + %HRADR,,[0] + %HROFS,,OFSSTS + %HRER1,,ER1STS + %HRER2,,ER2STS + %HRER3,,ER3STS +LGSTSR==.-GSTSRT + ;RH +DEFINE STS A,B/ +A,,[ASCIZ \B\] ? TERMIN + +; CONI STATUS (LH) + +CNLSTS: STS 400000,AR FULL + STS 200000,CB FULL + STS 040000,CC INH + STS 020000,CHANNEL ACTIVE + STS 010000,CHANNEL PULSE + STS 004000,22-BIT CHANNEL + STS 000400,CXR ILL FUNC + STS 000200,CXR DRIVE ACCESS ERR + STS 000004,MEMORY PARITY + STS 000002,CONTROL WORD PARITY + STS 000001,NXM + 0 + +; CONI STATUS (RH) + +CNISTS: STS 400000,DATA BUS PARITY + STS 200000,DRIVE EXCEPTION + STS 100000,CHANNEL ERROR + STS 020000,CHANNEL OVERRUN + STS 010000,DRIVE RESPONSE ERR + STS 004000,CXR ILL CMD + STS 002000,CXR POWER FAIL + STS 000200,CONTROL BUS OVERRUN + STS 000100,RAE INTR + STS 000040,ATTN INTR + STS 000020,BUSY + STS 000010,DONE + 0 + +; REGISTERS + +ZZ==-1 +XX==0 +YY==0 +DEFINE REG N,T/ +IFLE N-ZZ, .ERR REG OUT OF ORDER +REPEAT N-ZZ-1, REGH [ASCIZ\????\] + REGH [ASCIZ\T\] +TERMIN + +DEFINE REGH [A] +ZZ==ZZ+1 +IFE XX, YY==A +IFN XX, YY,,A +XX==1-XX +TERMIN + +RHRGTB: REG 0,DRV CTL + REG 1,DRV STATUS + REG 2,DRV ER1 + REG 3,DRV MAINT + REG 4,ATTENTION + REG 5,DRV TRACK-SECTOR + REG 6,DRV TYPE + REG 7,DRV LOOK-AHEAD + REG 10,DRV SERIAL NO + REG 11,DRV OFFSET + REG 12,DRV DESIRED CYL + REG 13,DRV CURRENT CYL + REG 14,DRV ER2 + REG 15,DRV ER3 + REG 16,DRV ECC POS + REG 17,DRV ECC PAT + REG 40,CONTROL + REG 44,INTR ADDR + REG 50,DATA BUFFER + REG 54,RAE STATUS + REG 74,CHANNEL BUFFER + REG 100,FOO +LOC RHRGTB+40 +EXPUNGE REG,REGH,XX,YY,ZZ + +; BITS IN DIB REGISTER + +DIBSTS: STS 004000,CTL-TO-DRIVE + STS 002000,CTL BUS TIMEOUT + STS 001000,CTL BUS PARITY + STS 000400,DIB DATA LATE + STS 000200,DIB ILL CMD + 0 + +; DRIVE STATUS REGISTER + +STSSTS: STS 1,FWD 5 IPS + STS 2,FWD 20 IPS + STS 4,INNER GUARD BAND + STS 10,GO REVERSE + STS 20,DIFF < 64 + STS 40,DIFF = 1 + STS 100,VOLUME VALID + STS 200,DRIVE READY + STS 400,CONN THIS CTRLR + STS 2000,LAST SECTOR XFERD + STS 4000,WRITE LOCK + STS 10000,MEDIUM ONLINE + STS 20000,POSITIONING IN PROGRESS + STS 40000,ERR + STS 100000,ATTENTION + 0 + +; DRIVE ERROR REGISTER 1 + +ER1STS: STS 1,ILL FUNC + STS 2,ILL REG + STS 4,REG MOD REFUSE + STS 10,BUS PARITY ERR + STS 20,PACK FORMAT ERR + STS 40,WRITE CLOCK FAIL + STS 100,ECC HARD ERR + STS 200,HEADER WRONG + STS 400,HEADER CRC ERR + STS 1000,ADDR OVERFLOW + STS 2000,INVALID ADDR + STS 4000,WRITE LOCK ERR + STS 10000,DRV TIMING ERR + STS 20000,OP NOT COMPLETE + STS 40000,UNSAFE + STS 100000,DATA CHECK + 0 + +; DRIVE ERROR REGISTER 2 + +ER2STS: STS 1,WRITE CURRENT UNSAFE + STS 2,CURRENT SINK FAILURE + STS 4,WRITE SELECT UNSAFE + STS 10,CURRENT SWITCH UNSAFE + STS 20,MOTOR SEQUENCE ERR + STS 40,TRANSITIONS DET FAIL + STS 100,TRANSITIONS UNSAFE + STS 200,"UNSAFE EXCEPT R/W" + STS 400,WRITE READY UNSAFE + STS 1000,MULTIPLE HEAD SELECT + STS 2000,NO HEAD SELECT + STS 4000,INDEX ERROR + STS 10000,30 VOLT UNSAFE + STS 20000,PHASE LK OSC UNSAFE + STS 100000,AC UNSAFE + 0 + +; DRIVE ERROR REGISTER 3 + +ER3STS: STS 1,PACK SPEED UNSAFE + STS 2,VELOCITY UNSAFE + STS 10,UNSAFE EXCEPT R/W + STS 40,AC LOW + STS 100,DC LOW + STS 40000,SEEK INCOMPLETE + STS 100000,OFF CYLINDER + 0 + +; DRIVE OFFSET REGISTER + +OFSSTS: STS 2000,HDR COMPARE INH + STS 4000,ECC INHIBIT + STS 10000,PDP-11 FORMAT + 0 +];RH + +IFN T300P,[ +;PRINT STATUS OF T300 (ERROR FROM LAST COMMAND) +;LATER THIS WILL BE INTEGRATED INTO GSTS +T300ST: MOVEI P,PDL + PUSH P,[DDT] +T3STS: INSIRP PUSH P,[A B C D T I K] + TYPE T-300 AND 2561 STATUS: + SKIPN D,DSCFLT + JRST T3STS2 + TRNN D,%DFRST+%DFCQE+%DFNXM+%DFPAR + JRST T3STS1 + MOVEI C,[ STS %DFRST,CONTROLLER POWER-CYCLED AND RESET + STS %DFCQE,COMMAND-QUEUE ERROR + STS %DFNXM,RQB NXM + STS %DFPAR,RQB PARITY ERROR + 0 ] + MOVSS D ;TYPSTS WANTS BITS IN LEFT HALF + PUSHJ P,TYPSTS + TYPE , PDP-11 ERROR ADDRESS= + LDB A,[000200,,DSCFLT] + LSH A,16. + IOR A,DSCSTS + PUSHJ P,TOPT +T3STS9: PUSHJ P,CRR + JRST GSTS3 + +;FAULT CODE +T3STS1: CAILE D,17 + JRST [ TYPE ILLEGAL FAULT CODE= + MOVE A,D + PUSHJ P,TOPT + JRST T3STS9 ] + MOVE B,(D)[ [ASCIZ/FAULT CODE 0?/] + [ASCIZ/DRIVE NOT READY/] + [ASCIZ/ILLEGAL HEAD OR SECTOR/] + [ASCIZ/SEEK TIMEOUT/] + [ASCIZ/DISK STATUS BAD AFTER ON-CYLINDER (FAULT CODE 4)/] + [ASCIZ/TIME OUT WRITING SECTOR ID (FAULT CODE 5)/] + [ASCIZ/FIFO ERROR IN FORMAT WRITE (FAULT CODE 6)/] + [ASCIZ/WRITE TIMEOUT (FAULT CODE 7)/] + [ASCIZ/SEEK TIMEOUT (FAULT CODE 10)/] + [ASCIZ/HEADS NOT LOADED/] + [ASCIZ/READ TIMEOUT (FAULT CODE 12)/] + [ASCIZ/INDEX TIMEOUT (FAULT CODE 13)/] + [ASCIZ/SECTOR TIMEOUT (FAULT CODE 14)/] + [ASCIZ/FAULT CODE 15?/] + [ASCIZ/DMA TIMEOUT (FAULT CODE 16)/] + [ASCIZ/DMA TIMEOUT IN ECC (FAULT CODE 17)/] ] + PUSHJ P,OUTSTR + PUSHJ P,CRR +;COMMAND OK, CHECK ORDINARY ERROR STATUS +T3STS2: MOVE D,DSCSTS + MOVEI C,[ STS %DSRTR,COMMAND WAS RETRIED + STS %DSECH,UNCORRECTABLE DATA ERROR + STS %DSECC,CORRECTED DATA ERROR + STS %DSIDE,ID ERROR + STS %DSHCE,HEADER COMPARE ERROR + STS %DSPRT,WRITE-PROTECTED SECTOR + STS %DSALT,ALTERNATE-SECTOR FLAG + STS %DSOVR,OVERRUN + STS %DSSKE,SEEK ERROR + STS %DSOFL,DRIVE OFF-LINE OR FAULT + STS %DSFLT,DRIVE FAULT + STS %DSNXM,PDP11 MEMORY NXM + STS %DSPAR,PDP11 MEMORY PARITY ERROR + STS %DSSFL,SYSTEM FAULT + STS %DSWLK,DRIVE WRITE-LOCKED + 0 ] + MOVSS D ;TYPSTS WANTS D IN LEFT HALF + PUSHJ P,TYPSTS + PUSHJ P,CRR ;NOW SHOW DISK COMMAND AND ADDRESS + TYPE DISK COMMAND: + MOVE A,DSCCMD + PUSHJ P,TOPT + PUSHJ P,TSPAC + MOVEI B,[ASCIZ/(UNKNOWN?)/] + CAIN A,%DMSNS + MOVEI B,[ASCIZ/(SENSE)/] + CAIN A,%DMTST + MOVEI B,[ASCIZ/(DIAGNOSTICS)/] + CAIN A,%DMREC + MOVEI B,[ASCIZ/(RECALIBRATE)/] + CAIN A,%DMSEK + MOVEI B,[ASCIZ/(SEEK)/] + CAIN A,%DMWRT + MOVEI B,[ASCIZ/(WRITE)/] + TRNE A,%DMRED + JRST [ CAIG A,%DMRED+10 + MOVE B,(A)[ [ASCIZ/(READ)/] + [ASCIZ/(READ EARLY-DATA-STROBE)/] + [ASCIZ/(READ LATE-DATA-STROBE)/] + [ASCIZ/(READ POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ NEGATIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ EARLY-DATA-STROBE POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ EARLY-DATA-STROBE NEGATIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ LATE-DATA-STROBE POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ LATE-DATA-STROBE NEGATIVE-CYLINDER-OFFSET)/] + ]-%DMRED + JRST .+1 ] + PUSHJ P,OUTSTR + TYPE , DRIVE= + MOVE A,DSCDRV + PUSHJ P,TOPT + TYPE , CYL= + MOVE A,DSCCYL + PUSHJ P,TOPT + TYPE , HEAD= + MOVE A,DSCHED + PUSHJ P,TOPT + TYPE , SEC= + MOVE A,DSCSEC + PUSHJ P,TOPT + JRST T3STS9 +];T300P + +SUBTTL READ & TYPE OUT HEADERS + +DC,[ ;FOR NOW, DC10 ONLY +RDHDHD==20 ;2WORDS PER SEC, MANY SECS + +RDHEAD: JSR INIT ;READ ALL HEADERS ON A TRACK + PUSHJ P,CRR + UNTMES UNIT= + PUSHJ P,GETNUM + JRST RDHEAD + CAIL A,NUNITS + JRST RDHEAD + MOVEM A,TOU + MOVE I,A + PUSHJ P,RESET +RDHD1: TYPE CYL= + PUSHJ P,GETNUM + JRST DDT + CAIL A,NCYLS+XCYLS + JRST RDHD1 + SKIPGE QTRAN(I) + ADDI A,NCYLS+XCYLS + DPB A,[DCYL READHD] + TYPE SURF= + PUSHJ P,GETNUM + SETZ A, + CAIL A,NHEDS + JRST RDHD1 + DPB A,[DSURF READHD] + DATAO DC0,[DJMP READHD] + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR + JRST [ TYPE ERROR--- + JRST GETSTS] + SETOM SECT0' + SETOM FIRST + SETZ T, +RDHD2: MOVE D,HEADBF(T) + TLZ D,777000 + CAMN D,SECT0 + JRST RDHD1 ;GONE AROUND ONCE + AOSN FIRST + MOVEM D,SECT0 + TYPE PKID= + LDB A,[DPKID HEADBF(T)] + PUSHJ P,TOPT + PUSHJ P,TCOMMA + MOVE D,HEADBF(T) + PUSHJ P,TYPLOC + PUSHJ P,CRR + MOVE A,HEADBF+1(T) + TLNE A,1000 ;INDIRECT BIT OF HEADER + JRST [ MOVEI A,"@ + PUSHJ P,TYO + MOVE D,HEADBF+1(T) + PUSHJ P,TYPLOC + JRST RDHD6] + TYPE LENGTH= + MOVN A,HEADBF+1(T) + LDB A,[1600,,A] ;LENGTH FIELD + PUSHJ P,TOPT + LDB A,[270200,,HEADBF+1(T)] ;ANY NEXT-ADDRESS CODE? + JUMPE A,RDHD3 + MOVE B,NXTADR(A) + PUSHJ P,OUTSTR +RDHD3: MOVE A,HEADBF+1(T) + TLNE A,200 + JRST [ MOVEI B,[ASCIZ /,WRITE PROTECT/] + PUSHJ P,OUTSTR + JRST .+1] +RDHD6: SETO C, ;PARITY + HRLI T,-2 +RDHD4: MOVEI D,14. + MOVE A,HEADBF(T) + XORM A,C + LSH A,-2 + SOJG D,.-2 + AOBJN T,RDHD4 + TRNN C,3 ;BOTH ODD? + JRST RDHD5 + MOVEI B,[ASCIZ /,BAD PARITY!!/] + PUSHJ P,OUTSTR +RDHD5: PUSHJ P,CRR + CAIL T,RDHDHD*NSECS + JRST RDHD1 + JRST RDHD2 + +READHD: DSPC+DSWIDX+DSWNUL+DSCRHD ;WAIT FOR INDEX, THENREAD HEADERS + QCOPY HEADBF,RDHDHD*NSECS + DHLT + +HEADBF: BLOCK RDHDHD*NSECS + +TCOMMA: MOVEI A,", + JRST TYO + +NXTADR: 0 + [ASCIZ /,END-OF-TRACK/] + [ASCIZ /,END-OF-CYLINDER/] + [ASCIZ /,END-OF-DISC/] + +TYPLOC: TYPE CYL= + LDB A,[DCYL D] + PUSHJ P,TOPT + TYPE ,SURF= + LDB A,[DSURF D] + PUSHJ P,TOPT + TYPE ,SECT= + LDB A,[DSECT D] + JRST TOPT + +GETNUM: SETZ C, + SETOM FIRST +GETNM1: PUSHJ P,TYI + CAIL A,"0 + CAILE A,"9 + JRST [ MOVE A,C + SKIPL FIRST + AOS (P) + JRST CRR] + AOS FIRST + IMULI C,10 + ADDI C,-"0(A) + JRST GETNM1 +];DC + +SUBTTL DRIVE RESET + +NTS,[ +DC,[ +RECAL: CONO DC0,DCCSET+DCDENB + MOVE T,QTRAN(I) + SKIPL DRIVE(T) ;SKIP IF DRIVE NOT KNOWN TO BE DEAD ALREADY + JRST [ SETZM QACT(I) + POPJ P,] + DPB T,[DUNFLD DRST] + DPB T,[DUNFLD STOSTS] + DATAO DC0,[DJMP STOSTS] + CONSZ DC0,DSSACT + JRST .-1 + MOVE T,STATUS + TDNN T,[DDSONL] ;ON LINE + JRST OFFL1 + DATAO DC0,DRST + CONSO DC0,DSSATT + JRST .-1 + CONSO DC1,20 ;OFF LINE OR MULTIPLE SELECT + POPJ P, +OFFL1: SETZM QACT(I) + SKIPE GOGOX + POPJ P, ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE Drive off line # + PUSH P,A + HRRZ A,QTRAN(I) + SETZM DRIVE(A) + PUSHJ P,DPT + POP P,A + PUSHJ P,CRR + POPJ P, +];DC + +RP,[ +RESET: PUSH P,A + CONSZ DPC,BUSY + JRST .-1 + DATAO DPC,[DEASEC 776] + DPB I,[DUNFLD DRST] + DATAO DPC,DRST +RESET0: DATAI DPC,T + TLNE T,20 + JRST RESET1 + SKIPE GOGOX + JRST RESET9 ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE OFF LINE # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,CRR + JRST RESET9 + +RESET1: TLNN T,4 + JRST RESET2 + SKIPE GOGOX + JRST RESET9 ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE NO SUCH DRIVE # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,LCRR + JRST RESET9 + +RESET2: TRNN T,776 + JRST RESET0 + DATAO DPC,[DEASEC 776] + JRST POPAJ + +RESET9: SETZM QACT(I) ;THIS DRIVE LOST + JRST POPAJ + +DRST: DRCALC +];RP + +DC,[ +RESET: PUSHJ P,RECAL + MOVE T,QTRAN(I) ;GET PACK ID FROM HARDWARE + DPB T,[DUNFLD GPKID] + MOVEI T,TUTCYL + SKIPGE QTRAN(I) + ADDI T,NCYLS+XCYLS + DPB T,[DCYL GPKID] + CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP GPKID] + CONSZ DC0,DSSACT + JRST .-1 + LDB T,[DPKID RPKID] + MOVEM T,PKNUM(I) + POPJ P, + +DRST: DSPC+DSRCAL+DSWINF+DUNENB +GPKID: DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +];DC +];NTS + +TS,[ +RESET: PUSH P,A + HRRZ A,QTRAN(I) + SKIPL DRIVE(A) + JRST OFFL2 + CAML I,NQS + JRST OFFL2 + HRRZ A,SQACT ;SYSTEM QACT TABLE + ADD A,I + MOVSS A + HRRI A,A + .GETLOC A, ;COPY SYSTEMS QACT + SKIPE A ;0 MEANS ON-LINE TO ITS + JRST OFFLIN + POP P,A + POPJ P, + + +OFFLIN: TYPE Drive off line # + HRRZ A,QTRAN(I) + SETZM DRIVE(A) + PUSHJ P,DPT + PUSHJ P,CRR +OFFL2: SETZM QACT(I) + POP P,A + POPJ P, +];TS + +NTS,[ +RH,[ +RESET: MOVE T,QTRAN(I) ;GET PHYS DRIVE +IFN T300P,[ + CAIL I,T300P + JRST T3RST +];T300P + SKIPL DRIVE(T) + JRST [ SETZM QACT(I) ;DRIVE ALREADY KNOWN TO BE DOWN + POPJ P, ] + PUSH P,A + MOVE A,[%HRDCL,,%HMCLR] ;CLEAR THE DRIVE + PUSHJ P,RHSET + JRST RESETL ;HMM, NO DRIVE + MOVE A,[%HRDCL,,%HMRDP] ;I SAID, "CLEAR THE DRIVE"! + PUSHJ P,RHSET + JRST RESETL + MOVE A,[%HROFS,,0] ;CLEAR THE FRIGGING DRIVE!!! + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRTYP ;GET DRIVE TYPE + PUSHJ P,RHGET + JRST RESETL ;?? + TRNE A,140000 + JRST RESETL ;TAPE? + TRNN A,020000 + JRST RESETL ;FIXED HEADS? + MOVE A,[%HRDCL,,%HMACK] ;PACK ACKNOWLEDGE + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRSTS + PUSHJ P,RHGET + JRST RESETL + TRNN A,%HSMOL + JRST RESET4 ;PACK NOT MOUNTED + MOVE A,[%HRDCL,,%HMREC] ;RECALIBRATE + PUSHJ P,RHSET + JRST RESETL + MOVEI B,80000. ;A LITTLE OVER 1/2 SEC +RESET0: MOVSI A,%HRSTS ;GET STATUS + PUSHJ P,RHGET + JRST RESETL ;DRIVE VANISHED? + TRNE A,%HSERR + JRST RESETL ;GOT ERROR RECALIBRATING? + TRC A,%HSVV+%HSMOL+%HSRDY ;CHECK FOR GOOD BITS + TRCE A,%HSVV+%HSMOL+%HSRDY + SOJG B,RESET0 ;BITS NOT ALL ON, WAIT MORE + JUMPG B,RESET5 ;WON. + ;TIMED OUT, FALL INTO RESETL + +RESETL: SETZM QACT(I) ;LOST + SKIPE GOGOX + JRST POPAJ ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + CONSZ DSK,%HIDRE + JRST RESET1 + CONSZ DSK,%HIILC + JRST RESET2 + TYPE MISC ERROR DRIVE # + MOVEI A,GSTS ;CALL GSTS BEFORE RETURNING + EXCH A,(P) + PUSH P,A + JRST RESET3 + +RESET2: TYPE ILC OR RAE DRIVE # + JRST RESET3 + +RESET1: TYPE DRIVE NOT PRESENT # +RESET3: HRRZ A,QTRAN(I) + X DPT + X CRR + JRST POPAJ + +RESET4: SETZM QACT(I) + SKIPE GOGOX + JRST POPAJ ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE DRIVE OFF LINE # + JRST RESET3 + +RESET5: SKIPE MARKF + JRST POPAJ ;PACK NOT FORMATTED YET + MOVSI A,%HRCYL + HRRI A,TUTCYL + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRADR + PUSHJ P,RHSET + JRST RESETL + MOVE A,[-2_4,,SLVIOWD-1] + MOVEM A,SLVICWA + SETZM SLVICWA+1 +KL,[ SWPUO 0 + CONSZ APR,200000 + JRST .-1 +] + MOVE A,[%HRCTL,,SLVICWA_6+%HMRHD] + PUSHJ P,RHSET + JRST RESETL + CONSO DSK,%HIDONE + JRST .-1 + CONSZ DSK,%HIERR + JRST RESETL + HRRZ A,SLVIOWD+1 ;GET I.T.S. PACK NUMBER + MOVEM A,PKNUM(I) + JRST POPAJ +];RH + +IFN T300P,[ +T3RST: PUSH P,D + MOVEI D,%DMSNS ;FIRST, SENSE STATUS (RECALIBRATE HANGS IF + PUSHJ P,T3CMD ; DRIVE OFF LINE, AND TIMEOUT LEAVES 11 WEDGED) + JUMPL T,T3RSTL ;TIMEOUT, 11 MUST BE DOWN + TDNE T,[%DFRST,,%DSOFL+%DSSFL] + JRST T3RSTL ;DRIVE OFF-LINE, LEAVE IT ALONE + MOVEI D,%DMREC ;SEND A RECALIBRATE + PUSHJ P,T3CMD + JUMPN T,T3RSTL ;JUMP IF ERROR + SETOM PKNUM(I) ;PACK NUMBER NOT GOTTEN FROM HARDWARE! + POP P,D + POPJ P, + +T3RSTL: SETZM QACT(I) ;OFF LINE + POP P,D + SKIPN GOGOX + JRST T3STS + POPJ P, + +;DO COMMAND IN D ON DRIVE NUMBER IN I, RETURN STATUS IN T (0 IF OK) +;LH(T) GETS DSCFLT, RH(T) GETS DSCSTS +;YOU MUST SET UP DSCCYL, ETC. BEFORE CALLING +T3CMD: MOVEI T,2561 + MOVEM T,DSCCHK + MOVEM D,DSCCMD + MOVEI T,-T300P(I) + MOVEM T,DSCDRV + SETZM DSCDON +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 + JRST .-1 +];KL + MOVEI T,1 + MOVEM T,DSCREQ +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 ;AGAIN SO 11 WILL SEE DSCREQ ON IN INTERRUPT + JRST .-1 +];KL + CONO DLC,100040 ;INTERRUPT 11 + MOVEI T,60000. ;I THINK THIS TIMEOUT IS ABOUT 3 SECONDS + ;UNFORTUNATELY, THIS TIMEOUT DOESN'T WORK ANYWAY + ;REALLY, BECAUSE IF DRIVE 0 IS OFFLINE THE + ;CONTROLLER HANGS AND EXECUTES COMMANDS WRONG + ;AND OTHERWISE LOSES ITS ASS. +T3CMD1: +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 ;AGAIN SO DSCDON GETS PICKED UP FROM MAIN MEMORY + JRST .-1 +];KL + SKIPN DSCDON + SOJG T,T3CMD1 + JUMPLE T,[ MOVSI T,(SETZ) ;SIGNAL TIMEOUT (DRIVE OFFLINE?) + POPJ P, ] ;DSCFLT & DSCSTS WILL SAY NON-ERROR + SETZM DSCDON + CONO DLC,10 ;11 IS TRYING TO INTERRUPT -10, TURN IT OFF + HRLZ T,DSCFLT + HRR T,DSCSTS + TRZE T,%DSRTR+%DSECC ;THESE ARE NOT ERRORS + AOS CERRS + POPJ P, +];T300P +];NTS + +SUBTTL READ & WRITE TUT + +;DISK NUMBER IN I, CORE ADDR IN A, ERROR RETURN HAS T NEGATIVE + +WRTUT: +TS, JRST SUCCESS +NTS,[ MOVE J,MFDBK + SUB J,NTBL(I) +WRTUT0: PUSHJ P,WRITE + JUMPL T,CPOPJ + ADDI A,2000 + ADDI J,1 + CAMGE J,MFDBK + JRST WRTUT0 + POPJ P, +];NTS + +RDTUT: +NTS,[ MOVE J,MFDBK + SUB J,NTBL(I) +RDTUT0: PUSHJ P,READ + JUMPL T,CPOPJ + ADDI A,2000 + ADDI J,1 + CAMGE J,MFDBK + JRST RDTUT0 + POPJ P, +];NTS +TS,[ TUTPAG==600000 ;READ TUT BY MAPPING IN ABS PAGE + MOVE T,NTBL(I) ;SIZE OF TUT ON THIS DRIVE + MOVE J,[SQUOZE 0,QTUTO] ;AND WHERE ARE THEY LOCATED? + .EVAL J, + .VALUE + PUSH P,A + PUSH P,I + ADD J,I ;-> -> FIRST BLOCK THIS TUT + MOVSS J + HRRI J,J + .GETLOC J, + HRRZS J + LSH J,-10. ;FIRST BLOCK# OF TUT + MOVN I,T + HRL J,I ;AOBJN PTR FOR BLOCKS OF THIS TUT +RDTUT1: .CALL [ SETZ + 'CORBLK + MOVEI 210000 ;READ ONLY + MOVEI -1 ;INTO SELF + MOVEI TUTPAG/2000 + MOVEI 400000 ;FROM SYSTEM + SETZI (J) ] + .VALUE + MOVSI I,TUTPAG + JRST RDTUT3 + +RDTUT3: HRRI I,(A) + BLT I,1777(A) ;COPY IN A BLOCK OF TUT + ADDI A,2000 + AOBJN J,RDTUT1 + POP P,I + POP P,A + SKIPGE QPKNUM(A) + .VALUE ;OLD FORMAT? + SKIPN QLASTB(A) + .VALUE ;OLDER FORMAT? + JRST SUCCESS +];TS + +SUBTTL DISK I/O + +WRITT: MOVE I,TOU +WRITE: HRRZM J,LBLK' +TS,[ HRRZ TT,I + CAML TT,NQS + .VALUE + HRRZ TT,J + CAIGE TT,TBLKS + SKIPGE TT + .VALUE + JRST SUCCESS +];TS +DC,[ SKIPA T,[DWR] +READ: MOVEI T,DRD ;A/ CORE LOCN, I/ DRIVE J/TRACK # + HRRM T,DGO + HRRZM J,BLK + MOVEM I,UNIT + HRRZ TT,I + CAIL TT,NUNITS + JRST 4,. + HRRZ TT,J + CAIGE TT,TBLKS + SKIPGE TT + JRST 4,. + MOVE TT,QTRAN(I) ;GET PHYSICAL DRIVE # + DPB TT,[DUNFLD (T)] + DPB A,[DCCA 1(T)] + DPB A,[DCCA 4(T)] + HRRZ TT,J + CAIL TT,NBLKS+XBLKS + JRST 4,. + IDIVI TT,NSECS + DPB T,[DSECT @DGO] + IDIVI TT,NHEDS + DPB T,[DSURF @DGO] + MOVE T,TT + SKIPGE QTRAN(I) + ADDI T,NCYLS+XCYLS ;MAP INTO 2ND HALF OF CALCOMP + DPB T,[DCYL @DGO] + MOVE T,PKNUM(I) + CAIL TT,NCYLS + MOVEI T,0 + DPB T,[DPKID @DGO] + HRRZ TT,DGO + MOVE T,(TT) + TLZ T,340000 ;CHANGE TO READ COMPARE + MOVEM T,3(TT) +RW1: MOVEI T,30. + SKIPE HCRASH + MOVEI T,0 ;SPEED IS OF THE ESSENCE - TRY ONLY ONCE +RW2: CONO DC0,DCCSET\DCDENB + DATAO DC0,DGO + MOVSI TT,3 ;WAIT AT MOST 3 SECONDS + CONSZ DC0,DSSACT + SOJGE TT,.-1 + JUMPL TT,[ PUSH P,T + X RECAL + POP P,T + JRST .+2 ] + CONSZ DC0,DSSERR + SOJGE T,RW2 + SKIPGE T + AOS FERRS + POPJ P, + +DGO: DJMP . + +DRD: DREAD+DUNENB + DCOPY .(-2000_2&37774) + DCOPY RXWDS(-4_2&37774) + DRC + DCCOMP .(-2000_2&37774) + DCCOMP RXWDS (-4_2&37774) + DHLT + +DWR: DWRITE+DUNENB + DCOPY .(-2000_2&37774) + DCOPY WXWDS(-4_2&37774) + DRC + DCCOMP .(-2000_2&37774) + DCCOMP WXWDS(-4_2&37774) + DHLT +];DC + +TS,[ +READ: HRRZ TT,I + CAIL TT,NUNITS + .VALUE + HRRZ TT,J + CAMN TT,MFDBK + JRST [ .OPEN QIN,[.BII,,'DSK + SIXBIT /M.F.D./ + SIXBIT /(FILE)/] + .VALUE + JRST RDIN] + CAML TT,NUDS + .VALUE ;SOME RANDOM DISK BLOCK + .SUSET [.SSNAM,,USRNAM] + .OPEN QIN,[.BII,,'DSK + SIXBIT /.FILE./ + SIXBIT /(DIR)/] + .VALUE +RDIN: HRLI A,-2000 + .IOT QIN,A + .CLOSE QIN, +SUCCES: MOVEI T,30. + POPJ P, +];TS + RP,[ ;RP10 I/O - FALL IN FROM WRITE + SKIPA T,DWR +READ: MOVE T,DRD + MOVEM T,RPIOOP + HRRZ TT,J + CAIL TT,MBLKS+XBLKS + JRST 4,. + IMULI TT,SECBLK + IDIVI TT,NSECS + MOVEM T,RPIOSC + IDIVI TT,NHEDS + MOVEM T,RPIOHD + MOVEM TT,RPIOCY + MOVEM A,RPAOBJ + MOVNI T,2000 + HRLM T,RPAOBJ + JRST RPIO ;DO IT + +DRD: DREADC+SLVICWA+5000 ;DISABLE PARITY ERROR STOPS +DWR: DWRITC+SLVICWA + +;VARIABLES SET UP TO CONTROL TRANSFER +;WHEN AN ERROR OCCURS, IT GOES INTO SECTOR AT A TIME MODE, AND +;THESE VARIABLES ARE STEPPED ALONG TO REFLECT THAT. +RPAOBJ: 0 ;AOBJN POINTER TO WORDS TO BE TRANSFERRED +RPIOCY: 0 ;CYLINDER TO START AT +RPIOHD: 0 ;HEAD TO START AT +RPIOSC: 0 ;SECTOR TO START AT +RPIOOP: 0 ;COMMAND WORD. SLVICWA ALREADY ADDED IN +;UNIT IS IN I + +;HIGH-LEVEL I/O ROUTINE. TRIES TO DO IT ALL AT ONCE, +;IF THAT LOSES TWICE TRIES IT A SECTOR AT A TIME. +;IF HCRASH IS SET, TRY ONLY ONCE. +;SMASHES T, TT. RETURNS T NEGATIVE IF ERROR. +RPIO: PUSH P,A + SETZM SLVIOWD+1 + MOVE T,RPAOBJ + SOS T + MOVEM T,SLVIOWD + PUSHJ P,RPXIO ;TRY IT + JRST RPIO1 + MOVEI T,102 ;WON + JRST RPIO9 + +RPIO1: SETOM T + SKIPE HCRASH + JRST RPIO9 ;GIVE UP IF HCRASH + PUSHJ P,RPRCAL ;RECALIBRATE, THEN + PUSHJ P,RPXIO ;TRY IT AGAIN + JRST RPIO2 + MOVEI T,101 ;WON +RPIO9: SKIPGE T + AOS FERRS + POP P,A + POPJ P, + +;SECTOR AT A TIME MODE +RPIO2: MOVEI T,100 + SKIPL TT,RPAOBJ + JRST RPIO9 ;TRANSFER EXHAUSTED, WON + SOS TT + HRLI TT,-200 + MOVEM TT,SLVIOWD + MOVEI T,10. ;TRY THIS SECTOR 10 TIMES + PUSHJ P,RPXIO + SOJGE T,.-1 + JUMPL T,RPIO9 ;GIVE UP + MOVE T,[200,,200] ;ADVANCE TO NEXT SECTOR + ADDM T,RPAOBJ + AOS T,RPIOSC + CAIGE T,NSECS + JRST RPIO2 + SETZM RPIOSC + AOS T,RPIOHD + CAIGE T,NHEDS + JRST RPIO2 + SKIPL RPAOBJ + JRST RPIO2 + JRST 4,. ;CYLINDER OVERFLOW? + +;LOW-LEVEL IO, JUST DO THE OPERATION SPECIFIED IN THE VARIABLES. +;CLOBBER A,TT. +;SKIP IF SUCCESS. +RPXIO: MOVEI TT,SLVIOWD ;SET UP DF10 COMMAND + HRRZM TT,SLVICWA + SETZM SLVICWA+1 + PUSH P,T + PUSHJ P,SEEK ;MAKE SURE AT DESIRED CYLINDER + JRST POPTJ ;SEEK FAILED + POP P,T + MOVE A,RPIOOP ;SET UP RP10 DATAO + DPB I,[DUNFLD A] + MOVE TT,RPIOCY + DPB TT,[DCYL A] + LSH TT,-8 ;FOR RP03 + DPB TT,[DCYLXB A] + MOVE TT,RPIOHD + DPB TT,[DSURF A] + MOVE TT,RPIOSC + DPB TT,[DSECT A] + CONO DPC,DCLEAR + SKIPN HCRASH ;IF HCRASH, MAY BE MONITORING SOMETHING IN LIGHTS? + DATAO LIGHTS,A + DATAO DPC,A ;ISSUE COMMAND + CONSO DPC,DONE ;AWAIT DONE + JRST .-1 + CONSZ DPC,ALLER ;SKIP-RETURN UNLESS ERROR + POPJ P, + HLRO TT,RPAOBJ ;SEEMS SUCCESSFUL, CHECK THE CHANNEL CONTROL WORD STORED + HRRZ A,RPAOBJ + SUB A,TT ;SUPPOSED END OF TRANSFER + HRRZ TT,SLVICWA+1 + CAIE A,1(TT) +DF10FK: POPJ P, ;CHANNEL TRYING TO FUCK YOU OVER + JRST POPJ1 + +;RECALIBRATE UNIT IN I, SMASHES T,TT +RPRCAL: CONO DPC,DCLEAR + MOVE T,[DEASEC 776] + DPB I,[DUNFLD T] ;LEAVE PROPER UNIT SELECTED FOR GETSTS + DATAO DPC,T ;CLEAR ATTNS + DPB I,[DUNFLD DRST] + DATAO DPC,DRST +RPRCL1: DATAI DPC,TT + TLNN TT,(ONLINE) + POPJ P, ;OFF LINE + TLNE TT,(NSCHDR) + POPJ P, ;NO SUCH DRIVE + TRNN TT,776 + JRST RPRCL1 ;AWAIT ATTENTION + DATAO DPC,T ;GOT ATTENTION, CLEAR IT +RPRCL2: TLNE TT,(ONCYL+SKINC) + POPJ P, ;DONE + DATAI DPC,TT + JRST RPRCL2 ;ON CYLINDER SOMETIMES TAKES A WHILE TO SET + +;SEEK TO CYLINDER IN RPIOCY ON UNIT I, SMASHES T,TT, SKIPS ON SUCCESS. +SEEK: MOVEI TT,10. + MOVEM TT,SEEKC +SEEK1: CONSZ DPC,BUSY + JRST .-1 + DATAO DPC,[DEASEC 776] + MOVSI TT,(DSEEKC) + DPB I,[DUNFLD TT] + MOVE T,RPIOCY + DPB T,[DCYL TT] + LSH T,-8 ;FOR RP03 + DPB T,[DCYLXB TT] + SKIPN HCRASH + DATAO LIGHTS,TT + CONO DPC,DCLEAR + DATAO DPC,TT + MOVE T,[DEASEC 776] + DPB I,[DUNFLD T] ;LEAVE PROPER UNIT SELECTED FOR GETSTS + PUSHJ P,RPRCL1 ;AWAIT COMPLETION + TLNE TT,(ONCYL) ;SUCCEED IF ON CYLINDER + JRST POPJ1 + SOSGE T,SEEKC ;COUNT FAILURES + POPJ P, ;GIVE UP + PUSHJ P,RPRCAL ;RECALIBRATE + JRST SEEK1 ;AND TRY AGAIN +];RP + RH,[ ;RH10 I/O - FALL IN FROM WRITE + +;ENTER WITH: A ADDRESS, J BLOCK NUMBER, I VIRTUAL UNIT +.SEE RHCMD ;VARIABLES CONTROLLING WHAT GOES ON HERE +;INSIDE RW2 TT GENERALLY HAS THE DISK COMMAND AND T HAS THE RETRY COUNT +;ONLY T AND TT CLOBBERED +;ON RETURN T MINUS IF ERROR + + SKIPA TT,[%HMWRT] +READ: MOVEI TT,%HMRED +IFN T300P,[ + CAIL I,T300P + JRST T3IO + SETZM T3IOP +];T300P + MOVEM TT,RHCMD + HRRZ TT,J + CAIL TT,TBLKS + JRST 4,. + IDIVI TT,NBLKSC ;TT:=CYLINDER, T:=BLOCKS INTO CYLINDER + HRLZM TT,RHPGA ;SAVE CYLINDER + MOVE TT,T ;GET BLOCKS INTO CYLINDER + IMULI TT,SECBLK ;SECTORS INTO CYLINDER + IDIVI TT,NSECS ;TT:=HEAD, T:=SECTOR + LSH TT,8 ;FORM ADDRESS WORD + IOR TT,T + HRRM TT,RHPGA ;COMPLETE THE ADDRESS + MOVEI T,-1(A) ;SET UP IOWD TO TRANSFER ONE BLOCK + HRLI T,-2000 + MOVEM T,RHIOW +;ENTER HERE WITH RHCMD, RHIOW, AND RHPGA SET UP. I HAS UNIT#. +RW1: MOVEI T,5 ;INIT LOSAGE COUNT + PUSHJ P,RW2 ;TRY + JRST RW7 ;FAILED +;HERE TO RETURN. T SAYS WHETHER WINNING OR LOSING. +RW5: MOVE A,[%HRDCL,,%HMCEN] ;RETURN TO CENTER-LINE IF NECESSARY + AOSN OFFSTF + PUSHJ P,RHSET + JFCL + SKIPGE T + AOS FERRS + MOVE A,RHIOW ;RESTORE A + MOVEI A,1(A) + POPJ P, + +;HERE IF LOSING. +RW7: SKIPE HCRASH + JRST RWL0 ;SPEED IS OF THE ESSENCE, TRY ONLY ONCE + PUSHJ P,RW2 ;HMM, TRY AGAIN + JRST RWLOSS ;STILL LOSING, COGITATE + JRST RW5 ;WINNING NOW + +RWLOSS: MOVSI A,%HROFS ;ATTACK OFFSET REGISTER + HRR A,OFFSTB(T) ;SET APPROPRIATE OFFSET VALUE + SETOM OFFSTF' ;REMEMBER TO RETURN TO CENTERLINE LATER + PUSHJ P,RHSET + JRST RWL0 ;WHAT?? + MOVE A,[%HRDCL,,%HMOFS] + PUSHJ P,RHSET + JRST RWL0 + MOVEI A,20000. ;WAIT 10 MS OR SO FOR GOOD LUCK + SOJG A,. + PUSHJ P,RW2 ;TRY IT NOW + SOJGE T,RWLOSS ;LOSE, TRY WITH DIFFERENT OFFSET + JUMPGE T,RW5 ;WON, SO TAKE WIN RETURN +RWL0: SETO T, ;COMPLETE LOSS, RETURN NOW + JRST RW5 + +OFFSTB: 260 + 60 + 240 + 40 + 220 + 20 + ;RH10 I/O ROUTINE PROPER +;FIRST STEP IS TO SET UP CHANNEL COMMAND LIST +RW2: MOVE TT,RHIOW ;SET UP ADDRESSES + MOVEM TT,RHTIOW + MOVE TT,RHPGA + MOVEM TT,RHTPGA +;RE-ENTER HERE AFTER ECC ERROR +RW2OVR: PUSH P,B + PUSH P,C + MOVE A,[-6,,SLVIOWD] ;POINTS TO WHERE CCWS WILL BE STORED + HLRO C,RHTIOW ;MINUS NUMBER OF WORDS TO TRANSFER + MOVNS C ;POSITIVE + HRRZ B,RHTIOW ;ADDRESS MINUS ONE +RW2CC1: MOVN TT,C ;WORDS TO TRANSFER IN THIS CCW + CAIL C,40000-200 ;WC IS ONLY A 14-BIT FIELD + MOVNI TT,40000-200 + MOVEM B,(A) ;STORE CA + DPB TT,[$DFWC (A)] ;STORE WC + ADD C,TT ;LESS WORDS TO DO + SUB B,TT ;ADVANCE ADDRESS + AOBJP A,[JRST 4,.] ;ADVANCE CCW PTR, HALT IF TOO BIG! + JUMPG C,RW2CC1 ;NEED MORE WORDS + SETZM (A) ;END CCW LIST + HRRZI A,SLVIOWD ;POINT CHANNEL AT IT + MOVEM A,SLVICWA + SETZM SLVICWA+1 ;INIT FOR CONTROL WORD WRITING + POP P,C + POP P,B + MOVEI A,SLVICWA ;BUILD DATAO CMD + MOVE TT,RHCMD + DPB A,[$HCICWA TT] + TLO TT,%HRCTL ;FILL OUT COMMAND WORD + ;NOW BEFORE GIVING COMMAND CHECK STATUS + CONSZ DSK,%HIBSY ;WAIT FOR DSK CONTROL + JRST .-1 + CONO DSK,%HOCLR ;CLEAR ANY LEFT-OVER ERROR INDICATORS +RW2A: MOVSI A,%HRSTS ;CHECK DRIVE STATUS + PUSHJ P,RHGET + JRST RW3 ;DRIVE VANISHED?? + TRNE A,%HSPIP ;WAIT FOR POSITIONING + JRST RW2A ;(MIGHT BE OFFSETTING HEADS?) + TRNE A,%HSERR ;ANY ERRORS IN DRIVE? + JRST RW6 ;YES, TRY TO RECOVER + TRC A,%HSVV+%HSMOL+%HSRDY ;CHECK FOR ALL READY BITS ON + TRCE A,%HSVV+%HSMOL+%HSRDY + JRST RW3 ;NOT READY?? + HLRZ A,RHTPGA ;SET CYLINDER + TLO A,%HRCYL + PUSHJ P,RHSET + JRST RW3 + HRRZ A,RHTPGA ;SET TRACK-SECTOR + TLO A,%HRADR + PUSHJ P,RHSET + JRST RW3 +KL,[ MOVE A,RHTIOW ;SWEEP THE CACHE + AOS A ;RH ADDRESS OF BUFFER, LH - # WDS + LSH A,-9. + TRZ A,777000 + TLO A,777000 ;A NOW HAS AOBJN PTR TO PAGES +RWSWP3: TRNE TT,10 ;SWEEP ONE PAGE + SWPIO (A) ;IF READING, INVALIDATE + TRNN TT,10 + SWPUO (A) ;IF WRITING, UNLOAD + CONSZ APR,200000 ;WAIT UNTIL SWEEPER WAKES + JRST .-1 + AOBJN A,RWSWP3 + SWPUO 0 ;STORE CHANNEL PROGRAM IN CORE + CONSZ APR,200000 + JRST .-1 +];KL +;DROPS THROUGH + ;DROPS IN +RWGO: MOVE A,TT ;ISSUE I/O COMMAND + PUSHJ P,RHSET + JRST RW3 + CONSO DSK,%HIDONE ;WAIT FOR COMPLETION + JRST .-1 + MOVSI A,%HRSTS ;CHECK DISK STATUS, ERRORS DON'T ALWAYS SHOW UP IN CONI + PUSHJ P,RHGET + JRST RW3 + TRNN A,%HSERR + CONSZ DSK,%HIERR + CAIA + JRST POPJ1 ;NO ERROR, SKIP RETURN FROM RW2 +;FOLLOWING TWO LINES CAUSE ECC NOT TO WORK +; CONSO DSK,%HIEXC +; POPJ P, ;NOT DRIVE EXCEPTION, PROBABLY CORRIGIBLE BY RETRY + TRNN A,%HSERR ;ANYTHING IN ERR REGS? + JRST RW3 ;FOO, WHAT IS GOING ON?? + MOVSI A,%HRER2 ;MAKE SURE NO UNSAFES + PUSHJ P,RHGET + JRST RW3 + JUMPN A,RW3 + MOVSI A,%HRER3 + PUSHJ P,RHGET + JRST RW3 + JUMPN A,RW3 + MOVSI A,%HRER1 ;GET ERROR1 REG + PUSHJ P,RHGET + JRST RW3 + TRNE A,077067 ;GROSS ERROR? + JRST RW3 ;YES, ABORT + TRZE A,100000 ;SEE IF CORRECTABLE DATA ERROR + JUMPE A,RWECC ;YES, GO FIX IT + POPJ P, ;ERROR, BUT RETRY MAY WIN + +RW6: MOVE A,[%HRDCL,,%HMCLR] ;ERROR IN DRIVE, TRY CLEARING + PUSHJ P,RHSET + JRST RW3 + MOVSI A,%HRSTS + PUSHJ P,RHGET + JRST RW3 + TRNN A,%HSERR + JRST RW2A ;WON + ;LOST, FALL INTO RW3 + +RW3: POP P,(P) ;UNCORRECTABLE ERROR, RW FAILS + JRST RWL0 + +;ERROR CORRECTION CODE -- TAKEN FROM MAINDEC-10-DDRPF +; THAT CODE HAD NO HOPE WHATSOEVER OF WORKING. RETAKEN FROM ITS. +; THAT CODE DIDN'T WORK EITHER. TAKEN FROM NEWER ITS. + +RWECC: TRNN TT,10 ;SKIP IF READ + POPJ P, ;RETRY IF WRITE + INSIRP PUSH P,[B W U J K H] + DW1==W ;FIRST WORD IN ERROR + DW2==U ;SECOND WORD IN ERROR + EP1==J ;FIRST WORD OF ERROR PATTERN + EP2==K ;SECOND WORD OF ERROR PATTERN + ADR==H ;ADDRESS OF LOSING WORDS + ;B ;SO CAN DIVIDE A + SKIPN A,SLVICWA+1 ;GET ADDRESS OF LAST WORD TRANSFERRED + JRST 4,.-1 ;CHANNEL SHOULD HAVE STORED CONTROL WORD + SOS ADR,A ;LAST WORD TRANSFERRED (SUPPOSEDLY) + ANDI ADR,-200 ;IN ANY CASE, THIS MAKES ADR -> START OF SECTOR + HRRZ A,RHTIOW ;ADR-1 OF START OF TRANSFER + SUBM ADR,A + SOS B,A ;NUMBER OF WORDS SUCCESSFULLY TRANSFERRED + MOVEM B,RHSUCC ;SAVE + HLRO K,RHTIOW + MOVNS K + CAIL B,0 ;CHECK FOR CHANNEL LYING + CAILE B,-200(K) + JRST RWECC3 ;FRAUD, TRANSFERRED NEGATIVE OR TOO MANY WORDS + MOVSI A,%HRPOS ;GET ERROR POSITION + PUSHJ P,RHGET + JRST RWECC3 + SOJL A,RWECC3 ;WHICH IS OFF BY 1. IF ZERO, LOSE. + IDIVI A,36. ;CONVERT TO WORD AND BIT + ADD ADR,A + MOVS DW1,(ADR) ;FETCH THE TWO LOSING WORDS + MOVS DW2,1(ADR) + MOVSI A,%HRPAT ;GET ERROR PATTERN + PUSHJ P,RHGET + JRST RWECC3 + MOVE EP1,A + SETZ EP2, + ROTC EP1,(B) ;ALIGN IT + XOR DW1,EP1 ;FIX THE ERRONEOUS BITS + XOR DW2,EP2 +RWECCB: ;SET BREAK HERE IF DON'T TRUST... + MOVSM DW1,(ADR) ;PUT CORRECTED DATA BACK + MOVSM DW2,1(ADR) + INSIRP POP P,[H K J U W] + + AOS CERRS ;COUNT NUMBER OF TIMES ECC DONE + MOVEI A,%HMCLR ;CLEAR THE ECC-ERROR CONDITION + PUSHJ P,RHSET + JFCL + MOVEI A,200 ;ALLOW FOR THE SECTOR WE CORRECTED + ADDB A,RHSUCC ;GET BACK NUMBER OF WORDS TRANSFERRED + IDIVI A,200 ;NUMBER OF SECTORS TRANSFERRED INCLUDING CORRECTED ONE + LDB B,[$HASEC RHTPGA] ;UPDATE DISK ADDRESS + ADD A,B + IDIVI A,NSECS + DPB B,[$HASEC RHTPGA] + LDB B,[$HATRK RHTPGA] + ADD A,B + DPB A,[$HATRK RHTPGA] ;NO NEED TO IDIVI A,NHEDS SINCE ALL XFERS WITHIN CYLINDER + MOVE A,RHSUCC ;NOW ADVANCE CCW + HRL A,A + ADDB A,RHTIOW + POP P,B + TLNE A,-1 + JRST RW2OVR ;NOT EXHAUSTED, CONTINUE DISK XFER + JRST POPJ1 ;ECC IN LAST SECTOR OF XFER, XFER COMPLETED SUCCESSFULLY + +RWECC3: INSIRP POP P,[H K J U W B] + JRST RW3 + +;ROUTINES TO ACCESS RH10 CONTROLLER AND DRIVE REGISTERS +;CALL WITH +; I UNIT NUMBER +; A REGISTER NUMBER IN LH +; NON-SKIP RETURN IF RAE ERROR +; SKIP RETURN IF WIN +;CLOBBERS ONLY A + +;SET REGISTER. TAKES DATA TO GO IN REGISTER IN RH OF A +;CLOBBERS A (PROBABLY) + +RHSET: TLOA A,%HRLOD ;TELL HARDWARE IS SET INSTEAD OF GET + ;AND FALL INTO RHGET + +;GET REGISTER. RETURNS 16 BITS RIGHT-JUSTIFIED IN A + +RHGET: TLZ A,%HRLOD + TLO A,(I) ;INSERT PHYS DRV NO + DATAO DSK,A ;TELL RH10 TO FETCH REGISTER + MOVEM A,RHLAST' ;SAVE FOR REBUGGING + MOVEI A,4 ;ENSURE 3 USEC DELAY BEFORE DATAI + SOJG A,. ;TO ALLOW MASSBUS TRANSACTION TO COMPLETE + DATAI DSK,A ;GET REG CONTENTS AND FLAGS + TLNE A,%HDERR ;ERROR? + JRST RHRAE ;YES, GO REPORT + ANDI A,177777 ;MASK TO 16 BITS + AOS (P) ;AND TAKE SUCCESS RETURN + POPJ P, + +RHRAE: MOVSI A,%HRRAE+%HRLOD(I) + DATAO DSK,A ;CLEAR RAE REGISTER IN CONTROLLER + POPJ P, ;AND TAKE NON-SKIP RETURN + +;DISK ROUTINE VARIABLES + +RHCMD: 0 ;%HMRED OR %HMWRT +RHIOW: 0 ;IOWD -NWDS,,ADR-1 FOR TRANSFER +RHTIOW: 0 ;TEMPORARY IOWD FOR CONTINUING FROM ECC +RHPGA: 0 ;DISK ADDRESS CYL,,HED_8+SEC +RHTPGA: 0 ;TEMPORARY DISK ADDRESS FOR CONTINUING FROM ECC +RHSUCC: 0 ;NUMBER OF WORDS SUCCESSFULLY TRANSFERRED BEFORE ECC +];RH + +IFN T300P,[ ;T-300 I/O - FALL IN FROM WRITE + +;ENTER WITH: A ADDRESS, J BLOCK NUMBER, I VIRTUAL UNIT +; TT %HMWRT OR %HMRED +;ONLY T AND TT CLOBBERED +;ON RETURN T MINUS IF ERROR + +T3IO: INSIRP PUSH P,[A B C D] + SETOM T3IOP' + CAIE TT,%HMRED ;GET READ OR WRITE COMMAND + SKIPA D,[%DMWRT] + MOVEI D,%DMRED +T3IO1: HRRZ A,J ;GUBBISH IN LH + IDIVI A,NBLKC1 ;A CYLINDER, B BLOCK WITHIN CYLINDER + MOVEM A,DSCCYL + IMULI B,SECBL1 ;B SECTOR WITHIN CYLINDER + IDIVI B,NSECS1 ;B HEAD, C SECTOR + MOVEM B,DSCHED + MOVEM C,DSCSEC + MOVE B,-3(P) ;ORIGINAL ADDRESS + HRLI B,730000 ;12-BIT BYTES, START WITH FIRST BYTE IN WORD + MOVE C,[-4,,DSCPNT] ;SET UP BYTE POINTERS + MOVEM B,(C) + ADDI B,400 + AOBJN C,.-2 +KL,[ SWPUA ;DUMP EVERYTHING OUT OF CACHE + CONSZ APR,200000 + JRST .-1 +];KL + PUSHJ P,T3CMD ;PERFORM THE OPERATION + JUMPE T,T3IO2 ;RETURN IF SUCCESS + MOVE A,T ;SEE IF ERROR MAY BE RECOVERABLE + TRZ A,%DSECH+%DSIDE+%DSHCE + JUMPN A,T3IO3 ;IF IRRECOVERABLE + TRNE D,%DMRED ;OR IF NOT A READ COMMAND + CAIN D,%DMRED+10 ;OR IF TRIED ALL RECOVERY FEATURES +T3IO3: TLOA T,(SETZ) ;ENSURE T NEGATIVE TO INDICATE ERROR + AOJA D,T3IO1 ;OTHERWISE RETRY USING NEXT ERROR RECOVERY FEATURE +T3IO2: INSIRP POP P,[D C B A] + POPJ P, +];T300P + +SUBTTL MISCELLANEOUS VARIABLES + +KL,SALVPF: JRST 4,. ;COME HERE IF PAGE FAIL IN SALVAGER + +CONSTANTS +VARIABLES + +POPTJ: POP P,T +CPOPJ: POPJ P, + +THBLK: -LTHBLK,,0 +THTPN: 0 ;TAPE #,,REEL # IN THIS DUMP +THDATE: 0 ;TAPE CREATION DATE +THTYPE: 0 ;0=>RANDOM >0 => FULL <0 => INCR +LTHBLK==.-THBLK + +MHBLK: -LMHBLK,,0 ;FILE HEADER BLOCK +MHSNM: 0 ;SYS NAME +MHFN1: 0 ;FN1 +MHFN2: 0 ;FN2 +MHPKN: 0 ;PACK # +MHDATE: 0 ;CREATION DATE +LMHBLK==.-MHBLK +LNKFLG: 0 ;NONZERO => RELOADING LINK +LNKNM1: 0 ;LINK FN1 +LNKNM2: 0 ;LINK FN2 +LNKSNM: 0 ;LINK SNAME +MAGHD: 0 +EOTFLG: 0 +EOFCNT: 0 +EOUF: 0 +SHORTL: 0 +MTRYS: 0 +MAGBFP: 0 +EOFLG: 0 + +FROM: 0 +TOU: 0 + +SBTAB: -1 ;FOR PATCHING + -1 + -1 + -1 +MFDBK: MFDBLK ;SPECIAL RESERVED BLKS + ;TUT USED TO BE HERE, BUT NO LONGER +LSBTAB==.-SBTAB + +;THIS IS AN ARRAY INDEXED BY UNIT GIVING THE NUMBER +;OF BLOCKS IN THE TUT ON THAT UNIT. +;THESE BLOCKS ARE ALWAYS RIGHT BEFORE THE MFD. +NTBL: +IFE T300P, REPEAT NUNITS, NTUTBL +IFN T300P,[ + REPEAT T300P, NTUTBL + REPEAT NUNITS-T300P, NTUTB1 +];T300P + +RXWDS: BLOCK 4 ;THE EXTRA WORDS + + 0 ;FOR BLT +WXWDS: BLOCK 4 + +NOLPT: 0 ;-1 FOR NO LPT +LPBUST: -1 ;-1 LPT IS BUSTED DON'T KEEP ASKING +PUNCH: 0 ;SET TO -1 WITH DDT IF COPY TTY OUTPUT TO PUNCH +HCRASH: 0 ;SET TO -1 WITH DDT IF EMERGENCY DUP AFTER HEAD CRASH + ;SACRAFICE EVERYTHING FOR SPEED SINCE PACK IS BEING SCRAPED BY HEADS +NUDS: NTS,[NUDSL]+0 ;NUMBER OF USER DIRECTORY BLOCKS +ADRSET: 0 ;ADDRESS SET +FMBLK: 0 ;FROM BLOCK +TOBLK: 0 ;TO BLOCK +LFRMSW: 0 +SEEKC: 0 +SHARED: 0 ;NUMBER OF SHARED BLOCKS +GOGOX: 0 ;-1 FOR AUTOMATIC MODE +NOQUES: 0 ;-1 TO ASK NO QUESTIONS (ONLY EFFECTIVE IN GOGOX MODE) +MDSK: 0 ;DISK TO GET MFD FROM +UDSK: 0 ;DSK TO GET UFD'S FROM +CKFLSW: 0 ;CHECK FILES FOR CLOBBERED BLOCKS +MFDWRT: 0 ;MFD CHANGED +TUTDFR: 0 ;FLAG TO SHOW TUT CHANGED +TTDFPS: 0 ;COUNT FROBS PER LINE WHEN PRINTING TUT +LFILES: 0 ;NUMBER OF FILES IN DIRECTORY +USRNAM: 0 ;M.F.D. USR NAME +UFDLOS: 0 ;SOME GARBAGE IN UFD +UFDSEE: 0 ; -1 IF A STRANGE UFD, PRINT WHOLE THING +FILEPK: 0 ; PACK FILE IS ON +LAST: 0 ; LAST FILE IN UFD +DBLK: 0 ;STORAGE FOR DIRECTORY NUMBER +FILEER: 0 ;ERROR IN FILE +BADFIL: 0 ; BLOCKS IN FILE WITH RETRIEVAL ERRORS +XWDSEE: 0 ; -1 IF HAVENT TYPED EXTRA WORDS YET +LASTQ: 0 ;STORAGE FOR Q +NOTUT: 0 ;TUT NOT ACTIVE FOR THIS FILE +LSTBLK: 0 ;LAST BLOCK STORAGE +BLK: 0 ; LAST BLOCK READ OR WRITTEN FROM +CKFIX: 0 ; -1 IF AUTO FIX RETRIEVAL POINTERS +UNIT: 0 ; UNIT " +FUNIT: 0 ; UNIT FILE IS ON, -1 IF PACK NOT MOUNTED +FERRS: 0 ;TRANSFER ERRORS +CERRS: 0 ;ERRORS CORRECTED BY ECC LOGIC +DUPRER: 0 ;DUP READ ERROR COUNT +DUPWER: 0 ;DUP WRITE ERROR COUNT +UFDTA: 0 +GARBF: 0 ;GARBAGE IN FREE AREA +EXGARB: 0 ;EXTRA GARBAGE IN UFD +MARKF: 0 ;MARKING PACK + +PDL: BLOCK 200 +QBTBLI: 440600,, +QBTBL: 360600,, + 300600,, + 220600,, + 140600,, + 60600,, + 600,, + +QTRAN: +DC,[ 0 ;RH IS PHYSICAL DRIVE + 1 ;4.9 BIT MEANS SECOND HALF + 2 ;(NO LONGER DOES ANYTHING, NOW THAT MEMOWRECKS HAVE BEEN + 3 ; FLUSHED, BUT KEEP AROUND IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +];DC +.ELSE REPEAT NDRIVE, .RPCNT ;OTHERWISE NOTHING SPECIAL + +IFN .-QTRAN-NUNITS,.ERR BARF AT QTRAN!! + +QTTBLI: REPEAT 36./TUTBYT+1, 440000+TUTBYT_6-TUTBYT_12.*.RPCNT,, +QTTBL=QTTBLI+1 + +TS, NQS: 0 ;SYSTEMS NUMBER OF DRIVES +TS, SQACT: 0 ;LOCATION OF QACT IN SYSTEM +TS, SALVRT: 0 ;DUMMY + + NBLKS-1 ;SNBLKS-1 +SNBLKS: NBLKS ;SYSTEM NBLKS (INIT'ED IN TS) +DRIVE: REPEAT NDRIVE,-1 ;-1 IF DRIVE ON LINE +QACT: REPEAT NUNITS,-1 ;-1 IF UNIT ACTIVE +QPKN: REPEAT NUNITS,-1 ;PACK NUMBER ACCORDING TO TUT +PKNUM: BLOCK NUNITS ;PACK NUMBER ACCORDING TO HARDWARE + +RPKID: 0 + +IRP A,,[OTUT,NTUT] +Q!A!O: REPEAT NUNITS,CONC A,\.RPCNT, +TERMIN + +PAT: +PATCH: BLOCK 100 + +LOC <.+1777>&776000 +CYLBUF: +OUSRD: BLOCK 2000 +NUSRD: BLOCK 2000 +FDBUF: BLOCK 2000 +MFD: BLOCK 2000 +MAGBUF: BLOCK 2000 +IRPS A,,OTUT NTUT +REPEAT NUNITS,CONC A,\.RPCNT,: BLOCK 2000*MXTUTB +TERMIN +D0==OTUT0 +D1==OTUT1 +TUT=NTUT0 +RH, CYLSIZ==200*NHEDS*NSECS +RP, CYLSIZ==NBLKSC*2000 +DC, CYLSIZ==NBLKSC*2004 +NTS, IFL .-CYLBUF-CYLSIZ,LOC CYLBUF+CYLSIZ +THEEND: +CONSTANTS +VARIABLES +IFN .-THEEND, .ERR CRUFT AFTER THEEND + +INFORM HIGHEST USED = ,\THEEND + +IFG THEEND-400000, .ERR TOO MOBY (MUST FIT IN 128K TO AVOID HOLE IF SOME MEM DOWN) +;This error check doesn't really matter for MC much, since memory has +;to be switched out in 128K increments, which means that the system +;can't work with any holes in the low 256K. + +IF2, NTS, KL, PAG=- + +TS, END DDT ;ALWAYS STARTED BY G +NTS,END ;DON'T CLOBBER I.T.S. START ADDR WHEN LOADED TOGETHER diff --git a/src/system/sysjob.117 b/src/system/sysjob.117 new file mode 100755 index 00000000..76e0b705 --- /dev/null +++ b/src/system/sysjob.117 @@ -0,0 +1,2796 @@ +; -*-MIDAS-*- + +SUBTTL DEMON JOB INTERFACE ROUTINES + ;GIVE STUFF TO DEMON JOB RUNNING IN USER MODE, WHICH THEN OUTPUTS + ;STUFF IN ITS OWN FORMAT TO THE DISK + ;COMMUNICATION IS VIA DMNBUF (BUFFER) AND POINTERS, + ;DEMON JOB FINDS IT BY LOOKING UP SYSTEM SYMS + + ;USAGE: + ;ROUTINES MUST BE CALLED WITH CLK OFF OR IN PROGRESS + ;FIRST CALL DMNP TO SET UP D AS "PDL POINTER" INTO DMNBF + ;DMNPSH ADR ;PUSH ADR INTO DMNBF (ASSEMBLES INTO A PUSH) + ;FIRST WORD PUSHED SHOULD HAVE ENTRY TYPE DESCRIPTOR IN HIGH SIX BITS + + ;ENTRY TYPE DESCRIPTORS: +DMNELI==10000 ;LOGIN (DMNPLI) +DMNELO==20000 ;LOGOUT (DMNPLO) + ;^ ADD MORE AS NEEDED, NEED NOT BE SYMBOLIC BUT PLEASE COMMENT THEM HERE FOR XREF + + ;DMNRS ;NORMALLIZE POINTER (DUE TO STANDARD LENGTH ENTRY IN TABLE) + ;ASSEMBLES INTO ONE STORAGE WORD + ;THEN CALL (PUSHJ) DMNRT WHICH STORES BACK D + ;ALL DMNPSH'S SHOULD BE ASSEMBLED BEFORE DMNRT; + ;ALL ROUTINES SHOULD BE BETWEEN THIS PAGE AND DMNBUF + +;DMNSZ (# ENTRIES IN DMNBF) DEFINED EARLY IN SYSTEM ENGLISH SO CAN BE CHANGED EASILY + +DMNFMT==2 ;ASCENDING FORMAT NUMBER, SHOULD BE INCREMENTED EACH TIME + ;A CHANGE IS MADE REQUIRING CHANGE IN CODING EITHER OF DEMON JOB + ;OR OF PROGRAMS READING ITS OUTPUT +;DMNFNT 1 -> 2 9/71 SWAPIN RQ INCLUDED W/LOGOUT + +DMNBAC==0 ;DMNPSH COUNTER, AFTER FIRST TIME GETS RE-INITIALIZED TO DMNBLM + +DEFINE DMNPSH ADR + DMNBAC==DMNBAC+1 + PUSH D,ADR +TERMIN + +IF1,DMNBEL==0 ;BECOMES LENGTH PER ENTRY IN DMNBF + +DEFINE DMNRS + ADDI D,DMNBEL-DMNBAC +IF1,IFG DMNBAC-DMNBEL,DMNBEL==DMNBAC +DMNBAC==DMNBLM +TERMIN + + ;PUSHJ P,DMNP ;SET UP D FOR DMNPSH'S INTO DMNBF + +DMNP: MOVE D,DMNBFP ;GET POINTER + CAIL D,DMNBFE-1 ;AT END OF BUFFER? + MOVEI D,DMNBF-1 ;YES, RE-INITIALIZE + AOS DMNBC ;INDICATE ENTRY ABOUT TO BE FILLED, SO DEMON KNOWS IF IT LOST +DMNP0: ;DMNP0 MAY BE CALLED IN USER MODE FROM DEMON JOB + DMNPSH TIME ;FIRST WORD IN BUFFER ALWAYS TIME OF ENTRY + ;^ MAYBE ADD MORE STANDARD PUSHES HERE + POPJ P, + +DMNBLM==DMNBAC ;NUMBER OF INITIAL WORDS PUSHED + + ;PUSHJ P,DMNRT (BUT USUALLY JRST DMNRT FOR RETURN) + ;DMNBF ENTRY COMPLETED, STORE BACK POINTERS + +DMNRT: TLZ D,-1 ;CLEAR OUT LEFT HALF OF POINTER + CAIL D,DMNBFE ;AFTER END OF BUFFER? + JRST 4,.+1 ;DMNBF POINTER INCREMENTED INCORRECTLY SOMEWHERE ALONG THE LINE + ;PROBABLY PROGRAMMER FORGOT TO DO DMNRS; CODING AFTER DMNBF MIGHT BE CLOBBERED + AOS DMNBD ;ENTRY COMPLETE, GIVE IT TO DEMON JOB + MOVEM D,DMNBFP + POPJ P, + + ;NOW FOR INDIVIDUAL ROUTINES + + ;LOGIN + +DMNPLI: PUSHJ P,DMNP ;SET UP + HRLI U,DMNELI ;INDICATE LOGIN + ;PUT FOLLOWING INTO DMNBF: + DMNPSH U ;INDEX OF USER BEING LOGGED IN + TLZ U,-1 + DMNPSH UNAME(U) ;UNAME + DMNPSH JNAME(U) ;JNAME + DMNPSH TRMNAM(U) ;TERMINAL NAME + DMNPSH XUNAME(U) + DMNRS ;THAT'S ALL + JRST DMNRT + + ;LOGOUT + +DMNPLO: PUSHJ P,DMNP ;SET UP D + PUSHJ P,LOGUSE ;GET TREE'S USAGE IN T AND TT + HRLI U,DMNELO ;INDICATE LOGOUT + ;PUT FOLLOWING IN DMNBF FOR DEMON JOB TO DUMP OUT ON DISK: + DMNPSH U ;INDEX OF USER BEING LOGGED OUT + TLZ U,-1 + DMNPSH UNAME(U) ;UNAME OF USER + DMNPSH JNAME(U) ;JNAME + DMNPSH TT ;TIME USED, IN 4.069 USEC UNITS + DMNPSH T ;# SWAPIN REQUESTS (THESE VALID SINCE LOGUSE ALREADY CALLED) + ;^ ADD MORE HERE + ADDM TT,LOUTIM ;COUNT UP TOTAL TIME USED BY ALL LOSERS + DMNRS + JRST DMNRT + +DMNPL0==CPOPJ ;DMNPL0 MAY BE CALLED FROM DEMON JOB IN USER MODE + ;IT IS NO LONGER POSSIBLE TO MAKE THIS WORK RIGHT, + ;SO WE JUST RETURN. PFTHMG DRAGON SHOULD BE FIXED. + +EBLK + ;DEMON VARIABLES, MUST FOLLOW CODING + ;USE CARE IN REDEFINING SYMBOLS ON THIS PAGE; DEMON JOB RUNNING IN USER MODE + ;LOOKS AT SOME OF THEM, EXCEPT AS INDICATED + +DMNBF: BLOCK DMNBEL*DMNSZ ;BUFFER +DMNBFE:: + +DMNBC: 0 ;ENTRY COUNT, INCREMENTED JUST BEFORE ENTRY ADDED TO DMNBF (USED BY DEMON) +DMNBD: 0 ;ENTRY COUNT, INCREMENTED JUST AFTER " " " +DMNBFP: DMNBF-1 ;POINTER INTO BUFFER, HAS ADR OF LAST WORD WRITTEN (NOT USED BY DEMON) +VSCLAU: 0 .SEE VSCLA1 ;LAST JOB TREE ACCOUNTING UPDATE DONE FOR + ;NO MORE CODING ALLOWED AFTER THIS POINT + +DEFINE DMNPSH A +INFORM DMNPSH AT .,\. +TERMIN + +DEFINE DMNRS +INFORM DMNRS AT .,\. +TERMIN + +BBLK + +SUBTTL "SYSTEM" JOBS + +IFN TPLP,[ +TPLI==11 ;PSEUDO LPT IN +PRTO==12 ;REAL LPT OUT +] +IFN DEMON,TPLI==11 ;FOR DEMON HACKER +IFN DEMON,TEMPC==16 ;FOR TESTING WHETHER DEMON FILE EXISTS. +STYOC==17 ;OUTPUT " + +;CODE FROM ICLR TO SCOR EXECUTED ONLY ONCE (SEE BEG) +ICLR: MOVE A,[GO,,GO+1] ;PICK UP BLT POINTER (COPY EXCH WORD INTO NEXT) + SETZM GO ;CLEAR FIRST WORD + BLT A,IEND ;CLEAR OUT INITIALIZING CODE (IN AREA TO BE USER VAR BLOCKS) + SKIPL CORRQ ;SKIP IF CORE RQ FOR SYSTEM'S SPACE PROCESSED + PUSHJ P,UFLS ;WAIT AS NECESSARY + PUSHJ P,SYSCOP ;"OPEN" SYSTEM CONSOLE CHANNEL +IFN CCLKP,[ + JRST .+3 ;JFCL FOR CHESS CLK MODE + PUSHJ P,CLQAD1 + CCLKB +];CCLKP +IFN IMPP,[ + MOVE A,TIME + MOVEM A,LNETIM + PUSHJ P,IMPINI +];IMPP + MOVEI A,IINTIC + MOVEM A,IINCNT +SCOR: MOVE P,SYSPDP + MOVE U,USER + CONO PI,CLKON + MOVE A,TIME + ADDI A,30.*60.*5 ;5 MINUTES BEFORE SHUTDOWN? + SKIPLE SHUTDN + CAMG A,SHUTDN + JRST .+3 + SKIPN SUSRS + JRST SYSOUT ;JUMP IF SYS DYING & NO ONE LOGGED IN + MOVE T,[.HANG] + MOVEM T,FORTY ;TELL PEEK WHAT OUR UFLS REALLY IS. + MOVE T,TIME + MOVEM T,SYSITM + SKIPN SUPCOR ;SKIP IF ANY BITS ON IN SUPCOR + PUSHJ P,UFLS ;HANG TILL A BIT ON +;SYS JOB IS HUNG IF SYSITM IS 30 SEC OLD AND PC ISN'T SCOR1. +SCOR1: MOVSI A,(SETZ) + MOVEI B,0 +SYSDP1: TDNE A,SUPCOR + JRST SYSDP2 +SYSDP3: LSH A,-1 + JUMPE A,SCOR + AOJA B,SYSDP1 + +SYSDP2: SKIPGE SYSDTB(B) ;SKIP UNLESS 4.9 BIT OF ENTRY ON + ANDCAM A,SUPCOR ;4.9 ON, CLEAR SUPCOR BIT + LDB C,[370200,,SYSDTB(B)] + TRNE C,2 ;IF ROUTINE IS GOING TO USE TTY, + PUSHJ P,WARMTTY ;THEN WARM IT UP FOR IT + TRNE C,1 + PUSHJ P,DINGTTY + LDB T,[420100,,SYSDTB(B)] ;GET 4.8 BIT + JUMPE T,@SYSDTB(B) ;IF 4.8 BIT = 0, JUMP TO ROUTINE + PUSH P,A ;4.8 .NE. 0, SAVE A + PUSH P,B ;SAVE B + PUSHJ P,@SYSDTB(B) ;CALL ROUTINE + POP P,B ;RESTORE B + POP P,A ;RESTORE A + LDB T,[410100,,SYSDTB(B)] ;GET 4.7 BIT + JUMPE T,SYSDP3 ;IF ZERO RETURN TO LOOP + ANDCAM A,SUPCOR ;NON-ZERO, CLEAR SUPCOR BIT + JRST SYSDP3 ;LOOP + +SUBTTL SUPCOR DISPATCH TABLE + +;DISPATCH TABLE FOR BITS IN SUPCOR +;4.9 = 1 TO CLEAR SUPCOR BIT BEFORE DISPATCHING +;4.8 = 0, JRST TO ROUTINE ; = 1, PUSHJ +;4.7 = 1 TO CLEAR SUPCOR BIT AFTER (ONLY USEFUL IF PUSHJ) +;4.6 WARM UP TELETYPE BEFORE CALL +;4.5 DING BEFORE CALL + +SCL==1,,525252 ;BIT TYPEOUT MASK FOR SUPCOR +SCR==525252 ; .. + +SYSDTB: +SCLEX==400000 ? 300000,,SYSEX ;INCREASE USER-VAR BLOCK SPACE. +SCLSHD==200000 ? 340000,,SYSSHD ;HANDLE .SHUTDN - PRINT "GOING DOWN" MESSAGES. +SCLOUT==100000 ? 400000,,SYSOUT ;TIME FOR SYSTEM TO GO DOWN. +IFE KS10P,[ 660000,,SYSCK5 ;CHECK FOR DEVICES GIVING SPURIOUS INTERRUPTS. + SCLCK5==040000] +IFN KS10P, 400000,,SYSDP3 +SCLDAT==020000 ? 600000,,DATIME ;CONTINUE TRYING TO DETERMINE DATE AND TIME. +SCLPAR==010000 ? 360000,,PARTYP ;PRINT "PARITY ERROR..." +SCLSET==004000 ? 340000,,SYSSET ;DEPOSIT IN SYSTEM (.SETLOC). +SCLIMP==002000 ? 600000,,SYSIMU ;PRINT "NETWORK UP ..." +SCLWRT==001000 ? 340000,,SYSWRT ;PRINT WRITING-ON-SYS: MESSAGE. +SCLLGI==000400 ? 340000,,SYSLGI ;PRINT LOGIN MESSAGE. +SCLDEC==000200 ? 300000,,SYSDEC ;DECREASE USER-VAR SPACE. +SCLVSK==000100 ? 600000,,VSCLK ;VERY SLOW (2 MINUTE) CLOCK. +SCLGUN==000040 ? 600000,,SYSGUN ;FLUSH TREES THAT ARE TRYING TO LOG OUT. +SCLNET==000020 ? 460000,,SYSNET ;BRING NCP DOWN AND UP. +IFN DEMON,[ 600000,,DEMCHK ;RUN ANY DEMONS WHICH NEED IT. + SCLDMN==000010] +IFE DEMON, 400000,,SYSDP3 +SCLNXM==000004 ? 360000,,NXMTYP ;PRINT "NON-EX MEM ERROR ..." +IFE KA10P,[ +SCLBPF==000002 ? 360000,,BPFTYP ;BAD PAGE FAIL +].ELSE 400000,,SYSDP3 +SCLIDK==000001 ? 600000,,ISYS ;DISK IS INITIALIZED +SCRTPP==400000 ? 600000,,TPLPRT ;TRANSFER DATA TO LPT (FROM TPL) +SCRTPC==200000 ? 600000,,VSCL6 ;SEE IF ANY FILES HAVE BEEN SPOOLED. + 400000,,SYSDP3 +SCRHNG==040000 ? 600000,,SYSDIL ;DIALUP LINE CONNECT OR DISCONNECT +SCRDET==020000 ? 600000,,SYSDT ;DETACH TOP-LEVEL JOBS WITH INTERRUPTS. +SCRCFM==010000 ? 600000,,SYSCFM ;PRINT CONSOLE FREE MSGS +SCRMSG==004000 ? 640000,,SYSMPR ;PRINT RANDOM SYSTEM MESSAG + REPEAT 5,400000,,SYSDP3 ;CAN BE SET BY USER (.SUPSET) +IFN N11TYS,[ 600000,,VWHO ;UPDATE WHO LINES (40) + SCRWHO==000040] +.ELSE 400000,,SYSDP3 +IFN N11TYS,[ 640000,,SYS11D ;TV 11 GONE DOWN (20) + SCR11D==000020] +.ELSE 400000,,SYSDP3 +IFN N11TYS,[ 640000,,SYS11U ;TV 11 COME UP, INIT IT (10) + SCR11U==000010] +.ELSE 400000,,SYSDP3 +IFE DEMON, 400000,,SYSDP3 ;(4) +IFN DEMON,[ 600000,,DMNOFF + SCRDMF==000004] +SCRTPF==000002 ? 300000,,TPLOFF ;BLOCK TPL. +SCRCKS==000001 ? 600000,,SYSCKS ;PERFORM CHECKSUMMING + +IFN .-SYSDTB-36.,.ERR SYS JOB DISPATCH + +SUBTTL DM DAEMON OVERSEER + +IFN DEMON,[ +DEMCHK: PUSHJ P,SYSDEX ;HANDLE REQUESTS TO KNOW WHETHER A FILE + ;EXISTS TO BE SIGNALLED AS A DEMON. + PUSHJ P,LSWTL ;SYSTEM JOB SIEZES DEMON TABLE SWITCH WITH UTCOFF + 400000,,DEMSW + MOVE B,DMLSEX + CAMN B,[-DMLNG,,0] ;IF AT BEGINNING OF TABLE SET FLAG + TDZA D,D + SETOM D +DMSCN9: SKIPE TT,DMTTBL(B) + SKIPE DMTTBL+1(B) ;ONLY PAY ATTENTION IF NOT DOWN + JRST DMSCN1 ;AND GUY THERE + MOVE T,DMTTBL+2(B) + HRRE C,T + TLNE T,-1 + JRST DMSCN3 + JUMPLE C,DMSC10 +DMSCN0: SKIPG DMNFLG + JRST DMSC11 ;IF FLAG SET CAN'T LOAD EM + CAME TT,[SIXBIT /UNSPOO/] + JRST DMSCN4 ;DON'T BOTHER WITH TPL STUFF, IF NOT TPL + SKIPGE TPLFLG + JRST DMSC10 ;REMOVE FROM WORLD + JRST DMSCN4 + +DMSCN4: HLRM T,DMTTBL+3(B) ;SET UP IMPLICIT REQUEST + CONO PI,UTCON ;ATTEMPT LOAD HERE + MOVE T,DMTTBL(B) + MOVEM T,DMOBLK+2 ;CHECK TO SEE IF FILE EXITS + .IOPUSH TPLI, + .OPEN TPLI,DMOBLK ;DON'T WORRY CAN'T PCLSR + JRST DMSCN5 ;OPEN FAILURE + .IOPOP TPLI, ;GET BACK STUFF + HRROI T,DMTTBL(B) + PUSHJ P,NUJBST ;TRY TO LOAD + JRST DMSCN6 ;COME BACK LATER, NO ENTRY FOR THIS GUY. +DMSCN8: ADD B,[DMTLL,,DMTLL] + SKIPL B + MOVSI B,-DMLNG + MOVEM B,DMLSEX ;FIX UP TABLE +DMSCN7: MOVSI B,SCLDMN + IORM B,SUPCOP ;IF MORE REQUESTS, RUN AGAIN IN 1 SECOND. + SOSLE REQCNT ;NO MORE REQUESTS => + JRST LSWPOP + SETZM REQCNT + ANDCAM B,SUPCOP ;DON'T RUN AGAIN. + ANDCAM B,SUPCOR ;THEN CLEAR OUT SUPCOR BIT + JRST LSWPOP + + +DMSCN5: .IOPOP TPLI, ;FILE DOESN'T EXIST + CONO PI,UTCOFF +DMSC10: PUSHJ P,DEMMRV ;REMOVE DEAMON + JRST DMSCN8 ;AND REQUEST + +DMSCN3: JUMPG C,DMSCN0 ;LOAD + JRST DMSCN1 + +DMSCN2: CONO PI,UTCON ;CONTINUE AROUND LOOP + ADD B,[DMTLL,,DMTLL] +DMSCN6: MOVEM B,DMLSEX + JRST LSWPOP ;COME BACK LATTER WITHOUT FLUSHING REQ + +DMSCN1: ADD B,[DMTLL,,DMTLL] ;ADD ON VAL + JUMPL B,DMSCN9 ;CONTINUE AROUND LOOP + MOVSI B,-DMLNG + MOVEM B,DMLSEX + JUMPE D,UTOLKJ +DMSC11: SETZM REQCNT ;IF RAN THROUGH WHOLE TABLE WITHOUT ANY PROCESS + CONO PI,UTCON + JRST DMSCN7 ;FLUSH ALL REQUESTS AND RETURN + +DMNOFF: MOVNS TT,DMNFLG + JUMPLE TT,DMNOF1 ;DEAMONS OFF + PUSHJ P,LSWTL + DEMSW +DMNOF3: SKIPE DMTTBL(B) + SKIPE DMTTBL+1(B) + JRST DMNOF2 + AOS REQCNT +DMNOF2: ADD B,[DMTLL,,DMTLL] + JUMPL B,DMNOF3 + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST LSWPOP + +DMNOF1: MOVSI B,SCLDMN + ANDCAM B,SUPCOR + SETZM REQCNT ;ZERO COUNT + POPJ P, + +;CALL HERE TO HANDLE ALL JOBS THAT ARE WAITING IN .DEMSIG TO +;BE TOLD WHETHER A PURPORTED DEMON REALLY EXISTS. GIVE THEM +;THEIR ANSWERS AND START THEM UP AGAIN. +SYSDEX: SETZ A, + MOVEI C,'SYS + MOVE D,['ATSIGN] +SYSDE1: CONO PI,CLKOFF + SKIPN SRN3(A) ;THIS JOB'S ALREADY BEEN SERVICED?^ + SKIPN UNAME(A) ;OR DOESN'T REALLY EXIST? + JRST SYSDE3 + MOVE B,UPC(A) ;IS IT WAITING FOR SERVICE FROM US? + XORI B,ADEMS1 ;MUST BE IN EXEC MODE AT THE RIGHT PLACE. + TDNE B,[%PCUSR,,-1] + JRST SYSDE3 + MOVE E,AC0S+A(A) ;GET THE FN2 IT WANTS TO CHECK. + CONO PI,CLKON + SETZ T, ;T GETS 0 IFF FILE CAN BE OPENED. + .OPEN TEMPC,C + CAIA + JRST SYSDE2 + LDB T,[220600,,IOCHST+TEMPC] + SKIPN T + MOVEI T,%ENSFL +SYSDE2: .CLOSE TEMPC, + CONO PI,CLKOFF + SKIPN UNAME(A) ;SEE IF JOB IS STILL WAITING FOR SERVICE + JRST SYSDE3 ;SO IT ISN'T CLOBBERED IF IT GOT AN + MOVE B,UPC(A) ;INTERRUPT AND IS DOING SOMETHING ELSE. + XORI B,ADEMS1 + TDNN B,[%PCUSR,,-1] + CAME E,AC0S+A(A) + JRST SYSDE3 + MOVEM T,AC0S+T(A) ;GIVE THE JOB ITS ANSWER IN T, AND + SETOM SRN3(A) ;TELL THE JOB IT HAS BEEN SERVED. +SYSDE3: CONO PI,CLKON + ADDI A,LUBLK + CAMGE A,USRHI + JRST SYSDE1 + POPJ P, +];DEMON + +SUBTTL VERY SLOW CLOCK + +;SUBROUTINES CALLED BY THE VERY SLOW CLOCK. + +;CHECK FOR DEMON REQUESTS WHOSE TIME HAS COME. +IFN DEMON,[ +VSCLDM: PUSHJ P,LSWTL + DEMSW + MOVSI B,-DMLNG +VSCLD2: SKIPG DMTTBL+3(B) ;IF SPECIFIC ENTRY IS < = O, IGNORE + JRST VSCLD1 + SOSE DMTTBL+3(B) + JRST VSCLD1 + HLRZ T,DMTTBL+2(B) ;SIGNAL DEAMON + MOVEM T,DMTTBL+3(B) + MOVE A,DMTTBL(B) + PUSHJ P,DEMSIG ;SIGNAL REQUEST FOR THIS GUY + BUG ;ENTRY IN TABLE NOT FOUND EVEN THOUGH NON ZERO TIME +VSCLD1: ADD B,[DMTLL,,DMTLL] + JUMPL B,VSCLD2 + JRST LSWPOP +] + +;CHECK FOR CLOBBERED TEN-11 INTERFACE CONTROL PAGE WORDS, +;AND RESET THEM TO THEIR CORRECT SETTINGS. +IFN TEN11P,[ +T11CK: SKIPE TEN11F + POPJ P, + MOVSI I,-256. +T11CKL: MOVE A,T11MP(I) + CAMN A,[-1] + MOVEI A,0 ;HARDWARE SHOULD BE 0 ON CONFLICT PAGE + TLZ A,174000 ;USAGE COUNT + MOVE B,400000+T11CP*2000(I) + CAME A,B + JRST T11ERR +T11CL1: AOBJN I,T11CKL + POPJ P, + +T11ERR: AOS T11ERC + MOVEM A,400000+T11CP*2000(I) + MOVEM A,T11CCN + MOVEM B,T11WCN + MOVEM I,T11PG + JRST T11CL1 +] + +;VERY SLOW CLOCK (EVERY 2 MIN). SIGNALLED BY SCLVSK, SET BY A CLOCK-QUEUE ENTRY. +;CALLS THE ULTRA-SLOW CLOCK (EVERY 2 HOURS) WHEN IT'S TIME. + +VSCLK:;JSP E,CHECK ;CHECK FOR CLOBBERED DEVICES (WOULD BE NICE, BUT BUGS...) +IFN DEMON,PUSHJ P,VSCLDM ;DEAMON SLOW CLOCK BREAK ROUTINE +IFN TEN11P,PUSHJ P,T11CK + MOVE U,VSCLAU ;ACCOUNTING UPDATE, FIND A JOB TREE +VSCLA1: ADDI U,LUBLK + CAML U,USRHI + MOVEI U,0 + SKIPE UNAME(U) + SKIPL SUPPRO(U) + JRST VSCLA1 + HRLO TT,UNAME(U) + AOJE TT,VSCLA1 ;DON'T IF NOT LOGGED IN YET + MOVEM U,VSCLAU + CONO PI,CLKOFF + PUSHJ P,LOGUPD + PUSHJ P,DMNPLI + CONO PI,CLKON + MOVE U,USER + SKIPLE CTLCNT ;Time to print date on console log? + JRST VSCLA2 ; No. + PUSHJ P,GLPDTM ;Yes - get localized pdtime. + JRST VSCLA2 ; Can't print time if we don't know it. + PUSHJ P,WARMTTY ;Warm up tty, newline. + PUSHJ P,DATIM6 ;Print what time it is now. + MOVEI TT,CTLMAX ;Restart countdown of lines printed. + MOVEM TT,CTLCNT +VSCLA2: PUSHJ P,VSCOLD ;CHECK FOR OLD DETACHED TREES TO BE KILLED + PUSHJ P,TTTMNT ;TURN OFF MOTORS OF IDLE TERMINETS. +VSCL7: SETOM UFDFLF ;CAUSE CORE JOB TO TRY TO FLUSH 2311 UFDS + AOS NCORRQ + MOVSI I,-NCLCH ;LOOK FOR UNOPEND CORE LINK BUFFERS THAT HAVE BEEN + PUSHJ P,SWTL ;AROUND FOR MORE THAN 2 MINUTES + CLOSW +VSCLCL: SKIPE CLSYN(I) ;SKIP IF VARS UNUSED + SKIPL A,CLUSR(I) + JRST VSCLC2 + AOJN A,VSCLC2 ;JUMP IF OPEN + MOVE TT,CLRAC(I) + TLOE TT,200000 + JRST VSCLCR ;BIT ALREADY ON, BUFFER OLD + MOVEM TT,CLRAC(I) +VSCLC2: AOBJN I,VSCLCL ;LOOP FOR ALL SETS OF VARIABLES + PUSHJ P,LSWPOP ;RELEASE SWITCH + + MOVE A,UTTBF ;IF MANY 200-WORD BUFFERS ARE FREE, + CAIGE A,8 + JRST .+3 + SETOM UTBFLF ;HAVE THE CORE JOB FLUSH THEM + AOS NCORRQ + +IFN IMPP,[ + SKIPGE IMPUP ;SKIP IF IMP UP, OR PERMANENTLY DOWN + PUSHJ P,SYSIMU ;TRY TO BRING IT UP +];IMPP +IFN TPLP,PUSHJ P,VSCL6 ;MAYBE START PRINTING FROM .LPTR. +IFN NLPTP,[ + SKIPL NLUSR ;IF LPT ISN'T IN USE, + JRST VSCNL1 + AOS TT,NLFREE ;KEEP TRACK OF HOW LONG THAT'S BEEN SO. + SOJN TT,VSCNL1 ;IF TRUE FOR >=2 VSCLK INTREVALS (4 MIN) + CONO NLPT,1000 ;TURN LPT MOTOR OFF: 1ST PUT LPT IN IMAGE MODE + DATAO NLPT,[.BYTE 7 ? 24 ? 177 ? 177 ? 177 ? 177] ;THEN TURN OFF. +VSCNL1:] + SOSLE IINCNT + POPJ P, + +;IT'S TIME FOR THE ULTRA-SLOW CLOCK + MOVEI A,IINTIC ;GET HERE EVERY TWO HOURS OR SO + MOVEM A,IINCNT + PUSHJ P,GLPDTM + POPJ P, ;TIME NOT KNOWN + PUSHJ P,WARMTTY + JRST DATIM6 ;TIME KNOWN, TELL SYSTEM CONSOLE + +VSCLCR: HRRZ A,TT + PUSHJ P,BRTN ;RETURN BUFFER + SETZM CLSYN(I) ;FREE VARIABLES + JRST VSCLC2 + +;CHECK FOR TREES WITH BUMRTL SET THAT HAVE NOT RUN FOR +;A WHOLE HOUR, AND GUN THEM. +VSCOLD: SETZB U,J + CONO PI,CLKOFF + MOVSI B,BUMRTL + MOVSI C,BULGOS + MOVE A,TIME + SUBI A,60.*60.*30. ;1 HOUR AGO +VSCOL0: SKIPE UNAME(J) + TDNN B,APRC(J) + JRST VSCOL1 ;JOB NON EX OR DOSN'T HAVE BUMRTL + SKIPGE SUPPRO(J) ;NO GOOD IF NOT TOP LEVEL. + TDNE C,APRC(J) ;IGNORE JOBS THAT ARE ALREADY LOGGING OUT. + JRST VSCOL1 + CAML A,LUBTM(J) ;NOT RUNNING AND HASN'T RUN FOR 1 HOUR => GUN. + JRST VSCOL2 +VSCOL1: ADDI J,LUBLK ;KEEP LOOKING TILL FIND JOB THAT NEEDS GUNING. + CAMGE J,USRHI + JRST VSCOL0 + JRST CLKONJ ;NO TREES NEED TO BE GUNNED. + +VSCOL2: MOVEI I,[ASCIZ /KILLED HOUR-OLD DETACHED JOB, # /] + PUSHJ P,SYSJEX ;PRINT MESSAGE AFTER CALLING ALOGO6 + PUSHJ P,ALOGO6 + JRST VSCOLD ;LOOK FOR ANOTHER TREE TO GUN. + +; MOVEI I,[ASCIZ/DID FOO TO JOB # /] +; PUSHJ P,SYSJEX +; PUSHJ P,FOO +;DOES FOO TO THE JOB WITH IDX IN J, AND PRINTS A SYSTEM MSG. +;FOO WILL FIND THE USR IDX IN A AND J. IT IS OK TO ENTER +;SYSJEX WITH CLOCK OFF BUT FOO MUST TURN IT ON. +SYSJEX: HRRZS A,J + PUSH P,JNAME(A) + PUSH P,UNAME(A) + PUSH P,A ;SAVE ALL THE INFO WE NEED FOR THE MESSAGE. + PUSH P,I + XCT @-4(P) ;DO "FOO" + JFCL ;LET FOO SKIP. + AOS -4(P) ;SKIP OVER THE PUSHJ TO FOO. + PUSHJ P,WARMTTY + HRRZ I,(P) + PUSHJ P,SYSSP ;PRINT THE STRING IN I + POP P,I + HLRZS I + SKIPE I + PUSHJ P,(I) ;IF LH(I) WAS NONZERO, CALL THAT PRINT ROUTINE + POP P,A + IDIVI A,LUBLK + PUSHJ P,SYSOPT ;PRINT THE JOB # + MOVEI I,[ASCIZ /, USR:/] + PUSHJ P,SYSSP + POP P,A + PUSHJ P,SYSIXP ;PRINT UNAME, AND SPACE + PUSHJ P,STYOS + POP P,A + PUSHJ P,SYSIXP ;PRINT JNAME + JRST SYSTCR ;SPACE, TIME AND CR. + +SUBTTL TPL + +VSCL6: ;CHECK TPL: SEE IF LPT FREE AND ANY FILE TO PRINT. +IFN UNSPLP,[ + PUSHJ P,LSWTL + DEMSW + MOVE A,[SIXBIT /UNSPOO/] + PUSHJ P,DEMSIG + JRST LSWPOP ;REQUEST FAILED, TOO BAD + JRST LSWPOP +] + +IFE TPLP,POPJ P, +IFN TPLP,[ + MOVEI A,SCRTPP ;ALSO ENTER HERE FOR TPL CHECK + TDNE A,SUPCOR ;SKIP IF NOT ALREADY PRINTING FILE + POPJ P, + IFG LPTP-1,[ + SKIPE TPLSWP + JRST VSCL6A + SKIPLE NLPTBR + SKIPL LPTUSR + POPJ P, +VSCL6B: + ] + IFLE LPTP-1,[ + SKIPL LPTUSR + POPJ P, + ] + IFG OLPTP-NLPTP,[ + MOVEI A,132. + CAMLE A,LPTCC + POPJ P, + ] + IFG NLPTP-OLPTP,[ + CONSO NLPT,207 + SKIPG NLPTBR + POPJ P, ;.OPEN OF LPT WOULD HANG + ] + MOVEI A,SCRTPF + TDNE A,SUPCOR ;BLOCKED + POPJ P, + .OPEN TPLI,[SIXBIT / TPL.FILE.(DIR)/] ;MAKE SURE FILE DIR IN CORE + JRST VSCLX1 + MOVEI B,2 +VSCL2: .IOT TPLI,A + CAIE A,^C + CAIN A,12 + SOJG B,VSCL2 + JUMPN B,VSCL2 + SETOB I,C + SETZM TPLFN1 + SETZM TPLFN2 + MOVEI B,TPLFN1 + HRLI B,440600 +VSCL2A: .IOT TPLI,A + CAIN A,"* + JUMPL I,VSCL4 + CAIE A,^C + CAIN A,14 + JRST VSCLX1 + CAIN A,40 + JUMPL I,VSCL2A ;IGNORE SPACES BEFORE THE PACK NUMBER. + CAIN I,3 ;AFTER 4 CHARS STARTING WITH BEGINNING OF PACK NUMBER + JRST VSCL2E ;COMES THE START OF THE FN1. + CAIN A,"L + MOVEI C,0 ;INDICATE LINK + AOJA I,VSCL2A ;FIRST NON SPACE CRUFTY + +IFG LPTP-1,[ +VSCL6A: MOVEI A,132. + CAMG A,LPTCC + SKIPL OLPUSR + POPJ P, + JRST VSCL6B +] + +VSCL2E: MOVEI TT,6 +VSCL2B: SUBI A,40 + IDPB A,B + .IOT TPLI,A + SOJG TT,VSCL2B + MOVE B,[440600,,TPLFN2] +VSCL2C: .IOT TPLI,A + SUBI A,40 + IDPB A,B + TLNE B,770000 + JRST VSCL2C + .IOPUSH TPLI, + .OPEN TPLI,TPLFN + JRST VSCLL1 ;TRY AGAIN + .IOPOP PRTO, + .CLOSE PRTO, +IFN NLPTP,[ +IFN OLPTP,[ + SKIPE TPLSWP + JRST VSCL3A +] + CONSZ NLPT,207 + JRST VSCLX1 + MOVEI T,LPTBSZ + CAMN T,NLPTBR ;SKIP ON OPEN WOULD HANG + .OPEN PRTO,[3,,(SIXBIT /LPT/)] + JRST VSCLX1 +IFN OLPTP,[ + JRST VSCL3B +VSCL3A: +]] +IFN OLPTP,[ + MOVEI A,132. + CAMG A,LPTCC ;SKIP IF .OPEN WOULD HANG +IFN NLPTP,.OPEN PRTO,[3,,'OLP] +.ELSE .OPEN PRTO,[3,,(SIXBIT /LPT/)] + JRST VSCLX1 +VSCL3B: +] + MOVEI A,SCRTPP + IORM A,SUPCOR ;PRINT THIS FILE + IORM A,SUPCOP ;PRINT MORE EVERY SECOND. + JRST TPLPRT + +VSCLL1: .IOPOP TPLI, + JUMPL C,VSCLX1 + MOVEI B,1 ;LINK THAT DIDN'T EXIST + JRST VSCL2 +] + +IFN TPLP,[ +;COME HERE TO TRANSFER SOME CHARS FROM DSK TO LPT, +;ASSUMING BOTH CHNLS ALREADY OPEN. +TPLPRT: +IFN NLPTP,[ +IFN OLPTP,[ + SKIPE TPLSWP + JRST TPLPR3 +] + MOVEI A,TPLBSZ + CAMLE A,NLPTBR + POPJ P, +IFN OLPTP,[ + JRST TPLPR5 +TPLPR3: +]] +IFN OLPTP,[ + MOVEI A,10.*TPLBSZ ;LEAVE SPACE FOR CHARS THAT TAKE MORE THAN 1 CHAR + CAMLE A,LPTCC + POPJ P, +TPLPR5: +] + MOVE A,[-TPLBSZ,,TPLBUF] ;"UN-RELOCATE" + .IOT TPLI,A + MOVE B,A + MOVNI A,-TPLBUF(A) + HRLZS A + JUMPE A,TPLPR1 ;JUMP ON END OF FILE + HRRI A,TPLBUF + .IOT PRTO,A + JUMPL B,TPLPR1 ;LAST BUFFER-FULL PRINTED + JRST TPLPRT + +TPLPR4: CLEARM TPLFN3 + .FDELE TPLFN ;DELETE FILE JUST PRINTED + JFCL + MOVEI A,SCRTPP + ANDCAM A,SUPCOP ;DON'T NEED TO CALL TPLPRT EVERY SECOND. + ANDCAM A,SUPCOR +VSCLX1: .CLOSE PRTO, + .CLOSE TPLI, + POPJ P, + +VSCL4: .IOT TPLI,A + CAIN A,14 + JRST VSCLX1 + CAIN A,12 + JRST VSCL2A + JRST VSCL4 + +TPLPR1: PUSHJ P,TPLPR4 + JRST VSCL6 +] +.ELSE TPLPRT==CPOPJ + +;HANDLE A USER'S REQUEST TO "BLOCK THE TPL" +IFN TPLP,[ +;IF SYS JOB IS SPOOLING, JUST THROW AWAY CURRENT FILE. +TPLOFF: MOVEI A,SCRTPP + TDZN A,SUPCOP + POPJ P, ;NOTHING HAPPENING + PUSHJ P,WARMTTY + .RESET PRTO, + PUSHJ P,TPLPR4 + MOVE A,[SIXBIT /TPLOFF/] + PUSHJ P,SYSIXP + JRST SYSTCR +] + +IFE TPLP+UNSPLP,TPLOFF==CPOPJ + +IFN UNSPLP,[ +TPLOFF: MOVNS B,TPLFLG + JUMPG B,VSCL6 ;IF NOW RUNNING GIVE REQ + MOVSI B,-DMLNG +TPLOF1: SKIPE C,DMTTBL(B) + SKIPG D,DMTTBL+1(B) ;USER INDEX -0 IF NOT YET LOADED + JRST TPLOF2 + CAME C,[SIXBIT /UNSPOO/] + JRST TPLOF2 + PUSH P,U + MOVE U,D + PUSHJ P,ALOGOUT ;DOES ONE USTOP FOR YOU + POP P,U + JRST TPLOF3 + +TPLOF2: ADD B,[DMTLL,,DMTLL] + JUMPL B,TPLOF1 +TPLOF3: PUSHJ P,WARMTTY + MOVE A,[SIXBIT /TPLOFF/ ] + PUSHJ P,SYSIXP + JRST SYSTCR +] + +SUBTTL WHO LINES + +IFN N11TYS,[ +;PDP11 COMM AREA (SYSTEM WIDE) +;STARTS AT PDP11 ADDRESS 40 +;PNTR TO TT11HD +;PNTR TO POINTA +;I/O VERSION # +;SORCE FILE VERSION # +;--PDP10 WD BOARDARY-- 0 , INITED +; 0 , GODOWN + +;AT POINTA: +; ADDR OF SYSTEM WHO-LINE VARS +; ADDR OF 10-11 COMMAND BUFFER +; TENWHO , 0 ;PDP10 SETS TO TELL PDP11 TO UPDATE WHO-LINES +; MAXTV , 0 ;MAXTV = # TV'S 11 IS SET UP TO HANDLE +; NF11TY , 0 ;10 TELLS 11 WHAT TTY # OF 1ST BUFFER IS. + +;PDP11 CONSOLE VARS +; EVEN PDP11 WORD ODD PDP11 WORD +;TT11HD - CHAIN OF ACTIVE INPUT BUFFERS 0 +; PNTR TO OUTPUT BUFFER CHNL 0 VIDEO BUFFER,KBD # (377 IF NONE) +; " CHNL 1 " +;... +; OUTPUT BFR EMPTY NOTIFY RQ FLAG TO FREE CHNL +;... +; PNTR TO WHO LINE BLOCK FREE + +;THE 11 HAS COME UP, SO INIT COMMUNICATION VARIABLES AND START USING IT +SYS11U: SKIPG TT11P + POPJ P, + LDB A,[$11AD0,,TT11HA] ;GET PDP10 ADDRESS OF INPUT-BFR-CHAIN PTR + CAIL A,NTTPG*2000 + BUG HALT,[GARBAGE POINTER IN TV-11 MEMORY] + ADDI A,TT11LO + CONO PI,TTYOFF + MOVEM A,TT11HD ;SAVE IT FOR CLOCK LVL TO CHECK. + LDB C,[$11WD0,,TT11HA+1] ;GET PDP11 IO VERSION #. + MOVEI B,12. ;OLD TV PROGRAMS HANDLE 12. BUFFERS + LDB T,[$11AD1,,TT11HA] ;GET ADDR OF POINTA + CAIL C,3 ;VERSION 3 AND UP TV PGM HAS MAXTV - READ IT + LDB B,[$11WD0,,TT11LO+2(T)] + MOVEM B,TT1111 ;THAT'S HOW MANY TV'S THE 11 THINKS TERE ARE + CAIL B,N11TYS + MOVEI B,N11TYS ;MIN OF THAT AND # TEN THINKS THERE ARE + MOVEM B,TT11RL + MOVEI B,NF11TY + CAIL C,3 ;VERSION 3 TV PGM AND UP WANTS NF11TY + DPB B,[$11WD0,,TT11LO+3(T)] + HRLZ I,TT11RL ;GET AOBJN -> TV'S BOTH 10 AND 11 WILL HANDLE. + MOVNS I +VSCL7C: LDB B,[$11AD0,,1(A)] ;GET DPY BUFFER ADRESS FOR THIS TTY + ADDI B,TT11LO+2 ;CONVERT TO PDP10 ADDRESS. + HRLI B,040000+TT11BY_6 ;GET BP TO ILDB 1ST DATA WORD. + MOVEM B,NF11TY+TOBBP(I) ;PNTR TO BEG OF OUTPUT BUFFER + LDB C,[$11AD0,,(B)] ;GET # BYTES IN DATA AREA + ADDI B,(C) ;GET BP TO LAST WORD IN AREA + MOVEM B,NF11TY+TOBEP(I) + MOVEM B,NF11TY+TOIP(I) + ADDI A,1 + AOBJN I,VSCL7C + MOVEM C,TT11OL ;REMEMBER LENGTH OF OUTPUT BUFFERS. + SETOM TT11P ;TV TTYS NOW UP. + CONO PI,TTYON + MOVE A,[-N11TYS,,NF11TY] + MOVSI B,%TACFM ;NOW SAY ALL PDP11 TTYS NEED + ANDCAM B,TTYSTA(A) ;CONSOLE FREE MESSAGES, + AOBJN A,.-1 + MOVEI A,SCRCFM + IORM A,SUPCOR ;TELL SYS JOB TO PRINT THEM. + PUSHJ P,CLQAD1 ;ADD WHO LINE BLOCK TO CLOCK QUEUE IF NOT THERE + WHOCLB + MOVEI I,[ASCIZ /TV 11 IS UP -/] + JRST SYSSTD ;STRING,SPACE TIME AND DATE THEN CR +] + +IFN N11TYS,[ + +$INSRT WHOVAR + +;UPDATE WHO-LINE VARIABLES. +VWHO: SKIPL TT11P ;DON'T SCREW UP IF PDP11 ISN'T UP. + POPJ P, + MOVE A,TT11HD + HRLZ A,TT11RL + MOVNS A + HRR A,TT11HD ;-<# TV'S BEING USED>,,
+ ADD A,TT1111 + ADD A,TT1111 ;NOW RH -> 2 11-WDS BEFORE PTR TO WHOLINE VARS OF 1ST TV +VWHO1: LDB B,[$11AD0,,1(A)] ;GET WHO LINE VAR PDP11-ADDR, SHIFTED 2. + ADDI B,TT11LO ;CONVERT TO PDP10 ADDRESS. + CONO PI,TTYOFF + MOVE TT,WHJOB(B) ;JOB # (SHIFTED 4+16.) + MOVE C,WHMODE(B) ;MODE (SHIFTED 4+16.) + JUMPG C,VWHO3 + CONO PI,TTYON + JUMPL C,VWHO2 ;MODE < 0 => NO WHOLINE. + HLRE I,A ;GET -<# TIMES REMAINING THRU LOOP> + ADD I,TT11RL + HRRZ TT,TTYSTS+NF11TY(I) ;MODE 0, USE JOB WHICH HAS THE TTY. + MOVE Q,TT + IDIVI Q,LUBLK + LSH Q,4.+16. + MOVEM Q,WHJOB(B) +;FOR OTHER MODES, COME BACK HERE, WITH USER IDX IN TT. +VWHO3R: CONO PI,CLKOFF + MOVE C,UNAME(TT) + HLLZM C,WHUNAM(B) + HRLZM C,WHUNM2(B) ;STORE THE JOB'S UNAME + MOVE C,JNAME(TT) + HLLZM C,WHJNAM(B) + HRLZM C,WHJNM2(B) ;AND JNAME. + MOVE C,USYSNM(TT) + HLLZM C,WHSNAM(B) + HRLZM C,WHSNM2(B) ;AND SNAME. + MOVE C,[SIXBIT /STOP/] + SKIPE USTP(TT) ;AND "STATUS": IF NOT RUNNABLE, "STOP". + JRST VWHO4 + MOVE C,[SIXBIT /RUN/] ;IF NOT WAITING, "RUN". + SKIPN FLSINS(TT) + JRST VWHO4A + MOVE C,[SIXBIT /PAGE/] ;DETECT WAITING FOR PAGE. + MOVE Q,USWST(TT) + TLNE Q,200000 + JRST VWHO4 + JRST VWHO4B + +VWHO4A: MOVE E,UPC(TT) ;JOB RUNNING: USER MODE? + TLNE E,%PCUSR ;IF SO, STATUS IS "RUN" (C ALREADY SET UP) + JRST VWHO4 +VWHO4B: MOVE E,SV40(TT) ;ELSE DECODE SYSTEM CALL TO GET STATUS. + HLRZ Q,E + CAIN Q,(.CALL) + JRST VWHO4D ;SYMBOLIC SYSTEM CALL. + TRZ Q,17_5 + MOVE I,OPTION(TT) + TLNN I,%OPDEC + JRST VWHO4E + CAIE Q,40_9 + CAIN Q,41_9 + JRST VWHO4F + CAIN Q,47_9 + JRST VWHO4F +VWHO4E: CAIN Q,(.IOT) ;.IOT => DECODE DEVICE IN USE. + JRST VWHOI1 + CAIN Q,(.OPER) + JRST VWHOO1 ;.OPER => DECODE ADDRESS FIELD. + CAIN Q,(.CALL) + JRST VWHOC1 ;.CALL BUT NOT SYMBOLIC => DECODE AC FIELD. + LSH Q,-9 + CAIL Q,40 + CAIL Q,40+NUUOSX +VWHO4F: SKIPA C,[SIXBIT /UUO/] ;UNRECOGNIZED UUO. + MOVE C,UUOSXB-40(Q) ;ELSE GET SIXBIT NAME OF UUO. + JRST VWHO4C + +;A SYMBOLIC SYSTEM CALL IS IN PROGRESS. +VWHO4D: MOVE C,LSCALL(TT) ;USE SYSTEM CALL NAME AS STATUS + CAME C,[SIXBIT /SIOT/] + CAMN C,[SIXBIT /IOT/] + JRST VWHOI2 ;BUT IF IT'S "IOT", DECODE DEVICE TYPE. +VWHO4C: SKIPE FLSINS(TT) + JRST VWHO4 + LSH C,-6 + TLO C,'+_12. ;STICK "+" ON FRONT IF RUNNING IN SYSTEM +;DROPS THROUGH ;(NOT IF IN USER MODE, OR IF HUNG). + ;DROPS IN +;COME HERE WITH STATUS AS SIXBIT IN C. +VWHO4: +IFE SWPWSP, SKIPL USWSCD(TT) ;SKIP IF SWAP-BLOCKED +IFN SWPWSP,[ MOVE Q,USWST(TT) + TLNN Q,%SWSB +] + JRST .+3 + LSH C,-6 + TLO C,(SIXBIT/>/) + HLLZM C,WHSTAT(B) + HRLZM C,WHSTA2(B) + MOVEI C,WHJ%RT(B) + HRLI C,442000 + MOVE Q,JTMU(TT) ;COMPUTE % RUN TIME FROM SCHEDULER PRIORITY. + MULI Q,100. + DIV Q,[2.^6] + IDPB Q,C + MOVE Q,UTRNTM(TT) + IDIVI Q,25000. + IDPB Q,C ;JOB RUNTIME IN .1 SEC UNITS. + MOVE Q,NMPGS(TT) + MOVE I,NSWPGS(TT) + SUBM Q,I + IDPB I,C ;JOB # REAL PAGES. + IDPB Q,C ;JOB # VIRTUAL PAGES. +;HANDLE THE USER-SPECIFIED FIELDS IN THE WHOLINE. + MOVE Q,UWHO1(TT) + ANDCMI Q,17 + MOVEM Q,1(C) ;STORE JOB'S WHOLINE FLAGS. + MOVE Q,UWHO2(TT) + HLLZM Q,2(C) ;STORE FIRST USER WHO VAR + HRLZM Q,3(C) + MOVE Q,UWHO3(TT) + HLLZM Q,4(C) ;STORE SECOND USER WHO VAR + HRLZM Q,5(C) +VWHO2: CONO PI,CLKON + AOBJN A,VWHO1 + JRST VWSYS + +VWHOO1: HRRZ Q,E ;JOB EXECUTING .OPER. + CAIL Q,MXOPR + SKIPA C,[SIXBIT/UUO/] + MOVE C,OPRSXB(Q) ;GET .OPER NAME AS STATUS + JRST VWHO4C + +VWHOI2: SKIPL Q,UUAC(TT) ;NEW SYS CALL IOT + JRST VWHO4C ;GETTING ARGUMENTS, UUAC NOT SET UP YET + MOVE I,C ;SAVE NAME IN I + JRST VWHOI4 + +VWHOI1: LDB Q,[270400,,E] ;.IOT + SETZ I, +VWHOI4: ADDI Q,IOCHNM(TT) ;Q HAS IOCHNM WORD ADDR FOR CHANNEL. + MOVE Q,(Q) ;GET IOCHNM WORD CONTENTS (RH INDEXES TABLES) + HLRZ C,Q + HLL Q,IOTTB(Q) ;LH GETS BITS SAYING DIRECTION, BLOCK VS UNIT. + HLL C,CLSTB(Q) + TLNE C,%CLSJ ;IF JOB DEVICE + JRST [ MOVE C,JBDEV(C) ;GET NAME OF SIMULATED DEVICE + JRST VWHOI6 ] + HLLZ C,DCHSTB(Q) ;C GETS DEVICE NAME (LEFT-JUST SIXBIT) + JUMPL C,VWHOI6 ;JUMP IF NORMAL 3-CHARACTER NAME + MOVSS C ;NO, IS ADDRESS OF 6-CHARACTER NAME + MOVE C,(C) +VWHOI6: SETZ D, ;EVENTUALLY MAKE STATUS BE 9 CHARS, NOT 6? + MOVE E,[360600,,C] + ILDB J,E ;FIND FIRST SPACE IN THAT DEVICE NAME + JUMPN J,.-1 + JUMPGE Q,VWHOI3 .SEE %IOTBK ;IF BLOCK MODE, PUT A "B" THERE. + MOVEI J,'B + DPB J,E + IBP E +VWHOI3: CAME I,[SIXBIT /SIOT/] + JRST VWHOI5 + MOVEI J,'S + DPB J,E + IBP E +VWHOI5: MOVEI J,'O ;FOLLOW WITH "O" OR "I" SAYING DIRECTION. + TLNN Q,%IOTOT + MOVEI J,'I + DPB J,E + JRST VWHO4C ;COMPLETED STATUS LOOKS LIKE "TTYBO". + +VWHOC1: LDB Q,[270400,,E] ;.CALL: GET AC FIELD, + MOVE C,CALSXB(Q) ;GIVE SIXBIT NAME OF .CALL. + JRST VWHO4C + +;MODE ISN'T 0: FIGURE OUT WHICH JOB TO DISPLAY WHO-LINE FOR, +;AND GO TO VWHO3R WITH JOB'S IDX IN TT. COME HERE WITH TTYCHN OFF. +VWHO3: LSH TT,-16.-4 ;WHAT JOB WAS LAST DISPLAY DONE FOR? + IMULI TT,LUBLK + CAMGE TT,USRHI + SKIPN D,UNAME(TT) + JRST VWHO3B ;JOB WE WERE LOOKING AT HAS VANISHED. + TLNE C,<-4>_<16.+4-18.> + JRST VWHO3B ;THIS TTY IS GETTING SYSTEM WHO-LINE. + TLNN C,2_<16.+4-18.> + JRST VWHO3E ;WANT SAME JOB AS LAST TIME. + +;MODE 2 OR 3: COME HERE TO SEARCH FOR DESIRED JOB. +VWHO3A: MOVSI E,1_<16.+4-18.> + MOVEM E,WHMODE(B) ;SWITCH TO MODE 1. + MOVEI E,MAXJ+5 ;DON'T LOOP FOREVER +VWHO3D: ADDI TT,LUBLK ;ADVANCE TO NEXT JOB UP OR DOWN. + TLNE C,1_<16.+4-18.> + SUBI TT,2*LUBLK + SKIPGE TT ;WRAP AROUND IF NEC GOING DOWN. + ADD TT,USRHI + CAML TT,USRHI ;WRAP AROUND IF NEC. GOING UP. + MOVEI TT,0 + CAMN D,UNAME(TT) ;BELONGS TO SOMEONE ELSE => KEEP GOING. + JRST VWHO3C ;BELONGS TO THIS USER => STOP. + SOJG E,VWHO3D ;KEEP LOOKING BUT DON'T LOOP IF NO JOB TO BE FOUND. +VWHO3B: SETZM WHSTAT(B) ;NO JOB TO BE FOUND. + CONO PI,TTYON + JRST VWHO2 + +VWHO3C: MOVE Q,TT ;DESIRED JOB FOUND: SET UP FOR MODE 1 + IDIVI Q,LUBLK ;LOOKING AT THIS JOB. + LSH Q,16.+4 + MOVEM Q,WHJOB(B) +VWHO3E: CONO PI,TTYON + JRST VWHO3R + + +;USER WHO LIES UPDATED; NOW UPDATE SYSTEM WHO LINE VARS. +VWSYS: LDB A,[$11AD1,,TT11HA] + LDB B,[$11AD0,,TT11LO(A)] + ADD B,[$11WD1,,TT11LO] ;FIRST WORD OF BLOCK SET BY 11 + MOVEI C,SRI + IDPB C,B ;ITS VERSION#. + MOVEI C,2 + MOVEI E,0 +IFN SWPWSP, MOVSI TT,%SWSB + MOVEI Q,2*LUBLK +VWSYS2: CAML Q,USRHI ;COUNT # JOBS. + JRST VWSYS1 + SKIPN UNAME(Q) + JRST VWSYS3 + AOS C ;C GETS # JOBS, + SKIPE USTP(Q) + JRST VWSYS3 +IFE SWPWSP, SKIPGE USWSCD(Q) +IFN SWPWSP, TDNE TT,USWST(Q) + AOS E ;E GETS NUMBER OF ACTIVE SWAPPED BLOCKED JOBS +VWSYS3: ADDI Q,LUBLK + JRST VWSYS2 + +VWSYS1: IDPB C,B ;TOTAL # JOBS + MOVE D,MMPCNT + IDPB D,B ;TOTAL MEM (= TOTAL # PAGES, COUNTING SHARED PAGES ONLY ONCE). + MOVE C,RNABLU + SUBI C,1 + IDPB C,B ;RUNNABLE USERS + IDPB E,B ;# SWAP-BLOCKED JOBS + MOVE TT,NPGWTU + IDPB TT,B ;# WAITING FOR PAGE. + MOVE C,TRUMM ;TOTAL RUNNABLE USER MEMORY + IDPB C,B + MOVEI C,0 + MOVE TT,USRHI ;COUNT PAGES AVAILABLE FOR USE OR ACTUALLY USED FOR USER MEM + ADDI TT,USRSTG+1777 + LSH TT,-10. +VWSYS5: LDB D,[MUR,,MEMBLT(TT)] + CAIE D,MURUSR + CAIN D,MUFR + AOS C ;FREE OR USER MEM. + CAIGE TT,TSYSM-1 + AOJA TT,VWSYS5 + IDPB C,B ;TOTAL MEM AVAIL FOR USERS + HLRZ C,QDATE + IDPB C,B + MOVE C,SYSDBG + IDPB C,B + AOS B ;SKIP A WHOLE WORD FOR TIME OF DAY + MOVEI D,(B) ;SAVE ADDRESS FOR BELOW + MOVE C,SUSRS ;# LOGGED IN USERS. + IDPB C,B + MOVEI E,10000. ;FAIR SHARE IN % + IDIV E,SLOADU ;BASHES TT + IDPB E,B + MOVE C,TIMOFF ;TIME OF DAY IN .5 SEC UNITS. + LSH C,4 + MOVEM C,(D) ;DEPOSITING TIME OF DAY TRIGGERS WHO-LINE UPDATE + POPJ P, ; BY THE PDP-11, SO DEPOSIT IT LAST + +] ;END IFN N11TYS + +SUBTTL EXPAND/CONTRACT USER VARIABLES AREA + +SYSEX: PUSHJ P,SCOREX + POPJ P, + MOVE A,TIME + MOVEM A,SCITM + POPJ P, + +SYSDEC: MOVE A,TIME ;TRY TO DECREASE CORE RESERVED FOR USER VARIABLES + SUB A,SCITM + CAIG A,50. + POPJ P, ;TOO SOON SINCE GOT MORE CORE + CONO PI,CLKOFF + MOVE A,USRHI + SUBI A,LUBLK + SKIPN UNAME(A) + JRST .-2 + ADDI A,LUBLK + MOVEM A,USRHI ;USRHI=> HIGHEST USER+L + ADDI A,USRSTG + ADDI A,1777 + SETOM SJCFF ;INHIBIT ALLOCATION WHILE HUSRAD IS CHANGING + CONO PI,CLKON + MOVEI U,0 ;FOR ACORE + LSHC A,-10.-36. ;MOVE INTO B AS WELL + PUSHJ P,ACORE + BUG ;LOST FLUSHING CORE? + CLEARM SJCFF + POPJ P, + +SCOREX: LDB B,[121000,,HUSRAD] ;EXTEND CORE FOR USER VARIABLES AT TOP OF SYSTEM + ADDI B,1 + CAILE B,LIOBLK + MOVEI B,LIOBLK ;TRYING TO GET TOO BIG, DON'T + MOVEI U,0 + JRST ACORE + +SUBTTL LOGGER OUT + +;THIS ROUTINE AWAKENED BY .LOGOUT, .GUN, ETC. +;SEARCH FOR TREES THAT ARE LOGGING OUT AND READY TO BE FLUSHED +;(IE HAVE BULGO SET) AND FLUSH THEM, PRINTING LOGOUT MESSAGE IF APPRO. +SYSGUN: SETZ U, +SYSGU0: MOVE T,APRC(U) + TLNE T,BULGO ;IS THIS JOB READY TO BE FLUSHED? + SKIPN UNAME(U) + JRST SYSGU1 +IFN NUNITS,[ + SKIPGE TTYTBL(U) ;IF CONSOLE-CONTROLLED, FLUSH UTAPE ASSIGNMENTS + JRST SYSGU2 + MOVSI I,-NUNITS + MOVE A,UNAME(U) + CAMN A,UTASS+1(I) + SETZM UTASS+1(I) + AOBJN I,.-2 +SYSGU2: ] + HLRO B,UNAME(U) + AOJE B,SYSGU3 ;IF THIS TREE COUNTS AS A LOGGED-IN USER, + SKIPL TTYTBL(U) + SOS SUSRS ;DECREMENT COUNT OF SUCH. +SYSGU3: CONO PI,CLKOFF + PUSHJ P,DMNPLO ;UPDATE TREE'S USAGE AND INFORM DEMON JOB + MOVEM TT,TRUNTM(U) ;SAVE RUN TIME FOR LOGOUT MSG + CONO PI,CLKON + SKIPGE A,TTYTBL(U) + JRST SYSGU4 ;IF TREE HAS CONSOLE, + SKIPE TTNTO(A) + BUG + PUSHJ P,TTYLO1 ;FREE IT. + CAMN U,EPDL(U) ;UNLESS GUNNED DOWN, + SKIPN SUPPLG ;MAY NOT WANT TO BOTHER PRINTING MESSAGE ON SYS CONSOLE + SKIPGE DEDTIM + JRST SYSGU4 ;IF LOGGED OUT BECAUSE SYS DOWN, SPARE THE LOGOUT MSG + PUSHJ P,WARMTTY + MOVEI I,[ASCIZ / LOGOUT /] + PUSHJ P,SYSSP + MOVE A,UNAME(U) + PUSHJ P,SYSIXP ;UNAME. + PUSHJ P,STYOS ;SPACE. + HRRZ A,TTYTBL(U) + PUSHJ P,SYSOPT ;TTY #. + PUSHJ P,SYSTCR + ;VALUE PRINTED IS WRONG, AND HARD TO FIX, SO FOLLOWING CODE HAS BEEN FLUSHED. + ;THE REASON IT'S WRONG IS BECAUSE TIME ALREADY SENT TO THE DAEMON IS NOT INCLUDED. + ;MOVEI I,[ASCIZ / TUSED= /] + ;PUSHJ P,SYSSP + ;MOVE A,TRUNTM(U) + ;MULI A,4069. + ;DIVI A,1000. + ;PUSHJ P,SYSDPC + ;MOVEI I,[ASCIZ / USECS/] + ;PUSHJ P,SYSSTD + CAMN U,EPDL(U) ;WAS LOGGED OUT BY SELF? + JRST SYSGU4 + MOVEI I,[ASCIZ / ^^ GUNNED DOWN BY /] + PUSHJ P,SYSSP + MOVE A,SRN4(U) + PUSHJ P,SYSIXP ;UNAME OF GUNNER. + MOVE A,SRN5(U) + PUSHJ P,SYSSIX ;SPACE, AND JNAME OF GUNNER. + PUSHJ P,SYSTCR ;CRLF. +;MESSAGES PRINTED IF NECESSARY. +SYSGU4: SETZ R, + PUSHJ P,ZUSER ;COMPLETELY ELIMINATE THE JOB. + CONO PI,CLKON +SYSGU1: ADDI U,LUBLK + CAMGE U,USRHI + JRST SYSGU0 + SETZ U, + POPJ P, + +;DETACH ANY TREES WHOSE TOP-LEVEL JOBS HAD FATAL INTS + +SYSDT: SETZB U,J + PUSHJ P,SWTL + TREESW + CONO PI,CLKOFF + MOVSI B,BUSRC + MOVSI T,BULGOS+400000 +SYSDT0: SKIPN UNAME(J) + JRST SYSDT1 + SKIPGE SUPPRO(J) ;LOOK FOR TOP-LEVEL + TDNE T,APRC(J) ;IGNORE JOBS ALREADY DISOWNED, OR LOGGING OUT. + JRST SYSDT1 + TDNE B,USTP(J) ;THAT HAS BEEN STOPPED AS BY SUPERIOR + JRST SYSDT2 +SYSDT1: ADDI J,LUBLK + CAMGE J,USRHI + JRST SYSDT0 + JRST CLKOPJ ;NO MORE SUCH JOBS, DONE; LSWPOP AND CLKON. + +;FOUND A TOP LEVEL JOB NEEDING TO BE DETACHED. +SYSDT2: PUSH P,J + MOVE T,OPTION(J) + TLNE T,%OPLKF + JRST [ IDIVI J,LUBLK ;BASHES R + .CALL [SETZ ? 'UNLOCK ? SETZI %JSNUM(J)] ;UNLOCK THE LOCKS + BUG + MOVE J,(P) + JRST .+1 ] + CONO PI,CLKOFF ;IODCSS MIGHT HAVE TURNED IT ON + SKIPL E,JBI(J) ;NOTE CLKOFF IN EFFECT WHILE HACKING JOB DEVICE STUFF + SKIPGE JBCG(E) + JRST SYSDTA + MOVE A,JBCUI(E) ;JOB DEVICE, GIVE IOCER1 OR OPNL7 + LDB T,[000400,,JBSTS(E)] + CAIE T,1 + JRST [ MOVSI T,7_5 ;NON IOT, UNHANG CREATOR SO WILL SEE OPNL7 + MOVEM T,JBSTS(E) + MOVE T,FLSINS(A) + CAMN T,JBFLS + SETZM FLSINS(A) + JRST SYSDTA ] + MOVEI B,1 ;IOT GIVE IOCER1 + MOVS H,E + PUSHJ P,NSTIOC + JFCL +SYSDTA: POP P,J + SETZ U, + MOVE I,[SYSDT8,,[ASCIZ/TOP LEVEL INTERRUPT /]] + PUSHJ P,SYSJEX + PUSHJ P,SYSDT7 + JRST SYSDT + +SYSDT8: MOVE A,-1(P) ;USER INDEX + MOVE A,PIRQC(A) ;TOP LEVEL INTERRUPT BITS + PUSHJ P,SYSFWP +SYSDT9: MOVEI I,[ASCIZ/ DETACHED JOB # /] + JRST SYSSP + +;JOB IN J SHOULD BE DETACHED, AND GUNNED AFTER AN HOUR, +; OR RIGHT AWAY IF NOT LOGGED IN +SYSDT4: HLRE B,UNAME(J) + AOJE B,SYSDT5 ;NOT LOGGED IN => KILL + HRLI I,SYSDT9 + PUSHJ P,SYSJEX + PUSHJ P,SYSDT3 + POPJ P, + +SYSDT5: HRLI I,[MOVEI I,[ASCIZ / KILLED JOB # /] + JRST SYSSP] + PUSHJ P,SYSJEX + PUSHJ P,SYSDT6 + POPJ P, + +SYSDT6: PUSHJ P,SYSDT3 ;FIRST DETACH (LEAVES USER INDEX OF TOP LEVEL JOB IN A). + JRST ALOGO6 ;THEN LOG OUT. SINCE DETACHED, NO ADDITIONAL MSG FROM SYSGUN. + +;CALL WITH CLOCK OFF TO DETACH THE JOB WITH IDX IN A AND J. +;ASSUME JOB'S BULGOS HAS BEEN CHECKED, AND TREESW LOCKED. +;TURNS CLOCK BACK ON AND DOES A LSWCLR +SYSDT7: TDZA B,B ;HERE TO LEAVE AROUND +SYSDT3: MOVEI B,10 ;HERE TO SET BUMRTL WHEN WE DETACH + PUSHJ P,SOSSET + DIELOK(A) + AOS DIELOK(A) + CONO PI,CLKON + MOVEM B,CTLBTS(U) + PUSHJ P,NDETA0 + BUG + POPJ P, + +IFN NDLTYS+NETYS,[ + +;HANDLE DIAL-UP LINE CONNECTS OR DISCONNECTS ON DL-10 AND DTE20. + +SYSDIL: +IFN NDLTYS,[ + SKIPN A,DL10CL + JRST SYSDL2 ;THERE'S NONE TO PROCESS? + SETZM DL10CL ;FREE THE VAR FOR THE PDP11 + PUSHJ P,SYSDL0 +SYSDL2: ];NDLTYS +IFN NETYS,[ + SKIPGE A,DTEHNG + JRST SYSDL3 + SETOM DTEHNG + PUSHJ P,SYSDL0 +SYSDL3: +];NETYS + POPJ P, + +SYSDL0: LDB I,[.BP 77,A] ;GET OUT THE TTY NUMBER + CAIL I,NCT + POPJ P, + TRNE A,-100 + JRST SYSDL1 ;IT'S A CONNECT + PUSHJ P,SWTL ;IT'S A DISCONNECT + TREESW + MOVE J,TTYSTS(I) ;DETACH THE TREE ON THAT TTY. + JUMPL J,LSWPOP ;THERE'S NO TREE. + TLNN J,%TSCNS + JRST LSWPOP ;TTY IS OPEN AS A DEVICE. + MOVE I,APRC(J) + TLNE I,BULGOS ;GIVE UP IF TREE LOGGING OUT. + JRST LSWPOP + MOVE U,USER + MOVEI I,[ASCIZ /DIALUP LINE DISCONNECTED,/] + JRST SYSDT4 + +;ON A CONNECT, SNARF THE LINE SPEEDS DETERMINED BY THE PDP11. +SYSDL1: LDB B,[.BP 7000,A] + DPB B,[$TTISP,,TTYTYP(I)] + LDB B,[.BP 700,A] + DPB B,[$TTOSP,,TTYTYP(I)] + PUSHJ P,NCNSSP ;SET UP INITIAL TTY TYPE AS PRINTING, ACCORDING TO SPEED + MOVEI B,20 ;DON'T ASSUME TTY IS AT LEFT MARGIN + MOVEM B,TTYIHP(I) + MOVEM B,TPHP(TT) + MOVEM B,TPHP+TPLEN(TT) + POPJ P, +];NDLTYS+NETYS +.ELSE SYSDIL==CPOPJ + +IFN N11TYS,[ +SYS11D: MOVEI I,[ASCIZ /TV 11 WENT DOWN --/] + PUSHJ P,SYSSTD ;STRING, SPACE, TIME AND CR + SETZM TT11P ;IN CASE SCR11D WAS SET BY A USER, AND HE DIDN'T HACK THIS. + MOVEI A,TT11HD+1 + MOVEM A,TT11HD ;PREVENT TT11IN FROM BEING CALLED ANY MORE. +SYS11G: PUSHJ P,SWTL ;PREPARE FOR DOING DETACHES + TREESW + MOVE I,[-N11TYS,,NF11TY] +SYS11F: SKIPGE J,TTYSTS(I) ;DETACH ALL 11TV TREES. + JRST SYS11E ;THIS 11TV NOT IN USE + TLNN J,%TSCNS + JRST SYS11P ;THIS 11TV IN USE AS A DEVICE, DON'T DETACH BUT DO PCLSR + MOVE T,APRC(J) + TLNE T,BULGOS + JRST SYS11E ;DON'T DETACH TREES THAT ARE LOGGING OUT. + MOVE U,USER + MOVEI I,[ASCIZ / .../] + PUSHJ P,SYSDT4 ;DETACH OR KILL JOB W/ # IN J, AND PRINT MESSAGE. + JRST SYS11G ;TREESW NOW UNLOCKED; MUST RE-LOCK. + +SYS11P: HRRZ A,J ;PCLSR THE NAME DRAGON + PUSHJ P,NJRPCL + PUSHJ P,NJUPCL ;AND DROP INTO SYS11E + +SYS11E: AOBJN I,SYS11F + PUSHJ P,LSWPOP ;TREESW NOT NEEDED IF NOTHING TO DETACH. + MOVSI T,-MXVBN ;FLUSH VIDEO BUFFER ASSIGNMENTS. + SETOM VBAST(T) + AOBJN T,.-1 + MOVEI T,0 +SYS11V: CAML T,USRHI + POPJ P, + SETZM NVDBA(T) + SETOM TVCREG(T) ;FLUSH TV BUFFER NUMBERS IN CREGS + ADDI T,LUBLK + JRST SYS11V + +TVBNCL: PUSH P,T ;"DEASSIGN" TVVBN(U) AND CLEAR IT ON SCREEN IF NECC + SKIPN TEN11F + SKIPL TT11P + JRST TVBNC1 + SKIPL T,TVVBN(U) + CAME U,USER + JRST TVBNC1 + PUSH P,400000+TTR10*2000 + MOVEM T,400000+TTR10*2000 + MOVE T,TVBLAD + CLEARM 400000+TTR0*2000(T) + POP P,400000+TTR10*2000 +TVBNC1: SETOM TVVBN(U) + JRST POPTJ +];N11TYS + +;PRINT CONSOLE FREE MSGS ON ALL TTYS THAT NEED IT. +;NOTE THAT THERE ARE LOWER CASE MESSAGES ON THIS PAGE. +.SEE TTYLO1 ;THIS RTN SIGNALLED WHEN A TTY BECOMES FREE. +SYSCFM: CLEARM IOCHNM+STYOC ;REUSE SYSTEM CONSOLE CHANNEL +SYSCF0: MOVEI A,0 +SYSCF1: CAIL A,NCT + JRST SYSCOP ;DONE, SWITCH SYSCON CHANNEL BACK TO SYSCON + SKIPGE B,TTYSTA(A) .SEE %TACFM + AOJA A,SYSCF1 + TLNE B,%TANJS + TLZ B,%TACTZ ;%TANJS MEANS A FAILED ^Z - FORGET ABOUT THAT ^Z. + MOVEM B,TTYSTA(A) + SKIPGE TTYSTS(A) .SEE %TSFRE + TLNE B,%TACTZ + AOJA A,SYSCF1 ;IN PROCESS OF LOADING TREE FOR THIS CONSOLE + HRLZ T,A + ADD T,[%TJDIS+%TJMOR,,TYODN] + MOVEM T,IOCHNM+STYOC ;"OPEN" A CHANNEL TO THAT TTY. + SKIPGE SHUTDN + PUSHJ P,SYSTS1 ;IF SHUTDOWN AND A DISPLAY, CLEAR THE SCREEN + MOVEI I,[ASCIZ / +Top level interrupt, tree detached +/] + MOVSI B,%TCDET ;IF TTY FREE DUE TO DETACH FOR TOP LEVEL INT, + TDNE B,TTYCOM(A) + PUSHJ P,SYSSP .SEE NDETAC ;SAY SO. + ANDCAM B,TTYCOM(A) + MOVSI B,%TANJS + ANDCA B,TTYSTA(A) + EXCH B,TTYSTA(A) ;CLEAR BIT, SAVE OLD VALUE + PUSH P,A + XCT DWNMSG + SKIPGE SHUTDN + JRST SYSCF2 ;SYSTEM IS DOWN, SAY SO + XCT SCMESG + CAMN A,SYSCN + JRST SYSCF2 ;SYSTEM JOB USING THIS CONSOLE, SAY SO + SRITYP [ System fully loaded. Console ] + TLNN B,%TANJS + SRITYP [ Console ] + PUSHJ P,SYSSP +IFN N11TYS, CAIE A,NF11TY ;ON ALL FREE PDP11-TV CONSOLES + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / Free./] + PUSHJ P,SYSSTD + XCT DMESSG + SKIPE SYSDBG +SYSCF2: PUSHJ P,SYSSTD ;SAY "SYS BEING DEBUGGED" IF NEC. + SKIPLE SHUTDN + PUSHJ P,SYSSHM ;SAY "SYS GOING DOWN" IF NEC. + POP P,A + MOVSI B,%TACFM ;TTY NO LONGER NEEDS CONSOLE FREE MSG. + IORM B,TTYSTA(A) +IFN N11TYS,PUSHJ P,TTYLO2 ;TELL THE PDP11 THIS TTY IS FREE + SETZM IOCHNM+STYOC + JRST SYSCF0 + +SUBTTL SHUTDOWN + +;HANDLE .SHUTDN - PRINT "GOING DOWN" MSGS, ETC. +SYSSHD: LDB D,[221700,,SHUTLK+1] + PUSHJ P,SWTL + SHUTLK + MOVEI I,SYSSHM + TLO I,40 + PUSH P,D + PUSHJ P,SYALCP + POP P,D + IMULI D,LUBLK + SKIPE D ;SKIP IF LEFT FROM >5 MIN PRINT OUT + SKIPN A,UNAME(D) + JRST LSWPOP + MOVEI I,[ASCIZ /CULPRIT = /] + PUSHJ P,SYSSP + PUSHJ P,SYSSIX + MOVE A,JNAME(D) + PUSHJ P,SYSSIX + PUSHJ P,SYSTCR + JRST LSWPOP + +;GOING DOWN, WHAT A SHAME +SYSSHM: SRITYP [GOING DOWN IN ] + SKIPG SHUTDN + SRITYP [REVIVED] + PUSHJ P,SYSSP + SKIPG B,SHUTDN + JRST SYSSHN + SUB B,TIME + IDIVI B,30. ;CONVERT TO SECONDS + PUSHJ P,RTIME ;CONVERT TO SIXBIT + MOVE B,A + PUSHJ P,SYSTCD +SYSSHN: MOVEI I,[.ASCII /. /] + JRST SYSSTD + +;AND COME HERE WHEN TIME FOR SYS TO GO DOWN. +;MARK THE SYSTEM "DOWN", START FLAPPING TAPES AND DISKS, +;GUN ALL USERS, ETC. COMPLETION OF GOING DOWN IS DETECTED AT +;SLOW CLOCK LEVEL ("COFFIN"). +SYSOUT: PUSHJ P,CLQDEL + DEDBLK + SETOM DEDTIM ;PREVENT ^Z'S + .FDELE [SIXBIT/ SYSDOWN MAIL/ ? 0 ? 0] + JFCL + MOVEI U,LUBLK*2 +SYSCK3: SKIPGE SUPPRO(U) ;LOOK FOR ALL TOP-LEVEL JOBS. + SKIPN UNAME(U) + JRST SYSCK4 + MOVE T,USTP(U) + TLNE T,BUSRC + JRST SYSCK1 + MOVE T,OPTION(U) ;IS THIS JOB AN EXCEPTION? + TLNE T,%OPLIV + JRST SYSCK4 ;YES, LET IT LOG ITSELF OUT +SYSCK1: PUSHJ P,ALOGOUT ;LOG IT OUT (TELLS IT TO PREPARE ITSELF, SIGNAL SYSGUN) +SYSCK4: ADDI U,LUBLK + CAMGE U,USRHI + JRST SYSCK3 + SETZ U, +DWNMSG: SRITYP [NOT IN OPERATION] + PUSHJ P,SYALCP ;TYPE OUT ON FREE CONSOLES +IFN TPLP, MOVEI A,SCRTPF ;TPLOFF +IFN TPLP, IORM A,SUPCOR +IFN UNSPLP,[ SKIPG TPLFLG + JRST SYSCK0 + MOVEI A,SCRTPF + IORM A,SUPCOR +SYSCK0: +] MOVE I,QACTB + IORM I,QMDRO + MOVSI A,-NQS +SYSCK7: MOVE I,DCHBT(A) + SKIPN QACT(A) + IORM I,QTUTO(A) + AOBJN A,SYSCK7 +IFN NUNITS,[ + MOVEI A,1 +SYSUDM: SKIPL UDIRO(A) + .UDISMT A, ;DISMOUNT TAPES + CAIGE A,NUNITS + AOJA A,SYSUDM +] + MOVE T,TIME + MOVEM T,DTHTIM + SETOM SHUTDN + PUSHJ P,TTTMNT ;TURN OFF ALL TERMINET MOTORS + JRST SCOR + +SUBTTL SYSTEM CHECKS +;CHECK FOR DEVICES THAT LOSE THE PIA, DEVICES THAT INTERRUPT SPURIOUSLY, +;CLOBBERD LOCATIONS IN MEMORY. + +IFE KS10P,[ ; KS has no devices to speak of... + +SYSCK5: MOVSI A,-128. +SYSC51: SKIPL B,DCHNTC(A) +SYSC5A: AOBJN A,SYSC51 + JUMPGE A,CPOPJ + TLNN B,300000 + JRST SYSC5A + PUSH P,A + TLZE B,200000 + JRST SYSC52 + PUSHJ P,SYSC5S + JRST SYSC53 +SYSC52: PUSHJ P,SYSC5C +SYSC53: POP P,A + MOVSI B,300000 + ANDCAM B,DCHNTC(A) + JRST SYSC5A + +SYSC5C: PUSHJ P,SYSC5B + MOVEI I,[ASCIZ / CLOBBERED/] + JRST SYSSTD + +SYSC5S: PUSHJ P,SYSC5B + MOVEI I,[ASCIZ / SUSPECTED OF INTERRUPTING ON CHANNEL /] + PUSHJ P,SYSSP + LDB T,[360300,,DCHNTC(A)] + PUSHJ P,SYSSOP + JRST SYSTCR + +SYSSOP: PUSH P,A + PUSH P,B + MOVE A,T + PUSHJ P,SYSOPT + JRST POPBAJ + +SYSC5B: MOVEI I,[ASCIZ /DEVICE /] + PUSHJ P,SYSSP + HRRZ T,A + LSH T,2 + PUSHJ P,SYSSOP + MOVEI I,[ASCIZ / (CONI= /] + PUSHJ P,SYSSP + HRRZ T,DCHNTC(A) + PUSHJ P,SYSSOP + MOVEI I,[ASCIZ /) /] + JRST SYSSP + +] ;IFE KS10P + +SYSCKS: HRRZ T,UPDBR1 ;CHECK FOR CLOBBERED DBRS + HRRZ TT,UPDBR2 + CAIN T,UPGMP + CAIE TT,UPGMP+100 + BUG HALT,[PAGER DATA CLOBBERED. MAY BE DEC-TTL LEVEL CONVERTERS LOSING.] +;DROPS THROUGH + ;DROPS IN + MOVE A,SYSCKP + MOVE B,(A) + MOVEI C,(B) + EQV C,(B) + AOBJN B,.-1 + CAME C,CKSUMS-TSTB(A) + JRST SYSKS2 + AOBJN A,SYSKS1 +SYSKS3: MOVE A,[-LTSTB,,TSTB] +SYSKS1: MOVEM A,SYSCKP + POPJ P, + +SYSKS2: EXCH C,CKSUMS-TSTB(A) + XOR C,CKSUMS-TSTB(A) ;SAVE XOR + PUSHJ P,WARMTTY + PUSHJ P,DINGTTY + MOVEI I,[ASCIZ /SYSTEM CLOBBERED BETWEEN /] + PUSHJ P,SYSSP + HRRZ A,(A) + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / AND /] + PUSHJ P,SYSSP + MOVE B,SYSCKP + HLRE A,(B) + SETCMM A ;OFFSET BY ONE + ADD A,(B) + HRRZS A + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / XOR= /] + PUSHJ P,SYSSP + MOVE A,C + PUSHJ P,SYSFWP + MOVEI I,[ASCIZ / !/] + PUSHJ P,SYSSTD + CLEARM TCKXOR ;TRY TO DETERMINE EXACT ADR AND PREV CONTENTS + MOVE A,[TCKXOR,,TCKXOR+1] + BLT A,TCKXOR+35. + MOVE A,[-LTSTB,,TSTB] +SYSKS6: MOVE B,(A) +SYSKS5: MOVE C,(B) +REPEAT 36.,[IFL .RPCNT-18.,TLNE C,400000_<-.RPCNT> +IFGE .RPCNT-18.,TRNE C,400000_<18.-.RPCNT> + XORM B,TCKXOR+.RPCNT + ] + AOBJN B,SYSKS5 + AOBJN A,SYSKS6 + MOVSI D,-36. +SYSKS7: MOVE A,TCKXOR(D) ;UPDATE CKXORS TBL AND FILL TCKXOR TBL WITH POSSIBLE ADRS + EXCH A,CKXORS(D) + XOR A,CKXORS(D) + HRRZM A,TCKXOR(D) + AOBJN D,SYSKS7 + PUSHJ P,STYOT ;INDENT LINE + MOVSI D,-36. + MOVSI E,400000 ;CURRENT BIT + CLEARB I,J ;COUNT OF #'S PRINTED, CLOBBERED WD +SYSKS8: SKIPE A,TCKXOR(D) + AOJA J,SYSKS9 ;INCR COUNT OF ADRS PRINTED +SYSKT2: LSH E,-1 + AOBJN D,SYSKS8 + SOJN J,SYSKT1 ;MORE THAN 1 ADR CLOBBERD SO CANT PRINT PREV CONTENTS + MOVEI T,"= + PUSHJ P,STYO + MOVE A,I ;PRINT CONTENTS PRIOR TO CLOBBERAGE + XOR A,(R) ;XOR CURRENT CONTENTS + PUSHJ P,SYSFWP + MOVEI T,"- + PUSHJ P,STYO + MOVEI T,"> + PUSHJ P,STYO + MOVE A,(R) + PUSHJ P,SYSFWP ;CURRENT CONTENTS +SYSKT1: PUSHJ P,SYSCRF + JRST SYSKS3 + +SCKX1: PUSH P,T ;UPDATE CKXORS TO REFLECT CHANGING WD IN T IN ADR IN Q + MOVSI C,-36. +SCKX2: SKIPGE T + XORM Q,CKXORS(C) + LSH T,1 + AOBJN C,SCKX2 + JRST POPTJ + +SYSKS9: PUSHJ P,SYSOPT + PUSHJ P,STYOS + MOVE R,TCKXOR(D) ;CLEAR DUP ENTRIES + MOVE T,D + MOVE Q,E ;ALSO LEAVE LAST ADR IN R (IN CASE ITS ONLY ADR) +SYSKT3: CAME R,TCKXOR(T) + JRST SYSKT4 + CLEARM TCKXOR(T) + XORM Q,I +SYSKT4: LSH Q,-1 + AOBJN T,SYSKT3 + JRST SYSKT2 + +SUBTTL SUPPORT ROUTINES FOR BUG MACRO + +;NOTE: THESE REPLACE THE SYSMSG ROUTINE THAT USED TO BE HERE + +;ENTRY POINTS +BUGCHK: PUSH P,TT + MOVE TT,SYSMPT ;HOW MANY MESSAGES BEHIND? + SUB TT,SYSMPU + CAIGE TT,<8_SYSMLNG>-8 + SKIPE SYSDBG + JRST BUGPSE+1 ;TREAT AS BUGPSE IF BUFFER FULL OR SYSDBG + CAIA +BUGINF: PUSH P,TT + PUSHJ P,SYSMS0 ;HAND MESSAGE TO SYSTEM JOB TO BE PRINTED + JRST POPTTJ ;CONTINUE TRAPPED ROUTINE + +BUGPSE: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER + JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/PAUSE. FIND A WIZARD, CONSIDER TAKING A CRASH DUMP, +OR TYPE P TO ATTEMPT TO REVIVE THE SYSTEM./ + +BUGDDT: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER + JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/DDT. TYPE P TO CONTINUE./ + +BUGNIL: PUSH P,TT + JRST BUGHL1 ;NO MESSAGE, JUST GO STRAIGHT TO DDT. + +BUGAWF: 0 ;JSR HERE WHEN AWFUL THINGS HAVE HAPPENED + CONO PI,PIOFF ;BETTER DO THIS AS SOON AS POSSIBLE + MOVEM P,BUGACS+P ;SAVE P AND GET A PDL TO USE + MOVE P,BUGPDL + PUSH P,BUGAWF ;SIMULATE PUSHJ P,BUGHLT +BUGHLT: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER +BUGHL1: JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/HALT. FIND A WIZARD OR CONSIDER TAKING A CRASH DUMP. +THE SYSTEM HAS CRASHED AND CANNOT BE REVIVED WITHOUT EXPERT ATTENTION. +IF YOU CAN'T FIND HELP, RELOAD THE SYSTEM./ + +;ROUTINE TO PICK UP THE DATA OUT OF THE BUG TABLE, EVALUATE THE +;ARGUMENTS, AND DUMP THE RESULTS INTO THE SYSMSG BUFFER TO BE +;PRINTED LATER. THE THIRD THING DOWN ON THE STACK IS THE PC+1 +;AT WHICH THE BUG WAS DETECTED. TT IS THE ONLY SMASHABLE REGISTER. +SYSMS0: MOVEI TT,8 ;8 WORDS IN ENTRY + ADDB TT,SYSMPT ;UPDATE STORING POINTER + ANDI TT,8_SYSMLNG-1 ;MASK TO BUFFER INDEX + ADDI TT,SYSMBF + PUSH P,TT ;SAVE PTR + PUSH P,A ;NOW LOCATE BUG TABLE ENTRY + PUSH P,B + MOVE A,TIME ;STASH TIME IN EXTRA WORD OF ENTRY + MOVEM A,7(TT) + MOVEI B,BUGTAB +SYSMS1: HRRZ A,(B) + CAIN A,@-5(P) + JRST SYSMS2 ;PC MATCHES + HLRZ A,(B) ;ADVANCE TO NEXT ENTRY + ADD B,A + JUMPN A,SYSMS1 + JRST 4,. ;NOT IN TABLE?? MACROS MUST BE SCHROD + +SYSMS2: HLRZ A,(B) + ADDI TT,-2(A) + EXCH TT,-2(P) ;TT START OF ENTRY, -2(P) END + MOVE A,TT + HRLI A,1(B) ;COPY BITS,,STRING AND ARG POINTERS + BLT A,@-2(P) + POP P,B + POP P,A + SUBM TT,(P) ;(P) GETS -NARGS + SKIPE (P) ;IN CASE NO ARGS +SYSMS3: PUSH TT,@1(TT) ;EVALUATE ARGUMENT POINTERS + AOSGE (P) + JRST SYSMS3 + MOVEI TT,SCRMSG ;BIT FOR MSG PRINT + IORM TT,SUPCOP ;TRY EVERY SECOND TO PRINT SOME MSGS + IORM TT,SUPCOR ;FIRST ATTEMPT RIGHT AWAY. + JRST POP1J ;RETURN TO BUGINF OR WHEREVER + +;CALL HERE TO PRINT THE MESSAGES OUT OF THE BUFFER +;A HAS SCRMSG +SYSMPR: MOVE TT,SYSMPT ;LAST MESSAGE IN + CAMG TT,SYSMPU ;LAST MESSAGE OUT + JRST [ ANDCAM A,SUPCOP ;CAUGHT UP + POPJ P, ] + SUBI TT,8_SYSMLNG + CAMLE TT,SYSMPU + JRST [ MOVE A,TT ;BEHIND BY MORE THAN SIZE OF BUFFER + SUB A,SYSMPU + MOVEM TT,SYSMPU + LSH A,-3 ;NUMBER OF MESSAGES LOST + PUSHJ P,DINGTTY + PUSHJ P,SYSDPT + MOVEI I,[ASCIZ/ SYS MSGS LOST/] + PUSHJ P,SYSSTD + JRST .+1 ] + MOVEI TT,8 + ADDB TT,SYSMPU + ANDI TT,8_SYSMLNG-1 + ADDI TT,SYSMBF + PUSHJ P,DINGTTY + HLLZ D,(TT) ;GET MODE FLAGS + HRRZ I,(TT) ;GET ASCIZ MSG + HRLI I,440700 +SYSMP0: ILDB T,I + JUMPE T,SYSMP1 + CAIGE T,10 + JRST SYSMP3 + PUSHJ P,STYO + JRST SYSMP0 + +SYSMP1: PUSHJ P,STYOS ;SPACE AND OUTPUT REMAINING ARGS + PUSHJ P,SYSMP2 + JRST SYSTCR ;END WITH TIME, POPJ + JRST SYSMP1 + +SYSMP3: PUSH P,T ;OUTPUT THIS MANY ARGS +SYSMP4: PUSHJ P,SYSMP2 + JFCL + PUSHJ P,STYOS + SOSLE (P) + JRST SYSMP4 + SUB P,[1,,1] + JRST SYSMP0 + +SYSMP2: MOVEI C,0 + LSHC C,3 ;GET A BYTE + JUMPE C,CPOPJ ;NO MORE ARGS TO PRINT + PUSH P,I + MOVE A,1(TT) + PUSHJ P,@SYSMTB(C) + POP P,I + AOJA TT,POPJ1 + +;DISPATCH TABLE FOR SYSTEM MESSAGE PRINTER + +SYSMTB: JRST 4,. ;0 CHECKED FOR END + SYSFWP ;1 FULL WORD OCTAL + SYSDPT ;2 FULL WD DECIMAL + SYSDPC ;3 " WITH COMMAS + SYSCRF ;4 DO CR + CPOPJ ;5 ? + SYSIXP ;6 SIXBIT + [MOVE I,A ;7 ASCIZ + JRST SYSSP] + +;ROUTINE FOR BUGS THAT NEED TO HALT INTO DDT +BUGDD0: HRLI TT,440700 + CONO PI,PIOFF ;PREVENT INTERFERENCE, AND HACK STYO + MOVEM TT,T00POS ;SAVE ADDRESS OF MESSAGE TEMPORARILY + POP P,TT ;RESTORE TT AT TIME OF BUG + POP P,BUGPC ;ADDRESS+1 OF BUG + SKIPE BUGAWF + MOVE P,BUGACS+P ;CORRECT P AT TIME OF BUG + SETZM BUGAWF ;CLEAR FLAG FOR NEXT BUG IN CASE REVIVED + CONI PI,BUGPI ; SAVE PI STATUS + CONI BUGAPR ; SAVE APR STATE +IFE KA10P,[ + CONI PAG,BUGEBR ; SAVE EBR, UBR, ETC + DATAI PAG,BUGUBR +] ;IFE KA10P + SPM BUGPGM ; SAVE PAGER STATE + MOVEM 17,BUGACS+17 ;SAVE ACS + MOVEI 17,BUGACS + BLT 17,BUGACS+16 + MOVE P,BUGPDL ;USE THIS PDL FOR TYPING OUT + PUSH P,T00POS ;RECOVER ASCIZ STRING FOR FLAVOR OF BUG + PUSHJ P,SYSCRF ;CARRIAGE RETURN +BUGDD1: MOVEI A,SCRMSG + PUSHJ P,SYSMPR ;DUMP SYSMSG BUFFER +IFN KA10P,[ + CONSZ TTY,40 ;PUNT IF CHARACTER TYPED + JRST BUGDD2 +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEI A,%DTTYI + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SKIPE DTEF11 ;INPUT TYPED? + JRST BUGDD2 ;YES, PUNT +] ;KL10P +IFN KS10P,[ + SKIPE 8CTYIN ; Any input available? + JRST BUGDD2 ; Yes: Punt. +] ;KS10P + MOVE TT,SYSMPT ;LAST MESSAGE IN + CAMLE TT,SYSMPU ;LAST MESSAGE OUT + JRST BUGDD1 +BUGDD2: MOVE A-1,BUGPI ;CHECK FOR PI IN PROGRESS + ANDI A-1,77400 + LSH A-1,20. + JFFO A-1,[ MOVEI I,[ASCIZ/PI LEVEL /] + PUSHJ P,SYSSP + PUSHJ P,SYSDPT + PUSHJ P,STYOS + JRST .+1 ] + MOVEI I,[ASCIZ/BUG/] + PUSHJ P,SYSSP + POP P,I ;PAUSE OR HALT MESSAGE + SKIPN SYSDBG ;PUNT LONG-WINDED MESSAGE IF DEBUGGING + PUSHJ P,SYSSP + MOVEI I,[ASCIZ/ +YOU ARE NOW IN DDT./] + PUSHJ P,SYSSP + MOVEI TT,[ASCIZ|BUGPC/Q-2/|] + HRLI TT,440700 + MOVEM TT,777777 ;TELL DDT TO EXAMINE BUGHLT ADDRESS + MOVE TT,BUGPC ;ARRANGE FOR P TO JUMP THERE + MOVEM TT,@DDT-6 ;IN OLDER DDT WILL JUST CLOBBER AC0 + MOVSI 17,BUGACS ;RESTORE ACS + BLT 17,17 + CONO PI,PION + JRST DDT + +EBLK + +;DATA AREAS POINTERS AND BUFFER FOR SYS MSG PRINTER + +CTLMAX==55. ;Number of lines after which we should print the date. +CTLCNT: 0 ;Keeps track of number of lines printed on console. + +SYSMPT: 0 ;POINTER TO MESSAGE MOST RECENTLY INSERTED +SYSMPU: 0 ;POINTER TO MESSAGE MOST RECENTLY PRINTED + ;(MUST TAKE MODULO LENGTH OF TABLE, AND ADD OFFSET OF BEGIN OF TABLE) +IFNDEF SYSMLNG,SYSMLNG==5 ;LOG(2) OF # ENTRIES (5=>32) + +SYSMBF: BLOCK 8_SYSMLNG ;8 WDS PER ENTRY: BITS,,STRING, 6 ARGS, TIME + +BUGPC: 0 ;RESTART PC FROM BUG +BUGPI: 0 ; CONI PI,BUGPI +BUGAPR: 0 ; CONI APR,BUGAPR +IFE KA10P,[ +BUGEBR: 0 ; CONI PAG,BUGEBR +BUGUBR: 0 ; DATAI PAG,BUGUBR +];IFE KA10P +IFN 0,[ ;UPGML/UPGMLE not defined yet... +BUGPGM: BLOCK UPGMLE-UPGML ; SPM BUGPGM +] +BUGPGM: BLOCK 8 ;KLUDGE +BUGACS: BLOCK 20 ;AC SAVE AREA FOR BUGDD0 +BUGPDL: -20,,. + BLOCK 20 +T00POS: 0 ;TTY00 HORIZONTAL POSITION + +BBLK + +SUBTTL .SETLOC ROUTINE (DOCUMENT THEN DOES IT) + +SYSSET: MOVE A,SETSLC ;LOCATION TO BE MODIFIED + TLNN A,-1 ;SKIP IF ALREADY DONE + SKIPA C,SETSLQ ;NEW VAL IN SETSLQ + SKIPA C,(A) ;NEW VAL IN LOC + SKIPA D,A ;OLD VAL IN @A + MOVEI D,SETSLQ ;OLD VAL IN SETSLQ + PUSHJ P,SYSSCT ;PRINT OUT DDT-TYPE SEQUENCE + MOVE A,SETSU ;GET USET NAME + PUSHJ P,STYOT ;TYPE OUT A TAB + MOVEI B,0 + PUSHJ P,SYSIXP ;PRINT NAME OF GUILTY PARTY + PUSHJ P,SYSTCR ;STANDARD SYS CARRIAGE RETURN + SKIPGE SETSLC ;IF ALREADY MUNGED AT UUO LEVEL + POPJ P, ;THEN EXIT NOW + MOVE T,SETSLQ ;GET DESIRED VALUE +; SKIPL UMBTS +; JRST SYSSE8 ;DON'T HACK METABITS +; LMB Q,@SETSLC ;GET META BIT OF DESIRED LOCATION +; TRNE Q,1 ;IF 1 THEN HAVE TO MOMENTARILY CLEAR IT +; JRST SYSSE5 +SYSSE8: EXCH T,@SETSLC ;META BIT=0, CHANGE LOCATION +SYSSE6: MOVE Q,SETSLC ;GET ADR OF MUNGED LOC + MOVE A,[-LTSTB,,TSTB] +SYSSE1: MOVE B,(A) + CAIGE Q,(B) + JRST SYSSE3 + HLRE C,B + SETCMM C + ADD C,B + CAILE Q,(C) + JRST SYSSE3 + PUSHJ P,SCKX1 ;UPDATE CKXORS TBL TOO + EQV T,@SETSLC + EQVM T,CKSUMS-TSTB(A) + MOVE T,@SETSLC + PUSHJ P,SCKX1 ;UPDATE TO REFLECT NEW CONTENTS +SYSSE2: MOVSI A,SCLSET + ANDCAM A,SUPCOR + CAIE Q,SYSDBG ;IF NOT DEBUG SWITCH + POPJ P, ;EXIT + PUSHJ P,DBGINT ;SYSDBG STATE CHANGE, TELL ALL USERS + SKIPE SYSDBG + JUMPN T,CPOPJ +;SYSDBG CLEARED, GIVE "IN OPERATION" MESSAGE BY DROPPING INTO ISYS +;HERE WHEN SYSTEM IS UP AND DISKS HAVE BEEN INITIALIZED +;RE-ENTER HERE WHEN SYSDBG STATE CHANGED +ISYS: PUSHJ P,DATIME ;MAY BE ABLE TO FIND TIME IMMEDIATELY (ONCE MFD IN) + PUSHJ P,TTTMN2 ;MAKE SURE WE THINK THAT ALL TERMINET + ;MOTORS ARE OFF, SO WE'LL TRY TO TURN THEM ALL ON WHEN WE TYPE + ;"ITS IN OPERATION" ON THEM. + PUSHJ P,TTRSAL ;SEND %TDORS TO ALL SOFTWARE TTYS + SRITYP [IN OPERATION] + SKIPE SYSDBG ;IF SYS IN DEBUG MODE +DMESSG: SRITYP [BEING DEBUGGED] ;SET TO APPROP MSG + PUSHJ P,SYALCP ;PRINT ON ALL CONSOLES +SCMESG: SRITYP [SYSTEM JOB USING THIS CONSOLE.] + PUSHJ P,SYSSP ;PRINT ON SYS JOB CONSOLE + SKIPGE DMLLDF ;START DRAGON (DAEMON) IF WANTED + SKIPL DMON+1 ;AND NOT DONE ALREADY + POPJ P, + HRROI T,DMON + CONO PI,UTCOFF + PUSHJ P,NUJBST + BUG ;SHOULD BE ROOM IN REQUEST BUFFER + JRST UTCONJ + +SYSSE3: AOBJN A,SYSSE1 + JRST SYSSE2 + + ;SETLOC ROUTINE TO MODIFY LOCATION WITH META BIT = 1 + +;SYSSE5: MOVEI D,0 +; SMB D,@SETSLC +; EXCH T,@SETSLC +; SMB Q,@SETSLC +; JRST SYSSE6 + +SUBTTL MEMORY ERROR MESSAGES + +NXMTYP: MOVEI I,[ASCIZ /NON-EX MEM ERROR #/] + MOVEI TT,1 + JRST MEMTYP + +IFE KA10P,[ +BPFTYP: MOVEI I,[ASCIZ /PAGE FAIL ERROR #/] + MOVEI TT,2 + JRST MEMTYP +] ;IFE KA10P + +PARTYP: MOVEI I,[ASCIZ /PARITY ERROR #/] ;PARITY ERROR + MOVEI TT,0 +MEMTYP: PUSHJ P,SYSSP + MOVE A,PARERR(TT) + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ /, PC = /] + PUSHJ P,SYSSP + MOVE A,PARPC(TT) + PUSHJ P,SYSFWP + MOVEI I,[ASCIZ /, JOB # /] + PUSHJ P,SYSSP + MOVE A,PARUSR(TT) + IDIVI A,LUBLK + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ /, USR:/] + PUSHJ P,SYSSP + MOVE D,PARUSR(TT) + MOVE A,UNAME(D) + PUSHJ P,SYSSIX + PUSHJ P,STYOS + MOVE A,JNAME(D) + PUSHJ P,SYSSIX + JRST @.+1(TT) ;DISPATCH ON TYPE OF ERROR + PARTY2 ;PARITY + SYSTCR ;NXM +IFE KA10P,[ + BPFTY2 ;BPF + +BPFTY2: MOVEI I,[ASCIZ /, PFW = /] + PUSHJ P,SYSSP + MOVE A,BPFPFW + PUSHJ P,SYSFWP + JRST SYSTCR +] ;IFE KA10P + +PARTY2: PUSHJ P,SYSTCR +IFN KS10P,[ + MOVEI I,[ASCIZ /ERR ADDR = /] + PUSHJ P,SYSSP + MOVE T,PARERA ; Error address is all we collect on the KS. + PUSHJ P,SYSP + PUSHJ P,SYSCRF +] ;KS10P +IFN KL10P,[ + SKIPN PARRSN + JRST PARTP1 + MOVEI I,[ASCIZ /ERR ADDR = /] + PUSHJ P,SYSSP ;PAR ERR INT ALWAYS GIVES ERR ADDR + MOVE T,PARERA + JRST PARTP2 + +PARTP1: MOVEI I,[ASCIZ /PFW = /] + PUSHJ P,SYSSP ;PAR ERR TRAP GIVES PFW AND BAD DATA + MOVE T,PARPFW ;EVEN IF SCAN DOESN'T FIND PAR ERRS. + PUSHJ P,SYSP + MOVEI I,[ASCIZ /, BAD DATA = /] + PUSHJ P,SYSSP + MOVE T,PARWRD +PARTP2: PUSHJ P,SYSP + PUSHJ P,SYSCRF +] ;KL10P + SOSGE D,PARCNT + POPJ P, + JUMPE D,PARTP3 ;IF SCAN FOUND MORE THAT ONE PAR ERR, + ;PRINT AND'S AND OR'S OF DATA AND ADDRS. +IRP X,,[PARAAN,PARAOR,PARAND,PARIOR]Y,,[ADDR AND,ADDR IOR,DATA AND,DATA IOR] +IFE .IRPCNT&1, MOVEI I,[ASCIZ /Y = /] +.ELSE MOVEI I,[ASCIZ /, Y = /] + PUSHJ P,SYSSP + MOVE T,X + PUSHJ P,SYSP +IFN .IRPCNT&1, PUSHJ P,SYSCRF ;PRINT TWO ITEMS PER LINE. +TERMIN +PARTP3: MOVEI I,[ASCIZ /PARITY ERRORS: +/] + PUSHJ P,SYSSP +SYSPR1: PUSHJ P,STYOT ;TYPE TAB + MOVE A,PARADR(D) + PUSHJ P,SYSFWP + PUSHJ P,STYOT + MOVE A,PARCON(D) + PUSHJ P,SYSFWP + PUSHJ P,SYSCRF + SOJGE D,SYSPR1 + AOS D,PARCNT + MOVEI I,[ASCIZ/ .../] + CAIN D,MXPARS + PUSHJ P,SYSSP ;NOT ALL PARITY ERRORS WERE PRINTED + JRST SYSCRF + +SUBTTL LOGIN & MISCELLANEOUS MESSAGES + +SYSLGI: SKIPE SUPPLG + POPJ P, ;DON'T BOTHER PRINTING MESSAGE + HLRZ I,SLGIV+1 ;Message (CHUNAME, LOGIN, etc) + PUSHJ P,SYSSP + MOVEI TT,SLGIV ;.LOGIN + MOVE A,(TT) + CAMN A,[-1] + BUG + PUSHJ P,SYSG23 + SKIPE A,SLGIV+2 + PUSHJ P,SYSSIX + JRST SYSTCR + +SYSG23: PUSHJ P,SYSIXP + PUSHJ P,STYOS + HRRZ A,1(TT) ;PICK UP TTY NUM + JRST SYSOPT + +;PRINT A MESSAGE WHEN SOMEONE WRITES ON SYS. +SYSWRT: MOVE A,SWUNAM ;WRITE ON SYS DEVICE + PUSHJ P,SYSIXP + MOVE A,SWJNAM + PUSHJ P,SYSSIX + MOVE A,SWFN3 ;SNAME - SYS,SYS1, ... + PUSHJ P,SYSSIX + MOVE A,SWFN1 + PUSHJ P,SYSSIX + MOVE A,SWFN2 + PUSHJ P,SYSSIX + MOVE A,[SIXBIT /WRITE/] ;Assume luser was writing. + MOVE B,SWMOD ;Check opcode. + CAIN B,2 ;MLINK? + MOVE A,[SIXBIT /LINK/] ; Yup. + CAIN B,4 ;Maybe DELE/WO, RENAM/WO? + MOVE A,[SIXBIT /DELRNM/] ; Yah, hmmhmmm. +SYSWR3: PUSHJ P,SYSSIX + JRST SYSTCR + +SUBTTL DETERMINE AND PRINT THE DATE AND TIME + +EBLK +DATIME: JRST .+1 ;RH MODIFIED TO REFLECT PROGRESS +BBLK ;ROUTINE CALLED BY PUSHJ, + ;BIT SET EVERY SECOND FROM SUPCOP UNTIL + ;THE DATE IS KNOWN. + MOVSI T,40000 ;"MFD IN" BIT IN QMDRO + CONO PI,UTCOFF ;DISABLE INTERRUPTS + TDNE T,QMDRO ;SEE IF DIRECTORY IN + JRST UTCONJ ;NOT IN + ;MFD IN, GET CRUD FROM IT + MOVE A,QMDRO ;GET ORIGIN OF MFD + SKIPE B,MDYEAR(A) ;YEAR + MOVEM B,FYEAR + SKIPE C,MPDOFF(A) ;PDTIME OFFSET + MOVEM C,PDTIME + MOVEI C,DATIM0 + HRRM C,DATIME + JRST UTCONJ + +DATIM0: PUSHJ P,GLPDTM ;NOW SEE IF IT'S ALL THERE + JRST DATIM2 ;NOT ALL THERE, DOCUMENT WHAT'S MISSING + JRST DATIM6 ;ALL THERE, TYPE OUT AND CLEAR SUPCOR BIT + + ;NOT ALL THERE, DOCUMENT (TYPE OUT) WHAT IS MISSING + ;SHOULD NOT BE NECESSARY TO WARM UP TTY + +DATIM2: +IFN PDCLKP,[ + DATAI PDCLK,A ;SEE IF CLOCK ON + JUMPN A,DATIM3 ;JUMP IF CLOCK WINNING + MOVEI I,[ASCIZ /DECORIOLIS CLOCK HAS BEEN POWERED OFF, IF THE TIME +CANNOT BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET +/] + MOVEI T,500. + SOJG T,. ;WAIT AND BE SURE + DATAI PDCLK,A ;GET DATAI AGAIN + JUMPN A,DATIM3 ;JUMP IF OK NOW + PUSHJ P,SYSSP ;COMPLAIN +] ;PDCLKP +IFN KS10P,[ + RDTIM A ; Clobbers B + TLC A,1729. ; "A most interesting number" + TLNN A,-1 ; If present, KS-10 clock still remembers the time. + JRST DATIM3 + MOVEI I,[ASCIZ /THE KS-10 CLOCK HAS BEEN RESET, IF THE TIME CANNOT +BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET +/] + PUSHJ P,SYSSP ; Complain +] ;KS10P +DATIM8: +; HRROI T,CCTSS ;NOW PREPARE TO LOAD CTSS CALLER FROM SYS:@ CCTSS +; PUSHJ P,NUJBST ;DO A PSEUDO-CONTROL Z +; JRST DATIM7 +DATIM3: MOVEI C,0 ;COUNTER OF THINGS MISSING FROM MFD + MOVEI I,[ASCIZ /YEAR, /] + SKIPG FYEAR ;CHECK YEAR + PUSHJ P,[AOJA C,SYSSP] ;NOT IN, COMPLAIN +IFN PDCLKP\KS10P,[ + MOVEI I,[ASCIZ /PDTIME OFFSET, /] + SKIPN PDTIME + PUSHJ P,[AOJA C,SYSSP] ;PDTIME OFFSET NOT IN +] ;PDCLKP\KS10P + JUMPE C,DATIM4 ;SKIP FOLLOWING IF EVERYTHING ON DISK + MOVEI I,[ASCIZ /NOT ON DISK. +PLEASE SETLOC APPROPRIATELY. +/] + PUSHJ P,SYSSP +DATIM4: SKIPA T,[DATIM5];UPDATE DATIME TO WAIT FOR EVERYTHING TO BE THERE +DATIM7: MOVEI T,DATIM8 ;UPDATE DATIME TO WAIT FOR ABILITY TO DO + ; PSEUDO-CONTROL Z FOR CTSS CALLER + HRRM T,DATIME + POPJ P, + + ;WAIT FOR EVERYTHING TO BE THERE + ;THEN TYPE OUT "IT IS NOW...", ETC. + +DATIM5: PUSHJ P,GLPDTM ;CHECK IT + POPJ P, ;NOT ALL THERE YET + MOVEI T,DATIME+1 ;ALL THERE, RE-INITIALIZE DATIME + HRRM T,DATIME +DATIM6: MOVSI T,SCLDAT ;STOP CALLING DATIME EVERY SECOND + ANDCAM T,SUPCOP ;NOW THAT THE WORK IS DONE. + HRRZS TIMOFF ;START UP SLOW CLOCK REAL-TIME ROUTINE + SETZM RSWTIM ;Initialize the resource-warning timestamp. + PUSHJ P,WARMTT ;WARM UP TTY + PUSHJ P,RYEAR1 ;GET DAY OF WEEK IN RELEVANT FIELD OF E +SYSNWP: MOVEI I,[ASCIZ /IT IS NOW /] + PUSHJ P,SYSSP ;TYPE IT OUT + IDIVI A,SPD ;A HAS RESULT OF PUSHJ TO GLPDTM + PUSH P,A ;SAVE DAY OF YEAR + MOVE A,B ;GET # SECS SINCE MIDNIGHT IN A + IDIVI A,SPD/2 ;GET AM/PM BIT IN A, 12 HOUR TIME (SECS) IN B + PUSH P,[SIXBIT / AM PM/](A) ;REMEMBER WHAT HALF-DAY + CAIGE B,3600. ;USE 12:01 RATHER THAN 0:01 IN 12-HR TIME. + ADDI B,12.*3600. + PUSHJ P,RTIME ;CONVERT TIME TO SIXBIT + MOVE B,A + TLNN B,170000 ;IF LEADING DIGIT IS ZERO, + TLZ B,770000 ;THEN TURN IT INTO A BLANK + PUSHJ P,SYSTCD ;TYPE OUT TIME + POP P,B ;RESTORE AM OR PM WORD + PUSHJ P,SYS6 ;TYPE IT OUT + MOVE B,[SIXBIT / EST,/] + TLNE E,100000 ;DST BIT + HRLI B,(SIXBIT / ED/) ;DAYLIGHT SAVINGS TIME, TYPE OUT EDT INSTEAD OF EST + PUSHJ P,SYS6 ;TYPE IT OUT + PUSHJ P,STYOS ;TYPE A SPACE + LDB B,[320300,,E] ;GET DAY OF WEEK (0 => SUNDAY) + MOVE B,DOWTBL(B) ;MON, TUES, WEDNES, ETC. (IN SIXBIT) + PUSHJ P,SYS6 ;TYPE IT OUT + MOVEI I,[ASCIZ /DAY, /] ;FINISH ON DAY OF WEEK + PUSHJ P,SYSSP ;" " " + POP P,A ;RESTORE DAY OF YEAR + PUSHJ P,RDATE1 ;CALCULATE MONTH AND DAY + MOVE B,NMNTBL-1(B) ;GET SIXBIT FOR MONTH + PUSHJ P,SYS6 ;TYPE OUT MONTH + PUSHJ P,STYOS ;TYPE A SPACE + MOVE A,C ;GET DAY OF MONTH IN A + PUSHJ P,SYSDPT ;TYPE OUT IN DECIMAL + MOVEI T,", + PUSHJ P,STYO ;TYPE A COMMA + MOVEI A,(E) ;GET YEAR + PUSHJ P,SYSDPT ;TYPE IT OUT + JRST SYSCRF ;END WITH CRLF + + ;TABLE OF NAMES OF MONTHS (FIRST THREE LETTERS, IN SIXBIT) + +NMNTBL: MNIRP [SIXBIT /M/] + + ;TABLE OF SIXBIT NAMES FOR DAYS OF THE WEEK + ;(THE "DAY" ON THE END LEFT OFF) + +DOWTBL: IRPS D,,[SUN MON TUES WEDNES THURS FRI SATUR] + SIXBIT /D/ + TERMIN +IFN .-DOWTBL-7,.ERR BARF AT DOWTBL + +SUBTTL NETWORK UP/DOWN + +SYSNET: +IFE IMPP,JRST SCOR +IFN IMPP,[ + MOVE A,IMERCN ;Get error status + CAME A,[-1] ;--1 means IMP cycled by user + SKIPA I,[[ASCIZ /IMP CRASHED, STATUS=/]] + MOVEI I,[ASCIZ /IMP cycled by user at/] + PUSHJ P,SYSSP ;Print string + MOVE A,IMERCN ;Get IMP error code back + CAME A,[-1] + PUSHJ P,SYSFWP ;Print status if error + PUSHJ P,SYSTCR ;Time, CRLF + SETOM IMERCN ;Reset error status + MOVE A,LNETIM ;Last time net was initted + SUB A,TIME ;A will be positive if net was last + ADDI A,30.*30. ; initted less than 30 sec ago. + PUSH P,A ;Flag for SYSNT5. + means don't restart IMP + MOVNI A,2 ;Say we are coming up, but no PI action yet, + MOVEM A,IMPUP ; and prevent new net openers. IMPUP may + PUSHJ P,SYSNT5 ; not already be -1 if got here via LOCK/NET + JRST SCOR ;Reset net, then back to main loop + +;Reset net, and potentially restart IMP +; Try restarting if IMP ready and -1(P) is negative. +; +;IMPUP is -1 so no new opens can happen. + +SYSNT5: + ;PCLSR those users running in OPEN. + ; + MOVEI U,0 +IFN NCPP,[ + PUSHJ P,LSTSTP ;PCLSR all users in .OPEN + NETLST + MOVSI I,-IMPSTL +SYSNT2: SKIPL A,IMSOC1(I) + JRST SYSNT1 + HRRZS A + SKIPN UNAME(A) + JRST SYSNT1 + MOVE T,APRC(A) + TLNE T,BULGO ;Tree is being deleted anyway. + JRST SYSNT1 + PUSHJ P,IFSTOP ;Stop network user + PUSHJ P,CHSCAA + PUSHJ P,SYSNT3 ;Hack IOCHNM words of net user +SYSNT1: AOBJN I,SYSNT2 +];NCPP + + ;Disconnect all STYs from the network + ; + MOVEI I,NFSTTY+NSTTYS-1 +SYSNT6: + PUSHJ P,NSTYN0 + JFCL + CAILE I,NFSTTY + SOJA I,SYSNT6 + +IFN NCPP,[ + ;Clean up connections which were closing + ; + CONO PI,UTCOFF + MOVSI I,-IMPSTL +SYSNT7: SKIPL H,IMSOC1(I) + JRST SYSNT4 + PUSHJ P,IMPBRT ;RETURN BUFFER + TLNN H,200000 ;IN PROCESS OF CLOSING? + JRST SYSNT4 ;NO, IGNORE + SETZM IMSOC1(I) ;FLUSH SOCKET + SOS IMNCS ;DECREASE COUNT OF CLOSES IN PROCESS +SYSNT4: AOBJN I,SYSNT7 ;LOOP THRU ALL SOCKETS + SKIPE IMNCS ;SKIP IF 0 MORE CLOSES + BUG PAUSE,DEC,IMNCS,[NET CHANNELS NOT CLOSED YET] + CONO PI,UTCON +];NCPP + + ;Maybe try to bring the IMP up again + ; + MOVEI U,0 + SKIPG -1(P) ;If last time down was < half minute ago, + CALL IMPCKR ; or IMP ready line is not set, + JRST LSWCLR ; then don't try to bring it up again + PUSHJ P,IMPINI +IFN NCPP,PUSHJ P,LSWCLR ;Restart old network users + PUSHJ P,WARMTTY + MOVEI I,[ASCIZ /IMP up again./] + JRST SYSSTD ;Print and return + +IFN NCPP,[ +SYSNT3: HRRZ C,(R) + CAIL C,NETDUI + CAILE C,NETDBO + POPJ P, ;NOT A NETWORK CHANNEL + HLRE C,(R) ;SOCKET MAP INDEX + JUMPL C,CPOPJ + HRROS (R) ;SET LH OF IOCHNM TO -1 + HRRZ C,R + SUBI C,IOCHNM(A) + CAIL C,20 + POPJ P, ;ON IOPDL + MOVE C,CHNBIT(C) + AND C,MSKST2(A) + IORM C,IFPIR(A) ;INTERRUPT USER + POPJ P, +];NCPP +];IMPP + +;Try to bring IMP up if desirable +SYSIMU: +IFE IMPP,POPJ P, ;No IMP, no work +IFN IMPP,[ + SKIPGE IMPTCU ;Already trying to come up? + POPJ P, ;Yes, no meddling needed + CALL IMPCKR ;Check if IMP ready line is now + JRST [ SETZM IMPTCU ;IMP not ready, we are down and not trying + POPJ P, ] ; to come up. Give up now + PUSH P,[-1] ;Force SYSNT5 to try and restart IMP if called + SKIPGE IMPUP ;Do this only if imp is temporarily down. + PUSHJ P,SYSNT5 ;Reset world, restart IMP + JRST POP1J ;Clean up and exit +];IMPP + +; PUSHJ P,LSTSTP +; LIST ;WHERE LIST/ +;STOPS ALL JOBS ON THE LIST, AND PUT THEM ON OUR LSWPR. +;LIST SHOULD BE LINKED THROUGH THE RH, AND EACH WORD IN THE LIST SHOULD BE +;IN THE USER VAR BLOCK OF SOME JOB. THAT JOB IS CONSIDERED TO BE ON THE LIST. +;0 IN THE RH MEANS NIL. +LSTSTP: MOVE T,@(P) ;POINTER TO FIRST ELEMENT OF LIST + CONO PI,CLKOFF + MOVE T,(T) +LSTST1: HRRZS T + SKIPN A,T ;ADDRESS OF LSWB BLOCK + JRST CLKOJ1 + MOVEI A,-USRSTG(A) + IDIVI A,LUBLK + IMULI A,LUBLK ;USER INDEX + PUSH P,(T) + PUSHJ P,IFSTOP ;STOP USER, ADDING HIS USTP TO OUR LSWPR + POP P,T + JRST LSTST1 + SUBTTL SYSTEM JOB TYPE-OUT ROUTINES + +;PRINT "/ <@D> " IN OCTAL. +;USED BY SYSSET. CLOBBERS A,B,T. +SYSSCT: HRRZS A + PUSHJ P,SYSOPT + MOVEI T,"/ + PUSHJ P,STYO + PUSHJ P,STYOT ;TAB + MOVE A,(D) ;GET CURRENT VALUE + PUSHJ P,SYSFWP + PUSHJ P,STYOT + MOVE A,C ;GET NEW VALUE + JRST SYSFWP + +;STRING <- I, SPACE, TIME AND CRLF. +;CLOBBERS A THRU E AND T. +SYSSTD: PUSHJ P,SYSSP + +;SPACE, TIME AND CRLF. +;CLOBBERS A THRU E AND T. +SYSTCR: PUSHJ P,SYSTPT + +;TYPE A CRLF. CLOBBERS T. +SYSCRF: SOS CTLCNT ;Countdown number of lines printed. + MOVEI T,15 + PUSHJ P,STYO + MOVEI T,12 + JRST STYO + +SYSTPT: PUSHJ P,STYOS ;TYPE SPACE, TIME + CONSZ PI,200 ;IF IN BUGDD0, MUSTN'T CALL GLPDTM + PUSHJ P,GLPDTM + POPJ P, ;TIME NOT KNOWN + IDIVI A,SPD + PUSHJ P,RTIME ;CONVERT TO SIXBIT. + MOVE B,A ;DROP INTO SYSTCD + +SYSTCD: LDB A,[301400,,B] + PUSHJ P,SYSTWR + LDB A,[141400,,B] + PUSHJ P,SYSTWR + MOVE I,[140600,,B] + JRST SYSIX2 + +;PREPARE FOR TYPING OUT A MESSAGE ON THE CONSOLE TTY. CALL HERE BEFORE +;STARTING TO TYPE A LINE, IF THERE IS A CHANCE THAT SYS JOB MIGHT JUST +;BE STARTING TO TYPE AFTER A PERIOD OF SILENCE. +WARMTTY:PUSHJ P,SYSCOP ;GET SYSTEM TTY READY TO USE + .IOT STYOC,[^P] ;ADVANCE TO FRESH LINE + .IOT STYOC,["A] +WARMT2: +IFN 1, POPJ P, +.ELSE [ MOVE T,SYSCN + MOVE T,TTLTM(T) ;DON'T DO THIS IF THERE'S BEEN ACTIVITY IN 2 MINUTES. + ADDI T,115.*30. + CAML T,TIME + POPJ P, + PUSH P,[[MOVEI T,^H + JRST WARMT1]] + SKIPA T,[175] ;WARM UP TELETYPE (ONLY ON AI-KA FOR NOW) +];END .ELSE +DINGTTY: SKIPA T,[^G] ;DING DING +WARMT1: PUSHJ P,.+1 + PUSHJ P,.+1 + JRST STYO + +;ROUTINE TO "OPEN" A CHANNEL TO THE SYSTEM CONSOLE +;IT'S DONE THIS WAY SO THAT THE CONSOLE CAN STILL BE +;USED AS A USER CONSOLE WHEN NECESSARY. SYSTEM JOB +;MESSAGES WILL JUST COME OUT FROM TIME TO TIME. + +SYSCOP: HRLZ T,SYSCN ;FAKE UP AN IOCHNM WORD + ADD T,[%TJDIS+%TJMOR,,TYODN] + SKIPGE SYSCN + MOVEI T,NLODN ;IF NO SYS TTY AVAIL, USE NUL DEVICE + MOVEM T,IOCHNM+STYOC + POPJ P, + +;TYPE OUT THE SIXBIT WORD IN B, QUIT WHEN WHAT IS LEFT IS BLANK +SYS6: JUMPE B,CPOPJ ;RETURN WHEN NOTHING LEFT + MOVEI A,0 ;INITIALIZE FOR LSH + LSHC A,6 ;SHIFT A CHARACTER IN + MOVEI T,40(A) ;CONVERT TO SIXBIT AND GET IN T + PUSHJ P,STYO ;TYPE OUT THE CHARACTER + JRST SYS6 ;LOOP BACK FOR NEXT CHARACTER + +;PRINT A MESSAGE ON ALL FREE CONSOLES. 40 SET IN LH(I) => IT IS ADDR OF ROUTINE; +;ELSE IT IS ADDR OF AN ASCIZ STRING TO BE TYPED FOLLOWED BY THE TIME AND A CRLF. +SYALCP: TLNN I,40 + HRLI I,440700 ;SYSTEM ALL CONSOLES PRINT + MOVEI A,0 +SYALC1: PUSHJ P,SYSTSU + AOJA A,SYALC3 + TLNE I,40 + JRST SYALC5 + MOVE Q,I ;SO NOT TO MUNG I UNTIL END +SYALC2: ILDB E,Q + JUMPE E,SYALC4 ;JUMP IF DONE + .IOT STYOC,E ;COPY CHARACTER + JRST SYALC2 ;GO GET NEXT CHARACTER + +SYALC5: PUSH P,I + PUSH P,A + PUSHJ P,(I) + POP P,A + POP P,I +SYALC6: MOVSI E,%TACFM + IORM E,TTYSTA(A) ;DONT NEED CONSOLE FREE MSG ANY MORE + AOS A ;INCREMENT CONSOLE NUMBER +SYALC3: CAIGE A,NCT+IFN N11TYS,[1-N11TYS] ;IF MORE CONSOLES LEFT, + JRST SYALC1 ;THEN PRINT OUT ON NEXT ONE + JRST SYSCOP ;FINALLY RE-OPEN SYSTEM CONSOLE. + +SYALC4: PUSH P,[SYALC6] ;PUT TIME AT END OF MESSAGE + PUSH P,A ;IF WE KNOW WHAT TIME IT IS + PUSH P,B + PUSHJ P,GLPDTM + JRST POPBAJ + PUSH P,I + IRPC A,,[ AT] + .IOT STYOC,["A] ;PUT TIME IN UP/DOWN MESSAGES + TERMIN + PUSHJ P,SYSTPT + POP P,I + JRST POPBAJ + +SYSTSU: CONO PI,TTYOFF + MOVE T,TTYSTA(A) + TLZN T,%TACFM + JRST TTYONJ ;IN USE OR WILL GET CONSOLE FREE MSG => DON'T HACK IT + MOVEM T,TTYSTA(A) + CONO PI,TTYON + AOS (P) ;TTY NEEDS HACKING, SO SKIP. + HRLZ T,A + ADD T,[%TJDIS+%TJMOR,,TYODN] + MOVEM T,IOCHNM+STYOC ;"OPEN" THE CHANNEL. +SYSTS1: MOVE T,TTYOPT(A) + TLNN T,%TOIML + TLNN T,%TOMVU + POPJ P, ;IMLAC OR PRINTING TTY, DON'T CLEAR. + MOVEI T,^P + PUSHJ P,STYO + MOVEI T,"C + JRST STYO + + ;SYSTEM JOB RADIX PRINT-OUT ROUTINES + ;FULL WORD (TWO HALFWORD) OCTAL: +SYSFWP: TLNN A,-1 ;IF LH=0, + JRST SYSOPT ;THEN PRINT ONLY RH + LSHC A,-18. + HLLM B,(P) + PUSHJ P,SYSOPT + HLRZ A,(P) + MOVEI T,", ;",," BETWEEN HALFWORDS + PUSHJ P,STYO + PUSHJ P,STYO + + ;OCTAL PRINTOUT, NO LEADING ZEROS, HALFWORD MAXIMUM +SYSOPT: IDIVI A,10 + JUMPE A,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSOPT +SYSRP2: HLRZ B,(P) ;ENTRY POINT FROM DECIMAL TYPEOUT ROUTINE +SYSRP1: MOVEI T,"0(B) ;" " " + JRST STYO + + ;DECIMAL PRINTOUT, COMMAS EVERY 3 DIGITS, FULLWORD MAXIMUM +SYSDPC: MOVE 0,A ;ROUTINE EXPECTS ARGUMENT IN A, CLOBBERS 0, A(=0+1), B(=A+1) +SYSDP5: IDIVI 0,1000. ;GET LEAST SIGNIFICANT 3 DIGITS IN A + JUMPE 0,SYSDPT ;PRINT HIGH ORDER DIGITS WITHOUT LEADING ZEROES + HRLM A,(P) + PUSHJ P,SYSDP5 + HLRZ A,(P) + MOVEI T,", ;SINCE 3*N DIGITS LEFT TO BE TYPED, N>0, + PUSHJ P,STYO ;PRINT OUT A COMMA + MOVEI T,3 ;NUMBER OF DIGITS TO PRINT OUT + ;ROUTINE TO PRINT OUT AS MANY DECIMAL DIGITS AS SPECIFIED IN T +SYSLZP: IDIVI A,10. + SOJLE T,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSLZP + JRST SYSRP2 + +;PRINT NUMBER IN A IN DECIMAL; CLOBBERS B, T. +SYSDPT: IDIVI A,10. + JUMPE A,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSDPT + JRST SYSRP2 + +STYOQ: MOVEI T,"? ;TYPE OUT "?" + JRST STYO + +STYOT: SKIPA T,[11] ;TAB +STYOS: MOVEI T,40 ;TYPE OUT A SPACE +STYO: CONSO PI,200 ;PI ON? (SYSTEM UP) + JRST STYO1 + .IOT STYOC,T + POPJ P, + +;TYPE OUT DIRECTLY WHILE SYSTEM IS NOT RUNNING +STYO1: HRLM T,(P) + CAIN T,15 + SETZM T00POS + AOS T,T00POS + CAIL T,75. + PUSHJ P,SYSCRF + HLRZ T,(P) +IFN KA10P,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,T +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEM T,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] ;KL10P +IFN KS10P,[ + ANDI T,177 ; ASCII for the 8080 + IORI T,400 ; Means a character is present + MOVEM T,8CTYOT + CONI T + IORI T,80INT + CONO (T) ; punch 8080 + SKIPE 8CTYOT ; wait for completion + JRST .-1 + HLRZ T,(P) ; God knows who might look at T... +] ;KS10P + POPJ P, + +;PRINT WORD IN I AS 12. OCTAL DIGITS. CLOBBERS J,T. +SYSP: MOVE J,[440300,,I] + MOVE I,T +SYSP1: ILDB T,J + ADDI T,"0 + PUSHJ P,STYO + TLNE J,770000 + JRST SYSP1 + POPJ P, + +SYSSP: HRLI I,440700 ;ENTRY TO TYPE C(I) AS A POINTER TO ASCIZ +SYSSP2: ILDB T,I + JUMPE T,CPOPJ + PUSHJ P,STYO + JRST SYSSP2 + +SYSTWR: LSH A,30-18. + ADDI A,(SIXBIT / :/) + MOVE I,[220600,,A] + JRST SYSIX2 +SYSSIX: PUSHJ P,STYOS ;TYPE A SPACE AND FALL IN +SYSIXP: MOVE I,[440600,,A] ;ENTRY TO TYPE OUT C(A) AS SIXBIT +SYSIX2: ILDB T,I + ADDI T,40 + PUSHJ P,STYO + TLNN I,770000 + POPJ P, + JRST SYSIX2 diff --git a/src/system/t20mac.1 b/src/system/t20mac.1 new file mode 100755 index 00000000..b8616e2a --- /dev/null +++ b/src/system/t20mac.1 @@ -0,0 +1,345 @@ +;Random useful coding macros. GZ@OZ developed MACSYM.MID based on the +;Twenex monitor macro collection MACSYM.MAC - this is a non-Twenex-specific +;subset of that. + +;Stuff supported (will add more stuff as need arises): +; FLD(VAL,MSK) & BIT(n) & POINT SIZE,ADDR,OFFSET +; MOVX AC,MASK & TXxx AC,MASK & JXx AC,MASK,ADDR & LOAD/STOR AC,MASK,ADDR +; DO./ENDDO. macros (and related stuff) +; IFxxx/ANxxx macros +; SAVEACS [A,B,C,D] & SAVE. [LOC,LOC,LOC] + + +.KILL ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3,TOP. +.XCREF ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3 +.XCREF ..DX,..IX,..EX,.SAVX1,.SAVX2 + +IF2,.INEOF ;Don't bother if no code + +;.NSTGW ;No storage words in this part + +DEFINE FLD (VAL,MASK) +<.DPB ,<.BP ,>,0>TERMIN + +DEFINE BIT (N) +<1_<35.->>TERMIN + +DEFINE POINT SIZE=7,ADDR=0,COUNT=0 +RADIX 8+2 +..X1==SIZE +..X2==COUNT +RADIX 8 +..XX==<..X2-1>/<36./..X1> +..X2==..X2-..XX*<36./..X1> +<<<36.-<..X1*..X2>>_30.>+<..X1_24.>++..X1> +TERMIN + +;MOVX - LOAD AC WITH CONSTANT + +DEFINE MOVX AC,#MSK + IFE <-1,,0>&MSK,[MOVEI AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[MOVSI AC,(MSK)] + .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[HRROI AC,MSK] + .ELSE [IFE <<0,,-1>&MSK>-<0,,-1>,[HRLOI AC,(MSK&.LHALF)] + .ELSE [MOVE AC,[MSK]]]]] +TERMIN + +;TX - TEST MASK + +IRP OP,,[N,NA,OE,ON,OA,ZE,ZN,ZA,CE,CN,CA] + DEFINE TX!OP AC,#MSK + IFE <-1,,0>&MSK,[TR!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)] + .ELSE [TD!OP AC,[MSK]]] + TERMIN +TERMIN + +IRP OP,,[N,E] + DEFINE TXN!OP AC,#MSK + IFE <-1,,0>&MSK,[TRN!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TLN!OP AC,(MSK)] + .ELSE [IFE MSK+1,[CAI!OP AC,0] + .ELSE [TDN!OP AC,[MSK]]]] + TERMIN +TERMIN + +..TXZ==ANDI +..TXO==ORCMI +..TXC==EQVI +IRP OP,,[Z,O,C] + DEFINE TX!OP AC,#MSK + IFE <-1,,0>&MSK,[TR!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)] + .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[..TX!OP AC,-1#MSK] + .ELSE [TD!OP AC,[MSK]]]] + TERMIN +TERMIN + +EQUALS IORX,TXO +EQUALS XORX,TXC + +DEFINE ANDX AC,#MSK +TXZ AC,-1#MSK +TERMIN + + SUBTTL JX -- JUMP ON MASK + +;JXE -- JUMP IF MASKED BITS ARE EQUAL TO 0 +;JXN -- JUMP IF MASKED BITS ARE NOT EQUAL TO 0 +;JXO -- JUMP IF MASKED BITS ARE ALL ONES +;JXF -- JUMP IF MASKED BITS ARE NOT ALL ONES (FALSE) + +DEFINE JXE AC,#MSK,?ADR + IFE MSK-.MINFI,[JUMPGE AC,ADR] + .ELSE [IFE MSK+1,[JUMPE AC,ADR] + .ELSE [TXNN AC,MSK + JRST ADR]] +TERMIN + +DEFINE JXN AC,#MSK,?ADR + IFE MSK-.MINFI,[JUMPL AC,ADR] + .ELSE [IFE MSK+1,[JUMPN AC,ADR] + .ELSE [TXNE AC,MSK + JRST ADR]] +TERMIN + +DEFINE JXO AC,#MSK,?ADR + IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXN AC,MSK,ADR] + .ELSE [TXC AC,MSK + TXCN AC,MSK + JRST ADR] +TERMIN + +DEFINE JXF AC,#MSK,?ADR +IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXE AC,MSK,ADR] +.ELSE [TXC AC,MSK + TXCE AC,MSK + JRST ADR] +TERMIN + +;LOAD, STOR +DEFINE LOAD AC,#MSK,?LOCN + IFE MSK+1,[MOVE AC,LOCN] + .ELSE [IFE MSK-777777,[HRRZ AC,LOCN] + .ELSE [IFE MSK-<-1,,0>,[HLRZ AC,LOCN] + .ELSE [LDB AC,[.BP MSK,LOCN]]]] +TERMIN + +DEFINE STOR AC,#MSK,?LOCN + IFE MSK+1,[MOVEM AC,LOCN] + .ELSE [IFE MSK-777777,[HRRM AC,LOCN] + .ELSE [IFE MSK-<-1,,0>,[HRLM AC,LOCN] + .ELSE [DPB AC,[.BP MSK,LOCN]]]] +TERMIN + + SUBTTL BLOCK MACROS + +;MACROS TO PROVIDE SOME BLOCK HANDLING OF CODE + +;DO. - LOOP STRUCTURE, DECLARES TOP OF LOOP +; LOOP. - JUMPS TO TOP OF LOOP +; EXIT. - EXITS LOOP +; TOP. - TAG AT TOP OF LOOP FOR JUMPS, E.G. SOJG T4,TOP. +; ENDLP. - TAG AT END OF LOOP FOR JUMPS, E.G. SOJL T4,ENDLP. + +DEFINE DO. + ..DX +TERMIN + +DEFINE ..DX \%TGE,%SV1,%SV2,%SV3 + EQUALS %SV1,TOP. ? EQUALS %SV2,ENDDO. ? EQUALS %SV3,ENDLP. + .KILL %SV1 + TOP.==. + DEFINE ENDDO. + %TGE::EQUALS TOP.,%SV1 ? EQUALS ENDDO.,%SV2 ? EQUALS ENDLP.,%SV3 + .KILL %TGE + TERMIN + DEFINE ENDLP. +%TGE!!TERMIN +TERMIN + +DEFINE ENDDO. +.ERR ENDDO. outside loop +TERMIN +DEFINE ENDLP. +.ERR ENDLP. outside loop +TERMIN +TOP.==-1 + +DEFINE OD. +ENDDO.!TERMIN + +DEFINE LOOP. +JRST TOP.!TERMIN + +DEFINE EXIT. +JRST ENDLP.!TERMIN + + +;Conditionals + +DEFINE IFSKP. +..IX [JRST ] +TERMIN + +DEFINE IFNSK. +TRNA + ..IX [JRST ] +TERMIN + +DEFINE IFXN. AC,#MASK + IFE 1_35.-MASK,..IX [JUMPGE AC,] + .ELSE [IFE MASK+1,..IX [JUMPE AC,] + .ELSE [TXNN AC,MASK + ..IX [JRST ] + ]] +TERMIN + +DEFINE IFXE. AC,#MASK + IFE 1_35.-MASK,..IX [JUMPL AC,] + .ELSE [IFE MASK+1,..IX [JUMPN AC,] + .ELSE [TXNE AC,MASK + ..IX [JRST ] + ]] +TERMIN + +DEFINE IFE. AC +..IX [JUMPN AC,] +TERMIN + +DEFINE IFN. AC +..IX [JUMPE AC,] +TERMIN + +DEFINE IFG. AC +..IX [JUMPLE AC,] +TERMIN + +DEFINE IFGE. AC +..IX [JUMPL AC,] +TERMIN + +DEFINE IFLE. AC +..IX [JUMPG AC,] +TERMIN + +DEFINE IFL. AC +..IX [JUMPGE AC,] +TERMIN + +DEFINE ..IX OP,\%TAG,%SV1,%SV2 + OP!%TAG + EQUALS %SV1,..TG ? EQUALS %SV2,ENDIF. + DEFINE ..TG LBL + %TAG!!LBL!TERMIN + DEFINE ENDIF. + ..TG [::] + .KILL ..TG + EQUALS ..TG,%SV1 ? EQUALS ENDIF.,%SV2 + TERMIN +TERMIN + +DEFINE ELSE. +..EX +TERMIN + +DEFINE ..EX \%TAG + JRST %TAG + ..TG [::] + DEFINE ..TG LBL + %TAG!!LBL!TERMIN +TERMIN + +DEFINE ..TG LBL + .ERR Conditional construct outside a conditional +TERMIN + +DEFINE ENDIF. + .ERR ENDIF. outside a conditional +TERMIN + + +;GENERAL CASES WITHIN CONDITIONALS + +DEFINE ANSKP. + JRST ..TG +TERMIN + +DEFINE ANNSK. + TRNA + JRST ..TG +TERMIN + +DEFINE ANDXN. AC,#MASK +IFE 1_35.-MASK,JUMPGE AC,..TG +.ELSE [IFE MASK+1,JUMPE AC,..TG + .ELSE [TXNN AC,MASK + JRST ..TG + ]] +TERMIN + +DEFINE ANDXE. AC,#MASK +IFE 1_35.-MASK,JUMPL AC,..TG +.ELSE [IFE MASK+1,JUMPN AC,..TG + .ELSE [TXNE AC,MASK + JRST ..TG + ]] +TERMIN + +DEFINE ANDE. AC + JUMPN AC,..TG +TERMIN + +DEFINE ANDN. AC + JUMPE AC,..TG +TERMIN + +DEFINE ANDG. AC + JUMPLE AC,..TG +TERMIN + +DEFINE ANDGE. AC + JUMPL AC,..TG +TERMIN + +DEFINE ANDLE. AC + JUMPG AC,..TG +TERMIN + +DEFINE ANDL. AC + JUMPGE AC,..TG +TERMIN + + + +; SAVEAC [A,B,C] +; Supports +1/+2 returns. +; Unlike macro version, supports arbitrary locations (not just AC's) +; and doesn't clobber AC16. Assumes stack in P, though. + +DEFINE SAVEAC ACS + IRP AC,,[ACS] + PUSH P,AC + ..XX==.IRPCNT + TERMIN + .SAVX1 ..XX+1,[ACS] +TERMIN + +EQUALS SAVE.,SAVEAC ;Not in MACRO version... + +DEFINE .SAVX1 #N#,ACS + PUSH P,[[CAIA + AOS -N(P) + .SAVX2 [ACS] + POPJ P, + ]] +TERMIN + +DEFINE .SAVX2 ACS + IRP AC,REST,[ACS] + .SAVX2 [REST] + POP P,AC + .ISTOP + TERMIN +TERMIN + diff --git a/src/system/t300.defs7 b/src/system/t300.defs7 new file mode 100755 index 00000000..5819e4d5 --- /dev/null +++ b/src/system/t300.defs7 @@ -0,0 +1,92 @@ +.AUXIL + +;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. +;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. + +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +];IF Not DEFined DEFSYM +.ELSE $$TEMP==0 + +;DISK PHYSICAL PARAMETERS (CENTURY DATA T-300 AND 2561 CONTROLLER) +;SINCE WE HAVE ALSO AN RH10 CONTROLLER, THESE ARE SUFFIXED WITH A 1 + +DEFSYM NCYLS1==812. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS1==815.-NCYLS1 ;# CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS1==19. ;# TRACKS/CYLINDER +DEFSYM NSECS1==32. ;# SECTORS/TRACK (256. 16-BIT WORDS) +DEFSYM SECBL1==12. ;# SECTORS/BLOCK +DEFSYM NBLKC1==NHEDS1*NSECS1/SECBL1 ;# BLOCKS/CYLINDER +DEFSYM NBLKS1==NCYLS1*NBLKC1 ;# BLOCKS NORMALLY USED +DEFSYM XBLKS1==XCYLS1*NBLKC1 ;# BLOCKS FOR HACKS +DEFSYM TBLKS1==NBLKS1+XBLKS1 ;TOTAL BLOCKS + +DEFSYM NTUTB1==4 ;4 BLOCKS PER TUT HERE +DEFSYM TUTBL1==MFDBLK-NTUTB1 ;TUT ALSO STARTS AT A DIFFERENT PLACE + +;TAKE DECADE FROM RH1O DEFS +;DEFSYM DECADE==NBLKSC ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME +; ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. +; ;DECADE SIZE = CYLINDER SIZE FOR KLFEDR'S SAKE + +;10/11 COMMUNICATION AREA IS 14. WORDS STARTING 48. WORDS INTO THE 64.-WORD DL10 AREA + +DEFSYM DSCCHK=DL10AR+60 ;MUST BE 2561 OCTAL +DEFSYM DSCREQ=DL10AR+61 ;SET NON-ZERO BY 10 TO SIGNAL REQUEST TO 11 +DEFSYM DSCDON=DL10AR+62 ;SET NON-ZERO BY 11 TO SIGNAL DONE TO 10 +DEFSYM DSCFLT=DL10AR+63 ;0 NO FAULT +DEFSYM %DFRST==100000 ;POWER CYCLED OR BROKEN, SO CONTROLLER WAS RESET +DEFSYM %DFCQE==10000 ;CONSISTENCY ERROR IN COMMAND QUEUE +DEFSYM %DFNXM==4000 ;NXM ERROR IN COMMAND QUEUE +DEFSYM %DFPAR==2000 ;PARITY ERROR IN COMMAND QUEUE + ; IF ONE OF THESE BITS IS ON, BITS 1-0 AND DSCSTS + ; ARE THE ERROR ADDRESS + ;BITS 7-0 SYSTEM FAULT CODE IF LEFT BYTE IS ZERO + ; SEE THE 2561 OEM MANUAL FOR MEANING OF FAULT CODES +DEFSYM DSCSTS=DL10AR+64 ;STATUS BITS AS FOLLOWS +DEFSYM %DSRTR==100000 ;COMMAND WAS RETRIED +DEFSYM %DSECH==40000 ;UNCORRECTABLE DATA ERROR (ECC HARD) +DEFSYM %DSECC==20000 ;CORRECTED DATA ERROR +DEFSYM %DSIDE==10000 ;ID ERROR +DEFSYM %DSHCE==4000 ;ADDRESS ERROR (HEADER COMPARE ERROR) +DEFSYM %DSPRT==2000 ;WRITE-PROTECT STATUS OF SECTOR (ABORTS WRITE COMMAND) +DEFSYM %DSALT==1000 ;ALTERNATE-SECTOR STATUS (ABORTS READ, WRITE, AND CHECK) +DEFSYM %DSOVR==400 ;FIFO OVER-RUN, NOT CORRECTED BY 1 RETRY +DEFSYM %DSSKE==200 ;SEEK ERROR FROM DRIVE +DEFSYM %DSOFL==100 ;DRIVE OFF-LINE OR FAULT +DEFSYM %DSFLT==20 ;DRIVE FAULT +DEFSYM %DSNXM==10 ;NXM ON PDP11 MEMORY +DEFSYM %DSPAR==4 ;PARITY ERROR IN PDP11 MEMORY +DEFSYM %DSSFL==2 ;SYSTEM FAULT, SEE LOW BYTE OF DSCFLT +DEFSYM %DSWLK==1 ;DRIVE WRITE-LOCKED, WRITE ABORTED + +DEFSYM DSCCMD=DL10AR+65 ;COMMAND CODE AS FOLLOWS +DEFSYM %DMSNS==2 ;SENSE DRIVE STATE. DSCSTS GETS CODE FOR DRIVE TYPE IN + ; BITS 14-8 (10 FOR T-300), AND %DSWLK, %DSFLT, %DSOFL, %DSSKE +DEFSYM %DMTST==3 ;TEST SPECIFIED DRIVE (RUNS DIAGNOSTICS) +DEFSYM %DMREC==4 ;RECALIBRATE +DEFSYM %DMSEK==5 ;SEEK +DEFSYM %DMWRT==6 ;WRITE DATA +DEFSYM %DMRED==20 ;READ DATA. ADD 1-10 FOR VARIOUS RECOVERY FEATURES AS + ; DOCUMENTED IN THE 2561 OEM MANUAL. + +DEFSYM DSCDRV=DL10AR+66 ;DRIVE NUMBER (0 IS FIRST DRIVE ON 11) +DEFSYM DSCCYL=DL10AR+67 ;CYLINDER NUMBER +DEFSYM DSCHED=DL10AR+70 ;HEAD NUMBER +DEFSYM DSCSEC=DL10AR+71 ;SECTOR NUMBER +DEFSYM DSCPNT=DL10AR+72 ;4 12-BIT BYTE POINTERS TO DATA TO TRANSFER + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/tcp.275 b/src/system/tcp.275 new file mode 100755 index 00000000..51d3b16e --- /dev/null +++ b/src/system/tcp.275 @@ -0,0 +1,3629 @@ +; This file holds the modules for TCP. +comment | STUFF TO DO + +Incoming ACKs should prevent retrans from aborting connection, since +clearly it is still alive, just doesn't have room for our stuff (which +is possibly overflowing its window). + +Note Clark suggs on windowing/ACKing. + If input data seg doesnt have PUSH, don't send ACK, but set + a timeout for sending ACK. Send ACK when: + PUSH is seen + outgoing seg forced out (new or retrans) + timed out + +Output buffering stinks. If can't send buff due to too many segs, +then should be able to keep adding to present segment. + +Provide way for output IOT to specify URGENT, and +Handle URGENT when received on input. + +| + +SUBTTL TCP definitions + +%WYTCP==:7 ; Move to BITS later + +%MOD32==:740000 ; LH mask used for mod 32 arithmetic +%TCPMI==:5 ; Max # segments in input queue per connection +%TCPMO==:5 ; Max # segments in output queue per connection +%TCPDS==:536. ; Default max # bytes per segment (when no + ; knowledge of receiving host) +%TCPMS==:2048.-40. ; Maximum possible segment size we can support + ; This must be 7777 (octal) or less. +%TCPMB==:%TCPMI*%TCPMS ; Max # bytes of data in queue (a bit fictional) +%TCPMR==:20. ; Max # retransmit retries allowed +%TCPMQ==:20 ; Max # pending RFCs allowed +%TCPMP==:777 ; Max port # allowed for pending-RFC (SYN) conns + ; Note pending-RFCs used ONLY for job startups, + ; SYNs are not queued in general. + +; Defintions of TCP Segment Header fields. +%TCPHL==:5 ; # of 32-bit words in fixed part of TCP header + +TH%SRC==:777774,, ; 0 Source Port +TH%DST==: 3,,777760 ; 0 Destination Port +TH%SEQ==:777777,,777760 ; 1 Sequence Number +TH%ACK==:777777,,777760 ; 2 Acknowledgement Number +TH%THL==:740000,, ; 3 Data Offset (TCP Header Length in 32-bit wds) +TH%RES==: 37400,, ; 3 Reserved (should be 0) +TH%CTL==: 374,, ; 3 Control bits +TH%WND==: 3,,777760 ; 3 Window +TH%CKS==:777774,, ; 4 Checksum +TH%UP==: 3,,777760 ; 4 Urgent Pointer + ; 5 Start of Options/Data + +TH$SRC==:<.BP TH%SRC,0> +TH$DST==:<.BP TH%DST,0 > +TH$SEQ==:<.BP TH%SEQ,1> +TH$ACK==:<.BP TH%ACK,2> +TH$THL==:<.BP TH%THL,3> +TH$RES==:<.BP TH%RES,3> +TH$CTL==:<.BP TH%CTL,3> +TH$WND==:<.BP TH%WND,3> +TH$CKS==:<.BP TH%CKS,4> +TH$UP==: <.BP TH%UP, 4> +TH$OPT==:<441000,,5> ; An ILDB-type pointer to start of options. + + ; Control bit definitions (as located in full word) +TC%URG==:<200,,> ; Urgent Pointer significant +TC%ACK==:<100,,> ; Ack field significant +TC%PSH==:< 40,,> ; Push Function +TC%RST==:< 20,,> ; Reset connection +TC%SYN==:< 10,,> ; Synchronize sequence numbers +TC%FIN==:< 4,,> ; Finalize - no more data from sender + +; TCP Connection tables, normally indexed by I +; These correspond to what the TCP document (RFC-793) calls +; the "Transmission Control Block" parameters. +; A TCB is "in use" if either XBUSER or XBSTAT is non-zero. +; XBUSER is set if a user job has channels associated with the TCB. +; XBSTAT is set if TCP is dealing with the TCB. +; PI level will never touch any TCBs which have a zero XBSTAT, so it is +; safe for the MP level to hack a zero-XBSTAT TCB without using NETOFF. + +IFNDEF XBL,XBL==10. ; Allow this many TCP connections for now. + +EBLK ; General variables + +XBUSER: BLOCK XBL ; RH User index + XB%STY==:<770000,,> ; TTY # of STY connected to (0 if none) + XB%ICH==:<007700,,> ; Input channel #+1 (77=IOPUSHed) + XB%OCH==:<000077,,> ; Output channel #+1 (77=IOPUSHed) + XB$STY==:<.BP XB%STY,XBUSER> + XB$ICH==:<.BP XB%ICH,XBUSER> + XB$OCH==:<.BP XB%OCH,XBUSER> +XBSTAT: BLOCK XBL ; ,, + ; Connection flags (internal to ITS) + %XBMPL==:SETZ ; Current output segment locked at MP level (IOT) + ; This must be sign bit for SGNSET/PCLSR to work. + %XBCTL==:<374,,> ; Array of output request bits + IFN %XBCTL-TH%CTL,.ERR %XBCTL flags must be the same as TH%CTL!! + ; For all bits in %XBCTL the general meaning is + ; "Set this bit in next outgoing segment". If no bits + ; are set, output is sent every 2 sec, otherwise every + ; 1/2 sec. If %XBNOW is set, output is sent as soon + ; as something notices it. + %XBNOW==:<1,,> ; Send output segment ASAP (else 1/2 sec clock) + %XBACF==:<2,,> ; Our FIN has been ACKed + + %XBABT==:< 400,,> ; We're aborting. + %XBFIN==:<1000,,> ; FIN received for input, input queue will not + ; get any more additions. +; %XBWOK==:<100,,> ; State is OK for user to write (else get IOC err) +; %XBROK==:<200,,> ; State is OK for user to read (else get IOC err) + + ; Connection state, as in TCP document (RFC-793) + ; Some test/dispatch code depends on the fact that the first + ; 4 states have the values they do. + ; ** NOTE: These .XSzzz symbols are not advertised to users. + ; ** Maybe I'll rename them in here sometime. -- CSTACY 9/84 + .XSCLS==:0 ; Closed (must be zero) + .XSSYQ==:1 ; ADDITIONAL ITS STATE: Syn-Queued + .XSLSN==:2 ; Listen + .XSSYN==:3 ; Syn-Sent + .XSSYR==:4 ; Syn-Rcvd + .XSOPN==:5 ; Established (Open) + .XSFN1==:6 ; Fin-Wait-1 + .XSFN2==:7 ; Fin-Wait-2 + .XSCLW==:10 ; Close-Wait + .XSCLO==:11 ; Closing + .XSCLA==:12 ; Last-Ack + .XSTMW==:13 ; Time-Wait + .XSTOT==:14 ; Total # of states +XBSTAU: BLOCK XBL ; User Channel state ,, +XBCLSU: BLOCK XBL ; Close reason ,, + .XCNTO==:0 ; Never opened + .XCUSR==:1 ; Closed by user + .XCFRN==:2 ; Closed by foreign host + .XCRST==:3 ; Fgn host reset things + .XCDED==:4 ; Fgn host dead (apparently) + .XCINC==:5 ; Incomplete transmission (retrans timeout) + ; ==:6 ; Byte size mismatch - can't happen + .XCNCP==:7 ; Local TCP went down + .XCRFS==:10 ; Fgn host refused connection (valid RST + ; received in SYN-SENT state) + +XBPORT: BLOCK XBL ; <4 zero bits> + ; It is set up this way for fast lookup of + ; incoming segments. +XBHOST: BLOCK XBL ; Remote host (HOSTS3 format) +XBLCL: BLOCK XBL ; Local host (HOSTS3 format) +XBNADR: REPEAT XBL,-1 ; Net host address to give the device driver (-1 none) + +; MP Input - see TCPI for detailed description +XBITQH: BLOCK XBL ; Input Segment TCP queue header +XBINBS: BLOCK XBL ; Total # bytes in input queue +XBINPS: BLOCK XBL ; Total # segments in input queue +XBIBP: BLOCK XBL ; Main prog BP to input +XBIBC: BLOCK XBL ; # bytes available for this BP + +; MP Output - see TCPW for detailed description +XBOCOS: BLOCK XBL ; Current Output Segment pointer (0 if none) +XBOBP: BLOCK XBL ; Main prog BP into output segment +XBOBC: BLOCK XBL ; # bytes of room for this BP + +XBORTP: BLOCK XBL ; Retransmit parameters +XBORTQ: BLOCK XBL ; Retransmit queue header +XBORTL: BLOCK XBL ; Retransmit queue length (# of segments) +XBORTC: BLOCK XBL ; Retransmit count (1st msg on queue) +XBORTT: BLOCK XBL ; Retransmit timeout (1st msg on queue) + +; TCP Send Sequence Variables +XBSUNA: BLOCK XBL ; Send Unacknowledged +XBSNXT: BLOCK XBL ; Send Next +XBSWND: BLOCK XBL ; Send Window (offered window) +XBSAVW: BLOCK XBL ; Available window (between SNXT and SUNA+WND) +XBSUP: BLOCK XBL ; Send Urgent Pointer +XBSWL1: BLOCK XBL ; Segment Seq number used for last window update +XBSWL2: BLOCK XBL ; Segment Ack number used for last window update +XBSMSS: BLOCK XBL ; Max seg size that receiver can handle + +; TCP Receive Sequence Variables +XBRNXT: BLOCK XBL ; Receive Next +XBRWND: BLOCK XBL ; Receive Window +XBRUP: BLOCK XBL ; Receive Urgent Pointer +XBRMSS: BLOCK XBL ; Max seg size we are expecting/ have asked for + +BBLK + +NTSYNL: SIXBIT /TCP/ ; Start SYS;ATSIGN TCP for random SYNs. +EBLK + 0 ; Word for NUJBST etc to mung for above job starting + +TCPUP: -1 ; -1 to handle TCP stuff, 0 to turn off. +TCPUSW: 0 ; -1 to disable net conns from anyone but ourself (like NETUSW) + ; Perhaps eventually this should be the same as NETUSW. +TCPRQN: 0 ; # of things in SYN queue, to keep it small +TCPRQL: 0 ; Index of last SYN queued. +TCPCRI: 0 ; Counter used for gensymming local port #s +TISSLU: 0 ; Last ISS used +TISSC: 0 ; Counter to further uniquize ISS +TCPLCP: 0 ; Last TCB index allocated +TCPBSW: -1 ? 0 ; Lock switch for allocating TCB indices +TCPTMO: 4*30. ; Default timeout for retransmits (in 30'ths of sec) +BBLK + +; Macro to perform sequence-number range checking. +; Note all numbers are 32-bit positive integers, modulo 2**32. +; Use it like this: +; CMPSEQ ,,,,,, +; Left and Right are addrs of the range bounds. One of them +; must be an AC. +; Seqno must be an AC. +; LT and LE are the strings "<" and "=<". +; Lerr and Rerr are the places to JRST to if the left or +; right compares fail, respectively. Rerr can +; be omitted and will default to Lerr. +; e.g. +; CMPSEQ A,<,D,=<,XBSNXT(I),TSI30 +; NOTE CAREFULLY that only existence within a range is checked, +; and the bounds L,R of the range MUST be known to be L =< R! +; It does not work to use CMPSEQ for the degenerate case +; CMPSEQ A,<,B,<,B,ERR +; to see if A < B. + +DEFINE CMPSEQ (L),C1,S,C2,(R),(OUTV1),(OUTV2) + %%%CML==0 + %%%CMR==0 +IFSE [C1][<] %%%CML==CAMG +IFSE [C1][=<] %%%CML==CAMGE +IFSE [C2][<] %%%CMR==CAML +IFSE [C2][=<] %%%CMR==CAMLE +IFE %%%CML&%%%CMR, .ERR Seq compare has bad relational arg + %%%CMX==CAMLE +IFSE [C1][=<] %%%CMX==CAML + +IFGE L-20,IFGE R-20, .ERR Seq compare needs ACs + +IFL L-20,CAMLE L,R ; Skip if normal order, L =< R +.ELSE CAMGE R,L + JRST [ ; Reverse order, R < L. Check S < R & L < S + %%%CMR S,R ; Skipwin if S <(=) R + %%%CMX S,L ; Unusual test here, win if S >(~=) L + JRST .+5 ; If either wins, win completely! +IFB OUTV2, JRST OUTV1 +.ELSE CAML S,[020000,,] ? JRST OUTV1 ? JRST OUTV2 + ] + ; Normal order, L =< R + %%%CML S,L ; Skipwin if S >(=) L + JRST OUTV1 + %%%CMR S,R ; Skipwin if S <(=) R +IFB OUTV2, JRST OUTV1 +.ELSE JRST OUTV2 +TERMIN + +SUBTTL TCP Open system call + +; .CALL TCPOPN +; arg 1 - receive channel number +; arg 2 - transmit channel number +; arg 3 - local port # (-1 to gensym unique port #) +; arg 4 - foreign port # (-1 for wild) +; arg 5 - foreign host address (HOSTS3 fmt) (-1 for wild) +; arg 6 - Retransmission timeout (optional) + +;Control bits: +; - None needed for channels - they are opened as .UAI and .UAO +; automatically (no other modes possible). +; - 7 vs 8 bit ASCII transfers can be determined by user-space byte +; pointer used in SIOT. System buffers are always 8-bit bytes. +%NOLSN==:100 ; Listen mode +%NOBBI==:200 ; Use big buffer for input (not implemented yet) +%NOBBO==:400 ; Use big buffer for output (not implemented yet) +%NOWDA==:1000 ; Use word-align algorithm on transmit (not implemented yet) + +; Note a value of -1 for either the foreign port or host will imply +; that the call is a "listen". For the time being, either also implies +; the other, i.e. wild port means wild host and vice versa. This is +; because I havent figured out what the right thing to do is for the +; various combinations that could result otherwise. +; Word-align means that for the transmit side, all segments sent will +; have the data aligned so that the first byte, and every fourth byte +; after that, will start on a 32-bit word boundary. This should +; produce a noticeable speedup for transfers that involve large blocks +; of words rather than small amounts of miscellaneous text. +; For the latter, it only makes things worse, so is not the default. + +; Return is semi-immediate; the call may +; hang momentarily waiting for a free network buffer. (Have timeout? +; do a SKIPA SKIPA HANG to schedule, then fail if still none?) +; Use NETBLK +; to determine when the channels become open. For a non-listen call, +; there is an internal ITS timeout, but for listen the state can persist +; forever. + +TCPOPN: METER("TCP: syscal tcpopn") + MOVEI A,(A) + MOVEI B,(B) + CAIGE A,NIOCHN + CAIL B,NIOCHN + JRST OPNL14 ; Bad channel # argument + CAIN A,(B) + JRST OPNL33 ; Illegal to use same channel # for both + MOVEI J,(B) + HRLI J,(A) ; Save chan #s in J/ ,, + PUSH P,C + PUSH P,D + PUSH P,E + PUSH P,J + MOVEI R,(A) ; Close receive chan + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE ; Close whatever is already on channels. + HRRZ R,(P) ; Close xmit chan + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + POP P,J + POP P,E + POP P,D + POP P,C + + HLRZM J,UUAC(U) ; Remember input channel # for errs. + SKIPN TCPUP ; If TCP disabled, + JRST OPNL7 ; Fail, "device not ready". + CALL SWTL ; Lock TCB assignment switch + TCPBSW + MOVE I,TCPLCP + SOJL I,TCPO2 +TCPO1: SKIPN XBUSER(I) ; Hunt for free TCB + SKIPE XBSTAT(I) ; Must be both closed and unassigned. + SOJGE I,TCPO1 + JUMPGE I,TCPO3 ; Jump if got one! +TCPO2: MOVEI I,XBL ; Hit beginning, wrap back to end + CAMN I,TCPLCP + JRST OPNL6 ; No free TCB's available + MOVEM I,TCPLCP ; Might as well make faster next time + SOJA I,TCPO1 + +TCPO3: MOVEM I,TCPLCP ; Save scan pointer for next time + JRST TCPO4 ; (This is here for patching. -CSTACY) + + ; Got an index, now see if we're going to do a LISTEN + ; or an active open. +TCPO4: SETZ W, ; Assume active + CAME C,[-1] ; Verify local port is OK + CAIG C,177777 + CAIA + JRST OPNL11 ; Complain "illegal file name" + CAMN D,[-1] + AOJA W,.+3 + CAILE D,177777 + JRST OPNL11 + CAMN E,[-1] + ADDI W,2 + ; W = 0 if no wildcards, =1 if port wild, =2 if host wild, =3 both. + MOVE B,CTLBTS(U) ; Get control bits for call + CAIE W, + TRO B,%NOLSN ; Set "Listen" bit if implied by args. +; Crock - if either is wild, ensure both are. + CAIE W, + SETOB D,E + + SETZ R, ; Say we have no buffer + TRNE B,%NOLSN ; Skip if not listening, doing active open. + JRST TCPO20 ; Listening, don't need buffer. + + ; No wild-cards, this is going to be an active open. We will need + ; a buffer to send the initial SYN, so let's get it now and get + ; all possible PCLSR'ing over with, before turning off the NET PI. + CALL PKTGFI ; Get a free packet, skip unless fail. + CAIA ; Didn't get, skip to schedule. + JRST TCPO15 ; Got it! + SKIPA + SKIPA ; Force a schedule + CALL UFLS + CALL PKTGFI ; Try again. If we fail again, net is full, + JRST OPNL6 ; so better just return "device full" err. +TCPO15: MOVEI R,(A) ; We have buffer! Fall through. + TRCPKT R,"TCPO15 Alloc to send initial SYN" + + ; Okay, nothing can stop us now from running through to completion. + ; We do all the following code with net interrupts OFF so that + ; (a) We can scan all TCBs for port/host conflicts and be + ; sure we checked everything right, + ; (b) Incoming segments at int level won't be confused by + ; an inconsistent state for this TCB. + ; (c) We can check the pending-RFC queue safely. +TCPO20: CONO PI,NETOFF ; Don't let PI level see dirty work. + CAMN C,[-1] + JRST [ CALL TCPPCR ; Assign unique TCP port # + ROT D,-16. ; Put fgn port in high 16 bits + DPB A,[.BP TH%DST,D] ; Deposit local port + JRST TCPO30] ; Note that since port is unique, no + ; possible conflict with existing, so skip chk. + ; Also, low 4 bits indicate wildness if set. + + ; Note that low 4 bits of XBPORT are set to indicate wildness. + ; This ensures that TCPIS won't find them, but TSISQ will. + ; Have specific local port, check to make sure it doesn't already + ; exist in TCB tables. + ROT D,-16. ; Get fgn port in high 16 bits + DPB C,[.BP TH%DST,D] ; Put together the ports word + MOVSI T,-XBL +TCPO22: CAMN D,XBPORT(T) ; Look for matching port set + SKIPN XBSTAT(T) ; which is in use + AOBJN T,TCPO22 + JUMPL T,TCPO91 ; Ugh, found match! Must fail... + + ; OK, D has our unique port set, and we're ready to set things up. +TCPO30: MOVEM D,XBPORT(I) ; Store port set + SKIPL A,E + CALL CVH3NA ; Make sure it's HOSTS3 format. + MOVEM A,XBHOST(I) ; Store foreign host + CALL IPBSLA ; Call IP for best local address + MOVEM A,XBLCL(I) + CALL TXBINI ; Initialize the TCB + CALL TCPMSS ; Set default MSS values. Reexamined when + ; foreign host known if this is a wild listen. + CALL TCPRWS ; Open a default receive window + HRRZM U,XBUSER(I) ; Make TCB/index in use + HLRZ A,J ; Get back saved rcv channel # + DPB A,[XB$ICH (I)] ; Deposit input channel + DPB J,[XB$OCH (I)] ; and output channel + MOVE B,[0101,,0] ; Increment both channel #'s by 1 + ADDM B,XBUSER(I) ; So can distinguish chan 0 from no chan. + HRLZ T,I ; Set up user's IOCHNM words + HRRI T,TCPDUI + ADDI A,IOCHNM(U) + MOVEM T,(A) ; Set up input chan ,,TCPDUI + HRRI T,TCPDUO + ADDI J,IOCHNM(U) + MOVEM T,(J) ; Set up output chan ,,TCPDUO + + ; Search pending-RFC queue to make sure we match up or reject + ; with stuff in there. + LDB B,[.BP TH%DST,XBPORT(I)] ; B gets local port # + SETO D, ; D is -1 for any PE ptr. + CALL TCPRQS ; Search queue, return index in A + JUMPL A,TCPO41 ; Ignore further RFC checks if nothing. + MOVEI C,(A) + HRRZ A,XBITQH(C) + CAIN A, + BUG HALT + HLRZ W,PK.IP(A) + HLRZ H,PK.TCP(A) + TRNE D,17 ; If we're "wild" accepting any request, + JRST TCPO35 ; Take it! + LDB B,[IP$SRC (W)] ; No, must try full match. + CAMN B,XBHOST(I) ; If hosts match + CAME D,TH$SRC(H) ; and ports match too + JRST TCPO40 ; (don't) + + ; Matching request!! + ; For now, we ignore the listen/active distinction here, and + ; always try to establish connection with the pending RFC. + ; So, can flush use of R for listen flag. Have to flush the + ; extra buffer if it was "active" open, though, since we can + ; just re-use the pending-RFC packet. +TCPO35: METER("TCP: Open matched pending RFC") + JUMPN R,TCPO36 + MOVEI Q,XBITQH(C) ; If don't already have buffer, + CALL PKQGF(PK.TCP) ; Get it from the queued SYN (C is idx to) + SKIPN R,A ; It had better have a buffer! + BUG HALT + TRCPKT R,"TCPO36 Queued SYN used to answer pending RFC rqst" +TCPO36: LDB B,[IP$SRC (W)] + MOVEM B,XBHOST(I) ; Set host address + LDB B,[IP$DST (W)] + MOVEM B,XBLCL(I) ; Use local address the other end wants + MOVE D,TH$SRC(H) + MOVEM D,XBPORT(I) ; And ports + CALL TCPMSS ; Find default segment sizes for connection + CALL TCPRWS ; Set up receive window + EXCH C,I ; C identifies slot of queued SYN. + CALL TSISQF ; Flush the SYN from queue! + MOVEI I,(C) + CALL TSILSX ; Invoke interrupt level SYN+ACK, re-uses + ; the packet and sets state and everything. + JRST TCPO80 ; OK, take win return. + + ; Request doesn't match, restore it and fall thru. +TCPO40: +; MOVEI Q,TCPRQH ; Thought we had something but didn't, +; CALL PKQPF(PK.TCP) ; so put back on queue. + + ; No matching request on pending-RFC queue. +TCPO41: CAIN R, ; Skip if handling active open + JRST [ MOVEI A,.XSLSN ; No, handling a listen. + JRST TCPO70] ; Just change state and we're done. + + ; Active open, must fire off initial SYN. + ; R has PE ptr to free packet to be used for the SYN. + CALL TCPISS ; Get initial sequence # + MOVEM A,XBSUNA(I) ; Set up sequence vars + MOVEM A,XBSNXT(I) + MOVSI T,(TC%SYN) ; Note no ACK in initial segment! + TRCPKT R,"TCPO41 Send initial SYN" + CALL TSOSSN ; Send SYN segment (clobber mucho ACs) + MOVEI A,.XSSYN ; Set state to SYN-SENT and fall thru. + +TCPO70: HRRM A,XBSTAT(I) ; Set state LISTEN or SYN-SENT. + CALL TCPUSI ; Change user state. +TCPO80: CONO PI,NETON + JRST LSWPJ1 ; Success return, unlock switch and skip. + + ; Port match failure, must back off and fail. +TCPO91: CONO PI,NETON ; No need to hide our shame + SKIPE A,R ; If we had a buffer, + CALL PKTRT ; return it to freelist. + JRST OPNL13 ; Say "file already exists". + +; TXBINI - Initialize TCB connection table entries for specific index. +; The things it doesn't touch are commented out below. +; I/ TCB index + +TXBINI: +; SETZM XBUSER(I) ; Set after +; SETZM XBSTAT(I) ; Set after + SETZM XBSTAU(I) + SETZM XBCLSU(I) +; SETZM XBPORT(I) ; Set prior +; SETZM XBHOST(I) ; Set prior +; SETZM XBLCL(I) + SETOM XBNADR(I) + + ; I/O vars + SKIPE XBITQH(I) + BUG CHECK,[TCP: Init TCB has input, I=],OCT,I,[list ],OCT,XBITQH(I) + SETZM XBITQH(I) + SETZM XBINBS(I) + SETZM XBINPS(I) + SETZM XBIBP(I) + SETZM XBIBC(I) + + SKIPE XBOCOS(I) + BUG CHECK,[TCP: Init TCB has output, I=],OCT,I,[list ],OCT,XBOCOS(I) + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) + + ; Retransmit stuff + SETZM XBORTP(I) + SKIPE XBORTQ(I) + BUG CHECK,[TCP: Init TCB has retrans, I=],OCT,I,[list ],OCT,XBORTQ(I) + SETZM XBORTQ(I) + SETZM XBORTL(I) + SETZM XBORTC(I) + SETZM XBORTT(I) + + ; TCP Send Sequence Initialization + SETZM XBSUNA(I) + SETZM XBSNXT(I) + SETZM XBSWND(I) + SETZM XBSAVW(I) + SETZM XBSUP(I) + SETZM XBSWL1(I) + SETZM XBSWL2(I) +; SETZM XBSMSS(I) ; Set after + + ; TCP Receive Sequence Initialization + SETZM XBRNXT(I) + SETZM XBRUP(I) +; SETZM XBRMSS(I) ; Set after +; SETZM XBRWND(I) ; Set after + RET + +; TCPPCR - Port Create. Creates a unique local port #. +; Returns # in A. Current algorithm is very simple/dumb. +; Must only be called at MP level with NETOFF. +; Clobbers T,Q + +TCPPCR: PUSH P,B + MOVEI A,(U) ; Get user index + IDIVI A,LUBLK ; Find job # + AOS B,TCPCRI ; Bump and get new counter + ROT B,-8. ; Put low bits into high + LSHC A,8. ; Then shift them into port # + CALL TCPPLU ; See if this port unique or not. + JRST [ AOS TCPCRI ; If not, AOS stuff and keep going. + AOJA A,.-1] + POP P,B + RET + +; TCPPLU - Port Lookup. Skips if port # unique among local ports. +; A/ port # +; Clobbers T, Q. +; Returns .+1 if fail (number not unique) +; T/ idx of matching TCB + +TCPPLU: LSH A,4 ; Shift over for easier compare + MOVSI T,-XBL +TCPLU2: SKIPN Q,XBPORT(T) + JRST TCPLU3 + AND Q,[TH%DST] + CAMN A,Q + JRST TCPLU7 +TCPLU3: AOBJN T,TCPLU2 + AOS (P) +TCPLU7: LSH A,-4 + RET + +; TCPMSS - Determine and set max bytes per segment for TCB in I +; I/ TCB index. XBHOST should be set already. +; Bashes A, T +; Base maximum TCP segment sizes on size of largest datagram IP wants +; to send to destination. This sets the default sizes. We will tell +; the foreign side what we want (XBRMSS) with a TCP MSS option in the +; outgoing SYN. We will adjust what we send (XBSMSS) down if foreign +; side requests it with MSS opton in an incoming SYN. + +TCPMSS: MOVE A,XBHOST(I) ; Foreign address + CALL IPMTU ; IP datagram size to T + SUBI T,40. + MOVEM T,XBSMSS(I) ; Set default send and receive segment sizes + MOVEM T,XBRMSS(I) + RET + + +SUBTTL Other TCP device system call routines + +; Device name in DEVTAB, device code in DCHSTB, index in RSTB to some tables + +; OPEN - from DEVADR + +TCPO: JRST OPNL12 ; Say "mode not avail" + ; Save rest temporarily. + HLRS C + MOVSI A,(A) ; Save RH of FN1 in LH of IOCHNM + JSP Q,OPSLC7 + TCPDUI,,TCPDUO + TCPDBI,,TCPDBO + TCPDUI,,TCPDUO + TCPDBI,,TCPDBO + +; CLOSE - from CLSTB +; R/ addr of IOCHNM word + +TCPCLS: METER("TCP: syscal close") + HLRZ I,(R) ; Get TCB index from LH of IOCHNM + CAIL I,XBL ; Make sure it's reasonable + BUG HALT,[TCP: CLS idx bad] + HRRZ A,XBUSER(I) ; Verify user + CAIE A,(U) + BUG HALT,[TCP: CLS usr bad] + SETO D, ; See if input or output + HRRZ A,(R) + CAIN A,TCPDUO ; Output? + AOSA D + CAIN A,TCPDUI ; Input? + ADDI D,1 + CAIGE D, ; D/ 0 for input, 1 for output. + BUG ; IOCHNM value screwed up?? + LDB A,[XB$ICH (I)] ; Get input chan # according to TCB + LDB B,[XB$OCH (I)] ; Ditto output + MOVEI C,(R) + SUBI C,IOCHNM(U) ; Find channel # we're closing + ADDI C,1 ; Increment since TCB # is really #+1 + CAME C,A(D) ; Compare with channel # in TCB + BUG HALT,[TCP: Close chan not same as TCB chan] + JUMPN D,[MOVEI D,2 + CAIE A, + MOVEI D,3 + JRST TCPC06] + CAIE B, + IORI D,1 +TCPC06: + ; D is now a 2-bit channel status index. + ; Bit 1.2 is 0 for input, 1 for output. + ; Bit 1.1 is 0 if other channel is closed, 1 if it is still open. + SKIPN XBSTAT(I) ; Perhaps already gone? + JRST TCPCL8 ; Yeah, flush channel etc. + PUSH P,D + CONO PI,NETOFF ; Ensure that state doesn't change on us. + HRRZ J,XBSTAT(I) + CAIL J,.XSTOT + BUG HALT,[TCP: CLS state bad] + XCT TCPCXT(J) ; Invoke closure stuff appropriate for state + CONO PI,NETON ; TCB state hacking done, can re-enable ints. + POP P,D + + ; Remove links between user channel and TCB. If both channels + ; are gone, XBUSER is cleared completely. + ; The TCB is not necessarily closed at this point (XBSTAT zero) + ; but TCP will look after it independently to ensure it eventually + ; goes away. +TCPCL8: SETZ B, ; Get a zero + MOVEI T,.XCUSR ; Use this for "Close reason" if needed + TRNE D,2 ; Remember D bit 1.2 indicates output chan + JRST [ DPB B,[XB$OCH (I)] ; Yup, clear output chan. + CALL TCPUCO ; Set close reason if necessary + HRRZ A,XBOCOS(I) ; Does a COS buffer exist? + CAIN A, + JRST TCPCL9 ; Nope, nothing to flush. + CALL PKTRTA ; Aha, free it up. + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) + JRST TCPCL9] + DPB B,[XB$ICH (I)] ; Clear input chan. + CALL TCPUCI ; Set close reason if need to. + CALL TXBIFL ; Flush input queue + +TCPCL9: TRNN D,1 ; Skip if other channel still there. + SETZM XBUSER(I) ; Else flush whole word incl user index! + TRNE D,1 ; If a channel is left, + CALL TCPUSI ; we may need to take interrupt on it. + LDB A,[XB$STY (I)] ; Was a STY connected to channel? + JUMPE A,CPOPJ ; Return if not. + MOVEI I,(A) ; Ugh, must disconnect it! Set up TTY # + CALL NSTYN0 ; Disconnect + JFCL + RET ; Return (CLOSE will clear IOCHNM/IOCHST) + +TCPCLE: BUG CHECK,[TCP: Illegal state in CLOSE, J=],OCT,J,[ D=],OCT,D + CALL TXBFLS ; Flush all of TCB but XBUSER + RET + +TCPCXT: OFFSET -. +.XSCLS:: CALL TXBFLS ; Closed already, but flush again to make sure +.XSSYQ:: CALL TCPCLE ; Syn-Queued - can't happen!! +.XSLSN:: CALL TXBFLS ; Listen - flush TCB, enter closed state. +.XSSYN:: CALL TXBFLS ; Syn-Sent - flush TCB, enter closed state. +.XSSYR:: XCT TCPCXT+.XSOPN ; Syn-Rcvd - handled same as OPEN below +.XSOPN:: XCT (D)[ ; Established (Open) + CALL TCPCLE ; In (only) - Can't happen + JFCL ; In (have Out) - Disconnect input + CALL TCPC30 ; Out (only) - Send FIN, enter FIN-WAIT-1 + CALL TCPC30] ; Out (have In) - " " " " +.XSFN1:: XCT (D)[ ; Fin-Wait-1 + JFCL ; In (only) - Disconnect input + CALL TCPCLE ; In (have Out) - Can't happen + CALL TCPCLE ; Out (only) - Can't happen + CALL TCPCLE] ; Out (have In) - Can't happen +.XSFN2:: XCT (D)[ ; Fin-Wait-2 + CALL TXBFLS ; In (only) - Flush, give up waiting + CALL TCPCLE ; In (have Out) - Can't happen + CALL TCPCLE ; Out (only) - Can't happen + CALL TCPCLE] ; Out (have In) - Can't happen +.XSCLW:: XCT (D)[ ; Close-Wait + CALL TCPCLE ; In (only) - Can't happen + JFCL ; In (have Out) - Disconnect input + CALL TCPC70 ; Out (only) - Send FIN, enter LAST-ACK + CALL TCPC70] ; Out (have In) - " " " " +.XSCLO:: XCT TCPCXT+.XSFN1 ; Closing - handled same as Fin-Wait-1 etc. +.XSCLA:: XCT TCPCXT+.XSFN1 ; Last-Ack - handled same as Fin-Wait-1 etc. +.XSTMW:: XCT TCPCXT+.XSFN1 ; Time-Wait - handled same as Fin-Wait-1 etc. +.XSTOT:: OFFSET 0 + + ; Closing output channel while in SYN-RCVD state. + ; Send a FIN and enter FIN-WAIT-1 state. +TCPC30: CALL TCPCLF + MOVEI J,.XSFN1 + JRST TCPC75 + + ; Closing output channel while in CLOSE-WAIT state. + ; Send a FIN and enter LAST-ACK state. +TCPC70: CALL TCPCLF + MOVEI J,.XSCLA +TCPC75: HRRM J,XBSTAT(I) + RET + +TCPCLF: MOVSI T,(TC%ACK+TC%FIN+%XBNOW) ; Tell TCP that output needs FIN and ACK. + JRST TCPOFR ; Go force out current buffer if any + +; TCPUC - Set "Reason-closed" states if not already set. +; T/ Reason to use, if none already exists. +; Clobbers Q +TCPUC: CALL TCPUCI +TCPUCO: HRRZ Q,XBCLSU(I) + CAIN Q, + HRRM T,XBCLSU(I) + RET +TCPUCI: HLRZ Q,XBCLSU(I) + CAIN Q, + HRLM T,XBCLSU(I) + RET + +; TXBFLS - Flush all info about a TCB from TCP viewpoint. +; Mostly consists of freeing up all buffers used, and then +; clearing out most other data cells of the TCB. +; Note that XBUSER and XBSTAU are not affected! +; TXBFLP - ditto but usable at PI level, it is careful not to smash +; things that MP level might be referencing. +; Clobbers A,T,Q +; TXBIFL - Flushes input queue +; TXBOFL - Flushes output queue (including retrans list!) + +TXBFLS: SETZM XBSTAT(I) + CALL TXBIFL + CALL TXBOFL + SETZM XBPORT(I) + SETZM XBHOST(I) + RET + +; TXBFLP - Things to be careful of: +; - swiping COS +; - flushing input queue (don't touch it) + +TXBFLP: CALL TXBOFL + SETZM XBSTAT(I) ; Say off-limits to PI level now. + SETZM XBPORT(I) + SETZM XBHOST(I) + LDB T,[XB$ICH (I)] ; See if input chan active + CAIN T, + CALL TXBIFL ; No input chan, so ensure input q flushed + CALL TCPUSI ; Alert user to mung + RET + +TXBIFL: SETZM XBINBS(I) + SETZM XBINPS(I) + SETZM XBIBP(I) + SETZM XBIBC(I) + MOVEI Q,XBITQH(I) + CALL PKPFLS + SKIPE XBITQH(I) + BUG CHECK,[TCP: Incompl input fls I=],OCT,I,[list ],OCT,XBITQH(I) + CALL TCPRWS ; Reset receive window. + RET + +TXBOFL: HRRZ A,XBOCOS(I) ; If current output seg exists, + CAIE A, + SKIPGE XBSTAT(I) ; and isn't locked by MP level, + CAIA + JRST [CALL PKTRTA ; then free it + SETZM XBOCOS(I) ; and clear the pointer. + SETZM XBOBP(I) + SETZM XBOBC(I) + JRST .+1] + SETZM XBORTT(I) + SETZM XBORTC(I) + MOVEI Q,XBORTQ(I) + CALL PKPFL ; Flush retrans list carefully. + SKIPE XBORTL(I) + BUG CHECK,[TCP: Incompl output fls, I=],OCT,I,[list ],OCT,XBORTQ(I) + MOVE A,XBSNXT(I) + MOVEM A,XBSUNA(I) ; Claim everything ACK'd. + SETZM XBSWND(I) ; Zero our send window. + SETZM XBSAVW(I) ; and available window + SETZM XBSUP(I) ; and urgent pointer. + RET + +PKPFLS: PUSH P,Q +PKPFL2: MOVE Q,(P) + CALL PKQGF(PK.TCP) + JUMPE A,POPQJ + CALL PKTRTA ; Should always be freeable. + JRST PKPFL2 + +; Ditto, but for flushing retransmit queue, which has to be special +; since packets are linked on IP output list as well as TCP list. +; Since we can't take packets off the IP output list here, we just set +; a flag telling output PI level to ignore the packet. + +PKPFL: PUSH P,Q +PKPFL3: MOVE Q,(P) + CALL PKQGF(PK.TCP) + JUMPE A,POPQJ + CONO PI,PIOFF + MOVE T,PK.FLG(A) ; Check packet flags + TLNN T,(%PKODN) ; Output done? + JRST [ TLO T,(%PKFLS) ; No, say to flush when hit it. + MOVEM T,PK.FLG(A) + CONO PI,PION + TRCPKT A,"PKPFL3 Packet not flushed" + JRST PKPFL4] + CONO PI,PION + CALL PKTRT +PKPFL4: SOSGE XBORTL(I) + BUG CHECK,[TCP: Retrans Q count err] + JRST PKPFL3 + +SUBTTL TCP Main Program Input + +; All TCP input segments for a connection are put on a queue that +; is headed at XBITQH. When this header is zero, there is no more +; input; if the %XBFIN flag is also set, the remote host has closed +; its transmit side and there will never be any more input. +; Segments are only added by PI level, at the end of the queue. +; Segments are only removed by MP level IOTs, at the start of the queue. +; (An incoming RST will of course flush the queue at PI level) + +; If XBIBP is non-zero, it points into the first segment on the input queue, +; and XBIBC is also valid; things are ready for MP IOTing. +; However, neither XBIBP nor XBIBC is meaningful if XBITQH is zero. + +; Input IOT - from IOTTB + SKIPA T,[SIOKT] ; Come here for SIOT entry +TCPI: MOVEI T,CHRKT + METER("TCP: syscal in") + HLRZ I,(R) ; Get TCB index + + ; Verify state, do misc setup for reading + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) ; Can't IOT if direct-connected to STY. + JRST IOCR10 ; "Chan in illegal mode" + HLRZ B,XBSTAU(I) ; Just reading state, don't need NETOFF. + SKIPG TCPTBI(B) ; Ensure meta-state allows reading. + JRST [ HLRZ B,XBCLSU(I) ; Can't read, see if reason OK + CAIN B,.XCFRN ; Only OK reason is clean fgn close. + JRST UNIEOF ; Yeah, just return quietly. + JRST IOCR10] + + MOVE E,[441000,,4] ; 8-bit bytes, 4 to a word + MOVEI B,[ + XBIBP(I) ; Byte pointer + XBIBC(I) ; # bytes to read + TCPIBG ; Routine to get next buffer + TCPIBD ; Routine to discard buffer + 0 ; not used + TRNA ; Negative - TCPIBG and TCPIBD will do waiting. + ] + CALL (T) + CAIA + AOS (P) + SKIPG XBIBC(I) ; If count for this buffer reached zero, + CALL TCPIBD ; Flush it so XBITQH is valid indication of input avail + RET + +; TCPIBD - Discard input buffer, invoked by I/O. +; This is always called before TCPIBG is. + +TCPIBD: SKIPN XBIBP(I) ; Make sure something's there to discard. + RET ; Nope, gone or was never set up. + MOVEI Q,XBITQH(I) ; Point to TCP input queue header + CALL PKQGF(PK.TCP) ; Get first thing off queue, into A + CAIN A, ; Something better be there. + BUG HALT,[TCP: IOTI queue lost] + + ; Check BP just out of sheer paranoia. + HRRZ T,XBIBP(I) ; Find addr BP points to (maybe +1 actual) + HLRZ Q,PK.TCP(A) ; Get addr of TCP header + CAIL Q,(T) ; Header better be less than BP! + JRST TCPIB2 + TRZ Q,PKBSIZ-1 ; Get addr of start of buffer + CAILE T,PKBSIZ(Q) ; BP should be within or just past end. +TCPIB2: BUG HALT,[TCP: IOTI BP incons] + + ; Okay, end of paranoia, just flush the buffer. + LDB T,[PK$TDL (A)] ; Find # chars we read + MOVN T,T + ADDM T,XBINBS(I) ; Update # chars avail for input. + CALL PKTRT ; Return packet to freelist. + SOSGE T,XBINPS(I) ; Decrement count of segs on input queue + BUG CHECK,[TCP: Input Q count incons] + CAIL T,%TCPMI/2 ; If we are now handling past 50% input, + JRST [ MOVSI T,(TC%ACK) ; Make sure we send an ACK + IORM T,XBSTAT(I) ; so new rcv window is reported. + JRST .+1] + CONO PI,NETOFF + CALL TCPRWS ; Set new receive window + CALL TXBIST ; Get new input chan state + HRLM T,XBSTAU(I) ; Set it. Note interrupt is avoided here. + CONO PI,NETON + SETZM XBIBP(I) + SETZM XBIBC(I) + RET ; Always return with simple POPJ + +TCPRWS: MOVEI T,%TCPMI + SUB T,XBINPS(I) ; Find # segs we can still queue up + CAIGE T,1 ; If no full segs left, + TDZA T,T ; Zero the window, no more segs allowed + IMUL T,XBRMSS(I) ; Else will take N * MSS bytes +TCPRW3: MOVEM T,XBRWND(I) + RET + +IFN 0,[ + ; This code turns out to lose because the code at TCPIS only + ; checks XBRWND to see whether to compact input or not, and as + ; long as XBRWND is non-zero, stuff will always be added to queue, + ; using up all the packet buffers. + ; Basically it's a question of whether or not to allow more input, + ; up to limits of last queued buffer, if the queue has too many + ; buffers on it. Metering will show whether most other implementations + ; win or lose with our buffer-alloc type windowing. +TCPRW2: HLRZ Q,XBITQH(I) ; Find # chars room in last seg + LDB T,[PK$TDL (Q)] + LDB Q,[PK$TDO (Q)] + ADDI Q,(T) + MOVEI T,576. + SUBI T,(Q) + CAIGE T, + SETZ T, + MOVEM T,XBRWND(I) + RET +] + +; TCPIBG - Get new input buffer (invoked by I/O, after TCPIBD) +; Return .+1 if can't get new buffer, must wait (Never, we do waiting) +; Return .+2 if OK, new BP and count set up. +; Return .+3 if "EOF", transfer complete + +TCPIBG: SKIPE XBIBP(I) ; Shouldn't be anything already there. + BUG HALT,[TCP: IOTI buf incons] +TCPIB3: SKIPN A,XBITQH(I) ; See if anything in input queue + JRST TCPIB5 ; No, go handle EOF. + LDB T,[PK$TDL (A)] ; Find # bytes input for this segment + CAIN T, ; Something probably shd be there. + BUG HALT,[TCP: IOTI null seg] + MOVEM T,XBIBC(I) ; Store as new # bytes + LDB T,[PK$TDO (A)] ; Get offset from start of header + HLRZ Q,PK.TCP(A) ; Get addr of TCP header + ROT T,-2 ; Divide offset by 4 + ADDI Q,(T) ; Point to right word + LSH T,-34. ; Right-justify the low 2 bits + HRL Q,(T)[441000 ? 341000 ? 241000 ? 141000] ; Get right LH for BP + MOVEM Q,XBIBP(I) ; Now store BP! + JRST POPJ1 ; Say ready to go again... + + ; No input available. First check to see if there will ever + ; be any more (FIN seen?), then whether to return right away or + ; hang. +TCPIB5: CONO PI,NETOFF ; Avoid timing inconsistencies + SKIPE A,XBITQH(I) ; Check again + JRST [ CONO PI,NETON ; Got some?? + JRST TCPIB3] ; Try again. + SKIPN XBINPS(I) ; No, should also have no segments + SKIPE XBINBS(I) ; and no bytes + BUG HALT,[TCP: IOTI count incons] + MOVE A,XBRWND(I) ; Save value of rcv window + CALL TCPRWS ; Then reset the window + CAME A,XBRWND(I) ; Was previous value correct? + METER("TCP: RCV.WND out of synch") + MOVE T,XBSTAT(I) ; Get flags + CONO PI,NETON + TLNE T,(%XBFIN) ; FIN seen, and input queue empty? + JRST TCPIB6 ; Yes, true EOF now. + + MOVE T,CTLBTS(U) ; See if call had "don't-hang" bit set + TRNE T,10 + JRST TCPIB7 ; No, return EOF. + SKIPN XBITQH(I) ; Wait until input queue has something. + CALL UFLS + JRST TCPIBG ; Then call again. + +TCPIB6: +TCPIB7: CALL TCPUSI ; Adjust user state. + JRST POPJ2 ; and return "EOF" + + +SUBTTL TCP Main Program Output + +; Output IOT - from IOTTB +; Output segments are chained together from XBORTQ, which is +; the "retransmit queue". +; The queue only contains segments which occupy sequence space, since +; these are the only ones which require ACKs and possible retransmit. +; All others are sent directly to the IP output queue. +; While the transmit connection is open, +; Segments are only added by MP level IOTs, at the end of the queue. +; Segments are only removed by PI level ACKs, at the start of the queue. + +; Main program I/O is done into the "Current Output Segment", which is NOT +; on the retransmit queue. There are three variables related to this COS. +; XBOCOS - ,, +; XBOBP - BP into the COS, for MP IOT writing. +; XBOBC - Count of # bytes left that MP IOT can deposit into. +; Note that the maximum possible size of the buffer is kept in PK$TDL +; (TCP segment Data Length). For windowing reasons it may be necessary +; to restrict the amount of space actually used, thus the initial value +; of XBOBC may be less than PK$TDL. This is why the initial value is also +; copied into the RH of XBOCOS, so that when XBOBC counts out we know +; exactly how much of the buffer was actually used. It is possible for +; XBOBC to be increased by interrupt level window processing, in order +; to increase utilization of the buffer. +; States: +; If XBOCOS is zero, XBOBP and XBOBC must also be zero; there is +; no COS. +; If XBOCOS is non-zero (a current output seg exists), then: +; if LH(XBOCOS) is zero, the segment hasn't yet been written +; into, and needs to be set up. +; XBOBP and XBOBC should be zero! +; else the segment is set up for writing. XBOBP should be set! +; If XBOBC is zero it means the segment now contains +; LH(XBOCOS) bytes of data. If this number is less +; than PK$TDL (max possible seg data) then the count +; may be reset to allow further output into this +; segment, or it may simply be sent as is. +; +; The current segment is put on the retransmit queue (and IP output queue) +; when: +; PI level (eg clock) decides it's time to send an ACK or do a FORCE. +; MP level IOT fills up the segment completely. +; MP level FORCE or CLOSE is invoked. +; The current segment is locked down during MP IOT, to keep PI level +; from ripping it away (which would leave entrails dangling). +; PCLSR'ing will clear this lock. If TCP flushes the TCB at PI level +; for some reason, XBOCOS will be freed unless locked. XBOBC and XBOBP +; will still be cleared even if locked, so as to cause a call to TCPOBW +; which will notice the condition and free the COS itself. + + SKIPA A,[SIOKT] ; Come here for SIOT entry +TCPW: MOVEI A,CHRKT + METER("TCP: syscal out") + HLRZ I,(R) ; Get TCB index from IOCHNM wd + + ; Verify state, do misc setup for writing, lock segment. + CONO PI,NETOFF + HRRZ B,XBSTAU(I) ; Get output chan state + SKIPG TCPTBO(B) ; See if meta-state allows writing + JRST IOCR10 ; Can't, say "chan not open" (ugh) + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) ; Also can't if direct-connected to STY. + JRST IOCR10 + MOVSI B,(%XBMPL) ; Set locked flag (must be sign bit!) + IORM B,XBSTAT(I) + CONO PI,NETON ; Okay, we've got it. + CALL SGNSET ; Set PCLSR routine to unlock flag. + XBSTAT(I) + SKIPN XBOCOS(I) ; If no COS there, + SETZM XBOBC(I) ; make SURE count is zapped so refill invoked. + MOVE E,[441000,,4] ; 8-bit bytes, 4 to a word + MOVEI B,[ + SETZ XBOBP(I) ; Output BP found here (sign sez is output) + XBOBC(I) ; # bytes of room remaining + TCPOBG ; Routine to get another buffer (not used) + TCPOBW ; Buffer full, routine to send it. + 0 ; Not used + TRNA] ; Negative - TCPOBG and TCPOBW will do waiting. + CALL (A) + CAIA + AOS (P) ; Pass on a skip return. + + ; User IOT is done, now unlock the segment. + ; We also check for wanting to do an immediate ACK and if needed + ; ship out the current buffer right now, without waiting + ; for the 1/2-sec clock to do it. + SKIPN A,XBSTAT(I) ; See if XBSTAT is still set + JRST IOCR10 ; No, take IOC error return! + CAIL A, ; It better still be locked! + BUG CHECK,[TCP: Output not locked] + CALL LSWPOP ; Clear the lock flag + TLNN A,(%XBNOW) ; Was "immediate-send" flag set? + RET ; Nope, can just return. + METER("TCP: TCPW exit force") + CONO PI,NETOFF + MOVSI T,(TC%PSH) ; Hmm, set up and shove out. + CALL TCPOFR ; and force out current output segment. + CONO PI,NETON + RET + +TCPOBG: BUG CHECK,[TCP: IOT called wrong rtn (TCPOBG)] + AOS (P) ; If proceeded, can still win. Make skip return + ; and drop through to TCPOBW. + +; TCPOBW - Write/Get output buffer, invoked by SIOKT/CHRKT when the +; buffer count (XBOBC) is zero. This routine can figure out +; whether it needs to ship out a full buffer, or get a new +; output buffer, or both. Always returns with XBOBP and +; XBOBC set up for additional output (otherwise it hangs and +; can be PCLSR'd) + +TCPOBW: SKIPE R,XBOCOS(I) ; Get PE ptr to COS + JRST [ HLRZ A,R ; Got a COS, see if already set up + JUMPN A,TCPOB5 ; Jump if so. + JRST TCPOB2] ; Else must set it up. + + ; No current segment, must get a new one. + HRRZ T,XBSTAU(I) ; First ensure output state is OK. + SKIPG TCPTBO(T) ; Skip if still OK to output. + JRST IOCR10 ; Blooie, say "Chan not open". + CALL PKTGF ; Get one, hang until we succeed. + MOVEI R,(A) ; Set up in std AC + TRCPKT R,"TCPOBW Alloc for IOT output buffer" + HRRZM R,XBOCOS(I) ; Store ptr + + ; Set up segment for IOT to deposit into. +TCPOB2: MOVEI T,%TCPMO ; Get max # segments allowed on queue + CAMG T,XBORTL(I) ; Hang until we have less than this. + CALL UFLS ; Note that conn closure will unhang too, + ; because it flushes output queue. + CALL TSOINI ; Initialize the segment (set up W, H) + LDB A,[PK$TDO (R)] ; Find offset data should start at. + TRNE A,3 + BUG HALT ; Should always start at wd boundary! + LSH A,-2 ; Find # words + ADDI A,(H) ; Add address of TCP header, + HRLI A,441000 ; and now we have our initial BP. + MOVEM A,XBOBP(I) ; Set it up. + LDB A,[PK$TDL (R)] ; Get max length avail in this segment + + ; Now have a fresh buffer and nothing else to wait for. + ; Freeze the world, make sure it's still OK to output, and find + ; out how big an output segment we can allow. +TCPOB4: CONO PI,NETOFF + HRRZ T,XBSTAU(I) ; Still OK to output? Check again. + SKIPG TCPTBO(T) + JRST [ MOVEI A,(R) ; Bah, must return buffer. + CALL PKTRTA + SETZM XBOCOS(I) + CONO PI,NETON + JRST IOCR10] ; Barf "Chan not open". + MOVEI T,(I) ; Get index in T for PCLSRing. + CALL TCPOB9 ; Check available window + JRST [ CONO PI,NETON ; Window too small, allow ints + CALL TCPOB9 + CALL UFLS + JRST TCPOB4] ; Big enough, go back and re-try stuff. + LDB Q,[PK$TDL (R)] ; Get max # bytes available + CAMLE Q,XBSAVW(I) ; Greater than window? + MOVE Q,XBSAVW(I) ; Yeah, truncate down to this size. + HRLM Q,XBOCOS(I) ; Store original # bytes in LH of XBOCOS + MOVEM Q,XBOBC(I) + CONO PI,NETON + RET ; Okay, all set up, return. + +TCPOB9: MOVE A,XBSWND(T) + LSH A,-2 ; Get 25% offered window + CAML A,XBSAVW(T) ; If 25% offered > avail window, + RET ; punt and wait for better stuff. + JRST POPJ1 + + ; Here when we were all set up, and output has used up all + ; of the buffer space initially available. Check to make sure + ; there isn't more we can fill out, and if not then fire off + ; the segment. +TCPOB5: HLRZ T,XBOCOS(I) ; Get # bytes we originally had + CONO PI,NETOFF ; Avoid magic changes in send window + CAML T,XBSAVW(I) + JRST TCPOB6 ; Send window same or smaller (!), send seg. + MOVE Q,XBSAVW(I) ; Send window is bigger! Get new size + LDB A,[PK$TDL (R)] ; Get max size + CAMLE A,Q + MOVEI A,(Q) ; Use minimum of max size and send window. + MOVEI Q,(A) ; Save result + SUBI A,(T) ; Find # more bytes we can hack + CAIG A, ; If there's no more, + JRST TCPOB6 ; Just send it off anyway. + HRLM Q,XBOCOS(I) ; Hurray, got more! Store new original # + MOVEM A,XBOBC(I) ; And set up new count + CONO PI,NETON + RET ; And return happily. + +TCPOB6: TRCPKT R,"TCPOB6 IOT Send" + CALL TCPOB7 + JRST TCPOBW + +TCPOB7: DPB T,[PK$TDL (R)] ; Okay, say this many bytes of data are in seg + PUSH P,B + PUSH P,C + PUSH P,E + MOVSI T,(TC%PSH) ; Ensure seg is pushed out. + IORM T,XBSTAT(I) + CALL TSOSND ; Send data segment (# bytes in PK.TCI) + ; This clobbers a lot of ACs! + SETZM XBOCOS(I) ; No current output segment now. + CONO PI,NETON + SETZM XBOBP(I) + SETZM XBOBC(I) + POP P,E + POP P,C + POP P,B + RET + +; TCPOFR - Force out partially-filled current output segment +; Must have NETOFF. +; Called by FORCE and CLOSE at MP level +; by TCPCLK at PI clock level +; Note that we try to never have stuff in the COS which would +; over-run our send window, by hanging in MP IOT. This will +; be slightly screwed up if the receiver suddenly decreases the window +; size, since this routine always sends the whole thing anyway, +; but it's probably OK (helps avoid SWS) +; I/ TCB index +; T/ additional flags to use (PUSH, URG, FIN) +; Clobbers R and everything that TSOSND does (a lot!) + +TCPOFR: MOVE A,XBSTAT(I) ; Get flags for connection + TLNE A,(%XBCTL) ; Wants anything added on? + IOR T,A ; Yes, OR the bits in. + JUMPL A,TCPOF6 ; If locked at MP level, don't send it! + SKIPN R,XBOCOS(I) ; See if current output seg exists + JRST TCPOF5 ; No, can't hack now. + HLRZ TT,R ; Get # bytes of original buffer size + JUMPE TT,TCPOF5 ; If none, nothing to hack. + SUB TT,XBOBC(I) ; Subtract # left, to get # bytes data + CAIG TT, + JRST [ SETZ TT, ; No data, see if a flag wants to be sent. + TLNN T,(TC%FIN+TC%ACK+TC%SYN) ; Any of these are impt. + JRST TCPOF9 ; Nope, do nothing. + JRST .+1] + DPB TT,[PK$TDL (R)] ; Store back # bytes of real data + AND T,[TH%CTL] ; Mask off the flags + IORM T,XBSTAT(I) ; Stuff in as requests + TRCPKT R,"TCPOFR Force send" + CALL TSOSND ; Send out the stuff + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) +TCPOF9: RET + + ; No current output segment, so no data to send. Check, though, + ; to see if any flags need sending. +TCPOF5: TLNN T,(TC%SYN+TC%ACK+TC%FIN) + RET ; Nope, just return. + MOVE E,T ; They do! Save em against smashage + CALL PKTGFI ; Try to get a buffer (clobbers T,Q) + JRST TCPOF6 ; Ugh, failed, see about setting flags. + MOVEI R,(A) + TRCPKT R,"TCPOF5 Alloc and send flags only in TCPOFR" + MOVE T,E ; Restore flags + CALL TSOSNR ; Set up the packet and send it! + RET + + ; Can't get packet now, so set up the request flags for later hacking. + ; Also comes here when current output seg is locked at MP level. +TCPOF6: AND T,[%XBCTL] ; Clear out extraneous bits + TLO T,(%XBNOW) ; Ask to send stuff immediately + IORM T,XBSTAT(I) ; and set flags back. + RET + +; TCPOSB - Routine similar to TCPOBW, except that it doesn't hang, +; so that it is suitable for calling at PI level (by STYNTC esp) +; Returns .+1 if can't set up output buffer for writing. +; Returns .+2 if output buff is all set up, with non-zero XBOBC. + +TCPOSB: SKIPE R,XBOCOS(I) + JRST [ HLRZ A,R ; Have COS, see if already set up + JUMPN A,TCPOS5 ; Jump if so. + JRST TCPOS2] ; Else just set it up. + + ; No current segment, get a new one. + HRRZ T,XBSTAU(I) ; First ensure output state is OK. + SKIPG TCPTBO(T) ; Skip if still OK to output. + RET ; Blooie. + CALL PKTGFI ; Get one, skip if successful + RET ; Sigh... + MOVEI R,(A) ; Set up in std AC + TRCPKT R,"TCPOSB Alloc for STYNET output data" + HRRZM R,XBOCOS(I) ; Store ptr + + ; Set up segment for IOT to deposit into. +TCPOS2: MOVEI T,%TCPMO ; Get max # segments allowed on queue + CAMG T,XBORTL(I) ; Fail if we have more than this. + RET + CALL TSOINI ; Initialize the segment (set up W, H) + LDB A,[PK$TDO (R)] ; Find offset data should start at. + TRNE A,3 + BUG HALT ; Should always start at wd boundary! + LSH A,-2 ; Find # words + ADDI A,(H) ; Add address of TCP header, + HRLI A,441000 ; and now we have our initial BP. + MOVEM A,XBOBP(I) ; Set it up. + LDB A,[PK$TDL (R)] ; Get max length avail in this segment + + ; Now have a fresh buffer and nothing else to wait for. + ; Freeze the world, make sure it's still OK to output, and find + ; out how big an output segment we can allow. +TCPOS4: CONO PI,NETOFF + HRRZ T,XBSTAU(I) ; Still OK to output? Check again. + SKIPG TCPTBO(T) + JRST [ MOVEI A,(R) ; Bah, must return buffer. + CALL PKTRTA + SETZM XBOCOS(I) + CONO PI,NETON + RET] ; Barf "Chan not open". + MOVEI T,(I) ; Get index in T for testing (no PCLSR) + CALL TCPOB9 ; Check available window + JRST NETONJ ; Window too small, just return + + LDB Q,[PK$TDL (R)] ; Get max # bytes available + CAMLE Q,XBSAVW(I) ; Greater than window? + MOVE Q,XBSAVW(I) ; Yeah, truncate down to this size. + HRLM Q,XBOCOS(I) ; Store original # bytes in LH of XBOCOS + MOVEM Q,XBOBC(I) + CONO PI,NETON + AOS (P) + RET ; Okay, all set up, return. + + ; Here when we were all set up, and output has used up all + ; of the buffer space initially available. Check to make sure + ; there isn't more we can fill out, and if not then fire off + ; the segment. +TCPOS5: HLRZ T,XBOCOS(I) ; Get # bytes we originally had + CONO PI,NETOFF ; Avoid magic changes in send window + CAML T,XBSAVW(I) + JRST TCPOS6 ; Send window same or smaller (!), send seg. + MOVE Q,XBSAVW(I) ; Send window is bigger! Get new size + LDB A,[PK$TDL (R)] ; Get max size + CAMLE A,Q + MOVEI A,(Q) ; Use minimum of max size and send window. + MOVEI Q,(A) ; Save result + SUBI A,(T) ; Find # more bytes we can hack + CAIG A, ; If there's no more, + JRST TCPOS6 ; Just send it off anyway. + HRLM Q,XBOCOS(I) ; Hurray, got more! Store new original # + MOVEM A,XBOBC(I) ; And set up new count + CONO PI,NETON + AOS (P) + RET ; And return happily. + +TCPOS6: TRCPKT R,"TCPOS6 STYNET Send" + CALL TCPOB7 + JRST TCPOSB + +TCPBI: +TCPBO: RET ; No-ops, labels left in case want to use. + +; STATUS - from LH(DTSTB) +; Must return status in LH(D). Must not smash C,R. +; R/ addr of IOCHNM word + +TCPSTA: HLRZ I,(R) ; Get TCB index + SKIPN XBUSER(I) ; Probably an error if this is zero. + BUG CHECK,[TCP: STATUS on unused conn ],OCT,I + SETZ D, + SKIPN XBSTAT(I) + RET + HRRZ A,(R) ; Find whether input or output + CAIN A,TCPDUI + SKIPA T,[TXBIST] + MOVEI T,TXBOST + CALL (T) + DPB T,[140600,,D] + RET + + +TXBIST: HRRZ T,XBSTAT(I) + CAIL T,.XSTOT + BUG HALT + SKIPGE T,XBCTBI(T) ; Get conversion + JRST [ SKIPN XBITQH(I) ; Must test for input avail - any segs? + SKIPA T,(T) ; None avail, use standard + MOVE T,1(T) ; Have some waiting, use alternate state + RET] + RET +XBCTBI: OFFSET -. +.XSCLS:: SETZ [%NTCLS ? %NTCLI] ; 0 Closed +.XSSYQ:: 0 ; Technically this is an impossible state... +.XSLSN:: %NTLSN ; 1 Listen +.XSSYN:: %NTSYN ; 4 Syn-Sent +.XSSYR:: %NTSYR ; 2 Syn-Rcvd +.XSOPN:: SETZ [%NTOPN ? %NTINP] ; 5/11 Established (open) +.XSFN1:: SETZ [%NTOPN ? %NTINP] ; 7 Fin-Wait-1 +.XSFN2:: SETZ [%NTOPN ? %NTINP] ; 7 Fin-Wait-2 +.XSCLW:: SETZ [%NTCLU ? %NTCLI] ; 3/10 Close-Wait +.XSCLO:: SETZ [%NTCLS ? %NTCLI] ; 7/10 Closing +.XSCLA:: SETZ [%NTCLS ? %NTCLI] ; 7 Last-Ack +.XSTMW:: SETZ [%NTCLS ? %NTCLI] ; 7 Time-Wait +.XSTOT:: OFFSET 0 + + +TXBOST: HRRZ T,XBSTAT(I) + CAIL T,.XSTOT + BUG HALT + SKIPGE T,XBCTBO(T) ; Get conversion + JRST [ SKIPN XBORTQ(I) ; Must test for output queued + SKIPA T,(T) ; None, use standard + MOVE T,1(T) ; Have some output waiting, use alternate state + RET] + RET +XBCTBO: OFFSET -. +.XSCLS:: %NTCLS ; 0 Closed +.XSSYQ:: 0 ; Technically this is an impossible state... +.XSLSN:: %NTLSN ; 1 Listen +.XSSYN:: %NTSYN ; 4 Syn-Sent +.XSSYR:: %NTSYR ; 2 Syn-Rcvd +.XSOPN:: SETZ [%NTOPN ? %NTWRT] ; 5/6 Established (open) +.XSFN1:: %NTCLX ; 7 Fin-Wait-1 +.XSFN2:: %NTCLX ; 7 Fin-Wait-2 +.XSCLW:: SETZ [%NTOPN ? %NTWRT] ; 5/6 Close-Wait +.XSCLO:: %NTCLX ; 7 Closing +.XSCLA:: %NTCLX ; 7 Last-Ack +.XSTMW:: %NTCLX ; 7 Time-Wait +.XSTOT:: OFFSET 0 + + + +; WHYINT - from RH(DTSTB) +; Results are: +; A/ %WYTCP +; B/ +; C/ input - # bytes in input buff +; output - # bytes of room avail in output buff +; D/ Close reason (only valid if state %NTCLS) + +TCPWHY: HLRZ I,(R) ; Get TCB index + METER("TCP: syscal whyint") + CAIL I,XBL + BUG HALT,[TCP: WHY idx bad] + CALL TCPSTA + LDB B,[140600,,D] ; Get state for channel + HRRZ A,(R) ; Find whether input or output + CAIN A,TCPDUI + JRST [ HLRZ D,XBCLSU(I) ; Get input close reason + MOVSI C,(XB%STY) + TDNE C,XBUSER(I) ; No input avail if direct-conn to STY + JRST [ SETZ C, ? JRST TCPWH5] + SKIPLE C,XBINBS(I) + JRST TCPWH5 + SKIPN C,XBITQH(I) + JRST TCPWH5 + LDB C,[PK$TDL (C)] + JRST TCPWH5] + HRRZ D,XBCLSU(I) ; Get output close reason + SKIPN C,XBOBC(I) ; Get # bytes of room left in current pkt + JRST [ MOVEI C,%TCPMO ; If none, return total queue space instead + SUB C,XBORTL(I) + IMUL C,XBSMSS(I) + CAIG C, + SETZ C, + JRST .+1] +TCPWH5: MOVEI A,%WYTCP + JRST POPJ1 + + + +; RFNAME - from LH(DRFNTB) +; A/ LH of IOCHNM word for channel. + +TCPRCH: MOVEI I,(A) + LDB B,[.BP TH%DST,XBPORT(I)] + LDB C,[.BP TH%SRC,XBPORT(I)] + MOVE D,XBHOST(I) + MOVEI W,4 + POPJ P, + +; RFPNTR - from RH(DRFNTB) +TCPRFP: JRST OPNL34 + +; IOPUSH/POP - from LH(RSTBI) +TCPIOP: HRRZ T,R + SUBI T,IOCHNM(U) + CAIN I, + SKIPA T,[77] ; IOPUSH, use 77 + ADDI T,1 ; IOPOP, use chan+1 + HLRZ I,(R) ; Get TCB index + HRRZ B,(R) ; Get direction + CAIN B,TCPDUI ; as a BP to chan # + SKIPA B,[XB$ICH (I)] + MOVE B,[XB$OCH (I)] + DPB T,B ; Store new saved channel # + POPJ P, + +; RESET - from RH(RSTBI) +; This doesn't have to do anything for a while yet. +TCPRST: + POPJ P, + +; FORCE - from LH(DFRCTB) +; Should force out the TCP segment currently being written, +; and give it a good shove (ie PUSH). +; A/ LH of IOCHNM word, in RH. +; H/ IOCHNM word +; R/ ,, +TCPFRC: METER("TCP: syscal force") + HRRZ B,(R) ; This should be a TCP output channel. + CAIE B,TCPDUO ; If not output, must be input, so + JRST OPNL2 ; say "wrong direction". + HLRZ I,(R) ; Get TCB index + CAIL I,XBL ; Ensure validity + BUG HALT,[TCP: FRC bad idx] + + ; Ensure that state allows sending anything. + CONO PI,NETOFF ; So state doesn't change while we think. + HRRZ J,XBSTAT(I) + CAIE J,.XSOPN + CAIN J,.XSCLW + CAIA + JRST OPNL7 ; Bad state, say "device not ready". + + PUSH P,R + MOVSI T,(TC%PSH) ; Set PUSH flag (but not ACK, to avoid + ; forcing send of empty buffer) + CALL TCPOFR ; Force out! Clobber many ACs. + CONO PI,NETON + POP P,R + JRST POPJ1 + + +; FINISH - from RH(DFRCTB) +; We already know that R is OK since FORCE looked at it first. +; In fact, I is still set up. +; R/ addr of IOCHNM word + +TCPFIN: METER("TCP: syscal finish") + MOVSI T,(%XBNOW) + TDNE T,XBSTAT(I) ; Wait until this bit is off (XBOCOS put on Q) + CALL UFLS + SKIPE XBORTQ(I) ; Hang until retransmit queue is empty. + CALL UFLS + JRST POPJ1 + +SUBTTL TCP STY connection routines + +; STYTCP - invoked by STYNTC routine during 1/2 sec clock, for +; STYs connected to TCP channels. +; R/ TTY # + +STYTCP: MOVE I,STYNTI-NFSTTY(R) ; Get TCB index for connection + LDB TT,[XB$STY (I)] ; Verify that TCB thinks we're hooked up + CAIE TT,(R) + BUG ; It doesn't?? + + ; First, check for and transfer any input for the STY. + HLRZ T,XBSTAU(I) ; Get input state + SKIPG TCPTBI(T) ; Make sure we can do input. + JRST STYTC9 ; Nope, must disconnect. +STYTC1: SOSGE XBIBC(I) + JRST [ CALL TCPIBD ; Discard input buffer if any + HRRZ A,XBITQH(I) ; Any more input avail? + JUMPE A,STYTC5 ; No, done, check for output. + CALL TCPIBG ; Have some! Set it up. Shd never hang. + JFCL + JRST STYTC1] + ILDB A,XBIBP(I) ; Get the byte + TRNE A,200 ; Special char? + JRST [ AOS XBIBC(I) ; Ugh, must back up and get user's attention + MOVSI B,8._14 ; Back up both count and 8-bit byte pointer + ADDM B,XBIBP(I) ; by adding to P field of BP + JRST STYTC9] ; Go disconnect. + EXCH R,I ; I gets TTY #, R gets TCB index + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + CALL NTYI5 ; Give the char to TTY input interrupt level + CONO PI,TTYON + POP P,R ; Note reverse order, so R gets TTY # + POP P,I ; and I gets TCB index again. + JRST STYTC1 ; Try for more input. + + ; Transfer chars from STY output to TCP connection +STYTC5: SKIPGE TTYOAC(R) ; Do we have any output? + JRST STYTC7 ; No, all's done, force out what we did. + HRRZ A,XBSTAU(I) ; Check output state + SKIPG TCPTBO(A) ; to verify that TCB is healthy. + JRST STYTC9 ; Ugh, go disconnect STY. + MOVSI A,(%XBMPL) + IORM A,XBSTAT(I) ; Lock COS against PI level snarfing + + SKIPE XBOCOS(I) + SKIPG E,XBOBC(I) ; Get # bytes room in output buff + JRST [ + ; Set up buffer, etc, possibly forcing out existing buff. + PUSH P,R + CALL TCPOSB ; Invoke special hang-less routine. + JRST [POP P,R ; If can't get any more room, jump to STYTC6 + JRST STYTC6] + POP P,R + SKIPG E,XBOBC(I) ; OK, should have bytes now. + BUG + JRST .+1] + SKIPN D,XBOBP(I) ; Get BP into buffer + BUG + EXCH R,I + CONO PI,TTYOFF + MOVEM D,DBBBP ; Set up buffer for TTY output interrupt level + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ; Generate output + SETZM TYPNTF + POP P,R + EXCH R,I ; Restore I/ TCB #, R/ TTY # + MOVE D,DBBBP ; Advance pointers + MOVEM D,XBOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ; Minus # chars output generated + CONO PI,TTYON + ADDM E,XBOBC(I) + JRST STYTC5 ; Check for more output + + ; No more output or we can't get more room, force out what + ; we've currently got. +STYTC6: CALL TCPUII ; Reactivate STY (expensive crock, but...) +STYTC7: MOVSI A,(%XBMPL) ; Unlock the COS + ANDCAM A,XBSTAT(I) + MOVSI T,(TC%PSH) ; PUSH this stuff + CALL TCPOFR ; Force out buffer + JRST STYNT8 ; Then go check other STYs. + + + ; Disconnect STY and get user's attention. Note this may be + ; buggy in that STY output has not yet been transferred to the + ; net by the time we get here, if we're here due to a 200 char. +STYTC9: PUSH P,I + MOVEI I,(R) ; Set up I/ TTY # + CALL NSTYN0 ; Disconnect it + BUG + POP P,I + CALL TCPUII ; Wake up the user program + JRST STYNT8 ; Go handle other STYs. + +IFN 0,[ +;CALLED AT CLOCK LEVEL FROM STYNTC WHEN A CHAOS STY IS ENCOUNTERED +;TTY NUMBER IN I & R +STYCHA: MOVE I,STYNTI-NFSTTY(R) ;GET CHAOS INDEX + MOVE TT,CHSSTA(I) + TLNN TT,%CFSTY + JRST 4,. ;CHAOS CONNECTION CLAIMS NOT BE CONNECTED? + JUMPL TT,STYCH9 .SEE %CFOFF ;OK TO USE? IF NOT, DISCONNECT + SKIPGE TTYOAC(R) ;ANY OUTPUT? + JRST STYCH1 ;NO, CHECK FOR INPUT + SKIPN D,CHSOBP(I) ;IF BUFFER ALLOCATED, USE IT + JRST [ SKIPG CHSNOS(I) ;OTHERWISE ALLOCATE ONE + JRST STYCH1 ;WINDOW FULL, WAIT UNTIL REACTIVATED + PUSHJ P,CHABGI + JRST STYCH3 ;NO CORE, WAIT ONE CLOCK TICK + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSOBP(I) + MOVEI E,%CPMXC + MOVEM E,CHSOBC(I) + JRST .+3 ] + SKIPG E,CHSOBC(I) + JRST STYCH4 ;BUFFER FULL, FORCE IT + EXCH R,I ;I GETS TTY, R GETS CHAOS + CONO PI,TTYOFF + MOVEM D,DBBBP ;SET UP BUFFER FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;GENERATE OUTPUT + SETZM TYPNTF + POP P,R + EXCH R,I ;I GETS CHAOS, R GETS TTY + MOVE D,DBBBP ;ADVANCE POINTERS + MOVEM D,CHSOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ;MINUS # CHARS OUTPUT GENERATED + CONO PI,TTYON + ADDM E,CHSOBC(I) +STYCH4: PUSHJ P,CHAFC1 ;FORCE THE BUFFER + JRST STYCHA ;CHECK FOR MORE OUTPUT + +STYCH3: PUSHJ P,CHINTI ;REACTIVATE SO WILL COME BACK ON NEXT CLOCK TICK +STYCH1: SOSGE CHSIBC(I) ;GET INPUT, IF ANY + JRST [ PUSHJ P,CHAIBD ;DISCARD EXHAUSTED INPUT BUFFER, IF ANY + HLRZ A,CHSIBF(I) + JUMPE A,STYNT8 ;NONE, RETURN TO STYNTC + LDB TT,[$CPKOP(A)] + CAIE TT,%CODAT + JRST STYCH9 ;RANDOM PACKET, DISCONNECT + PUSHJ P,CHPKIA ;ACKNOWLEDGE GOBBLING OF THIS PACKET + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + LDB E,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEM E,CHSIBC(I) + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSIBP(I) + JRST STYCH1 ] + ILDB A,CHSIBP(I) ;GET CHARACTER OF INPUT + TRNE A,200 + JRST [ AOS CHSIBC(I) ;WOOPS, SPECIAL CHARACTER, NEEDS USER ATTENTION + MOVSI A,8_14 ;SO PUT IT BACK AND DISCONNECT + ADDM A,CHSIBP(I) + JRST STYCH9 ] + EXCH R,I ;I GETS TTY, R GETS CHAOS + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL + CONO PI,TTYON + POP P,R + POP P,I ;I GETS CHAOS, R GETS TTY ((POP IN REVERSE ORDER)) + JRST STYCH1 ;TRY FOR MORE INPUT + +STYCH9: PUSH P,I + MOVE I,R ;I GETS TTY + PUSHJ P,NSTYN0 ;DISCONNECT THE STY + JRST 4,. + POP P,I ;I GETS CHAOS + PUSHJ P,CHINTI ;WAKE UP THE TELNET SERVER + JRST STYNT8 ;GO HANDLE OTHER STYS +] ;ifn 0 + +SUBTTL Other TCP system call functions + +; TCPRQ - Handle .CALL NETRFC, return port # of next pending +; request for connection (SYN). +; Perhaps return a uniquizer in LH, so know when see +; the same request again? + +TCPRQ: TRNE C,%NQREF ; Skip if just getting, not flushing. + JRST TCPRQ5 + METER("TCP: syscal netrfc get") + CONO PI,NETOFF ; In case a RST comes for it or something. +; MOVE I,TCPRQL ; Get last thing stored on queue + SETOB B,D ; Look for any match + CALL TCPRQS ; Search the queue... + JUMPL A,OPNL4 ; None, say "file not found". + MOVEI I,(A) + LDB A,[.BP TH%DST,XBPORT(I)] ; Get local port # for the SYN + HRLI A,(I) ; And put index in LH as uniquizer. + CONO PI,NETON + JRST POPJ1 + +TCPRQ2: BUG CHECK,[TCP: Pending SYN smashed!] + RET + + ; Refuse indicated connection. +TCPRQ5: METER("TCP: syscal netrfc ref") + CAIGE W,2 ; Must have 2 args + JRST OPNL30 ; "Too few args" + HLRE D,A ; Get identifier + HRRE B,A + CONO PI,NETOFF + CALL TCPRQS ; Search for the queued SYN + JUMPL A,OPNL4 + + ; Now must refuse connection. + MOVEI I,(A) + MOVEI Q,XBITQH(I) + CALL PKQGF(PK.TCP) ; Get queued SYN segment + SKIPN XBITQH(I) ; Should have been only one + SKIPG R,A ; and should have been one! + BUG HALT + CALL TXBFLS ; Flush the TCB. + SOSGE TCPRQN ; Decrement count of queued SYNs + BUG HALT + HLRZ W,PK.IP(R) ; Move all this setup somewhere modular. + HLRZ H,PK.TCP(R) + LDB TT,[PK$TDL (R)] + MOVE E,TH$CTL(H) + TLNE E,(TC%SYN) + ADDI TT,1 + TLNE E,(TC%FIN) + ADDI TT,1 + CALL TSISLR ; Respond to this req with RST+ACK + CONO PI,NETON + JRST POPJ1 + +; TCPRQS - Search pending-RFC queue. Must be called with NETOFF!! +; B/ local port # (-1 for any) +; D/ Index #, -1 for any (searches back from last one stored) +; Clobbers T,Q +; Returns +; A/ Index to matching SYN (-1 if no match) + +TCPRQS: JUMPGE D,TCPRQ7 + MOVE A,TCPRQL + MOVEI C,1 +TCPRQ6: HRRZ T,XBSTAT(A) ; See if right state + CAIN T,.XSSYQ + JRST [ LDB T,[.BP TH%DST,XBPORT(A)] + CAIL B, + CAMN T,B + RET + JRST .+1] + SOJGE A,TCPRQ6 + MOVEI A,XBL-1 + SOJGE C,TCPRQ6 +TCPRQ9: SETO A, + RET + +TCPRQ7: SKIPL A,D + CAIL D,XBL + JRST TCPRQ9 + HRRZ T,XBSTAT(A) ; Verify state + CAIE T,.XSSYQ + JRST TCPRQ9 + LDB T,[.BP TH%DST,XBPORT(A)] ; Got one! Get local port # + CAIL B, + CAIN T,(B) ; Must match given arg unless -1 + RET ; Won! + JRST TCPRQ9 + +ifn 0,[ +TCPRQS: MOVEI A,TCPRQH-PK.TCP +TCPRQ6: MOVEI Q,(A) ; Save ptr to prev node + HRRZ A,PK.TCP(A) ; Get ptr to next PE + JUMPE A,TCPRQ8 ; If not there, return 0 as error. + JUMPL D,TCPRQ7 + CAIE A,(D) ; See if identifier matches + JRST TCPRQ6 ; Jump if not. +TCPRQ7: HLRZ T,PK.TCP(A) ; Yes, verify port number + CAIN T, ; Ensure ptr to TCP header exists. + BUG HALT + LDB T,[TH$DST (T)] + CAIE T,(B) + JRST TCPRQ6 ; Nope, get next thing. + + ; Found it! Take off list, a bit tricky. + SOSGE TCPRQN ; Decrement count of entries + BUG HALT + MOVSI T,(%PQFL2) ; Clear the on-list flag for PK.TCP + ANDCAM T,PK.FLG(A) +IFN 2-PK.TCP,.ERR TCPRQS must fix %PQFL2 to match PK.TCP + HRRZ T,PK.TCP(A) ; Get its next-ptr + HRRM T,PK.TCP(Q) ; Store in node previous to this one. + JUMPN T,TCPRQ8 ; If wasn't last thing, all's well. + CAIN Q,TCPRQH-PK.TCP ; Last thing. If prev was actually hdr, + SETZ Q, ; must store zero. + HRLM Q,TCPRQH ; Set new "last" ptr in hdr. +TCPRQ8: + RET + +] ;ifn 0 + +; TSOINI - set up a raw PE for use as a TCP output segment. Means +; setting IP, TCP header pointers properly, so that all fields +; are contiguous. Note that PK.TCI is set to indicate XBSMSS(I) +; bytes of (available) data storage! +; Sets up PK.IP, PK.TCP, and PK.TCI. +; R/ PE ptr +; I/ TCB connection index (val put into PK.TCI) +; Returns with R, W, H pointing to PE, IP hdr, and TCP hdr. +; +; TSOINA - Ditto, but takes arg in A and only clobbers T (doesn't set W, H) + + +TSOINI: HRRZ W,PK.BUF(R) ; Get addr of buffer + HRLM W,PK.IP(R) ; Store as IP header addr + MOVEI H,(I) ; Set up TCI with all fields. + ANDI H,PK%TCB + IOR H,[<<%TCPHL*4>_<.TZ PK%TDO,>>] + MOVEM H,PK.TCI(R) ; + MOVE H,XBSMSS(I) ; Allow XBSMSS(I) bytes with assumed offset. + DPB H,[PK$TDL (R)] + MOVEI H,%TCPHL(W) ; For now, this will do. + HRLM H,PK.TCP(R) ; Store as TCP header addr + RET + +TSOINA: HRRZ T,PK.BUF(A) ; Get addr of buffer + HRLM T,PK.IP(A) ; Store as IP header addr + ADDI T,%TCPHL ; For now, this will do to get TCP hdr. + HRLM T,PK.TCP(A) ; Store as TCP header addr + MOVEI T,(I) ; Set up TCI with all fields. + ANDI T,PK%TCB + IOR T,[<<%TCPHL*4>_<.TZ PK%TDO,>>] + MOVEM T,PK.TCI(A) ; Set up index and header length fields + MOVE H,XBSMSS(I) ; Allow XBSMSS(I) bytes with assumed offset. + DPB H,[PK$TDL (R)] + RET + +; TCPUSI - TCP User State-change Interrupt. Called each time connection +; changes state (.XSnnn) or I/O queues start/end. Always tries +; to interrupt user, except for change %NTWRT->%NTOPN on output +; and %NTINP->%NTOPN on input. +; Moon: Interrupt when input rcvd and buff empty, or output full +; and becomes reasonably non-full. +; Clobbers T, Q + +TCPUSI: METER("TCP: tcpusi called") + CALL TXBIST ; Check input state + HLRZ Q,XBSTAU(I) + CAIE T,(Q) ; New state? + JRST TCPUS3 ; Yes, go handle. +TCPUS2: CALL TXBOST + HRRZ Q,XBSTAU(I) + CAIN T,(Q) + RET + + ; Output channel state change + ; Q/ old state, T/ new state (%NT values, not .XS) + HRRM T,XBSTAU(I) ; Store new state (old in Q) + CAIN Q,%NTOPN ; If was open + CAIE T,%NTWRT ; Changing to buff-full + CAIA + RET ; Then don't interrupt. + MOVE Q,TCPTBO(Q) + CAMN Q,TCPTBO(T) ; See if meta-state change + RET ; Nope, ignore. + LDB Q,[XB$OCH (I)] ; Yes, get channel # + METER("TCP: User O ints") + CALRET TCPUS5 + + ; Input channel state change +TCPUS3: HRLM T,XBSTAU(I) ; Store new state (old in Q) + CAIN Q,%NTINP ; If was input avail + CAIE T,%NTOPN ; Changing to plain open + CAIA + JRST TCPUS2 ; Then don't interrupt. + MOVE Q,TCPTBI(Q) + CAMN Q,TCPTBI(T) ; See if meta-state change + JRST TCPUS2 ; No + ; Drop thru to interrupt + + ; Give input channel interrupt +TCPUII: METER("TCP: User I ints") + LDB Q,[XB$STY (I)] ; See if hooked to STY + JUMPN Q,TCPUSS ; Jump to handle STY stuff if so. + LDB Q,[XB$ICH (I)] ; No, just get input chan + CALL TCPUS5 + JRST TCPUS2 + + ; Give interrupt to STY that TCB is connected to. + ; Q/ TTY # +TCPUSS: CONO PI,PIOFF ; Protect list hacking + SKIPL STYNTL-NFSTTY(Q) ; Don't put on list twice + JRST PIONJ + MOVE T,STYNTA ; Add to list + MOVEM T,STYNTL-NFSTTY(Q) + MOVEM Q,STYNTA + JRST PIONJ + + ; Interrupt on channel in Q. +TCPUS5: JUMPE Q,CPOPJ ; May be no channel there. + PUSH P,U + SKIPN U,XBUSER(I) + BUG HALT ; Jumpe above should catch this. + MOVSI T,(SETZ) + IORM T,PIRQC(U) + CAIN Q,77 ; If IOPUSH'ed, no interrupt. + JRST POPUJ + MOVE T,CHNBIT-1(Q) ; Q is -1 based. + AND T,MSKST2(U) + IORM T,IFPIR(U) + POP P,U + RET + + ; Input chan state type. Pos # means can read. + ; 0 is pre-open, 1 is open, 2 is input avail, -1 is post-open. +TCPTBI: OFFSET -. +%NTCLS:: 0 ; 0 CLS +%NTLSN:: 0 ; 1 LSN +%NTSYR:: 0 ; 2 RFC +%NTCLU:: -1 ; 3 RCL? +%NTSYN:: 0 ; 4 RFS +%NTOPN:: 1 ; 5 OPN +%NTWRT:: 1 ; 6 RFN +%NTCLX:: -1 ; 7 CLW +%NTCLI:: 1 ; 10 CLI +%NTINP:: 2 ; 11 INP + OFFSET 0 + + ; Output chan state type. Pos # means can write. + ; 0 is pre-open, 1 is open, 2 is buff full, -1 is post-open. +TCPTBO: OFFSET -. +%NTCLS:: 0 +%NTLSN:: 0 +%NTSYR:: 0 +%NTCLU:: 1 +%NTSYN:: 0 +%NTOPN:: 1 +%NTWRT:: 2 +%NTCLX:: -1 +%NTCLI:: 1 +%NTINP:: 1 + OFFSET 0 + + +SUBTTL TCP Input Interrupt Level + +; TCPIS - Process TCP Input Segment (PI level) +; R/ PE ptr to packet, not on any list. +; PK.BUF is set, ditto IP/TCP header pointers. +; W/ addr of IP header +; H/ addr of IP data (start of TCP header) +; J/ host-table index for address datagram received from. +; Can clobber all ACs except P, returns with POPJ. +; AC usage during incoming segment processing: +; R/ PE ptr to packet +; W/ addr of IP header +; H/ addr of TCP header +; I/ TCB index (if any) +; J/ TCB connection state +; TT/ # bytes of TCP data in segment +; E/ ,, +; D/ Segment Sequence no. +; Flags for RH of E +%TSISL==1 ; Seq starts to left of rcv.nxt +%TSISR==2 ; Seq starts to right of " ; if neither on, is = rcv.nxt +%TSIFL==4 ; Bad seq, flush after handling RST/ACK/URG + +TCPIS: METER("TCP: Segs rcvd") + SKIPN TCPUP ; Unless TCP claims to be up, + JRST TSIFL ; Throw it away, no TCP yet, sigh. + + ; First verify that this is a valid TCP segment, by + ; checksumming it (sigh!). TT gets total # bytes in TCP segment. + CALL THCKSI ; Get checksum in A for segment + LDB B,[TH$CKS (H)] ; Get segment's checksum + CAME A,B ; Should match. + JRST TSIF01 ; Failed, go bump err count and flush it. + LDB T,[TH$THL (H)] ; Find TCP header length in words + LSH T,2 ; Make it in octets + SUBI TT,(T) ; TT now has # octets of segment data. + + ; Contents of segment have been validated (more or less), + ; now set up convenient context values + ; PK.TCI contents + ; E/ Segment control flags (in LH) + ; TT/ SEG.LEN + HLLZ E,TH$CTL(H) ; Get word with segment control flags + DPB T,[PK$TDO (R)] ; Store offset of data (from THCKSI) + DPB TT,[PK$TDL (R)] ; Store length of data + TLNE E,(TC%SYN) ; Note that SYN counts in seg.len + ADDI TT,1 ; so allow for it + TLNE E,(TC%FIN) ; And do same thing for FIN. + ADDI TT,1 ; Either way, get SEG.LEN set up in TT. + + ; Then see if any TCB exists for this segment. + SKIPE A,TH$SRC(H) ; Get source/dest port word + SKIPN B,IP$SRC(W) ; Get source addr from IP header + JRST TSIF02 ; Flush anything with zero field. + LSH B,-4 ; Right-justify the addr + MOVSI I,-XBL +TSI02: CAMN A,XBPORT(I) ; Loop til we find it + CAME B,XBHOST(I) +TSI03: AOBJN I,TSI02 + JUMPL I,TSI05 ; Jump if found existing connection + JRST TSISQ ; Jump if no existing connection. + +TSI04: SKIPE XBSTAT(I) ; Found "closed" connection???? + JRST TSI02 ; LH must have crud still set, ignore for now + BUG CHECK,[TCP: Clsed TCB has active port/host] ; Shouldn't happen! + SETZM XBHOST(I) ; If continued, fix up. + JRST TSI02 + + ; Connection exists, TCB index now in I. + ; Set up a little more context (PK.TCI and J) +TSI05: DPB I,[PK$TCB (R)] ; Store TCB index in packet info + MOVEM J,XBNADR(I) ; Save host-table idx of addr this seg is from. + HRRZ J,XBSTAT(I) ; Get connection state + CAIL J,.XSTOT ; Highest possible state. + BUG HALT,[TCP: Bad conn state] + METER("TCP: IS all states") + XCT XSMTRS(J) ; Bump meter for each state + CAIG J,.XSSYN ; If it's CLS, SYQ, LSN or SYN-SENT + JRST @(J)[ ; then process specially. + TSI04 ; Closed??? + TSISQQ ; Syn-Queued? (Probably re-trans) + TSILS ; Listen + TSISS] ; Syn-sent + ; Drop through to perform general sequence-number checking. + + ; Check Sequence Number!!! + ; This code doesn't do two things: + ; 1) it doesn't keep around stuff that arrives to the + ; right of rcv.nxt. + ; 2) for situation where seg.seq number is valid, + ; (i.e. seq =< rcv.nxt) the code punts if + ; end of seg is out of window. It should simply + ; expand the window! + LDB D,[TH$SEQ (H)] ; Get sequence number + JUMPG TT,TSI10 ; Jump if data present. + JUMPL TT,TSIF03 ; No data. Jump if error (neg data!) + + ; No data in this segment, it is probably a simple ACK. + CAME D,XBRNXT(I) ; Seg.seq == snd.nxt (as expected?) + JRST TSI01 + METER("TCP: 0-len seg seq match") + JRST TSI20 ; Yep, seg is acceptable instantly! + +TSI01: SKIPN C,XBRWND(I) ; Have some receive window? + JRST TSI09 + ADD C,XBRNXT(I) ; Get nxt+wnd + TLZ C,%MOD32 ; all arith mod 32 + CMPSEQ XBRNXT(I),=<,D,<,C,TSI07,TSI08 + JRST TSI20 ; Within rcv window, buy it + +TSI07: METER("TCP: 0-len seg before rcv window") + JRST TSISNE + +TSI08: METER("TCP: 0-len seg after rcv window") + JRST TSISNE + + ; 0-data, 0-window, and SEG.SEQ != RCV.NXT +TSI09: METER("TCP: Ifl 0-len 0-window seqerr") + JRST TSISNE ; Sigh, flush it. + + ; Seq number check when data present. +TSI10: CAME D,XBRNXT(I) ; Is seq # what we expect (seq = nxt)? + JRST TSI11 + SKIPE C,XBRWND(I) ; Yes! And is our window open? + JRST TSI20 ; Yes! Fast dispatch! + + ; Data segment, with valid sequence number, but our window is + ; zero. See if there's some way we can avoid throwing away the + ; segment... if we can't take it then still must handle + ; ACK/URG/RST flags. For now, we really handle this at TSI70. +TSI12: METER("TCP: 0-wnd data seg") + JRST TSI20 + + ; Sequence # isn't exactly what we hoped for, see if the + ; segment overlaps a valid portion of sequence space. +TSI11: SKIPN C,XBRWND(I) ;#3: Get window, is it zero? + MOVEI C,512. ; If zero, substitute a dummy window. + + ; Both len>0 and wnd>0. + ADD C,XBRNXT(I) ; Get nxt+wnd + TLZ C,%MOD32 ; all arith mod 32 + ;#4a: nxt =< seq < nxt+wnd + CMPSEQ XBRNXT(I),=<,D,<,C,TSI13 ; Jump if fail this test, try 4b. + + ; Come here when sequence # is OK, but segment starts farther on + ; than we want, i.e. there is a "hole" between rcv.nxt and seg.seq. + ; Eventually we could keep this segment around, to speed up + ; throughput for nets that get packets out of order, but for + ; now we'll just flush it and force a retransmit. + METER("TCP: Iseg hole") + TRO E,%TSISR+%TSIFL ; Say starts to right, and flush later. + JRST TSI20 ; Go process RST/ACK/URG etc. + +TSIF12: METER("TCP: Ifl seq dup") ; Segment falls in prev rcvd data. + MOVE D,XBRNXT(I) ; Fake out, say seq # OK + TRO E,%TSIFL ; and don't process data. + JRST TSI20 ; Go handle RST/ACK/URG. + +TSIF13: METER("TCP: Ifl seq int err") ; Shouldn't ever happen, due to + JRST TSISNE ; right-bound check code above. +TSIF14: METER("TCP: Ifl seq old") + JRST TSISNE +TSIF15: METER("TCP: Ifl monster seg") ; Impossible error + JRST TSISNE + + ; Segment does not overlap window to right, so see if it + ; overlaps to left, i.e. sequence # falls within data we have + ; already received. +TSI13: MOVE A,XBRNXT(I) + SUBI A,%TCPMB ; Make a fictional lower bound + CAIGE A, + ADD A,[1_32.] ; Keep bound mod 2^32 + CMPSEQ A,=<,D,=<,XBRNXT(I),TSIF14,TSIF13 + + ; Yep, falls within received data. It's probably a duplicate + ; retransmitted segment; see if there's any new data on right side. + ; Note that we are not using XBRWND here, because as long as we + ; have a non-zero window we will always accept everything in the + ; segment. So we create another fictional bound to the right. + ADD A,[%TCPMB*2] ; Get back to other side of rcv.nxt + TLZ A,%MOD32 ; Keep mod 2^32 + MOVE C,D + ADDI C,-1(TT) ; Get seq+len-1 + TLZ C,%MOD32 + ;#4b: nxt =< seq+len-1 < nxt+wnd? + CMPSEQ XBRNXT(I),=<,C,=<,A,TSIF12,TSIF15 ; If fail this too, error. + + ; Aha, have some new data in spite of being overlapped with some + ; previously received data! Here, we + ; twiddle things so that it appears to start properly at + ; rcv.nxt. This is done without touching the segment contents + ; at all, just modifying the packet entry info. + METER("TCP: Iseg ovlap") + MOVE A,XBRNXT(I) ; Get rcv.nxt + CAMGE A,D ; Make sure it's greater than seg.seq + TLO A,(1_32.) ; Mod 2^32 screw, make it greater (add 33d bit) + SUB A,D ; Find # octets of sequence space diff + CAMLE A,TT ; Shouldn't be greater than seg.len!! + BUG CHECK,[TCP: Trim error] + SUBI TT,(A) + JUMPLE TT,TSIF12 ; If nothing left, drop this segment. + TLZE E,(TC%SYN) ; Clear SYN since it's at front. + SUBI A,1 ; If it was set, reduce cnt of actual data + LDB T,[PK$TDL (R)] ; that we're going to flush. Get cnt + SUBI T,(A) ; Decrement # valid data bytes in segment + DPB T,[PK$TDL (R)] ; Put back + LDB T,[PK$TDO (R)] ; Also adjust offset to valid data + ADDI T,(A) ; Increment to point at new data + DPB T,[PK$TDO (R)] ; Put back + MOVE D,XBRNXT(I) ; Now say seg.seq = rcv.nxt! + ; Segment sanitized, drop through. + SKIPN XBRWND(I) ; Only proceed if our window not zero. + JRST TSI12 ; It's zero! May have to flush it... + + ; Fall through to TSI20 for RST/ACK/URG processing. + + ; Now check RST +TSI20: TLNE E,(TC%RST) ; RST bit set? + JRST TSIRST ; Yeah, go process it. + + ; Now check security/precedence + JFCL ; ho ho ho + + ; Now check SYN bit +TSI40: TLNE E,(TC%SYN) ; SYN bit set? + JRST TSISYN ; Yeah, go process it (basically error) + + ; Now check ACK bit +TSI50: TLNN E,(TC%ACK) ; ACK bit set? + JRST TSIF50 ; No, error. Drop segment. + JRST @TSI51(J) ; Yes, dispatch depending on state. +TSI51: OFFSET -. +.XSCLS:: [JRST 4,TSI51] ; Closed +.XSSYQ:: [JRST 4,TSI51] ; ITS: Syn-Queued +.XSLSN:: [JRST 4,TSI51] ; Listen +.XSSYN:: [JRST 4,TSI51] ; Syn-Sent +.XSSYR:: TSI53 ; Syn-Rcvd +.XSOPN:: TSI54 ; Established (open) +.XSFN1:: TSI54 ; Fin-Wait-1 +.XSFN2:: TSI54 ; Fin-Wait-2 +.XSCLW:: TSI54 ; Close-Wait +.XSCLO:: TSI54 ; Closing +.XSCLA:: TSI54 ; Last-Ack +.XSTMW:: TSIATW ; Time-Wait +.XSTOT:: OFFSET 0 + + + ; SYN-RCVD state, handling ACK. +TSI53: LDB A,[TH$ACK (H)] ; Get ACK field + MOVE B,XBSUNA(I) ; Need one CMPSEQ arg in AC + ; Test: snd.una =< seg.ack =< snd.nxt + CMPSEQ B,=<,A,=<,XBSNXT(I),TSISRA ; Jump if fail + MOVEI J,.XSOPN ; ACK wins, we're now open! + HRRM J,XBSTAT(I) ; Set new state, fall through to handle. + CALL TCPUSI ; Adjust user state. + ; Must initialize SND.WL1, SND.WL2, and SND.WND. + ; Maybe later merge this with TSI55. + MOVEM A,XBSWL2(I) ; Yes! Update send window, set WL2 to ACK + MOVEM D,XBSWL1(I) ; and WL1 to SEQ + LDB B,[TH$WND (H)] + MOVEM B,XBSWND(I) ; and snd.WND to seg.WND. + MOVEM B,XBSAVW(I) ; and make avail window be same as send wind. + JRST TSI54X ; Skip repeating the ACK test. + + ; Handle ACK while in open state (also other receive-OK states) +TSI54: LDB A,[TH$ACK (H)] ; Get ACK field + MOVE B,XBSUNA(I) ; Need one CMPSEQ arg in AC + ; Test: snd.una =< seg.ack =< snd.nxt + ; If seg.ack < snd.una, go to TSI60 and ignore the ACK. + ; If seg.ack > snd.nxt, go to TSISAK to drop segment (ACKing) + CMPSEQ B,=<,A,=<,XBSNXT(I),TSI60,TSISAK ; Jump if fail + + ; ACK is fine. Update SND.UNA and clean up retransmit queue. +TSI54X: MOVEM A,XBSUNA(I) ; Update snd.una + + ; Must check retransmit queue slowly to find right place to flush, + ; if any. + ; Procedure is: (1) pull off 1st thing on queue. + ; (2) If the new 1st thing has a seq # =< snd.una, + ; then can flush what we pulled off, and try again. + ; (3) otherwise put it back on at front. +TSI54A: MOVE C,A ; Save ACK # in C +TSI54B: MOVEI Q,XBORTQ(I) ; Get pointer to retrans q + CALL PKQGF(PK.TCP) ; Get 1st thing on queue + JUMPE A,TSI54Z ; None left? Win! + TRCPKT A,"TSI54B Mabye flush from rexmit Q" + MOVE T,PK.FLG(A) ; Check packet flags, + TLNN T,(%PKODN) ; to make sure output was completed. + JRST TSI54Y ; Not done yet, so don't flush yet. + HRRZ B,XBORTQ(I) ; Get pointer to next thing + JUMPE B,[CAMN C,XBSNXT(I) ; No next thing, compare with snd.nxt + JRST TSI54D ; Equal, can flush! + JRST TSI54Y] ; If not equal, must have ack < snd.nxt + ; so previous segment can't be flushed. + HLRZ B,PK.TCP(B) ; Get addr of TCP hdr for 2nd queued segment + LDB B,[TH$SEQ (B)] ; Get sequence # for it +TSI54C: CMPSEQ B,=<,C,=<,XBSNXT(I),TSI54Y ; See if ACK comes after that # + + ; Hurray, matches or exceeds this seq #, + ; So we can flush the seg we pulled off! +TSI54D: TRCPKT A,"TSI54D Flushing from Q" + TLO T,(%PKFLS) ; Tell IP to forget it if queued + MOVEM T,PK.FLG(A) + CALL PKTRT ; Flush if not otherwise occupied +TSI54E: MOVE A,TIME ; Crock crock, set up new timeout. + ADD A,TCPTMO + MOVEM A,XBORTT(I) + SETZM XBORTC(I) ; Reset retry counts + SOSGE XBORTL(I) ; Decrement # segments on retrans q. + BUG HALT,[TCP: Retrans Q count error] + JRST TSI54B ; Keep going as long as we can. + +TSI54Y: MOVEI Q,XBORTQ(I) + CALL PKQPF(PK.TCP) ; Put back on front of queue +TSI54Z: MOVE A,C ; Restore ACK # to A. + + ; Now see if send window should be updated. + CAMN D,XBSWL1(I) ; Fast check first, WL1 = SEQ? + JRST TSI55C ; Yes, go check ACK then + MOVE T,XBSWL1(I) + ADDI T,-1 + TLZ T,%MOD32 + CMPSEQ XBSWL1(I),<,D,<,T,TSI56 ; Check if wl1 < seq < wl1+xxx + JRST TSI55 ; Yes, must update window. +TSI55C: MOVE T,XBSWL2(I) + ADDI T,-1 + TLZ T,%MOD32 + CMPSEQ XBSWL2(I),=<,A,=<,T,TSI56 ; Fall-thru win if snd.wl2 =< seg.ack + +TSI55: MOVEM A,XBSWL2(I) ; Yes! Update send window, set WL2 to ACK + MOVEM D,XBSWL1(I) ; and WL1 to SEQ + LDB B,[TH$WND (H)] + MOVEM B,XBSWND(I) ; and snd.WND to seg.WND. + ; Drop thru + + ; Either SND.UNA or SND.WND was probably updated, so lets update + ; SND.AVW also (available window). The following computes + ; WND - (NXT - UNA) and assumes UNA =< NXT. +TSI56: MOVE A,XBSNXT(I) + CAMGE A,XBSUNA(I) ; If need mod 32 wrap, + TLO A,(1_32.) ; wrap up the number that should be higher. + SUB A,XBSUNA(I) ; Find NXT-UNA (# bytes not yet acked) + CAIL A,0 + CAILE A,177777 ; Make simple check + BUG INFO,[TCP: Bad AVW calc, UNA=],OCT,XBSNXT(I),[NXT=],OCT,XBSUNA(I) + MOVE B,XBSWND(I) + SUBI B,(A) ; Find # bytes we can still send + CAIGE B, ; Make sure it's not negative! + SETZ B, + MOVEM B,XBSAVW(I) + + ; Done with ACK processing for OPEN state, see if must handle + ; idiosyncracies of other states. +TSI57: CAIN J,.XSOPN ; Skip other checks if state is OPEN (normal) + JRST TSI60 ; Go check for URG etc. + CAIN J,.XSCLW + JRST TSI80 + CAIN J,.XSFN1 + JRST [ SKIPE XBORTQ(I) ; If our FIN is ACK'd, enter FIN-WAIT-2 + JRST TSI60 ; Not yet. + MOVEI J,.XSFN2 ; Yes, FIN was ACKed, change state. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Call this for any state change. + LDB T,[XB$ICH (I)] ; Do we have an input chan? + JUMPN T,TSI60 ; If so, CLOSE will handle the wrapup. + MOVE T,TIME ; No, must set timeout. + ADDI T,2*60.*30. ; Use 2*MSL + MOVEM T,XBORTT ; set timeout. + JRST TSI60] + CAIN J,.XSFN2 + JRST [ ; If retrans queue empty, transmit-chan CLOSE done. + JRST TSI60] + CAIN J,.XSCLO + JRST [ SKIPE XBORTQ(I) ; If our FIN is ACK'd, + JRST TSIF55 ; No-- flush the segment. + CALL TSITMW ; then enter TIME-WAIT state, start timeout. + JRST TSI80] ; Then go check for FIN, etc. + CAIN J,.XSCLA ; LAST-ACK waiting for ACK of our FIN. + JRST [ SKIPE XBORTQ(I) ; If our FIN has been ACK'd, + JRST TSIF56 ; No-- flush the segment. + METER("TCP: FIN acked in .XSCLA") + CALL TXBFLP ; Flush the TCB immediately, PI level + JRST TSIFL] ; then flush the segment. + BUG CHECK,[TCP: Bad ACK state] + + ; Check the URG bit. The only states which get to this + ; point are OPEN, FIN-WAIT-1, and FIN-WAIT-2. +TSI60: TLNN E,(TC%URG) ; Segment has urgent pointer set? + JRST TSI70 ; Nope, on to next step. + LDB A,[TH$UP (H)] ; Get SEG.UP (urgent ptr from segment) + + ; This is where URGENT should be handled!!!! + ; Drop through + + ; Finally process segment text! + ; Only states OPEN, FIN-WAIT-1 and FIN-WAIT-2 can get here. +TSI70: TRNE E,%TSIFL ; If segment being flushed after ACK/URG, + JRST TSIF70 ; flush it now! + + LDB A,[PK$TDL (R)] ; Find # bytes of real data in segment + JUMPLE A,TSI80 ; If none, no text processing. + + TLNE E,(TC%FIN) ; Check that # bytes data == seg.len + JRST [ CAIE A,-1(TT) ; Must allow for funny non-data FIN. + JRST TSI71 ; Nope + JRST TSI72] ; Yep + CAIE A,(TT) ; # bytes data should == seg.len +TSI71: BUG CHECK,[TCP: seglen error] +TSI72: SKIPE D,XBRWND(I) ; Note D used for flag, + JRST TSI75 ; and is non-zero if no compaction done. + + ; Our window is zero, and technically we should throw away the + ; data now that all RST/ACK/URG processing has been done. However, + ; we try to see if we can possibly do a little compaction, since + ; the overhead of doing this is a lot less than the overhead + ; of re-processing the re-transmitted segment! + MOVE A,XBINPS(I) ; Check length of input queue + CAIL A,2 ; Must be at least 2 + SKIPN XBITQH(I) + BUG CHECK,[TCP: Wind & Queue both 0] + + ; See if it's worth trying to compact the input seg into the + ; last one received (which hasn't yet been seen by MP level) + HLRZ A,XBITQH(I) ; Get ptr to last input seg on queue + LDB B,[PK$TDO (A)] ; Get offset to data in old seg + LDB C,[PK$TDL (A)] ; See how much data is there + LDB T,[PK$TDL (R)] ; Find # bytes in new segment + ADDI B,(C) ; Get offset to end of data + MOVEI D,(B) + ADDI D,(T) ; Get projected total offset + CAML D,XBRMSS(I) ; Crock method of ensuring enuf room. + JRST TSI17 ; Not enough, we lose. Lose. Lose. + + ; Win! We're gonna compact! + METER("TCP: Iseg cmpct") + ADDI C,(T) ; Get new # bytes for prev seg + DPB C,[PK$TDL (A)] ; Store it in advance. + HLRZ D,PK.TCP(A) ; Find addr of TCP header in prev seg + IDIVI B,4 + ADDI D,(B) ; Get addr for BP to end of data + HRL D,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + LDB B,[PK$TDO (R)] ; Get data offset for new segment + IDIVI B,4 + ADDI B,(H) ; Get addr for BP to start of new data + HRL B,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + ; B/ BP to new data + ; D/ BP to end of old data + ; T/ # bytes of new data + MOVEI A,(T) ; Save # added data in A +TSI74: ILDB C,B + IDPB C,D + SOJG T,TSI74 + SETZ D, ; Clear D to indicate compaction done. + JRST TSI75 + + ; Can't accept segment data, period. +TSI17: METER("TCP: Ifl 0-wnd") + JRST TSIFL ; Flush the seg, sob. + +TSI75: MOVEI B,(TT) + ADDB B,XBRNXT(I) ; Update rcv.nxt value by adding seg.len + TLZE B,%MOD32 + MOVEM B,XBRNXT(I) ; Updated! + LDB B,[XB$ICH (I)] ; See if we have an input channel # + JUMPE B,[METER("TCP: IS fl no chan") + JRST TSI78] ; No input channel, so just throw away. + MOVEI C,(A) ; Save # bytes data. + ADDM A,XBINBS(I) ; Add new bytes to # bytes in input queue + JUMPE D,TSI78 ; If compaction done, that's all... + SKIPE B,XBINPS(I) ; If no segments previously on queue, + MOVE B,XBIBC(I) ; or current input buff has zero cnt, + ; then will definitely interrupt user later. + AOS XBINPS(I) ; Bump # segments on queue + + ; Check to see how much to reduce window by. + ; Amount is in C (defaults to amount we just received) + CALL TCPRWS ; Set receive window + + ; Finally add segment to queue! + MOVEI A,(R) ; Set up pointer to packet/segment + MOVEI Q,XBITQH(I) ; Point to TCP input queue + CALL PKQPL(PK.TCP) ; Add to end of queue, using TCP links. + JUMPN B,TSI78 ; Check, jump unless had no input before + CALL TXBIST ; If none, then must definitely change state! + HRLM T,XBSTAU(I) ; + CALL TCPUII ; And always give an input-avail int! + + ; Now must send an ACK, or rather arrange for one to be + ; sent soon. FIN is also checked here, so as to bypass the + ; code which assumes that XBRNXT hasn't been updated (if we are + ; here, it certainly has!) +TSI78: MOVSI A,(TC%ACK) ; Set bit asking for ACK to be sent. + IORM A,XBSTAT(I) + TLNN E,(TC%FIN) ; Perform FIN-bit check + JRST TSI90 ; None, all done with segment! + JRST TSI82 ; FIN exists, handle it (bypass bump of XBRNXT) + + ; Lastly check the FIN bit. + ; Connection states which do not expect to receive data come here + ; directly from ACK processing. +TSI80: TRNE E,%TSIFL ; If duplicate segment being flushed after + JRST TSIF70 ; ACK/URG, flush it now! + TLNN E,(TC%FIN) + JRST TSI90 + CAIG J,.XSSYN + JRST TSIF80 ; Flush if CLOSED, LISTEN, SYN-SENT + + ; Advance RCV.NXT over the FIN + AOS A,XBRNXT(I) + TLZE A,%MOD32 + MOVEM A,XBRNXT(I) + + ; Rest of FIN processing, after processing new data in packet. + ; Ack FIN, update connection state, inform user. +TSI82: MOVSI A,(TC%ACK+%XBFIN) ; Set bit asking that ACK be sent, and FIN + IORM A,XBSTAT(I) ; was seen. + MOVEI T,.XCFRN ; Say foreign host closed input side. + CALL TCPUCI + + ; Now effect some state changes + CAIE J,.XSOPN ; If OPEN + CAIN J,.XSSYR ; or SYN-RCVD + JRST [MOVEI J,.XSCLW ; Change state to CLOSE-WAIT + JRST TSI85] + CAIN J,.XSFN1 + JRST [ SKIPN XBORTQ(I) ; If our FIN was ACK'd, + JRST TSI84 ; Go enter TIME-WAIT state + MOVEI J,.XSCLO ; Otherwise enter CLOSING state. + JRST TSI85] + CAIE J,.XSFN2 + CAIN J,.XSTMW + JRST TSI84 ; Go to TIME-WAIT + JRST TSI90 ; Any other states just do nothing. + +TSI84: CALL TSITMW ; Enter TIME-WAIT state, starting 2-MSL timeout + JRST TSI90 +TSI85: HRRM J,XBSTAT(I) ; Set new state and fall through. + CALL TCPUSI ; Set user state. + + ; Done. Finally decide whether to keep segment around or not. +TSI90: HLRZ A,XBITQH(I) ; Get ptr to last thing on input queue + CAIN A,(R) ; Same as current seg (ie it was queued?) + RET ; Yes, just return! + JRST TSIF90 ; Else drop through to flush the segment. + +XSMTRS: OFFSET -. +.XSCLS:: METER("TCP: state CLS") +.XSSYQ:: METER("TCP: state SYQ") +.XSLSN:: METER("TCP: state LSN") +.XSSYN:: METER("TCP: state SYN") +.XSSYR:: METER("TCP: state SYR") +.XSOPN:: METER("TCP: state OPN") +.XSFN1:: METER("TCP: state FN1") +.XSFN2:: METER("TCP: state FN2") +.XSCLW:: METER("TCP: state CLW") +.XSCLO:: METER("TCP: state CLO") +.XSCLA:: METER("TCP: state CLA") +.XSTMW:: METER("TCP: state TMW") +.XSTOT:: OFFSET 0 + + +TSIF01: METER("TCP: ISeg cksm errs ") + JRST TSIFL +TSIF02: METER("TCP: IS zero port/addr") + JRST TSIFL +TSIF03: METER("TCP: IS fl neg data") + JRST TSIFL +;TSIF10: ; Flush this later (retain til get new .METER LIST) + METER("TCP: IS fls Seq # err") + JRST TSIFL +TSIF50: METER("TCP: IS fls Seq no ACK ") + JRST TSIFL +TSIF55: METER("TCP: IS fls CLO & FIN not ACKed") + JRST TSIFL +TSIF56: METER("TCP: IS fls CLA & FIN not ACKed") + JRST TSIFL +TSIF70: METER("TCP: IS fls seqerr processed A/U/R") + JRST TSISNE ; Go respond with ACK +TSIF80: METER("TCP: IS fls FINchk state") + JRST TSIFL +TSIF2A: METER("TCP: IS fls random RST") + JRST TSIFL +TSIF2B: METER("TCP: IS fls Fresh SYN already on SYNQ") + JRST TSIFL + +TSIF90: METER("TCP: IS fls processed seg") + JRST TSIFL + + ; Come here to flush the datagram/segment and return. +TSIFL: METER("TCP: Isegs flushed") + MOVEI A,(R) + CALRET PKTRT + +; TSITMW - Routine to enter TIME-WAIT state. +; TSITM2 is entry point when already in that state. +; Clobbers T, Q +TSITMW: MOVEI J,.XSTMW + HRRM J,XBSTAT(I) + CALL TCPUSI ; Alert user if necessary. +TSITM2: SKIPE XBORTQ(I) ; Unless retransmit still hogs timeout + RET ; (if so, return) + MOVE T,TIME ; then set up 2-MSL timeout. + ADDI T,30.*2.*60. + MOVEM T,XBORTT(I) + RET + +; TSISNE - Sequence number error, segment not acceptable, +; return an ACK unless RST was set. + +TSISNE: METER("TCP: IS NE seqerr") + TLNE E,(TC%RST) + JRST TSIFL ; Flush segment if RST was set + + ; Send an immediate ACK without data, re-using the + ; packet/segment that R points to. +TSOACK: MOVSI T,(TC%ACK) ; Send an ACK immediately + TRCPKT R,"TSOACK return ACK in response to out-of-seq ACK" + CALL TSOSNR + RET + +; TSISQ - Jumped to from TCPIS when TCP segment is received that matches +; no existing connection. Check to see if it's a valid connection +; request. If so, +; (1) see if it matches any wild listens; if so, process. +; (2) see if it's OK to start up a server for it; if so, process. + +TSISQ: TLNE E,(TC%RST) ; If it has RST set, + JRST TSIF2A ; Go drop it quietly. + TLNE E,(TC%ACK) ; If ACK, can't be a valid request either + JRST TSISAR ; Go send a RST in response (with SEQ=SEG.ACK) + TLNN E,(TC%SYN) ; Anything else had better have a SYN + JRST TSISLR ; otherwise send RST with SEQ=0,ACK=SEQ+LEN + + ; Okay, we have a promising SYN. See if it matches any + ; "wild" listens. + METER("TCP: Fresh SYN") + LDB B,[TH$DST (H)] ; Get desired port # + LDB C,[TH$SRC (H)] ; Find port it's from + LDB D,[IP$SRC (W)] ; and host it's from. + MOVSI I,-XBL +TSISQ2: HRRZ J,XBSTAT(I) ; Get state for TCB + CAIE J,.XSLSN ; We're hunting for LISTEN +TSISQ3: AOBJN I,TSISQ2 + JUMPGE I,TSISQ5 ; Jump if no match. + LDB A,[.BP TH%DST,XBPORT(I)] ; Get our local port (never wild) + CAIE A,(B) ; It must match desired "dest port"! + JRST TSISQ3 ; Nope, doesn't want this one. + SKIPL XBHOST(I) ; Aha, very likely will match. Follow thru. + CAMN D,XBHOST(I) + CAIA + JRST TSISQ3 ; Host didn't match. + MOVE A,XBPORT(I) ; Check remote port field + TRNE A,17 ; Low 4 bits are non-zero if remote wild. + JRST TSISQ4 ; Won! + LDB A,[.BP TH%SRC,A] ; Not wild, see if it matches request. + CAIE A,(C) ; Compare our remote with its source. + JRST TSISQ3 ; No, no match here. + + ; Matched a wild listen! Must fill in various stuff. +TSISQ4: MOVEI A,17 + ANDCAM A,XBPORT(I) ; Clear wild bits + DPB C,[.BP TH%SRC,XBPORT(I)] ; Set remote port # + MOVEM D,XBHOST(I) ; Set remote host addr + LDB D,[IP$DST (W)] ; Set local address to whichever address other guy knows + MOVEM D,XBLCL(I) + DPB I,[PK$TCB (R)] ; Finish setting up context for dispatch + CALL TCPMSS ; Correct MSS values for specified foreign host + CALL TCPRWS ; Open up a receive window + JRST TSILS ; Go handle SYN rcvd for LISTEN. + + ; No outstanding listens. Check the port number, to + ; see if it's something we are likely to service. +TSISQ5: LDB A,[TH$DST (H)] ; Get destination port # + CAILE A,%TCPMP ; Fits max port # for RFC service? + JRST TSISLR ; Naw, barf about it (send RST). + + ; See if we're actually willing to start up a job... + LDB A,[IP$SRC (W)] ; See who it's from + JSP T,IPLCLH ; Ask IP if this is one of us + SKIPL TCPUSW ; It isn't, so make sure we're open for biz + CAIA + JRST TSISLR ; Sorry charlie (send RST) + + ; Okay, we'll take it as SYN-QUEUED! We know this is a new + ; request, otherwise it would have been matched at TSI02 and + ; dispatched to TSISQQ instead. + +ifn 0,[ + ; first see if it's already on the queue! + ; Note that we still have remote host # in D. + SKIPN Q,TCPRQH ; Get pointer to 1st item on queue + JRST TSISQ7 ; No queue, so not on. + MOVE B,TH$SRC(H) ; Get req's source/dest ports + MOVE D,IP$SRC(W) ; and its source addr +TSISQ6: HLRZ T,PK.TCP(Q) ; Get addr of TCP header from queue + HLRZ C,PK.IP(Q) ; and addr of IP header + CAIE T, + CAIN C, + BUG CHECK,[TCP: SYNQ smashed] + CAMN B,TH$SRC(T) ; Same ports? + CAME D,IP$SRC(C) ; Same host? + CAIA ; No + JRST TSIF2B ; Yes, assume SYN is a dup, ignore it. + HRRZ Q,PK.TCP(Q) ; Get next thing on pending queue + JUMPN Q,TSISQ6 + + ; Not on queue, let's try to add it. +TSISQ7: MOVE A,TCPRQN ; Find # of things on queue already + CAIL A,%TCPMQ ; Keep its length reasonable + JRST TSISQ8 ; Sigh, ran out. + HRROI T,NTSYNL ; OK, now try loading job up! + CALL NUJBST ; Queue request for job TCPRFC + JRST TSISLR ; Bah, no job slots or something! + MOVEI A,(R) ; It's on the way! Queue the SYN now. + MOVEI Q,TCPRQH + CALL PKQPL(PK.TCP) ; Add onto end of pending-RFC queue. +] ;ifn 0 + + MOVSI I,-XBL +TSISQ6: SKIPN XBUSER(I) + SKIPE XBSTAT(I) + AOBJN I,TSISQ6 + JUMPGE I,TSISQ8 ; Jump if no free slots. + CALL TXBINI ; Got one, might as well verify it's cleared. + MOVE A,TCPRQN ; Find # of things on queue already + CAIL A,XBL/2 ; Keep number reasonable + JRST TSISQ8 ; Sorry, too many. + HRROI T,NTSYNL ; Now see if we can load up handler job. + CALL NUJBST ; Do it + JRST TSISLR ; Ugh, couldn't start new job... + MOVEI J,.XSSYQ + MOVEM J,XBSTAT(I) ; Set state SYN-QUEUED + LDB A,[IP$SRC (W)] + MOVEM A,XBHOST(I) ; Set up host # + MOVE A,TH$SRC(H) ; and ports + ; Don't need to set XBLCL, won't be looked at + MOVEM A,XBPORT(I) ; That's all we need for now. + CALL TCPMSS ; Might as well keep these right even though + CALL TCPRWS ; this TCB will be flushed when conn opens. + MOVE A,TIME + ADDI A,10.*30. ; Let it stay queued for 10 seconds. + MOVEM A,XBORTT(I) + MOVEI Q,XBITQH(I) ; Put the segment on input queue for slot. + MOVEI A,(R) + CALL PKQPF(PK.TCP) + + HRRZM I,TCPRQL ; Save # of last SYN queued. + AOS TCPRQN ; And increment count of entries. + METER("TCP: Srvjob starts") + RET ; All done! + +TSISQ8: BUG INFO,[TCP: SYN queue full] + JRST TSISLR ; Sigh. + + +; TSISQQ - Come here when segment received that matches an +; existing port/host which is in SYN-QUEUED state. + +TSISQQ: TLNE E,(TC%RST) ; Is it an RST? + JRST [ CALL TSISQF ; Yeah, flush the queued SYN. + JRST TSIFL] ; and drop segment. + TLNE E,(TC%ACK) ; An ACK? That's illegal etc... + JRST [ CALL TSISQF ; Flush the queued SYN, + JRST TSISAR] ; and send a RST in response. + TLNN E,(TC%SYN) ; Anything else better be a SYN + JRST [ CALL TSISQF ; else send RST. + JRST TSISLR] + JRST TSIF2B ; Most likely a duplicate SYN, so just + ; flush it and return. + + ; Flush TCB for a queued SYN. +TSISQF: SETZM XBSTAT(I) + SETZM XBPORT(I) + SETZM XBHOST(I) + SETZM XBORTT(I) + SKIPE XBITQH(I) + CALL TXBIFL + SOSGE TCPRQN + BUG HALT + RET + + +; TSISAR - Respond to current segment by sending a RST with +; SEQ=SEG.ACK. Re-uses the current segment's packet buffer. +; R, W, H set up for PE, IP, and TCP. +; E has seg flags. May not be anything in I, so re-use fields +; from given packet! +; TSISAQ - like TSISAR but just drops segment if it has RST in it. +; TSISLR - like TSISAR, but SEQ=0, ACK=SEG.SEQ+SEG.LEN +; This is used when responding to segments without an ACK, i.e. +; initial SYNs. + +TSISLR: METER("TCP: times at TSISLR") + LDB A,[TH$SEQ (H)] ; Get SEQ. Assume TT still valid. + ADDI A,(TT) ; ACK=SEG.SEQ+SEG.LEN + LSH A,4 ; Left justify it. + SETZ D, ; SEQ=0 + MOVSI T,(TC%RST+TC%ACK) + JRST TSISA2 + +TSISAQ: TLNE E,(TC%RST) ; Here, if incoming seg was RST, + JRST TSIFL ; just ignore, don't respond. +TSISAR: METER("TCP: times at TSISAR") + MOVE D,TH$ACK(H) ; Use SEG.ACK for SEQ + MOVSI T,(TC%RST) + + ; Here, A, D, and T must be set up. +TSISA2: SETZ B, + LDB C,[TH$SRC (H)] ; Get source port + DPB C,[.BP TH%DST,B] ; Use as dest port + LDB C,[TH$DST (H)] ; Get dest + DPB C,[.BP TH%SRC,B] ; Use as... you guessed it. + PUSH P,IP$DST(W) ; Which of my addresses to claim to be from + MOVE C,IP$SRC(W) + +; A/ ACK field (left justified) +; B/ (left justified) +; C/ remote host (left justified) +; D/ SEQ field (left justified) +; R/ PE ptr to packet responding to +; T/ flags to use + + + SETZ I, + CALL TSOINI ; Initialize W,H,PK.IP(R),PK.TCP(R),PK.TCI(R) + ; Note everything in PK.TCI will be wrong. + MOVEM C,IP$DST(W) ; Store remote host + MOVEM B,TH$SRC(H) ; Store loc/rem ports + MOVEM D,TH$SEQ(H) ; Deposit new SEQ field + TLNN T,(TC%ACK) ; If sending an ACK + SETZ A, + MOVEM A,TH$ACK(H) ; Deposit ACK field. + TLO T,240000 ; Set IHL + MOVEM T,TH$CTL(H) ; Deposit segment flags + MOVEI A,5*4 + DPB A,[IP$TOL (W)] ; Say length just a std TCP header. + POP P,IP$SRC(W) + CALL THCKSM ; Figure TCP checksum + DPB A,[TH$CKS (H)] ; Deposit in + CALL IPKSND ; Put this buffer on IP output queue! + RET + + +; TSILS - Segment received for this connection while in LISTEN state. +; +TSILS: METER("TCP: Segs rcvd in LSN") + TLNE E,(TC%RST) ; Ignore any RSTs. + JRST TSIFL + TLNE E,(TC%ACK) ; ACKs are bad too. + JRST TSISAR ; Respond with a RST to them. + TLNN E,(TC%SYN) ; It should be a SYN. + JRST TSIFL ; If not, just flush. + + ; We've received a SYN that should be valid. Set up for + ; SYN-RCVD state. Note that we ignore security/precedence + ; except to remember it so our transmits look OK. + ; NOTE!!! TSILSX is an entry point from MP level TCPOPN call, + ; which is used to hook up a user OPEN to a matching SYN on + ; the pending-RFC queue! + METER("TCP: SYN in LSN") +TSILSX: LDB D,[TH$SEQ (H)] ; Get sequence number + LDB A,[TH$WND (H)] + MOVEM A,XBSWND(I) ; Initialize send window + MOVEM A,XBSAVW(I) ; and available window + MOVEM D,XBSWL1(I) ; Save seg.seq used for last window update + LDB A,[TH$ACK (H)] + MOVEM A,XBSWL2(I) ; Save seg.ack used for last window update + ADDI D,1 + TLZ D,%MOD32 ; Get seg.seq+1 + MOVEM D,XBRNXT(I) ; Store as initial RCV.NXT + CALL TCPISS ; Select a new ISS in A (Initial Send Seq#) + MOVEM A,XBSUNA(I) ; Set SND.UNA to ISS +; ADDI A,1 +; TLZ A,%MOD32 + MOVEM A,XBSNXT(I) ; And SND.NXT also; assume that process of + ; sending it will increment by 1. + + ; Check for TCP options at this point, and process if present + LDB A,[TH$THL (H)] ; TCP header length + CAILE A,%TCPHL ; If default, no options present + CALL TCPPIO ; Else, process input options + + ; Nasty business - put together and send a segment with + ; seq=ISS,ack=RCV.NXT,ctl=SYN+ACK. + ; For now we can assume that initial SYNs will never + ; contain text, and so we don't have to queue it up. + ; Alternatively can hope that remote site is clever about + ; retransmitting! + ; This is because if we don't need to keep received segment + ; around, can just re-use it. + MOVSI T,(TC%SYN+TC%ACK) + TRCPKT R,"TSISLX Reflecting incoming SYN with SYN" + CALL TSOSSN ; Fire off SYN. Sends MSS option too. + MOVEI J,.XSSYR ; Change state to SYN-RCVD. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Set user state. + RET + +; TCPISS - Select new ISS, return in A + +TCPISS: MOVE A,TIME + LSH A,13. +TCPIS2: TLZ A,%MOD32 + CAMN A,TISSLU ; Same as last used? + JRST [ AOS A,TISSC + ANDI A,17 + LSH A,9. + ADD A,TISSLU + JRST TCPIS2] ; Jump to mask off and test again. + MOVEM A,TISSLU + RET + +; TCPPIO - Process TCP options from incoming segment. +; This is only checked for SYN segments because the only interesting +; option (Max Segment Size) is only sent with SYN segments +; +; R/ Pkt buffer +; I/ TCB Index +; H/ TCP Header +; A/ TCP header size in 32-bit words + +TCPPIO: SUBI A,%TCPHL + LSH A,2 ; Options length in bytes + MOVE B,[TH$OPT (H)] ; BP to start of options +TCPPIL: SKIPG A ; Anything left? + RET ; Nope, done + ILDB C,B ; Get option type + CAIL C,TCPPIS ; In range? + RET ; Have to give up if unknown option + JRST @TCPPIT(C) + +TCPPIT: TCPPI0 + TCPPI1 + TCPPI2 +TCPPIS==.-TCPPIT + + ;End of option list +TCPPI0: RET + + ;NOP +TCPPI1: SOJA A,TCPPIL ; Decrement length and loop + + ;Max Seg Size TYPE ? LENGTH ? MSB ? LSB +TCPPI2: ILDB C,B ; Get length + SUB A,C ; Count it + ILDB C,B ; Get 16-bit quantity, updating B + LSH C,8. + ILDB D,B + ADD C,D ; Now contains foreign MSS request + CAMGE C,XBSMSS(I) ; Don't exceed our own limits! + MOVEM C,XBSMSS(I) ; Set new value in TCB + JRST TCPPIL + + +; TSISS - Segment received while in SYN-SENT state. +; Note that being in this state implies that there is one +; segment on the retransmit queue, which must be the initial SYN +; that we sent. + +TSISS: METER("TCP: Segs rcvd in SYN-SENT") + LDB D,[TH$SEQ (H)] ; Get SEG.SEQ + TLNN E,(TC%ACK) ; Has an ACK? + JRST TSISS2 ; Nope, it better be RST or SYN. + + ; See if our SYN has been ACKed. Since we only send SYNs + ; without data, this just means a test for SEG.ACK = SND.NXT. + LDB B,[TH$ACK (H)] ; Have ACK. Get ack field + CAME B,XBSNXT(I) ; It should ACK our initial SYN + JRST TSISAQ ; If not, send a RST. +; MOVE A,XBSUNA(I) ; snd.una =< seg.ack =< snd.nxt ? +; CMPSEQ A,=<,B,=<,XBSNXT(I),TSISAQ ; If not good, send RST. + +TSISS2: TLNE E,(TC%RST) ; Check for RST + JRST [ TLNN E,(TC%ACK) ; Ugh, have RST. Did we also get good ACK? + JRST TSIFL ; No, can just flush this segment. + MOVEI T,.XCRFS ; Yeah, our SYN is being refused, so + CALL TCPUC ; say this is close-reason. + JRST TSIRST] ; Then must go abort connection. + + ; Here we get to check security/precedence. Hurray. + ; We should just copy the seg values, so as to fake sender out. + + ; Now finally check the SYN bit! + TLNN E,(TC%SYN) ; Must be set + JRST TSIFL ; Neither RST nor SYN? Flush it. + + ; It's a SYN. Update our send params from its values. + ; We will either send an ACK or another SYN; in both cases the + ; SYN segment currently on the retransmit queue should be flushed. + MOVEI Q,XBORTQ(I) ; Point to retrans q + CALL PKQGF(PK.TCP) ; Pluck off 1st thing + SOSN XBORTL(I) ; Verify none left on queue + CAIN A, ; and something was there! + BUG CHECK,[TCP: SYN-SENT retrans Q bad] + JUMPE A,TSISS3 ; Just for robustness + TRCPKT A,"TSISS2 Flushing our SYN from rexmit Q" + MOVE T,PK.FLG(A) + TLO T,%PKFLS ; Tell IP to flush packet if seen + MOVEM T,PK.FLG(A) + CALL PKTRT ; Flush SYN packet if not otherwise busy + SETZM XBORTT(I) ; and flush timeout. + +TSISS3: LDB A,[TH$WND (H)] + MOVEM A,XBSWND(I) ; Initialize send window + MOVEM A,XBSAVW(I) ; and available window + MOVEM D,XBSWL1(I) ; Save seg.seq used for last window update + LDB A,[TH$ACK (H)] + MOVEM A,XBSWL2(I) ; Save seg.ack used for last window update + ADDI D,1 + TLZ D,%MOD32 + MOVEM D,XBRNXT(I) ; Set RCV.NXT to SEQ+1 + + ; Process segment options in case sender specified MSS + LDB A,[TH$THL (H)] ; TCP header length + CAILE A,%TCPHL ; If default, no options present + CALL TCPPIO ; Else, process input options + + TLNN E,(TC%ACK) + JRST TSISS4 + LDB A,[TH$ACK (H)] ; If ACK also present, (known acceptable) + MOVEM A,XBSUNA(I) ; Set SND.UNA to SEG.ACK. + + ; Here must test if SND.UNA > ISS (our SYN has been ACKed). + ; But this was already checked just before TSISS2. + MOVSI T,(TC%ACK) ; Hurray, we're open! Must ACK the SYN + TRCPKT R,"TSISS3 ACK SYN to open conn" + CALL TSOSNR ; (Re-using its segment) + MOVEI J,.XSOPN ; Hurray, we're open now! + HRRM J,XBSTAT(I) + CALL TCPUSI ; Update user state + RET + + ; Our SYN not ACKed yet, so enter SYN-RCVD state. +TSISS4: + ; Must go send seq=ISS,ack=RCV.NXT,ctl=SYN+ACK + LDB D,[TH$SEQ (H)] ; Get sequence number + ADDI D,1 + TLZ D,%MOD32 ; Get seg.seq+1 + MOVEM D,XBRNXT(I) ; Store as initial RCV.NXT + SOSGE A,XBSUNA(I) ; Set SND.UNA to ISS + JRST [ MOVEI A,1 + MOVEM A,XBSUNA(I) + JRST .+1] + MOVEM A,XBSNXT(I) ; And SND.NXT also; assume that process of + ; sending it will increment by 1. + MOVSI T,(TC%SYN+TC%ACK) + TRCPKT R,"TSISS4 ACK and re-SYN SYN-SENT conn" + CALL TSOSSN ; Fire off SYN/ACK with MSS option included. + MOVEI J,.XSSYR ; Change state to SYN-RCVD. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Set user state. + RET + +; TSIRST - valid RST segment received (not in LISTEN). +; Basically must flush the connection, signal user, etc. + +TSIRST: METER("TCP: Valid RSTs") + CALL TXBFLP ; Flush the TCB immediately, PI level + MOVEI T,.XCRST ; Say fgn host reset stuff + CALL TCPUC ; as "close reason" + CALRET TSIFL ; Flush segment. + +; TSISYN - SYN segment received. +; If in window, error - send a RST and close things up. +; If not in window, return an ACK as for TSISNE. + +TSISYN: METER("TCP: Random SYN") + + CALRET TSIFL + +; TSISRA - Bad ACK seen while in SYN-RCVD state, +; send a RST. + +TSISRA: METER("TCP: Bad ACK in SYR") + CALRET TSIFL + +; TSISAK - Received ACK for something not yet seen, send ACK and +; drop segment. +TSISAK: METER("TCP: ACK for nxm") + CALRET TSIFL + +; TSIATW - Received ACK while in TIME-WAIT state. This should be +; a re-transmit of the remote FIN. ACK it, and restart +; 2-MSL timeout. + +TSIATW: METER("TCP: ACK in .XSTMW") + MOVSI T,(TC%ACK) + TRCPKT R,"TSIATW ACK send in TIME-WAIT" + CALL TSOSNR ; Send simple ACK in response. + JRST TSITM2 ; and restart 2-MSL timeout. + +SUBTTL TCP Send output segment + +; Send TCP output segment. +; Send output (usually data) segment, for connection indexed by I. +; Note this differs from TSISAR etc. which don't have any active connection, +; thus no valid I. As much context as possible is taken from the +; TCB tables indexed by I. +; In particular, the %XBCTL flags are examined to see if anything should +; be added to the outgoing segment, other than what was requested in the +; call. + +; Sequence space variables are updated. +; The following possibilities are independently possible: +; Re-using packet / using fresh packet +; Uses seq space (must retrans) / no seq space used +; +; TSOSND - send output segment while connection established +; R/ PE ptr to packet, +; PK.BUF, PK.IP and PK.TCP must be set. +; If these were not initialized by TSOINI so as to get +; the right offsets, you will probably lose. +; PK.TCI should have the # bytes of data and offset. +; I/ TCB index +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +; TSOSNR - Just sends a data-less "reply" type segment using +; TCB's sequence space vars. Seq=snd.nxt, ack=rcv.nxt, etc. +; R/ PE ptr to packet (packet will be smashed and re-used) +; I/ TCB index +; T/ flags to use (Neither ACK nor %XBCTL will be added automatically!) + +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +TSOSNR: CALL TSOINI ; Initialize (sets up W,H PK.IP,PK.TCP,PK.TCI) + SETZ TT, ; Say zero bytes of real data + DPB TT,[PK$TDL (R)] ; and make sure packet entry reflects this. + JRST TSOSN ; Jump in to do it. + + +; TSOSSN - Send an initial SYN segment. No data, but add a TCP +; MSS option set from XBRMSS(I), and using TCB's sequence space +; vars. Seq=snd.nxt, ack=rcv.nxt, etc. +; R/ PE ptr to packet (packet will be smashed and re-used) +; I/ TCB index +; T/ flags to use (None, including SYN, will be added automatically) + +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +TSOSSN: CALL TSOINI ; Initialize (sets up W,H PK.IP,PK.TCP,PK.TCI) + MOVE TT,XBRMSS(I) ; Max seg size we would like + LSH TT,4 ; 32-bit option + IOR TT,TSOMSO ; Add in type and length fields of option + MOVEM TT,TH$OPT(H) ; Write it. Damn well better be first option. + LDB TT,[PK$TDO (R)] ; Get current TCP header size + ADDI TT,4 ; Adding 4-byte option + DPB TT,[PK$TDO (R)] + SETZ TT, ; Say zero bytes of real data + DPB TT,[PK$TDL (R)] ; and make sure packet entry reflects this. + JRST TSOSN ; Jump in to do it. + +TSOMSO: .BYTE 8 ? 2 ? 4 ? 0 ? 0 ? .BYTE ; Option 2, length 4, two data words + +TSOSND: MOVSI T,(TC%ACK) ; Simple data segment + IOR T,XBSTAT(I) ; Plus whatever is being requested. + HLRZ W,PK.IP(R) ; Get ptr to IP header + HLRZ H,PK.TCP(R) ; and TCP header + LDB TT,[PK$TDL (R)] ; Get # bytes of data +; LDB A,[PK$TDO (R)] ; Get offset of data +; ADDI TT,(A) ; Now have # bytes past std hdr length. + +; TSOSN - Entry point if W, H, and TT already set up. +; I/ TCB index +; T/ flags for segment +; R/ PE ptr (PK.BUF, PK.IP, PK.TCP, PK.TCI must all be set) +; W/ IP header ptr +; H/ TCP header ptr +; TT/ # bytes of data (real data, not including header or SYN/FIN) +; Clobbers A,B,C,D,E,TT,T,Q and updates various TCB data. + +; This code assumes TT is the bytes of DATA only. +; Must store the out-of-TCP info in the IP header field, so that +; the checksum and IPKSND routines will find it there. +; This info consists of: +; IP$SRC - Source address +; IP$DST - Dest address +; IP$TOL - TCP segment length including header +; IP$PTC - Protocol number (needn't set, assumes %PTCTC always) + +TSOSN: METER("TCP: Out segs") + AND T,[TH%CTL] ; Ensure non-flag bits are flushed. + MOVE A,T + ANDCAB A,XBSTAT(I) ; Turn off these request bits + TLNE A,(TH%CTL) ; Any request bits left? + JRST TSOSN2 ; Yeah, can't turn off "now" bit. + MOVSI A,(%XBNOW) ; Satisfied everything, so flush + ANDCAM A,XBSTAT(I) ; the send-immediately bit. + +TSOSN2: LDB A,[PK$TDO (R)] ; Bytes of header + ADDI A,(TT) ; Add bytes of data + DPB A,[IP$TOL (W)] ; Store in IP length field + MOVE A,XBLCL(I) + LSH A,4 + MOVEM A,IP$SRC(W) ; Set source host + MOVE A,XBHOST(I) + LSH A,4 + MOVEM A,IP$DST(W) ; Set dest host + + ; Out-of-TCP info set up, now build the real TCP header. + LDB A,[.BP TH%DST,XBPORT(I)] ; Get port sending from (local) + DPB A,[TH$SRC (H)] + LDB A,[.BP TH%SRC,XBPORT(I)] ; Get port to send to + DPB A,[TH$DST (H)] + MOVE A,XBSNXT(I) ; Get sequence number to use + LSH A,4 + MOVEM A,TH$SEQ(H) ; Set SEQ field + TLNN T,(TC%ACK) ; Check flags, sending ACK? + TDZA A,A ; If not, use zero field anyway. + MOVE A,XBRNXT(I) ; Get ack number to use + LSH A,4 + MOVEM A,TH$ACK(H) ; Set ACK field + + SKIPE A,XBSUP(I) ; Urgent data being sent? + JRST [ TLO T,(TC%URG) ; Yes! Say urgent pointer signif + METER("TCP: Urgent dgms") + MOVNI B,(TT) + ADDB B,XBSUP(I) ; Adjust pointer as result of data sent + CAIGE B, + SETZM XBSUP(I) + LSH A,4 + JRST .+1] + MOVEM A,TH$UP(H) ; Set urgent pointer if any + + MOVE A,XBRWND(I) ; Get our current receive window + LSH A,4 + IOR A,T ; Add in caller's flags + LDB B,[PK$TDO (R)] ; Header length in bytes + LSH B,-2 ; TCP wants length in 32-bit words + DPB B,[<.BP TH%THL,A>] + MOVEM A,TH$THL(H) ; Store header len, flags, window + + PUSH P,TT ; Goddam checksum clobberage + CALL THCKSM ; Now figure out checksum + POP P,TT + DPB A,[TH$CKS (H)] + + ; TCP header set up. Now update our TCB connection vars to + ; account for the stuff we're sending. + TLNE T,(TC%SYN) ; Now find new seq # (SND.NXT) + ADDI TT,1 ; SYN counts as 1 octet + TLNE T,(TC%FIN) ; So does a FIN + ADDI TT,1 + JUMPLE TT,TSOSN8 ; If not actually using seq space, skip + ; a bunch of update/retrans stuff. + + ; We're using up some sequence space! Must update avail window, + ; and put the segment on retransmit queue. + MOVE A,XBSAVW(I) ; Must update avail send window + SUBI A,(TT) + CAIGE A, ; If window becomes negative, + SETZ A, ; keep it at zero. + MOVEM A,XBSAVW(I) + ADD TT,XBSNXT(I) ; Get new SND.NXT + TLZ TT,%MOD32 + MOVEM TT,XBSNXT(I) + SKIPN XBORTT(I) ; Retrans timeout already set? + JRST [ MOVE A,TIME + ADD A,TCPTMO ; Make it 5 sec for now. + MOVEM A,XBORTT(I) + SETZM XBORTC(I) ; Clear count of retries. + JRST .+1] + TRCPKT R,"TSOSND Pkt w/seq space added to retransmit queue" + MOVEI A,(R) ; Arg to PKQPL, A/ PE ptr + MOVEI Q,XBORTQ(I) ; Arg to PKQPL, Q/ queue hdr ptr + CALL PKQPL(PK.TCP) ; Put on TCP retrans queue + AOS XBORTL(I) ; Bump count of segs on queue + +TSOSN8: CALL IPKSND ; Put on IP output queue + RET + +SUBTTL TCP Retransmit and Timeout + +Comment | + The following things in TCP need some sort of timeout: + Retransmit output segment if not ACKed (removed) within RT sec + Timeout to abort connection if retransmission fails for UT sec + Timeout to ACK incoming data (ie avoid ACKing immediately, + wait for more output or input). + Timeout during TIME-WAIT to flush connection. +| + +; TCPCLK - This routine is called by 1/2-sec "slow" clock. What it has to do +; is scan all active TCB's for the following conditions: +; (1) Retransmit timeout has expired, must resend something. +; or TIME-WAIT timeout has expired. +; (2) An ACK must be sent, either by sending the current output +; buffer, or by generating an ACK without data. + +EBLK +TCLKRC: 0 ; Count of segs compacted in pass over a retrans Q +BBLK + +TCPCLK: SKIPN TCPUP ; Do nothing if turned off. + RET + MOVSI I,-XBL + CONO PI,NETOFF + SKIPA A,TIME +TCLK05: SKIPA A,TIME + +TCLK10: SKIPN B,XBSTAT(I) + JRST TCLK15 + SKIPE C,XBORTT(I) + CAMG A,C + CAIA + JRST TCLK20 ; Retrans timeout +TCLK12: TLNE B,(TH%CTL+%XBNOW) ; Any flags set? + JRST TCLK50 ; Wants ACK sent +TCLK15: AOBJN I,TCLK10 + CONO PI,NETON + RET +TCLK16: MOVE A,TIME + AOBJN I,TCLK10 + CONO PI,NETON + RET + + ; Come here for timeout of some sort. +TCLK20: SKIPE XBORTQ(I) ; If a retrans queue exists, + JRST TCLK22 ; then assume it was a retrans timeout. + MOVEI C,(B) ; No retrans Q, probably a TIME-WAIT one? + CAIN C,.XSTMW ; State TIME-WAIT? + JRST [ METER("TCP: Time-Wait timeout") + CALL TXBFLP ; Flush the TCB completely, PI level + JRST TCLK16] + CAIN C,.XSSYQ ; State SYN-QUEUED? + JRST [ METER("TCP: SYQ timeout") + CALL TSISQF ; Flush the queued SYN. + JRST TCLK16] + CAIN C,.XSFN2 ; State FIN-WAIT-2? + JRST TCLK21 + METER("TCP: Random timeout") ; Sigh. + SETZM XBORTT(I) ; Flush whatever it was. + JRST TCLK16 + +TCLK21: METER("TCP: FN2 timeout") + CALL TXBFLP ; Flush the TCB completely, PI level + SKIPE XBUSER(I) ; Shouldn't still have anything open. + BUG CHECK,[TCP: FN2 timo with active user] + JRST TCLK16 + +TCLK22: METER("TCP: Retrans") + AOS C,XBORTC(I) ; Retrans timeout. Send it again. + SKIPE D,XBORTP(I) ; Has user set any retrans params? + JRST [ JRST TCLK25] ; Yes! For now, non-Z means skip abort check. + CAILE C,%TCPMR ; Tried too many times? + JRST TCLK80 ; Ugh, abort the connection! + SKIPN R,XBORTQ(I) + JRST [ SETZM XBORTT(I) ; If nothing on queue, + JRST TCLK12] ; just reset the timeout to nothing. + SKIPGE A,PK.FLG(R) ; Ensure that packet isn't being output now + JRST TCLK25 ; Still being output?? Reset timeout. + ; Note that we don't check to see whether segment has already + ; been transmitted, on the theory that compaction is going to + ; pay off anyway. + HLRZ W,PK.IP(R) + HLRZ H,PK.TCP(R) + SETZM TCLKRC ; Clear compaction count. + + ; Looks like we have to retransmit. Try to compact up as much + ; stuff as possible into a single segment; this gets a bit + ; hairy. Note that we compact as much as we can, ignoring the + ; %PKPIL and %PKODN bits (except for setting the appropriate flush + ; flags). + TRCPKT R,"TCLK30 Segment being retransmitted" +TCLK30: HRRZ J,PK.TCP(R) ; Get pointer to succeeding segment + JUMPE J,TCLK39 ; If none following, can't compact (ignore + ; possibility of adding XBOCOS for now) + LDB B,[PK$TDO (R)] ; Get 1st offset + LDB C,[PK$TDL (R)] ; Get 1st length + LDB T,[PK$TDL (J)] ; Get 2nd length + ADDI B,(C) ; Find offset to end of 1st data + MOVEI D,(B) + ADDI D,(T) ; Find total length after compaction + CAILE D,576.-<5*4> ; Hack hack hack! Limit to 556. so std + ; IP datagram is limited to 576. + JRST TCLK39 ; If too big, don't compact. + + ; Compact two segments into one! + ; R/ 1st seg D/ offset to end of data + ; J/ 2nd seg T/ len of 2nd data + METER("TCP: Retrans compact") + TRCPKT J,"TCLK30 Segment being compacted into previous seg for rexmit" + ADDI C,(T) ; Get new # bytes for 1st seg + DPB C,[PK$TDL (R)] ; Store it in advance. +; HLRZ D,PK.TCP(R) ; Find addr of TCP header in 1st seg + MOVEI D,(H) + IDIVI B,4 + ADDI D,(B) ; Get addr for BP to end of data + HRL D,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + LDB B,[PK$TDO (J)] ; Get data offset for 2nd seg + IDIVI B,4 + HLRZ A,PK.TCP(J) ; Get addr for BP to start of 2nd data + ADDI B,(A) + HRL B,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + ; B/ BP to 2nd data + ; D/ BP to end of 1st data + ; T/ # bytes of 2nd data + LDB A,[IP$TOL (W)] ; Get current length of whole datagram + ADDI A,(T) ; Increment by length of added stuff + DPB A,[IP$TOL (W)] ; Store back + ADDI A,3 + LSH A,-2 + HRLM A,PK.BUF(R) ; Set up new count of # words in datagram. +TCLK32: ILDB C,B + IDPB C,D + SOJG T,TCLK32 + + ; Data copied over, now update flags and stuff. + HLRZ D,PK.TCP(J) + MOVE A,TH$CTL(D) ; Get flags for 2nd seg + AND A,[TH%CTL] ; Mask off just flags + IORM A,TH$CTL(H) ; Add them to flags for 1st seg + TLNE A,(TC%URG) ; If URGENT bit set, + JRST [ LDB B,[TH$UP (D)] ; Get pointer from 2nd seg + LDB C,[PK$TDL (R)] ; Sigh, get new len of 1st seg + ADDI B,(C) ; Adjust for bytes in front + LDB C,[PK$TDL (J)] ; But have to subtract length + SUBI B,(C) ; of 2nd seg (already in 1st len) + DPB B,[TH$UP (H)] ; Store ptr back in 1st seg + JRST .+1] + + ; Compaction done! Now have to remove 2nd seg from queue. + HRRZ B,PK.TCP(J) ; Get pointer to 3rd seg + HRRM B,PK.TCP(R) ; Point 1st at it + CAIN B, ; If 2nd was the last one, + HRLM R,XBORTQ(I) ; must update "last" ptr in queue header. + MOVE A,PK.FLG(J) ; Get flags +IFN PK.TCP-2,.ERR %PQFL flag must match PK.TCP + TLZ A,(%PQFL2) ; Say it's off the TCP list, to allow + ; flushing from IP queue. + TLO A,(%PKFLS) ; In fact, require it + MOVEM A,PK.FLG(J) ; Store flags back + JUMPGE A,[MOVEI A,(J) ; If not locked by PI output, + TRCPKT A,"TCLK32 Seg flushed from rexmit by compaction" + CALL PKTRT ; try to flush it now. + JRST .+1] + SOSGE XBORTL(I) ; Decrement count of retrans queue segs + BUG HALT + AOS TCLKRC ; Bump count of recompacts done + JRST TCLK30 ; OK, try to recompact next seg! + + ; Note one possible problem with following code; although + ; the segment being re-trans'd is given latest poop (ACK, WND), + ; the ones following are not. This is usually OK as we assume + ; that following segs have actually been sent out, but if it + ; happens that they HAVEN'T (i.e. %PKODN not set) then their + ; info is going to be a little out of date. This shouldn't + ; screw things too much, however. +TCLK39: MOVE D,XBRNXT(I) ; Get latest ACK value + LSH D,4 + MOVEM D,TH$ACK(H) ; Set it + MOVE D,XBRWND(I) ; And latest window + DPB D,[TH$WND (H)] + CALL THCKSI ; Compute checksum for it (note not THCKSM) + DPB A,[TH$CKS (H)] + SKIPE TCLKRC ; Was any recompaction done? + CALL IPKHD2 ; Yes, must recompute IP header (checksum etc) + MOVE A,PK.FLG(R) + TLNN A,(%PKODN) ; Has segment already been tried once? + JRST [ ; No, don't put on output queue twice!! + TRCPKT R,"TCLK39 Rexmit skipped because seg not yet output" + METER("TCP: Pretrans compact") + JRST TCLK25] + TLO A,(%PKRTR) ; Set flag saying this is a retransmit + MOVEM A,PK.FLG(R) + MOVEI A,(R) + CALL IPKSNQ ; Put back on IP output queue + ; Note PK.BUF shd still be set up right. +TCLK25: MOVE A,TIME + HRRZ B,XBORTP(I) ; If RH set, use it for new timeout. + CAIN B, + MOVE B,TCPTMO ; Use timeout default. + ADD B,A + MOVEM B,XBORTT(I) + JRST TCLK79 + + ; Here when need to send an ACK. First see if we can + ; make use of existing output buffer. +TCLK50: METER("TCP: slow ACKs") + TLNE B,(TC%SYN+TC%RST) + BUG CHECK,[TCP: SYN or RST set in XBSTAT clock req] + SKIPE R,XBOCOS(I) ; Ensure there is one. + TLNE B,(%XBMPL) ; and that it isn't locked. + JRST TCLK60 ; Sigh, can't use it. + + ; There is an output buffer, and it's not locked, so use that + ; to send stuff out! + TRCPKT R,"TCLK50 COS used to send clock level ACK" + MOVSI T,(TC%PSH) + CALL TCPOFR ; Force it out. + JRST TCLK16 + + ; Come here when we have to generate a new segment for ACK. +TCLK60: TLNN B,(%XBNOW) ; Insisting that we ACK? + JRST TCLK65 ; No, can semi-punt. + CALL PKTGFI ; Get buffer + JRST TCLK65 ; and forget about ACKing if we cant get one + METER("TCP: Clk ACK") + MOVEI R,(A) + MOVE T,B ; Use request flags in segment. + TRCPKT R,"TCLK60 Alloc and send ACK from clock level" + CALL TSOSNR ; Send a simple ACK + JRST TCLK16 + +TCLK65: MOVSI A,(%XBNOW) ; No, so just set insist flag + IORM A,XBSTAT(I) ; and wait a bit longer. + JRST TCLK16 + +TCLK79: + JRST TCLK16 + + ; Abort the connection, timed out. +TCLK80: METER("TCP: Timeout abort") + CALL TXBFLP ; This is pretty drastic... flush, PI level. + MOVEI T,.XCINC ; Say "incomplete transmission" + CALL TCPUC ; as close reason. + JRST TCLK16 + +TCLK90: CONO PI,NETON + RET + + +; Checksum cruft. + +; THCKSM - Figures TCP segment checksum, IP$TOL has TCP segment length. +; THCKSI - Figures TCP segment checksum, IP$TOL has IP header plus TCP seg. +; W/ addr of IP header +; H/ addr of TCP header +; Note that the following out-of-TCP values are looked up +; from the IP header in order to compute sum for the "pseudo header". +; IP$SRC - source host +; IP$DST - dest host +; IP$TOL - # octets in TCP segment (plus IP header) +; Finally, +; %PTCTC - Assumed value +; +; Clobbers B,C,D,E +; Returns +; A/ checksum +; TT/ Total # bytes in TCP segment + +THCKSM: TDZA C,C ; Compute as if IHL=0 +THCKSI: MOVNI C,5*4 + ; First compute pseudo header + LDB A,[IP$SRC (W)] ; Source addr + LDB B,[IP$DST (W)] ; Dest addr + ADD A,B + ADDI A,%PTCTC ; Add TCP protocol number + LDB TT,[IP$TOL (W)] ; Get total length in octets + JUMPE C,THCKS2 + LDB B,[IP$IHL (W)] ; Find IP header length in 32-bit wds + LSH B,2 ; mult by 4 to get # octets + SUBI TT,(B) ; Find # octets of IP data (TCP segment) +THCKS2: ADDI A,(TT) ; Add in. + MOVEI C,-<5*4>(TT) ; Get # bytes in segment after 1st 5 wds + + ; Done with pseudo header (not folded yet, though). + LDB B,[044000,,0(H)] ; Get wd 0 (src/dest) + ADD A,B + LDB B,[TH$SEQ (H)] ; Get wd 1 (seqno) + ADD A,B + LDB B,[TH$ACK (H)] ; wd 2 + ADD A,B + LDB B,[044000,,3(H)] ; wd 3 + ADD A,B + LDB B,[TH$UP (H)] ; wd 4 (part of) + ADDI A,(B) + + LSHC A,-16. + LSH B,-<16.+4> + ADDI A,(B) ; Now have it folded up. + JUMPLE C,THCKS7 ; If nothing more, can leave now. + MOVEI E,5(H) + HRLI E,442000 ; Set up 16-bit byte ptr to options/data + LSHC C,-1 + JUMPLE C,THCKS6 +THCKS5: ILDB B,E + ADDI A,(B) + SOJG C,THCKS5 +THCKS6: JUMPL D,[ ; Jump if odd byte left. + ILDB B,E ; get it + ANDCMI B,377 ; mask off low (unused) byte. + ADDI A,(B) + JRST .+1] +%CKMSK==<-1#177777> ; Mask for stuff above 16 bits +THCKS7: TDNE A,[%CKMSK] ; If any carries, add them in. + JRST [ LDB B,[.BP %CKMSK,A] + TDZ A,[%CKMSK] + ADD A,B + JRST THCKS7] + ANDCAI A,177777 ; Complement sum and mask off. + RET + + +MTRCOD ; Last stuff -- expand meter tables. +TRCCOD ; Expand trace tables diff --git a/src/system/tcpbuf.58 b/src/system/tcpbuf.58 new file mode 100755 index 00000000..e761cc90 --- /dev/null +++ b/src/system/tcpbuf.58 @@ -0,0 +1,575 @@ +COMMENT | + +Notes on TCP input and output buffers + +Ideally the TCP segment queues should be logically separate from the IP +datagram queues, but for efficiency it should be possible to have them +both together. + +Input buffers are expected to be lists of datagrams/segments. +This is reasonably simple, since pointers (in known places) can just be +set up to the data (whereever it is in the datagram/segment). +There is a problem with allocation/windows in this scheme, since it +is possible to run out of datagram buffers before running out of window, +if the remote site becomes cretinous about it and sends only a few +bytes per dgram very fast. But in that case re-transmission can just +force it to buffer up its output, so that future dgrams will be somewhat +more filled, so it is probably OK. If this does become a screw, can +add code to do compaction at clock level. + +Output buffers are a little more uncertain. Could have simple +circular buffer, with appropriate pointers set up so that IMP output +message is read directly from the buffer (same as NCP). Alternatively +could have queue of segments/datagrams all ready to go. Guess I'd +like to try doing the latter, to keep things "simple" by minimizing +the number of kinds of things floating around. + +Problem with putting output datagram together: can't always predict +ahead of time how big the leaders are going to be! Especially true +for IP level, which TCP is not supposed to know too much about. Thus +if not careful, it could happen that output is put into a segment too +close to the start of the buffer, so that there is not enough room for +the TCP and IP headers to fit in. Have to look at this; may need to +give up notion of keeping all the packet internals nicely contiguous. +Maximum IP header length is set at 60 bytes (15 words). The maximum +TCP header length is also 15 words. +Looking at the currently defined options, it seems unlikely that ITS +will use any of them, and if so, they can be predicted fairly easily on +a per-connection basis, so things should work out okay. Note that +the IP level can always simply fragment stuff if it really wants to be +that complex. + +It would be nice to be able to keep track of stuff which is on the +device (IMP) output queue but hasn't yet gone out, in order to add +last-minute bits (like ACK) or even some more data. Idea: output "queue" +is just a list of TCP connections that need attention, so can always +go in and mung stuff (even change mind about outputting) just by playing +with connection flags/lists. This is basically how NCP does it. + +Re packet buffer design: + Somewhat more hypothetical is the notion of keeping a "usage +count" for each buffer, so that pointers from the packet table entries +can point to several different buffers and not just one. When a usage +count hits zero, put the buffer on the freelist. Actually this is not +really needed for the case of a table entry pointing to more than one +buffer, but it IS needed for the case of more than one table entry +pointing to the same buffer. This might happen, for example, if +an internet bypass were set up so that datagrams going to ourselves +were simply vectored directly to the input queues. But for the +time being, it probably isn't too outrageous to simply re-copy the +datagram in question. (Also better emulates a fake network device). + +Suggest that lists point directly to themselves rather than +to start of entry; this allows low-level list routines to be used +on all lists. The higher-level routines of course have to know what +offsets to use for a specific list. Alternatively provide different routines +for each offset needed, and equate references to the appropriate routine +for each use. (This is what I'm trying at the moment, hence the IRPS) + +May want to use format ,, where is the addr +of the initial pointer (not initial node). This allows backtracking +to figure out what TCP connection or IP queue a packet belongs to. +Brute force approach is to simply have another word for the TCB index, etc. + +If this stuff is general enough it could be used for CHAOS packets also. +| + +COMMENT | + +-- Lots of this is wrong now... -- + +Buffers are all 256 (400 octal) words long, and 4 of them fit on one +ITS page. This size was chosen because the maximum length of an IMP +message (not counting IMP-Host padding) is 255 words of 4 8-bit bytes +per word. This allows one extra word; not much. Taking away the +3 IMP leader words (which has to be done anyway for NCP to continue +working) gives us 4 spare words per buffer. + +This still may not be enough. Rather than shoe-horn some clever stuff +into each buffer header, I am opting to maintain "Packet Entries" in a +"Packet Table" separate from the "Packet Buffers" themselves. All +messages/datagrams/segments/packets are identified by a pointer +into the table. (Could use index, as for sockets/TCBs, but this is +awkward for lists). The entry identified by the pointer will contain +the actual pointers into the buffer associated with that packet. +[NOTE: may want to have these pointers point into various places, not +necessarily all the same buffer. Must think about this.] + +Free buffers are linked by a freelist pointer in their first word, +with an identifier in the second word to help GC. The only design +issue for the buffers themselves is how to set things up so that it is +easy to GC a large freelist, i.e. identify pages that have nothing +but free buffers in them and thus can be removed from the system's +address space. Currently I have simply adopted the strategem used for +CHAOS buffers (at CHCLN) to have the core job snuffle over the freelist. + +Note that the low-level routines for manipulating lists are actually +referenced via macros which are given an offset as argument. This +offset refers to the offset between the node pointer and the location +of the "next" pointer in the node; the macro will assemble into a +call to the right routine for that offset. Currently only offsets +up to 2 are supported; any lists that the packet is put on must +be threaded through the first 3 words of the node, and the macros check +for this. +| + + SUBTTL Packet Tracing Code + +IFNDEF PKTTRC,PKTTRC==:0 ; Nonzero turns tracing code on +IF1,IFN PKTTRC,.ERR IP packet tracing code included. + +COMMENT | + +This code can be used to keep a history of what happens to a packet. +The history is stored in the packet buffer as a series of indexes +into a table of named events. + +To trace a particular event use the TRCPKT macro. + + TRCPKT(REG,"String") + +REG is the register which currently contains an index to the packet +buffer table. The code is more efficient if the register is R. String +is the description of the event. + +To generate the event table, you must call the TRCCOD macro somewhere +after the last call to TRCPKT. + +| + +%NTRCE==:77 ; Allow this many trace events. Value must be a bit mask (all + ; ones) to work right. If you make it bigger than 77 + ; you have to change the "TRC%" in the macros to something + ; shorter, too. + +%%%TRC==1 + +; TRCCOD generates TRCTBL, which holds +; for each trace event. +DEFINE TRCCOD +IFN PKTTRC,[ +TRC%0==:<0,,[ASCIZ /Null event/]> +TRCTBL: REPEAT %%%TRC,CONC TRC%,\.RPCNT +IF2, REPEAT %%%TRC,CONC EXPUNGE TRC%,\.RPCNT +] +TERMIN + +DEFINE TRCPKT REG,&(EVENT) +IFN PKTTRC,[ +IFG %%%TRC-%NTRCE,.ERR Too many packet trace events! +CONC TRC%,\%%%TRC,==:<.,,[ASCIZ EVENT]> + IFN REG-R,[ + PUSH P,R + MOVE R,REG + ] + PUSH P,TT + MOVEI TT,%%%TRC + PUSHJ P,PKTPTS + POP P,TT + IFN REG-R,[ + POP P,R + ] +%%%TRC==%%%TRC+1 +] +TERMIN + +IFN PKTTRC,[ + +; Store information in the packet history data buffer +; "Information" is a 6-bit quantity which indexes into a table +; of strings. +; TT/ Reason index +; R/ Pkt Buffer index + +PKTPTS: CONO PI,PIOFF ; Freeze machine + DPB TT,PK.HSP(R) ; Store trace info + IBP PK.HSP(R) ; Bump BP + HRRZ TT,PK.HSP(R) ; Pick up history byte ref (address only) + CAIL TT,PK.HSP(R) ; If we've gotten to the bottom, + JRST [ MOVEI TT,PK.HST(R) ;Wrap around + HRLI TT,(<.BP %NTRCE_30.>) ; BP to left 6 bits + MOVEM TT,PK.HSP(R) ;Reset it to top + JRST .+1 ] + CONO PI,PION + POPJ P, +] + +;;; Packet Table Entries + +EBLK +IFNDEF PKBSIZ,PKBSIZ==1000 ; 512. words per packet buffer (2048 byte MTU) +IFNDEF NPKPGS,NPKPGS==40. ; # pages OK to use for packet buffers +NPKB==:> ; # packet buffers available +NPKE==:NPKB ; # packet entry nodes. +IFN NPKB-NPKE,.ERR You must fix the UFLS at PKTGF. + +PKETBL: OFFSET -. + ; General (device driver, etc) +PK.FLG:: 1,,PKETBL+PK.L ; General - ,, + %PKPIL==: ; Packet locked at PI level, being output + %PKODN==:<1000,,> ; Packet has been output (else not yet) +;;; %PKNOF==:<2000,,> ; Packet should not be freed when output done. + %PKFLS==:<4000,,> ; Flush pkt if seen on output queue (ie dont output) + %PKRTR==:<10000,,> ; Packet is being re-transmitted by TCP + .SEE %PQFLX ; Low bits of LH used for on-list flags. + +PK.IP:: 0 ; IP Datagram - ,, + ; May be strung on Internet Queue, IP output queue +PK.TCP:: 0 ; TCP Segment - ,, + ; May be strung on TCB input Q, output retransmit Q +PK.TCI:: 0 ; TCP Segment - <# bytes data><# bytes offset> + PK%TDL==:<777700,,0> ; # octets of data in TCP segment + PK%TDO==:< 77,,770000> ; # octets data is offset from TCP header + PK%TCB==:< ,,007777> ; TCB connection index + PK$TDL==:<.BP PK%TDL,PK.TCI> + PK$TDO==:<.BP PK%TDO,PK.TCI> + PK$TCB==:<.BP PK%TCB,PK.TCI> +PK.BUF:: 0 ; General - <# wds>,, +PK.TIM:: 0 ; General - Time sent or received, int level (Sys time) +PK.DST:: 0 ; Immediate destination address if on output queue +PK.HWI:: 0 ; Hardware Information - currently KS Unibus address + +IFN PKTTRC,[ +PK.HST:: BLOCK 3 ; Packet trace history buffer +PK.HSP:: 0 ; Packet trace history pointer +] + +PK.L:: OFFSET 0 ; Length of a Packet-Entry (PE) node + REPEAT ,[ + IFN .RPCNT-, 1,,.+PK.L ; Build initial freelist + .ELSE 1,,0 + BLOCK PK.L-1 + ] +PKETBE==:.-PK.L ; Last legal PE pointer value + +PKEQHF: PKETBE,,PKETBL ; Header for Packet-Entry node freelist + +BBLK + +; A "queue" is a list of nodes pointed to by a "queue header" word +; of format ,,. Each node pointer points to +; the next node pointer (or zero if no more). +; There is a set of flags in the LH of a certain word, at offset +; PQ.FLG, that indicate which lists a node is currently on. + +PQ.FLG==:PK.FLG ; Offset of word list-flags are in. +%PQFLX==0 ; Initial val +IFNDEF %%%QOF,%%%QOF==0 ; This gets set to highest offset supported + +IRPS PKQGF,,[PKQGF0:PKQGF1:PKQGF2:]PKQPL,,[PKQPL0:PKQPL1:PKQPL2:]PKQPF,,[PKQPF0:PKQPF1:PKQPF2:]%PQFL,,[%PQFL0:%PQFL1:%PQFL2:] +IFG .IRPCNT-%%%QOF,%%%QOF==.IRPCNT + + %PQFL==:<1_.IRPCNT,,> ; Def a flag in LH at offset PQ.FLG + %PQFLX==%PQFLX\%PQFL ; Mask of all list-flags def'd. + +; PKQGF - Get first node from queue +; Q/ addr of queue header +; A/ addr of node (zero if none) + +PKQGF: CONO PI,PIOFF ; Work at all levels + HRRZ A,(Q) ; Get 1st from queue header word + JUMPE A,PIONJ ; None, so return zero. + MOVSI T,(%PQFL) ; Now clear appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's not on it any more. + TLNE T,(%PQFL) ; Paranoia plus + BUG HALT,[PK: GF node wasnt on list] + HRRZ T,.IRPCNT(A) ; Get 2nd + HRRM T,(Q) ; Make it 1st + CAIN T, ; If all's well, done. + SETZM (Q) ; Else must clear whole header +IFNDEF PIONJ,PIONJ: + CONO PI,PION + POPJ P, + +; PKQPL - Put node on queue as last thing. +; Q/ addr of queue header +; A/ addr of node +PKQPL: TRNN A,-1 ; More paranoia + BUG HALT,[PK: zero node ptr] + HLLZS .IRPCNT(A) ; Say this node is last one + CONO PI,PIOFF ; Work at all levels + MOVSI T,(%PQFL) ; Paranoia: Set appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's on it now. + TLNN T,(%PQFL) ; plus check... + BUG HALT,[PK: node already on list] + HLRZ T,(Q) ; Get last node + HRLM A,(Q) ; Point to new last node + JUMPN T,[HRRM A,.IRPCNT(T) ; Make prev last node point to new last + JRST .+2] ; Skip over next instr!! + HRRM A,(Q) ; Queue was empty, make this the new first too + CONO PI,PION + POPJ P, + +; PKQPF - Put node on queue as first thing. +; Q/ addr of queue header +; A/ addr of node +PKQPF: TRNN A,-1 ; Yes more paranoia + BUG HALT,[PK: zero node ptr] + CONO PI,PIOFF + MOVSI T,(%PQFL) ; Paranoia: Set appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's on it now. + TLNN T,(%PQFL) ; check... + BUG HALT,[PK: node already on list] + HRRZ T,(Q) ; Get first thing + CAIN A,(T) ; paranoia, avoid loops to self + BUG + HRRM T,.IRPCNT(A) ; Make it second thing + HRRM A,(Q) ; Make new first thing + CAIN T, + HRLM A,(Q) ; Was empty, also make it last thing. + CONO PI,PION + POPJ P, +TERMIN + +; Define PKQGF, etc so that they actually reference PKQGF0, etc as +; appropriate for the given offset. +IRP RTN,,[PKQGF,PKQPF,PKQPL] +DEFINE RTN ?OFFST=0, +CONC RTN,\OFFST +IFG OFFST-%%%QOF,.ERR RTN used with bad offset +TERMIN +TERMIN + + +; PKEGF - Get a free Packet-Entry node +; Clears node contents. +; Clobbers Q,T +; Returns A/ PE ptr (0 if none) + +PKEGF: MOVEI Q,PKEQHF +IFE PKTTRC,[ + CALRET PKQGF ; Get a node +] +IFN PKTTRC,[ + CALL PKQGF + JUMPE A,CPOPJ ; No packet + SETZM PK.HST(A) + SETZM PK.HST+1(A) + SETZM PK.HST+2(A) + MOVEI Q,PK.HST(A) ; Build byte ref to history trail + HRLI Q,(<.BP %NTRCE_30.>) ; (dpb ref) + MOVEM Q,PK.HSP(A) ; save ref + POPJ P, +] + +; PKERT - Return a Packet-Entry node to freelist +; A/ PE ptr to node +; Clobbers Q,T + +PKERT: MOVEI Q,PKEQHF ; Use Packet-Entry freelist + CALRET PKQPF ; Put back on start of list. + +; Note that all MP calls to the routines below which allocate or free +; entries/buffers must be sure not to block (page fault or UFLS) +; while any "loose" entries/buffers exist (not pointed to by any list) +; unless there something on the PCLSR locked-switch list which will return the +; currently "loose" entry/buffer to its freelist -- otherwise +; it is possible for "loose" stuff to slowly accumulate. + +; PKTGF - Get a free Packet-Entry node and Packet Buffer. Hangs until +; it wins. Note that it depends on fact there is one PE node +; for every packet buffer, and vice versa! If this becomes untrue +; then the way it UFLSes should be fixed up. +; PKTGFI - version that skips if wins, doesn't hang. +; Returns A/ PE ptr Clobbers Q,T + +PKTGF: SKIPN PKEQHF ; Fast check, see if any packet entries/buffers free + CALL UFLS ; Nope, hang until something turns up. + CALL PKTGFI ; Get a entry/buffer! + JRST PKTGF ; None? Sigh, go hang. + RET + +PKTGFI: CALL PKEGF ; Get a free node + JUMPE A,CPOPJ + PUSH P,A ; Save pointer to it +PKTGF1: CALL PKBGF ; Get a free buffer + JUMPN A,PKTGF8 ; Jump if found one right away! + CALL PKBAL ; None left on freelist, try to allocate more. + CAIA ; Sigh, failed. + JRST PKTGF1 ; Won, go pluck a buffer from freelist. + + ; Lost, can't get any more buffers. + POP P,A ; None available, take non-skip return + CALRET PKERT ; Put PE node back on its freelist. + + ; Won, store buffer pointer in PE. +PKTGF8: MOVE T,A + POP P,A ; Restore PE ptr + MOVEM T,PK.BUF(A) + MOVE T,PQ.FLG(A) ; Paranoia dept, verify not on any lists. + TLNE T,(%PQFLX) + BUG HALT,[PK: Freelist node not free!] + SETZM PK.FLG(A) ; Zap all other entries in packet node. + SETZM PK.IP(A) + SETZM PK.TCP(A) + SETZM PK.TCI(A) + SETZM PK.TIM(A) + AOS (P) ; Win, skip on return! + RET + +; PKTRT - Return both a Packet-Entry and its associated buffer to freelist +; only if check shows that it doesn't belong to any lists. +; PKTRTA - Always return to freelist. If check shows that it is still +; on some list, bad error! +; Clobbers A,Q,T +; A/ PE ptr (must be off all lists) + +PKTRTA: CAIL A,PKETBL ; Paranoia check for legal pointers + CAILE A,PKETBE + BUG HALT,[PK: Bad PE pointer] + MOVE T,PQ.FLG(A) + TLNE T,(%PQFLX\%PKPIL) ; On list or locked at I/O PI level? + BUG HALT,[PK: Freeing packet still in use!] + JRST PKTRTX ; Nope, can proceed to put on freelist. + +PKTRT: CAIL A,PKETBL ; Paranoia check for legal pointers + CAILE A,PKETBE + BUG HALT,[PK: Bad PE pointer] + MOVE T,PQ.FLG(A) + TLNE T,(%PQFLX\%PKPIL) ; On a list or locked by interface PI level? + RET ; Yes, don't return to freelist yet. +PKTRTX: PUSH P,A ; Save PE ptr + SKIPE A,PK.BUF(A) ; Get buffer pointer associated with PE + CALL PKBRT ; Return the buffer + POP P,A + SETZM PK.BUF(A) ; Ensure buffer pointer zapped. + CALRET PKERT ; Then return the packet entry + +; PKTPCL - Return a packet entry/buffer while PCLSR'ing. +; This is the standard LOSSET routine to use. +; A must hold the PE ptr at time of the block (which we are backing +; out of). +; Must only clobber A and T!! + +PKTPCL: MOVE A,AC0S+A(U) ; Get ac A at time of the block + PUSH P,Q ; Mustn't clobber Q + CALL PKTRT ; Return the entry/buffer (clobbers Q,T) + JRST POPQJ + + +EBLK +PKBNF: 0 ; # free Packet Buffers +PKBNT: 0 ; # total Packet Buffers +PKBCTM: 0 ; Time of last no-more-core complaint +PKBQHF: 0 ; Queue Header for buffer freelist +PKBQHC: 0 ; Queue Header for core job cleanup +BBLK + +; PKBGF - Get a free Packet Buffer +; Clobbers Q,T +; Returns A/ PB ptr (0 if none) + +PKBGF: MOVEI Q,PKBQHF ; Point to buffer freelist + CALL PKQGF ; Get first thing off it + JUMPE A,CPOPJ ; If got nothing, just return. + SETZM 1(A) ; Aha, got it! Flush free-buffer identifier. + SOS PKBNF ; Decrement # free packet buffers. + RET + +; PKBRT - Return a Packet Buffer to freelist. Puts back at END of freelist, +; as PKBCLN clean-up depends on this. +; Clobbers Q,T +PKBRT: SETZM (A) ; Paranoia aid - clear "flags" in LH of 1st wd. + ; Otherwise PKQ routines complain. + MOVE T,[SIXBIT /BRUNCH/] + MOVEM T,1(A) ; Set up free-buffer identifier + AOS PKBNF ; Increment # free packet buffers. + MOVEI Q,PKBQHF ; Point to buffer freelist + CALRET PKQPL ; Put it back on, at end. + +; PKBRTL - Return a list of Packet Buffers to freelist +; Q/ ptr to queue header of list +; Clobbers A,T +PKBRTL: CALL PKQGF ; Get first thing off list + JUMPE A,CPOPJ + PUSH P,Q + CALL PKBRT ; Return it to buffer freelist + POP P,Q + JRST PKBRTL + +; PKBAL - Allocate more Packet Buffers +; Clobbers A,Q,T +; Returns .+1 if lost +; .+2 if won (must still call PKBGF to get a buffer from list) + +PKBAL: PUSH P,B + CONI PI,Q ; Save PI channel-on status + ANDI Q,177 + CONO PI,UTCOFF ; Make the world safe for IOMQ + MOVE B,PKBNT ; Check total # of buffers so far + CAIL B,NPKB ; Make sure we're not already using max allowed + JRST PKBAL4 ; Ugh, already at max! Go complain. + PUSHJ P,IOMQ ; Get 1K of memory + JRST PKBAL3 ; Mem not available, fail + CONO PI,PICON(Q) ; Won, restore PI status + MOVEI B,MUPKT ; Set page type = packet + DPB B,[MUR,,MEMBLT(A)] + LSH A,10. ; Turn allocated page # into mem address + HRLI A,-<2000/PKBSIZ> ; Make AOBJN into page (# buffers per page) +PKBAL2: PUSHJ P,PKBRT ; Put them all on free list + ADDI A,PKBSIZ-1 + AOBJN A,PKBAL2 + MOVEI B,<2000/PKBSIZ> ; This many more buffers have been created + ADDM B,PKBNT ; Increase total (PKBNF bumped by PKBRT) + POP P,B + AOS (P) ; Take win return. + RET + + ; Here if packet stuff trying to use up too much core +PKBAL4: MOVE B,PKBCTM ; Don't complain too often + ADDI B,60.*30. ; Just once a minute + CAMLE B,TIME + JRST PKBAL3 + BUG CHECK,[PACKET NET ATTEMPTING TO USE TOO MUCH CORE] + MOVE B,TIME + MOVEM B,PKBCTM +PKBAL3: CONO PI,PICON(Q) ; Lost, restore PI status + POP P,B + POPJ P, ; and take error return. + + +; PKBCLN - Called only by core job, to clean up packet buffers. +; Smashes all ACs. + +PKBCLN: SKIPE A,PKBNT ; See if 2/3 or more of buffers free + SKIPN B,PKBNF + POPJ P, ; No buffers or none free, nothing to do + SUBM A,B + IDIV A,B ; Get ratio of total to used + CAIGE A,3 ; Note if B is zero, A is unchanged + POPJ P, ; and at least 32. +IFL TSYSM-256., MOVEI D,TSYSM-1 ; Scan memory for packet buffer pages +.ELSE MOVEI D,255. +PKBCL0: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUPKT +PKBCL4: SOJGE D,PKBCL0 + JUMPL D,CPOPJ + MOVE A,D ; Quickly determine if any non-free buffers + LSH A,10. ; on this page + HRLI A,-<2000/PKBSIZ> + MOVE T,[SIXBIT/BRUNCH/] +PKBCL5: CAME T,1(A) + JRST PKBCL4 ; Not free, don't bother with slow stuff + ADDI A,PKBSIZ-1 + AOBJN A,PKBCL5 + SETZB C,PKBQHC ; Collect all free buffers on this page + MOVE E,PKBNF ; Loop about as many times as there are free buffers +PKBCL1: PUSHJ P,PKBGF ; Get next free buffer + JUMPE A,PKBCL2 + LDB B,[121000,,A] + CAMN B,D + JRST [ MOVEI Q,PKBQHC ; This one's on the page, save it + PUSHJ P,PKQPL + AOJA C,.+2 ] ; Count them + PUSHJ P,PKBRT ; Not on the page, put back. This depends on + ; the fact PKBRT puts back at END of list! + SOJG E,PKBCL1 +PKBCL2: CAIE C,<2000/PKBSIZ> ; Did we get the whole page? + JRST [ MOVEI Q,PKBQHC ; No, must punt this one, and + PUSHJ P,PKBRTL ; return all the buffers we saved up. + JRST PKBCL4] + MOVNS C ; Yes, get rid of these buffers + ADDM C,PKBNT ; Decrement total # of buffers in use + MOVE A,D + PUSHJ P,MEMR ; Flush the page from addr space + JRST PKBCLN ; Back to flush more, until quota done. diff --git a/src/system/time.950 b/src/system/time.950 new file mode 100755 index 00000000..06e616fc --- /dev/null +++ b/src/system/time.950 @@ -0,0 +1,343 @@ +;I T S .OPERS RELEVANT TO REAL TIME + + ;.PDTIME AC, ;RETURNS PDUPS*<# SECS SINCE BEGINNING OF YEAR> + +APDTIM: PUSHJ P,GPDTIM + JRST RETM1 ;-1 IF NOT KNOWN + JRST APTUAJ + + ;.RDATE AC, ;RETURNS SIXBIT YYMMDD IN AC + +ARDATE: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + JRST RETM1 ;NOT AVAILABLE + IDIVI A,SPD ;GET # DAYS SINCE BEGINNING OF YEAR + PUSHJ P,RDATE ;GET THE ANSWER + JRST APTUAJ ;RETURN IT + + ;.RTIME AC, ;RETURNS SIXBIT HHMMSS (24 HOUR TIME) IN AC + +ARTIME: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + JRST RETM1 ;NOT AVAILABLE + IDIVI A,SPD ;GET # SECS SINCE MIDNIGHT IN B + PUSHJ P,RTIME ;CONVERT TO SIXBIT HHMMSS + JRST APTUAJ ;RETURN IT + + ;.RDATIM AC, ;DOES .RTIME TO AC, .RDATE TO AC+1 + +ARDATI: PUSHJ P,GLPDTM ;GET CRUD + JRST RETM1 ;NO LUCK (THIS IS GETTING BORING) + IDIVI A,SPD ;CONVERT TO DAYS AND SECONDS + HRLM A,(P) ;SAVE DAYS ON PDL + PUSHJ P,RTIME ;GET TIME (HHMMSS) + UMOVEM A,(J) ;GIVE TO USER + HLRZ A,(P) ;GET DAYS AGAIN + PUSHJ P,RDATE ;CONVERT TO SIXBIT + AOJA J,APTUAJ ;GIVE TO USER AND RETURN + + ;.RYEAR AC, ;PUSHJ'S TO RYEAR AND MOVEM'S E TO AC + +ARYEAR: PUSHJ P,RYEAR ;GET THE CRUFT + UMOVEM E,(J) ;STORE YEAR AND CRUD + POPJ P, + + ;.RLPDT AC, ;DOES .RYEAR AC+1, AND ALSO MOVEM'S A TO AC + +ARLPDT: PUSHJ P,RYEAR ;GET THE CRUFT + UMOVEM E,1(J) ;STORE YEAR AND CRUD + JRST APTUAJ ;STORE TIME AND RETURN + + ;ROUTINE TO RETURN -1 ON AN OPER + +RETM1: XCTR XRW,[SETOM (J)] + POPJ P, + + ;GET THE CORRECTED PDUPS*<# SECS SINCE BEGINNING OF YEAR> IN A + ;SKIP IF OFFSET AVAILABLE AND CLOCK ON + +GPDTIM: +IFN PDCLKP,[ + SKIPN A,PDTIME ;GET THE OFFSET + JRST GPDTM2 ;NOT AVAILABLE + DATAI PDCLK,B ;GET WHAT THE CLOCK IS SAYING + TLZ B,600000 + JUMPE B,GPDTM2 ;POWER PROBABLY (BUT NOT NECESSARILY) TURNED OFF + SUBM B,A ;DO THE CORRECTION + JUMPL A,CPOPJ ;LOST, DON'T RETURN A NEGATIVE NUMBER! + JRST POPJ1 ;EXIT SKIPPING (SUCCESS) +] ;PDCLKP +IFN KS10P,[ + SKIPN PDTIME ; Offset available? + JRST GPDTM2 ; No: Try backup + RDTIM A ; Read clock into A!B + TLC A,1729. ; "A most interesting number" + TLNE A,-1 ; Does the clock look like it has been set? + JRST GPDTM2 ; Must have been reset + DIVI A,KSFREQ ; Convert to 60ths + SUB A,PDTIME ; Subtract offset + JUMPL A,CPOPJ ; Wooops, don't return a negative number! (Why + ; don't we use the backup in this case?) + JRST POPJ1 +] ;KS10P +GPDTM2: SKIPGE A,PDYTIM ;CLOCK NOT ON, TRY BACKUP + POPJ P, ;SORRY, NOT AVAILABLE + IMULI A,30. ;CONVERT TO SIXTIETHS OF A SECOND + JRST POPJ1 ;CALL IT CORRECT AND AVAILABLE + + ;GET SIXBIT YYMMDD (DATE) IN A (LOCALIZED PDTIME/SPD IN A, YEAR IN RH(E)) + +RDATE: PUSHJ P,RDATE1 ;GET DAY IN C, MONTH IN B + MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT + PUSHJ P,RDATM1 ;DEPOSIT DAY + MOVE C,B ;GET MONTH + PUSHJ P,RDATM1 ;DEPOSIT MONTH + MOVEI B,(E) ;GET YEAR + IDIVI B,100. ;GET LAST TWO DIGITS IN C +ARTIMX: PUSHJ P,RDATM1 ;DEPOSIT YEAR (ENTRY FROM RTIME TO DEPOSIT HOUR) + IOR A,[SIXBIT /000000/] ;CONVERT TO REAL SIXBIT + POPJ P, + + ;GET MONTH (1 => JAN) IN B, DAY (1 => THE FIRST) IN C + +RDATE1: AOS C,A ;GET DAY OF YEAR (LOCALIZED) (1 => THE FIRST) + MOVEI B,12. ;INITIALLY ASSUME DECEMBER FOR MONTH + CAMG C,LMNTBL-1(B) ;IF DAY IN YEAR .LE. DAY IN YEAR AT BEGINNING OF THIS MONTH, + SOJA B,.-1 ;THEN DECREMENT TO PREVIOUS MONTH AND TRY AGAIN + SUB C,LMNTBL-1(B) ;C(C) := DAY OF MONTH + POPJ P, + +LMNTBL: MNIRP [] ;TABLE OF DAYS GONE BY AT BEGINNING OF MONTH + + ;GET THE SIXBIT TIME IN A (# SECS SINCE MIDNIGHT IN B) + +RTIME: MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT + IDIVI B,60. ;GET SECONDS IN C + PUSHJ P,RDATM1 ;DEPOSIT INTO A + IDIVI B,60. ;GET HOURS IN B, MINUTES IN C + PUSHJ P,RDATM1 ;DEPOSIT MINUTES + MOVE C,B ;GET HOURS IN C + JRST ARTIMX ;DEPOSIT HOURS, CONVERT TO SIXBIT, AND RETURN + + ;DEPOSIT C(C) AS TWO SIX BIT (AS OPPOSED TO SIXBIT) DECIMAL DIGITS + ; VIA T (INTO A) THEN DECREMENT T + +RDATM1: IDIVI C,10. ;SEPARATE DIGITS + DPB C,[60600,,D] ;DEPOSIT FIRST DIGIT TO GIVE 12 BITS + DPB D,T ;OUTPUT BYTE + ADD T,[140000,,] ;DECREMENT BYTE POINTER + POPJ P, ;THAT'S ALL + + ;DO A PUSHJ P,GLPDTM THEN HACK AROUND + ;DO THOSE THINGS TO E COMMENTED IN GLPDTM AS BEING DONE BY RYEAR + ;TRY TO GET YEAR EVEN IF GLPDTM DOESN'T SKIP, BUT IN THAT CASE CLOBBER A TO -1 + +RYEAR: PUSHJ P,GLPDTM ;GET THE CRUFT + JRST RYEAR2 ;DIDN'T SKIP, SEE WHAT CAN BE SALVAGED +RYEAR1: PUSH P,A ;PROTECT A FROM FUTURE CLOBBERAGE + IDIVI A,SPD ;GET LOCALIZED # DAYS SINCE BEGINNING OF YEAR + JUMPL E,[SOJA A,.+1] ;DE-LOCALIZE + LDB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR + ADD A,B ;ADD IN + IDIVI A,7 ;GET TODAY'S DAY OF WEEK (0 => SUNDAY) IN B + DPB B,[320300,,E] ;DEPOSIT IN E + TLO E,40000 ;DOCUMENT FACT THAT TIME OF YEAR KNOWN + JRST POPAJ ;RESTORE A AND RETURN + +RYEAR2: PUSHJ P,GDWOBY ;GLPDTM DIDN'T SKIP, TRY TO SALVAGE CRUFT: FIRST DOWOBY + MOVNI A,1 ;DOCUMENT FACT THAT TIME OF YEAR NOT KNOWN + JUMPE E,CPOPJ ;RETURN IF YEAR NOT KNOWN EITHER + DPB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR + JRST CMPF29 ;SEE IF LEAP YEAR, AND RETURN + + ;NOTE: THE SYMS JAN, FEB, MAR, ETC. ARE DEFINED AFTER (AND BY) MNIRP (A MACRO) + + ;INCREMENT YEAR + +NUPDT: TLNN E,200000 ;SEE IF LEAP YEAR + SKIPA A,[<365.*SPD*PDUPS>] ;NORMAL YEAR + MOVE A,[<366.*SPD*PDUPS>] ;LEAP YEAR + ADDM A,PDTIME ;UPDATE PDCLK OFFSET + IDIVI A,30. ;CONVERT TO HALF-SECONDS + EXCH A,PDYTIM ;ALSO UPDATE BACKUP SYSTEM + SUBM A,PDYTIM + AOS FYEAR ;INCREMENT YEAR + + ;INSERT OTHER CRUFT HERE IF DESIRED + ;DROPS THROUGH + + ;CODING DROPS THROUGH FROM PREVIOUS PAGE +;GET "LOCALIZED" NUMBER OF SECONDS SINCE BEGINNING OF YEAR IN A + ;IF DIVIDED BY # SECONDS IN A DAY, + ;GIVES REMAINDER OF # SECONDS SINCE MIDNIGHT LOCAL TIME + ;QUOTIENT WHEN FED TO DATE GENERATOR ROUTINE ASSUMING LEAP YEAR GIVES CORRECT DATE +;ALSO GET YEAR AND FLAGS (AS RETURNED BY .RYEAR) IN E + ;1.1-2.9 => YEAR (E.G. 1969.) + ;3.1-3.5 ZERO + ;3.6-3.8 => DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) + ;3.9-4.2 ZERO (RYEAR SETS THIS BYTE TO TODAY'S DAY OF WEEK IF TIME OF YEAR KNOWN) + ;4.6 ZERO (RYEAR SETS IT TO 1 IF TIME OF YEAR KNOWN) + ;4.7 ONE => DAYLIGHT SAVINGS TIME IN EFFECT + ;4.8 ONE => LEAP YEAR + ;4.9 ONE => 365 DAY YEAR AND AFTER FEB 28 +;SKIPS IF PDCLK ON AND BOTH PDTIME AND FYEAR NON-ZERO (IN OTHER WORDS IF SUCCESSFUL) +;PREVIOUS CODING DROPS THROUGH ON YEAR INCREMENT + +GLPDTM: CONO PI,CLKOFF ;AVOID DOUBLE YEAR INCREMENT + SKIPE E,FYEAR ;GET YEAR IN E, SKIP IF NOT AVAILABLE + PUSHJ P,GPDTIM ;GET PDTIME, SHOULD SKIP + JRST CLKONJ ;SOMETHING NOT AVAILABLE, DON'T SKIP + IDIVI A,60. ;CONVERT TO SECONDS + PUSHJ P,CMPF29 ;MAYBE SET BIT 4.8 OR 4.9 OF E, IF 4.9 SET THEN ADD SPD TO A + CAML A,[366.*SPD] ;IF MORE THAN A YEAR HAS GONE, + JRST NUPDT ;THEN INCREMENT YEAR + CONO PI,CLKON ;TIMIMG ERROR PROBLEM GONE + PUSH P,A ;SAVE # SECONDS DURING NEXT CALL + PUSHJ P,GDWOBY ;GET DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) + DPB B,[270300,,E] ;DEPOSIT IN RIGHT PLACE + POP P,A ;RESTORE A + AOS (P) ;CAUSE RETURN TO SKIP + + ;IF DAYLIGHT SAVINGS TIME THEN ADD 3600. TO A AND SET BIT 4.7 IN E + +GLPDT2: JFCL ;POPJ FOR STD TIME + ;JRST CRDDST FOR DAY LIGHT TIME + ;JFCL "NORMAL" + CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 1, + CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCT 31, + POPJ P, ;THEN OBVIOUSLY STANDARD TIME IS IN EFFECT + CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 7 STANDARD TIME, + CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCTOBER 25, + JRST GLPDT3 ;THEN NOT OBVIOUS +CRDDST: TLO E,100000 ;DAYLIGHT SAVINGS TIME, SET BIT IN E + ADDI A,3600. ;CONTINUE TO LOCALIZE THE TIME THAT WILL BE RETURNED + POPJ P, + + ;IT IS NOW SOMETIME DURING THE WEEKS IN APR AND OCTOBER + ;WHEN IT MAY BE EITHER STANDARD OR DAYLIGHT SAVINGS TIME + +GLPDT3: PUSH P,A ;SAVE # SECS + CAMG A,[JUL*SPD] ;IF NOT YET JULY, + TDZA D,D ;THEN IT MUST BE APR, SET INDEX + MOVEI D,1 ;OCTOBER, SET INDEX + SUB A,CRDSB(D) ;COMPENSATE FOR 2AM OR 1AM + IDIVI A,SPD ;FLUSH SECONDS, LEAVE ONLY DAYS (IT LOOKS LIKE A LEAP YEAR, REMEMBER) + LDB C,[270300,,E] ;GET DAY OF WEEK OF BEGINNING OF YEAR IN C + JUMPGE E,.+3 ;IF REGULAR YEAR, + SOJGE C,.+2 ;THEN DE-LOCALIZE SO IT WILL RE-LOCALIZE LATER... + MOVEI C,6 ;MOD 7 + ADD A,C ;ADD TO NUMBER OF DAYS + IDIVI A,7 + IMULI A,7 + SUB A,C ;C(A) := NUMBER OF DAYS IN YEAR BEFORE LAST SUNDAY (MAYBE TODAY) + ;IF LAST SUNDAY (AS DEFINED ABOVE) IS BELOW THE "REGION OF AMBIGUITY", + ;THEN IT HAS NOT YET CHANGED TO THE LATER TIME + XCT CRDTST(D) ;SKIP IF DAYLIGHT SAVINGS TIME + JRST POPAJ ;STANDARD TIME, NO CHANGES NECESSARY + POP P,A ;DAYLIGHT SAVINGS TIME, RESTORE A + JRST CRDDST ;MUNG A AND E AND RETURN + +CRDSB: 7200. ;IN APR CHANGES AT 2AM EST + 3600. ;IN OCTOBER CHANGES AT 1AM EST + +CRDTST: CAIGE A, + CAIL A, + + ;IF LEAP YEAR THEN SET BIT 4.8 OF E + ;IF NOT LEAP YEAR THEN IF AFTER FEB 28 THEN SET BIT 4.9 OF E AND ADD SPD TO A + +CMPF29: TRNN E,3 ;IF LEAP YEAR, (HOPEFULLY THIS ONLY PLACE WHERE DIRECTLY CHECKED FOR LEAP YEAR) + TLOA E,200000 ;THEN SET BIT 4.8 OF E AND RETURN + CAMGE A,[<-1>*SPD] ;365 DAY YEAR, IF BEFORE MARCH FIRST, + POPJ P, ;THEN RETURN + TLO E,400000 ;365 DAY YEAR AFTER FEB 28, SET BIT 4.9 OF E + ADDI A,SPD ;INCREMENT A ONE DAY + POPJ P, + + ;GET DAY OF WEEK OF BEGINNING OF YEAR (IN E) (0 => SUNDAY) IN B + ;FOLLOWING ROUTINE HAS BEEN EXHAUSTIVELY CHECKED + +GDWOBY: MOVEI A,-1(E) + IDIVI A,400. + MOVEI A,1(B) + IDIVI B,4 + ADD A,B + IDIVI B,25. + SUB A,B + IDIVI A,7 + POPJ P, + + ;SLOW CLOCK ROUTINE TO CHECK ON REAL-TIME CLOCK SYSTEM + +PDCCHK: SKIPL PDYTIM ;IF BACKUP TIME (SINCE BEGINNING OF YEAR) CALCULATED, + AOS PDYTIM ;THEN UPDATE IT + SKIPGE TIMOFF ;IF TIMOFF NOT CALCULATED, + POPJ P, ;THEN RETURN + AOS A,TIMOFF ;UPDATE TIMOFF + CAMGE A,[2*SPD] ;Incremented beyond length of day? + JRST PDCCH1 + SETZB A,TIMOFF ;Yes - reset it. + MOVEM A,RSWTIM ;Also reset last-resource-warning timestamp. +PDCCH1: TRNE A,64.*2-1 ;Is this a 64. second (based on TIMOFF) clock break? + POPJ P, ; No, so return. +INITIM: +IFN PDCLKP,[ + SKIPN A,PDTIME ;MAYBE UPDATE BACKUP SYSTEM + JRST INITM2 ;PDTIME NOT AVAILABLE, DON'T + DATAI PDCLK,B + TLZ B,600000 + JUMPE B,INITM2 ;JUMP IF CLOCK OFF + SUBM B,A + JUMPL A,CPOPJ + IDIVI A,30. ;CONVERT TO HALF-SECONDS SINCE BEGINNING OF YEAR + MOVEM A,PDYTIM ;STORE RE-CALCULATED BACKUP TIME +] ;PDCLKP +IFN KS10P,[ + SKIPN PDTIME ; Update backup system? + JRST INITM2 ; Not without offset + RDTIM A + TLC A,1729. + TLNE A,-1 + JRST INITM2 ; Not if clock reset + DIVI A,KSFREQ + SUB A,PDTIME ; 60ths since Jan 1 + JUMPL A,CPOPJ + IDIVI A,30. ; halfs since Jan 1 + MOVEM A,PDYTIM ; Store backup +] ;KS10P +INITM2: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + POPJ P, ;SOMETHING'S MISSING + IDIVI A,SPD ;SEPARATE INTO DAYS AND SECONDS + LSH B,1 ;CONVERT TIME SINCE MIDNIGHT TO HALF-SECONDS + MOVEM B,TIMOFF ;STORE RE-CALCULATED NUMBER OF HALF-SECONDS SINCE MIDNIGHT + PUSHJ P,CLCQDT ;GET QDATE,,TIMOFF IN A + CONO PI,UTCOFF ;INHIBIT INTERRUPTS DURING THIS RITUAL + SKIPGE A,QMDRO ;GET ORIGIN OF MASTER DSK DIRECTORY + JRST UTCONJ ;DIRECTORY LOCKED + MOVE B,QACTB ;DIRECTORY CHANGED BIT FOR DSK DIRECTORY + SKIPE T,PDTIME ;GET OFFSET FOR DECORIOLIS CLOCK + CAMN T,MPDOFF(A) ;SEE IF IT MATCHES RELEVANT WORD IN DSKDIR + JRST .+3 ;MATCHES OR PDTIME NOT AVAILABLE + MOVEM T,MPDOFF(A) ;NO MATCH, CORRECT THE DSKDIR ONE + IORM B,QMDRO ;SET DIRECTORY CHANGED BIT + SKIPE T,FYEAR ;NOW DO THE SAME FOR THE YEAR, + CAMN T,MDYEAR(A) ;AND THE RELEVANT WORD IN DSKDIR + JRST .+3 + MOVEM T,MDYEAR(A) + IORM B,QMDRO + JRST UTCONJ ;THAT'S ALL + +CLCQDT: PUSHJ P,RDATE1 ;GET DAY OF MONTH IN C, MONTH IN B + SETZM QDATE ;INITIALIZE FOR FOLLOWING + PUSH P,E-1 + PUSH P,E + MOVE E-1,FYEAR + IDIVI E-1,100. + DPB E,[330700,,QDATE] ;YEAR + POP P,E + POP P,E-1 + DPB B,[270400,,QDATE] ;MONTH + DPB C,[220500,,QDATE] ;DAY + MOVE C,QDATE ;THE FIRST TIME QDATE IS SET UP, + HRR C,TIMOFF ;SET UP QDATEI = TIME SYSTEM CAME UP. + SKIPGE QDATEI + MOVEM C,QDATEI ;MECHANISM IS, SET QDATEI UNLESS ALREADY SET. + POPJ P, diff --git a/src/system/tm03s.defs4 b/src/system/tm03s.defs4 new file mode 100755 index 00000000..172054fe --- /dev/null +++ b/src/system/tm03s.defs4 @@ -0,0 +1,151 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + + +;;; RH11/TM03 Interrupt vector: +DEFSYM %TMVEC==224 ;(224/4 = 45) Interrupts occur on level 6 + ; (high priority) on UBA #1. +DEFSYM %TMBAS==772400 ;Unibus address of first register + +;;; RH11/TM03 Unibus register addresses: + +DEFSYM %TMCS1=:%TMBAS ;CONTROL AND STATUS 1 + DEFSYM %TM1SC==1_15. ; Special Condition + DEFSYM %TM1TE==1_14. ; Transfer Error + DEFSYM %TM1MP==1_13. ; Massbus Control Bus Parity Error + DEFSYM %TM1DA==1_11. ; Drive Available + DEFSYM %TM1A7==1_9. ; UB Address Extension Bit 17 + DEFSYM %TM1A6==1_8. ; UB Address Extension Bit 16 + DEFSYM %TM1RY==1_7. ; Ready + DEFSYM %TM1IE==1_6. ; Interrupt Enable + DEFSYM $TM1CM==.BP 77 ; Bits 0-5 specify commands. + DEFSYM %TM1GO==1_0. ; GO bit + +;;; Commands with bit 0 (GO) included: + +DEFSYM %TMNOP==1 ;No Operation +DEFSYM %TMUNL==3 ;Unload +DEFSYM %TMREW==7 ;Rewind +DEFSYM %TMCLR==11 ;Formatter clear (reset errors etc.) +DEFSYM %TMER3==25 ;Erase three inch gap +DEFSYM %TMWTM==27 ;Write Tape Mark +DEFSYM %TMSPF==31 ;Space Forward +DEFSYM %TMSPR==33 ;Space Reverse +DEFSYM %TMWCF==51 ;Write Check FOrward +DEFSYM %TMWCR==57 ;Write Check Reverse +DEFSYM %TMWRT==61 ;Write Forward +DEFSYM %TMRDF==71 ;Read Forward +DEFSYM %TMRDR==77 ;Read Data Reverse + +DEFSYM %TMWC=:%TMBAS+2 ;WORD COUNT. + +DEFSYM %TMBA=:%TMBAS+4 ;UNIBUS ADDRESS. + +DEFSYM %TMFC=:%TMBAS+6 ;TAPE FRAME COUNT + +DEFSYM %TMCS2=:%TMBAS+10 ;CONTROL AND STATUS 2. + DEFSYM %TM2DL==1_15. ; Data Late + DEFSYM %TM2UP==1_13. ; Unibus Parity Error + DEFSYM %TM2NF==1_12. ; Non-existant Formatter + DEFSYM %TM2NM==1_11. ; %TMBA is NXM during DMA + DEFSYM %TM2PE==1_10. ; Program Error + DEFSYM %TM2MT==1_9. ; Missed Transfer + DEFSYM %TM2MP==1_8. ; Massbus Data Bus Parity Error + DEFSYM %TM2OR==1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %TM2IR==1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %TM2CC==1_5. ; Controller Clear + DEFSYM %TM2PT==1_4. ; Parity Test + DEFSYM %TM2AI==1_3. ; Unibus Address Increment Inhibit + +DEFSYM %TMFS=:%TMBAS+12 ;FORMATTER STATUS + DEFSYM %TMSAA==1_15. ; Attention Active + DEFSYM %TMSES==1_14. ; Error Summary + DEFSYM %TMSPP==1_13. ; Positioning in Progress + DEFSYM %TMSOL==1_12. ; Medium On-Line + DEFSYM %TMSWL==1_11. ; Write Locked + DEFSYM %TMSET==1_10. ; End of Tape + DEFSYM %TMSFP==1_8. ; Formatter Present + DEFSYM %TMSFR==1_7. ; Formatter Ready + DEFSYM %TMSSC==1_6 ; Slave Status Change + DEFSYM %TMSPE==1_5. ; Phase Encoded (1600BPI) Mode + DEFSYM %TMSSD==1_4. ; Slowing Down + DEFSYM %TMSIB==1_3. ; PE Identification Burst Detected + DEFSYM %TMSTM==1_2. ; Tape Mark detected + DEFSYM %TMSBT==1_1. ; Beginning of Tape + DEFSYM %TMSSA==1_0. ; Slave Attention (on-line) + +DEFSYM %TMERR=:%TMBAS+14 ;ERROR REGISTER + DEFSYM %TMECE==1_15. ; Correctable Data/CRC Error + DEFSYM %TMEUS==1_14. ; Unsafe + DEFSYM %TMEOI==1_13. ; Operation Incomplete + DEFSYM %TMECT==1_12. ; Controller Timing Error + DEFSYM %TMENX==1_11. ; Non Executable Function + DEFSYM %TMECS==1_10. ; Correctable Skew/Illegal Tape Mark Error + DEFSYM %TMEFC==1_9. ; Frame Count Error + DEFSYM %TMENG==1_8. ; Non-standard Gap + DEFSYM %TMEFL==1_7. ; PE Format/LRC Error + DEFSYM %TMEIC==1_6. ; Incorrectable Data/Hard Error + DEFSYM %TMEMD==1_5. ; Massbus Data Parity Error + DEFSYM %TMEFS==1_4. ; Format Select Error + DEFSYM %TMEMC==1_3. ; Massbus Control Parity Error + DEFSYM %TMERM==1_2. ; Register Modification Refused + DEFSYM %TMEIR==1_1. ; Illegal Register + DEFSYM %TMEIF==1_0. ; Illegal Function + DEFSYM %TMEHD==44077 ; Hard errors - US,NX,MD,FS,MC,RM,IR,IF + +DEFSYM %TMASN=:%TMBAS+16 ;ATTENTION SUMMARY. + ;Each bit 7-0 corresponds to a formatter asserting ATA. + +DEFSYM %TMCCR=:%TMBAS+20 ;CHECK CHARACTER REGISTER + DEFSYM %TMCDP==1_8. ; Dead Track Parity/CRC Parity + DEFSYM $TMCEI==.BP 177 ; Error Information + +DEFSYM %TMBUF=:%TMBAS+22 ;DATA BUFFER REGISTER + +DEFSYM %TMMNT=:%TMBAS+24 ;MAINTENANCE. + +DEFSYM %TMTYP=:%TMBAS+26 ;DRIVE TYPE. + ;2.7 Not Sector addressed + ;2.6 Tape + ;2.5 Moving Head + ;2.3 Dual controller option available + ;1.9 - 1.1 Drive Type Number. + ; TU77=14, TU45=12, TE16=11 Nothing=10 + +DEFSYM %TMSER=:%TMBAS+30 ;SERIAL NUMBER + +DEFSYM %TMTC=:%TMBAS+32 ;TAPE CONTROL REGISTER + DEFSYM %TMTAC==1_15. ; Acceleration (not up to speed) + DEFSYM %TMTFC==1_14. ; Frame Count non-zero + DEFSYM %TMTSA==1_13. ; Slave Address (selected slave) Changed + DEFSYM %TMTEA==1_12. ; Enable Abort on data transfer error + DEFSYM %TMTDS==7_8. ; Density Select Field + DEFSYM $TMTDS==.BP %TMTDS + DEFSYM %TMD08==3 ; 800 BPI NRZI + DEFSYM %TMD16==4 ; 1600 BPI PE + DEFSYM %TMTFS==17_4. ; Format Select + DEFSYM $TMTFS==.BP %TMTFS + DEFSYM %TMFCD==0 ; PDP10 Core Dump + DEFSYM %TMFIC==3 ; Industry Compatible (32 bit mode) + DEFSYM %TMTEP==1_3. ; Even Parity + DEFSYM %TMTTS==7 ; Transport Select + DEFSYM $TMTTS==.BP %TMTTS + +IFN $$TEMP,EXPUNG DEFSYM + + diff --git a/src/system/tm78s.defs2 b/src/system/tm78s.defs2 new file mode 100755 index 00000000..5f02e013 --- /dev/null +++ b/src/system/tm78s.defs2 @@ -0,0 +1,178 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + + +;;; RH11/TM78 Interrupt vector: +DEFSYM %ARVEC==224 ;(224/4 = 45) Interrupts occur on level 6 + ; (high priority) on UBA #1. +DEFSYM %ARBAS==772400 ;Unibus address of first register + +;;; RH11/TM78 Unibus register addresses: + +DEFSYM %ARCS1==%ARBAS ;CONTROL AND STATUS 1 (RH11 and MB Reg 00) + DEFSYM %A1SC==1_15. ; Special Condition + DEFSYM %A1TE==1_14. ; Transfer Error + DEFSYM %A1MCP==1_13. ; Massbus Control Bus Parity Error + DEFSYM %A1DA==1_11. ; Drive (TM78) Available + DEFSYM %A1A7==1_9. ; UB Address Extension Bit 17 + DEFSYM %A1A6==1_8. ; UB Address Extension Bit 16 + DEFSYM %A1RDY==1_7. ; Ready + DEFSYM %A1IE==1_6. ; Interrupt Enable + DEFSYM %A1CMD==77 ; Bits 0-5 specify commands. + DEFSYM %A1GO==1_0. ; GO bit + +;;; Commands, with GO bit or'd in. +;;; --NOTE-- +;;; Commands are passed to the controller in two ways. Data transfer +;;; command get written into the CS1 register, as usual. Non-data-transfer +;;; commands are written to the %ARNDC register for the desired drive +;;; unit (see below). Non-data-transfer commands are marked with a '*'. + +DEFSYM %ACNOP==3 ;(*) No Operation +DEFSYM %ACUNL==5 ;(*) Unload +DEFSYM %ACREW==7 ;(*) Rewind +DEFSYM %ACSNS==11 ;(*) Sense (Get status from TM) +DEFSYM %ACDSE==13 ;(*) Data Security Erase! (Erase rest of tape) +DEFSYM %ACWPM==15 ;(*) Write Phase Encoded (1600bpi) Tape Mark +DEFSYM %ACWGM==17 ;(*) Write GCR (6250bpi Tape Mark +DEFSYM %ACSFR==21 ;(*) Space Forward Record +DEFSYM %ACSRR==23 ;(*) Space Reverse Record +DEFSYM %ACSFF==25 ;(*) Space Forward File +DEFSYM %ACSRF==27 ;(*) Space Reverse File +DEFSYM %ACSFE==31 ;(*) Space Forward Either (record or file) +DEFSYM %ACSRE==33 ;(*) Space Reverse Either +DEFSYM %ACE3P==35 ;(*) Erase Three-inch gap, set PE +DEFSYM %ACE3G==37 ;(*) Erase Three-inch gap, set GCR +DEFSYM %ACCFP==41 ;(*) Close File PE (write two marks, back one) +DEFSYM %ACCFG==43 ;(*) Close File GCR +DEFSYM %ACEOT==45 ;(*) Space to Logical EOT +DEFSYM %ACSFU==47 ;(*) Space forward usefully (to file or EOT) +DEFSYM %ACWCF==51 ;Write Check Forward +DEFSYM %ACWCR==57 ;Write Check Reverse +DEFSYM %ACWRP==61 ;Write Forward PE +DEFSYM %ACWRG==63 ;Write Forward GCR +DEFSYM %ACRDF==71 ;Read Forward +DEFSYM %ACRES==73 ;Read Extended Sense Information +DEFSYM %ACRDR==77 ;Read Data Reverse + + +DEFSYM %ARWC==%ARBAS+2 ;UNIBUS DMA WORD COUNT. (RH11) + ; Negative count of the number of PDP11 (18-bit) words to DMA + +DEFSYM %ARBA==%ARBAS+4 ;UNIBUS ADDRESS. (RH11) + ; Unibus address of start of DMA transfer + +DEFSYM %ARFC==%ARBAS+6 ;TAPE FRAME BYTE COUNT (MB Reg 05) + +DEFSYM %ARCS2==%ARBAS+10 ;CONTROL AND STATUS 2. (RH11) + DEFSYM %A2DL==1_15. ; Data Late + DEFSYM %A2UPE==1_13. ; Unibus Parity Error + DEFSYM %A2NF==1_12. ; Non-existant Formatter (TM78) + DEFSYM %A2NM==1_11. ; Unibus mem NXM during DMA + DEFSYM %A2PE==1_10. ; Program Error + DEFSYM %A2MT==1_9. ; Missed Transfer + DEFSYM %A2MDP==1_8. ; Massbus Data Bus Parity Error + DEFSYM %A2OR==1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %A2IR==1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %A2CC==1_5. ; Controller Clear + DEFSYM %A2PT==1_4. ; Parity Test + DEFSYM %A2UAI==1_3. ; Unibus Address Increment Inhibit + +DEFSYM %ARDER==%ARBAS+12 ;DATA TRANSFER ERROR REPORT (MB Reg 01) + DEFSYM %ADEIC==77 ; Interrupt Code + DEFSYM %ADEDP==1_8. ; DPR ??? + DEFSYM %ADEFC==77_10. ; Failure Code + +DEFSYM %ARDCA==%ARBAS+14 ;DATA COMMAND ARGUMENTS (MB Reg 02) + DEFSYM %ADACA==3 ; Command Address (TU78 unit number) + DEFSYM %ADARC==77_2. ; Record Count + DEFSYM %ADASC==17_8. ; Skip Count + DEFSYM %ADAFT==7_12. ; Format + DEFSYM %ADASR==1_15. ; Supress Repositioning on error + +DEFSYM %ARASN==%ARBAS+16 ;ATTENTION SUMMARY. (MB Reg 04) + ;Each bit 3-0 corresponds to a drive wanting attention + ; You must explicitly -RESET- an attention bit by writing a + ; one into it before the controller can interrupt you again. + +DEFSYM %ARDS==%ARBAS+20 ;DRIVE STATUS (MB Reg 07) + ;;; This register is valid only after a SENSE command + ;;; (or possibly an unsolicited ONLINE interrupt) + DEFSYM %ASRDY==1_15. ; Tape Ready + DEFSYM %ASPRE==1_14. ; Present (TM78 powered up) + DEFSYM %ASONL==1_13. ; Online + DEFSYM %ASREW==1_12. ; Tape Rewinding + DEFSYM %ASPE==1_11. ; Tape is Phase Encoded + DEFSYM %ASBOT==1_10. ; Tape at BOT + DEFSYM %ASEOT==1_9. ; Tape at EOT + DEFSYM %ASWPT==1_8. ; Tape is Write Protected + DEFSYM %ASUA==1_7. ; Unit Available + DEFSYM %ASUS==1_6. ; Unit is shared + DEFSYM %ASMMD==1_5. ; Unit is in Maintainance mode + DEFSYM %ASDSE==1_4. ; Data Security Erase in progress. + +DEFSYM %ARBUF==%ARBAS+22 ;DATA BUFFER REGISTER (RH11) + +DEFSYM %ARMR1==%ARBAS+24 ;MAINTENANCE REGISTER 1 (MB Reg 03) + +DEFSYM %ARTYP==%ARBAS+26 ;DRIVE TYPE. (MB Reg 06) + ;;; This register is valid only after a SENSE command + ;2.7 Not Sector addressed + ;2.6 Tape + ;2.5 Moving Head (always 0) + ;2.4 7 track (always 0) + ;2.3 Dual port (must do arbitration) + ;2.2 Slave present (always 1) + ;2.1 Writable Control Store (always 0) + ;1.9 - 1.1 Drive Type Number. + ; TU78=101 + +DEFSYM %ARSER==%ARBAS+30 ;SERIAL NUMBER (MB Reg 010) + ;;; This register is valid only after a SENSE command + ;0-3 SN digit 0, in BCD + ;4-7 SN digit 1 + ;8-11 SN digit 2 + ;12-15 SN digit 3 + +DEFSYM %ARMR2==%ARBAS+32 ;MAINTAINANCE REGISTER 2 (MB Reg 011) + +DEFSYM %ARMR3==%ARBAS+34 ;MAINTAINANCE REGISTER 3 (MB Reg 012) + +DEFSYM %ARNDE==%ARBAS+36 ;NON-DATA CMD ERROR REGISTER (MB Reg 013) + DEFSYM %ANEIC==77 ; NDT Interrupt code + DEFSYM %ANEAA==3_8. ; Attention Address (drive that caused this) + DEFSYM %ANEFC==77_10. ; NDT Failure Code + +DEFSYM %ARNDA==%ARBAS+40 ;NON-DATA CMD ARG REGISTERS (MB Reg 014 - 017) + ;;; There are four of these, one for each of the possible slave TU78 + ;;; units on the TM78. This is where you write commands that don't + ;;; move data over the massbus. + DEFSYM %ANCMD==77 ; Command to execute + DEFSYM %ANCNT==377_8. ; Count + +DEFSYM %ARIA==%ARBAS+50 ;INTERNAL ADDRESS (MB Reg 020) + +DEFSYM %ARID==%ARBAS+52 ;HARDWARE CONTROL (MB Reg 021) + DEFSYM %AHRDY==1_15. ; Set when controller is ready. (read only) + DEFSYM %AHCLR==1_14. ; Write 1 here to reset controller. + ;;; And a bunch of other stuff + + +IFN $$TEMP,EXPUNG DEFSYM + + diff --git a/src/system/ts3tty.400 b/src/system/ts3tty.400 new file mode 100755 index 00000000..be6f862e --- /dev/null +++ b/src/system/ts3tty.400 @@ -0,0 +1,8214 @@ +;-*-MIDAS-*- + +TTYVRS==.IFNM2 + +OVHMTR TTY ;MISC TTY CODE + +SUBTTL SPY DEVICE + +;FIRST FILE NAME MUST BE TTY NUMBER (NOT CHARACTERS) + +SPYO: JUMPN D,OPNL12 ;ONLY UNIT ASCII INPUT ALLOWED + JUMPL A,OPNL11 + CAIL A,NCT + JRST OPNL11 + MOVE E,TIIP(A) + MOVEM E,IOCHST-IOCHNM(R) + MOVEI C,ISPY + HRL C,A + MOVEM C,(R) + JRST POPJ1 + +;A HAS LH OF IOCHNM =TTY # + +SPYI: MOVE T,IOCHST-IOCHNM(R) ;POINTER TO INPUT BUFFER + HRRZ B,TIBEP(A) + CAIL B,(T) + CAILE B,TIBL(T) + JRST SPYIL +SPYILL: CAMN T,TIIP(A) + PUSHJ P,UFLS + CAMN T,TIBEP(A) + SUBI T,TIBL + HRRM T,IOCHST-IOCHNM(R) + ILDB W,IOCHST-IOCHNM(R) + POPJ P, + +SPYIL: MOVE T,TIIP(A) + MOVEM T,IOCHST-IOCHNM(R) + JRST SPYILL + +;.CALL RFNAME on a SPY channel. A contains LH(IOCHNM) = TTY # +SPYRCH: MOVEI B,(A) ;FN1 is TTY # + POPJ P, ;easy! + +SUBTTL STY DEVICE + +;STY OPEN + +;MODE BITS (LH) +;3.1=0 => INPUT =1 => OUTPUT (FROM PROGRAM POINT OF VIEW) +;3.2=0 => UNIT =1 => BLOCK +;INPUT +;3.3=0 => FULL DUPLEX =1 => HALF DUPLEX +;3.4=1 => DON'T HANG ON INPUT IOTS, INPUT -1 INSTEAD (IGNORED ON OUTPUT OPEN) +;3.5=1 => WANT TO GET %TDORS ON OUTPUT RESET. + ;BIT 3.5 NOTICED ON OUTPUT, TOO, BUT THAT'S NO FEATURE? + +STTYO: HRRZ I,USTYN(U) + JUMPN I,STTYO3 ;JUMP IF STY ALREADY OPEN + PUSHJ P,SWTL ;LOCK STY OPEN SWITCH + STYOSW + MOVE I,[-NSTTYS,,NFSTTY] + MOVSI TT,%SSUSE +STTYO1: TDNE TT,STYSTS-NFSTTY(I) ;SKIP ON FREE SLOT +STTYO5: AOBJN I,STTYO1 + JUMPGE I,OPNL6 ;NO SLOTS. GIVE DEVICE FULL + SKIPGE TTYSTA(I) ;SKIP IF CONSOLE FREE MSG NOT TYPED. + SKIPE TTNTO(I) ;SKIP IF NOT OPEN. + JRST STTYO5 + MOVEI I,(I) ;We want to compare left half + CAMLE I,STYMAX ;If we're limiting STY's, is this over our + JRST OPNL6 ; limit? If so, give DEVICE FULL + HRRM I,USTYN(U) ;STORE TTY NUMBER OF STY +STTYO4: ANDI I,-1 + SETZM STYNTO-NFSTTY(I) + SETZM STYMSK-NFSTTY(I) + MOVSI TT,%SSUSE + MOVEM TT,STYSTS-NFSTTY(I) ;SET IN USE BIT + MOVSI TT,(<.BM ($TTISP)>+<.BM ($TTOSP)>) + ANDCAM TT,TTYTYP(I) ;RESET SPEEDS TO ZERO + PUSH P,C + PUSHJ P,NCNSSP ;MAKE THE TTY A PRINTING TTY. + PUSHJ P,TTYIN1 ;INIT THE TTYOPT AND TTYCOM USER OPTION BITS. + PUSHJ P,STYIR1 ;FLUSH TTY'S OUTPUT BUFFER. + PUSHJ P,STYOR1 ;AND ITS INPUT BUFFER. + PUSHJ P,LSWPOP ;UNLOCK STY OPEN SWITCH + POP P,C + HRRM U,STYSTS-NFSTTY(I) + MOVE T,UTMPTR(U) ;Check out this tree + CAIE T,SYSRCE-1 ;Is this a top-level non-console tree, + CAIN T,SYSRCE ;or a system demon? + JRST STTYO3 ; Yes, don't print on console. + ; since TELSER, etc., logs in + MOVEI T,(I) ;Get TTY number + HRLI T,[ASCIZ / STYOPN /] + PUSHJ P,SGWAIT ;Ask SYSJOB to print the info + MOVE T,JNAME(U) ;Add the JNAME to the info + MOVEM T,SLGIV+2 ;to be printed + +STTYO3: JUMPL D,[MOVSI TT,%SSOHG ;JUMP IF OPENING FOR OUTPUT + JRST STTYO2] + LDB TT,[240100,,C] + DPB TT,[400100,,STYSTS-NFSTTY(I)] .SEE %SSHDX + DPB TT,[$TOHDX,,TTYOPT(I)] + MOVSI TT,%SSHNG +STTYO2: TLNE C,10 + IORM TT,STYSTS-NFSTTY(I) + MOVSI TT,%SSORS + TLNE C,20 + IORM TT,STYSTS-NFSTTY(I) + MOVE J,R + SUBI J,IOCHNM(U) ;CHANNEL BEING OPENED FOR INPUT ON + MOVE J,CHNBIT(J) + SKIPL D ;SKIP IF OUTPUT + IORM J,STYMSK-NFSTTY(I) + SKIPGE D ;SKIP IF INPUT + IORM J,STYOMS-NFSTTY(I) + AOS STYNTO-NFSTTY(I) + HRLZ A,I ;LH OF IOCHNM GETS STY NUMBER + MOVSS C + JSP Q,OPSLC3 + STYDUI,,STYDUO + STYDBI,,STYDBO + + +;ENTRY FOR OPEN OF PSEUDO-TTY AS SNM OR STN +STTYOA: JUMPL I,OPNL1 + CAIL I,NSTTYS + JRST OPNL1 + ADDI I,NFSTTY + PUSHJ P,SWTL + STYOSW + MOVE TT,STYSTS-NFSTTY(I) ;SKIP IF IN USE + TLNN TT,%SSUSE + JRST STTYO4 ;OK TO OPEN IF FREE + CAIE U,(TT) + JRST OPNL10 ;DIFFERENT USER HAS IT OPEN + PUSHJ P,LSWPOP + JRST STTYO3 + + JRST STTS ;STY INPUT SIOT ROUTINE. +;PSEUDO-TTY INPUT ROUTINE. RETURNS CHAR WITHOUT PARITY BIT +STTYI: MOVE I,A +STTYIA: SKIPGE TTYOAC(I) ;SKIP IF ANY CHARS AVAIL (MAYBE) + JRST STTYI1 +STTYI4: PUSH P,C + PUSH P,E + CONO PI,TTYOFF + PUSHJ P,TYPSC + POP P,E + POP P,C + MOVE U,USER + MOVE W,STYICH + SKIPGE DBBBP + JRST STTYI2 ;REALLY NO CHARS AVAIL + CONO PI,TTYON + MOVSI R,%SSONT ;FOR TTYO INT TO STYI + JRST STTYIC ;INT CLEAR + +STTYI2: CONO PI,TTYON +STTYI1: SKIPGE STYSTS-NFSTTY(I) + JRST STTYI3 ;DON'T HANG + SKIPGE TTYOAC(I) + PUSHJ P,UFLS + JRST STTYIA + +STTYI3: MOVNI W,1 + TLO E,100000 .SEE INBTCH ;UNHANG BLOCK MD IOT IMMEDIATELY. + JRST POPJ1 ;UNHANG SIOT IMMEDIATELY. + +;STY INPUT SIOT; GOES 1 WORD AT A TIME, WHATEVER THE USER'S BYTE SIZE. +STTS: XCTR XRW,[SKIPG E,(C)] + JRST POPJ1 ;RETURN AT ONCE IF NO CHARS WANTED BY USER. + PUSH P,B ;SAVE ADDRS OF USER'S B.P. AND COUNT. + PUSH P,C +STTSA: SKIPGE TTYOAC(I) + JRST STTS4 ;NO INPUT AVAILABLE. +STTS2: UMOVE B,@-1(P) +STTS1: XCTR XRW,[MOVES D,(B)] +;IT IS ASSUMED THAT E HAS THE # OF CHARS THE USER WANTS. + CONO PI,TTYOFF + MOVEM D,STYICH ;STORE THE WORD THE USER'S B.P. POINTS AT. + LDB C,[360600,,B] + LDB D,[300600,,B] + IDIV C,D ;HOW MANY MORE CHARS GO IN THIS WORD? + JUMPE C,STTS7 + PUSH P,B ;SAVE STARTING B.P. AND # CHARS FITTING IN WORD. + HRRI B,STYICH ;SET UP TO STORE CHARS AT APPRO. PLACE IN STYICH. + MOVEM B,DBBBP + CAML C,E + MOVE C,E ;GET MIN OF # CAHRS FITTING IN WORD AND # CHARS USER WANTS. + MOVEM C,DBBCC ;THAT'S HOW MANY CHARS WE CAN ACCEPT THIS TIME. + MOVEM C,DBBCC1 + PUSHJ P,TYP ;FILL UP STYICH WITH CHARS, VIA DBBBP. + POP P,B ;NOTE E HAS -<# CHARS GOBBLED> + MOVE D,STYICH ;GET USER'S WORD, WITH CHARS STUCK IN IT. + UMOVEM D,(B) ;STORE IT WHERE IT CAME FROM. + XCTR XRW,[ADDB E,@(P)] ;UPDATE COUNT BY -<# CHARS OBTAINED>. + HLL B,DBBBP ;UPDATE B.P. TO THE L.H. CORRESP. TO CHARS STORED IN STYICH. + UMOVEM B,@-1(P) + SKIPE DBBCC ;DID WE GET AS MANY CHARS AS WE WANTED? + JRST STTS3 ;NO, SO EITHER RETURN OR HANG UP. + CONO PI,TTYON + JUMPG E,STTS7 ;USER WANTS MORE CHARS => TRANSFER ANOTHER WORD. +STTS5: MOVE U,USER + MOVSI R,%SSONT + SUB P,[2,,2] + AOS (P) + JRST STTYIC + +;COME HERE DURING STY INPUT SIOT IF USER WANTS CHARS BUT THERE ARE NONE. +STTS3: CONO PI,TTYON +STTS4: SKIPGE STYSTS-NFSTTY(I) + JRST STTS5 ;DON'T HANG MODE. + SKIPGE TTYOAC(I) + PUSHJ P,UFLS + JRST STTSA + +STTS7: AOS B +STTS6: TLZ B,770000 + TLO B,440000 + JRST STTS1 + +;PSEUDO-TTY OUTPUT +STTYW: MOVE I,A + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +BSTTYW: MOVSI T,%SSOHG ;BIT ON SAYS DONT HANG + TDNE T,STYSTS-NFSTTY(I) + JRST BSTTYX ;J TO NOT HANG. CHARS MAY BE LOST + MOVEI T,TIBS + CAMG T,TICC(I) + PUSHJ P,UFLS ;HANG UNTIL ROOM IN INPUT BUFFER +BSTTYX: CONO PI,TTYOFF + PUSH P,I + PUSHJ P,NTYI5 + POP P,I + MOVE U,USER + MOVSI R,%SSINT +STTYIC: ANDCAM R,STYSTS-NFSTTY(I) ;CALLED BY STTYI ABOVE ALSO + HRRZ R,UUAC(U) + MOVE R,CHNBIT(R) + ANDCAM R,IFPIR(U) ;FLUSH ANY OUTPUT INTERRUPT + CONO PI,TTYON + POPJ P, + +STTBI: JSP E,INBTCH + JRST STTYI + +STTBO: JSP E,NBTOCH + CAIN A,EOFCH + POPJ P, + HLRZ I,(R) + PUSH P,R + PUSH P,D + PUSH P,TT + PUSH P,E + PUSH P,C + PUSHJ P,BSTTYW + POP P,C + POP P,E + POP P,TT + POP P,D + POP P,R + POPJ P, + +;STY OUTPUT CLOSE. +STYOCL: SUBI R,IOCHNM(U) + MOVE B,CHNBIT(R) + ANDCAM B,STYOMS-NFSTTY(A) + JRST STYCL + +;STY INPUT CLOSE +STYICL: SUBI R,IOCHNM(U) + MOVE B,CHNBIT(R) + ANDCAM B,STYMSK-NFSTTY(A) +STYCL: SOSE STYNTO-NFSTTY(A) + POPJ P, +STYCL1: PUSHJ P,TTYLFC ;LEAVE COM. MODE, PUT TTY # IN I. +IFN NETP,[ + PUSHJ P,NSTYN0 ;DISCONNECT ANY NET SOCKETS FROM THE STY + JFCL +] + CONO PI,TTYON#200_<-APRCHN> ;LEAVE CLOCK OFF. + SKIPGE C,TTYSTS(I) + JRST STYOC8 ;TTY NOT IN USE. + TLNN C,%TSCNS + JRST STYOC9 ;OPEN AS DEVICE, NOT AS CONSOLE. + PUSH P,U +STYOC3: HRRZ U,C + SKIPL C,SUPPRO(U) + JRST STYOC3 ;NOT TOP LEVEL + MOVE C,USER +STYC4A: HRRZ TT,C + SKIPL C,SUPPRO(TT) + JRST STYC4A + AOS STYNTO-NFSTTY(I) ;IN CASE WE PCLSR, PREVENT JRST 4,. + PUSH P,I + CAME U,USER ;DON'T GET INTO LOOP AT ALOGO1 + PUSHJ P,ALOGOUT ;TELL SYS JOB TO FLUSH THE TREE UNDER THE STY. + POP P,I + POP P,U + SOS STYNTO-NFSTTY(I) +STYOC5: PUSHJ P,STYIR1 ;FLUSH TTY OUTPUT BUFFER. +STYOC9: SETZM STYSTS-NFSTTY(I) + CAIN I,@USTYN(U) ;IF HE'S CLOSING HIS STY:, SAY HE HAS NONE. + HLLZS USTYN(U) + JRST CLKONJ + +STYOC8: SKIPGE TTYSTA(I) ;IN TRANSIENT STATE BETWEEN USAGE AND NOT? + JRST STYOC5 ;NO, REALLY FREE, SIMPLE. + CONO PI,CLKON + AOS STYNTO-NFSTTY(I) + MOVE T,I + PUSHJ P,STYOCF + PUSHJ P,UFLS + MOVE A,I + JRST STYCL + +STYOCF: SKIPGE TTYSTS(T) ;IF NOW IN USE + SKIPGE TTYSTA(T) ;OR COMPLETELY FREE, + AOS (P) ;THEN NO LONGER IN TRANSIENT STATE. + POPJ P, + +;STY OUTPUT .CALL FINISH +STYFIN: SKIPE TICC(A) ;WAIT UNTIL CORRESPONDING INPUT BUFFER IS EMPTY + PUSHJ P,UFLS + JRST POPJ1 + +;STY OUTPUT .CALL WHYINT +STOWHY: MOVEI A,%WYSTO ;NULL ROUTINE FOR NOW + JRST POPJ1 + +;STY INPUT .CALL WHYINT +STIWHY: MOVEI A,%WYSTI ;NULL ROUTINE FOR NOW + JRST POPJ1 + +;STY INPUT RESET. DOES TTY OUTPUT RESET, WITH THE TTY'S OWNER STOPPED. +STYIRS: HLRZ I,(R) +STYIR1: CONO PI,TTYOFF + SKIPGE B,TTYSTS(I) + JRST STYIR2 ;TTY IS FREE => NO PROBLEM. + HRRZ A,B + PUSHJ P,RPCLSR ;ELSE MUST MAKE SURE ITS OWNER ISN'T TYPING OUT. + CONO PI,TTYOFF + XOR B,TTYSTS(I) ;WE MIGHT HAVE BEEN DELAYED - HAS TTY MOVED AROUND? + TRNN B,-1 + JRST STYIR4 ;NO; THE GUY WAS STOPPED WHILE STILL ITS OWNER. + PUSHJ P,UPCLSR ;YES; UNSTOP GUY WE STOPPED, + JRST STYIR1 ;THEN GO STOP THE NEW OWNER. + +STYIR4: PUSH P,A ;SAVE JOB STOPPED + PUSHJ P,STYIR2 ;ACTUALLY DO THE RESET OF TTY OUTPUT + POP P,A + JRST UPCLSR ;THEN UNSTOP THE TTY'S OWNER + +STYIR2: SETOM TTYOAC(I) ;WE WILL NO LONGER BE LOOKING FOR TTY'S OUTPUT. + JRST TYORS1 ;DO THE TTY OUTPUT RESET AND TURN ON PI CHANNELS. + +;STY OUTPUT RESET. +STYORS: HLRZ I,(R) +STYOR1: CONO PI,TTYOFF + PUSHJ P,TYIRS1 ;TURNS INTO TTY INPUT RESET. + JRST TTYONJ + +;STY OUTPUT STATUS - BIT 2.1 => BUFFER FULL, 2.2 => EMPTY. +STASTO: ANDI A,77 + SKIPN B,TICC(A) + IORI D,1_<9+1> ;BUFFER EMPTY. + CAIL B,TIBS-10. + IORI D,1_9 ;ALMOST FULL. + POPJ P, + +;STY INPUT STATUS - THE SAME 2 BITS. +STASTI: ANDI A,77 + SKIPG B,TORM(A) + IORI D,1_9 ;FULL. + CAIN B,TOBS + IORI D,1_<9+1> ;EMPTY. + POPJ P, + +;"STYGET" SYSTEM CALL. 1 ARG, A TTY SPECIFYER. +;1ST VALUE IS STYSTS WORD (RH IS JOB NUMBER OF OWNER OF STY). 0 FOR FREE STY. +; %SSHNG AND %SSOHG BITS MAY BE INTERESTING. +;2ND VALUE IS JOB THAT OWNS CORRESP. TTY (OR -1 IF TTY FREE). +;3RD VALUE IS -1 IF TTY NOT CONSOLE; ELSE JOB NUMBER OF TOP OF TREE IN RH +; AND BIT 4.8 SET IFF IT IS LOGGING OUT. +; AND BIT 4.7 SET IF IT IS LOGGED IN. +;4TH VALUE BITS ARE: +; 1 IF TTY OWNER IS IN TYO WAIT +; SIGN IF HE'S IN TYI WAIT. +;5TH VALUE BITS ARE: +; 4.9 => TTY INPUT AVAILABLE +; 4.8 => TTY OUTPUT BUFFER HAS ROOM +;6TH VALUE IS TTYSTA WORD + +NSTYGT: JSP J,ATTYCI ;DECODE A TTY-SPECIFYER IN A. + CONO PI,CLKOFF + SETZ A, + MOVE TT,TTYTYP(I) + TRNN TT,%TYSTY ;IF SPEC'D TTY ISN'T ASSOCIATED WITH A STY, IT HAS NO STYSTS WORD. + JRST NSTYG3 + HRRZ A,STYSTS-NFSTTY(I) + IDIVI A,LUBLK ;NUMBER OF JOB USING THE STY. + HLL A,STYSTS-NFSTTY(I) ;AND SOME RANDOM BITS. +NSTYG3: SETOB B,C ;B GETS # OF JOB THAT HAS TTY, OR -1. + ;C GETS (IF TTY IS CONSOLE, JOB # OF TOP OF TRREE, ELSE -1). + SETZB D,E ;D, E SHOULD GET 0 IF NO JOB HAS TTY. + HRRE B,TTYSTS(I) + JUMPL B,NSTYG1 ;JUMP IF CONSOLE NOT IN USE. + IDIVI B,LUBLK ;ELSE GET JOB NUMBER OF JOB USING IT. + MOVE D,TTYSTS(I) + TLNN D,%TSCNS ;TTY NOT CONSOLE => DON'T REPLACE THE -1 IN C WITH ANYTHING. + JRST NSTYG2 + HRRZ C,TTYSTS(I) + SKIPL D,SUPPRO(C) ;ELSE TRACE SUPPRO'S TO TOP OF TREE. + JRST [ HRRZ C,D + JRST .-1] + MOVE TT,APRC(C) + HLRE W,UNAME(C) + IDIVI C,LUBLK ;GET JOB # OF TOP OF TREE. + TLNE TT,BULGOS + TLO C,200000 + AOSE W + TLO C,100000 +NSTYG2: SETZ D, + MOVE TT,TTYSTS(I) + HRRZ TT,FLSINS(TT) ;WHAT VARIABLE IS FLSINS OF JOB OWNING TTY WAITING ON? + CAIE TT,TICC(I) ;RETURN IN D SETZ IFF JOB IS IN TYI WAIT, + CAIN TT,TACC(I) + MOVSI D,(SETZ) + CAIN TT,TORM(I) + MOVEI D,1 ;OR 1 IF JOB IS IN TYO WAIT; ELSE 0. +NSTYG1: SKIPE TICC(I) + TLO E,400000 + MOVE TT,TORM(I) + CAIL TT,TYOWNC + TLO E,200000 + MOVE TT,TTYSTA(I) + CONO PI,CLKON + JRST POPJ1 + +;.CALL STLGET - GET INFO FROM SERVER TELNET + +; Arg 1: a TTY +; Val 1: XJNAME of server telnet +; Val 2: TRMNAM of server telnet (has sixbit name of host) +; Val 3: SNAME of server telnet +; Val 4: STY control bits,,STY owner idx + +NSTLGT: JSP J,ATTYCI + SETZB A,B + SETZB C,D + MOVE TT,TTYTYP(I) + TRNN TT,%TYSTY + JRST OPNL34 + SKIPN T,STYSTS-NFSTTY(I) ;Get STY status bits,,STY user. + JRST POPJ1 + MOVE A,XJNAME(T) + MOVE B,TRMNAM(T) + MOVE C,USYSNM(T) + HRRZ D,T + IDIVI D,LUBLK ;Make it into user index. + HLL D,T ;Stuff STY status bits in LH. + JRST POPJ1 + + +SUBTTL .ATTY, .DTTY - PASS CONTROL OF TTY + +NATTY: MOVE J,A ;.CALL ATTY + JSP T,NCRUI2 ;DECODE JOBSPEC BUT DON'T SET DIELOK + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;SORRY, I/O BUS MPXR IS NOT THAT HAIRY +] + HRRZ B,SUPPRO(J) + CAME B,U + JRST OPNL31 ;NOT DIRECT INFERIOR (CAN'T MODIFY JOB) + MOVE A,J + JRST NATTY1 + +; .ATTY USR, OPER 11 + +AATTY: HLRZ A,(R) ;A HAS INFERIOR'S USER INDEX + HRRZ B,(R) + SKIPL CLSTB(B) .SEE %CLSU ;SKIP IF USER OPEN ON CHANNEL + JRST OPNL34 +NATTY1: MOVE TT,APRC(A) + TLNE TT,BULGOS ;REFUSE TO GIVE TTY TO A DYING JOB. + JRST OPNL42 ;JOB GOING AWAY + CONO PI,CLKOFF + MOVE I,TTYTBL(U) + JUMPL I,AATT1 ;DOESNT HAVE TTY NOW + HLLZS TTYTBL(U) + HRLI A,%TBNOT + IORM A,TTYTBL(U) ;NO LONGER HAS TTY. STORE USER INDEX GIVEN TO + PUSHJ P,AATT6 ;A _ IDX OF USER TO RECEIVE TTY, + ;ALSO CHANGE ALL TTYTBL VARS THAT NEED IT. + EXCH A,U + PUSHJ P,AGBLT6 ;TAKE TTY FROM USER IN A (ME), + ;GIVE TO USER IN U (HIM) + ;CHANGES TTY VARS AND TTSTSV VARS. + ;ALSO SETS CHANNELS-OPEN MASKS. + ;TURNS ON ALL PI CHNLS. + EXCH A,U + JRST POPJ1 + +AATT1: TLZN I,%TBDTY ;SAY OUR INFERIOR HAD IT WHEN TAKEN + JRST OPNL10 ;DEVICE NOT AVAILABLE, ALREADY GAVE TTY AWAY + HRRI I,(A) + MOVEM I,TTYTBL(U) + PUSHJ P,AATT6 ;SET UP HIS VARS + JRST CLKOJ1 + +;CHANGE TTYTBL VARS OF ALL JOBS DOWN TO THE ONE GETTING THE TTY. +;RETURN IN A, T, TT THE TTYSTS, TTYST1, TTYST2 SETTINGS FOR THAT JOB. +;IF THAT JOB NEVER HAD THE TTY, INIT HIS TTSTSV VARS. +;I HAS TTY #, U HAS RUNNING JOB. +AATT6: MOVE E,TTYTBL(A) + MOVSI T,%TSATY ;TELL THIS GUY TTY WAS TAKEN FROM HIM & RETURNED. + IORM T,TTSTSV+2(A) + TLNE E,%TBDTY ;SKIP IF NOT TAKEN FROM ME + JRST AATT3 ;GUY IT WAS TAKEN FROM (I.E. HE HADN'T GIVEN IT TO SOMEONE ELSE) + HRRZ A,TTYTBL(A) + JRST AATT6 + +AATT3: HRRZS I ;TTY NUMBER + HLL A,TTSTSV+2(A) + TLZ A,%TSFRE+%TSLCZ ;CLEAR TTY NOT OPEN AND ^Z BITS + MOVEM A,TTSTSV+2(A) ;UPDATE SAVED TTY STATUS + POPJ P, + +;SET UP TYIMSK AND TYOMSK. ARGS: TTY # IN I, +;D -> 1ST IOCHNM WORD OF USER TO SET UP FOR. +;MAKE LAST CHAR IN INPUT BFR AN ACTIVATION CHAR. TURN ON TTYCHN. +AATT8: SETZM TYOMSK(I) + SETZM TYIMSK(I) + CONO PI,TTYOFF + HRLI D,A ;INDIRECTION POINTER TO INFERIOR'S IO CHANNELS + MOVSI A,-20 ;AOBJN POINTER +AATT9: MOVE B,@D ;GET IOCHNM IN B + JUMPGE B,AATT10 ;IF CHANNEL HAS CONSOLE BIT SET, + ANDI B,-1 + MOVE C,CHNBIT(A) ;GET THE BIT WE MIGHT WANT TO SET. + CAIE B,TYODN + CAIN B,TYOBN ;IF TTY OUTPUT CHNL, + IORM C,TYOMSK(I) ;SET BIT IN OUTPUT MASK. + CAIE B,TYIDN + CAIN B,TYIBN ;IF INPUT, SET IN INPUT MASK. + IORM C,TYIMSK(I) +AATT10: AOBJN A,AATT9 ;TRY NEXT CHANNEL OR CONTINUE IF DONE + JRST ATTYS1 ;ALL CHRS SO FAR ARE ACTIVATION CHRS + +ADTTY: ;DON'T CLOBBER R (SEE AUCL2) +SDTTY: CONO PI,CLKOFF + MOVE A,TTYTBL(U) + JUMPGE A,CLKOJ1 ;I ALREADY HAVE IT + TLNE A,%TBDTY + JRST CLKOJ1 ;I ALREADY DID A .DTTY AND SO DID MY SUPERIOR + +;LOOK FOR SUBJOB THAT HAS TTY, OR DOESN'T WANT TO GIVE TTY +;AWAY IF IT GETS THE TTY. +AGBLT3: MOVE I,TTYTBL(A) + TLNE I,%TBDTY ;REACHED A JOB THAT DIDN'T GIVE TTY AWAY + JRST AGBLT1 ;THIS IMPLIES OUR SUPERIOR TOOK TTY AWAY. + JUMPL I,AGBLT2 ;IF THIS GUY GAVE IT AWAY THEN TRY THE ONE HE GAVE IT TO + HRRZS A ;A HAS IDX OF TTY OWNER; TAKE TTY FROM HIM. + PUSHJ P,RPCLSR ;TURNS CLOCK ON! + CONO PI,CLKOFF + SKIPGE TTYTBL(A) ;DID TTY MOVE WHILE CLOCK WAS ON? + JRST [PUSHJ P,UPCLSR ;IF SO, START OVER + JRST SDTTY] + HLLZ D,TTYTBL(A) + TLZ D,%TBCLR ;DON'T ALTER USER-SETTABLE BITS, BUT + TLO D,%TBNOT+%TBDTY ;TELL HIM HE HASN'T GOT TTY. + MOVEM D,TTYTBL(A) + AOS (P) ;THE .DTTY SHOULD SKIP. + PUSH P,[UPCLSR] ;AFTER RESTARTING THE SUBJOB. +AGBLT6: ANDI I,-1 ;LH(TTYTBL) MAY BE NONZERO EVEN IF JOB HAS TTY! + MOVSI D,%TCLED + TDNE D,TTYCOM(I) ;IF OLD JOB WAS WANTING LOCAL EDITING, + PUSHJ P,AGBLT5 ;TELL TERMINAL TO STOP IMMEDIATELY. + ANDCAM D,TTYCOM(I) ;ASSUME NEW JOB DOES NOT WANT LOCAL EDITING + ;AND SHOULD NOT SEE RESYNCHS (TOP-S). + MOVEI D,TTSTSV-1(A) ;SAVE CURRENT TTY STATUS IN + PUSH D,TTYST1(I) ;USER VARS OF USER GIVING AWAY THE TTY. + PUSH D,TTYST2(I) + PUSH D,TTYSTS(I) + MOVE TT,I + IMULI TT,TPLEN*2 + MOVE D,TPVB+TPLEN(TT) + SUB D,TCMXV(I) + MOVNS D + DPB D,[$TBECL,,TTYTBL(A)] +IFN N11TYS,[ + EXCH U,A ;GET USER GIVING AWAY TTY IN U + MOVE D,TVVBN(U) ;SAVE THIS + PUSHJ P,TVBNCL ;CLEAR OUT CURRENT GUY (MAYBE CLEARING RUN GLITCH ON SCREEN) + MOVEM D,TVVBN(A);PASS THE BALL TO HIM + EXCH U,A +] +;ENTRY FROM "ATTACH". GIVE TTY TO JOB W/ IDX IN U, WITHOUT +;"TAKING" IT FROM ANY JOB. USED WHEN TTY HAD BEEN FREE; JOB, DISOWNED. +AGBLT4: HRROI D,TTSTSV+2(U) + POP D,TTYSTS(I) ;RESTORE THE TTY STATUS OF JOB GIVING TTY TO. + POP D,TTYST2(I) + POP D,TTYST1(I) + HRRM I,TTYTBL(U) ;INDICATE THAT IT HAS THE TTY + LDB H,[$TBECL,,TTYTBL(U)] + HRLOI D,#%TBCLR + ANDM D,TTYTBL(U) + PUSHJ P,ASCML1 ;SET # COMMAND LINES FROM H + MOVSI D,%PJATY + AND D,MSKST(U) + IORM D,PIRQC(U) + MOVEI D,IOCHNM(U) + PUSH P,A ;GENERATE CHNLS-OPEN MASKS, CREATE AN + PUSHJ P,AATT8 ;ACTIVATION CHAR IF NEC, TURN ON PI. + JRST POPAJ + +AGBLT2: HRRZ A,TTYTBL(A) + JRST AGBLT3 + +AGBLT1: MOVSI A,%TBDTY ;TTY WAS TAKEN AWAY FROM US, + IORM A,TTYTBL(U) ;WHEN GIVEN BACK WILL STOP WITH THIS JOB. + JRST CLKOJ1 + +;TELL TERMINAL TO STOP DOING LOCAL EDITING IMMEDIATELY. +AGBLT5: MOVE H,TTYOPT(I) + TRNE H,%TP11T + POPJ P, ;DON'T EVEN TRY ON A TV -- TORM DOESN'T MEAN ANYTHING. + SKIPG TORM(I) ;WAIT FOR ROOM IN OUTPUT BUFFER. + PUSHJ P,UFLS + PUSH P,A + MOVE Q,TOIP(I) + MOVEI A,%TDNLE + PUSHJ P,TYOOU1 ;PUT CMD IN OUTPUT BFR, + MOVEM Q,TOIP(I) + AOSN TTYOAC(I) + XCT TTYST(I) ;AND TELL INT. LVL. ABOUT IT. + JRST POPAJ + +SUBTTL CNSSET, TTYSET, ETC. .CALLS FOR TTYS + +;DECODING TTY SPECIFIERS. CALL WITH JSP,J. MAY RETURN TO (J), +;OR POPJ AND REPORT AN ERROR. + +;DECODE A TTY SPECIFIER, BUT DON'T CHECK FOR PERMISSION TO +;USE THE TTY. ALWAYS RETURN IMMEDIATELY WITH LEGAL TTY SPECIFIER. +ATTYCI: MOVEI Q,CPOPJ + JRST ATTYC8 + +;DECODE A TTY SPECIFIER. +;IF W IS GREATER THAN ONE, DO NOT ALLOW RANDOM TTY NUMBERS. +;ALWAYS WAIT FOR PERMISSION TO OUTPUT. +;IF THE SPECIFIED TTY IS OUR CONSOLE AND OUTPUT IS BEING IGNORED, +;CLOBBER W TO ONE, SO THAT ITS PARAMETERS WILL NOT BE CHANGED (FOR SCPOS). +ATTYCW: JSP Q,[ CAIGE W,2 + JRST ATTYC8 + JRST ATTYC7 ] + PUSHJ P,TTYWO2 + MOVEI W,1 + POPJ P, + +;DECODE A TTY SPEC. +;IF THERE ARE TWO OR MORE ARGS, AND IT IS OUR CONSOLE, +;WAIT UNTIL WE OWN IT, OR MAYBE INTERRUPT. +ATTYC: CAIGE W,2 + JRST ATTYCI +;DECODE A TTY SPEC. +;IF IT IS OUR CONSOLE, WAIT TILL WE OWN IT, OR MAYBE INTERRUPT. +ATTYC2: MOVEI Q,TTYWC2 + JRST ATTYC7 + +;DECODE A TTY SPEC. +;IF IT IS OUR CONSOLE, WAIT TILL WE CAN DO INPUT, +;OR INTERRUPT IF DOING INPUT WOULD. +ATTYCR: MOVEI Q,TTYWI2 + JRST ATTYC7 + +;DECODE A TTY SPEC. SKIP IF IT REFERS TO OUR CONSOLE. +;DO NOT ALLOW RANDOM TTY NUMBERS. +ATTYCM: MOVEI Q,[AOJA J,CPOPJ] + JRST ATTYC7 + +;DECODE A TTY SPEC. SKIP IF IT REFERS TO OUR CONSOLE. +ATTYC9: MOVEI Q,[AOJA J,CPOPJ] +;DECODE CHNL # (IF < 400000) OR TTY # (OTHERWISE) IN A. -1 MEANS TREE'S CONSOLE. +;IF CHNL # BAD, POPJ WITH OPNL. IF NOT STY OR TTY, POPJ WITH OPNL. +;IF OUR CONSOLE, CALL THE ROUTINE Q POINTS TO. +;THEN RETURN WITH TTY # IN I. +ATTYC8: TDZE A,[-400000] ;IS IT A TTY NUMBER? + JRST ATTYC3 ;YES, DECODE THAT. +;DECODE CHNL #, TTY # NOT ALLOWED. +ATTYC7: HRRE T,A + AOJE T,ATTYC6 + HRLI J,ATTYC5 ;RETURN THERE IF NORMAL, OPEN CHANNEL + MOVEI T,AIOCAL ;USE JOB DEVICE CHECKER + JRST CHNDCD ;DECODE CHANNEL AND HANDLE JOB DEVICE SPECIALLY. + +;CHNDCD RETURNS HERE WITH IOCHNM WORD CONTENTS IN H. +ATTYC5: HRRZ T,H + LDB I,[$TIIDX,,H] ;FOR EITHER TTY CHNL OR STY CHNL, GET TTY #. + CAIN I,%TINON ;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE". + JRST OPNL10 + CAIG T,4 ;TTY CHNL => GOOD. + JUMPG T,ATTYC4 + CAIL T,STYDUI + CAILE T,STYDBO + JRST OPNL34 ;NOT STY => BAD. + JRST (J) ;STY => GOOD. + +ATTYC4: LDB T,[.BP <%TICNS,,>,H] ;GET DEVICE/CONSOLE BIT + JUMPE T,ATTYC1 ;JUMP IF IT'S A DEVICE. + PUSHJ P,(Q) ;AWAIT TTY OR INTERRUPT + LDB I,[$TIIDX,,(R)] + SKIPGE T,TTYTBL(U) + JRST (J) ;USER DOESN'T HAVE THE TTY (^P), ERROR CHECKS DON'T APPLY + CAIE I,(T) + BUG ;USER HAS TWO DIFFERENT CONSOLE TTYS +ATTYC1: HRRZ T,TTYSTS(I) ;USER INDEX THAT HAS THIS TTY + CAME T,U + BUG ;USER HAS TTY BUT TTY DOESN'T HAVE THAT USER + JRST (J) + +ATTYC3: MOVEI I,(A) + CAIGE I,NCT ;IS THE ARG THE # OF A REAL TTY? + JRST (J) ;YES, OK. + CAIE I,377777 ;SKIP IF ARG WAS -1 + JRST OPNL1 ;"NO SUCH DEVICE" ERROR. +ATTYC6: PUSHJ P,(Q) ;"MY OWN CONSOLE" SPECIFIED; WAIT OR INTERRUPT. + HRRZ I,TTYTBL(U);NOW GET TTY NUMBER + CAIN I,%TINON ;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE". + JRST OPNL10 + JRST ATTYC1 + +;TTYSET SYSTEM CALL +;SETS TTYST1, TTYST2, TTYSTS, WHEN THE USER HAS THE TTY +;HANGS UNTIL HE GETS IT +ATTYST: JSP J,ATTYCM ;GET TTY NUMBER IN I; SKIP IF IT'S OUR CONSOLE. + JRST ATTYS6 + SKIPGE TTYTBL(U) + JRST ATTYS5 ;JUMP IF OUR CONSOLE AND WE DON'T OWN IT. +ATTYS6: CONO PI,TTYOFF + MOVEM B,TTYST1(I) + MOVEM C,TTYST2(I) + CAIGE W,4 + JRST ATTYS0 ;NO 4TH ARG => DON'T SET TTYSTS. + TLNE D,%TSINT ;SETTING "INT ON NEXT CHAR REGARDLESS"? + PUSHJ P,ATTYS3 ;MAYBE THE "NEXT CHAR" HAS ALREADY BEEN READ. + HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;DON'T CHANGE THESE. + TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX + ANDCMI D,-1 + ANDM B,TTYSTS(I) + IORM D,TTYSTS(I) +ATTYS0: AOS (P) ;MAKE ALL CHRS IN BUFFER ACTIVATION CHARS +ATTYS1: SKIPG TICC(I) + JRST TTYONJ + LDB E,TIIP(I) ;MAKE LAST CHAR AN ACTIVATION CHAR + TRON E,%TXACT + AOS TACC(I) ;IF IT WASN'T ONE, IS ONE MORE ACT CHAR NOW + DPB E,TIIP(I) + JRST TTYONJ + +ATTYS3: SKIPE B,TINTP(I) +ATTYS4: CAMN B,TIIP(I) ;ANY MORE CHARS TO CHECK? + POPJ P, + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB E,B ;YES, CHECK THE NEXT ONE. + TRNE E,%TXIGN ;IF IT ISN'T REALLY THERE, IT SHOULDN'T + JRST ATTYS4 ;INTERRUPT. + TLZ D,%TSINT ;ELSE THIS CHAR IS THE "NEXT CHAR" THAT + TROE E,%TXINT ;SHOULD INTERRUPT REGARDLESS. + POPJ P, + AOS TINTC(I) ;SO MAKE IT AN INT. CHAR IF IT ISN'T. + DPB E,B + MOVE B,TYIMSK(I) + AND B,MSKST2(U) + MOVN C,B + AND B,C + IORM B,IFPIR(U) + MOVEI A,%PITYI + TDNE A,MSKST(U) + IORM A,PIRQC(U) + POPJ P, + +;TTYSET WHEN WE DON'T OWN OUR CONSOLE. +ATTYS5: MOVEM B,TTSTSV(U) + MOVEM C,TTSTSV+1(U) + CAIGE W,4 + JRST POPJ1 + HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;DON'T CHANGE THESE. + TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;CHANGE ONLY CERTAIN LH BITS. + ANDCMI D,-1 + ANDM B,TTSTSV+2(U) + IORM D,TTSTSV+2(U) + JRST POPJ1 + +;TTYGET SYSTEM CALL +;GETS TTYST1, TTYST2 AND TTYSTS WHEN THE USER HAS THE TTY +;HANGS UNTIL HE GETS IT, IF IT'S HIS CONSOLE. +;ALSO RETURNS HIS TTYTYP, TCTYP. +;THE RH OF TTYSTS AS RETURNED IS PRE-DIVIDED BY LUBLK +ATTYGT: JSP J,ATTYC9 ;GET TTY NUMBER NOW IN I; SKIP IF IT'S OUR CONSOLE. + CAIA + SKIPL TTYTBL(U) + JRST ATTYG1 +;OUR CONSOLE AND WE DON'T CURRENTLY OWN IT. + MOVE A,TTSTSV(U) + MOVE B,TTSTSV+1(U) + MOVE C,TTSTSV+2(U) + JRST ATTYG2 + +;EITHER NOT OUR CONSOLE OR WE OWN IT. +ATTYG1: MOVE A,TTYST1(I) + MOVE B,TTYST2(I) + HLLZ C,TTYSTS(I) +ATTYG2: HRRZ D,TTYSTS(I) ;GET IDX OF TTY'S OWNER + CAIE D,-1 ;(BUT MAY BE NO OWNER IF WE SPECIFIED RANDOM TTY) + IDIVI D,LUBLK ;RETURN IN EASY-TO-DIGEST FORM. + HRR C,D + MOVE D,TTYOPT(I) + TLNE D,%TOHDX ;THE %TSHDX BIT REFLECTS THE %TOHDX BIT. + TLO C,%TSHDX + MOVE D,TTYTYP(I) + MOVE E,TCTYP(I) + JRST POPJ1 + +;SCML SYSTEM CALL. 1ST ARG TTY OR STY CHNL, +;2ND ARG IS DESIRED # COMMAND LINES(FOR ECHOING AT BOTTOM OF SCREEN) +;2ND ARG 0 => NO ECHO REGION. +ASCML: JSP J,ATTYCM + JRST ASCML3 + SKIPL TTYTBL(U) + JRST ASCML3 + DPB B,[$TBECL,,TTYTBL(U)] ;IT'S OUR CONSOLE AND WE DON'T OWN IT. + JRST POPJ1 + +ASCML3: PUSH P,[TTYOJ1] + CONO PI,TTYOFF + MOVEI H,(B) +;I HAS TTY #, H HAS # CMD LINES, TTY CHANNEL OFF (TURNED BACK ON). +ASCML1: MOVE TT,TCMXV(I) + CAMN TT,[MOVE] + JRST [ MOVE H,TT ;PRINTING TERMINALS (INFINITE SCREEN) ARE A SPECIAL CASE + JRST ASCML2 ] + CAML H,TT + SOS H,TT + SUB H,TCMXV(I) + MOVMS H ;VPOS OF START OF ECHO AREA. + CAIL H,117. + MOVEI H,117. ;IF TCMXV GARBAGE, AVOID GETTING GARBAGE INTO TPVP +ASCML2: MOVE TT,I + IMULI TT,TPLEN*2 + ADDI TT,TPLEN + CAMN TT,TTYLPP(I) ;MAKE SURE TTY ISN'T ASSOCIATED WITH PC OF PPR + PUSHJ P,TYOMVC ;WHILE THE LATTER'S SIZE IS CHANGING. + SUBI TT,TPLEN + MOVEM H,TPVB+TPLEN(TT) + MOVEM H,TPVP+TPLEN(TT) + HRLM H,TPSP+TPLEN(TT) + JRST NCNSSG + +;RCPOS SYSTEM CALL. (READ CURSOR POSITION) +;1 ARG - TTY OR STY CHNL. +;1ST VALUE ,, +;2ND VALUE
,,
+;1ST VALUE IRRELEVANT IF NO ECHO LINES. +ARCPOS: JSP J,ATTYCW + HRRZ B,H + CAILE B,4 + JRST NRCPO1 + SKIPL TTOALC(I) + PUSHJ P,UFLS +NRCPO1: MOVE TT,I + IMULI TT,TPLEN*2 + HRRZ B,TPVP+TPLEN(TT) + SUB B,TPVB+TPLEN(TT) + HRLZS B + HRR B,TPHP+TPLEN(TT) + HRLZ A,TPVP(TT) + HRR A,TPHP(TT) + JRST POPJ1 + +;SCPOS SYSTEM CALL GETS OR SETS THE SYSTEM'S IDEA OF WHERE THE TTY'S +;CURSOR IS REALLY LOCATED (AT THE M.P. SIDE OF THE OUTPUT BUFFER). +;TO BE USED AFTER OUTPUTTING IN SUPERIMAGE MODE, TO TELL THE SYSTEM +;WHAT THE CHARS ALREADY OUTPUT WILL DO TO THE TTY. MAY ALSO BE USED +;BY A STY PROGRAM LOOKING AT A SOFTWARE TTY, TO TELL THE SYSTEM HOW +;IT HAS INTERPRETED THE CURSOR-MOVING DISPLAY CODES, PROVIDED THE +;OUTPUT BUFFER IS EMPTY (AS IT WILL BE AFTER AN OUTPUT RESET). +;FOR THAT APPLICATION, A WAY TO SET TTOALC IS PROVIDED. +;3 VALUES - VPOS, HPOS AND TTOALC. +;1 ARG (TTY SPEC) => JUST READ THEM. +;2 MORE ARGS => THEY ARE NEW VPOS AND HPOS. +;A FOURTH ARG WILL SET TTOALC. +NSCPOS: JSP J,ATTYCW + HRRZ T,H + CAILE T,4 ;IF WE'RE HACKING A TTY CHANNEL + JRST NSCPO4 + SKIPL TTOALC(I) ;THEN MAYBE THE TTY WANTS TO HACK IT FIRST. + PUSHJ P,UFLS +NSCPO4: SOJE W,NSCPO2 + JUMPL B,OPNL33 + JUMPL C,OPNL33 + CAIG B,118. ;DON'T ALLOW GARBAGE TO GET INTO TPVP + CAIGE W,2 + JRST OPNL33 ;NOT 3 ARGS?? + CAMGE B,TCMXV(I) + ;CAML C,TCMXH(I) + CAIL C,400 ;PREVIOUS LINE MESSES UP ON !-CONTINUED LINES + JRST OPNL33 +NSCPO2: MOVSI TT,%TCLED ;CONTROL BIT SET => SET %TCLED, ALLOWING THIS JOB TO + SKIPE CTLBTS(U) ;READ TOP-E AND TOP-S CHARS. NORMALLY, ITS DISCARDS THEM. + IORM TT,TTYCOM(I) + CONO PI,TTYOFF + SKIPL TT,TTYLPP(I) + JRST NSCPO1 ;WHERE POS LIVES DEPENDS ON WHETHER TTY IS ASSOCIATED. + HRRZ T,C + HRL T,B ;FOR DISSOCIATED TTYS, TTYLPS HAS POS, MUST BE SET. + CAIE W, + MOVEM T,TTYLPS(I) + SETCA TT, ;MAKE SURE TT HAS THE PC PPR #, UNCOMPLEMENTED. +NSCPO1: MOVE A,TPVP(TT) ;FOR ASSOCIATED TTY, POS LIVES IN TPVP AND TPHP OF PC PPR. + CAIE W, + MOVEM B,TPVP(TT) + MOVE B,TPHP(TT) + CAIE W, + MOVEM C,TPHP(TT) +NSCPO3: MOVE C,TTOALC(I) ;NOW GET OLD TTOALC, AND SET IT IF THERE WERE 4 ARGS. + CAIGE W,3 + JRST TTYOJ1 + MOVEM D,TTOALC(I) + CONO PI,TTYON + AOSN TTYOAC(I) ;MAY BE RESTARTING FROM ZERO ALLOCATION + XCT TTYST(I) + JRST POPJ1 + +;CNSGET OR RSSIZE SYSTEM CALL. 1 ARG - TTY OR STY CHNL. +;RETURNS THE SAME VARS THAT CNSSET SETS, IN THE SAME ORDER. +NCNSGET: ;RETURN PERMANENT AND SEMIPERMANENT TTY INFO. +ARSSIZ: JSP J,ATTYCI + MOVE TT,TTYTYP(I) + MOVE E,TTYOPT(I) + MOVE D,TTYCOM(I) + MOVE C,TCTYP(I) + MOVE B,TCMXH(I) ;NOTE TCMXH IS LINEL INCLUDING THE CONTIN. COLUMN, + MOVE A,TCMXV(I) + MOVE I,TTYSMT(I) + SOJA B,POPJ1 + +;CNSSET SYSTEM CALL. +;1ST ARG TTY OR STY CHNL. NEXT ARGS SET +;VERT SIZE, HORIZ SIZE, TCTYP, TTYCOM, TTYOPT VARS RESPECTIVELY. +;TCTYP CAN'T BE SET TO A NONSENSE VALUE, SOME TTYCOM BITS CAN'T BE SET. +;IF 2ND, 3RD OR 4TH ARG IS NEGATIVE, ITS VALUE ISNT CHANGED +NCNSSET: + JSP J,ATTYC + MOVE H,TT +;.CALL TTYVAR ENTERS HERE WITH B/TCMXV, C/TCMXH-1, D/TCTYP, E/TTYCOM, H/TTYOPT +;AND I/TTY#, W/6 +NCNSS0: SKIPL D ;MAKE SURE D HAS NEW VALUE OF TCTYP, + CAIG W,3 ;WHETHER WE'RE CHANGING IT NOW OR NOT. + MOVE D,TCTYP(I) + CAIL D,%TNMAX ;DON'T LET TCTYP BE SET TO ILLEGAL VALUE. + JRST OPNL33 + CONO PI,TTYOFF + MOVE T,TTYTYP(I) ;DON'T LET %TPORS BE SET FOR PDP11 TV. + TRNE T,%TY11T + TRZA H,%TPORS+7*%TPPCR+%TPCBS + TRZA H,%TP11T ;%TP11T MUST REFLECT %TY11T. + IORI H,%TP11T + TRNE T,%TY11T + JRST [ MOVEI B,37. ;DON'T ALLOW A TV TO BE CALLED ANYTHING BUT. + MOVEI C,95. + MOVEI D,%TNTV + JRST NCNSS3] + CAIN D,%TNTV ;NOT A PDP11 LINE => DON'T LET IT BE TREATED AS ONE. + MOVEI D,%TNDP +NCNSS3: CAIGE W,6 + MOVE H,TTYOPT(I) + SKIPE D + TLZ H,%TORAW ;"RAW" MODE EXISTS ONLY ON PRINTING TTYS. + SKIPGE TYMDTB(D) + TLZ H,%TOMVU+%TOERS ;DON'T CLAIM TO DO SOMETHING WE DON'T KNOW HOW TO DO + MOVEI T,1 + TLNN H,%TOMVU + MOVEM T,TTYROL(I) ;ON PRINTING TTYS TTYROL MUST BE 1 + TRNN H,%TPCBS ;IF ^\ ISN'T TO BE HANDLED SPECIALLY, MAKE SURE ALL OF + SETOM TTOALC(I) ;THE FEATURES IT PROVIDES ARE IN THEIR NORMAL STATES. + MOVEI TT,TYBN + TRNN H,%TPCBS+%TPTEL + MOVEM TT,TYBPC(I) + MOVE TT,I + IMULI TT,TPLEN*2 ;TT HAS IDX OF MAIN PC PPR OF TTY. + XORI W,-1 ;EACH OF THE INSNS AFTER THE JRST SETS ONE PARAMETER. + CAIL W,#6 ;>6 ARGS SAME AS 6 ARGS. + JRST NCNSS1+2(W) ;ELSE DON'T SET VARS WE DIDN'T GET ARGS FOR. + MOVEM H,TTYOPT(I) + PUSHJ P,NCNSSC ;SET TTYCOM + MOVEM D,TCTYP(I) ;SET TCTYP. + PUSHJ P,[CAIL C,3 ;DON'T ALLOW SCREEN WIDTH LESS THAN 3. + CAIL C,377777 ;DON'T ALLOW AN HPOS THAT WON'T FIT IN HALFWORD. + POPJ P, ;SPEC NO GOOD, IGNORE + JRST NCNSSH ] ;SET TCMXH. + PUSHJ P,[CAMN B,[200000,,] ;200000,, IS SPECIAL (PRINTING TTY). + JRST NCNSSV + CAIL B,3 ;DON'T ALLOW SCREEN HEIGHT LESS THAN 3. + CAIL B,120. ;VPOS MUST FIT IN ASCII CHARACTER, USUALLY. + POPJ P, ;NO GOOD, IGNORE + JRST NCNSSV ] ;SET TCMXV +NCNSS1: PUSHJ P,NCNSSG ;COMPUTE TTYEPP FROM NEW SETTINGS OF TTY VARS. + JRST TTYOJ1 + +;SET TTY WIDTH (NOT INCLUDING THE SPACE FOR THE "!") TO ARG IN C. +;TTY # IN I, MAIN PC PPR IDX IN TT. +NCNSSH: ADDI C,1 + MOVEM C,TCMXH(I) + CAMG C,TTYIHP(I) ;DON'T ALLOW TTYIHP TO HAVE ILLEGAL VALUE. + SETZM TTYIHP(I) +.SEE TPHE ; MOVEM C,TPHE(TT) +.SEE TPHE ; MOVEM C,TPHE+TPLEN(TT) + CAMG C,TPHP(TT) + MOVEM C,TPHP(TT) + CAMG C,TPHP+TPLEN(TT) + MOVEM C,TPHP+TPLEN(TT) + POPJ P, + +;SET TTY SCREEN HEIGHT FROM VALUE IN B. +NCNSSV: MOVEM B,TCMXV(I) + CAMG B,TTYIVP(I) ;DON'T ALLOW TTYIVP TO GET ILLEGAL VALUE. + SETZM TTYIVP(I) +.SEE TPVE ; MOVEM B,TPVE(TT) +.SEE TPVE ; MOVEM B,TPVE+TPLEN(TT) + HRLM B,TPSP+TPLEN(TT) ;CLOBBER THE 2ND PC PPR TO NULL STATE. + MOVEM B,TPVP+TPLEN(TT) + MOVEM B,TPVB+TPLEN(TT) + CAMG B,TPVP(TT) + SETZM TPVP(TT) + HRRZS TPSP(TT) + POPJ P, + +;MAKE A TTY INTO AN ORDINARY PRINTING TTY. +;TTY # IN I; CLOBBERS TT,B,C. +NCNSSP: SETZM TCTYP(I) + MOVE TT,[%TOMVB+%TOOVR+%TOLWR,,%TPORS] + MOVE B,TTYTYP(I) + TRNN B,%TYSTY + IORI TT,%TPPCR + LDB B,[$TTOSP,,B] + CAIN B,2 + TLC TT,%TOALT+%TOMVB+%TOLWR ;10CPS => ASSUME TELETYPE. +IFN 0,[ ;THIS WOULD TURN THE MOTOR OF A CRTSTY DISPLAY ON AND OFF. + CAIN B,5 ;120CPS => ASSUME TERMINET. + JRST [ TRC TT,%TPPCR+5*%TPPLF + MOVEI C,%TNTRM + MOVEM C,TCTYP(I) + JRST .+1 ] +];IFN 0 + MOVEM TT,TTYOPT(I) + SETZM TTYSMT(I) ;NO GRAPHICS, NO LOCAL EDITING. + SETOM TTOALC(I) ;%TPCBS TURNED OFF + MOVEI TT,1 ;SCROLLS A LINE AT A TIME (THIS IS + MOVEM TT,TTYROL(I) ; MAINLY FOR THE BENEFIT OF TYIFLS) + HRRZ TT,I + IMULI TT,TPLEN*2 + MOVEM TT,TTYEPP(I) + MOVEI C,71. + CAIE B,2 ;10 CPS => TELETYPE + MOVEI C,79. ;ANYTHING ELSE IS AT LEAST 80 WIDE +IFN 0,[ + CAIN B,5 + MOVEI C,119. +] + MOVSI B,(MOVE) + PUSHJ P,NCNSSH + JRST NCNSSV + +;SET TTYEPP OF TTY # IN I, MAIN PC PPR # IN TT. CLOBBER H,TT. +;HAD BETTER ALWAYS BE CONO PI,CLKOFF HERE, OR SYSTEM MAY CRASH IN ECHOING CODE. +NCNSSG: MOVE H,TTYOPT(I) + TLNE H,%TOMVU ;NOT DISPLAY OR + TLNN H,%TOERS ;ARDS-LIKE (CAN'T ERASE) + JRST NCNSSF ; => CAN'T HAVE ECHO AREA. + MOVE H,TPLEN+TPVB(TT) + CAMGE H,TCMXV(I) ;NO ECHO LINES => CAN'T USE ECHO AREA. + ADDI TT,TPLEN ;ELSE USE IT. +NCNSSF: MOVEM TT,TTYEPP(I) + POPJ P, + +IFN N11TYS,[ +;RE-INIT THE PARAMETERS OF A T.V. WHEN IT BECOMES FREE. +NCNSST: HRRZ TT,I + IMULI TT,TPLEN*2 + MOVEI B,%TNTV + MOVEM B,TCTYP(I) + MOVE B,[%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI+%TOLID+%TOCID,,%TP11T+%TPRSC] + MOVEM B,TTYOPT(I) + MOVEI B,4 ;TV'S SCROLL BY 4 LINES PER GLITCH + MOVEM B,TTYROL(I) + MOVEI B,37. + MOVEI C,95. + PUSHJ P,NCNSSH + JRST NCNSSV +];N11TYS + +NCNSSC: XOR E,TTYCOM(I) ;DON'T CHANGE TTYCOM BITS EXCEPT THESE. + AND E,[%TCQRY+%TCRFS+%TCICO+%TCOCO,,] + XORM E,TTYCOM(I) + POPJ P, + +TYVSRO: JUMPL A,OPNL33 ;CAN'T BE NEGATIVE + ;CAME D,%TNTV ;CAN'T SET NON-ZERO ON TVS + CAML A,TCMXV(I);CAN'T BE BIGGER THAN SCREEN SIZE + JUMPN A,OPNL33 + TLNN H,%TOMVU ;ON PRINTING TTYS, TTYROL MUST BE 1 OR GET INTO + CAIN A,1 ; INFINITE RECURSION AT TYOLF3/TYOCLR/TYOCRL + CAIA + JRST OPNL33 + MOVEM A,TTYROL(I) + JRST TTYOJ1 + +;TTYVAR SYSTEM CALL - READ AND WRITE VARIOUS TTY VARIABLES + +;TABLES OF TTY VARIABLES. +;THE NEXT 3 TABLES ARE PARALLEL, IF YOU CHANGE ONE CHANGE THEM ALL. + +;TTY VARIABLE NAMES. MUST BE SORTED IN SIXBIT ORDER. + +TYVTAB: SIXBIT/HEIGHT/ + SIXBIT/IDLTIM/ + SIXBIT/ISPEED/ ;IN BITS PER SECOND + SIXBIT/OSPEED/ ;IN BITS PER SECOND + SIXBIT/SMARTS/ + SIXBIT/TCTYP/ + SIXBIT/TTYCOM/ + SIXBIT/TTYOPT/ + SIXBIT/TTYROL/ + SIXBIT/TTYSMT/ + SIXBIT/TTYTYP/ + SIXBIT/WIDTH/ +LTYVTA==:.-TYVTAB +TYVTL2==.RADIX 2,CONC [.LENGTH/]\.-TYVTAB-1,/ ;BASE 2 LOG-1 OF TABLE SIZE +REPEAT 1_-<.-TYVTAB-1>-1, -1 ;PAD OUT TO POWER OF 2 SIZE + +;INSTRUCTIONS TO GET VARIABLE INTO A + +TYVGET: MOVE A,TCMXV(I) + PUSHJ P,[MOVE A,TIME ? SUB A,TTITM(I) ? POPJ P,] + PUSHJ P,[LDB A,[$TTISP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,] + PUSHJ P,[LDB A,[$TTOSP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,] + MOVE A,TTYSMT(I) + MOVE A,TCTYP(I) + MOVE A,TTYCOM(I) + MOVE A,TTYOPT(I) + MOVE A,TTYROL(I) + MOVE A,TTYSMT(I) + MOVE A,TTYTYP(I) + PUSHJ P,[MOVE A,TCMXH(I) ? SOJA A,CPOPJ] + +;INSTRUCTIONS TO SET VARIABLE FROM A. OPNL33 IF VALUE BAD. OPNL26 IF CAN'T WRITE. +;OTHERWISE, IF GOES VIA .CALL CNSSET, MOVE A INTO APPROPRIATE AC (SEE COMMENT AT NCNSS0). +;FOR OTHER VARIABLES, JRST TO ROUTINE TO STORE A INTO VARIABLE. + +TYVSET: MOVE B,A ;HEIGHT + JRST [SUB A,TIME ? MOVNM A,TTITM(I) ? JRST TTYOJ1] ;IDLTIM + JRST TYSISP ;ISPEED + JRST TYSOSP ;OSPEED + JRST TYVSSM ;SMARTS + MOVE D,A ;TCTYP + MOVE E,A ;TTYCOM + MOVE H,A ;TTYOPT + JRST TYVSRO ;TTYROL + JRST TYVSSM ;TTYSMT + JRST OPNL26 ;TTYTYP + MOVE C,A ;WIDTH + +TYVSSM: MOVEM A,TTYSMT(I) + JRST TTYOJ1 + +;SET SPEED. MAYBE THIS SHOULD CHANGE IT IN HARDWARE ALSO? +TYSISP: SKIPA B,[$TTISP,,TTYTYP(I)] +TYSOSP: MOVE B,[$TTOSP,,TTYTYP(I)] + MOVEI C,17 ;FIND CODE + CAME A,BAUDRT(C) + SOJGE C,.-1 + JUMPL C,OPNL33 ;NON-EXISTENT + DPB C,B + JRST TTYOJ1 + +;TRANSLATION FROM INTERNAL SPEED CODES TO BAUDS +BAUDRT: 0 ? 600. ? 110. ? 150. + 300. ? 1200. ? 1800. ? 2400. + 4800. ? 9600. ? 25000. ? 40000. + 50000. ? 80000. ? -1 ? -2 + +;CODE FOR TTYVAR SYS CALL BEGINS HERE + +NTTYVA: HRRE E,A + JSP J,ATTYC9 ;I TTY NUMBER + SKIPA J,[1] + SETO J, ;J GETS -1 IF IT'S OUR CONSOLE, 1 IF OTHER TTY CHNL. + AOSGE E ;SKIP IF ARG WAS -1 (OWN CNSL) OR CHANNEL NUMBER + MOVEI J,0 ;J ZERO IF TTY SPECIFIED BY NUMBER. + PUSHJ P,VARCAL ;RETURN WITH SUITABLE STUFF IN E,D,W + JUMPE W,NTTYV1 + JUMPE J,OPNL26 ;ERR OUT IF WRITE LOCKED (SOMEONE ELSE'S TTY) + JUMPG J,NTTYV1 ;IF IT'S OUR CONSOLE, WAIT TILL WE OWN IT, OR INTERRUPT. + PUSHJ P,TTYWC2 +NTTYV1: TLNN E,-1 ;DEFAULT LH OF SIXBIT VARIABLE NAME TO 'TTY' + HRLI E,'TTY ;SO CALLER CAN USE IMMEDIATE ARGUMENT -- PRETTY RANDOM + MOVEI B,0 ;LOOK UP IN TABLE OF TTY VARIABLES (TYVTAB) + REPEAT TYVTL2,[CAML E,TYVTAB+1_(B) + ADDI B,1_ + ] + CAME E,[-1] + CAME E,TYVTAB(B) + JRST OPNL11 ;IILEGAL TTY VARIABLE NAME + CONO PI,TTYOFF + XCT TYVGET(B) ;GET VALUE OF VARIABLE INTO A + JUMPE W,TTYOJ1 ;RETURN IF READING + HRRI W,A + XCT W ;PUT NEW VALUE INTO A + MOVE W,TYVSET(B) ;GET INSTRUCTION TO PUT A IN PROPER PLACE + MOVE B,TCMXV(I) ;SET UP OLD VARIABLES FOR NCNSS0 + MOVE C,TCMXH(I) + SUBI C,1 + MOVE D,TCTYP(I) + MOVE E,TTYCOM(I) + MOVE H,TTYOPT(I) + XCT W ;CHANGE THE AC CONTAINING THE VARIABLE TO BE CHANGED + MOVEI W,6 ;TELL CNSSET TO CHANGE EVERYTHING + JRST NCNSS0 ;MAKE THE CHANGES, THEN TTYOJ1. + +;.CALL TTYFLS +; ARG 1 - +;WITH CONTROL BITS 0, MARKS LAST INTERRUPT CHARACTER ITYIC'ED +; TO BE IGNORED AT MAIN PROGRAM LEVEL. +;WITH CONTROL BIT 1, DISCARDS ALL INPUT THROUGH LAST CHARACTER ITYIC'ED. +NTTYFLS:JSP J,TTYNGT + MOVE A,CTLBTS(U) + TRNN A,1 + JRST NTTYF2 + CONO PI,TTYOFF +NTTYF1: MOVE C,TIOP(I) + CAMN C,TINTP(I) + JRST TTYOJ1 + PUSHJ P,TYIREM + JRST NTTYF1 + +NTTYF2: LDB A,TINTP(I) + TRO A,%TXIGN + DPB A,TINTP(I) + JRST POPJ1 + +NTTYESC: ;SIMULATES TYPING OF ^_ + JSP J,ATTYC2 ;DECODE TTY SPEC. IF OUR CONSOLE, WAIT TILL WE CAN INPUT. + CONO PI,TTYOFF + HRRZ A,TTYIPC(I) + CAIE A,TTYI + JRST OPNL7 ;DEVICE NOT READY + MOVEI A,TYCI + MOVEM A,TTYIPC(I) + JRST TTYOJ1 + +;WHOLINE SYSTEM CALL. +;TAKES A MANDATORY 1ST ARGUMENT SPECIFYING A TTY. +;RETURNS TWO VALUES - THE OLD SETTINGS OF WHMODE AND WHJOB +;FOR THAT TTY. +;OPTIONAL 2ND AND 3RD ARGUMENTS SET WHMODE AND WHJOB. IF THEY +;ARE PRESENT, THE RETURNED VALUES ARE THE OLD SETTINGS. +;THE CALL FAILS FOR TTY'S OTHER THAN TV'S. + +NWHOLI: JSP J,ATTYC ;DECODE THE TTY SPEC. + MOVE H,TTYOPT(I) +IFN N11TYS,TRNN H,%TP11T ;FAIL IF NOT PDP11 TV. + JRST OPNL34 +IFN N11TYS,[ + SKIPL TT11P ;TV PDP11 DOWN => DON'T USE IT. + JRST OPNL10 + CAIGE W,2 ;IF THERE ARE OPTIONAL ARGS, DECODE THEM. + JRST NWHOL2 + CAIE B,1 ;DECODE 3RD ARG ONLY IF RELEVANT. + JRST NWHOL2 + MOVE J,C ;IT SHOULD BE A JOB SPEC. + CAIGE W,3 + SETO J, ;USE -1 (SELF) AS THE DEFAULT. + JSP T,NCRUI2 + JFCL + JUMPL J,OPNL34 ;PDP6 IS NO GOOD. + MOVE C,J + IDIVI C,LUBLK ;CONVERT USER IDX TO JOB #. +NWHOL2: ADD I,TT11HD + ADD I,TT1111 + ADD I,TT1111 + LDB TT,[$11AD0,,1-NF11TY(I)] + ADDI TT,TT11LO ;TT HAS PDP10 ADDR OF TTY'S WHOLINE VARS. + CONO PI,TTYOFF + MOVE T,WHMODE(TT) ;FIRST, GET THE CURRENT SETTINGS. + LDB Q,[$11WD0,,WHJOB(TT)] + CAIGE W,2 + JRST NWHOL3 + DPB B,[$11WD0,,WHMODE(TT)] ;THEN, SET TO NEW VALUES IF REQUIRED. + DPB C,[$11WD0,,WHJOB(TT)] +NWHOL3: CONO PI,TTYON + MOVE A,T ;PUT RETURN VALUES IN APPRO. ACS + ASH A,-24 + MOVE B,Q + JRST POPJ1 +] + +;TVWHER SYSTEM CALL. +;TAKES 1 ARG SPECIFYING A TTY, WHICH MUST BE A TV TTY. +;RETURNS 2 VALUES. +;1ST VALUE: THE KEYBOARD NUMBER OF THE PHYSICAL TERMINAL IN USE. +;2ND VALUE: THE NUMBER OF THE DISPLAY BUFFER IN USE ON THIS TTY. + +NTVWHE: JSP J,ATTYCI + MOVE H,TTYOPT(I) +IFN N11TYS, TRNN H,%TP11T + JRST OPNL34 +IFN N11TYS,[ +NTVWH1: LDB A,[$11AD0,,TT11HA] + ADDI A,TT11LO(I) + LDB B,[$11BY3,,1-NF11TY(A)] + LDB A,[$11BY2,,1-NF11TY(A)] + JRST POPJ1 +] + +SUBTTL .ITYIC, .LISTEN, TTY WHYINT + +;.CALL ITYIC. 1 ARG, A TTY INPUT CHANNEL; 1 VALUE, THE INTERRUPT CHAR. +;FAILS IF THERE ARE NO INTERRUPT CHARACTERS. +NITYIC: JSP J,TTYNGT +AITYI1: SKIPG D,TINTC(I) + POPJ P, + MOVE A,TINTP(I) ;SAVE SOME INFO FOR DEBUGGING + MOVE J,TICC(I) + MOVE C,TIIP(I) ;GET THE END OF FILLED PART OF BUFFER +AITYI2: CAMN C,TINTP(I) ;IF OUR MOVING POINTER PASSES THERE, THERE ARE REALLY + BUG ;NO INT CHARS IN THE BUFFER. BUT TINTC NON-ZERO?? + MOVE B,TINTP(I) + CAMN B,TIBEP(I) ;WRAP AROUND AT END OF BUFFER + SUBI B,TIBL + HRRM B,TINTP(I) ;ADVANCE TINTP TO NEXT CHARACTER. + ILDB B,TINTP(I) + TRZN B,%TXINT ;KEEP LOOKING TILL FIND NEXT INT. CHAR. + JRST AITYI2 + DPB B,TINTP(I) + SOS TINTC(I) + HLRZ R,H ;GET IOCHNM BITS IN R. UNLESS %TIFUL IS SET, + MOVE A,B + AOS (P) + JRST TYINRM ;NORMALIZE PDP-11 12-BIT CHARACTERS TO 7-BIT. + +;.CALL WHYINT ON TTY INPUT CHANNEL IS SIMILAR TO ITYIC +TYIWHY: JSP J,TTYNG1 + PUSHJ P,AITYI1 + SOS (P) ;DON'T SKIP-RETURN IF NO INTERRUPT CHARS + MOVE B,A ;SECOND RESULT IS INTERRUPT CHARACTER + MOVEI A,%WYTYI ;FIRST RESULT IS DEVICE CODE + JRST POPJ1 + +AITYI: SETO A, ;.ITYI OBSOLETE. + TDZA H,H +AITYIC: UMOVE A,(J) ;.ITYIC + PUSH P,J ;TURN INTO NEW SYSTEM CALL ITYIC + MOVE B,[SIXBIT /ITYIC/] + MOVEM B,LSCALL(U) ;FOR JOB DEVICES' SAKE. + MOVEI W,1 + PUSHJ P,NITYIC + JRST POP1J + UMOVEM A,@(P) + JRST POP1J1 + +ALISTEN:SKIPGE I,TTYTBL(U) ;.LISTEN + JRST ALIS1 + PUSHJ P,TYOWC + SKIPA B,TICC(I) +ALIS1: SETZ B, + MOVE A,PIRQC(U) + TRNE A,%PIC.Z + JRST UDELAY + UMOVEM B,(J) + POPJ P, + +TTYFIN: JSP J,TTYNG1 ;HERE FOR .CALL FINISH ON TTY OUTPUT CHANNEL + PUSHJ P,TYOWC + JRST POPJ1 + +NLISTE: JSP J,TTYNGT ;HERE FOR .CALL LISTEN + PUSHJ P,TYOWC + MOVE A,TICC(I) + JRST POPJ1 + +TTYNGT: TRC A,-1 ;RH(A)=-1 => TREE'S CONSOLE + TRCN A,-1 + JRST TTYNG2 + MOVEI T,AIOCAL ;OTHERWISE MUST BE CHANNEL NUMBER + HRLI J,.+2 + JRST CHNDCD + TLNN R,%CLSTI ;CHNDCD RETURNS CLSTB BITS IN R, IOCHNM WD CONTENTS IN H + JRST OPNL34 +TTYNG1: HLRZ I,H + TRZ I,377700 + TRZE I,400000 ;SKIP IF DEVICE (RATHER THAN CONSOLE) +TTYNG2: SKIPL I,TTYTBL(U) + JRST (J) + JRST OPNL10 + +TYOWHY: MOVEI A,%WYTYO ;.CALL WHYINT ON TTY OUTPUT CHANNEL + MOVSI B,(SETZ) ;FOR NOW, JUST ASSUME REASON IS **MORE** + JRST POPJ1 + +SUBTTL TTY OPEN + +;LH TTY OPEN +;3.1 0 -> IN 1 -> OUT +;3.2 0 -> UNIT 1 -> BLOCK + +;OUTPUT +;3.3 => IMAGE MODE (SET ALL %TGIMG BITS IN TTYST1 AND TTYST2) +;3.4 0 -> NORMAL 1 -> ECHO MODE OUTPUT (SET %TJECH, %TJPP2, %TJMOR). +;3.5 0 -> NORMAL 1 -> DISPLAYMODE, LOOK FOR ^P (SET %TJDIS). +;3.6 0 -> NORMAL 1 -> SUPER-IMAGE OUTPUT (SET %TJSIO). + +;INPUT +;3.3 => IMAGE MODE (CLEAR ALL ECHO BITS IN TTYST1, TTYST2). +;3.4 => "DDT" (DON'T ECHO CR, LF, TAB) +;3.5 => CONVERT LOWER TO UPPER CASE +;3.6 => WANT 3 LINES IN ECHO AREA. + +;BITS 3.4 AND 3.6 ON INPUT, AND BIT 3.3, HAVE EFFECT +;ONLY ON THE FIRST OPEN IN EITHER DIRECTION. +;(THEY ARE OBSOLETED BY THE TTYSET SYSTEM CALL) + +;LH OF IOCHNM WD +;(SHOWS UP IN RH OF A ON .IOT, .CLOSE, ETC) + +%TICNS==400000 ;4.9 1-> CONSOLE 0 -> DEVICE. THIS BIT EXIST IN INPUT AND OUTPUT CHNLS. +%TJCNS==400000 ;4.9 1-> CONSOLE 0 -> DEVICE + +;OUTPUT: +%TJCP1==200000 ;^P-CODE ANTICIPATION STATE. +%TJCP2==100000 ; ". 0=>NORMAL, 1=> CHAR AFTER ^P, 2=> ^PH, 3=>^PV. +%TJECH==40000 ;SET => ECHO MODE OUTPUT.-MODE OUTPUT (ALL CHARS OUTPUT THE + ;WAY THEY WOULD BE ECHOED) +%TJCTN==20000 ;SET => DON'T DO LINE-CONTINUATION. +%TJSTP==10000 ;SET => THIS CHANNEL IS HUNG IN **MORE**. +%TJDIS==4000 ;SET => LOOK FOR ^P CODES. +%TJSIO==2000 ;SET => SUPERIMAGE OUTPUT, NO PADDING OR CURSOR CTL. +%TJMOR==1000 ;SET => DON'T DO **MORE** PROCESSING. +%TJPP2==400 ;SET => USE ALTERNATE PC PPR (THE ECHO AREA) +%TJINK==200 ;SET => NEXT CHAR ASSUMED TO BE 1-POSITION PRINTING. +%TJHDE==100 ;SET => ACCOUTING FOR CURSOR MOTION DUE TO + ;CHAR ECHOED ON A HALF-DUPLEX TTY. + +;INPUT +;3.3 => NO ECHO. +%TIECH==40000 ;CAN READ EVEN IF CHAR NEEDS PI ECHOING. +%TIPEK==20000 ;DON'T REMOVE CHAR FROM BUFFER. +%TIACT==4000 ;SET => DON'T WAIT FOR ACTIVATION CHARACTER. +%TIINT==2000 ;SET => CAN READ A CHAR EVEN IF IT IS SUPPOSED TO INTERRUPT & HASN'T YET. +%TINWT==1000 ;SET => IF NO INPUT AVAILABLE, DON'T WAIT, JUST RETURN -1. +%TIFUL==400 ;SET => GIVE FULL CHARACTER (SIGNIFICANT ON IMLAX, TVS) + +$TIIDX==220600 ;3.6-3.1 CONSOLE #, OR 77 FOR A "DISOWNED" CONSOLE TTY CHNL +;IE, ONE THAT CORRESPONDS TO NO REAL TTY. THEY EXIST ONLY IN +;TREES WITH NO TTY, IN JOBS THAT CAM FROM TREES WITH TTYS. +%TINON==77 ;"TTY #" FOR A CHANNEL WITH NO REAL TTY. + +;ENTRY FOR OPEN OF TTY AS DEVICE TYN OR TNM + + +IFN TTLPTP,[ +LPTO: MOVE J,TIME + SUB J,LPTTIME ;"LPT" INPUTS EVERY ONCE IN A WHILE IF IT IS UP + CAIL J,60. ;2 SECONDS + JRST OPNL7 + SKIPA I,LPTTTY +] +TTYO: PUSHJ P,TTYFD ;TEST FOR FILE NAME OF .FILE. (DIR) + CAIL I,NCT + JRST OPNL1 ;TTY NUM TOO LARGE +TTYO3C: +IFN NNVTTS,[ + .ERR Shouldn't this be using NFNVTY instead? + CAIGE I,NOTYS+NNTYS+NNVTTS + CAIGE I,NOTYS+NNTYS ;SKIP ON NOVA TTY + JRST TTYO3A + SKIPGE NOVATT + JRST OPNL10 ;NOVA LINK NOT ACTIVE +TTYO3A: CAMN I,NOVATT + JRST OPNL10 ;CANT OPEN TTY USED AS CNHL TO NOVA +] + MOVEI A,0 ;MARK AS A DEVICE + CONO PI,TTYOFF ;INTERLOCK WITH OTHER TTY OPENS, AND ^Z'S. + SKIPGE TT,TTYSTS(I) ;SKIP IF TTY OPEN + JRST TTYO3B ;OK IF TTY NOT OPEN + CAIE U,(TT) ;SAME USER THAT HAS IT? + JRST OPNL10 ;TTY ALREADY OPEN AS DEVICE BY SOMEONE ELSE. + TLNN TT,%TSCNS ;OPEN AS CONSOLE? + JRST TTYO8 ;NO, AS DEVICE + CONO PI,TTYON + JRST TTYO7 ;OPEN, THIS TIME AS CONSOLE. + +TTYO3B: SKIPGE TTYSTA(I) ;TTY IS FREE: IS IT IN TRANSITION TO OR FROM BEING IN USE? + JRST TTYO8 ;OK IF NOT; + MOVE T,I ;STYOCF TAKES TTY # IN T. + PUSHJ P,STYOCF ;AND WAIT TILL TTY IS NO LONGER IN TRANSITION + PUSHJ P,UFLS + JRST TTYO3C ;THEN TRY AGAIN TO OPEN IT. + +;TTY IS AVAIL. TO OPEN AS A DEVICE. +TTYO8: SKIPN TTNTO(I) ;IF TTY USED TO BE FREE, INIT. IT. + PUSHJ P,TTYINI + MOVSI TT,%TSFRE + ANDCAM TT,TTYSTS(I) + JRST TTYO3 + +TTYFD: PUSHJ P,FLDRCK ;SKIP IF FILE DIR BEING OPENED + JRST TTYFD1 ;FILE NAMES NOT SPECIAL + SUB P,[1,,1] + MOVEI J,6 + JRST LISTF7 ;GO GET DIRCTORY + +TTYFD1: JUMPE W,CPOPJ ;0 IS THE ONLY DEFINED MODE FOR ANY TTY OPEN + SUB P,[1,,1] + JRST OPNL12 + +FLDRCK: CAMN A,[SIXBIT /.FILE./] + CAME B,[SIXBIT /(DIR)/] + POPJ P, + JRST POPJ1 + +;INIT A TTY WHEN IT CEASES TO BE FREE. (ZFLAG7 FOR TTY, TTYO8 FOR TNM) +;CHNL 3 (TTYCHN) MUST BE OFF OR IN PROGRESS. +TTYINI: SETZM TTYST1(I) + SETZM TTYST2(I) + MOVSI J,%TACFM ;TTY NEEDS A CONSOLE FREE MESSAGE. + ANDCAM J,TTYSTA(I) + MOVE J,TTYTYP(I) + TRNN J,%TYSTY ;EXCEPT ON STY TTYS, + PUSHJ P,TTYIN1 ;INIT THE USER OPTIONS IN TTYOPT, TTYCOM. + MOVE J,TTYOPT(I) + HRLOI H,%TSFRE ;INITIALIZE TTYSTS FROM TTYOPT + TLNE J,%TOROL + TLO H,%TSROL + TLNN J,%TOMOR ;NOTE %TOMOR SAYS DO **MORE** PROC, + TLO H,%TSMOR ;%TSMOR SAYS INHIBIT **MORE** PROC. + TLNE J,%TOSA1 + TLO H,%TSSAI + MOVEM H,TTYSTS(I) + HRRZ TT,I + IMULI TT,TPLEN*2 + SETZM TPFLAG(TT) + SETZM TPFLAG+TPLEN(TT) + SETZ H, ;START OUT WITH NO ECHO LINES. + JRST ASCML1 + +;INIT A FEW BITS IN TTYOPT, TTYCOM THAT ARE CONSIDERED USER OPTIONS. +;NORMALLY DONE WHENEVER A TTY BECOMES IN USE, BUT ON STY TTY'S +;DONE ONLY WHEN THE STY IS INITIALIZED (SO STY-USER CAN SET THESE OPTIONS). +TTYIN1: MOVE J,TTYCOM(I) + TLZ J,%TCRFS+%TCQRY+%TCOCO+%TCICO + MOVEM J,TTYCOM(I) + MOVE J,TTYOPT(I) ;INIT SOME TTYOPT BITS. + TLZ J,%TOUSR + TRZ J,%TPUSR + TLO J,%TOMOR ;DO **MORE** + HLLM J,TTYOPT(I) + POPJ P, + +;TELETYPE OPEN ROUTINES + +;ENTRY FOR OPEN OF "TTY" AS A CONSOLE + +TTYO1: PUSHJ P,TTYFD ;TEST FOR FILE NAME OF .FILE. (DIR) +TTYO7: MOVE I,TTYTBL(U) + JUMPGE I,TTYO2 ;JUMP IF HAS TTY NOW + TLNE I,%TBWAT + JRST TTYO2A + TLNN I,%TBNVR ;IF I SHOULD FAIL IF TRY TO OPEN TTY WHEN DON'T HAVE IT, + TLNN I,%TBDTY ;OR IF I HAVE DONE A .ATTY, + JRST OPNL10 ;THE OPEN SHOULD FAIL. +TTYO2A: PCLT + SKIPGE TTYTBL(U) + PUSHJ P,UFLS ;HANG UNTIL HAS TTY + MOVE I,TTYTBL(U) +TTYO2: HRRZS I ;TTY NUMBER + CAIL I,NCT + JRST 4,OPNL1 ;TTY NUM TOO LARGE + MOVSI A,%TICNS ;SAY TTY CHNL WILL BE OPEN AS CONSOLE. + CONO PI,TTYOFF +TTYO3: HRLZI J,(D) ;SET IOCHNM BITS (IN A) FROM OPEN MODE. + LSH J,1 + TLZ J,700077 ;BUT DON'T USE PARTS OF OPEN WD USED FOR OTHER THINGS. + IOR A,J +IFN TTLPTP,[ + CAMN I,LPTTTY ;SKIP IF OT TTY + HRRZM U,LPTUSR +] + DPB I,[$TIIDX,,A] ;LH OF A WILL BE STORED IN LH OF IOCHNM WORD + HRRZ TT,UUAC(U) ;TT HAS CHNL # BEING OPENED. + JUMPGE D,TTYO4 ;J IF INPUT OPEN. + TRNE D,20 + TLO A,%TJSIO ;SUPER IMAGE OUT. + TRNE D,4 + TLO A,%TJECH+%TJPP2+%TJMOR ;ECHO OUTPUT + TRNE D,10 + TLO A,%TJDIS ;DISPLAY OUTPUT MODE. + MOVE J,TYOMSK(I) + IOR J,CHNBIT(TT) ;UPDATE CHANNELS-OPEN MASK + EXCH J,TYOMSK(I) ;FOR THE NEW OUTPUT CHANNEL. + JUMPN J,TTYO5 ;FOR 1ST OUTPUT OPEN, INIT TTYST1,2. + MOVE J,[101010,,101010] + IORM J,TTYST1(I) + IORM J,TTYST2(I) ;SET ALL THE OUTPUT-IN-IMAGE-MODE BITS. + TRNN D,2 + ANDCAM J,TTYST1(I) ;IF NOT IMAGE, CLEAR THEM. + TRNN D,2 + ANDCAM J,TTYST2(I) + JRST TTYO5 + +TTYO4: MOVE J,TYIMSK(I) + IOR J,CHNBIT(TT) ;UPDATE INPUT-CHNLS-OPEN MASK + EXCH J,TYIMSK(I) ;FOR NEWLY OPENED INPUT CHANNEL. + JUMPN J,TTYO5 ;THE 1ST INPUT CHNL OPEN, INIT ECHO BITS... + MOVEI H,0 ;INPUT + TRNE D,20 + MOVEI H,3 ;# COMMAND LINES + PUSHJ P,ASCML1 + MOVE J,TTYST1(I) + AND J,[101010,,101010] ;SAVE IMAGE MODE OUTPUT BITS + TRNN D,2 ;SKIP ON IMAGE MODE INPUT + IOR J,[202020,,202020] ;ASCII MODE INPUT + IOR J,[030303,,030303] ;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER + MOVEM J,TTYST1(I) ;STORE BACK + MOVE J,TTYST2(I) + AND J,[101010,,101010] ;SAVE IMAGE MODE OUTPUT BITS + TRNN D,2 ;SKIP ON IMAGE MODE INPUT + IOR J,[202020,,200020] ;SAY ALL CHARS EXCEPT RUBOUT SHOULD ECHO. + TRNE D,4 ;SKIP ON NOT DDT MODE + ANDCM J,[006000,,606000] ;DDT MODE + IOR J,[030303,,030303] ;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER + MOVEM J,TTYST2(I) ;STORE BACK +TTYO5: HRRM U,TTYSTS(I) + AOS TTNTO(I) ;INCREMENT NUMBER OF CHNLS THIS TTY OPEN ON. + CONO PI,TTYON + MOVSS C + JSP Q,OPSLC3 ;SET UP IO CHNM WORD AND RETURN + TYIDN,,TYODN + TYIBN,,TYOBN + +SUBTTL WAITING FOR ACCESS TO TTY + +;HERE WHEN WANT TO DO TTY INPUT, TO CHECK FOR PERMISSION. +TTYWI: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS ;CLEAR AND CHECK CONSOLE/DEVICE BIT + POPJ P, ;RETURN RIGHT AWAY IF DEVICE +;CALL FROM ATTYCR. +TTYWI2: MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN RIGHT AWAY IF WE OWN THE TTY. + POPJ P, + TLNE T,%TBIIN ;ELSE INTERRUPT IF %TBIIN IS SET. + JRST TTYLOS +TTYWC3: TLC T,%TBINT ;ELSE INTERRUPT IF %TBINT IS SET AND NOT %TBWAT. + TLNN T,%TBINT+%TBWAT + JRST TTYLOS + PCLT + SKIPGE TTYTBL(U) + PUSHJ P,UFLS ;WAIT TILL HAS TTY (CANT HAVE TTY IF DISOWNED) + POPJ P, + +;CALL FROM ATTYC, ATTYC2. WAIT TILL WE OWN THE TTY. +TTYWC2: MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN RIGHT AWAY IF WE OWN THE TTY. + POPJ P, + JRST TTYWC3 + +;HERE WHEN WANT TO DO A TTY RESET. +;SKIP IF THE RESET SHOULD REALLY BE DONE. +TTYWR: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS ;CLEAR AND CHECK CONSOLE/DEVICE BIT + JRST POPJ1 ;RETURN YES IF DEVICE + MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN YES IF WE OWN THE TTY. + JRST POPJ1 + POPJ P, ;OTHERWISE IGNORE THE RESET. + +;HERE TO WAIT FOR OUTPUT PERMISSION FOR TTY +;RETURN WITHOUT SKIP IF THE OUTPUT SHOULD BE THROWN AWAY +;AND REPORTED TO THE USER AS DONE. +TTYWO: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS + JRST POPJ1 ;ALWAYS HAVE PERMISSION IF TTY IS A DEVICE. +;CALL FROM ATTYC, ETC. +TTYWO2: MOVE A,U + HRRZ T,I + CAIN T,%TINON ;NEVER HAVE PERMISSION FOR CONSOLE IF WE'RE DISOWNED. + JRST TTYWO1 + MOVE T,TTYTBL(U) ;WE HAVE OUTPUT PERMISSION IFF ALL OUR SUPERIORS + ;HAVE PERMISSION AND WE HAVE %TBOUT + ;AND THE TREE HAS A TTY. +;THE NEXT INSN IS TEMPORARY, UNTIL DDT ETC. ARE CHANGED TO WIN FULLY. +TTYWO3: JUMPGE T,TTYWO4 ;IF WE HAVE THE TTY, WE CAN TYPE ON IT. + SKIPGE SUPPRO(A) ;ALL OK TO TOP OF TREE => SEE IF TREE HAS A TTY. + JRST TTYWO4 + TLNN T,%TBOUT ;NOT AT TREE TOP => DOES THIS JOB HAVE PERMISSION + JRST TTYWO1 ;FROM ITS SUPERIOR? + MOVE A,SUPPRO(A) ;AND IS THE SUPERIOR ALLOWING ANY INFERIORS PERMISSION? + MOVE T,TTYTBL(A) + TLNE T,%TBINF ;SUPERIOR SAYS WE'RE OK => SEE IF SUPERIOR HAS PERMISSION. + JRST TTYWO3 +TTYWO1: MOVE T,TTYTBL(U) ;HERE IF WE DON'T HAVE PERMISSION. + TLNE T,%TBOIG ;IF OUTPUT IS TO BE IGNORED, + POPJ P, ;TELL OUR CALLER TO THROW IT AWAY, RIGHT NOW. + TLNE T,%TBWAT+%TBOUT + JRST TTYWO6 + TLNE T,%TBINT + JRST TTYLOS + TLNE T,%TBNVR+%TBDTY + JUMPL I,[ SUB P,[1,,1] ? JRST OPNL10 ] +TTYWO6: MOVE T,TTYTBL(A) ;ELSE MUST WAIT. WAIT FOR A CHANGE IN THE + CAMN T,TTYTBL(A) ;TTYTBL OF THE SUPERIOR DENYING US PERMISSION. + PUSHJ P,UFLS + JRST TTYWO ;NOW RE-CHECK EVERYTHING. + +;WE HAVE PERMISSION, BUT MAYBE WAIT ANYWAY TO AVOID MIXING JOBS' OUTPUT. +TTYWO4: SKIPGE TTYTBL(U) ;NO NEED TO WAIT IF WE OWN THE TTY + CAMN U,TTYLJB(I) ;OR WE WERE LAST JOB TO USE IT. + JRST TTYWO5 + MOVEI T,TOBS ;ELSE WAIT FOR BUFFER TO BE EMPTY + CAMN T,TORM(I) + JRST TTYWO5 + CAME T,TORM(I) + PUSHJ P,UFLS + JRST TTYWO ;RECHECK EVERYTHING, SINCE WE MAY HAVE LOST PERMISSION. + +;WE ARE ALLOWED TO OUTPUT RIGHT AWAY. +TTYWO5: MOVEM U,TTYLJB(I) ;MAKE SURE WE DON'T HAVE TO WAIT AGAIN. + JRST POPJ1 + +;TURN TTY OFF, THEN WAIT UNTIL EITHER TTY ISN'T IN COM MODE OR +;ONE OF THE BITS IN T IS SET IN TTYCOM(I). +TTYCMW: CONO PI,TTYOFF + TDNN T,TTYCOM(I) + SKIPL TTYCOM(I) + POPJ P, + SKIPN USER + POPJ P, ;SYS JOB TRYING TO HACK + HRR T,I ;WAIT UNTIL NOT COM MODE OR IN COM MODE BUT ONE OR MORE BITS IN LH OF T + PUSHJ P,LWAIT1 ;COME ON. WAIT UNTIL OUT OF COM MODE WITH UTCOFF + PUSHJ P,TTYSCM + POPJ P, + +TTYSCM: SKIPL TTYCOM(T) + JRST POPJ1 ;NOT COM MODE + PUSH P,A + HLLZ A,TTYCOM(T) + TDNE A,T + AOS -1(P) ;MASKED BIT(S) ON + POP P,A + POPJ P, + + +;ECHOIN SYSTEM CALL. ASK FOR ECHOING OF CERTAIN CHARACTERS +;UNTIL A BREAK CONDITION OCCURS. +;A BREAK CONDITION IS WHEN EITHER A NON-ECHOED CHARACTER IS TYPED IN +;OR A CERTAIN NUMBER OF CHARACTERS HAVE BEEN TYPED IN. +;CHARACTERS ECHOED BY THE ECHOIN ARE STORED INTO THE USER'S +;MEMORY BY THE INTERRUPT LEVEL. IF THE NECESSARY AREAS OF MEMORY +;ARE SWAPPED OUT, THAT CONSTITUTES A BREAK CONDITION. + +;THE BREAK TABLE IS 128 BITS (DIVIDED INTO 4 WORDS THE LOW 4 BITS OF EACH UNUSED) +;ONE BIT FOR EACH ASCII CHARACTER. A 1 INDICATES A CHARACTER THAT +;IS A BREAK CONDITION. A 0 INDICATES A CHARACTER THAT CAN BE ECHOED. +;A CHARACTER WITH THE CONTROL OR META BIT IS ALWAYS A BREAK. + +;ARG 1 TTY INPUT CHANNEL +;ARG 2 B.P. TO WHERE IN USER'S MEMORY TO STORE CHARACTERS. +;ARG 3 NUMBER OF CHARACTERS TO ALLOW +;ARG 4 ADDRESS OF BREAK TABLE. +;ARG 5 ADDRESS OF BLOCK OF COUNTERS TO BE INCREMENTED OR DECREMENTED FOR EACH CHARACTER. +; IF THE ADDRESS IS ZERO, ALL THIS IS OMITTED. +; THE BLOCK HAS SEVEN WORDS. +; THE FIRST TWO WORDS ARE LEFT ALONE. +; THE NEXT FOUR ARE INCREMENTED. +; THE SEVENTH IS DECREMENTED. + +;THE WORDS OF THE BREAK TABLE RESIDE IN ACS Q, J, R AND W. +;SIMILARLY, THE ADDRESS OF THE COUNT RESIDES IN AC C, +;THE ADDRESS OF THE BYTE POINTER IN B, +;AND THE ADDRESS OF THE BLOCK OF COUNTERS IN E. +;THEY ARE LOOKED AT BY THE INTERRUPT LEVEL, +;WHICH KNOWS THAT THE PROGRAM IS EXECUTING AN ECHOIN +;BY THE FACT THAT THE PC IS NECHO1. IT IS IMPORTANT THAT WE +;NOT LOCK ANY SWITCHES SO THAT SWAPPING OUT A PAGE WON'T PCLSR +;US UNTIL WE ARE AWAKENED BY THE INTERRUPT LEVEL WHEN IT SEES +;THAT THE PAGES IT NEEDS ARE NOT IN CORE. + +NECHOIN: + JSP J,ATTYCR ;DECODE CHANNEL. GET TTY NUMBER IN I. + XCTR XRW,[MOVES A,(C)] ;MAKE SURE COUNT IS IN CORE AND WRITABLE. + JUMPLE A,POPJ1 ;IF WANT ZERO OR FEWER CHARACTERS, RETURN IMMEDIATELY. + XCTR XRW,[MOVES A,(B)] ;MAKE SURE BYTE POINTER IS IN CORE AND WRITABLE. + IBP A ;MAKE SURE BYTE BUFFER IS IN CORE AND WRITABLE. + XCTR XRW,[MOVES (A)] ; (NO LOSSAGE IF IT ISN'T, BUT MIGHT AS WELL SWAP IT IN NOW.) + XCTR XRW,[MOVES (E)] ;MAKE SURE BLOCK OF COUNTERS IS IN CORE AND WRITABLE. + XCTR XRW,[MOVES 6(E)] + UMOVE Q,(D) ;LOAD BREAK TABLE WORDS INTO Q, J, R, W. + UMOVE J,1(D) + UMOVE R,2(D) + UMOVE W,3(D) + SKIPE TICC(I) ;IF TYPE-AHEAD AVAILABLE, WE CAN'T DO ANYTHING. + JRST POPJ1 + SKIPG TACC(I) ;WAIT FOR AN ACTIVATION (PROBABLY NON-ECHOED) CHARACTER. + PUSHJ P,TYIFL2 ;CALL TYIFL2 INSTEAD OF UFLS TO PREVENT IMPENDING **MORE**. +NECHO1: JRST POPJ1 ;THE JOB IS INSIDE AN ECHOIN IF ITS PC IS HERE. + +SUBTTL TTY INPUT IOT + +;BLOCK MODE INPUT IOT. +TTYBI: JSP E,INBTCH + +;UNIT MODE INPUT IOT. +;R HAS THE ADDRESS OF THE IOCHNM WORD. +;VALUE RETURNED IN W. +TYI: PUSHJ P,TTYWI ;WAIT FOR THE TTY IF ITS A CONSOLE. TTY NUMBER IN I + HLRZ R,(R) ;GET IOCHNM WORD FLAGS, MODIFIED BY CTL BITS + XOR R,CTLBTS(U) ;R HAS CHANNEL FLAGS + PUSH P,E + PUSHJ P,TYI0 ;GET THE CHAR IN D. + POP P,E + JUMPL D,UNIEOF ;TYI0 RETURN -1 => DON'T FLUSH THE SIGN BIT, AND TERMINATE BLOCK IOT. + ANDI D,%TXPIE+%TXMPE+%TXECI+%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + CAIN A,^C + AOS (P) ;EOF, SKIP RETURN + MOVE W,D + POPJ P, + +;ASSUMING I HAS TTY NUMBER AND R HAS IOCHNM BITS. +;READ A CHARACTER FROM THE TERMINAL AND RETURN IT IN D. +TYI0: MOVE D,TTYTYP(I) + TRNN D,%TYSTY ;SKIP IF TTY IS ALTER EGO OF STY. + JRST TYI1B1 + MOVSI D,%SSINT + TDNE D,STYSTS-NFSTTY(I) + JRST TYI1B1 ;HAVE ALREADY GIVEN INT + SKIPE TICC(I) + JRST TYI1B1 + IORB D,STYSTS-NFSTTY(I) + MOVE TT,STYOMS-NFSTTY(I) ;CHANNELS OPEN FOR OUTPUT ON + AND TT,MSKST2(D) + MOVN B,TT + AND TT,B + IORM TT,IFPIR(D) ;GIVE INT ON LOWEST-NUMBERED CHANNEL. + JRST TYI1B1 + +TYI1B1: TRNE R,%TIACT + JRST TYI1B ;GOBBLE NEXT CHR REGARDLESS OF ACTIVATION + MOVE TT,TTYSTS(I) + TLNE TT,%TSACT + JRST TYI1B + PCLT + SKIPG TACC(I) + PUSHJ P,TYIFLS +TYI1B: PCLT ;WAIT TILL THERE'S A CHAR TO READ. + SKIPG TICC(I) + PUSHJ P,TYIFLS + CONO PI,CLKOFF ;PREVENT ECHOING WHILE WE'RE MESSING WITH POINTERS. + MOVE B,TIOP(I) + MOVE T,B + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB D,B + SKIPN TT,TICC(I) ;CHECK FOR CHAR FLUSHED BY ECHO BEFORE WE TURNED OFF CLOCK. + JRST TYI1A + TRNN D,%TXIGN + JRST TYI1 + TRNN R,%TIECH + TRNN D,%TXPIE + JRST [ PUSHJ P,TYIREM + JRST TYI1A ] + PCLT + CAMN T,TIOP(I) ;WAIT FOR ECHOING TO FLUSH THIS CHAR FROM BUFFER, + PUSHJ P,UFLS +TYI1A: CONO PI,CLKON ;ALLOW ECHOING. + JRST TYI1B1 ;THEN TRY AGAIN TO READ CHAR. + +TYI1: CONO PI,CLKON ;ALLOW ECHOING. + MOVE T,TTYSTS(I) + TLNN T,%TSNOE ;ECHOING BEING DEFERRED OR + TRNE R,%TIECH ;THIS CHANNEL NEEDN'T WAIT FOR ECHO + ANDCMI D,%TXPIE ;=> DON'T. + SKIPE PICLR(U) ;AT INT LVL IN USER PRGM OR + TRNE R,%TIINT ;THIS CHNL NEEDN'T WAIT FOR CHAR TO INTERRUPT + ANDCMI D,%TXINT ;=> DON'T WAIT FOR THAT. + MOVEI T,(D) + ANDI T,%TXINT+%TXPIE ;WAIT FOR THESE BITS TO CLEAR. + TRNE T,%TXINT ;IF ABOUT TO WAIT FOR %TXINT TO CLEAR, + PUSHJ P,TYIIWT ;TAKE CARE OF SEVERAL POSSIBLE SCREWS - MAY SET T. + LDB D,[360600,,B] + LSH T,(D) + PCLT + TDNE T,@B + PUSHJ P,UFLS ;HANG UNTIL PI ECHO BIT FOR THIS CHAR IS TURNED OFF + LDB D,B ;GET CHARACTER + TRNN R,%TIECH ;IF WE AREN'T SUPPRESSING ECHOING, + TRNN D,%TXMPE ;AND M.P. ECHOING NEEDED BUT NOT YET DONE, + JRST TYI2 + MOVE T,TTYSTS(I) + TLNE T,%TSNOE + JRST TYI2 + JRST TYIMP1 ;GO DO IT. + +TYIMP1: PUSH P,R ;DO MAIN-PRGM ECHO IF NECESSARY. + PUSH P,C + PUSHJ P,[MOVEI J,1(P) + ADD P,[3,,3] + HRRZM P,(P) + MOVE TT,TTYEPP(I) + PUSHJ P,NULSET ;NO LOSSET OF IOCHNM + JSP E,TYOSE1 + MOVEI R,%TJECH+%TJMOR + MOVE A,D + ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + JRST TYO6] + POP P,C + POP P,R + CONO PI,TTYOFF + MOVE B,TIOP(I) + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB D,B + TRZ D,%TXMPE ;M.P. ECHOING NO LONGER PENDING FOR THIS CHAR. + DPB D,B + CONO PI,TTYON +TYI2: TRNN R,%TIPEK ;DON'T REMOVE IF CHNL SAYS DON'T. + PUSHJ P,TYIREM ;FINALLY REMOVE CHAR FROM BUFFER. + MOVE TT,TTYCOM(I) + TLNE TT,%TCLED ;DOES THIS JOB WANT TO SEE LOCAL EDITING PROTOCOL + JRST TYI2Z ;REPLIES, ETC.? + MOVE TT,D + ANDI TT,%TXTOP+%TXASC ;NO. DISCARD THEM. + CAIE TT,%TXTOP+"S ;TOP-S AND TOP-E ARE SPECIAL COMMANDS SENT + CAIN TT,%TXTOP+"E ;BY LOCAL EDITING TTYS. + JRST [SKIPG TICC(I) ;IGNORE THE TOP-E OR TOP-S, + PUSHJ P,UFLS ;AND THE CHARACTER AFTER IT AS WELL. + PUSHJ P,TYIREM + JRST TYI1B1] + CAIN TT,%TXTOP+"T ;TOP-T MEANS "LABEL FAILURE" IN LINE SAVING PROTOCOL. + JRST [ MOVEI T,3 ;IGNORE COMMAND AND THREE ARGS. + CAMLE T,TICC(I) + PUSHJ P,UFLS + PUSHJ P,TYIREM + PUSHJ P,TYIREM + PUSHJ P,TYIREM + JRST TYI1B1] +TYI2Z: MOVE T,TTYSTS(I) + TLNE T,%TSCNS + SKIPGE SUPPRO(U) + JRST TYI3 ;DEFERRED CALL IGNORED IF TOP-LEVEL, OR NOT A CONSOLE + CAIN TT,%TXTOP+"Z + JRST [ TRNE R,%TIPEK ;DEFERRED CALL + PUSHJ P,TYIREM ;REMOVE IT IF DIDN'T ALREADY + MOVSI T,(%PIDCL) + JRST UUOER1 ] +TYI3: MOVSI TT,%TSACT + ANDCAM TT,TTYSTS(I) +;TYIFLS CAN COME HERE AFTER THROWING AWAY 1 WORD FROM STACK, FOR NO CHARS AVAIL WITH %TINWT. +TYI4: MOVSI TT,%SSINT ;IF TTY IS STY'S, MAKE SURE NEXT TTY IOT GIVES STY OUTPUT INT. + MOVE B,TTYTYP(I) + TRNE B,%TYSTY + ANDCAM TT,STYSTS-NFSTTY(I) + SKIPGE A,D ;CHAR IN A FOR TYINRM + POPJ P, ;DON'T CANONICALIZE A -1 (NO CHARS AVAILABLE) TO A RUBOUT! + PUSHJ P,TYINRM ;CANONICALIZE TO ASCII UNLESS %TIFUL IS SET. + ANDI D,%TXPIE\%TXMPE\%TXECI ;BUT PRESERVE THE EXTRA INFO BITS + IOR D,A ;WHICH ARE NOT REALLY PART OF THE CHARACTER. + ANDI A,%TXASC + POPJ P, + +;ASSUME R HAS IOCHNM BITS (OR AT LEAST THE %TIFUL BIT). +;TURN CHAR. IN A TO 7-BIT ASCII CHAR IF %TIFUL IS OFF. +TYINRM: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + TRNE R,%TIFUL + POPJ P, + MOVE TT,A ;LEAVE THE HELP CHARACTER ALONE + ANDI TT,%TXTOP+%TXASC ;(THIS USED TO FLUSH THE SUPER ("SHIFT") BIT + CAIN TT,%TXTOP+"H ; PERHAPS IT SHOULD FLUSH ALL OF CTL/MTA/SUP?) + POPJ P, +TYINR2: ANDI A,%TXCTL+%TXASC ;FLUSH THE EXTRA BITS. + TRZE A,%TXCTL ;DON'T WANT FULL CHAR SET: TURN CTL+X INTO ASCII CTL-X + CAIN A,177 ;BUT LEAVE CTL-RUBOUT AS RUBOUT, FOR TECO'S SAKE. + POPJ P, + CAIGE A,77 ;CTL-? => RUBOUT + JRST [ CAIN A,40 ;CTL-SPACE => CTL-@ + MOVEI A,^@ ;41-76 STAY THE SAME + POPJ P, ] ;LETTERS TURN INTO ASCII CONTROLS + CAIL A,140 ;TO CONTROLIFY, FIRST TURN LOWER CASE TO UPPER, + SUBI A,40 + XORI A,100 ;THEN TOGGLE 100 BIT, TURNING A INTO ^A AND ? INTO RUBOUT. + POPJ P, + +;REMOVE THE FIRST CHAR. FROM THE INPUT BUFFER, AND RETURN IT IN D. +;UPDATES ALL COUNTS AND POINTERS. HALTS IF BUFFER EMPTY. +;CLOBBERS B,TT. +TYIREM: CONO PI,TTYOFF + PUSHJ P,TYIRE1 + JRST TTYONJ + +TYIRE1: SOSGE TICC(I) ;ENTRY WHEN TTYCHN IS OFF. + BUG PAUSE,[TTY: BUFFER EMPTY AT TYIREM] + MOVE B,TIOP(I) ;SAVE COPY OF BUFFER-EMPTYING POINTER IN TT. + MOVE TT,B + CAMN B,TIBEP(I) ;ADVANCE THE POINTER, FETCHING THE CHARACTER. + SUBI B,TIBL + ILDB D,B + MOVEM B,TIOP(I) + TRNE D,%TXACT ;IF CHAR SAYS IT WAS AN ACTIVATION CHAR, UPDATE # OF ACTIVATION + SOS TACC(I) ;CHARS STILL INB THE BUFFER. + TRNE D,%TXPIE ;IF IT NEEDED PI ECHO, + SOS ECHOC(I) ;ONE FEWER CHAR AWAITS PI ECHO. + TRNE D,%TXINT + SOS TINTC(I) ;SIMILAR FOR INT. TO PROGM. + SKIPL TINTC(I) + SKIPGE ECHOC(I) + BUG PAUSE,[TTY: TINTC OR ECHOC OVER-DECREMENTED] + CAMN TT,ECHOP(I) ;IF ECHOP POINTED AT THIS CHAR, + MOVEM B,ECHOP(I) ;ADVANCE IT. + CAMN TT,TINTP(I) ;SIMILAR FOR TINTP + MOVEM B,TINTP(I) + POPJ P, + +;COME HERE WHEN ABOUT TO WAIT FOR A CHAR'S %TXINT TO CLEAR OUT. +;CLOBBERS D, TT; MAY ZERO %TXINT IN T, IN WHICH CASE CALLER SHOULD +;NOT BOTHER TO WAIT FOR %TXINT TO CLEAR. +TYIIWT: MOVE D,MSKST2(U) + AND D,TYIMSK(I) ;D GETS ENABLED TTY INPUT CHANNELS. + MOVE TT,D + ANDCM TT,IDF2(U) ;TT GETS ENABLED, UNDEFERRED TTY INPUT CHANNELS. + TDNE TT,IFPIR(U) ;IF AN INTERRUPT IS PENDING ON ONE OF THEM, %TXINT + POPJ P, ;WILL CLEAR IF WE LET THE INT. HAPPEN. + MOVN TT,D ;ELSE GET LOWEST NUMBERED ENABLED INPUT CHANNEL'S BIT + AND D,TT + AND D,IDF2(U) ;IF THAT CHANNEL ISN'T DEFFERED, + IORM D,IFPIR(U) ;REQUEST AN INTERRUPT ON IT, AND WE CAN STILL WIN. + JUMPN D,CPOPJ + ANDCMI T,%TXINT ;CAN'T RQ AN INT, SO BIT WON'T BE CLEARED, IT IS CERTAIN, + POPJ P, ;SO GIVE UP ON WAIITING FOR IT TO CLEAR. + +;COME HERE TO HANG UP FOR INPUT. LIKE UFLS BUT PREVENTS +;A **MORE** THIS TIME AROUND THE SCREEN, ON GROUNDS THAT USER +;HAS COMMANDED THE OUTPUT FOR 1 MORE PAGE AT LEAST. +;IF %TINWT IS SET, INSTEAD OF HANGING, THROW AWAY RETURN ADDRESS +;AND JUMP TO TYI4, TO RETURN -1 FROM THE IOT. +;CLOBBERS A,D,H. +TYIFLS: TRNE R,%TINWT + JRST [ SUB P,[1,,1] + SETO D, + JRST TYI4] +;ENTER HERE FROM ECHOIN - R IS NOT MEANINGFUL. +TYIFL2: MOVE H,TTYOPT(I) + TLNE H,%TOMVU ;THIS DOESNT APPLY TO ARDS-LIKE DISPLAYS + TLNE H,%TOERS + SKIPA D,I + JRST UFLS + IMULI D,TPLEN*2 + MOVEI A,%TFEOP + ANDCAM A,TPFLAG(D) ;CLEAR PENDING MORE + HLL D,TTYSTS(I) + MOVE A,TCMXV(I) .SEE TPVE;(D) + TLNE H,%TOMVU ;PRINTING TTY'S AND DISPLAYS IN SCROLL MODE + TLNE D,%TSROL ;DO ONE THING. + JRST TYIFL1 + CAME A,TPVB+TPLEN(D) ;FOR WRAP-AROUND DISPLAYS, + JRST UFLS ;IF NOT USING AN ECHO AREA, + MOVEI A,6 ;PREVENT MORES FOR THE NEXT 6 LINES. + MOVEM A,TPVM(D) + JRST UFLS + +TYIFL1: SUB A,TTYROL(I) ;IN SCROLL MODE, **MORE** WHEN THIS LINE GOES OFF THE SCREEN. + MOVEM A,TPVM(D) + JRST UFLS + +SUBTTL TTY OUTPUT IOT + +;THESE PUSHED BY TYOSET, REFERENCED INDEX OF J. +TYOPV0==0 ;COUNT OF NUMBER OF CHARACTERS THAT WE CAN TAKE A SHORTCUT FOR, + ;IN SUPERIMAGE MODE SIOT. +;TYOPV1 UNUSED, BUT SPACE ALLOCATED. +TYOPV2==2 ;-> IOCHNM WORD OF CHANNEL IOT IS ON. +TYOPV3==3 ;PC PPR IDX,,TTY #. + + +;TO OUTPUT TO A TTY (R -> IOCHNM WD OF TTY CHNL) +; JSP E,TYOSET ;WAIT TILL JOB HAS TTY AND OUT OF COM MODE, +; ;INIT FOR PCLSRING, PUSH VARS ON STACK. +; JRST IGNORE ;TYOSET RETURNS HERE IF THIS OUTPUT SHOULD BE DISCARDED. +; ... ;OUTPUT 1 OR MORE CHARS TO TTY +; ;MEANWHILE, J -> BLOCK OF 4 STACK VARS. +; POPJ P, ;RETURNS TO TYOUNS TO FLUSH STACK, ETC. + +TYOSET: PUSHJ P,TTYWO ;WAIT TILL THIS JOB HAS OUTPUT PERMISSION. + JRST (E) ;RETURN IF OUTPUT BEING IGNORED. + AOS E ;SKIP THAT RETURN IF WE ARE GOING TO DO THE OUTPUT. + JUMPN U,TYOSE3 + MOVEI T,TYOWNC ;FOR SYSTEM JOB, CHECK TTOALC WITH A TIMEOUT IN CASE + SKIPL TTOALC(I) ;THE TTY IS FORGETTING TO TURN TYPEOUT BACK ON. + PUSHJ P,TYOW2 + JRST TYOSE4 ;NOTE THAT TYOW2 CAN POP1J. + +TYOSE3: SKIPL TTOALC(I) ;^\ CAN DELAY TYPEOUT AT M.P. LEVEL THROUGH SIGN OF TTOALC. + PUSHJ P,UFLS ;ALSO USED BY OUTPUT RESET ON SOFTWARE TTY. +TYOSE4: MOVEI J,1(P) ;PROVIDE SPACE FOR TEMPS, WHERE FINSET CAN FIND THEM. + ADD P,[2,,2] + PUSH P,R .SEE TYOPV2 + MOVE H,TTYOPT(I) + MOVSI T,%TCLFT+%TCOCO+%TCICO + SKIPGE TTYCOM(I) + PUSHJ P,TTYCMW ;WAIT TILL TTY IS NOT IN COM MODE, OR OVER-RIDDEN. + CONO PI,TTYON + MOVEI A,%TJCNS+77+%TJCP1+%TJCP2+%TJSTP+%TJINK ;DON'T LET THESE IOCHNM BITS BE CHANGED + ANDCAB A,CTLBTS(U) ;EVEN TEMPORARILY. + HRLZS A ;ELSE, IF A BIT IS SET IN THE CTL BITS, + XORB A,(R) ;CHANGE IT (TEMPORARILY) IN IOCHNM WORD. + PUSHJ P,LOSSET ;SET UP ROUTINE TO UNDO THAT TEMPORARY CHANGE + [MOVE A,AC0S+J(U) ;IF WE SHOULD PCLSR OUT + HLRZ T,@TYOPV2(A) + XOR T,CTLBTS(U) + HRLM T,@TYOPV2(A) + POPJ P,] + HLRZS A + TRNE A,%TJSTP ;IF WE ARE HUNG IN A **MORE**, WAIT TILL THERE'S A CHARACTER + PUSHJ P,TYOSMR ;IT'S IMPORTANT WE WAIT WITOUT TYOSW SET - ELSE NO ECHOING! + MOVE TT,I ;NOW MAKE TT -> APPRO. PC PPR FOR THIS CHNL. + IMULI TT,TPLEN*2 + TRNE A,%TJPP2 + MOVE TT,TTYEPP(I) +TYOSE1: PCLT ;ENTER HERE FROM INPUT IOT WHEN DOING M.P. ECHOING + AOSE TYOSW(I) ;SEIZE THIS TTY FOR MP LEVEL. + JRST [SKIPL TYOSW(I) + PUSHJ P,UFLS + JRST .-1] + PUSHJ P,LSWDEL ;THEN SET UP LOSSET ROUTINE FOR BOTH TYOSW AND + PUSHJ P,LOSSET ;PREVIOUSLY-LOSSET'ED CHANGE TO IOCHNM BITS. + [MOVE A,AC0S+J(U) + HLRZ T,@TYOPV2(A) + XOR T,CTLBTS(U) + HRLM T,@TYOPV2(A) + MOVE A,TYOPV3(A) + SETOM TYOSW(A) + POPJ P,] + CAMN TT,TTYLPP(I) ;IF TTY IS ASSOCIATED W/ ANOTHER PC PPR, + JRST TYOSE2 + PUSH P,TT + SKIPL TT,TTYLPP(I) + PUSHJ P,TYOMVC ;DISASSOCIATE THEM. + POP P,TT + SETCAM TT,TTYLPP(I) +TYOSE2: PUSH P,I .SEE TYOPV3 + HRLM TT,(P) + MOVE Q,TTYCOM(I) + TLNE Q,%TCECH ;IF THERE'S ECHOING OUTPUT IN OUTPUT BUFFER, + JRST [ PCLT ;WAIT FOR IT TO GET PRINTED. MUSTN'T HAVE ECHO AND + PUSHJ P,TYOWC ;OUTPUT IN THE OUTPUT BUFFER AT ONE TIME. + MOVSI Q,%TCECH + ANDCAB Q,TTYCOM(I) + JRST .+1] + TLNE Q,%TCMTR ;IF THIS TTY IS A TERMINET & ITS MOTOR IS OFF, + PUSHJ P,TTTMTO ;TURN THE MOTOR ON BEFORE OUTPUT. + PUSHJ P,(E) + +TYOUNS: CAIA ;IF WE ARE SKIPPED INTO, PROPAGATE THE SKIP. + AOS -4(P) + SUB P,[4,,4] + +TYOUN1: HRLZ R,CTLBTS(U) ;UNDO TEMPORARY CHANGES IN IOCHNM WD. + XORM R,@TYOPV2(J) + PUSHJ P,LSWDEL + SKIPGE TTYERQ(I) ;IF ECHOING ISN'T ALREADY REQUESTED, + SKIPL TTYLPP(I) ;AND THERE IS BUFFERED CURSOR POSITIONING, + JRST TYOUN3 + CONO PI,TTYOFF + MOVEI J,TTEDMY ;SO TYOFNR WON'T CLOBBER RANDOMNESS. + SETCM TT,TTYLPP(I) ;TT -> PC PPR TTY WAS DISSOCIATED FROM. + MOVE H,TTYOPT(I) + MOVE A,TORM(I) + CAIN A,TOBS ;AND IT CAN BE DONE NOW, + PUSHJ P,TYOFRC ;FORCE OUT BUFFERED CURSOR MOTION. + SETOM TYOSW(I) + JRST TTYONJ + +TYOUN3: SETOM TYOSW(I) ;RELEASE TTY. + POPJ P, + +;WAIT TILL THERE'S A TTY INPUT CHARACTER. +TYOSMR: PUSH P,A + PUSH P,R + MOVEI R,%TIACT+%TIECH+%TIPEK + PUSHJ P,TYI0 + POP P,R + JRST POPAJ + +;OUTPUT IOT + +;BLOCK MODE. +TTYBO: JSP E,TYOSET + JRST TTYBOI + JSP E,NBTOCH +TTYBO3: CAIN A,EOFCH + POPJ P, + PUSH P,TT + PUSHJ P,TTYBO1 + POP P,TT + MOVEI E,TTYBO3 + POPJ P, + +;IGNORE SOME BLOCK MODE OUTPUT. +TTYBOI: XCTR XRW,[MOVES D,(C)] + TLO D,700000 + HLRE A,D + MOVNS A + HRLS A + ADD D,A ;COUNT THE AOBJN POINTER ALL THE WAY OUT. + XCTR XRW,[MOVEM D,(C)] + POPJ P, + + JRST TYOBP ;SIOT DISPATCH IS -1 + ADDR. OF UNIT MODE ROUTINE. +;UNIT MODE TTY OUTPUT. +TYO: JSP E,TYOSET + POPJ P, ;JUST RETURN IF WE ARE SUPPOSED TO DISCARD THE OUTPUT. + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +;MUSTN'T CLOBBER C OR D. +TTYBO1: HLRZ R,@TYOPV2(J) ;RH(R) GETS LH(IOCHNM WD) + HRRZ I,TYOPV3(J) + HLRZ TT,TYOPV3(J) +TYOBP2: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + SKIPGE E,TTYCOM(I);IN COM MODE W/ LOCAL FEED THRU, + TLNN E,%TCLFT + JRST TYO6 + PUSH P,C + PUSH P,D + PUSH P,U + PUSH P,TT ;ECHO CHAR ON ALL TTYS IN LOOP + PUSH P,R ;THAT HAVE REMOTE-FEED-THRU. + PUSHJ P,TYCREP ;DO FOLLOWING INSN FOR EACH TTY IN LOOP. + PUSHJ P,TYO7 ;(# OF TTY DOING IT FOR PUT IN I) + JFCL ;(TYCREP WILL SKIP IF THAT INSN ALWAYS DOES) + POP P,R + POP P,TT + POP P,U + POP P,D + POP P,C + JRST TYO6 + +TYO7: MOVE D,TTYCOM(I) ;IF THIS TTY WANTS MY TYPEOUT. + TLNE D,%TCRFT + CAMN I,-2(P) ;AND IF IT ISN'T ME, + JRST POPJ1 + PUSHJ P,TYCSET ;SET UP ACS Q,R,U FOR TTY TO ECHO ON. + CONO PI,TTYOFF + PUSH P,A + PUSHJ P,TTYI13 ;ECHO CHAR ON THIS TTY. + CONO PI,TTYON + JRST POPAJ1 + +;SIOT ROUTINE FOR TTY OUTPUT - JUST LIKE REPEATED UNIT MODE, +;BUT MOVES THE TYOSET OUTSIDE THE LOOP TO SAVE TIME. +TYOBP: MOVEM B,SRN3(U) ;SAVE B, C; CAN'T USE STACK SINCE TYOSET PUSHES. + MOVEM C,SRN4(U) + JSP E,TYOSET ;SET UP FOR DOING TTY OUTPUT. + JRST TYOBPI ;RETURN HERE IF WE SHOULD DISCARD THE OUTPUT + HLRZ R,@TYOPV2(J) ;FOR TYOFRC + CAME TT,TTYLPP(I) + TRNN R,%TJSIO ;ONLY IN SUPER-IMAGE MODE, + CAIA + PUSHJ P,TYOFRC ;FORCE OUT ALL PREVIOUS MAIN PROGRAM CURSOR MOTION + MOVE B,SRN3(U) ;BE JUST LIKE ORDINARY REPEATED-UNIT-MODE SIOT, + MOVE C,SRN4(U) ;EXCEPT THAT THE TYOSET IS OUTSIDE THE LOOP. + SETOM TYOPV0(J) ;CAN'T TAKE SHORTCUT AT FIRST. + MOVE D,[%IOTOT,,.+2] + JRST NSIOT1 ;SIOT ROUTINE WILL COME BACK FOR EACH CHAR, PRESERVING I,J,TT + HLRZ R,@TYOPV2(J) + MOVE A,D ;PUSHJ HERE FOR EACH CHARACTER. + SOSG TYOPV0(J) ;PERHAPS THE PREVIOUS CHARACTER DISCOVERED WE CAN + ;START TAKING THE SHORTCUT. + JRST TYOBP2 ;IF NOT, DO THE WHOLE PILE OF WORK. + ANDI A,%TXDIS+%TXASC + SKIPGE E,TTYCOM(I) + TLNN E,%TCLFT ;SHORT CUT IS TO PUT THE CHARACTER RIGHT IN THE OUTPUT BUFFER. + JRST TYONCC ;MAY BE USED ONLY FOR SUPERIMAGE OUTPUT. + JRST TYOBP2 ;AND BETTER NOT BE IN COM MODE WITH LOCAL FEED THRU. + +;IGNORE THIS STRING OF OUTPUT; TELL THE USER WE OUTPUT IT. +TYOBPI: MOVE B,SRN3(U) + MOVE C,SRN3(U) + UMOVE T,(B) + UMOVE TT,(C) + JUMPE C,POPJ1 + IBP T + SOJG TT,.-1 + XCTR XRW,[MOVEM T,(B)] + XCTR XRW,[MOVEM TT,(C)] + JRST POPJ1 + + +;A USUALLY HOLDS THE CHAR BEING IOTTED, OR THE CHAR TO BE PUT IN BUFFER. +;B IS A TEMP. +;C IS USUALLY UNUSED, AND MUSTN'T BE CLOBBER BY IOT RTN. +;D " +;E IS A TEMP. +;TT HOLDS THE INDEX OF THE PC PPR BEING USED. +;I HOLDS THE TTY NUMBER. +;H HOLDS THE TTY'S TTYOPT WORD. +;J HOLDS THE INDEX OF A 4-WORD BLOCK USUALLY ON THE STACK +; INDEX USING TYOPV0, TYOPV1, TYOPV2, TYOPV3. +;T IS A TEMP. +;R'S RH HOLDS THE IOCHNM WORD'S LH. +;Q HOLDS THE BP FOR STORING IN OUTPUT BUFFER. +; INITTED FROM TOIP, AND STORED BACK IN TOIP WHEN FINALIZED. + +TYO6: PCLT + MOVEI T,TYOWNC ;MAKE SURE AT LEAST TYOWNC + CAML T,TORM(I) ;CHARS OF SPACE LEFT IN OUTPUT BUFFER. + PUSHJ P,TYOW2 ;NOTE THIS CAN POP1J. SO CAN TYOWN. + MOVE H,TTYOPT(I) +IFN N11TYS,[ + TRNN H,%TP11T ;FOR A PDP11 TV TTY, + JRST TYO8 + SKIPL TT11P ;IGNORE IT IF PDP11 ISN'T UP. + POPJ P, + PUSHJ P,TYOWN ;WAIT TILL AT LEAST TYOWNC CHARS SPACE. +] ;(TORM HAS NO INFO ON TV TTYS). +;A,R,I,TT,H,J SET UP AT THIS POINT. +;ENTER HERE FROM PI LEVEL TO ECHO CHARS +TYO8: MOVE Q,TOIP(I) ;GET COPY OF BP TO STORE WITH. + ;WHEN OUTPUTTING CHARS, WILL UPDATE Q INSTEAD TOIP. + ;THEN, WHEN CAN NO LONGER PCLSR, DO TOIP(I)_Q. + MOVE B,TPFLAG(TT) +TYOIG1: TRNE B,%TFEOP+%TFIGL ;ANY EXCEPTIONAL CONDITION FOR THIS PC PPR? + JRST TYOIGL ;IF SO, HANDLE IT. +TYOEO9: TRNE R,%TJCP1+%TJCP2+%TJSTP+%TJSIO+%TJINK + JRST TYOCP1 ;HANDLE ANY EXCEPTIONAL CONDITION FOR CHANNEL. + TRNE A,%TXCTL+%TXMTA+%TXSUP+%TXTOP + JRST TYOMTA ;TAKE CARE OF FUNNY BITS IN CHARACTER. +TYOMT9: CAILE A,40 + JRST TYONRM ;PRINTING CHARS AND RUBOUT. + CAIN A,40 + JRST TYOSPC ;SPACE MAY BE EITHER PRINTING OR CURSOR MOTION. + CAIL A,^G ;< ^G OR > ^S => NORMAL CTL CHAR, +IFE 0, CAIL A,^Q ;RIGHT NOW, ^S USES %TGIMG OF GROUP 0. +IFN 0, CAIL A,^T ;BUT FOR INPUT, IT USES GROUP 6. THIS INSN MAKES IT USE GROUP 6 FOR OUTPUT TOO. + JRST TYOCTL + JRST @.+1-^G(A) ;ELSE DO WHAT THIS PARTICULAR ONE WANTS. + + TYOBEL ;^G DOESN'T MOVE CURSOR. + TYOBS ;^H MOVES BACKWARDS. + TYOTAB ;^I MOVES TO TAB STOP. + TYOLF ;^J IS LINEFEED. + TYOCTL ;^K IS NORMAL. + TYOFF ;^L MAY CAUSE A **MORE** + TYOCR ;^M IS A CARRET + TYOCTL ;^N IS NORMAL + TYOCTL ;^O IS NORMAL + TYOCTP ;^P MAY SIGNIFY A CURSOR CTL CODE. + TYOCTL ;^Q IS NORMAL + TYOCTL ;^R IS NORMAL + TYOCTS ;^S IS NORMAL EXCEPT USES A DIFFERENT GROUP'S %TGIMG. + +;OUTPUT CHARACTER IN SUPERIMAGE MODE. +TYOSIO: ANDI A,377 + MOVEI B,TYOWNC ;IF WE'VE GOT THIS FAR, THEN THERE'S AT LEAST TYOWNC CHARS OF SPACE, + CAME TT,TTYLPP(I) ;IF DISSOCIATED, + PUSHJ P,[ + PUSH P,Q + PUSHJ P,TYOASS ;ASSOCIATE, + POP P,T + CAME T,Q ;AND IF THAT REQUIRED OUTPUT, + SUBI B,5 ;THAT'S SO MANY FEWER CHARS BEFORE TIME TO CHECK TORM AGAIN. + POPJ P,] + MOVEM B,TYOPV0(J) ;AND NO UNUSUAL CONDITIONS, SO SIOT CAN GO FAST FOR A WHILE. +;OUTPUT A CHAR WITH NO CURSOR CONTROL. +;ASSUMES ITS POSITION DOESN'T MATTER. +TYONCC: PUSHJ P,TYOOUT + JRST TYOFN2 + +;COME HERE WHEN ^P IS OUTPUT. +TYOCTP: TRNN R,%TJDIS ;IS THIS OUTPUT CHNL TREATING ^P SPECIALLY? + JRST TYOCTL ;NO, TREAT ^P AS NORMAL CTL CHAR. + TRO R,%TJCP1 ;YES, SAY TREAT NEXT CHAR AS CURSOR CODE. + JRST TYOFNR + +;COME HERE TO OUTPUT A ^S. +TYOCTS: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;PREPARE TO OUTPUT PRINTING CHARACTERS. + HLLZ T,TTYST2(I) ;GET THE RELEVANT %TGIMG BIT. + TLZ T,#<%TGIMG_12.> + JRST TYORU2 + +;HERE TO OUTPUT ^G +TYOBEL: MOVEI A,%TDBEL + JRST TYONCC + +;COME HERE FOR ^PP - OUTPUT A ^P. +TYOCPP: SKIPA A,[^P] + +;COME HERE FOR ^PQ TO OUTPUT A ^C. +TYOCPQ: MOVEI A,^C + +;COME HERE FOR NORMAL (NON-FORMATTING) CONTROLS. +TYOCTL: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;PREPARE TO OUTPUT PRINTING CHARACTERS. + CAIN A,33 + JRST TYOALT ;CHECK FOR ALTMODE. + HLLZ T,TTYST1(I) ;GET THE "OUTPUT IN IMAGE MODE" BIT THAT'S RELEVANT. + TLZ T,#<%TGIMG_12.> +TYORU2: TRNE R,%TJECH ;ECHO-MODE OUT => PRINT IN ASCII MODE. + JRST TYOCT1 + MOVE B,TTYSTS(I) + TLNE B,%TSSAI ;SHOULD USE SAIL CHAR SET FOR OUTPUT => DO SO. + JRST TYONR0 + JUMPN T,TYOAL1 ;IF "OUTPUT IN IMAGE" IS SET, GO DO SO. +TYOCT1: HRLM A,(P) ;ELSE OUTPUT CTL CHAR IN ASCII MODE, + MOVEI A,"^ ;AS "^" FOLLOWED BY UN-CTL'ED CHAR. + TLNE H,%TOSAI + MOVEI A,13 ;IF TTY HAS SAIL MODE, USE A SAIL UPARROW. + PUSHJ P,TYONR1 + HLRZ A,(P) + XORI A,100 + JRST TYONR0 + +TYOAL1: TLNN H,%TOSAI + JRST TYORU1 + JRST TYONR0 + +;HANDLE CHARACTERS WHICH HAVE %TXCTL, %TXMTA, %TXSUP OR %TXTOP SET. +TYOMTA: MOVE B,TTYSTS(I) + TLNN B,%TSFCO ;IF USER DOESN'T WANT FULL CHAR SET OUTPUT, + JRST TYOMT4 ;IGNORE THE META BITS (USUALLY). + TRNE A,%TXCTL + PUSHJ P,TYOMT1 ;ECHO AN ALPHA FOR %TXCTL. + TRZE A,%TXMTA + PUSHJ P,TYOMT2 ;TYPE A BETA FOR %TXMTA + TRZE A,%TXSUP + PUSHJ P,TYOMT5 + TRZN A,%TXCTL+%TXTOP ;IF CTL OR TOP IS SET, THE CHARACTER + JRST TYOMT9 + CAIN A,40 ;ISN'T AN ASCII CONTROL CHAR EVEN IF < 40 + JRST TYOSPC ;(BTW, SPACE IS STILL SPACE) + CAIE A,177 + CAIG A,40 +TYOMT3: TLNE H,%TOSAI + JRST TYONRM + CAME TT,TTYLPP(I) ;WE HAVE WHAT WOULD OTHERWISE BE AN ASCII CTL CHAR. + PUSHJ P,TYOASS + CAIN A,33 + JRST TYOAL3 + JRST TYOCT1 + +TYOMT5: MOVEI B,6 ; EPSILON + JRST TYOMT6 + +TYOMT1: SKIPA B,[2] ; ALPHA +TYOMT2: MOVEI B,3 ; BETA +TYOMT6: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + PUSH P,A + MOVE A,B + PUSHJ P,TYONR1 + JRST POPAJ + +TYOMT4: TRNN R,%TJECH ;FOR OUTPUT, IGNORE THE META BITS. FOR ECHO, + ANDI A,%TXASC ; TRY TO ECHO WHAT THE GUY TYPED. + TRNE A,%TXTOP ;IF TOP IS ON, + TLNN H,%TOSAI ;AND THE TTY HAS THE SAIL CHAR SET, + TRZA A,%TXMTA+%TXSUP+%TXTOP + JRST TYONR3 ;ECHO THE CHAR USING SAIL CHAR SET. + PUSHJ P,TYINR2 ;ECHO AS WHAT PROGRAM SEES + JRST TYOMT9 ;ALSO HACKS SUCH AS ^L MAY CLEAR THE SCREEN + +;HANDLE SPACE: ON OVERPRINTING TERMINALS, SPACE = ^PF. +;ON IMLACS, SPACE = SPACE BECAUSE THE IMLAC PROGRAM LOSES FOR ^PF AT END OF LINE. +;ON RAW TERMINALS, SPACE OF COURSE GOES OUT AS SPACE. +;ON OTHER TERMINALS, SPACE = SPACE. THIS IS A CROCK, BUT IT IS NECESSARY +;BECAUSE ^PF TAKES 6 TIMES AS LONG ON DATAPOINTS BECAUSE OF PADDING, +;AND TWICE AS LONG ON VT52S BECAUSE IT TAKES TWO CHARACTERS. + +TYOSPC: TLNN H,%TOOVR ;NON-OVERPRINTING => OUTPUT A REAL SPACE. + JRST [ TLNE H,%TOMVU + JRST TYONRM + HLRE B,TTYLPS(I) ;BUT ON GLASS TTY'S (NON-OVERPRINTING, NO UPWARD MOTION) + CAMGE B,TPVP(TT) + JUMPGE B,.+1 ;IT IS SAFE TO TREAT SPACES AS CURSOR MOTION + JRST TYONRM] ;IF THEY ARE GOING TO FOLLOW DOWNWARD MOTION ANYWAY. + TLNE H,%TORAW+%TOIML ;IMLAC, OR NO OPTIMIZATION => OUTPUT A REAL SPACE. + JRST TYONRM ;NORMAL CHARACTER. + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPHP(TT) ;MOVE FORWARD 1 POS. + CAML B,TCMXH(I) .SEE TPHE;(TT) + TRNE R,%TJCTN + JRST TYOFNR + SOS TPHP(TT) ;IF NECESSARY, CONTINUE TO NEXT LINE AND RETRY. + PUSHJ P,TYOCTN + JRST TYOSPC + +TYONR3: ANDI A,%TXASC +;OUTPUT A NORMAL CHARACTER, AND FINALIZE. COME HERE FOR +;NORMAL CHAR ACTUALLY IOTTED. +TYONRM: CAME TT,TTYLPP(I) ;ABOUT TO OUTPUT PRINTING CHARS SO + PUSHJ P,TYOASS ;FORCE ANY CURSOR MOTION INTO OUTPUT BFR + CAIN A,177 + JRST TYORUB + +;CALL HERE TO OUTPUT NORMAL CHAR, IF CURSOR POSITIONING KNOWN +;NOT TO BE NECESSARY. +TYONR0: PUSH P,[TYOFNA] ;CAUSE FINALIZATION WHEN FINISHED. + +;CALL HERE TO OUTPUT NORMAL CHAR AS PART OF TASK OF OUTPUTTING +;SOME LARGER GROUP. DOESN'T FINALIZE, IN CASE WE PCLSR LATER. +TYONR1: AOS B,TPHP(TT) ;ADVANCE CURSOR OF PC PPR 1 SPACE. + CAML B,TCMXH(I) .SEE TPHE;(TT) ;NOT YET AT END OF LINE => OUTPUT CHAR. + TRNE R,%TJCTN ;AT END: NO CONTIN => OUTPUT, + JRST TYOOUT + PUSHJ P,TYONR2 ;CONTINUE THE LINE (NOTE CURSOR POS FOR + CAME TT,TTYLPP(I) ;THE "!" WAS ALREADY DONE) + PUSHJ P,TYOASS ;TYONR2 DISSOCIATED THE TTY + JRST TYONR1 ;BUT TYONR1 NEEDS IT ASSOCIATED. + +;TYPE "!" TO CONTINUE A LINE. +;THIS FINALIZES THE !CRLF BUT ALSO REMOVES THE CONDITIONS WHICH +;CAUSED IT TO BE CALLED; SO PCLSRING IS NO PROBLEM. +;LEAVES TTY DISSOCIATED FROM PC PPR. +TYOCTN: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + AOS TPHP(TT) ;ACCOUNT FOR THE "!". +TYONR2: PUSH P,A + MOVEI A,"! ;PUT "!" IN OUTPUT BUFFER, + PUSHJ P,TYOOUT + PUSHJ P,TYORCR ;AND GO TO NEXT LINE. + PUSHJ P,TYOLF + MOVE B,TPFLAG(TT) ;IF THAT LF TOOK US TO LAST LINE, + TRNE B,%TFEOP + JRST TYOEO5 ;DO **MORE** PROCESSING IF NEC. + JRST POPAJ ;AND RETRY WHATEVER CAUSED CONTINUATION. + +;COME HERE TO OUTPUT A RUBOUT. +TYORUB: TRNN R,%TJECH + JRST TYORU3 + TLNN H,%TOERS ;RUBOUT ON A DISPLAY CONSOLE ECHOES AS DELETE BACKWARDS. + TLNN H,%TOOVR ;LIKEWISE ON A GLASS TTY + JRST TYODLB +TYORU3: MOVE T,TTYST2(I) + ANDI T,%TGIMG_6 ;GET RUBOUT'S "OUTPUT IN IMAGE MODE" BIT. + JRST TYORU2 + +;COME HERE TO OUTPUT A LF. FINALIZES. LEAVES TTY DISSOCIATED. +TYOLF: CAMN TT,TTYLPP(I) ;BEFORE MUNGING PC PPR'S CURSOR POS, + PUSHJ P,TYOMVC ;MUST DISASSOCIATE TTY'S POS FROM PC PPR. + SOS TPVM(TT) ;COUNT DOWN # LINES TILL NEXT **MORE**. + AOS B,TPVP(TT) ;MOVE PC PPR'S CURSOR 1 LINE DOWN. + CAIG B,118. ;DON'T LET VPOS ON PRINTING TTY GET TOO BIG. + CAML B,TCMXV(I) .SEE TPVE;(TT) ;END OF RANGE => GO TO TOP OR SCROLL. + JRST TYOLFE +TYOLF0: MOVE A,TTYSTS(I) + TLNE A,%TSMOR ;IF **MORE** DESIRED, + JRST TYOLF1 + ADDI B,1 ;THEN IF ENTERING LAST LINE OF RANGE, + CAME B,TCMXV(I) .SEE TPVE;(TT) + JRST TYOLF1 + SKIPGE TPVM(TT) ;UNLESS NOT TIME YET, + SKIPA B,[%TFEOP] ;TELL NEXT OUTPUT ATTEMPT TO CAUSE **MORE**. +TYOLF1: SETZ B, + PUSH P,B + TLNE H,%TORAW + JRST [ MOVEI A,%TDLF ;NO OPTIMIZATION => + PUSHJ P,TYOOUT ;OUTPUT A REAL LF (PLUS PADDING) + PUSHJ P,TYOMVC + JRST TYOLF5] + TLNN H,%TOERS ;IF TTY HAS SELECTIVE ERASE, + JRST TYOLF5 + PUSH P,TPHP(TT) + PUSHJ P,TYORCR ;GO TO BEGINNING OF LINE + HLRZ B,TTYLPS(I) ;IF CR AND LF AND CLR-EOL ARE EXACTLY + ADDI B,1 ;WHAT WE NEED, + CAMN B,TPVP(TT) + SKIPN TTYROL(I) ;AND TTY CAN DO IT, DO THEM ALL AT ONCE. + SKIPA A,[%TDEOL] ;OTHERWISE, OUTPUT MOVE-CURSOR AND %TDEOL. + SKIPA A,[%TDCRL] ;OUTPUT %TDCRL = %TDMOV AND %TDEOL TOGETHER. + PUSHJ P,TYOASS + PUSHJ P,TYOOUT + PUSHJ P,TYOMVC + POP P,TPHP(TT) +TYOLF5: POP P,B + IORM B,TPFLAG(TT) + JRST TYOFND + +;LINEFEED THAT WRAPS AROUND. +TYOLFE: MOVE A,TTYSTS(I) + TLNN H,%TOMVU ;END OF SCREEN ON PRINTING TTY => SCROLL BY 1. + JRST TYOLF2 + TLNE A,%TSROL ;DISPLAY IN SCROLL MODE? + SKIPE TPVB(TT) ;CAN'T SCROLL UNLESS PC PPR IS WHOLE SCREEN. + JRST TYOLF3 +TYOLF2: MOVN A,TTYROL(I) ;A GETS - # LINES TO SCROLL AT ONCE. + JUMPE A,TYOLF3 ;JUMP IF THIS TTY CAN'T SCROLL + SOS TPVP(TT) + PUSH P,TPHP(TT) + HRRZ B,TTYLPS(I) + MOVEM B,TPHP(TT) + PUSHJ P,TYOASS ;MOVE CURSOR DOWN TO LAST LINE ON SCREEN, PREPARING FOR SCROLL + PUSHJ P,TYOMVC + POP P,TPHP(TT) + AOS TPVP(TT) +;SCROLL: A HAS -<# LINES TO ADJUST ALL VPOS'S BY>. +TYOLF6: HLRZ B,TTYLPS(I) ;COMPUTE NEW TTYLPS LH. + ADD B,A + JUMPGE B,TYOLF7 ;IF IT WOULD BE NEGATIVE, + TLNN H,%TORAW ;ON DISPLAY WRAP AROUND INSTEAD (LOSSAGE HAPPENING). + JRST TYOLF3 + SETZ B, ;IN RAW MODE, DON'T WORRY ABOUT IT. +TYOLF7: HRLM B,TTYLPS(I) ;STORE UPDATED M.P. VPOS. + ADDM A,TPVP(TT) ;CHANGE OTHER MAIN PRGM VPOS'S. + MOVE B,TPVP(TT) ;IF SCROLLING 1 LINE AT A TIME, + JRST TYOLF0 ;MAY NEED TO SET %TFEOP. + ;IN ANY CASE, CLEAR NEXT LINE & FINALIZE. + +;HERE TO WRAP AROUND TO TOP OF SCREEN. +TYOLF3: SETZM TPVM(TT) ;TURN OFF ANY SUPPRESSION OF MORES BY INPUT + TLNN H,%TOERS ;ON DISPLAYS WITHOUT SELECTIVE ERASE, + JRST [ PUSHJ P,TYOCLR ;MUST CLEAR SCREEN WHEN WRAP AROUND. + JRST TYOMVC] ;MUST LEAVE TTY DISSOCIATED. +TYOLF4: MOVE B,TPVB(TT) ;ELSE JUST MOVE TO TOP OF PC PPR + MOVEM B,TPVP(TT) + JRST TYOLF1 ;AND CLEAR THE TOP LINE. + +;HANDLE BACKSPACE. +TYOBS: TLNN H,%TOIML ;BACKSPACE ON IMLAC ISN'T SAME AS MOVE BACK. + JRST TYOBS1 + MOVE B,TPHP(TT) ;ON IMLAC, FIRST, IF AT LEFT MARGIN, + SKIPG B .SEE TPHB;(TT) ;DO NOTHING. + JRST TYOFN2 +TYOBS2: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;IF WE SHOULD BACKSPACE, + SOSGE TPHP(TT) + SETZM TPHP(TT) + JRST TYORU1 ;DO IT BY SENDING A ^H. + +TYOBS1: TLNE H,%TOMVB ;ARE WE ECHOING ^H ON TTY THAT CAN'T BS? + JRST TYOBS4 + TRNN R,%TJECH + JRST TYOBS3 + JRST TYOCTL ;ECHO "^H" RATHER THAN CR AND SPACE FWD. + +TYOBS4: TLNE H,%TORAW ;IN RAW MODE ON TTY THAT CAN BS? + JRST [ MOVEI A,%TDBS ;IF NO OPTIMIZATION, + JRST TYOBS2 ] ;ARRANGE TO OUTPUT REAL BS. +TYOBS3: CAMN TT,TTYLPP(I) ;BS ON TTY THAT ISN'T AN IMLAC. + PUSHJ P,TYOMVC ;PREPARE TO DO CURSOR MOTION. + SOS B,TPHP(TT) ;MOVE BACK 1 POS. + SKIPGE B .SEE TPHB;(TT) + AOS TPHP(TT) ;AT LEFT MARGIN, DO NOTHING. + JRST TYOFNX + +;COME HERE WHEN TAB OUTPUT (AT TOP LEVEL ONLY) +TYOTAB: TRNE R,%TJECH + JRST TYOTA1 + MOVE B,TTYST2(I) ;MAYBE TABS SHOULD BE OUTPUT IN IMAGE MODE. + TLNE B,%TGIMG_6 + JRST TYONMV +TYOTA1: MOVE A,TPHP(TT) + ADDI A,10 + TRZ A,7 ;HPOS OF NEXT TAB STOP. + MOVE B,TCMXH(I) .SEE TPHE;(TT) + TRNN R,%TJCTN + SUBI B,1 ;B HAS EFFECTIVE LINEL. + CAML A,B + MOVE A,B ;A HAS PLACE TAB MOVES TO. + SUB A,TPHP(TT) ;HOW FAR TO MOVE RIGHT? + TRNN R,%TJCTN + JUMPE A,[PUSHJ P,TYOCTN + JRST TYOTAB] + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR CTL. + ADDM A,TPHP(TT) ;MOVE CURSOR TO TAB STOP. + JRST TYOFNX + +;HANDLE ^L. +TYOFF: TRNN R,%TJECH ;ECHOING? + JRST TYOCTL + MOVE B,TTYSTS(I) ;YES; ^L ECHOES AS UPARROW-L + TLNE H,%TOMVU ;EXCEPT ON DISPLAYS, UNLESS PRGM HAS DISABLED. + TLNE B,%TSCLE + JRST TYOCTL ;ECHO AS UPARROW L + JRST TYOCLR ;ECHO AS CLEAR SCREEN. + +;^M IOTTED - MAYBE DO CR AND LF. +TYOCR: TRNE R,%TJECH ;IF ECHO MODE OUT, CR DOES CRLF. + JRST TYOCRL + MOVE B,TTYST2(I) + TRNE B,%TGIMG_12. ;ELSE OUTPUT-CR-IN-IMAGE PREVENTS LF. + JRST TYOCR1 + PUSHJ P,TYOCRL ;DO CR AND LF, + MOVEI B,%TFIGL ;THEN SAY IGNORE NEXT CHAR IF IT'S A LF. + IORM B,TPFLAG(TT) + POPJ P, + +TYOCRL: PUSHJ P,TYORCR + PUSHJ P,TYOLF + JRST TYOFND + +TYOCR1: PUSHJ P,TYORCR + JRST TYOFND + +;ALTMODE IOTTED - SHOULD WE OUTPUT DOLLARSIGN? +TYOALT: MOVE B,TTYST2(I) + TRNN R,%TJECH ;ECHO MODE => YES. + TLNN B,%TGIMG ;OUTPUT ALT IN ASCII MODE SAYS YES. + JRST TYOAL4 + JRST TYOAL1 ;NO, OUTPUT AN ALTMODE, WHETHER IT PRINTS OR NOT. + +TYOAL4: TLNN H,%TOSAI ;IF ALTMODE IS A GRAPHIC, USE IT; +TYOAL3: MOVEI A,"$ ;ELSE USE DOLLARSIGN. + JRST TYONR0 ;EITHER WAY IT'S A NORMAL PRINTING CHAR. + +;IF ABOUT TO CHANGE PC PPR'S CURSOR POS WITHOUT PUTTING +;ANYTHING IN THE OUTPUT BUFFER THAT WILL CHANGE THE TTY'S +;REAL CURSOR POS THE SAME WAY, MUST DISASSOCIATE TTY'S +;CURSOR POS FROM THIS PC PPR. TTYLPS WILL THEN +;SAY WHERE THE TTY'S CURSOR WILL BE AFTER CHARS IN OUTPUT +;BUFFER ARE ALL OUTPUT. +TYOMVC: HRLZ B,TPVP(TT) + HRR B,TPHP(TT) + MOVEM B,TTYLPS(I) + SETCAM TT,TTYLPP(I) ;TTY NO LONGER ASSOCIATED. + POPJ P, + +;BEFORE PUTTING ANYTHING IN OUTPUT BUFFER USING A PC PPR, +;TTY'S CURSOR MUST BE ASSOCIATED WITH PC PPR (THAT IS, +;THE TTY'S CURSOR MUST BE WHERE THE PC PPR'S CURSOR IS) +;WHEN A TTY IS ASSOCIATED WITH A PC PPR, TTYLPS +;IS NONSENSE, AND IT IS NECESSARY FOR OUPUT RTNS +;TO UPDATE PC PPR'S CURSOR IN ACCORDANCE WITH WHAT +;IS PUT IN THE OUTPUT BUFFER. +;THIS ROUTINE ASSOCIATES TTY IN I WITH PC PPR IN TT. +TYOASS: TRNE R,%TJHDE + POPJ P, + PUSH P,A + HLRZ T,TTYLPS(I) ;CURRENT VERTICAL POS + HRRZ A,TTYLPS(I) ;CURRENT HORIZONTAL POS + CAMN T,TPVP(TT) ;IF CURSOR IS WHERE WE WANT IT, + CAME A,TPHP(TT) + AOSA A + JRST TYOAS3 ;JUST SAY WE'RE ASSOCIATED. + SKIPGE TTYLPS(I) + BUG ;TTY ALREADY ASSOCIATED WITH A PC PPR? + CAMN T,TPVP(TT) ;SEE IF JUST MOVING ONE SPACE TO THE RIGHT + CAME A,TPHP(TT) + JRST TYOAS6 ;NO, NEED FULLY GENERAL CURSOR MOTION + MOVEI A,%TDFS ;SAVE BUFFER SPACE IN THIS COMMON CASE + TLNE H,%TOOVR + MOVEI A,40 ;IF SPACE OVERPRINTS, IT IS BETTER THAN %TDFS SINCE FEWER CHARS + PUSHJ P,TYOOUT ;IF SENT TO A SOFTWARE TTY OVER HARDWARE LINE. + JRST TYOAS3 + +TYOAS6: MOVEI A,%TDMV0 ;TELL THE TTY TO PUT ITS CURSOR + TLNE H,%TOMVU + JRST TYOAS7 + MOVEI A,%TDMOV + PUSHJ P,TYOOUT ;WHERE THIS PC PPR WANTS IT. + HLRZ A,TTYLPS(I) + PUSHJ P,TYOOUT + HRRZ A,TTYLPS(I) +TYOAS7: PUSHJ P,TYOOUT + MOVE A,TPVP(TT) + CAML A,TCMXV(I) ;ATTEMPT TO GO BELOW SCREEN BOTTOM? + BUG + PUSHJ P,TYOOUT ;AND THE NEW POSITION. + MOVE A,TPHP(TT) + PUSHJ P,TYOOUT +TYOAS3: MOVEM TT,TTYLPP(I) ;TELL TTY IT IS ASSOCIATED. + SETOM TTYLPS(I) + JRST POPAJ + +TYOAS5: PUSH P,A ;REGARD TTY AS ASSOCIATED WITHOUT ACTUALLY + JRST TYOAS3 ;MOVING ITS CURSOR. + +;FORCE OUT BUFFERED CURSOR MOTION. +;CALL ONLY IF TTY DISSOCIATED, FROM M.P. OR CLOCK LEVEL. +;H MUST BE SET UP ALREADY +TYOFRC: MOVE Q,TOIP(I) + PUSHJ P,TYOASS + JRST TYOFN2 + +;PUT CHAR IN OUTPUT BFR (BUT IT DOESN'T BECOME VISIBLE +;TO INT. LEVEL UNTIL WE FINALIZE - IN CASE WE PCLSR) +TYOOUT: TRNE R,%TJHDE + POPJ P, +TYOOU1: CAMN Q,TOBEP(I) ;Going to deposit past end of buffer? + MOVE Q,TOBBP(I) ; Yes, make wrap around instead. + HRRZI T,(Q) ;Get addr part of the buffer pointer. + CAILE T,@TOBEP(I) ;Reasonable buffer pointer? + ; CANT HAVE BEEN DUE TO 11 DOWN + BUG HALT,[TTY: OUTPUT BUFFER POINTER PAST END OF BUFFER] + IDPB A,Q ;Stuff char into output buffer. +IFN N11TYS, TRNN H,%TP11T ;TV-11 ttys dont have TORM. + SOSL TORM(I) ; One less space available in buffer. + POPJ P, + BUG HALT,[TTY: OUTPUT BUFFER OVERFLOWED, TYOWNC IS TOO SMALL] + +;FINALIZE, UPDATING TOIP, TORM AND FLAGS. +;ALSO RESET Q FOR ANOTHER BUNCH OF OUTPUT. +TYOFNX: ;FINALIZE WHEN TTY DISSOCIATED AND NOTHING PUT IN BFR. +TYOFND: ;SIMILAR, WHEN SOMETHING MIGHT HAVE BEEN PUT IN BFR. +TYOFNA: ;FINALIZE WHEN TTY ASSOCIATED W/ PC PPR. +TYOFN2: MOVEM Q,TOIP(I) + AOSN TTYOAC(I) ;START THE TTY. + XCT TTYST(I) + JRST TYOFNR + +;ON ORDINARY TTY, CALL WHEN BUFFER FULL. +;WAIT TILL AT LEAST 3/4 EMPTY. T HAS MINIMUM # CHARS NEEDED. +;IF RUNNING SYS JOB, POP1J IF TTY SEEMS TO BE HUNG. +TYOW1: CAIGE T,TOBS*3/4 ;DON'T UNBLOCK TILL BUFFER AT LEAST 3/4 EMPTY. + MOVEI T,TOBS*3/4 +TYOW2: MOVEM I,EPDL3(U) ;MAY TRAP OUT ON SYSTEM JOB + CAME U,USER + BUG + JUMPN U,TYOW4 + JRST TYOW5 ;HANG UP SYS JOB FOR MAX OF 5 SEC + + PUSHJ P,TYOW6 +TYOW5: PUSHJ P,UFLS + MOVE T,TTYCOM(I) + TLNE T,%TCHNG + SUB P,[1,,1] ;TIMED OUT + POPJ P, + + CAMLE T,TORM(I) +TYOW4: PUSHJ P,UFLS + POPJ P, + +TYOW6: MOVE A,AC0S+U(U) ;(IN CASE U DIDN'T EQUAL USER AT TYOW1) + MOVE A,EPDL3(A) ;IF SYS JOB, FLUSH IF NO CHR PROCESSED FOR 15 SEC + MOVE Q,TTYTYP(A) + SKIPL TTOALC(A) ;TIME OUT ON SOFTWARE TTY'S WITHOUT ALLOCATION. + JRST TYOW6A ;IF THIS IS A PDP-11 TV, + TRNE Q,%TY11T ;TEST FOR ROOM IN BUFFER IS DIFFERENT ON TV'S + JRST TYOW7 + CAMG T,TORM(A) ;FOR NON-TV'S, TORM IS VALID. + JRST TYOW6B ;THERES ROOM NOW +TYOW6A: MOVSI T,%TCHNG + MOVE Q,TIME + SUB Q,TTLTM(A) + CAIG Q,5.*30. + JRST TYOW6C ;NO NEW TIMEOUT YET + IORM T,TTYCOM(A) ;MARK THIS TTY AS HUNG FOR SYS JOB + JRST POPJ1 + +TYOW6C: CAILE Q,3 + TDNN T,TTYCOM(A) ;SKIP ON CONSOLE WAS LOSING RECENTLY + POPJ P, + JRST POPJ1 ;TIME OUT MUCH SHORTER IF CONSOLE DETERMINED TO BE A LOSER + +TYOW7: LDB Q,T + CAIE Q,1_TT11BY-1 + JRST TYOW6A +TYOW6B: MOVSI T,%TCHNG ;GET HERE WHEN ROOM EXISTS IN BUFFER + ANDCAM T,TTYCOM(A) ;ITS NOT HUNG NOW + JRST POPJ1 + +IFN N11TYS,[ +;ON A PDP-11 TV, CALL HERE TO WAIT UNTIL THERE ARE AT LEAST +;TYOWNC CHARS OF SPACE IN THE OUTPUT BUFFER. +;CAN POP1J FOR THE SYS JOB. +TYOWN: PUSHJ P,TYOWN1 + LDB B,T ;IS THE POS. 20. CHARS UP VACANT? + CAIN B,1_TT11BY-1 + POPJ P, ;YES, NO NEED TO WAIT. + JUMPN U,TYOWN2 ;IF SYS JOB, TIME OUT BEFORE TOO LONG. + MOVEM I,EPDL3(U) + MOVE B,TIME + MOVEM B,TTLTM(I) + JRST TYOW5 + +TYOWN2: PUSH P,A ;SEEMS TO BE NO SPACE, CHECK AGAIN + MOVE B,(T) ;DOING THINGS IN THE RIGHT ORDER THIS TIME + LDB A,T ;TO AVOID GETTING HUNG BY A TIMING ERROR + CAIN A,1_TT11BY-1 + JRST POPAJ ;SOME SPACE APPEARED IN THE MEANTIME + POP P,A + EXCH B,T + CAMN T,(B) ;WAIT FOR THIS WORD TO CHANGE + PUSHJ P,UFLS + JRST TYOWN ;THEN CHECK IT AGAIN + +TYOWN1: MOVE T,TOIP(I) + ADDI T,TYOWNC/<36./TT11BY> + HRRZ B,TOBEP(I) + CAIGE B,(T) + SUB T,TT11OL + HRLI T,040000+TT11BY_6 ;BP TO WHOLE OF RIGHTMOST BYTE IN WORD + POPJ P, +] + +;COME HERE WHEN DETECT THAT %TFEOP OR %TFIGL IS SET. +TYOIGL: TRZN B,%TFIGL ;%TFIGL TAKES PRIORITY. + JRST TYOEOP + MOVEM B,TPFLAG(TT) ;CLEAR IT, AND IGNORE THIS CHAR + CAIE A,^J + JRST TYOIG1 + POPJ P, + +;%TFEOP IS SET AND OUTPUT IS DONE: DO **MORE** PROC. +TYOEOP: PUSH P,[TYOEO9] + PUSH P,A +TYOEO5: SKIPE USER ;DON'T DO MORES IF SYSTEM JOB IS TYPING + TRNE R,%TJMOR+%TJECH ;OR THIS CHANNEL DOESN'T WANT TO + JRST TYOEO7 + MOVSI B,%TSMOR + TDNE B,TTYSTS(I) ;OR THIS JOB DOESN'T WANT TO + JRST TYOEO7 + HRRZ B,TTYSTS(I) ;DON'T **MORE** AN $$^P'ED JOB'S OUTPUT + CAME B,U + JRST POPAJ + MOVE B,TCMXV(I) .SEE TPVE;(TT) + MOVEM B,TPVM(TT) + HRRZ B,UUAC(U) ;GET INTERRUPT BIT FOR CHANNEL THIS IOT IS ON + MOVE B,CHNBIT(B) + AND B,MSKST2(U) ;HAS USER ENABLED OUTPUT INTERRUPT? + JUMPE B,TYOEO1 ;NO, SYSTEM DOES **MORE** PROC. + IORM B,IFPIR(U) ;YES, JUST GIVE USER INT + MOVEI B,%TFEOP ;HE CAN TYPE **MORE** IF HE WANTS TO. + ANDCAM B,TPFLAG(TT) ;INT. HAS BEEN GIVEN. + PUSHJ P,TYOUN1 ;LSWPOP THE FINSET, ETC. + SKIPA + SKIPA + PUSHJ P,UFLS ;MAKE HIM TAKE THE INT. RIGHT NOW. +TYOEO6: PUSHJ P,LSWCLR + SOS UUOH ;HIS PICLR IS SET? RETRY THE UUO. + JRST URET + +TYOEO7: MOVEI B,%TFEOP ;MORE SUPPRESSED, TURN OFF THE FLAG + ANDCAM B,TPFLAG(TT) + JRST POPAJ + +;COME HERE AT END OF PAGE IF PROGRAM ISN'T SMART. +TYOEO1: PUSH P,TPHP(TT) + MOVE A,TPHP(TT) + ADDI A,10 + CAML A,TCMXH(I) + PUSHJ P,TYORCR + CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + IRPC X,,**MORE** + MOVEI A,"X + PUSHJ P,TYONR1 + TERMIN ;OUTPUT THE STRING "**MORE**" + IORI R,%TJSTP ;MAKE ALL OUTPUT ON THIS CHNL HANG. + MOVEI B,%TFEOP ;NO LONGER WANT NEXT CHAR TO DO **MORE** + ANDCAM B,TPFLAG(TT) + POP P,A ;REMEMBER VALUE TO RESET HPOS TO LATER. + HRLM A,TPFLAG(TT) + PUSHJ P,TYOFNA ;FINALIZE SO "**MORE**" WILL TYPE OUT; + ;PCLSRING NO PROBLEM; SINCE %TJSTP IS SET THE IOT + ;WILL COME TO TYOEO3. +TYOEO3: +IFN N11TYS,[ + TRNE H,%TP11T ;WAIT FOR BUFFER SPACE ON TV. + PUSHJ P,TYOWN ;NOTE THIS CAN POP1J +] + PCLT + MOVEI T,TOBS ;WAIT FOR ALL OF "**MORE**" TO GET OUT. + CAME T,TORM(I) + PUSHJ P,TYOW1 + PUSH P,C + PUSH P,D + PUSH P,R + PUSH P,TT + MOVEI R,%TIPEK+%TIACT+%TIECH+%TINWT + PUSHJ P,TYI0 ;LOOK AHEAD AT NEXT INPUT CHAR. + JUMPL D,TYOEO6 ;IS NONE => RETRY UUO AND WAIT IN TYOSET. + EXCH TT,(P) + EXCH R,-1(P) + MOVE Q,TOIP(I) + MOVE C,TTYSTS(I) + TLNE C,%TSROL ;IN SCROLL MODE, MAKE NEXT LINE OF OUTPUT OVERWRITE **MORE**. + JRST [ PUSHJ P,TYORCR + PUSHJ P,TYOCEL + SOS TPVM(TT) ;MORE AGAIN BEFORE THIS LINE GOES OFF SCREEN + JRST TYOEO4] + TRZN R,%TJCP1 ;UNLESS THIS IS ^PN + PUSHJ P,TYOHD1 ;HOME UP (BY HOMING DOWN AND LF'ING) + PUSHJ P,TYOLF ;OTHERWISE (FOR ^PN) JUST LF. +TYOEO4: CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + HLRZ A,TPFLAG(TT) ;SET HPOS TO WHAT IT WAS BEFORE THE **MORE**. + MOVEM A,TPHP(TT) + HRRZS TPFLAG(TT) + EXCH TT,(P) + EXCH R,-1(P) + ANDI D,177 + CAIE D,177 + CAIN D,40 ;IF A SPACE, FLUSH IT FROM INPUT BFR + PUSHJ P,TYIREM + POP P,TT + POP P,R + POP P,D + POP P,C + ANDCMI R,%TJSTP ;RETURN CHANNEL TO NORMAL. + MOVE Q,TOIP(I) + PUSHJ P,TYOFNR + POP P,A ;RESTORE THE CHAR BEING IOTTED + POPJ P, ;AND TRY AGAIN TO IOT IT. + +TYOEO2: PUSH P,[TYOEO9] + PUSH P,A ;COME HERE IF PCLSR OUT OF TYOEO3, ETC. + JRST TYOEO3 ;WHEN THE IOT IS RETRIED. + +TYOCP1: TRZE R,%TJINK ;IF THIS IS THE CHAR AFTER A ^PI, TREAT IT AS + JRST TYONR3 ;NORMAL PRINTING CHARACTER. + TRNE R,%TJSTP + JRST TYOEO2 ;CHANNEL HUNG IN **MORE**. +;HANDLE CURSOR CONTROL CODES. COME HERE WITH IOTTED CHAR IN A. +;IF WE ARE IN THE MIDDLE OF A ^P CODE. +;OR IF THE CHANNEL IS A SUPERIMAGE OUTPUT CHANNEL. + TRZE R,%TJCP2 ;AFTER A ^PV OR ^PH ? + JRST TYOCP2 + TRZN R,%TJCP1 ;NO, NEXT CHAR ISN'T IN THE ^P CODE. + JRST TYOSIO ;MUST BE %TJSIO THAT WAS SET. +TYOCP4: CAIL A,"A ;IF ^P CODE IS A LETTER, + CAILE A,"_ + JRST TYOCP3 + MOVE B,TYOCPT-"A(A) ;GET THE DISPATCH ENTRY FOR IT, + TLNN H,%TOMVU + JUMPL B,TYOCPA ;TURN SOME CURSOR OPERATIONS INTO CRLF ON PRINTING TTY + TLNE B,200000 + PUSH P,[TYOCPR] ;SOME OPERATIONS RETURN HERE FOR FINALIZATION + JRST (B) ;FINALLY, DISPATCH + +TYOCPR: MOVEI B,%TFEOP + ANDCAM B,TPFLAG(TT) + JRST TYOFNX + +TYOCP3: CAIL A,140 ;LOWERCASE LETTERS ACT LIKE UPPERCASE + JRST [ SUBI A,40 + JRST TYOCP4] + HRLM R,@TYOPV2(J) + PUSHJ P,TYOUN1 ;OR IT'S ILLEGAL. + JRST IOCR11 ;IOC ERROR. + +TYOCPV: IORI R,%TJCP1 ;HERE FOR ^PV +TYOCPH: IORI R,%TJCP2 ;SAME FOR ^PH. SAY NEXT CHAR IS THE CURSOR POS. +TYOFNR: HRLM R,@TYOPV2(J) + POPJ P, + +TYOCP2: CAMN TT,TTYLPP(I) ;INTERPRET THE CHAR AFTER ^PH OR ^PV. + PUSHJ P,TYOMVC + ANDI A,177 + TRZN R,%TJCP1 ;WHICH OF THOSE 2 WAS IT? + JRST TYOCH1 ;IT WAS ^PH + ADD A,TPVB(TT) + SUBI A,10 + CAML A,TCMXV(I) .SEE TPVE;(TT) ;DON'T PUT CURSOR PAST END. + JRST [ MOVE A,TCMXV(I) .SEE TPVE;(TT) + SOJA A,.+1] + CAMGE A,TPVB(TT) ;OR BEFORE BEGINNING. + MOVE A,TPVB(TT) + MOVEM A,TPVP(TT) + JRST TYOCPR + +TYOCH1: .SEE ADD A,TPHB;(TT) + SUBI A,10 + CAML A,TCMXH(I) .SEE TPHE;(TT) ;DON'T PUT CURSOR PAST END. + JRST [ MOVE A,TCMXH(I) .SEE TPHE;(TT) + SOJA A,.+1] + SKIPGE A .SEE TPHB;(TT) ;OR BEFORE BEGINNING. + SETZ A, .SEE TPHB;(TT) + MOVEM A,TPHP(TT) + JRST TYOCPR + +;DISPATCH TABLE FOR ^P CODES. +;SIGN => TURN INTO ^PA ON PRINTING TTY. +;4.8 => PUSHJ, ELSE JRST +TYOCPT: TYOCPA ;A - ADVANCE TO FRESH LINE. + 200000,,TYOMVB ;B - MOVE BACK. + TYOCLR ;C - CLEAR SCREEN. + 200000,,TYOMVD ;D - MOVE DOWN. + TYOCEF ;E - CLEAR TO END OF SCREEN. + 200000,,TYOMVF ;F - MOVE FORWARD. + TYOCP3 ;G - ILLEGAL. + TYOCPH ;H - NEXT CHAR IS DESIRED HPOS. + TYOCPI ;I - NEXT CHARACTER TREATED AS NORMAL PRINTING. + TYOCP3 ;J - ILLEGAL. + 200000,,TYODLF ;K - DELETE FORWARD. + TYOCEL ;L - CLEAR REST OF LINE. + TYOMOR ;M - DO **MORE**. + TYOMO1 ;N - SIMILAR BUT DON'T HOME UP. + TYOCP3 ;O - ILLEGAL. + TYOCPP ;P - TYPE "^P". + TYOCPQ ;Q - TYPE "^C". + 600000,,TYORPS ;R - RESTORE SAVED POS. + 200000,,TYOSPS ;S - SAVE POSITION (FOR A ^PR). + 600000,,TYOHMU ;T - HOME UP. + 200000,,TYOMVU ;U - MOVE UP. + TYOCPV ;V - NEXT CHAR IS DESIRED VPOS. + TYOCP3 ;W - ILLEGAL. + 200000,,TYODLB ;X - DELETE BACKWARDS. + TYOCP3 ;Y - ILLEGAL. + 600000,,TYOHMD ;Z - HOME DOWN. + 200000,,TYOILP ;[ - INSERT LINE POSITION + 200000,,TYODLP ;\ - DELETE LINE POSITION + TYOCEL ;] - CLEAR TO END OF LINE (USE ^PL IT'S BETTER) + 200000,,TYOICP ;^ - INSERT CHARACTER POSITION + 200000,,TYODCP ;_ - DELETE CHARACTER POSITION +IFN .-31.-TYOCPT,.ERR WRONG LENGTH TABLE. + +;^PM AND ^PN DON'T WORK IN PROGRAMS THAT TAKE **MORE** +;INTERRUPTS - OR, PRECISELY, THEY ALWAYS ENTER +;THE STATE OF A CHANNEL THAT HAS JUST TYPED OUT "**MORE**". +TYOMO1: IORI R,%TJCP1 .SEE TYOEO3 ;^PN - ENTER **MORE** STATE. +TYOMOR: IORI R,%TJSTP ;^PM. + HRRZS TPFLAG(TT) + JRST TYOFNR + +TYOCPI: IORI R,%TJINK + JRST TYOFNR + +;INSERT AND DELETE CHARACTERS AND LINES +TYOILP: SKIPA A,[%TDILP] +TYODLP: MOVEI A,%TDDLP + TLNN H,%TOLID + POPJ P, + PUSH P,A ;SUPPOSED TO BE AT LEFT MARGIN + PUSHJ P,TYORCR ;MAKE SURE + POP P,A + JRST TYOIL1 + +TYOICP: SKIPA A,[%TDICP] +TYODCP: MOVEI A,%TDDCP + TLNN H,%TOCID + POPJ P, +TYOIL1: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + PUSHJ P,TYOOUT + MOVEI A,1 ;SUPPLY PARAMETER OF 1 + JRST TYORU1 ;IF YOU WANT TO OPTIMIZE CONSECUTIVE ONES + ; USE SUPER-IMAGE OUTPUT, AT LEAST FOR NOW + +;RTNS FOR VARIOUS ^P CODES. +;THE FIRST FOUR DON'T FINALIZE ANYTHING. +TYOMVF: CAMN TT,TTYLPP(I) ;^PF + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPHP(TT) + CAMGE B,TCMXH(I) .SEE TPHE;(TT) + POPJ P, + ;SETZ A, .SEE TPHB;(TT) ;WRAP AROUND FROM LAST POS. TO FIRST. + SETZM TPHP(TT) +TYOMVD: CAMN TT,TTYLPP(I) ;^PD + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPVP(TT) + MOVE A,TPVB(TT) + CAIGE B,119. + CAML B,TCMXV(I) .SEE TPVE;(TT) ;WRAP AROUND FROM LAST POS. TO FIRST. + MOVEM A,TPVP(TT) + POPJ P, + +TYOMVB: CAMN TT,TTYLPP(I) ;^PB - MOVE BACK. + PUSHJ P,TYOMVC + SOSL B,TPHP(TT) .SEE TPHB;(TT) + POPJ P, + MOVE A,TCMXH(I) .SEE TPHE;(TT) ;WRAP AROUND FROM FIRST TO LAST. + SUBI A,2 + MOVMM A,TPHP(TT) +TYOMVU: CAMN TT,TTYLPP(I) ;^PU - MOVE UP. + PUSHJ P,TYOMVC + SOS B,TPVP(TT) + MOVE A,TCMXV(I) .SEE TPVE;(TT) ;WRAP AROUND FROM FIRST TO LAST. + SUBI A,1 + CAIL A,119. + MOVEI A,118. + CAMGE B,TPVB(TT) + MOVEM A,TPVP(TT) + POPJ P, + +TYOSPS: MOVE B,TPHP(TT) ;^PS - SAVE CURSOR POS. + HRL B,TPVP(TT) + MOVEM B,TPSP(TT) + POPJ P, + +TYORPS: CAMN TT,TTYLPP(I) ;^PR - RESTORE CURSOR POS FROM SAVED. + PUSHJ P,TYOMVC + MOVE B,TPSP(TT) + HRRZM B,TPHP(TT) + HLRZM B,TPVP(TT) + POPJ P, + +TYOCPA: CAMN TT,TTYLPP(I) ;ADVANCE TO FRESH LINE, IN ANY CASE CLEAR REST OF LINE + PUSHJ P,TYOMVC + SKIPE TPHP(TT) ;IF NOT AT THE BEGINNING OF A LINE, + JRST TYOCRL ;CRLF. MAYBE SOMEDAY THIS WILL CHECK + JRST TYOCEL ;WHETHER ANYTHING HAS YET BEEN TYPED ON THIS LINE. + +TYOCLR: TLNN H,%TOMVU ;^PC - CLEAR SCREEN. + JRST [ MOVE A,TCMXV(I) ;ON PRINTING TTYS, JUST CRLF. + SUB A,TTYROL(I) ;BUT DON'T --MORE-- UNTIL THIS LINE + MOVEM A,TPVM(TT);GOES OFF THE SCREEN + JRST TYOCRL ] + SKIPN TPVB(TT) ;USE FAST METHOD IF REALLY CLEARING WHOLE SCREEN + JRST TYOCIM +TYOCI1: PUSHJ P,TYOHMU +TYOCEF: SKIPA A,[%TDEOF] ;^PE CLEAR EOF +TYOCEL: MOVEI A,%TDEOL ;[ ^P] - CLEAR EOL. + TLNN H,%TOERS + JRST TYOFNR +TYONMV: CAME TT,TTYLPP(I) ;HERE FOR CHARS THAT DON'T MOVE THE CURSOR + PUSHJ P,TYOASS ;BUT DO DEPEND ON BEING PRINTED AT THE RIGHT PLACE ON THE SCREEN +TYORU1: PUSHJ P,TYOOUT + JRST TYOFNA + +TYOCIM: PUSHJ P,TYOHMU ;CLEAR WHOLE SCREEN + MOVEM TT,TTYLPP(I) + SETOM TTYLPS(I) + MOVEI A,%TDCLR + JRST TYONMV + +TYOHMU: SETZM TPVM(TT) ;^PT - HOME UP + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;GO TO COLUMN 0, + MOVE B,TPVB(TT) ;LINE 0. + MOVEM B,TPVP(TT) + +TYORCR: TLNE H,%TORAW ;GO TO COLUMN 0 - CR IN IMAGE MODE. + JRST [ CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;NO OPTIMIZATION => + SETZM TPHP(TT) + MOVEI A,%TDRCR ;ARRANGE TO SEND REAL CR. + PUSHJ P,TYONCC + JRST TYOMVC] + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;ELSE DO CURSOR-MOTION. + SETZ B, .SEE TPHB;(TT) + MOVEM B,TPHP(TT) + POPJ P, + +TYOHMD: PUSHJ P,TYORCR ;^PZ - HOME DOWN. +TYOHD1: MOVE B,TCMXV(I) .SEE TPVE;(TT) + SUBI B,1 + CAIGE B,119. + MOVEM B,TPVP(TT) + POPJ P, + +TYODLB: SKIPN TPHP(TT) ;^PX - DELETE BACKWARD. + PUSHJ P,.+1 ;IN COLUMN 0, DO IT TWICE SO AS TO ERASE THE "!" AND CHAR BEFORE IT + PUSH P,TPHP(TT) + PUSHJ P,TYOMVB + POP P,B + SKIPN B + AOS TPHP(TT) ;IF WRAPPED AROUND, SET TO TCMXH-1 +TYODLF: MOVE B,TPHP(TT) ;^PK - ERASE 1 CHARACTER. + CAML B,TCMXH(I) .SEE TPHE;(TT) ;DO NOTHING AT END OF LINE. + POPJ P, + TLNE H,%TOOVR ;IF CAN'T OVERPRINT, USE SPACE TO ERASE + JRST [ TLNN H,%TOERS + POPJ P, ;OTHERWISE, USE SPECIAL CONTROL SEQUENCE IF KNOWN + MOVEI A,%TDDLF + JRST TYONMV ] + CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + AOS TPHP(TT) + MOVEI A,40 ;USE REALLY SPACE, NOT CURSOR MOTION! + PUSHJ P,TYOOUT + PUSHJ P,TYOMVB ;THEN BACKSPACE OVER IT + JRST TYOFNX + +SUBTTL .STATUS AND IOPDL FOR TTY + +;2.4 HAS "TTY" +;2.3 DDT MODE ON INPUT +;(STATYI);2.5 CHRS HAVE BEEN ITYI'ED BUT NOT .IOT'ED (STATYI) + ;2.8 TELETYPE NEXT TO 340 OR 340 SLAVE + ;2.9 TELETYPE IS LOCAL, NOT DIAL IN + +STATYO: ANDI A,77 + CAIN A,%TINON ;IF CHANNEL HAS NO REAL TTY, + POPJ P, ;THERE ARE NO SPECIFICS WE CAN SAY. + SKIPN B,TORM(A) + TRO D,1_9. ;BUF CAP FULL + CAIN B,TOBS + TRO D,1_<9.+1> ;BUFFER CAP EMPTY +STATY1: SKIPL TTYTBL(U) + TRO D,1_<9.+3> ;HAS TTY + IORI D,SNTTY + MOVE H,TTYOPT(A) + TLNE H,%TOERS + TRC D,SNTTY#SNTDS + POPJ P, + +STATYI: ANDI A,77 + CAIN A,%TINON ;CATCH "DISOWNED" TTY CHNLS. + POPJ P, + TRO D,1_<9+1> ;ASSUME BUF CAP EMPTY + SKIPN B,TICC(A) ;SEE IF THERE ARE ANY INPUT CHARACTERS + JRST STATY2 ;NOT INCLUDING COM MODE ECHO + MOVE E,TIOP(A) +STATY3: CAMN E,TIBEP(A) + SUBI E,TIBL + ILDB TT,E + TLNN TT,%TXIGN + TRZA D,1_<9+1> ;INPUT SEEN, BUF CAP NOT EMPTY + SOJG B,STATY3 +STATY2: CAIL B,TIBS-10. + TRO D,1_9. ;BUF CAP NEARLY FULL + LDB B,[400400,,TTYTYP(A)] ;GET LOCAL AND 340 MDS + DPB B,[160400,,D] ;DEPOSIT IN STATUS WORD + CONO PI,TTYOFF + MOVE TT,TICC(A) + CAMLE TT,TINTC(A) + TRO D,20000 ;MORE CHRS HAVE BEEN ITYI'ED THAN .IOT'ED + CONO PI,TTYON + JRST STATY1 + +;TELETYPE IO PUSHDOWN ROUTINES + +TYOIOP: TDZA A,A ;OUUTPUT CHNL. +TYIIOP: MOVEI A,TYIMSK-TYOMSK ;INPUT CHNL, SET TYIMSK INSTEAD TYOMSK. + CONO PI,CLKOFF ;TO PREVENT TELETYPE (IF CONSOLE) FROM MOVING AROUND + JUMPGE B,TYIOP1 ;JUMP IF OPEN AS DEVICE + SKIPGE TTYTBL(U) ;IF PROCEDURE DOESN'T HAVE CONSOLE, + JRST CLKONJ ;THEN THAT'S ALL +TYIOP1: LDB E,[$TIIDX,,B] ;GET TTY NUMBER IN E + ADDI E,(A) ;IF INPUT, TYOMSK(E) WILL BE TYIMSK VAR. + HRRZ R,UUAC(U) ;GET "AC FIELD" (IO PUSHDOWN ROUTINES RESTORE R) + MOVE A,CHNBIT(R) ;GET RELEVANT CHANNEL INTERRUPT BIT + XCT TYIOPT(I) ;IORM OR ANDCAM A TO TYOMSK(E) + JRST CLKONJ ;RETURN + +TYIOPT: ANDCAM A,TYOMSK(E) ;IOPUSH (PSEUDO-CLOSE) + IORM A,TYOMSK(E) ;IOPOP (PSEUDO-OPEN) + +;STY IO PDL ROUTINES + +STYOIP: TDZA A,A +STYIIP: MOVEI A,STYMSK-STYOMS + ADDI A,STYOMS-NFSTTY-TYOMSK + JRST TYIOP1 + +SUBTTL TTY CLOSE ROUTINES + +;INPUT CLOSE + +TYICLS: JSP E,TYCLOS ;IGNORE FOR DISOWNED CONSOLE + ANDCAM B,TYIMSK(A) ;INDICATE CHANNEL CLOSURE + JRST TYICL2 + +TYCLOS: LDB I,[210100,,A] + ANDI A,77 ;THROW AWAY TOP BITS OF IOCHNM WD, GET TTY #. + CAIN A,%TINON ;FOR A CHNL IN A TTYLESS TREE, + POPJ P, ;DON'T SOS ANYONE'S TTNTO. + SKIPGE APRC(U) ;SKIP UNLESS DISOWNED + JUMPN I,[JRST 4,.] ;DISOWNED JOB HAS REAL CONSOLE TTY? + SKIPGE TTYTBL(U);IF IT'S A CONSOLE AND THIS JOB DOESN'T + JUMPN I,TYICL2 ;HAVE TTY, DON'T CHANGE TYIMSK OR TYOMSK. + HRRZ R,UUAC(U) + MOVE B,CHNBIT(R) ;GET THE BIT TO CLEAR IN TYIMSK OR TYOMSK. + JRST (E) ;RETURN & CLEAR IT. + +;OUTPUT CLOSE + +TYOCLS: JSP E,TYCLOS ;IGNORE FOR DISOWNED CONSOLE + MOVE I,A + SKIPE USER + PUSHJ P,TYOWC ;WAIT A WHILE FOR OUTPUT TO FINISH + ANDCAM B,TYOMSK(A) ;SET OF OUTPUT CHNLS OPEN. +TYICL2: SOSLE TTNTO(A) + POPJ P, ;MORE OPENS ON TTY + SKIPE TTNTO(A) + BUG + MOVE B,TTYSTS(A) + TLNE B,%TSCNS + POPJ P, ;OPEN AS CONSOLE + JRST TTYLO1 + +;WAIT FOR TTY OUTPUT BUFFER TO BE EMPTY, +;BUT TIME OUT IF TTY DOESN'T TYPE OUT FOR 5 SEC. +TYOWC: MOVEM I,EPDL3(U) ;SAVE TTY # FOR TYOW5. +IFN N11TYS,[ + MOVE T,TTYTYP(I) + TRNE T,%TY11T + POPJ P, +] + MOVEI T,TOBS ;WAIT TILL OUTPUT BUFFER EMPTY + PUSHJ P,TYOW5 ;BUT DON'T WAIT TOO LONG. + POPJ P, ;TYOW5 MAY POP1J. + +;TTY # IN A - MAKE THE TTY FREE. +TTYLO1: SETZM TTNTO(A) + SETZM TYIMSK(A) + SETZM TYOMSK(A) + HRLOI B,%TSFRE + IORB B,TTYSTS(A) ;SAY TTY FREE (BUT TTYSTA OFF SO CAN'T ^Z) + PUSHJ P,TTYLFC ;REMOVE TTY FROM COM MODE AND + PUSHJ P,TYIRS0 ;RESET INPUT BUFFER +IFN TTLPTP,[ + CAMN I,LPTTTY ;IF TTY'S THE LPT, IT'S NOT IN USE. + SETOM LPTUSR +] + MOVE T,TTYTYP(I) + TRNN T,%TYSTY + PUSHJ P,TTYIN1 ;RE-INIT USER OPTIONS + TRNE T,%TYDIL\%TYRLM ;DIALUP LINE => MAKE IT PRINTING. + TRNE T,%TYMDM ;UNLESS WE CAN DETECT DISCONNECTS, IN WHICH CASE DO IT THEN. + CAIA + PUSHJ P,NCNSSP +IFN N11TYS,[ + TRNE T,%TY11T + PUSHJ P,NCNSST +] + MOVEI B,SCRCFM + SKIPL TTYSTA(I) + IORM B,SUPCOR ;REQUEST A CONSOLE-FREE MESSAGE. + MOVE A,I ;IN CASE OUR CALLER WANTS TTY # IN A. + POPJ P, + +IFN N11TYS,[ +TTYLO2: MOVE B,TTYTYP(A) ;TTY BEING CLOSED & CNSL FREE MSG NOT NEEDED, + SKIPGE TT11P ;IF IT'S A PDP11-TV TTY + TRNN B,%TY11T + POPJ P, + MOVE I,A ;MAKE ALL JOBS CEASE TO HACK THIS SCREEN + PUSHJ P,NTVWH1 ;B := VIDEO BUFFER NUMBER + BUG + SETZ A, +TTYLO3: LDB C,[$11BY0,,TVCREG(A)] ;VIDEO BUFFER HACKED BY THIS JOB OR 377 + CAMN C,B + SETOM TVCREG(A) ;IF JOB HACKING THIS VIDEO BUFFER, MAKE IT STOP. + ADDI A,LUBLK + CAMGE A,USRHI + JRST TTYLO3 + MOVE B,TT11HD ;TELL THE 11 THE TTY IS FREE. + ADDI B,1-NF11TY(I) + ADD B,TT1111 + HRROI T,-1_4+10 ;SET TTY'S PHYSLC WORD TO -1. + MOVEM T,(B) + MOVE T,TOBBP(I) ;RESET OUTPUT BUFFER POINTER TO BEGINNING OF + MOVEM T,TOIP(I) ; BUFFER. THE 11 DOES ALSO. + POPJ P, +] + +;REMOVE A TTY FROM COM MODE IF IT IS COM MODE. +;CALLED WHEN TTY BECOMES FREE, ETC. +;TAKES TTY # IN A; LEAVES IT IN A AND I. +TTYLFC: HRRZ I,A + CONO PI,TTYOFF + SKIPL Q,TTYCOM(I) + JRST TTLFC1 + PUSH P,I + PUSH P,U + PUSHJ P,TYCSET + TLZ Q,%TCCBK+%TCTPN+%TCCBS + MOVEM Q,TTYCOM(I) ;FLUSH COM MODE TEMP FLAGS. + PUSHJ P,TYCGTM ;REMOVE THE TTY FROM COM LINKS. + POP P,U + POP P,I +TTLFC1: MOVE A,I + MOVEI B,TTYI + MOVEM B,TTYIPC(A) + POPJ P, + +SUBTTL TTY RESET ROUTINES + +;TTY INPUT RESET + +TYIRS: PUSHJ P,TTYWR + POPJ P, ;IGNORE IF WE DON'T OWN THE TTY. +TYIRS0: MOVSI T,%TCLFT+%TCICO + PUSHJ P,TTYCMW ;MAYBE WAIT FOR COM LINK TO FINISH. RETURN WITH TTYCHN OFF. + PUSHJ P,TYIRS1 ;DISCARD THE INPUT. + JRST TTYONJ + +;; DISCARD THE CONTENTS OF THE TTY INPUT BUFFER. TTY NUMBER IN I. +TYIRS1: MOVE B,TIIP(I) ;Get input pointer. + MOVEM B,TIOP(I) ;Bash output ptr to it. + MOVEM B,TINTP(I) ;Bash interrupt-peeked ptr to it. + MOVEM B,ECHOP(I) ;Bash echo ptr to it. + SETZM ECHOC(I) ;Nothing to echo. + CLEARM TICC(I) ;Nothing has been input. + CLEARM TACC(I) ;No activation chars either. + CLEARM TINTC(I) ;Nothing to ITYIC either. + POPJ P, + +;OUTPUT RESET + +TYORS: PUSHJ P,TTYWR ;CHECK FOR OWNING TTY. TTY NUMBER IN I. + POPJ P, ;NON-SKIP MEANS NO; IGNORE THE .RESET. + SKIPL TTOALC(I) + PUSHJ P,UFLS + MOVSI T,%TCLFT+%TCOCO+%TCICO+%TCFPD ;ALSO WAIT FOR OUTPUT SEQ TO FINISH. + PUSHJ P,TTYCMW ;HANG UNTIL OUT OF COM MODE, OR OVER-RIDDEN. MAY UTCOFF. + MOVSI B,%TJCP1+%TJCP2+%TJSTP ;IF LAST CHAR THIS CHNL WAS ^P, + ANDCAM B,(R) ;FORGET IT. ALSO UNHANG CHANNEL FROM **MORE**. + MOVE TT,I + IMULI TT,TPLEN*2 + MOVEI B,%TFEOP+%TFIGL ;RESTORE BOTH PCS OF PPR TO NORMAL STATE. + ANDCAM B,TPFLAG(TT) + ANDCAM B,TPFLAG+TPLEN(TT) + MOVE B,TTYOPT(I) ;IS OUTPUT RESET SUPPOSED TO DO SOMETHING? + TRNN B,%TPORS ;(ON FAST TTYSS IT DOESN'T) + JRST UTCONJ + MOVE B,TTYCOM(I) + TLNE B,%TCECH + JRST UTCONJ +TYORS1: MOVE B,TOOP(I) ;SCAN BACKWARD 4 CHARS FROM TOOP TO SEE IF A %TDMOV + MOVEM B,TOIP(I) + MOVEI TT,TOBS-4 ;HAS BEEN PARTIALLY REMOVED FROM THE BUFFER. + MOVEM TT,TORM(I) ;TORM HAS THE RIGHT VALUE ASSUMING A %TDMOV APPEARS + ;JUST BEFORE TOOP - THE FIRST PLACE WE WILL LOOK FOR ONE. +TYORS4: LDB T,B + CAIE T,%TDMV0 + CAIN T,%TDMV1 + JRST TYORS8 + CAIN T,%TDMOV ;IF ONE IS FOUND IN THOSE 4 CHARS, IT MUST EXTEND PAST TOOP, + JRST TYORS5 ;SO TAKE TOOP AND INCREMENT IT TO GET NEW TOIP. + IBP B ;DBP B - KNOWING THAT THERE ARE 4 BYTES/WORD. + IBP B + IBP B + SUBI B,1 + CAMN B,TOBBP(I) + MOVE B,TOBEP(I) + AOS TT,TORM(I) ;AS THE %TDMOV GETS FARTHER BACK, ITS REMNANT OCCUPIES LESS SPACE. + CAIE TT,TOBS ;IF ITS REMNANT TAKES NO SPACE, FORGET ABOUT IT. + JRST TYORS4 + JRST TYORS6 + +TYORS8: ADDI TT,2 ;THIS REMNANT IS TWO CHARS LONG + CAIL TT,TOBS + JRST [ MOVEI TT,TOBS + MOVEM TT,TORM(I) + JRST TYORS6 ] + MOVEM TT,TORM(I) +TYORS5: SUBI TT,TOBS ;TT GETS - + MOVE B,TOOP(I) +TYORS7: CAMN B,TOBEP(I) ;SCAN FORWARD FROM TOOP TO FIND END OF REMNANT + MOVE B,TOBBP(I) + IBP B + AOJL TT,TYORS7 + MOVEM B,TOIP(I) ;AND FLUSH FROM BUFFER ALL BUT THAT REMNANT. +;DROPS THROUGH + ;DROPS IN +TYORS6: MOVE B,TCTYP(I) ;IF A "SOFTWARE" TTY, SEND A %TDORS. + CAIE B,%TNSFW + JRST [ MOVE B,TTYTYP(I) + TRNN B,%TYSTY ;ELSE, ON A STY, IF %SSORS + JRST TYORS2 + MOVE B,STYSTS-NFSTTY(I) + TLNN B,%SSORS + JRST TYORS2 + JRST .+1] ;THEN SEND %TDORS + SOS TORM(I) + MOVE B,TOIP(I) + CAMN B,TOBEP(I) + MOVE B,TOBBP(I) + MOVEM B,TOIP(I) ;CHECK FOR WRAP + MOVEI B,%TDORS ;RESET CODE + IDPB B,TOIP(I) + PUSHJ P,TYORS2 ;FINISH RESETTING, TURN TTYCHN BACK ON, + AOSN TTYOAC(I) ;AND ACTIVATE INT. LEVEL, SO %TDORS WILL BE SENT. + XCT TTYST(I) ;(THIS MAY TURN TTYCHN OFF AND ON AGAIN). + MOVE B,TTYOPT(I) + TRNN B,%TPCBS ;ON SOFTWARE TTY WITH ^\ TURNED ON, STOP TYPEOUT AT M.P. + POPJ P, ;LEVEL UNTIL THE TTY SAYS WHAT ITS CURSOR POSITION IS NOW, + HRRZS TTOALC(I) ;USING ^\^P... OR SCPOS + POPJ P, + +TYORS2: SKIPGE TT,TTYLPP(I) + SETCMB TT,TTYLPP(I) + SKIPL B,TTYIHP(I) ;AND UNDO MAIN PRGM CURSOR POS MVT + CAMGE B,TCMXH(I) + JRST TYORS3 + MOVE B,TCMXH(I) + SUBI B,1 + MOVEM B,TTYIHP(I) +TYORS3: MOVEM B,TPHP(TT) + MOVE B,TTYIVP(I) + CAML B,TCMXV(I) + BUG + MOVEM B,TPVP(TT) + SETOM TTYLPS(I) + JRST UTCONJ + +;SEND A %TDINI TO ALL TTYS. CALLED AT SYSTEM STARTUP. +TTRSAL: MOVSI I,-NCT +TTRSA1: MOVE T,TCTYP(I) + MOVE H,TTYOPT(I) + MOVE Q,TOIP(I) + CONO PI,TTYOFF + MOVEI A,%TDINI + PUSHJ P,TYOOU1 ;YES, SEND IT A REINIT CHARACTER + MOVEM Q,TOIP(I) + CONO PI,TTYON + AOSN TTYOAC(I) + XCT TTYST(I) ;AND MAKE SURE IT GETS SENT TO THE TTY +TTRSA2: AOBJN I,TTRSA1 + POPJ P, + +SUBTTL TV-11 INPUT PROCESSOR + +IFN N11TYS,[ +;CALL HERE FROM CLOCK LEVEL WHEN THERE IS INPUT FROM THE PDP-11. +;TAKE CHARACTERS FROM THE PDP11 AND CALL THE TTY INPUT INT. LVL. +;ROUTINES WITH THEM ONE AT A TIME. MAY CLOBBER ANY ACS. +TT11IN: SKIPL TT11P ;IF 11 DOWN, DON'T LOOK FOR INPUT FROM IT. + JRST TT11D1 + LDB TT,[$11WD0,,@TT11HD] + SETZM @TT11HD ;GET AND RESET CHAIN OF INPUT BUFFERS. +;HANDLE THE NEXT INPUT BUFFERFULL. PDP11 ADDRESS IN TT. +TT11I1: LSH TT,-2 ;CONVERT PDP11 ADDRESS TO PDP10 ADDR. + ADDI TT,TT11LO + MOVE A,(TT) ;GET -<# CHARS IN BUFFER> + ASH A,-24 + LDB I,[$11WD0,,2(TT)] ;GET # OF TTY THE CHARS ARE FOR. + CAML A,[-400] ;IF A OR I IS RIDICULOUS, + CAML I,TT1111 + JRST TT11LS ;ASSUME 11 HAS CRASHED. + JUMPG A,TT11LS + ADDI I,NF11TY + MOVEI B,3(TT) ;SET UP BP TO DATA AREA OF BUFFER. + HRLI B,$11WD1 ;EACH CHAR IS 16. BITS - A PDP11 WORD. + PUSH P,TT ;SAVE BUFFER ADDR SO CAN FIND NEXT BFR. + CAIL I,NF11TY+N11TYS + JRST [ MOVE A,I ;IF 11 KNOWS MORE TV'S THAN 10, IGNORE THOSE 10 ISN'T USING. + PUSHJ P,TTYLO2 ;AND IF THE 11 STARTS USING ONE, FREE IT SO USER ISN'T CONFUSED. + JRST TT11I3] + CONO PI,TTYOFF-1 + JUMPE A,TT11I4 + PUSH P,I + PUSH P,A + PUSH P,B +TT11I2: ILDB A,(P) ;GET NEXT CHAR FROM BFR, + MOVE I,-2(P) + PUSHJ P,NTYI5 ;PRETEND IT CAME FROM A TTY CONTROLLER INT., + AOSE -1(P) + JRST TT11I2 ;MORE CHARS => HANDLE THEM. + SUB P,[3,,3] +TT11I3: CONO PI,TTYON-1 + POP P,A ;ADDR. OF BUFFER JUST EMPTIED. + LDB TT,[$11WD1,,1(A)] ;GET ADDR OF NEXT BUFFER. + SETZB B,(A) ;THIS BUFFER NOW FREE. + DPB B,[$11WD1,,1(A)] + JUMPN TT,TT11I1 ;LOOK AT NEXT ONE, IF ANY. + POPJ P, + +TT11I4: PUSHJ P,TYPEND ;INPUT BUFFER WITH 0 CHARS SAYS OUTPUT BUFFER + JRST TT11I3 ;IS EMPTY, SO MAYBE REQUEST ECHOING. + +TT11LS: MOVEM A,TT11ER ;LEAVE DIAGNOSTIC INFO BEHIND + MOVEM I,TT11ER+1 + MOVEM TT,TT11ER+2 + MOVE A,(TT) + MOVEM A,TT11ER+3 + MOVE A,1(TT) + MOVEM A,TT11ER+4 + MOVE A,2(TT) + MOVEM A,TT11ER+5 +TT1LS1: SETZM TT11P ;MARK 11 DOWN AND DONT TRY TO COME BACK UP FOR NOW + MOVEI A,SCR11D ;MAKE SYS JOB PRINT "11 WENT DOWN" MESSAGE. + IORM A,SUPCOR +TT11D1: MOVEI A,TT11HD+1 ;MAKE SURE CLOCK LEVEL DOESN'T THINK + MOVEM A,TT11HD ;THAT THE 11 IS SENDING INPUT. + POPJ P, +] + +SUBTTL TERMINET MOTOR CONTROL + +;COME HERE FROM VERY SLOW CLOCK (2 MIN.), RUNNING IN SYS JOB. +;TURN OFF MOTORS OF ALL TERMINETS THAT HAVE BEEN IDLE 30. SEC. +;MAY CLOBBER ANY ACS. +TTTMNT: MOVE TT,TIME + SUBI TT,900. ;TT=30. SECONDS AGO. + CAIA +TTTMN2: MOVE TT,TIME ;TURN OFF ALL TERMINETS AT SYSTEM STARTUP. + MOVSI I,-NCT +TTTMN0: MOVE T,TCTYP(I) + CONO PI,TTYOFF + SKIPL SHUTDN + CAML TT,TTLTM(I) ;IF TTY HAS OUTPUT RECENTLY + CAIE T,%TNTRM ;OR ISN'T A TERMINET, + JRST TTTMN1 ;NOTHING TO DO. + MOVSI T,%TCMTR + TDNE T,TTYCOM(I) ;DITTO IF MOTOR ALREADY OFF. + JRST TTTMN1 + IORM T,TTYCOM(I) + MOVE H,TTYOPT(I) + MOVE Q,TOIP(I) + MOVEI A,%TDMTF ;PUT A MOTOR-OFF COMMAND IN OUTPUT BFR + PUSHJ P,TYOOU1 + MOVEM Q,TOIP(I) + CONO PI,TTYON + AOSN TTYOAC(I) + XCT TTYST(I) ;AND TELL INT. LVL. ABOUT IT. +TTTMN1: CONO PI,TTYON + AOBJN I,TTTMN0 + POPJ P, + +;CALL HERE WHEN ABOUT TO OUTPUT TO A TERMINET WHOSE MOTOR IS OFF +;TTY # IN I. LEAVES TTY'S TTYCOM IN Q. +TTTMTO: MOVE Q,TOIP(I) + MOVEI A,%TDMTN + MOVE H,TTYOPT(I) + PUSHJ P,TYOOU1 ;PUT MOTOR-ON CMD IN OUTPUT BFR, + MOVEM Q,TOIP(I) + MOVSI Q,%TCMTR ;MOTOR NOW ON AS FAR AS MAIN PRGM + ANDCAB Q,TTYCOM(I) ;IS CONCERNED. + POPJ P, + +SUBTTL PI-LEVEL ECHOING + +;ECHOING - CALLED AT CLOCK LEVEL. MAY CLOBBER ANY AC. +;ECHOES CHARS BY COPYING THEM FROM INPUT BFR TO OUTPUT BFR. +TTECH: MOVSI I,200000 ;GET LIST OF TTYS NEEDING ECHO, AND REINIT IT. + EXCH I,TTERQS +TTELUP: AOS NTTELU ;TAKE STATISTICS. + CAIL I,-1 + POPJ P, ;NO MORE TTYS NEED ECHOING. + ;I HAS IDX OF A TTY NEEDING ECHOING. +IFN N11TYS,[ + MOVE T,TTYTYP(I) + TRNE T,%TY11T + JRST TTELU3 +TTELU4: ] + MOVEI A,TOBS + MOVSI T,%TCECH + TDNE T,TTYCOM(I);CAN'T ECHO UNLESS OUTPUT BUFFER HAS ENOUGH ROOM, + MOVEI A,TYOWNC+1 + CAMG A,TORM(I) ;NO MAIN PROGRAM OUTPUT IN IT, + SKIPL TTOALC(I);OUTPUT NOT BLOCKED AT M.P. LEVEL, + JRST TTEDU4 + SKIPL TYOSW(I) ;AND NO MORE OUTPUT COMING SOON. + JRST TTEWAT ;PUT TTY BACK ON LIST. + MOVE H,TTYOPT(I) + MOVE Q,TTYCOM(I) + TLNE Q,%TCMTR ;IF TTY'S MOTOR IS OFF, TURN IT ON. + PUSHJ P,TTTMTO + MOVEI J,TTEDMY ;PROVIDE IOT RTNS WITH VARIABLE-BLOCK. + SKIPGE TT,TTYLPP(I) ;TT HAS IDX OF MOST RECENTLY USED PC PPR + SETCM TT,TTYLPP(I) ;WHETHER NOW ASSOCIATED OR NOT. + MOVE A,TPVB(TT) ;PERHAPS MOST RECENT PC PPR IS ECHO AREA, + CAMN A,TCMXV(I) ;BUT THERE'S NO ECHO AREA NOW. IN THAT CASE, + SUBI TT,TPLEN ;MAKE SURE DON'T TRY TO FORCE OUT BUFFERED CURSOR POS IN THAT PC PPR. +TTEDU2: TLZE Q,%TCDNG ;SHOULD BELL BE TYPED BECAUSE INPUT BFR FULL? + PUSHJ P,[MOVEM Q,TTYCOM(I) + MOVEI R,%TJECH+%TJMOR + MOVEI A,^G ;DING ON TTY IF DESIRED. + JRST TYO8] +TTELP1: SKIPN T,ECHOC(I) ;ANY CHARS TO BE ECHOED NOW IN INPUT BFR? + JRST TTEDUN ;NO, FINISHED ECHOING. + SKIPG T + BUG ;ECHOED MORE CHARS THAN THERE WERE? + AOS NTTEL1 +;NOW FIND NEXT CHARACTER NEEDING PI ECHO, +;AND MARK IT AS NO LONGER NEEDING IT. +;CAN EXIT TO TTEDU5 IF MUST STOP ECHOING BECAUSE ECHOING IS DEFERRED. + CONO PI,TTYOFF-1 ;PREVENT INTERACTION WITH INPUT INTERRUPTS. + MOVE B,ECHOP(I) +TTELP2: MOVE C,TICC(I) + CAMN B,TIIP(I) + JRST TTELBG + MOVE C,B + CAMN B,TIBEP(I) ;LOOK FOR 1ST CHAR NEEDING PI ECHO. + SUBI B,TIBL + ILDB A,B + TRZN A,%TXPIE + JRST TTELP2 + TRNN A,%TXIGN ;DON'T ECHO NON-COM-MODE CHARS + JRST [ MOVE T,TTYSTS(I) ;IF ECHOING BEING DEFERRED. + TLNE T,%TSNOE + TLNE H,%TOHDX ;BUT IF HALF-DUPLEX, IT ECHOES IN ANY CASE. + JRST .+1 + JRST TTEDU5] + SOSGE ECHOC(I) ;FOUND ONE; NOW ECHO IT. + BUG + MOVEM B,ECHOP(I) + DPB A,B ;MARK IT AS ECHOED. + LDB A,B ;CHECK FOR HARDWARE LOSSAGE. + TRNE A,%TXPIE + BUG ;DPB OR TRZN LOST?? + TRNN A,%TXIGN ;IF CHAR IS IN BFR ONLY TO BE ECHOED, + JRST TTELP5 + CAMN C,TIOP(I) ;IF IT'S 1ST CHAR IN CUFFER, + JRST [ PUSHJ P,TYIRE1 ;REMOVE IT THE NORMAL WAY. + JRST TTELP5] + CAMN B,TIIP(I) ;IF CHAR IS LAST CHAR IN BFR, + PUSHJ P,TTEBAK ;DELETE IT, & MAYBE OTHERS BEFORE IT. +TTELP5: CONO PI,TTYON-1 +;DECIDE WHICH PC PPR TO USE. + MOVE T,I + IMULI T,2*TPLEN ;COMPUTE INDEX OF M.P. PC-PPR. + SKIPGE Q,TTYCOM(I) ;COM MODE, UNLESS %TCICO OR %TCLFT, MEANS USE M.P. AREA. + TDNE Q,[%TCICO+%TCLFT,,400000] + MOVE T,TTYEPP(I) ;OTHERWISE USE THE ECHO AREA IF ANY. + MOVE B,TTYSTS(I) + TRNN A,%TXECI + TRNN A,%TXIGN ; FOR ^_ COMMANDS, DON'T OBEY %TSNEA. + TLNN B,%TSNEA ; %TSNEA SAYS USE M.P. AREA. + JRST TTELP4 + MOVE T,I + IMULI T,2*TPLEN +TTELP4: SKIPGE TT,TTYLPP(I) ;TT GETS LAST PC PPR HACKED WITH THIS TTY. + SETCA TT, + CAMN TT,T ;IF WE ARE SWITCHING TO A DIFFERENT PC PPR, + JRST TTELU1 + SKIPL TTYLPP(I) ;DISASSOCIATE THE OLD ONE IF NEC. + PUSHJ P,TYOMVC +TTELU1: MOVE TT,T ;MOST RECENT PC PPR NOW ECHOING PC PPR. + MOVSI Q,%TCECH ;NOW DEFINITELY GOING TO PUT CHARS IN OUTPUT BUFFER + IORB Q,TTYCOM(I) + MOVEI R,%TJECH+%TJMOR + TLNN H,%TOHDX ;ON HALF-DUPLEX TTYS, EXCEPT FOR + JRST TTELP3 + TRNN A,%TXCOM ;CHARS PRODUCED BY COM LINKS, + PUSHJ P,[IORI R,%TJHDE + JRST TYOAS5] ;MOVE CURSOR BUT DON'T REALLY OUTPUT. + ;THUS, CURSOR MOTION DUE TO ECHOING BY TTY + ;IS ACCOUNTED FOR. +TTELP3: LDB B,[.BP %TXASC,A] + TRNE A,%TXECI + JRST TTELP6 + TRZE A,%TXIGN + CAIE B,^L ;^L ECHOED IN COM MODE SHOULD CLEAR SCREEN. + TRZA R,%TJCP1 + JRST [ MOVEI A,"C ;(BY SIMULATING A ^PC). + IORI R,%TJCP1 + JRST .+1] +TTELP6: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + PUSHJ P,TYO8 + TRZE R,%TJHDE + PUSHJ P,TYOMVC + SKIPN ECHOC(I) + JRST TTEDUN +IFN N11TYS,[ + TRNE H,%TP11T + JRST [ PUSHJ P,TYOWN1 + LDB B,T + CAIE B,1_TT11BY-1 + JRST TTEDU6 ;LESS THAN 20. FREE SPACES IN BFR => GIVE UP. + JRST TTELP1] +] + MOVE A,TORM(I) + CAIGE A,TYOWNC ;IS THERE A CHANCE OUTPUT WOULD HANG UP? + JRST TTEDU4 ;YES, WAIT UNTIL LATER TO ECHO THE REST. + JRST TTELP1 ;NO, ECHO MORE + +TTELBG: BUG PAUSE,[ECHOC is ],OCT,T,[ but ECHOP equals TIIP. TICC=],OCT,C,[. TTY ],OCT,I + SETZM ECHOC(I) +;COME HERE WHEN ALL ECHOING DESIRED ON THIS TTY WAS DONE. +TTEDUN: CONO PI,TTYOFF-1 + SKIPE ECHOC(I) + JRST TTEDU1 +TTEDU5: MOVE Q,TTYCOM(I) + TLNE Q,%TCDNG ;HAS ANOTHER REASON TO ECHO ARISEN AFTER WE CHECKED? + JRST TTEDU1 ;YES, GO PROCESS IT. + PUSH P,TTYERQ(I);SAVE NEXT TTY TO ECHO ON + SETOM TTYERQ(I) ;AND TURN OFF THIS ONE'S ECHO REQUEST + CONO PI,TTYON-1 + SETZ R, + CAME TT,TTYLPP(I) + PUSHJ P,TYOFRC ;FORCE OUT BUFFERED CURSOR MOTION. + POP P,I + JRST TTELUP + +TTEDU4: +TTEDU3: SETO A, ;NO, MOVE TO NEXT TTY ON LIST. + EXCH A,TTYERQ(I) + MOVE I,A + JRST TTELUP + +TTEDU1: CONO PI,TTYON-1 + JRST TTEDU2 + +;COME HERE WHEN CAN'T ECHO BECAUSE TYOSW IS LOCKED. +TTEWAT: AOS NTTEWA + MOVE A,I ;IF WE CAN'T DO ANY. + CONO PI,TTYOFF-1 + EXCH A,TTERQS ;PUT THIS TTY BACK ON LIST, + EXCH A,TTYERQ(I) ;SO IT WIL BE REEXAMINED NEXT TICK. + CONO PI,TTYON-1 + MOVE I,A ;MOVE TO NEXT TTY ON OLD LIST. + JRST TTELUP + +IFN N11TYS,[ +TTELU3: SKIPL TT11P + JRST TTEDU4 ;DON'T ECHO ON PDP11 TTYS IF PDP11 DOWN. + LDB A,TOIP(I) ;DEFER ECHOING UNLESS OUTPUT BFR EMPTY. + CAIN A,1_TT11BY-1 + JRST TTELU4 ;JUMP IF BUFFER EMPTY (LAST CHAR OUTPUT CHANGED TO -1) +TTEDU6: JRST TTEWAT ;TEMPORARY PATCH +.ERR IS THIS PATCH TEMPORARY OR PERMANENT? + MOVE A,TT11HD ;BFR NOT EMPTY: TELL 11 + ADDI A,1-NF11TY(I) ;(BY SETTING ECOFLG) + ADD A,TT1111 + MOVSI B,400000 ;TO SIGNAL TEN WHEN THE BUFFER BECOMES EMPTY. + IORM B,(A) .SEE TT11I4 + JRST TTEDU4 +] +;COME HERE WHEN ARE JUST ABOUT TO ECHO THE LAST CHAR +;IN THE INPUT BUFFER, AND ITS %TXIGN IS SET. +;TRY TO FLUSH THE CHARACTER FROM THE INPUT BFR, +;AND ALSO THE CHARS BEFORE IT, IF THEY TOO HAVE %TXIGN. +TTEBAK: SKIPE C,ECHOC(I) + BUG PAUSE,[ECHOING LAST CHAR BUT ECHOC IS ],OCT,C,[. TTY ],OCT,I + SETZM ECHOC(I) + IBP B ;THIS DEPENDS ON 18-BIT BYTES IN INPUT BUFFER. + SUBI B,1 + CAMN B,TIBEP-1(I) + ADDI B,TIBL + SOSN TICC(I) + JRST TTEBA1 + LDB C,B + TRNE C,%TXIGN + JRST TTEBAK +TTEBA1: MOVE C,TIIP(I) + CAMN C,TINTP(I) + MOVEM B,TINTP(I) + CAME C,ECHOP(I) + BUG + MOVEM B,ECHOP(I) + MOVEM B,TIIP(I) + POPJ P, + +SUBTTL TTY INTERRUPT HANDLING + +;MACRO TO SAVE ACS AND CONI APR ON ENTERING A TTYCHN INTERRUPT ROUTINE. +;PCLOC SHOULD BE THE ADDRESS OF THE STORED PC, WHICH IS MOVED TO TTYBRK. +DEFINE TTYSAV PCLOC=TTYBRK +IFN KL10P,[ + CONSO PI,1_<7-TTYCHN> + JRST 4,. ;HARDWARE BUG ALLEGEDLY FIXED +] +IFN KA10P, CONI TTYAPC + MOVEM A,TTYA + MOVE A,[B,,TTYACS] + BLT A,TTYACS+17-B+1-1 ;SAVE ALL ACS BUT 0 +IFSN PCLOC,TTYBRK,[ + MOVE A,PCLOC + MOVEM A,TTYBRK +] + MOVE P,TTYPDP + PUSH P,[TTYRET] +TERMIN + +EBLK + +TTYBRK: 0 + +BBLK + TTYSAV ;SAVE ACS AND SET UP P. +IFN KL10P,[ + CONSZ DTE,%DBL10+560 + JRST TTDTE1 ;DTE20 INTERRUPTED (DOORBELL OR BYTE TRANSFER ERROR OR DONE) +] ;KL10P +IFN DL10P,[ + CONSZ DLC,10 + JRST TTDLB0 ;DL10 INTERRUPTED +] +IFN TK10P,[ + CONSZ NTY,200000 + JRST NTY1 ;NEW TELETYPE KLUDGE +] +IFN MTYP,[ + CONSZ MTY,50 + JRST MTY1 ;MORTON BOX +] +IFN DPKPP,[ + CONSZ DPK,60 + JRST DPKPE ;PARITY ERROR OR NXM + CONSZ DPK,10 + JRST DPTI1 ;CHAR AVAIL DPK + CONSZ DPK,400 + JRST DPTO1 ;OUTPUT BUFFER FIN DPK +] +IFN NOTYS,[ + MOVEI I,0 + CONSZ TTY,50 + JRST GOTTY +] +IFN NDZTYS,[ +;DZ-11 Code The only place that emulates an interrupt on the TTY interrupt +; channel is the DTE code, handled above, so there should never be a +; need for a DZ11 entry here. +] +; MOVEI J,TTYCHN ;KNIGHT TTY KLUDGE GENERATES SPUR INTS +; JSP E,SPUR ;SPURIOUS INT +TTYRET: +TTYRT3: +IFN KA10P,[ + CONI A + ANDCM A,TTYAPC + TRNE A,220000 ;DID MPV OR PDL OV COME ON DURING THIS INT? + BUG PAUSE,[MPV OR PDL OV IN TTY INT HANDLER, APR CONI=],OCT,A +] ;KA10P + MOVS A,[B,,TTYACS] + BLT A,17 + MOVE A,TTYA + JRST 12,@TTYBRK + +IFN DPKPP,[ +DPKPE: AOS NDPKPE + CONO DPK,60+TTYCHN ;PARITY ERROR OR NXM + JRST TTYRT3 +] + +IFN DZ11P,[ ;DZ-11 Code + +IFE KS10P, .ERR DZ11 code only works on a KS-10. + +$INSRT DZ11 + +REPEAT DZ11NB,[ + +EBLK +CONC DZ,\.RPCNT,RB: 0 +BBLK + MOVEM U,TTYACS-B+U + JSP U,DZRBK + ;; ,,: + NFDZTY+,,CONC DZ,\.RPCNT,BA + +EBLK +CONC DZ,\.RPCNT,XB: 0 +BBLK + MOVEM U,TTYACS-B+U + JSP U,DZXBK + ;; ,,: + NFDZTY+,,CONC DZ,\.RPCNT,BA + +];DZ11NB + +DEFINE DZSAV + MOVEM A,TTYA + MOVE A,[B,,TTYACS] + BLT A,TTYACS-B+ ;SAVE ALL ACS BUT 0, A AND U... + MOVE A,-3(U) ;Get return address + MOVEM A,TTYBRK ;Save it in TTYBRK + MOVE P,TTYPDP ;Stack + PUSH P,[TTYRET] ;Set up return address + HRRZ C,(U) ;Get Unibus address + HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board +TERMIN + +; DZ11 receiver interrupts (actually silo overflow) +DZRBK: DZSAV ;Save ACs and setup parameters + IORDI A,%DZRCS(C) + TRNN A,%DZCRD ;Character ready? + JRST [ AOS DZRSPR ;Count spurious interrupts + POPJ P, ] +DZRBK1: IORDI A,%DZRDR(C) + TRNN A,%DZDDV ;Data valid? + POPJ P, ;Nope, got it all + ; If parity must be hacked, it should be done here + LDB D,[.BP %DZLM,A] ;Get line number + ANDI A,%DZTCM ;Get character + ADD I,D ;Get TTY number + CAIL I,NFDZTY+NDZTYS + BUG + JRST NTYI1 + +; The following code can't work because I found the place where NTYI1 +; clobbers U (Alan 3/26/86): +; +; PUSHJ P,NTYI1 ;Process the input +; HRRZ C,(U) ;Get Unibus address +; HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board +; JRST DZRBK1 + +; DZ11 transmitter interrupts +DZXBK: DZSAV ;Save ACs and setup + AOS DZXINC ;Count interrupts +DZXBK1: IORDI A,%DZRCS(C) + TRNN A,%DZCTR ;Transmitter ready? + POPJ P, + LDB D,[.BP %DZLM,A] ;Get line number + ADD I,D ;ITS terminal number of this line + CAIL I,NFDZTY+NDZTYS + BUG + AOS DZXCHC ;Count characters sent + PUSHJ P,TYPSC ;Merge with the rest of the world + HRRZ C,(U) ;Get UB address of board again + HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board + JRST DZXBK1 ;Try to send another, maybe we'll get lucky + +];DZ11P + +IFN KL10P,[ +;HANDLE INTERRUPTS FROM THE CONSOLE PDP11 VIA THE DTE20 +;CODE FOR HANDLING MULTIPLE CONSOLES, BLOCK TTY OUTPUT, ETC. +;IN THE FUTURE ETHERNET STUFF WILL GET ADDED HERE. + +TTDTE1: CONI DTE,DTECNI ;SAVE FOR DEBUGGING + CONSZ DTE,460 ;TO11 ERROR OR TO10 DONE OR TO10 ERROR + BUG PAUSE,[DTE20 ERROR, CONI=],OCT,DTECNI + CONSZ DTE,100 ;TO11 TRANSFER COMPLETE + JRST [ CONO DTE,100 ;CLEAR TO11 TRANSFER COMPLETE + SETZM DTEBBY ;BUFFER NO LONGER BUSY + JRST .+1 ] + CONO DTE,%DBL10+40 ;CLEAR DTE20 INTERRUPTING STATE + SKIPGE A,DTETYI ;CHECK FOR TTY INPUT AVAILABLE + JRST TTDTE2 + SETOM DTETYI ;AVAILABLE. INDICATE HAS BEEN GOTTEN. + CONO DTE,%DBL11 ;SIGNAL 11 THAT WE'RE READY FOR MORE. + HLRZ I,A ;GET LINE NUMBER + CAIL I,NFETY ;CHECK IT + CAIL I,NFETY+NETYS + BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11] + PUSHJ P,NTYI1 ;PROCESS THE INPUT + JRST TTDTE1 ;CHECK FOR MORE + +TTDTE2: MOVEI A,SCRHNG ;IF HANGUP/DIALIN, SIGNAL SYSTEM JOB TO HANDLE IT + SKIPL DTEHNG + IORM A,SUPCOR + SKIPN DTEBBY ;DON'T CHECK FOR OUTPUT DONE IF BUFFER BUSY + SKIPGE A,DTEODN ;CHECK FOR TTY OUTPUT DONE + POPJ P, ;NOTHING, DISMISS INTERRUPT + SETOM DTEODN ;INDICATE SIGNAL HAS BEEN RECEIVED + HLRZ I,A ;GET LINE NUMBER + CAIL I,NFETY ;CHECK IT + CAIL I,NFETY+NETYS + BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11] + HRRZS A ;SET UP MULTI-CHARACTER TRANSFER, + HRRZ B,TTOALC(I) ;SETTING MAX# CHARACTERS FROM ELEVEN'S BUFFER SIZE + CAIGE B,(A) ;DON'T SEND MORE CHARACTERS THAN ALLOCATED + MOVE A,B + CAILE A,DTEOBL ;DON'T EXCEED SIZE OF OUR BUFFER + MOVEI A,DTEOBL + MOVEM A,DBBCC + MOVEM A,DBBCC1 + MOVE A,[441000,,DTEOBF] + MOVEM A,DBBBP + JRST TYP ;GO FILL OUTPUT BUFFER +];KL10P + +IFN DL10P,[ +;HANDLE THE DL-10 (A PDP-11 FRONT END FOR THE KL-10). +;ALL INTERRUPTS FROM DL-10 COME HERE. + +TTDLB0: CONO DLC,10+TTYCHN ;CLEAR INTERRUPT FLAG + SKIPN DL10F ;IGNORE DL10 IF IT IS MARKED OUT OF SERVICE. + POPJ P, +IFN CHAOSP, IFN DLCP, PUSHJ P,DLCWAK ;SEE IF INTR IS FOR CHAOS NET +IFN T300P,[ ;CHECK FOR T-300 INTERRUPT, PASS TO DISK LEVEL IF SO + SKIPE DSCDON + CONO PI,DSKRQ +];T300P + SKIPE I,DL10IL ;IS INPUT AVAIL? IF SO, READ WHICH LINE + PUSHJ P,TTDLIN ;AND PROCESS THE CHARACTER. + MOVEI A,SCRHNG ;DOES THE 11 SAY A MODEM WAS DISCONNECTED? + SKIPE DL10CL + IORM A,SUPCOR ;IF SO, TELL SYS JOB TO TAKE APPROPRIATE ACTION. + SKIPN DL10LN ;DON'T CHECK OUTPUT-DONE IF OUTPUT BUFFER IS BUSY + SKIPN I,DL10OD ;OUTPUT DONE ON SOME TTY? + POPJ P, + MOVE A,DL10BS ;YES, GET 11'S BUFFER SIZE AND + SETZM DL10OD ;MAKE COMMUNICATION CHANNEL FREE FOR -11 AGAIN + HRRZ B,TTOALC(I) + CAMLE A,B + MOVE A,B ;DON'T SEND MORE CHARACTERS THAN TERMINAL HAS ALLOCATION FOR + MOVEM A,DBBCC ;INIT CHARACTER COUNTERS TO SIZE OF BUFFER IN 11 + MOVEM A,DBBCC1 + MOVE A,[441000,,DL10BF] + MOVEM A,DBBBP ;INIT B.P. USED BY 10 TO STORE INTO BUFFER. + JRST TYP ;GO FILL UP THE OUTPUT BUFFER + +TTDLIN: MOVE A,DL10IC ;GET THE CHARACTER TYPED IN + SETZM DL10IL ;FREE THE INPUT CHANNEL SO 11 CAN USE IT AGAIN. + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + JRST NTYI1 ;AND PROCESS THE INPUT. +] + +IFN DPKPP,[ +DPTO1: CONI DPK,A + LDB I,[220400,,A] + ADDI I,NFDPTY + SKIPL @DPKC-NFDPTY(I) + SETOM @DPKC-NFDPTY(I) + LDB J,[$TTOSP,,TTYTYP(I)] ;GET OUTPUT SPEED CODE. + CAIL J,LDPSPT + MOVEI J,LDPSPT-1 + HRRZ A,TTOALC(I) + CAMLE A,DPSPT(J) + MOVE A,DPSPT(J) ;# CHARS BUFFER SPACE FOR THAT SPEED. + MOVEM A,DBBCC + MOVEM A,DBBCC1 + MOVE A,DBBFP-NFDPTY(I) + MOVEM A,DBBBP ;BP FOR STORING CHARS. + MOVSM A,@DPKP-NFDPTY(I) + JRST TYP0 + +DPTI1: DATAI DPK,A + LDB I,[220400,,A] + ADDI I,NFDPTY + JRST NTYI1 +] +IFN TK10P,[ +NTY1: CONSZ NTY,400000 + POPJ P, ;SCANNER NOT STOPPED + CONI NTY,I ;READ IN TTY # +IFE NNTYS-10,LDB I,[110300,,I] +IFE NNTYS-20,LDB I,[100400,,I] +IFN *,.ERR + CAIL I,NNTYS + BUG + ADDI I,NFNTY ;CALCULATE CONSOLE # + CONO NTY,@TTYLT(I) ;SELECT APPROPRIATE TTY + CONSZ NTY,20 + JRST TYPSC ;DONE FLAG ON TYPEOUT + CONSO NTY,40 + JRST TTYRT2 ;THIS TTY NOT REALLY UNHAPPY + DATAI NTY,A + JRST NTYI1 + +TTYRT2: CONO NTY,200000+TTYCHN + JRST TTYRET +] + +IFN MTYP,[ +MTY1: CONI MTY,I + LDB I,[140500,,I] ;GET SUBDEVICE + CAIL I,NMTYS + JRST MTY2 ;NOT A VALID # + ADDI I,NFMTY + CONO MTY,@TTYLT(I) + CONSO MTY,40 ;INPUT DONE + JRST MTY6 + DATAI MTY,A + JRST NTYI1 + +MTY6: CONSO MTY,10 ;OUTPUT DONE + POPJ P, + HRRZ A,TTOALC(I) + CAILE A,MTYNC + MOVEI A,MTYNC + MOVEM A,DBBCC ;# CHARS CAN GIVE AT ONCE. + MOVEM A,DBBCC1 + SETZM MTYOW ;SET UP WORD TO FILL WITH OUTPUT CHARS. + MOVE A,[440700,,MTYOW] + MOVEM A,DBBBP ;SET UP BP FOR STUFFING THAT WORD. + JRST TYP + +MTY2: CONSZ MTY,10 + JRST MTY3 ;OUTPUT + CONSZ MTY,40 + DATAI MTY,A ;INPUT + POPJ P, ;AND IGNORE + +MTY3: LSH I,12. + CONO MTY,200+TTYCHN(I) ;CLEAR OUTPUT DONE FLAG + POPJ P, +] + +IFN NOTYS,[ +GOTTY: CONSZ TTY,10 + JRST TYPSC ;TTO DONE + CONSO TTY,40 + POPJ P, ;NONE + DATAI TTY,A ;TTI DONE, READ CHR + JRST NTYI1 +] + +;PROCESS INPUT INTERRUPT WITH CHARACTER IN A, TTY # IN I + +OVHMTR TTI ;TTY INPUT INTERRUPT LEVEL + +;ENTER HERE FOR "HARDWARE" TTYS, LOW 8 BITS OF A ARE THE INPUT, OTHER BITS ARE GARBAGE +NTYI1: +IFN NNVTTS,[ + CAME I,NOVATT ;SKIP IF THIS TTY IS NOVA + JRST NTYI3 + TRZE A,200 ;SKIP IF DATA AND NOT TTY # + JRST NTYI2 ;SET TTY # + SKIPGE I,NVIPTT ;CURRENTLY SELECTED CONSOLE ON INPUT + POPJ P, ;NONE SELECTED +NTYI3:] +IFN TTLPTP,[ + CAMN I,LPTTTY + JRST INLPT +] + ANDI A,377 ;FLUSH EXTRANEOUS BITS, KEEP LOW 7 + MOVE H,TTYOPT(I) + TRNN H,%TPMTA ; OR KEEP LOW 8 IF 8TH IS HARDWARE META KEY + ANDI A,177 +;ENTER HERE FOR TTYS WHICH MAY INPUT IN FULL-CHARACTER-SET +NTYI5: MOVEM I,LOCTTY ;TTY CHAR ACTUALLY TYPED ON + MOVSI U,%TSLCZ + ANDCAB U,TTYSTS(I) ;CLEAR LAST CHR ^Z BIT + MOVE Q,TTYCOM(I) + MOVE R,TTYTYP(I) + MOVE H,TTYOPT(I) + TRNE H,%TPMTA ;PROCESS HARDWARE META KEY IF PRESENT + TRZN A,200 + CAIA + IORI A,%TXMTA + ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC ;FLUSH MEANINGLESS BITS. + TLNE H,%TOALT ;IF THIS TTY WANTS IT, MAYBE STANDARDIZE ALTMODES + PUSHJ P,TTYSAM + HRRZ D,TTYIPC(I) + MOVEM D,LTTYIPC ;REMEMBER INPUT RTN FOR DEBUGGING + MOVE D,TYBPC(I) + MOVEM D,LTYBPC + JRST (D) ;PROCESS THE CHARACTER AND RETURN. + +IFN NNVTTS,[ +NTYI2: JUMPE A,CPOPJ + ADDI A,NFNVTY + CAIGE A,NFNVTY+NNVTTS + MOVEM A,NVIPTT ;SELECT CONSOLE + POPJ P, +] + +IFN TTLPTP,[INLPT: MOVE A,TIME + MOVEM A,LPTTIME + POPJ P, +] + +SUBTTL HANDLE ^\ CODES +;OR PASS CHARACTERS ON TO NEXT LEVEL OF INPUT +;PROCESSING IF NO ^\ CODE IS IN PROGRESS. + +;THIS IS THE NORMAL VALUE OF TYBPC FOR ALL TTY'S; IT IS THE ONLY POSSIBLE VALUE +;FOR A TTY WHOSE %TPCBS AND %TPTEL ARE 0. +TYBN: TRNE H,%TPPRN + PUSHJ P,TYBPRN + TRNN H,%TPCBS+%TPTEL + JRST TYBRT2 ;IF NOT ENABLED, JUST PASS CHAR TO NORMAL INPUT LEVEL. +; USED TO CLEAR %TXSFT (NOW %TXSUP) BEFORE CHECKING FOR ^\ +; MOVEI E,(A) +; ANDCMI E,%TXSUP + CAIN A,^\ + TRNN H,%TPCBS + JRST TYBCR1 ;IF NOT AN ENABLED ^\, GO CHECK FOR SPECIAL CR HANDLING + JSP D,TYBRED ;READ THE CHARACTER AFTER THE ^\ + CAIGE A,100 ;^\ FOLLOWED BY @ THROUGH _ IS THE HIGH BITS FOR THE NEXT CHARACTER. + JRST TYBCTL ;^\ FOLLOWED BY A CONTROL CHAR, ETC. IS A SPECIAL HACK. + ANDI A,<%TXCTL+%TXMTA+%TXSUP+%TXTOP>_-7 + LSH A,7+18. ;GET THE EXCESS OVER 100 AND SHIFT BY 7, + HRRI A,TYBPFX ;AND STORE IN LH OF TYBPC + MOVEM A,TYBPC(I) + POPJ P, ;RETURN. NEXT CHAR COMES TO TYBPFX + +TYBPFX: HLRZ D,TYBPC(I) ;GET THE HIGH BITS READ IN LAST TIME + IOR A,D ;AND MERGE INTO THE CHAR JUST READ IN +TYBRET: MOVEI D,TYBN ;RESET ^\ STATUS TO NORMAL +TYBRT1: MOVEM D,TYBPC(I) +TYBRT2: MOVE E,TIME + MOVEM E,TTITM(I) ;UPDATE TIME OF LAST INPUT ON THIS TTY. +;NOW DETECT SPECIAL TOP-CHARS THAT SHOULD NOT ECHO +;AND SHOULD BE IGNORED IN COM MODE OR IN ^_ COMMANDS. + SETZ E, ;WE SET E TO -1 BELOW FOR THOSE CHARACTERS. + MOVE D,TTYSTA(I) + TLNE D,%TANEC ;IF COUNT OF DON'T-ECHO CHARS IS >0, + JRST [ SUB D,[<.DPB 1,.BP %TANEC>,,] ;DECREMENT IT + SETO E, ;AND DON'T ECHO THIS ONE. + JRST TYBRT3] + MOVE E,A ;IS THIS INPUT REALLY FOR LOCAL EDITING PROTOCOL? + ANDI E,%TXTOP+%TXASC ;THAT IS, TOP-E OR TOP-S, OR THE CHARACTER FOLLOWING ONE? + CAIE E,%TXTOP+"E + CAIN E,%TXTOP+"S ;DON'T ECHO OR INTERRUPT FOR TOP-S OR TOP-E, + TLO D,<.DPB 1,.BP %TANEC> ;OR THE CHAR THAT FOLLOWS IT. + CAIN E,%TXTOP+"T ;DON'T ECHO OR INT FOR TOP-T, OR FOLLOWING 3 CHARS. + TLO D,<.DPB 3,.BP %TANEC> + CAIE E,%TXTOP+"Y ;GRAPHICS INPUT CMDS TAKE 5 ARG CHARS. + CAIN E,%TXTOP+"X + TLO D,<.DPB 5,.BP %TANEC> + SETZ E, + TLNE D,%TANEC + SETO E, +TYBRT3: MOVEM D,TTYSTA(I) + MOVEM E,LEPCHR ;LEPCHR IS -1 FOR SPECIAL CHARS THAT SHOULD USUALLY BE IGNORED. + HRRZ D,TTYIPC(I) + JUMPE E,(D) ;IN WHICH CASE, DROP THIS CHAR ENTIRELY + CAIN D,TTYI ;IF IT IS NOT THE NORMAL SORT OF INPUT. + JRST (D) + POPJ P, + +;COME HERE FOR ^\ FOLLOWED BY A CHARACTER < 100. +TYBCTL: CAIN A,^A ;^\^A => ALLOCATE OUTPUT CHARS. + JRST TYBA + CAIN A,^Z ;^\^Z => ZERO ALLOCATION + JRST TYBZ + CAIN A,^I ;^\^I => INFINITY ALLOCATION + JRST TYBI + CAIN A,^R ;^\^R => RESTART OUTPUT AT M.P. LEVEL. + JRST TYBR + CAIN A,^P ;^\^P => SET CURSOR POSITION AND RESTART OUTPUT AT M.P. LEVEL. + JRST TYBP + CAIN A,^\ ;^\^\ => INPUT A ^\. + JRST TYBRET + CAIN A,^C ;^\^C => SCREEN HAS BEEN SURREPTITIOUSLY CHANGED + PUSHJ P,TYBC +;RETURN TO NORMAL ^\ STATUS BUT DON'T PASS ANY INPUT UP TO NORMAL INPUT LEVEL. +TYBXIT: MOVEI D,TYBN +TYBRED: MOVEM D,TYBPC(I) ;JSP D,TYBRED TO WAIT FOR NEXT CHARACTER + POPJ P, + +TYBC: MOVSI D,%TSATY + IORB D,TTYSTS(I) + JUMPL D,CPOPJ + HLLZ E,MSKST(D) + TLZ E,#%PJATY + TLNE D,%TSCNS + IORM E,PIRQC(D) + POPJ P, + +TYBCR1: CAIN A,15 ;SEE IF ENABLED CR + TRNN H,%TPTEL + JRST TYBRT2 ;NO, JUST PASS CHAR TO NORMAL INPUT LEVEL + JSP D,TYBRT1 ;PASS CHAR TO NORMAL INPUT LEVEL BUT HACK NEXT CHAR + CAIE A,12 ;IF IT IS LF OR NULL IGNORE IT + JUMPN A,TYBRET ;BUT OTHERWISE PASS IT TO NORMAL INPUT LEVEL + JRST TYBXIT ;IN ANY CASE RESET TYBPC TO NORMAL + +TYBPRN: LDB E,[.BP %TXASC,A] + CAIE E,"( + CAIN E,"[ + XORI A,"(#"[ + CAIE E,") + CAIN E,"] + XORI A,")#"] + POPJ P, + +;^\^P - SET CURSOR POS, THEN RESTART OUTPUT AT M.P. LEVEL. +;THIS IS THE WAY TO RESPOND TO A %TDORS CHARACTER ON A SOFTWARE TTY, +;SINCE OUTPUT RESET WILL STOP OUTPUT AT M.P. LEVEL ON SOFTWARE TTY'S +;WHICH HAVE ^\ TURNED ON. +TYBP: JSP D,TYBRED ;WAIT FOR VPOS TO COME IN + CAML A,TCMXV(I) + SETZ A, + MOVEM A,TTYIVP(I) + SKIPGE TT,TTYLPP(I) + SETCA TT, + MOVEM A,TPVP(TT) + SKIPGE TTYLPP(I) + HRLM A,TTYLPS(I) + JSP D,TYBRED ;NOW WAIT FOR HPOS TO COME IN + CAML A,TCMXH(I) + SETZ A, + MOVEM A,TTYIHP(I) + SKIPGE TT,TTYLPP(I) + SETCA TT, + MOVEM A,TPHP(TT) + SKIPGE TTYLPP(I) + HRRM A,TTYLPS(I) +TYBR: HRROS TTOALC(I) ;RESTART AT M.P. LEVEL. + PUSHJ P,TYPEN2 ;REQUEUE ECHOING IF NECESSARY + JRST TYBXIT + +TYBZ: HLLZS TTOALC(I) ;SET ALLOCATION TO 0. + JRST TYBXIT + +TYBI: HLLOS TTOALC(I) ;SET ALLOCATION TO INFINITY. + JRST TYBST ;NOW MUST START THE TTY IN CASE IT WAS STOPPED DUE TO NO ALLOC. + +TYBA: JSP D,TYBRED ;^\^A => INCREMENT ALLOCATION BY + MOVE D,TTOALC(I) + TRNN D,400000 ;SKIP IF ALLOCATION = INFINITY + ADD D,A + HRRM D,TTOALC(I) +TYBST: AOSN TTYOAC(I) + XCT TTYST(I) + JRST TYBXIT + +SUBTTL NORMAL TTY INPUT HANDLER +;CLOBBERS A - E, EXPECTS R, U, I SET UP. +;R HAS TTYTYP, U HAS TTYSTS, I HAS # OF TTY. +;Also seems to expect Q/ TTYCOM and perhaps H/ TTYOPT -Alan 12/18/85 + +TTYI: CAIN A,^_ + JRST TTYICB ;CHAR IS ^_, MAYBE ENTER COM MODE. +TTYI2: CAIN A,^Z ;TEST FOR ^Z + JRST ZFLAG ;^Z TYPED +TTYI2A: JUMPL U,CPOPJ ;IGNORE CHAR IF NO USER. + TLNE U,%TSSII ;If in superimage input mode, + JRST TTYI2B ; don't check for magic chars. + CAIN A,%TXCTL+^Z ;Control-CALL is Deferred-Call + JRST [ MOVEI A,%TXACT+%TXPIE+%TXCTL+%TXTOP+"Z ;DEFERRED CALL + JRST TTYI19 ] + CAIN A,%TXTOP+"C ; CLEAR-INPUT does like TYCFLS, flushes + ; input buffer of TTY in I. + JRST TYIRS1 ; TYIRS1 does a POPJ P, for us: Hear no + ; evil, see no evil, echo no evil... +TTYI2B: TLZ A,-1 ;IF WE WERE CALLED FROM ^_-QUOTING RTN, BIT 3.1 WAS + ;SET TO FAKE OUT ABOVE JUNK. FLUSH FAKEOUT BIT. + MOVE E,TIME + MOVEM E,TTITM(I) ;REMEMBER TIME OF LAST TYPE-IN ON TTY. +TTYI11: MOVE E,TICC(I) + CAIL E,TIBS ;SKIP IF ANY ROOM LEFT IN INPUT BUFFER + JRST DING1 + MOVE C,A + ANDI C,%TXTOP+%TXASC + CAIL C,141 ;IF A LOWER CASE CHAR, + CAILE C,172 + JRST TTYI15 + MOVE C,TTYOPT(I) + TLNE C,%TOCLC ;CONVERT TO UPPER CASE IF WANTED + XORI A,40 +TTYI15: MOVE E,UPC(U) + TLZ E,#%PCUSR + CAIN E,NECHO1 ;IS THE JOB EXECUTING AN ECHOIN RIGHT NOW? + SKIPE E,TACC(I) ;IF SO, AND IF IT HASN'T HAD A BREAK CONDITION YET, + JRST TTYI12 + PUSHJ P,TTECIN ;MAYBE STORE CHAR IN USER MEMORY, AND JUST ECHO IT. + MOVEI E,0 ;E 0 IF CALLED TTECIN, NON-0 IF DIDN'T +TTYI12: TRNN A,%TXACT ;IF TTECIN DIDN'T ACTIVATE IT, THEN IGNORE TTYSET BITS + JUMPE E,TTYI19 ;AND DON'T ACTIVATE OR INTERRUPT NO MATTER WHAT. + MOVE C,LEPCHR + JUMPL C,TTYI19 ;JUMP IF LOCAL EDITING PROTOCOL COMMAND CHAR. + PUSHJ P,GETGRP ;GET 6 BIT BYTE FOR GROUP THIS CHARACTER IS IN + TLZE U,%TSINT ;IF WANT THIS CHAR TO INT. WHATEVER IT IS, + IORI B,%TGINT ;PRETEND IT'S AN INT. CHAR. + MOVEM U,TTYSTS(I) + LSH B,14 ;PUT %TXACT, %TXPIE, AND %TXMPE IN. + TRNN A,%TXECI + IORI A,(B) + ANDCMI A,%TXIGN+%TXINT+%TXCOM + TRNN B,%TXINT ;TEST INTERRUPT BIT FOR THIS GROUP + JRST TTYI19 ;OFF. DON'T INTERRUPT + HRRE B,U ;RH OF B IS USER INDEX + JUMPL B,[JRST 4,.] ;SHOULDN'T BE NO USER + HRL B,MSKST(B) ;LH OF B IS USER'S INTERRUPT MASK + TLNN B,%PITYI ;SKIP IF INTERRUPTS ON TYPE IN ENABLED + JRST TTYI5 ;DISABLED + MOVEI C,%PITYI + IORM C,PIRQC(B) ;GENERATE TYPE IN INTERRUPT REQUEST + TRO A,%TXINT ;INDICATE INTERRUPT +TTYI5: MOVE C,TYIMSK(I) ;GET TTY CHANNELS OPEN MASK + AND C,MSKST2(B) ;MASK OFF CHANNELS NOT ENABLED + JUMPE C,TTYI19 ;JUMP IF NO OPEN CHANNELS HAVE INTERRUPTS ENABLED + MOVN D,C + AND C,D ;ISOLATE LEAST SIGNIFICANT BIT + IORM C,IFPIR(B) ;GENERATE SECOND WORD INTERRUPT REQUEST + IORI A,%TXINT ;INDICATE INTERRUPT + JRST TTYI19 + +;LIKE TTYI18 BUT FOR A CHAR THAT WASN'T REALLY TYPED IN. +TTYI13: IORI A,%TXCOM + +;ECHO BUT DON'T USE AS INPUT THE CHAR IN A, +;ASSUMING IT WAS ACTUALLY TYPED IN BY USER. MUST NOT CLOBBER H, TT. +TTYI18: IORI A,%TXPIE+%TXIGN ;THIS CHAR WILL ECHO & BE IGNORED. + +;PUT CHARACTER IN A IN INPUT BUFFER, ADJUSTING ALL COUNTS AND POINTERS. +TTYI19: MOVE C,TICC(I) + CAIL C,TIBS + JRST DING1 ;NO ROOM IN INPUT BFR => COMPLAIN. + TRNE A,%TXACT ;IF ACTIVATION CHAR, COUNT IT. + AOS TACC(I) + TRNE A,%TXPIE ;IF PI ECHO CHAR, COUNT IT. + AOS ECHOC(I) + TRNE A,%TXINT ;SIMILAR FOR TINTC, TINTP IF INT. CHAR. + AOS TINTC(I) + MOVE E,TICC(I) + CAIL E,MICBAA + SKIPLE TACC(I) ;BUFFER FULL+ NO ACTV CHRS, GEN ONE + JRST TTYIS5 + AOS TACC(I) + IORI A,%TXACT +TTYIS5: MOVE E,TIIP(I) + CAMN E,TIBEP(I) ;SKIP IF NOT OFF THE END OF THE CIRCULAR BUFFER + SUBI E,TIBL ;RESET TIIP + HRRM E,TIIP(I) ;STORE BACK IN RH + IDPB A,TIIP(I) ;STORE CHARACTER IN INPUT BUFFER + AOS TICC(I) + TRNN A,%TXPIE ;IF PI ECHO NEEDED, + POPJ P, +TTYI7: MOVE C,TORM(I) + CAIL C,TOBS + SKIPL TTYERQ(I);PUT THIS TTY ON LIST OF THOSE NEEDING ECHO + POPJ P, ;UNLESS IT'S ALREADY ON. + TLNE I,-1 + BUG + MOVE C,TTERQS + MOVEM I,TTERQS + MOVEM C,TTYERQ(I) + POPJ P, + +DING1: TLNE R,%TTDDI ;SKIP IF WANT TO DING ON EXCESS INPUT + POPJ P, + MOVSI C,%TCDNG + IORM C,TTYCOM(I) + JRST TTYI7 ;TELL CLOCK LEVEL TO LOOK AT THIS TTY. + +TYCLWR: PUSHJ P,TCNRM + CAIL E,141 ;CONVERT LOWER CASE LTRS TO UPPER + CAILE E,172 + POPJ P, + SUBI E,40 + POPJ P, + +TTYSAM: ;STANDARDIZE ALT MODE (IF APPRO) + TLNE U,%TSALT+%TSSII ;SKIP IF ALT MODE NOT TO BE STANDARDIZED + POPJ P, ;DON'T STANDARDIZE ALT MODE + CAIE A,176 ;ALT MODE CAN BE 176 OR + CAIN A,175 ;175 + MOVEI A,33 ;CHANGE EITHER TO 33 + POPJ P, + +;GETS BYTE IN B, GROUP NUMBER IN C, BYTE POINTER IN D +GETGRP: PUSH P,A + PUSHJ P,TYINR2 ;NORMALIZE CHARACTER TO FIND CORRECT GROUP. + MOVE B,A + IDIVI B,5 + POP P,A + LDB C,GRPBPT(C) ;GET GROUP BITS + MOVEI D,TTYST1(I) + CAIL C,6 + JRST GETGR2 + LDB E,[301400,,SBTBL(C)] ;LOAD LH OF BYTE PTR +GETGR1: DPB E,[301400,,D] ;MAKE TTYST1 OR TTYST2 APPROPRIATE BYTE POINTER + LDB B,D + POPJ P, + +GETGR2: LDB E,[301400,,SBTBL-6(C)] + MOVEI D,TTYST2(I) + JRST GETGR1 + +DEFINE GGRPTB A,B,C,D,E +A_29.+B_22.+C_15.+D_8+E_1 +TERMIN + +GRPTBL: GGRPTB 0,0,0,0,0 + GGRPTB 0,0,6,13,7 + GGRPTB 7,0,0,11,0 + GGRPTB 0,0,0,0,6 + GGRPTB 0,0,0,0,0 + GGRPTB 0,0,10,0,0 + GGRPTB 0,0,13,3,3 + GGRPTB 3,3,3,3,3 + GGRPTB 5,5,4,4,3 + GGRPTB 4,3,4,2,2 + GGRPTB 2,2,2,2,2 + GGRPTB 2,2,2,3,3 + GGRPTB 5,4,5,3,3 + REPEAT 5,GGRPTB 1,1,1,1,1 + GGRPTB 1,5,3,5,4 + GGRPTB 4,3,1,1,1 + REPEAT 4,GGRPTB 1,1,1,1,1 + GGRPTB 1,1,1,5,3 + GGRPTB 5,3,12,0,0 + +GRPBPT: 350700,,GRPTBL(B) + 260700,,GRPTBL(B) + 170700,,GRPTBL(B) + 100700,,GRPTBL(B) + 010700,,GRPTBL(B) + +;HANDLE A CHARACTER TYPED WHILE THE TTY OWNER IS DOING AN ECHOIN. +;A HOLDS THE CHARACTER, U HOLDS THE JOB INDEX. CLOBBERS B, C, E. +;IF THE CHARACTER IS A BREAK, ACTIVATE ON IT. +;OTHERWISE, STORE IT IN THE USER'S BUFFER AND JUST ECHO IT AND DISCARD IT; +;BUT IF THAT IS IMPOSSIBLE BECAUSE PAGES HAVE BEEN SWAPPED OUT, +;JUST ACTIVATE INSTEAD. +TTECIN: HRRZ B,U ;PREVENT TIMING ERRORS BY NOT CONSIDERING + ; HIM INSIDE THE ECHOIN IF HE HAS THE + ; PROCESSOR, SINCE UPC NOT VALID. +IFE KA10P,[ ;IF HIS USER-MODE ACS ARE IN AC BLOCK 1, WE + ; HAVE TO GIVE UP SINCE THEY MIGHT BE SAVED + ; IN TTYACS OR SOME PLACE. + MOVEI C,UUOACS(U) + CAME C,AC1PTR +] ;IFE KA10P +IFN KA10P,[ ;ON KA10, DON'T DO THIS IF MPV IS SET + CONSO 20000 ;INTERRUPT OUT OF XCTR WITH PI TRAP SET +] ;KA10P ;GETS THE MACHINE VERY CONFUSED, I SUSPECT + CAMN B,USER + JRST TTECI9 + TRNN A,%TXCTL+%TXMTA+%TXSUP ;DECIDE WHETHER THIS CHAR ECHOES OR + ; BREAKS. + CAIGE A,40 ;CONTROL CHARS, EITHER 9-BIT OR ASCII, BREAK. + JRST TTECI9 ;NOTE THAT SAIL CHARS WILL HAVE %TXTOP. + CAIN A,%TXTOP+"H ;DON'T ECHO HELP CHAR. + JRST TTECI9 + LDB B,[050200,,A] ;WHICH WORD OF BREAK TABLE IS THIS CHARACTER IN? + ADD B,U ;JOB OWNING TTY + MOVE B,AC0S+Q(B) .SEE NECHOIN ;GET THAT WORD. + LDB E,[0500,,A] + LSH B,(E) ;GET THE BIT FOR THIS CHARACTER INTO THE SIGN BIT. + JUMPL B,TTECI9 ;IF BIT IS SET, THIS IS A BREAK CHARACTER. + SPM TTECIM ;SAVE PAGE MAP AND LOAD UP TTY-OWNING JOB'S MAP. + LPMR UPGML(U) +IFE KA10P,[ + JRST 2,@[%PSPCU,,.+1] ;XCTR DOESN'T WORK IF THIS BIT NOT SET + DATAI PAG,TTECIX ;SAVE ACS CONTEXT ALSO, SET PREVIOUS AC + ; CONTEXT TO AC BLOCK 2, BUT DON'T CHANGE + ; CURRENT CONTEXT WHICH MAY BE 0 OR 1. + MOVE B,[600200,,400000] .SEE SPCCTX ;THIS DATAO PAG, IS SAME AS IN + ; AC2CTX. (ALTHOUGH THERE ARE + ; A FEW SPURIOUS BITS SET ON + ; THE KS-10.) + LDB C,[330300,,TTECIX] ;BUT TRANSFER CURRENT AC BLOCK INTO IT + DPB C,[330300,,B] + DATAO PAG,B + MOVSI B,UUOACS(U) ;COPY THE JOB'S USER MODE ACS INTO THAT BLOCK. + XCTR XBW,[BLT B,17] +] ;IFE KA10P + MOVE C,AC0S+C(U) + XCTRI XRW,[MOVES E,(C)] ;MAKE SURE THE COUNT IS STILL IN CORE AND > 0. + CAIG E,0 + JRST TTECIL + MOVE B,AC0S+B(U) + XCTRI XRW,[MOVES E,(B)] ;MAKE SURE BYTE POINTER STILL IN CORE, + CAIA + JRST TTECIL + IBP E + XCTRI XRW,[MOVES (E)] ;AND THAT THE WORD THE CHARACTER WILL GO IN IS IN CORE + SKIPA E,AC0S+E(U) ; AND WRITABLE + JRST TTECIL + XCTRI XRW,[MOVES (E)] ;MAKE SURE THE BLOCK OF COUNTERS IS STILL IN CORE. + CAIA + JRST TTECIL + XCTRI XRW,[MOVES 6(E)] + CAIA + JRST TTECIL + XCTRI XBYTE,[IDPB A,(B)] ;STORE THE CHARACTER. + CAIA + BUG + XCTRI XRW,[SOS (C)] ;DECREMENT THE COUNT OF CHARS TO ECHO. + CAIA + BUG + JUMPE E,TTECI2 ;UPDATE THE BLOCK OF COUNTERS, IF THERE IS ONE. + ADDI E,2 ;THE FIRST TWO ARE IGNORED. + HRLI E,-4 ;THE NEXT FOUR ARE INCREMENTED. +TTECI1: XCTRI XRW,[AOS (E)] + CAIA + BUG + AOBJN E,TTECI1 + XCTRI XRW,[SOS (E)] ;THE SEVENTH IS DECREMENTED. + CAIA + BUG +;GOOD. CHARACTER HAS BEEN STORED IN THE USER'S MEMORY. +TTECI2: TRO A,%TXIGN\%TXPIE\%TXECI ;NOW MAKE IT ECHO. + PUSHJ P,TTECIR + POPJ P, + +;WE CAN'T HANDLE A CHARACTER, SO MAKE IT ACTIVATE SO THE ECHOIN WILL RETURN. +;TTECIL IS FOR AFTER THE MAP HAS BEEN SWITCHED. TTECI9 IS FOR BEFORE THEN. +TTECIL: PUSHJ P,TTECIR +TTECI9: IORI A,%TXACT + POPJ P, + +;RESTORE THE PAGE MAP THAT WE SAVED. +TTECIR: +IFE KA10P,[ + MOVEI B,UUOACS(U) ;COPY POSSIBLY ALTERED USER ACS BACK INTO + ; THE JOB. + XCTR XBR,[BLT B,UUOACS+17(U)] + DATAO PAG,TTECIX +] ;IFE KA10P + LPMR TTECIM + POPJ P, + +EBLK + +TTECIM: BLOCK 10 ;OUTER LEVEL MAP SAVED HERE AND RESTORED AT EXIT. +IF2 IFG UPGMLE-UPGML-10,.ERR TTECIM too short. +IFE KA10P,[ +TTECIX: 0 ;SAVED DATAI PAG VALUE. +] + +BBLK + +SUBTTL HANDLE ^Z + +ZFLAG: MOVSI U,%TSLCZ ;EVEN IF THIS BIT IN TTYSTS IS OFF, TTY MAY BE FREE + IORB U,TTYSTS(I) ;GET TTYSTS + JUMPGE U,ZFLAG2 ;(TTY IS IN USE) + SKIPGE TTYSTA(I) ;CONSOLE FREE MSG COMING OUT OR ALREADY TRYING TO ^Z + SKIPGE DEDTIM ;OR SYSTEM IS DOWN. DON'T CREATE A NEW JOB TREE. + POPJ P, + MOVN B,SYSDBG + SKIPGE SYSDBG ;IF NOT ALLOWING USERS, + CAMN I,B ;ALLOW ONLY THE SPEC'D TTY (= -C(SYSDBG) ) + JRST ZFLAG7 + MOVE B,TTYTYP(I) ;AND STY TTY'S, AS WELL AS TTY 0. + TRNN B,%TYSTY ;NOTE STELNT WILL REFUSE NETWORK LOGINS WHEN SYS BEING DEBUGGED. + JUMPN I,CPOPJ +ZFLAG7: CONO PI,PICOFF\<200_-UTCCHN> .SEE NUJBST + MOVE A,UTTYCT ;SET UP NEW USER + CAIL A,MXCZS ;BUT DON'T OVERFILL BUFFER + JRST [ CONO PI,PICON\<200_-UTCCHN> ? POPJ P,] + AOS UTTYCT + HRRZM I,@UTTYI + AOS A,UTTYI + CAIL A,UTTYS+MXCZS + MOVEI A,UTTYS + MOVEM A,UTTYI + CONO PI,PICON\<200_-UTCCHN> + MOVSI A,%TACTZ ;SAY TTY BEING ^Z'D - ELSE SYS JOB MIGHT TYPE CONSOLE-FREE MSG, + IORM A,TTYSTA(I) ;SINCE TTY IS FREE AND %TACFM IS OFF (OR WILL BE AFTER TTYINI) + JRST TTYINI + +ZFLAG4: HRR U,SUPPRO(U) +ZFLAG2: SKIPL SUPPRO(U) + TLNE U,%TSSII + JRST ZFLAG3 ;SUPER IMAGE INPUT MODE OR TOP LEVEL JOB + TLNN U,%TSCNS ;OR IN USE AS A DEVICE => DON'T TREAT ^Z SPECIALLY + JRST ZFLAG3 + MOVEI E,%PIC.Z + TDNE E,PIRQC(U) ;IF IMMEDIATE SUPERIOR DOESN'T RESPOND TO ^Z BY TAKING + JRST ZFLAG4 ;THE TTY FROM THE ^Z'ED JOB, TRY FOR HIS SUPERIOR. + IORM E,PIRQC(U) ;OTHERWISE GIVE ^Z INTERRUPT TO JOB + PUSHJ P,TYIRS1 ;DISCARD ALL PENDING INPUT BEFORE THE ^Z. + MOVEI A,^Z+%TXPIE+%TXIGN + JRST TTYI19 ;ARRANGE FOR THE ^Z TO BE ECHOED. + +ZFLAG3: MOVSI U,%TSLCZ ;CLEAR BIT + ANDCAB U,TTYSTS(I) + JRST TTYI2A ;TREAT ^Z AS ANY OTHER CHAR. + +SUBTTL HANDLE ^_ + +TTYICB: TLNE U,%TSSII ;^_ NOT SPECIAL IF TTY IS IN USE, IN SUPERIMAGE INPUT. + JUMPGE U,TTYI2 + SKIPGE DEDTIM ;DON'T ALLOW ^_ IF ITS IS DOWN + POPJ P, + JUMPGE U,TYCGTN ;DO ALLOW THEM ON ANY TTY THAT'S IN USE + SKIPGE SYSDBG ;IF ITS BEING DEBUGGED, ALLOW ^_ IN SAME CASES ^Z IS ALLOWED. + TRNE R,%TYSTY + JRST TYCGTN + MOVN B,SYSDBG + CAME B,I + JUMPN I,CPOPJ +TYCGTN: JSP D,TYCRDE ;ECHO IT, RETURN WITH NEXT CHAR TYPED. +TYCI: SETOM COMT1(I) ;CHR AFTER ^_ + PUSHJ P,TCNRM + CAIE E,^_ + CAIN E,^Z + JRST TYCI3A ;GIVE EITHER CHARACTER TO MAIN PROGRAM + CAIL E,^B + CAILE E,^D ;^B, ^C, ^D, ^F SIGNIFY META BITS BEING SPEC'D. + CAIN E,^F + JRST TYCMB + CAIL E,"0 ;DIGIT => CHARATER BEING TYPED IN BY ITS ASCII CODE. + CAILE E,"9 + JRST TYCI7 ;JUMP IF NOT A DIGIT. + MOVEI B,-"0(E) + MOVEM B,COMT1(I) ;STORE FIRST DIGIT + JSP D,TYCRDE ;ECHO DIGIT, READ ANOTHR. (TTYIPC LEFT -> TYCI4) +TYCI4: PUSHJ P,TYCI22 ;READ NUM AFTER FIRST DIGIT + JRST TYCI6 ;CHARACTER IS NON-NUMERIC + JRST TTYI18 ;ECHO THE DIGIT - IT'S ALREADY HANDLED. + +TYCI3A: TRNN H,%TP11T ;ON NON-TV TERMINALS, + MOVEI A,%TXCTL+100(E) ;MAKE QUOTED ^Z LOOK LIKE "CONTROL" AND "Z" IN FULL +TYCI3: PUSHJ P,TYCI17 ;RESTORE TTYIPC TO NORMAL, + HRLI A,1 ;PREVENT CHAR FROM BEING TAKEN AS ^Z OR ^_. + JRST @TTYIPC(I) ;HANDLE CHAR (BUT QUOTE ^_ AND ^Z) + + +TYCI22: LDB E,[700,,A] + CAIL E,"0 + CAILE E,"9 + POPJ P, ;RETURN WITHOUT SKIPPING IF NON-NUMERIC + MOVE B,COMT1(I) + LSH B,3 + ADDI B,-"0(E) + MOVEM B,COMT1(I) ;UPDATE VALUE SO FAR + JRST POPJ1 ;SKIP RETURN + +TYCMB: SETZM COMT1(I) ;^A THRU ^F SEEN - INITIALIZE, AND DECODE THE CHARACTER. + JRST TYCMB2 + +TYCMB1: IORM D,COMT1(I) ;SET THE SPEC'D META-BIT AND READ ANOTHER CHAR. + JSP D,TYCRDE ;WHICH WE THEN DECODE ... +TYCMB2: SETZ D, + PUSHJ P,TCNRM + CAIN E,^B + IORI D,%TXCTL + CAIN E,^C + IORI D,%TXMTA + CAIN E,^D + IORI D,%TXTOP + CAIN E,^F + IORI D,%TXSUP + JUMPN D,TYCMB1 ;IF CHAR WAS ^B THRU ^F, SET APPRO META-BIT AND LOOP. + CAIN E,^Q + JSP D,TYCRDE ;OTHERWISE, ^Q QUOTES, + IOR A,COMT1(I) ;JUST READ THE CHARACTER, WITH SPEC'D META-BITS MERGED IN. + JRST TYCI3 + +TYCI2: PUSHJ P,TTYI18 ;ECHO CHAR, RESET TTYIPC TO NORMAL. +TYCI17: MOVEI B,TYCG + SKIPL Q + MOVEI B,TTYI + MOVEM B,TTYIPC(I) + TLZ Q,%TCCBS+%TCCBK ;ALSO FLUSH TEMPORARY STATUS INFO. + MOVEM Q,TTYCOM(I) + POPJ P, + +TYCI6: EXCH A,COMT1(I) ;A NOW HAS CHAR REPRESENTED BY DIGITS; COMT1 HAS THE NON-DIGIT JUST TYPED IN. + ANDI A,7777 + PUSH P,I ;IF IN COME MODE, TYCI3 CALLS TYCG AND SMASHES I + PUSHJ P,TYCI3 ;SIMULATE ITS TYPE IN + POP P,I + MOVE A,COMT1(I) ;GET LAST CHARACTER TYPED + CAIN A,40 ;A SPACE GETS FLUSHED FOLLOWING DIGITS + POPJ P, + MOVE Q,TTYCOM(I) ;RESTORE ACS BASHED BY TYCG + MOVE R,TTYTYP(I) + MOVE H,TTYOPT(I) ;THIS ONE MAY BE SUPERFLUOUS + MOVE U,TTYSTS(I) + JRST @TTYIPC(I) ;PROCESS IT NORMALLY + +TCNRM: MOVE E,A + PUSHJ P,TYINR2 + EXCH E,A + POPJ P, + +TYCI7: PUSHJ P,TYCLWR ;NON-DIGIT, NON-^Z, NON-^_ AFTER ^_. + CAIN E,^U ;^U is CLEAR INPUT. + JRST TYCFLS + CAIL E,"A ;IF IT'S A LETTER, + CAILE E,"Z + JRST TYCI7A + XCT TYIQT-"A(E) ;JUST DISPATCH ON IT. + MOVEM H,TTYOPT(I) +TYCI7D: MOVEM U,TTYSTS(I) + JRST TYCI2 + +TYCI7A: CAIE E,"" ;ASIDE FROM LETTERS, " AND ^ ARE OK. + CAIN E,"^ + JRST TYCI7B +TYCI7F: MOVEI A,"? ;OTHER CHARS ARE ERRORS. +TYCI2A: PUSHJ P,TTYI13 ;ECHO A CHARACTER THAT WASN'T INPUT, AND RESET TTYCOM AND TTYIPC. + JRST TYCI17 + +TYCI7B: CAIE E,"" + TLCA U,%TSROL ;^_^ COMPLEMENTS SCROLL MODE. + TLC U,%TSSAI ;^_" COMPLEMENTS SAIL CHAR SET USAGE. + JRST TYCI7D + +TYIQT: JRST TYCA ;A => ACCEPT COM LINKS. + JRST TYCB ;B => TRIGGER A **MORE** (BLOCK TYPEOUT). + JRST TYCC ;C => CREATE COM LINK. + JRST TYCD ;D => DEFERRED CALL + JRST TYCRFT ;E => ENTER REMOTE FEED-THRU. + JRST TYCI7F ;F => ERROR. + TLC U,%TSMOR ;G => COMPLEMENT MORE-PROCESSING. + JRST TYCH ;H => HELP KEY. + TLC Q,%TCICO ;I => COMPLEMENT INPUT OVERRIDE. + JRST TYCJ ;J => Cause %PIJST interrupt. + JRST TYCK ;K => FLUSH SPEC'D TTY FROM COM LINK. + MOVEI A,^L+%TXIGN+%TXCOM ;L => CLEAR SCREEN. + TLC U,%TSMOR ;M => COMPLEMENT MORE-PROCESSING. + JRST TYCN ;N => BREAK COM LINK. + TLC Q,%TCOCO ;O => COMPLEMENT OUTPUT COM OVERRIDE. + JRST TYCI7F ;P => ERROR. + JRST TYCQ ;Q => ENTER QUERY MODE. + JRST TYCR ;R => ENTER REFUSE MODE. + JRST TYCS ;S => SLAVE ANOTHER TTY. + JRST TYCI7F ;T => ERROR. + TLC H,%TOCLC ;U => COMPLEMENT CASE-CONVERSION. + JRST TYCI7F ;V => ERROR. + JRST TYCI7F ;W => ERROR. + JRST TYCI7F ;X => ERROR. + JRST TYCQA ;Y => ACCEPT PENDING QUERIES FOR COM LINKS + JRST TYCQR ;Z => REJECT PENDING QUERIES. + +IFN .-TYIQT-26.,.ERR WRONG LENGTH TABLE. + +;PUT IN A DEFERRED CALL +TYCD: PUSHJ P,TTYI18 ;ECHO THE D + MOVEI A,%TXACT+%TXCTL+%TXTOP+"Z + PUSHJ P,TTYI19 ;PUT A DEFERRED CALL IN THE BUFFER + JRST TYCI17 ;RESET ^_ STATE + +;HELP KEY +TYCH: PUSHJ P,TTYI18 ;ECHO THE H + MOVEI A,%TXACT+%TXTOP+"H + PUSHJ P,TTYI19 ;PUT A [HELP] IN THE BUFFER + JRST TYCI17 ;RESET ^_ STATE + +;Cause %PIJST interrupt. +TYCJ: SKIPA B,[%PIJST] +TYCJ1: MOVE U,SUPPRO(U) + JUMPL U,TYCI7F ; Error if tty not in use or nobody enabled + ; for it. + TDNN B,MSKST(U) + JRST TYCJ1 + IORM B,PIRQC(U) + JRST TYCI2 ; Echo the J and reset ^_ state. + +;CLEAR INPUT +TYCFLS: CONO PI,TTYOFF ;No touching buffer while I'm frobbing it. + PUSHJ P,TYIRS1 ;Completely flush input buffer of TTY in I. + CONO PI,TTYON + MOVEI A,^U + PUSHJ P,TTYI13 ;Can echo the ^U now. + JRST TYCI17 ;Reset ^_ state. + + +TYCB: HRRZ B,I ;COME HERE FOR ^_B. + IMULI B,TPLEN*2 + MOVEI C,%TFEOP + IORM C,TPFLAG(B) + JRST TYCI2 + +TYCRFT: PUSH P,A ;COME HERE FOR ^_E. + MOVE A,TTYTYP(I) ;ARE WE A LOCAL TTY? + TRNN A,%TYDIL\%TYRLM\%TYSTY + JRST TYCRF0 ;LOCAL TTYS ARE ALLOWED TO SLAVE W/O LOGIN + TRNN A,%TYSTY ;Is it a STY? + JRST TYCRFA ; Nope + HRRZ A,STYSTS-NFSTTY(I) ;Special Check for TARAKA demons linking + MOVE A,UNAME(A) ;Is the UNAME of the owner of this STY + CAMN A,[SIXBIT /TARAKA/] ;TARAKA? + JRST TYCRF0 ;Yes, let it hack all it wants. +TYCRFA: HRRE A,TTYSTS(I) ;GET OWNER OF THIS TTY + AOJE A,TYCRF2 ;IF THIS IS A FREE TTY, DON'T LET HIM + HLRE A,UNAME-1(A) ;IS HE LOGGED IN? + AOJE A,TYCRF2 ; IF NOT, FAIL +TYCRF0: SETZ B, ;COMPLEMENT OUR %TCRFT BIT. + PUSHJ P,TYCREP ;1ST, COUNT # TTYS IN LOOP. + PUSHJ P,[ + MOVE A,TTYCOM(I) + TLNE A,%TCLFT ;IF ANY TTY IN LOOP HAS %TCLFT SET + POPJ P, ;THEN IT'S OK FOR OUR %TCRFT TO BE. + AOJA B,POPJ1] + JRST TYCRF1 ;SOME TTY IN LOOP HAS %TCLFT => OK TO SET %TCRFT. + CAIE B,2 ;ONLY 1 OTHER TTY => SET ITS %TCLFT, THEN OUR %TCRFT. + JRST TYCRF2 ;FAIL TO SET %TCRFT IF CAN'T FIND OTHER WITH %TCLFT. + MOVE A,TTYCOM(I) + MOVSI B,%TCLFT + IORM B,TTYCOM(A) +TYCRF1: TLC Q,%TCRFT + POP P,A + JRST TYCI7D + +TYCRF2: SUB P,[1,,1] + JRST TYCI7F + +;COME HERE AFTER READING UNAME FOR ^_S. B HAS IDX OF SPEC'D TTY. +;SET THAT TTY'S %TCLFT, ENSLAVING IT. CLEAR %TCLFT OF ALL OTHER TTYS +;IN THE SAME LOOP AS SPEC'D TTY. +TYCS1: PUSHJ P,TYCREP + CAIN B,(I) ;IF SPEC'D TTY NOT IN COM WITH US + CAIA + JRST TYCI7F ;THEN IT'S AN ERROR. + MOVSI A,%TCLFT + PUSHJ P,TYCREP ;CLEAR %TCLFT OF ALL TTY'S LINKED TO US, + ANDCAM A,TTYCOM(I) + JFCL + IORM A,TTYCOM(B) ;THEN SET IT FOR HIM. + POPJ P, + +;CALL WITH JSP D, ECHO CHAR IN A, RETURN WITH NEXT CHAR. +TYCRDE: HRRZM D,TTYIPC(I) + JRST TTYI18 + +;LIKE TYCRDE BUT DON'T ECHO THE CHARACTER IN A. +TYCRED: HRRZM D,TTYIPC(I) + POPJ P, + +;T -> ASCIZ STRING, ECHO ON TTY # IN I (MUST HAVE DONE TYCSET) +TYCI40: HRLI T,440700 +TYCI39: ILDB A,T + JUMPE A,CPOPJ + PUSHJ P,TTYI13 ;ECHO CHARACTER ON TTY + JRST TYCI39 + +;SET UP ACS FOR ECHOING ON TTY # IN I. +TYCSET: MOVE R,TTYTYP(I) + MOVE Q,TTYCOM(I) + MOVE U,TTYSTS(I) + POPJ P, + +;PUT TTY IN COM MODE IF IT ISN'T. TTY # IN I. +TYCI63: TLON Q,400000 + TLZ Q,%TCLFT+%TCRFT + MOVEM Q,TTYCOM(I) + JRST TYBC + +;TTY # IN I, REPEAT OVER THAT TTY AND ALL LINKED TO IT. +;INSN TO BE REPEATED FOLLOWS CALL. +;IF THE INSN DOESN'T SKIP, IMMEDIATELY RERURNS +;SKIPPING ONLY THAT INSN. ELSE RETURNS SKIPPING 2 WHEN ALL TTYS DONE. +TYCREP: PUSH P,I ;PUSH TTY STARTING WITH. + PUSH P,I ;PUSH TTY DOING NEXT. +TYCRE0: XCT @-2(P) ;(THE INSN AFTER THE PUSHJ) + JRST TYCRE1 ;IT DIDN'T SKIP, GIVE UP RIGHT AWAY. + MOVE I,(P) ;ELSE KEEP GOING, + SKIPL I,TTYCOM(I) + JRST TYCRE2 ;LAST TTY DONE NOT LINKED, THRU. + ANDI I,-1 + CAIE I,-1 ;IN COM MD BUT NOT LINKED OR + CAMN I,-1(P) ;HAVE GONE ALL AROUND CIRCULAR LIST + JRST TYCRE2 ;=> DONE. + MOVEM I,(P) ;ELSE DO THE NEXT ONE. + JRST TYCRE0 + +TYCRE2: AOS -2(P) ;RETURN SKIPPING 2. +TYCRE1: SUB P,[1,,1] + POP P,I + JRST POPJ1 + +;^_A - ACCEPT ALL PENDING AND FUTURE REQUESTS FOR COM LINKS. +TYCA: TLZ Q,%TCRFS+%TCQRY + +;^_Y - ACCEPT ALL PENDING REQUESTS FOR COM LINKS. +TYCQA: PUSHJ P,TYCI2 ;ECHO THE A OR Y. + PUSHJ P,TYCQRP ;FIND ALL PENDING QUERIES + PUSHJ P,TYCQAC ;ACCEPT EACH ONE. + POPJ P, + +TYCQAC: PUSHJ P,TYCREP ;DON'T ACCEPT A RQ FROM SOMEONE ALREADY LINKED TO US. + CAIN B,(I) + POPJ P, + MOVE H,B ;HIS TTY # IN H FOR TYCI43 + PUSHJ P,TYCSET + PUSHJ P,TYCI43 ;LINK HIM AND ME; ECHANGE I AND H. + MOVE B,I + MOVE I,H ;GET HIS # BACK IN B AND MINE IN I. + POPJ P, + +;^_R - REFUSE ALL PENDING AND FUTURE REQUESTS FOR COM LINKS. +TYCR: TLO Q,%TCRFS + TLZ Q,%TCQRY + +;^_Z - REFUSE ALL PENDING REQUESTS FOR COM LINKS. +TYCQR: PUSHJ P,TYCI2 ;ECHO THE R OR Z. + PUSHJ P,TYCQRP ;FIND ALL PENDING QUERIES + PUSHJ P,TYCQRF ;AND REFUSE EACH ONE. + POPJ P, + +TYCQRF: EXCH B,I + PUSHJ P,TYCSET ;TYPE ON REQUESTING TTY + PUSHJ P,TYCI36 ;THAT IT IS BEING REJECTED + EXCH B,I ;AND REMOVE IT FROM A QUERYING STATE. + POPJ P, + +;^_Q - ALL REQUESTS FOR COM LINKS SHOULD REMAIN PENDING UNTIL ANSWERED +;WITH ^_Y, ^_Z OR AN INVERSE ^_C. +;ALSO, LIST ALL REQUESTS THAT ARE NOW PENDING. +TYCQ: TLZ Q,%TCRFS + TLO Q,%TCQRY + PUSHJ P,TYCI2 ;ECHO THE "Q" AND RESET ALL STATUS INFO. + PUSHJ P,TYCSET + SETZ T, ;INDICATE NOTHING HAS BEEN TYPED YET. + PUSHJ P,TYCQRP ;FIND THE PENDING REQUESTS + PUSHJ P,TYCQLS ;SAY WHO EACH IS FROM. + POPJ P, + +TYCQLS: JUMPE T,TYCQL1 ;IF THIS ISN'T THE FIRST NAME MENTIONED, + MOVEI T,[ASCIZ/, /] ;SEPARATE FROM THE PREVIOUS NAME. + PUSHJ P,TYCI40 +TYCQL1: MOVE C,B ;THIS IS TTY NUMBER QUERYING US + PUSH P,C .SEE TYCI92 + PUSH P,[POPCJ-1] ;TYCI67 ALWAYS SKIP-RETURNS. + JRST TYCI67 ;TYPE THE USER'S NAME OR THE TTY NUMBER. + +; PUSHJ P,TYCQRP +; INSN +;EXECUTES INSN ONCE FOR EACH TTY QHICH IS QUERYING THE TTY IN I. +;THE QUERYING TTY'S NUMBER IS IN B. INSN MUST PRESERVE B AND I. +;A IS CLOBBERED BY TYCQRP. OTHER ACS ARE UNTOUCHED. + +TYCQRP: SETZ B, +TYCQR1: MOVE A,TTYIPC(B) + CAIE A,TYCRW + CAIN A,TYCRW2 + CAME I,COMT1(B) + JRST TYCQR2 ;TTY IN B ISN'T QUERYING TTY IN I. + XCT @(P) ;EXECUTE INSN. +TYCQR2: CAIE B,NCT-1 + AOJA B,TYCQR1 + JRST POPJ1 ;SKIP OVER INSN WHEN RETURN. + +SUBTTL HANDLE COM-LINKS + +TYCC: TLOA Q,%TCTPN ;^_C - WHEN LEAVE COM MODE MUST TYPE ^_N. +TYCK: TLO Q,%TCCBK ;SAY WE'RE DOING ^_K. + JRST TYCI19 + +TYCS: TLO Q,%TCCBS ;^_S - ENSLAVE SPEC'D TTY. +TYCI19: MOVEM Q,TTYCOM(I) + JSP D,TYCRDE ;ECHO, RETURN, COME BACK WITH NEXT CHAR. + PUSHJ P,TCNRM + CAIE E,15 ;SPACE OR CR IS 1ST CHAR, IGNORE. + CAIN E,40 + JRST TTYI18 + MOVEI B,TYCI27 + MOVEM B,TTYIPC(I) + SETZM COMT3(I) ;INIT. ACCUMULATED #. + SETZM COMT1(I) ;AND ACCUM UNAME. + +;READING CHARS AFTER ^_C (AFTER A NON-SPACE HAS BEEN SEEN) +;COMT1 ACCUMULATES SIXBIT, COMT3 OCTAL NUMBER. +;SIGN OF COMT3 SET => NONDIGIT WAS SEEN, USE THE SIXBIT. +TYCI27: PUSHJ P,TYCLWR ;CONVERT TO UPPER CASE. + CAIN E,^_ + JRST TYCI7F ;ANOTHER ^_ IS NO GOOD. + CAIE E,15 + CAIN E,40 + JRST TYCI28 ;SPACE DELIMITS UNAME OR NUMBER + CAIN E,^^ + JRST TYCI28 + CAIN E,177 + JRST TYCI7F ;RUBOUT => TYPE ? AND GIVE UP. + MOVE B,COMT3(I) ;ACCUM NUMBER IN RH OF COMT3. + LSH B,3 + ADDI B,-"0(E) + HRRM B,COMT3(I) + CAIL E,"0 + CAILE E,"9 ;NON-DIGIT SEEN => SET SIGN OF COMT3 SAYING + SETOM COMT3(I) ;CERTAINLY NOT NUMBER. + MOVE B,COMT1(I) + LSH B,6 + IORI B,-40(E) + MOVEM B,COMT1(I) ;ADD NEW CHARACTER ONTO THE END OF THE NAME + JRST TTYI18 ;EXIT TO ECHO THE CHARACTER + +TYCI28: MOVE H,Q ;SAVE SETTINGS OF %TCCBS, %TCCBK, SINCE TYCI2 WILL CLEAR THEM. + PUSH P,E + PUSHJ P,TYCI2 ;ECHO TERMINATING CHAR IN A, AND RESET ALL TO NORMAL. + POP P,E + SKIPGE B,COMT3(I) + JRST TYCI52 ;TYPEIN WASN'T NUMBER. + CAIGE B,NCT ;IS NUMBER THAT OF A TTY THAT EXISTS? + JRST TYCI53 +TYCI52: MOVE D,COMT1(I) +TYCI29: TLNE D,770000 ;LEFT ADJUST THE UNAME + JRST TYCI30 + LSH D,6 + JRST TYCI29 + +TYCI30: MOVEI U,LUBLK ;START LOOKING AT USER NUMBER 2 + MOVSI A,%TCRFS + SETO B, ;NO REFUSE-MODE TTY FOUND YET +TYCI31: ADDI U,LUBLK + CAML U,USRHI + JRST [ JUMPGE B,TYCI36 ;REFUSED + JRST TYCI7F ] ;OUT OF USERS SO GIVE ? AND RETURN + CAMN D,UNAME(U) ;SKIP IF UNAME DOESN'T MATCH + SKIPGE C,TTYTBL(U) ;SKIP IF PROCEDURE HAS THE TTY + JRST TYCI31 ;TRY NEXT PROCEDURE + HRRZ B,C ;TTY NUMBER + TDNE A,TTYCOM(B) ;IN REFUSE MODE? + JRST TYCI31 ;YES, MAY BE CRTSTY, TRY TO FIND A BETTER TTY WITH THIS UNAME +TYCI53: MOVEM B,COMT1(I) ;# OF TTY TRYING TO HACK + SETZM COMT3(I) ;IEC FLAG FOR QUERY MODE + CAIN E,^^ + SETOM COMT3(I) + TLZE H,%TCCBK ;JUMP IF DOING ^_K. + JRST TYCK1 +IFG APL,[ + CAIN B,APL ;DON'T SEND MESSAGE TO A.P. LINE + JRST TYCI7F ;(OK NOW TO SEND TO SYSTEM CONSOLE, HAS O.C.O. ANYWAY) +] + TLZE H,%TCCBS + JRST TYCS1 ;ALSO CHECK FOR ^_S. + PUSHJ P,TYCREP ;NO, IT'S ^_C. + CAIN B,(I) ;DON'T LET LINK TO SELF OR SOMEONE ALREADY LINKED TO. + JRST TYCI7F + HRRE C,TTYSTS(B) + AOJN C,TYCI34 ;TTY HAS A USER + MOVEI A,"F ;TTY IS FREE + PUSHJ P,TTYI13 ;TYPE AN F + MOVEI A,40 + PUSHJ P,TTYI13 ;FOLLOWED BY A SPACE + MOVE B,COMT1(I) ;RESTORE THAT TTY'S NUMBER. + JRST TYCI32 + +TYCI34: MOVE C,TTYSTS(B) ;TTY IN USE: AS A DEVICE? + TLNN C,%TSCNS + JRST TYCI7F ;^_C NOT ALLOWED TO TTY OPEN AS DEVICE. +TYCI32: MOVE A,TTYIPC(B) + CAIE A,TYCRW2 + CAIN A,TYCRW ;IF HE'S QUERYING ME, THEN HE AUTOMATICALLY ACCEPTS + JRST [CAME I,COMT1(B) ;REGARDLESS OF HIS %TCRFS AND %TCQRY. + JRST TYCI37 ;IF HE'S QUERYING SOMEONE ELSE, HE'S BUSY. + JRST TYCI33] + MOVE C,TTYCOM(B) + TLNE C,%TCRFS ;GIVE UP IF HE IS REFUSING ^_C'S. + JRST TYCI36 + CAIN A,TTYI ;MUNGING IPC WHILE NOT NORMAL WOULD LEAVE + JRST TYCI44 ;WHAT HE'S DOING UNFINISHED - CAUSING BUGS. + CAIE A,TYCG + JRST TYCI37 ;IPC NOT NORMAL. + MOVEM B,COMT1(I) ;IPC NORMAL BUT HE'S IN A COM LINK. + MOVE TT,I + MOVE H,B ;MY TTY # IN TT AND I, HIS IN H. + MOVEI T,[ASCIZ/ IN COM: /] + PUSHJ P,TYCI71 ;LIST ALL TTYS IN COM WITH HIM. + JFCL + MOVEI T,[ASCIZ/ +BREAK IN? /] + PUSHJ P,TYCI40 ;PRINT STRING ON MY TTY. + JSP D,TYCRED ;READ THE ANSWER + PUSHJ P,TTYI18 ;AND ECHO IT. + PUSHJ P,TYCLWR ;NORMALIZE IT AND CONVERT TO UPPER CASE IN E. + CAIE E,"Y + JRST TYCI17 ;NO => RESET US TO NORMAL AND GIVE UP. + MOVE B,COMT1(I) ;ANSWER IS YES, GO AHEAD. + MOVE A,TTYIPC(B) + CAIE A,TTYI + CAIN A,TYCG + CAIA + JRST TYCI37 ;CAN'T MUNG HIM IF IPC NOT NORMAL. + MOVE C,TTYCOM(B) + TLNE C,%TCRFS + JRST TYCI36 ;HE'S REFUSING. +TYCI33: PUSHJ P,TYCREP + CAIN B,(I) ;MAYBE HE ENTERED OUR LOOP WHILE WE WAITED. + JRST TYCI7F ;LINKING TO SOMEONE ALREADY LINKED TO CAUSES BUGS. + JRST TYCI44 ;GO AHEAD AND LINK UP. + +TYCI37: SKIPA T,[[ASCIZ/BUSY /]] ;TARGET IS BUSY. +TYCI36: MOVEI T,[ASCIZ/REFUSED /] ;TARGET IS REFUSING. + PUSHJ P,TYCI40 + JRST TYCI17 + +;NOW WE KNOW IT'S OK TO TRY TO ^_C HIM. HIS TTY # IN B, MINE IN I. +TYCI44: MOVE H,I ;PUT MY TTY # IN H, HIS IN I. + MOVE I,B + SETO TT, + PUSHJ P,TYCSET ;GET HIS TTYCOM IN Q FOR TYCI63 + PUSHJ P,TYCI64 ;TYPE MSG FROM ME ON HIM. + JFCL + MOVE A,TTYIPC(I) + CAIE A,TYCRW2 ;IF HE'S QUERYING US, NO NEED TO QUERY HIM; + CAIN A,TYCRW ;JUST PRETEND HE'S IN ACCEPT MODE. + JRST TYCI43 + MOVSI A,%TCQRY + TDNN A,TTYCOM(I) ;SKIP IF HE MUST BE ASKED + JRST TYCI43 ;HE'S IN ACCEPT MODE. + MOVEI T,[ASCIZ /- QUERYING/] ;ELSE JUST MENTION TO HIM THAT WE'RE QUERYING + SKIPL COMT3(H) + PUSHJ P,TYCI40 + MOVEM I,COMT1(H) ;AND SETTLE DOWN FOR HIM TO DO SOMETHING ABOUT IT. + MOVEI A,TYCRW + MOVEM A,TTYIPC(H) + MOVE I,H + PUSHJ P,TYCSET + MOVEI T,[ASCIZ /QUERYING /] ;TELL OUR USER THAT WE'RE WAITING FOR ANSWER. + JRST TYCI40 + +TYCI68: CAIN TT,(I) ;ENTRY TO DO FOR ALL LINKED TO HIM BUT NOT HIM. + JRST POPJ1 +TYCI64: MOVEI T,[ASCIZ / +MESSAGE FROM /] + MOVE R,LOCTTY + MOVE R,TTYTYP(R) + TRNN R,%TYSTY + JRST TYCI62 + MOVE R,LOCTTY + MOVE R,STYSTS-NFSTTY(R) + MOVE R,JNAME(R) + CAME R,[SIXBIT /PEEK/] ;THIS SEEMS TO BE A CROCK --RG +TYCI62: MOVEI T,[ASCIZ / +LINK FROM /] +TYCI71: PUSHJ P,TYCSET ;SET UP Q,R,U,W FOR HIS TTY (# IN I) + PUSHJ P,TYCI40 ;PRINT MSG <- T ON IT. + PUSH P,I ;SAVE HIS TTY #, + MOVE I,H ;GET MINE (ARG TO TYCREP) + PUSHJ P,TYCREP ;LOOP OVER ME AND ALL ALREADY LINKED TO ME. + PUSHJ P,TYCI66 + JFCL +TYCI41: POP P,I + MOVEI A,40 + PUSHJ P,TTYI13 + JRST POPJ1 + +;TYPE UNAME OF 1 OF MY TTYS ON 1 OF HIS. +TYCI66: HRRZ C,TTYCOM(H) + CAIE C,-1 + JRST TYCI72 + CAIN H,(I) ;BUT DON'T TYPE MY NAME ON HIM. + CAME TT,-4(P) + CAIA + JRST POPJ1 +TYCI72: MOVEI C,(I) ;PUT THIS TTY # IN C, + MOVE I,-4(P) ;GET HIS BACK IN I SINCE STILL TYPING ON HIM. + CAMN C,-2(P) ;IF THIS ISN'T MY TTY, + JRST TYCI67 + MOVEI T,[ASCIZ/ AND /] ;THEN IT'S SOMEONE LINKED TO ME + PUSHJ P,TYCI40 ;AND MY NAME WAS ALREADY TYPED + MOVE C,-1(P) +TYCI67: HRRE C,TTYSTS(C) ;MY USER INDEX + JUMPL C,TYCI92 + MOVE C,UNAME(C) + HLRE A,C + AOJE A,TYCI92 +TYCI91: PUSH P,C + MOVSI T,(440600,,(P)) +TYCI42: ILDB A,T + JUMPE A,POP1J1 + ADDI A,40 ;CONVERT MY UNAME FROM SIXBIT TO ASCII + PUSHJ P,TTYI13 ;ECHO CHARACTER ON HIS TTY + TLNE T,770000 + JRST TYCI42 + JRST POP1J1 + + +TYCI92: MOVSI C,(SIXBIT /T/) + LDB T,[030300,,-1(P)] + ADDI T,20 + DPB T,[300600,,C] + LDB T,[000300,,-1(P)] + ADDI T,20 + DPB T,[220600,,C] + JRST TYCI91 + +;ACTUALLY JOIN MY TTY AND HIS IN COM LINK. +;ENTER WITH HIS TTY # IN I AND MINE IN H. +;LEAVE WITH MINE IN I AND HIS IN H, TT. +TYCI43: TLO Q,%TCTPN ;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM. + PUSHJ P,TYCI63 ;PUT HIM IN COM MODE IF HE ISN'T ALREADY. + MOVE TT,I ;HIS TTY # IN TT, MINE IN H. + PUSHJ P,TYCREP ;LOOP OVER TTYS LINKED TO HIM. + PUSHJ P,TYCI68 ;PRINT OUT MSG FROM ON ALL LINKED TO HIM, NOT HIM. + JFCL + EXCH TT,H ;INTERCHANGE HIS AND MINE. + MOVE I,TT ;LOOK AT ALL LINKED TO ME. + PUSHJ P,TYCSET ;WHEN I CHANGES, RELATED ACS SHOULD ALSO CHANGE. + TLO Q,%TCTPN ;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM. + PUSHJ P,TYCI63 ;PUT HIM IN COM MODE IF HE ISN'T ALREADY. + PUSHJ P,TYCREP ;ON EACH OF MINE, GIVE NAMES OF HIS. + PUSHJ P,TYCI69 + JFCL + MOVE TT,H + MOVE A,TTYCOM(TT) ;SET UP LINK + MOVE B,TTYCOM(I) ;LINK TTYCOM WORDS + HRRE E,A + AOJN E,TYCI45 + HRRM TT,A +TYCI45: HRRE E,B + AOJN E,TYCI46 + HRRM I,B +TYCI46: HRRZ D,A + HRRZ E,B + HRRM E,A + HRRM D,B + MOVEM A,TTYCOM(TT) + MOVEM B,TTYCOM(I) + MOVEI A,TYCG + MOVEM A,TTYIPC(I) + MOVEM A,TTYIPC(TT) + POPJ P, + +TYCI69: CAIE I,(TT) ;PRINT MSG ON ONE OF MY TTYS. + JRST TYCI70 + SKIPA T,[[ASCIZ/OK /]] ;MY TTY, SAY "G". +TYCI70: MOVEI T,[ASCIZ/ +LINK TO /] + JRST TYCI71 ;DUE TO EXCH'S IN TYCI43, + ;EXCHANGE "ME" AND "HIM" IN COMMENTS IN TYCI71. + +;TTYIPC FOR A ^_C'ER WHO IS QUERYING IS EITHER TYCRW OR TYCRW2. +;THAT IS DEPENDED ON. +TYCRW: PUSHJ P,TCNRM + CAIE E,^G ;^_C'ER MAY USE ^G TO GET ATTENTION. + SKIPGE COMT3(I);IN IEC MODE CAN ALSO SAY THE NAME + JRST TYCRW4 + CAIE E,^_ ;IGNORE ALL TYPEIN EXCEPT ^G AND ^_N. + POPJ P, + JSP D,TYCRDE ;^_, ECHO IT AND GET NEXT CHAR. +TYCRW2: PUSHJ P,TYCLWR + CAIN E,"N + JRST TYCI2 + MOVEI A,"? ;^_ FOLLOWED BY OTHER THAN N. + MOVEI B,TYCRW + MOVEM B,TTYIPC(I) + JRST TTYI13 ;ECHO ? AND GO BACK TO TYCRW + +TYCRW4: PUSHJ P,TTYI18 ;^_C'ER TYPED ^G - ECHO ON HIS TTY + MOVE I,COMT1(I) ;AND ^_C'D TTY. + PUSHJ P,TYCSET + JRST TTYI13 + +;THE TTYIPC FOR A TTY IN A COM LINK NORMALLY POINTS HERE. +;ECHO OR INPUT THE CHAR ON ALL TTYS IN THE LOOP ACCORDING TO SETTINGS +;OF THE RELEVANT %TCICO, %TCLFT AND %TCRFT BITS. +TYCG: MOVE E,A + ANDCMI E,#177 .SEE TYCI3 + CAIN E,^_ ;REC CHRS IN COM MODE + JRST TYCGTN +TYCG21: PUSH P,TTYCOM(I) ;SAVE COMMUNICATE WORD. + PUSH P,I ;SAVE MY CONSOLE NUMBER + PUSH P,A ;SAVE THE CHARACTER + TLNE Q,%TCICO ;SKIP IF INPUT COM OVERRIDE OFF + PUSHJ P,TTYI2 ;PROCESS INPUT OVERRIDE + TLNN Q,%TCICO + PUSHJ P,TTYI18 ;ECHO CHR ON MY TTY IF %TCICO NOT SET, OTHERWISE GIVE TO PROGRAM + MOVE A,(P) ;RESTORE CHARACTER +TYCG5: HRRE B,TTYCOM(I) ;FIRST TTY IN CHAIN + JUMPL B,[JRST 4,.] ;I'M NOT COMMUNICATING WITH ANYONE + CAME B,-1(P) ;SKIP IF I'M COMMUNICATING WITH MYSELF +TYCG3: SKIPL C,TTYCOM(B) ;SKIP IF HE IS IN COMMUNICATE MODE (THIS POINT IS "COM IN") + BUG ;LOSSAGE + MOVE I,B ;GET HIS TTY NUMBER IN I + MOVE R,TTYTYP(I) + MOVE B,-2(P) + TLNE B,%TCRFT ;IF MY %TCRFT AND HIS %TCLFT SET, + TLNN C,%TCLFT + JRST TYCG1 + MOVSI U,%TSLCZ ;GIVE CHAR TO HIS PROGM. + ANDCAB U,TTYSTS(I) + PUSHJ P,TTYI2 ;TREAT CHAR AS INPUT FROM HIS TTY. + JRST TYCG2 ;PROCESS NEXT TTY IN CHAIN + +TYCG1: PUSHJ P,TTYI13 ;OUTPUT CHAR ON HIS CONSOLE +TYCG2: MOVE A,(P) ;RESTORE CHARACTER + HRRE B,TTYCOM(I) ;NEXT TTY IN CHAIN + JUMPL B,[JRST 4,.] ;CHAIN ENDS STRANGELY + CAME B,-1(P) ;SKIP IF DONE + JRST TYCG3 ;PROCESS NEXT TTY + SUB P,[3,,3] + POPJ P, + +;COME AFTER READING UNAME AFTER ^_K, HIS TTY # IN B. +TYCK1: PUSHJ P,TYCREP ;NO GOOD IF THAT TTY ISN'T LINKED TO ME. + CAIN B,(I) + CAIN B,(I) ;BUT NO GOOD IF IT IS ME. + JRST TYCK2 ;NO GOOD, COMPLAIN. + MOVE I,B + PUSHJ P,TYCSET ;GET HIS TTYCOM IN Q. + JRST TYCGTM ;NOW PRETEND HE DID ^_N (READ "HIM" FOR "ME") + +TYCK2: MOVE A,TTYIPC(B) + CAIE A,TYCRW + CAIN A,TYCRW2 + CAME I,COMT1(B) + JRST TYCI7F ;NOT LINKED TO THIS GUY, GIVE "?" + JRST TYCQRF ;FLUSH GUY WHO WAS QUERYING + +;^_N TYPED IN. +TYCN: TLZ Q,%TCTPN ;I DON'T NEED ^_N SUPPLIED IF I JUST TYPED IT IN MYSELF. + PUSHJ P,TYCI2 ;ECHO THE N AND STORE Q. ALSO RESTORE TTYIPC AND TTYCOM TO NORMAL. + SKIPL TTYCOM(I) + POPJ P, + +;ASSUMING THAT TTY IN I IS IN A COM LINK, UNLINK IT. +;IF ONLY ONE OTHER TTY IS IN THE LINK, REMOVE IT FROM COM MODE TOO. +TYCGTM: HRRE B,TTYCOM(I) .SEE TTYLFC + JUMPL B,[JRST 4,.] ;WASN'T COMMUNICATING WITH ANYONE + CAMN B,I + BUG ;COMMUNICATING WITH SELF +TYCGT3: HRRE C,TTYCOM(B) + JUMPL C,[JRST 4,.] ;LIST NOT CIRCULAR + CAMN C,I + JRST TYCGT4 ;B HAS TTY NUMBER OF GUY POINTING TO ME + MOVE B,C + JRST TYCGT3 + +TYCGT4: HRRZ C,TTYCOM(I) + PUSH P,B + PUSH P,C + PUSHJ P,TYCGT2 ;TAKE ME OUT OF COM MODE. + POP P,C + POP P,B + EXCH I,B + PUSHJ P,TYCSET + CAME C,I ;SKIP IF ONLY 1 IN LOOP BESIDES ME. IF SO, HE'S UNLINKED TOO. + JRST TYCGT5 +;MARK TTY IN I AS UNLINKED AND NOT N COM MODE. TYPE ^_N ON IT IF NECESSARY. +TYCGT2: HRRI Q,-1 + TLZ Q,400000+%TCLFT+%TCRFT + TLZN Q,%TCTPN + JRST TYCI17 + MOVEI T,[ASCIZ/N/] + PUSHJ P,TYCI40 + JRST TYCI17 + +TYCGT5: HRRM C,TTYCOM(I) ;TAKE ME OUT OF THE CIRCULAR LIST + MOVEI H,(B) + SETO TT, ;FOOL TEST AT TYCI66 + PUSHJ P,TYCREP ;TELL ALL THE OTHERS THAT I'VE LEFT. + PUSHJ P,TYCI73 + JFCL + POPJ P, + +TYCI73: JSP T,TYCI71 ;PRINT MSG AND MY UNAME ON TTY # IN I. + ASCIZ/ +BYE FROM / + +SUBTTL TTY OUTPUT INTERRUPT LEVEL + +OVHMTR TTO ;TTY OUTPUT INTERRUPT LEVEL + +;HANDLE AN OUTPUT INTERRUPT FROM A CHAR-AT-A-TIME CONTROLLER. +TYPSC: MOVEI B,1 + MOVEM B,DBBCC + MOVEM B,DBBCC1 + MOVE B,[444400,,STYICH] + MOVEM B,DBBBP +;HANDLE AN OUTPUT INT. ON A MULTI-CHAR CONTROLLER, ASSUMING +;COUNT AND B.P. ARE ALREADY SET UP. +TYP: LDB J,[220300,,TTYTYP(I)] ;GET TTY OUTPUT SPEED. +TYP0: ;COME HERE FOR DPK; J ALREADY SET UP. +IFN NNVTTS,[ + CAMN I,NOVATT + JRST TYP0N +] + HRRZ W,TCTYP(I) + MOVE T,TTYTYP(I) + MOVE H,TTYOPT(I) + HRRZ A,TTOALC(I) + JUMPE A,[SETOM TTYOAC(I) + JRST TYP1C] ;IF TTY HAS NO SPACE FOR ANY OUTPUT, STOP SENDING. + MOVE A,TIME + MOVEM A,TTLTM(I) ;UPDATE TIME OF LAST OUTPUT THIS TTY. +TYP0F: PUSHJ P,TYPLUP ;OUTPUT AT LEAST 1 CHAR. + SKIPGE TTYOAC(I) + JRST TYP1C + SKIPLE DBBCC ;SKIP IF OUT OF ROOM + JRST TYP0F ;CONTINUE MESSAGE +TYP1B: SKIPGE A,DBBCC + BUG ;CONTROLLER'S BUFFER OVERFILLED? + SUB A,DBBCC1 ;GET -<# CHARS WE ARE SENDING> + SKIPL E,A + BUG ;SENDING NO CHARS OR NEGATIVELY MANY? + ADD A,TTOALC(I) ;IF THE ALLOCATION ISN'T INFINITE, + TRNN A,400000 + HRRM A,TTOALC(I) ;DECREMENT IT BY # CHARS JUST OUTPUT. +IFN MTYP,[ + TRNN T,%TYMTY ;IF MTY ISN'T THE ONLY CONTROLLER, CHECK FOR THE OTHERS + JRST TYP1D + CONO MTY,@TTYLT(I) + DATAO MTY,MTYOW + POPJ P, + +TYP1D: ] +IFN DPKPP,[ + TRNN T,%TYDPK + JRST TYP1E + MOVN A,E ;- - # CHARS OUTPUT + ADDM A,@DPKC-NFDPTY(I) ;GIVES # OF CHARS FOR CONTROLLER. + XCT TTYST(I) ;TELL THE DPK THEY'RE THERE. + POPJ P, + +TYP1E:] +IFN DL10P,[ + TRNN T,%TYDL + JRST TYP1G + MOVNM E,DL10CC ;STORE # CHARS BEING SENT. + MOVE A,[340000,,DL10BF-1] + MOVEM A,DL10BP ;GIVE THE 11 ITS MAGIC POINTER TO SNARF THE BUFFER. + MOVEM I,DL10LN ;STORE LINE # OF TTY, THUS TELLING 11 TO GO AHEAD. + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, +TYP1G:] +IFN KL10P,[ + TRNN T,%TYETY + JRST TYP1I + SKIPL DTEOUT + BUG ;OVER-RUNNING PREVIOUS TRANSFER + MOVE A,[441000,,DTEOBF] ;SET UP BYTE POINTER FOR 10-11 CHANNEL + MOVEM A,DTEBPO + MOVN A,E ;NUMBER OF CHARACTERS BEING SENT + HRLI A,%DCTYO(I);SEND TYPE-OUT COMMAND, AND LINE NUMBER + MOVEM A,DTEOUT ;GIVE COMMAND TO 11 + MOVEM A,DTEBBY ;FLAG BUFFER BUSY (AND REMEMBER WHICH COMMAND FOR DEBUGGING) + MOVEI A,10. ;5-SECOND TIMEOUT FOR LOST TO-11 XFER DONE INTERRUPT + MOVEM A,DTEBBT ;WHICH SEEMS TO HAPPEN NOW & THEN FOR SOME REASON + CONO DTE,%DBL11 ;AND GIVE INTERRUPT + POPJ P, +TYP1I:];KL10P + TRNN T,%TYSTY + JRST TYP1H + MOVEI A,TOBS + CAML A,TORM(I) + POPJ P, + MOVE A,TTYBYP(I) + ILDB B,A + JUMPE B,TYPEND + POPJ P, + +TYP1H: MOVE A,STYICH ;HANDLE CHAR-AT-A-TIME CONTROLLERS. + TLNN T,%TTPAR ;GENERATE A PARITY BIT IF NECESSARY. + JRST TYPDA1 + IMUL A,[2010040201] + AND A,[21042104377] + IDIVI A,17_7 + MOVE A,B +TYPDA1: CAIL I,NFDPTY + BUG + XCT TTYDO(I) ;DATAO XXX,A + POPJ P, + +TYP1C: MOVE E,DBBCC + CAME E,DBBCC1 ;SKIP IF NOTHING TO SEND + JRST TYP1F ;SEND WHAT THERE IS + XCT TTYDFF(I) ;CLEAR OUTPUT DONE + POPJ P, + +TYP1F: AOS TTYOAC(I) + JRST TYP1B + +IFN NNVTTS,[ +TYP0N: AOSE NVTSIP ;CHAR PENDING? + JRST TYP0A ;NO + DATAO NTY,NVTSSC ;SEND CHR AFTER SELECT + POPJ P, + +TYP0A: SKIPN A,NVOPTT + .ERR Shouldn't this be using NFNVTY Instead? + MOVEI A,NOTYS+NNTYS+NNVTTS-1 + MOVEM A,NNVSEC ;SET UP END CHECK + SKIPN I,NVOPTT + MOVEI I,NOTYS+NNTYS ;INITIALIZE + SETOM NNVSFL ;SET FIRST TIME THRU FLAG + MOVE A,NVTCC + CAIGE A,10 ;SENT TOO MANY CHRS TO THIS CONSOLE W/O LOOKING AT OTHERS? + JRST TYP ;NO, LOOK AT CONSOLE + SETZM NVOPTT + SETZM NVTCC ;YES LOOK AT OTHERS +TYP0C: AOS I + CAIL I,NOTYS+NNTYS+NNVTTS + SUBI I,NNVTTS + AOS NNVSFL + JRST TYP +] + +;FEED SOME CHARACTERS FROM OUTPUT BUFFER TO THE TTY. +TYPLUP: SKIPE TTYBYP(I) + JRST TYPBP + MOVE Q,TOOP(I) + MOVE E,TORM(I) +TYPLU1: CAIL E,TOBS + JRST [ MOVEM E,TORM(I) ;OUTPUT BUFFER EMPTY + MOVEM Q,TOOP(I) + JRST TYPEND ] + MOVE D,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q ;GET NEXT CHARACTER FROM OUTPUT BUFFER + CAIL A,%TXDIS-1 ;IF DISPLAY OR CURSOR MOTION, DISPATCH. + JRST [ MOVEM E,TORM(I) ;LEAVING THE FAST LOOP + MOVEM D,TOOP(I) ;WITHOUT EATING THIS CHAR YET + CAIN W,%TNSFW ;"SOFTWARE" TTY GETS THE CODES + JRST TYPSFW ;AS THEY APPEAR IN THE BUFFER. + CAIL A,%TDMAX + JRST TYEEO1 + JRST @TYPDTB-%TXDIS(A)] + TLNN H,%TOSAI ;CTL CHARS ARE SPACING IFF SAIL CHAR SET; + CAIL A,40 ;NON-CONTROLS ARE SPACING. + AOS TTYIHP(I) +IFN MTYP,[ + JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + PUSHJ P,MNULLO + JRST .+1 ;OUTPUT IT NOW + MOVE Q,D ;BACKUP BYTE POINTER AND OUTPUT IT LATER + JRST TYPLU2] +];MTYP + IDPB A,DBBBP ;PUT INTO DEVICE BUFFER + SOSLE DBBCC + AOJA E,TYPLU1 + AOS E ;MAXIMUM AMOUNT OF CRUFT GENERATED +TYPLU2: MOVEM E,TORM(I) + MOVEM Q,TOOP(I) + POPJ P, + +IFN MTYP,[ +MNULLO: MOVE A,DBBCC ;SKIPS IF NULL MAY NOT BE OUTPUT TO MTY NOW + SETZM DBBCC + SUBM A,DBBCC1 + MOVNS DBBCC1 + CAIE A,MTYNC + JRST POPJ1 + SETZB A,MTYOW + AOS DBBCC + AOS DBBCC1 + POPJ P, +];MTYP + +;HERE TO OUTPUT CHARACTER WHEN NOT IN FAST LOOP +TYPSIO: +IFN MTYP,[ + JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + PUSHJ P,MNULLO + JRST .+1 ;OUTPUT IT NOW + POPJ P, ] ;WAIT +];MTYP + MOVEM Q,TOOP(I) ;REMOVE CHAR FROM OUTPUT BUFFER. + AOS TORM(I) + +;OUTPUT CHAR IN A TO TTY, AND LOOP BACK TO TYPLUP IF THERE IS +;ROOM FOR MORE CHARS. (OTHERWISE POPJ OUT OF TYPLUP). +TYPOU2: IDPB A,DBBBP ;FOR FAST CONTROLLERS, STICK CHAR IN LOW LVL BUFFER. + SOSLE DBBCC + JRST TYPLUP ;ROOM FOR MORE CHARS. + POPJ P, + +;ACTUALLY OUTPUT A CHAR TO THE TTY (AND POPJ). +TYPOUT: +IFN MTYP,[ + TRNE T,%TYMTY + JUMPE A,CPOPJ ;MTY CAN'T HANDLE NULLS. +] + IDPB A,DBBBP + SOSGE DBBCC + BUG + POPJ P, + +TYPSFW: TRNE T,%TYSTY ;STY TTY IN SOFTWARE MODE => + JRST TYPSFS ;SEND THE 8-BIT FROB + SUBI A,%TXDIS-2 ;ELSE SEND IT, ESCAPED BY A RUBOUT, WITH 176 + CAIE A,%TDMV0-%TXDIS+2 ; SUBTRACTED FROM IT SO FITS IN 7 BITS + CAIN A,%TDMV1-%TXDIS+2 + JRST [ MOVE E,TORM(I) ;FOR %TDMV1, MUST INCREMENT THE 2 ARGS. + CAILE E,TOBS-3 + JRST TYPEND + JRST TYPSF2] + CAIE A,%TDMOV-%TXDIS+2 + JRST TYPSF0 + MOVE E,TORM(I) ;AND FOR %TDMOV, MUST INCREMENT THE 4 ARGS SO THEY'RE NOT 0. + CAILE E,TOBS-5 ;IF NOT ALL IN BUFFER, WAIT FOR THEM. TTY WILL BE STARTED AGAIN. + JRST TYPEND +IRPS TYPSF1,,TYPSF4:TYPSF3:TYPSF2:TYPSF1: ;DIGIT MANY CHARS FOLLOW +TYPSF1: DPB A,Q ;STORE PREV. CHAR, FIXED UP. + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + ADDI A,1 ;UPDATE %TDMOV ARGS BY ADDING 1. +TERMIN +TYPSF0: DPB A,Q ;OK, THE COMMANDS ARE ALTERED, SO SEND THE 177. + MOVEI A,%TXDIS-1 + JRST TYPOU2 + +IFE NETP,TYPSFS== +IFN NETP,[ +;HERE FOR OUTPUT OF 8-BIT FROB TO A SOFTWARE TTY THAT IS A STY +TYPSFS: CAIN A,%TDORS ;SKIPS INTO TYPORS +;HERE FOR %TDORS IN OUTPUT BUFFER +TYPORS: SKIPN TYPNTF + JRST TYPSIO +;HERE FOR %TDORS OUTPUT BY STY DIRECTLY INTO A NET SOCKET +IFN CHAOSP\TCPP, MOVE T,STYSTS-NFSTTY(I) ; Get flags for STY +IFN CHAOSP,[ + TLNE T,%SSCHA ; If Chaosnet, + JRST TYPOR1 ; don't send "INS" +];CHAOSP +IFN TCPP,[ + TLNN T,%SSTCP ; If TCP, send magic chars in URGENT mode. + JRST TYPOR2 + HRRZ A,STYNTI-NFSTTY(I) ; Get TCB index + SKIPL XBSTAT(A) ; Verify that COS is locked down + BUG HALT,[TCP: Buff not locked] + HLRZ T,XBOCOS(A) ; Find orig val of XBOBC + SUB T,XBOBC(A) ; Find # bytes already in buffer + CAIGE T, + BUG HALT ; Just-in-case check + MOVE H,STYORC-NFSTTY(I) ; Get magic 8-bit chars to send + TLNE H,(377_<<8.*3>+4>) ; Check 1st char + AOJA T,[TLNE H,(377_<<8.*2>+4>) ; Check 2nd char + AOJA T,[ TDNE H,[377_<8.+4>] ; Check 3rd char + AOJA T,.+1 + JRST .+1] + JRST .+1] + MOVEM T,XBSUP(A) ; Store # chars up to # including magic chars + ; as the TCP URGENT pointer. + JRST TYPOR1 +TYPOR2: +];TCPP +IFN NCPP,[ + HRRZ A,STYNTI-NFSTTY(I) ;GET NET INDEX + PI2SAF + MOVE T,IMFCQL ;IF INSUFFICIENT SPACE IN + CAIG T,2 ; THE CONTROL QUEUE, + JRST [ MOVSI T,200000 ; DEFER SENDING THIS + IORM T,IMSOC5(A) ;AND REQUEST TTY WAKEUP LATER + AOS IMNAS ;TELL 1/2 SECOND CLOCK + AOS IMNORH + MOVE T,TTYTYP(I) ;NEEDED BY TTY ROUTINES + JRST TYPEN1 ] + EXCH A,I ;A TTY IDX, I NET IDX + PUSH P,Q + PUSH P,IMPCSH + LDB T,IMSCFH + MOVEM T,IMPCSH ;SECRET ARGUMENT TO IMSTCM + JSP T,IMSTCM + 2,,1 + BUG PAUSE,[TTY: NO IMP BUFFERS AVAILABLE FOR "INS" MSG] + MOVSI B,8_10. ;INS + LDB C,IMSCLN ;LINK # + DPB C,[241000,,B] + MOVEM B,10(Q) + PUSHJ P,IMWCQ + POP P,IMPCSH + POP P,Q + MOVE I,A +] ;IFN NCPP +TYPOR1: MOVE H,TTYOPT(I) + MOVE T,TTYTYP(I) + MOVE W,TCTYP(I) + MOVEI A,STYORC-NFSTTY(I) ;TYPE OUT THE MAGIC CHARACTERS + HRLI A,440800 + JRST TYEEO2 +];NETP + +;COME HERE FROM TYPLUP WHEN THERE'S NOTHING TO TYPE OUT. +;CALL ALSO FROM TT11I4 WHEN THE PDP11 SAYS THE OUTPUT BUFFER IS EMPTY. +TYPEND: PUSHJ P,TYPEN2 +TYPEN1: SETOM TTYOAC(I) + POPJ P, + +;SUBROUTINE TO ACTIVATE ANY ECHOING ETC. THAT MAY NEED TO BE DONE +TYPEN2: SKIPGE TYOSW(I) ;IF ECHOING CAN BE DONE NOW, + SKIPL TTOALC(I) + POPJ P, + MOVE Q,TTYCOM(I) + TLNN Q,%TCDNG ;IS THERE ECHOING NEEDING TO BE DONE? + SKIPE ECHOC(I) + PUSHJ P,TTYI7 ;IF SO, QUEUE IT. + SKIPGE TTYLPP(I) + PUSHJ P,TTYI7 ;ALSO FORCE OUT BUFFERED CURSOR MVT. + POPJ P, + +IFN NNVTTS,[ +TYP5: CAMN I,NNVSEC ;REACHED END + AOSG NNVSFL ;AND NOT FIRST TIME + JRST TYP0C ;LOOK AT OTHER NOVA CONSOLES + MOVE I,NOVATT + JRST TYP1C +] + +;IF TTYBYP ISN'T 0, IT IS B.P. TO ASCIZ STRING TO TYPE. +;COME HERE TO OUTPUT THE NEXT CHAR OF THE STRING OR CLEAR TTYBYP. +TYPBP: ILDB A,TTYBYP(I) + TRZE A,400 ;KLUDGE FOR C-100 (and others) TO GET NULLS OUT +IFE MTYP,JRST TYPOU2 +.ELSE [ JRST [ TRNE T,%TYMTY + PUSHJ P,MNULLO ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + JRST TYPOU2 ;OUTPUT THE NULL NOW + MOVSI A,100000 ;BACK UP BYTE POINTER + ADDM A,TTYBYP(I) + POPJ P, ] ;OUTPUT PARTIAL WORD THEN SEND NULL NEXT TIME +];MTYP + JUMPN A,TYPOU2 ;NOT END => OUTPUT THE CHAR. + MOVE A,@TTYBYP(I) ;AT END, CHECK FOR SPECIAL + TRNE A,1 ; TEKTRONIX DELAY KLUDGE + JRST TYPBP1 +TYPBP2: CLEARM TTYBYP(I) ;END OF ASCIZ STRING. + JRST TYPLUP + +TYPBP1: MOVSI B,7700 ;CLEAR SIZE FIELD + ANDCAB B,TTYBYP(I) + LDB A,[$TTOSP,,TTYTYP(I)] + MOVM A,BAUDRT(A) ;GET BITS PER SECOND + MOVE B,1(B) ;GET SPECIFICATION WORD SAYING WHAT PADDING WE WANT. + CAMN B,[SETZ] + JRST TYPBP3 ;JUMP IF SPECIAL KLUDGE FOR TEKTRONIX + JUMPG B,TYPBP4 ;JUMP IF PADDING INDEPENDENT OF VPOS. +; this is fixed elsewhere now. +; MOVE Q,TCTYP(I) ;IS THIS AN H19 +; CAIN Q,%TNH19 ;H19'S HAVE TO BE PADDED WITH NUL's +; JRST TYPBP8 ; SO HANDLE THEM SPECIALLY + PUSHJ P,TYPBP6 ;CALCULATE NUMBER OF CHARACTERS OF PADDING NEEDED + JRST TYPBP5 + +TYPBP4: IMUL B,A ;1000. * NUMBER OF BITS PADDING + IDIVI B,10000. ;NUMBER OF CHARACTERS PADDING (NOTE ROUND-DOWN) +TYPBP5: SETZM TTYBYP(I) ;IN CASE NO PADDING REQUIRED + PUSHJ P,TYMPAD ;PUT THE PADDING BYTE POINTER INTO TTYBYP + JRST TYPLUP + +TYPBP3: IDIVI A,9 ;GET CHARACTERS PER 1.1 SECOND + SKIPL TTYIHP(I) ;KLUDGE KLUDGE + MOVNM A,TTYIHP(I) ;BUT IT'S GOTTA BE STORED SOMEPLACE + AOSL TTYIHP(I) + JRST TYPBP2 ;SIGH, DELAY COMPLETED + MOVEI A,^V ;NOT YET COMPLETED, SEND ANOTHER PAD + JRST TYPOU2 + +TYPBP6: MOVMS B + IMUL A,B ;IF NEGATIVE, TAKE ABS VALUE + MOVE B,TCMXV(I) ;TIMES NUMBER OF LINES AT AND BELOW THE CURSOR. + SUB B,TTYIVP(I) + IMUL B,A ; 1000.* NUMBER OF BITS OF PADDING + IDIVI B,10000.*8. ; DIVIDE BY 10000. TO GET NO. OF CHARS OF PADDING + ; AND THEN BY 8 BECAUSE PER LINE TIMES ARE EXPRESSED + POPJ P, ; IN TERMS OF 1/8 MS FOR BETTER RESOLUTION + +;once upon a time someone thought that this might cause padding with nulls to +;happen. It didn't work. +;TYPBP8: SKIPL TTYIHP(I) ;TO EXPAND UPON A KLUDGE +; JRST [ PUSHJ P,TYPBP6 ;CALCULATE THE # OF CHARS NEEDED +; MOVNM B,TTYIHP(I) ;AND SAVE THEM AWAY TO BE COUNTED +; JRST .+1 ] +; AOSL TTYIHP(I) ;COUNT THIS CHARACTER +; JRST TYPBP2 ; DELAY COMPLETED, RESET WORLD +; SETZ A, ;NUL! +; JRST TYPOU2 ;STUFF IT IN THE BUFFER, AND FIND WAY BACK HERE + +;COME HERE TO DO CURSOR MOTION ON PRINTING TTYS. +;TT HAS DESIRED HPOS; D HAS DESIRED VPOS. +TYMPRR: MOVE B,TCMXH(I) + SUBI B,1 + CAMGE B,TTYIHP(I) + MOVEM B,TTYIHP(I) +TYMPRT: CAIN W,%TNMEM + JRST [ CAMLE D,TTYIVP(I) ;VERTICAL MOTION NEEDED, AND CURSOR NOT AT LEFT MARGIN? + SKIPN TTYIHP(I) + JRST .+1 ;(PREVENT INFINITE CR LOOP). + SETZ TT, ;START WITH A CR. + JRST TYMPH1] ;MEMOWRECK LOSES LF'ING IN MID-LINE. + CAMGE TT,TTYIHP(I) ;BACKWARD MOTION TAKES PRIORITY. + JRST TYMPH1 + CAMLE D,TTYIVP(I) ;THEN DOWNWARD MOTION. + JRST TYMPV2 + CAMLE TT,TTYIHP(I) ;THEN FORWARD MOION. + JRST TYMPHF + MOVEM D,TTYIVP(I) ;MUST BE UPWARD MOTION + JRST TYMOV8 ;WHICH IS A NO-OP ON PRINTING TTYS. + +TYMPV2: AOS TTYIVP(I) ;MOVING DOWN: DO ONE LF + MOVEI A,^J + PUSHJ P,TYPOUT + PUSHJ P,TYMOVX ;IF REACHED GOAL, SAY FINISHED. + LDB B,[$TPPLF,,TTYOPT(I)] + CAIN W,%TNTRM + ADDI B,TYMTVT-TYMPVT + CAIN W,%TNMEM + ADDI B,TYMMVT-TYMPVT + HRRZ B,TYMPVT(B) ;# PADDING AFTER LF. + JUMPN B,TYMPAD + POPJ P, + +TYMPVT: 0 ;NORMAL + 2 ;2741, MEMOWRECK +REPEAT 6,2+.RPCNT ;EXTRA +TYMTVT: 0 ;UNPADDED TERMINET + 3 ;10CPS TERMINET + 4 ;15CPS TERMINET + 10 ;30CPS TERMINET + 17 ;60CPS TERMINET + 35 ;120CPS TERMINET (MAX SPEED) + 0 + 0 +TYMMVT: 0 ;UNPADDED WRECK + 0 + 0 + 1 ;30CPS WRECK + 2 ;60CPS +REPEAT 3,0 + +TYMPHF: LDB B,[$TPPTB,,TTYOPT(I)] ;FORWARD: CAN WE DO IT WITH TABS? + JUMPE B,TYMPH6 ;TABS NOT ALLOWED ON THIS TTY. + MOVE A,TTYIHP(I) + ANDCMI A,7 ;SEE WHERE A TAB WOULD BRING US. + ADDI A,10 + CAILE A,(TT) ;BEYOND WHERE WE WANT TO GO? + JRST TYMPH6 + SUBI A,(B) ;A HAS TAB STOP - <# PADDING>-1 + CAMG A,TTYIHP(I) ;TAB FASTER THAN SPACES (INCLUDING PADDING)? + JRST TYMPH6 ;NO, USE SPACES. + ADDI A,(B) ;A HAS TAB STOP. + MOVEM A,TTYIHP(I) + MOVEI A,^I + SOJA B,TYMPT1 ;B HAS # PADDING AFTER TAB. + +TYMPH6: MOVEI A,40 ;GO FORWARD WITH SPACES + MOVE C,[AOS TTYIHP(I)] + JRST TYMPH7 + +TYMPH2: MOVEI A,^H ;GO BACKWARD WITH BACKSPACES + MOVE C,[SOS TTYIHP(I)] +TYMPH7: MOVE B,TT + SUB B,TTYIHP(I) + MOVMS B ;HOW MANY TIMES TO PUT CHAR +TYMPH8: XCT C + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY + SOJG B,TYMPH8 + JRST TYMOVX + +;COME HERE TO MOVE BACKWARDS. +TYMPH1: MOVE A,TTYIHP(I) + SUB A,TT ;A HAS # CHARS IF WE BACKSPACE. + LDB B,[$TPPCR,,TTYOPT(I)] + JUMPE B,TYMPH9 + MOVE E,B ;E HAS PADDING TYPE OF TTY, + MOVE B,TTYIHP(I) ;B HAS CURRENT HPOS. + CAIL E,<.BM $TPPCR,_-.TZ .BM $TPPCR>-TYMPHL+1 ;THIS ONE A SPECIAL $TPPCR CODE? + JRST @TYMPHT-<.BM $TPPCR,_-.TZ .BM $TPPCR>-1(E) + LDB C,[$TTOSP,,TTYTYP(I)] + SUBI C,2 ;(THIS ONLY WORKS FOR SPEED CODES 2,3,4,5) + ANDI C,3 ;(= 110, 150, 300, 1200 BAUD). + MOVE C,(C)[33. ? 20. ? 10. ? 5] + IDIV B,C ;1 PAD CHAR FOR EACH (33./20./10./5) SPACES TO MOVE. + ADDI B,1 ;I.E. MOVES AT 300/PADCODE COLUMNS PER SECOND + IMULI B,(E) ; OR 600/PADCODE COLUMNS PER SECOND AT 1200 BAUD + ADDI B,-1(E) +TYMPH9: MOVE C,D + SUB C,TTYIVP(I) ;IF WE'RE MOVING DOWN AFTER THE CR, HOW MANY LF'S? + JUMPLE C,TYMPH5 + SUB B,C ;EACH LF REDUCES # PADDING NEEDED BY CR. + CAIGE B, ;BUT CAN'T NEED LESS THAN 0 PADDING. + SETZ B, +;B HAS # CHARS PADDING NEEDED AFTER CR, IF WE DECIDE TO CR. +TYMPH5: TLNN H,%TOMVB ;HOW DO WE MOVE BACKWARD? + JRST TYMPH3 ;CAN'T BS => MUST CR AND SPACE FWD. + JUMPE TT,TYMPH3 ;GOING TO COLUMN 0 => ALWAYS CR + TLNN H,%TOOVR ;ON A GLASS TTY, IF STAYING ON THE SAME LINE, HAVE TO + JUMPLE C,TYMPH2 ; USE BACKSPACES TO NOT OBLITERATE PREVIOUS OUTPUT + LDB E,[$TPPTB,,TTYOPT(I)] + JUMPE E,[MOVE C,TT ;CAN'T USE TABS: C _ TIME IF MOVE FWD. + JRST TYMPT2] + PUSH P,B ;CAN USE TABS: SEE HOW LONG TO GO FWD + MOVE B,TT ;USING TABS. + IDIVI B,10 ;NEED C(B) TABS AND C(C) SPACES. + IMULI B,(E) ;B _ TIME NEEDED FOR TABS & PADDING. + ADDI C,(B) ;C _ TIME NEEDED TO GO FWD. + POP P,B +TYMPT2: ADDI C,1(B) ;ADD IN TIME TO CR, + PADDING. + CAMLE C,A + JRST TYMPH2 ;FASTER TO BACKSPACE. +TYMPH3: MOVEI A,^M ;OUTPUT A CR (WILL SPACE FORWARD LATER) + SETZM TTYIHP(I) ;WHEN WE COME BACK WE'LL SEE WE +TYMPT1: PUSH P,B ;NEED TO GO FORWARD. + PUSHJ P,TYPOUT + PUSHJ P,TYMOVX + POP P,B + JRST TYMPAD ;PAD THE TTY (# CHARS PADDING IN B) + +;DISPATCH TABLE FOR SPECIAL %TPPCR CODES. +TYMPHZ: TYMPEX ;EXECUPORT. + TYMP27 ;2741. + TYMPMW ;MEMOWRECK. + TYMPH5 ;CODE 7 NOT USED. +TYMPHT: TYMPHL==.-TYMPHZ + +TYMP27: IDIVI B,10. + CAILE B,14. + MOVEI B,14. + AOJA B,TYMPH5 + +TYMPMW: LDB E,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYMPM1 ;NO CHRS + MOVNS B + ADD B,TYMPMT(E) + CAMGE B,TYMMVT(E) +TYMPM1: MOVE B,TYMMVT(E) + CAMLE D,TTYIVP(I) ;BEFORE LF'ING, MEMOWRECK + JRST TYMPH3 ;MUST CR RATHER THAN BS. + JRST TYMPH5 + +TYMPMT: 0 ;MEMOWRECK MIMIMUM LINE SIZE, AS FUNCTION OF SPEED + 8 ;VIA THE $TPPLF CODE. + 11. + 22. + 43. +REPEAT 3,0 + +TYMPEX: IDIVI B,10. ;EXECUPORT: 1 PAD CHAR FOR EVERY 10 POSITIONS TO CR THRU. + ADDI B,5 + JRST TYMPH9 + +;COME HERE TO PAD A PRINTING TERMINAL: # CHARS OF PADDING IN B. +TYMPAD: AOSG A,B ;AOS COMPENSATES FOR ILDB + POPJ P, + MOVE Q,TCTYP(I) ;is this an H19? + CAIN Q,%TNH19 ;H19's have to be nullified. I mean, padded with nulls. + JRST TYMPNL + CAILE A,199. ;DON'T TRY TO PAD MORE THAN 199 TIMES, WOULD + MOVEI A,199. ; BLOW OUT AT TYPBP1 + IDIVI A,5 + MOVNS A + ADD A,TYMPA1(B) ;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS. + MOVEM A,TTYBYP(I) + POPJ P, +TYMPNL: CAILE A,399. ;we make an exception for H19's, which need a lot of + MOVEI A,399. ;padding. + IDIVI A,4 ;This works same as with rubouts, but for 9 bits + MOVNS A + ADD A,TYPNL1(B) + MOVEM A,TTYBYP(I) + POPJ P, + +;THIS IS AN ASCIZ STRING OF 199. RUBOUTS. +;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT. +TYMPA0: REPEAT 199./5, -2 +TYMPA2: -400 + +TYMPA1: 010700,,TYMPA2 + 100700,,TYMPA2 + 170700,,TYMPA2 + 260700,,TYMPA2 + 350700,,TYMPA2 + +;This is a not-quite ASCIZ string of 399. pseudo-nulls. They are 9 bits long so +;that the typeout loop will spot the high bit and see that we're not at the end. +;This is used by things that want to be padded with nulls, like h19s. +TYPNL0: REPEAT 399./4,<.BYTE 9 ? 400 ? 400 ? 400 ? 400> +TYPNL2: 400400400000 + +TYPNL1: 001100,,TYPNL2 + 111100,,TYPNL2 + 221100,,TYPNL2 + 331100,,TYPNL2 + +;DISPATCH TABLE FOR CURSOR CONTROL CMDS AND RUBOUT + TYPSIO ;RUBOUT DISPATCHES HERE +TYPDTB: OFFSET %TDMOV-. +%TDMOV::TYMOV ;MOVE CURSOR +%TDMV1::TYMOV2 ;DUMMY COMMAND CREATED BY TYMOV. + ;MAKES IT POSSIBLE FOR TYMOV TO STOP WHEN BUFFER FULL + ;AND BE REENTERED NEXT INTERRUPT. +%TDEOF::TYEEOF ;CLEAR REST OF PAGE +%TDEOL::TYEEOL ;CLEAR REST OF LINE +%TDDLF::TYEDLF ;DELETE FORWARD (FOR ERASABLE OVERPRINTING TTYS) +%TDMTF::TYEMTF ;MOTOR OFF (FOR TERMINETS) +%TDMTN::TYEMTN ;MOTOR ON (FOR TERMINETS) +%TDCRL::TYECRL ;CRLF ON DATAPOINTS, IMLACS. +%TDNOP::TYEEO1 ;NO-OP FOR SUPERDUPERIMAGE MODE. +%TDBS:: TYEBS ;BACKSPACE (FOR TTY'S WITH %TORAW SET). +%TDLF:: TYELF ;LINEFEED ("). +%TDRCR::TYERCR ;CARRET ("). +%TDORS::TYPORS ;"OUTPUT RESET" FOR SAKE OF SOFTWARE TTYS & STYS +%TDQOT::TYEQOT ;DEVICE-DEPENDENT DATA IN NEXT BYTE. +%TDFS:: TYEFS ;FORWARD ONE SPACE +%TDMV0::TYMV0 ;REPLACEMENT FOR %TDMOV +%TDCLR::TYECLR ;CLEAR THE SCREEN +%TDBEL::TYEBEL ;DING THE BELL. +%TDINI::TYEINI ;REINITIALIZE INTELLIGENT TERMINAL +%TDILP::TYEILP ;INSERT LINE POSITION, FOLLOW BY COUNT +%TDDLP::TYEDLP ;DELETE LINE POSITION, FOLLOW BY COUNT +%TDICP::TYEICP ;INSERT CHARACTER POSITION, FOLLOW BY COUNT +%TDDCP::TYEDCP ;DELETE CHARACTER POSITION, FOLLOW BY COUNT +%TDBOW::TYEBOW ;ENTER INVERSE VIDEO MODE +%TDRST::TYERST ;CLEAR ALL SPECIAL MODES (SUCH AS INVERSE VIDEO). +%TDGRF::TYEEO1 ;GRAPHICS, FLUSH IT +%TDRSU::TYERSU ;REGION SCROLL UP +%TDRSD::TYERSD ;REGION SCROLL DOWN + TYEEO1 ;NEXT 4 CODES ARE USED FOR SOME WEIRD FORM OF GRAPHICS OUTPUT + TYEEO1 ;THAT WILL EVENTUALLY BE FLUSHED. + TYEEO1 + TYEEO1 +;FOLLOWING CODES ARE FOR LOCAL EDITING TERMINALS +;NON-SOTFWARE TERMINALS DON'T HANDLE THEM, SO IGNORE THEM. +%TDSYN::TYEIG1 ;RESYNCH REPLY TO LOCAL EDITING TERMINAL. IGNORE 1 ARG. +%TDECO::TYEEO1 ;ASK TERMINAL TO TRY LOCAL EDITING BY SENDING A RESYNCH. IGNORE. +%TDEDF::TYEIG2 ;SET LOCAL EDITING TERMINAL COMMAND DEFINITION. IGNORE 2 ARGS. +%TDNLE::TYEEO1 ;STOP DOING LOCAL EDITING. IGNORE. +%TDTSP::TYEEO1 ;DISPLAYS LIKE SPACE, BUT IS PART OF A TAB. IGNORE. SHOULDN'T HAPPEN. +%TDCTB::TYEEO1 ;THIS LINE IS CONTINUED AT THE BEGINNING. +%TDCTE::TYEEO1 ;THIS LINE IS CONTINUED AT THE END. +%TDMLT::TYEIG2 ;DECLARE MULTI-POSITION CHAR FOR LOCAL EDITING. IGNORE 2 ARGS. +%TDSVL::TYEIG3 ;SAVE LINE CONTENTS. IGNORE 3 ARGS. +%TDRSL::TYEIG3 ;RESTORE LINE CONTENTS. IGNORE 3 ARGS. +%TDSSR::TYEIG2 ;SET RANGE OF COLUMNS TO SAVE. IGNORE 2 ARGS. +%TDSLL::TYEIG2 ;SET LABEL FOR LOCAL LINE SAVING. IGNORE 2 ARGS. +%TDMAX::OFFSET 0 + + +;IGNORE THIS COMMAND AND 3 ARGS. +TYEIG3: MOVE A,TORM(I) + CAILE A,TOBS-4 + JRST TYPEND + AOS A,TORM(I) + IBP Q +;IGNORE THIS COMMAND AND 2 ARGS. +TYEIG2: MOVE A,TORM(I) + CAILE A,TOBS-3 + JRST TYPEND + AOS A,TORM(I) + IBP Q +;IGNORE THIS COMMAND AND 1 ARG. +TYEIG1: MOVE A,TORM(I) + CAILE A,TOBS-2 + JRST TYPEND + AOS A,TORM(I) + IBP Q + JRST TYEEO1 + +TYEQOT: MOVE A,TORM(I) + CAILE A,TOBS-2 + JRST TYPEND + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + AOS TORM(I) + JRST TYPSIO + +TYEBEL: MOVEI A,7 + JRST TYPSIO + +;%TDMOV MOVE CURSOR COMMAND DISPATCHES HERE. +TYMOV: MOVE A,TORM(I) + CAILE A,TOBS-5 ;IF THE 4 ARGUMENT CHARS AREN'T IN THE BUFFER YET, + JRST TYPEND ;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT. + CAMN Q,TOBEP(I) ;FETCH THE NEXT 2 CHARS WHICH + MOVE Q,TOBBP(I) ;HOLD THE "OLD" POSITION + ILDB A,Q + MOVEM Q,TOOP(I) ;FLUSH FIRST TWO CHARS (AS IF WAS %TDMV0) + MOVEI C,2 + ADDM C,TORM(I) + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q + CAMGE A,TCMXV(I) + MOVEM A,TTYIVP(I) ;SET INITIAL STARTING PLACE + MOVEM B,TTYIHP(I) + JRST TYMV0A + +TYMV0: MOVE A,TORM(I) ;MAKE SURE THE TWO ARG CHARS ARE IN THE BUFFER + CAILE A,TOBS-3 + JRST TYPEND ;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT. +;DROPS THROUGH + ;DROPS IN +;%TDMOV COMMAND ON ALL TERMINALS. +TYMV0A: MOVSI C,%TCPAD+%TCFPD ;FOR DATAPOINTS, PADDING WILL BE NECESSARY NOW. + ANDCAM C,TTYCOM(I) ; ALSO, CLEAR FPD IF IT GOT LEFT ON SOMEHOW + MOVEI A,%TDMV1 ;PUT A NEW COMMAND IN OUTPUT BUFFER + DPB A,Q ; IN CASE WE FILL UP BUFFER AND HAVE TO COME BACK. + ; IN THAT CASE WILL RETURN TO TYMOV2. +;BUFFER NOW HOLDS: +; %TDMV1 ? NEW VPOS ? NEW HPOS +TYMOV2: CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) ;FETCH DESIRED POS. FROM BUFFER. + ILDB D,Q + CAML D,TCMXV(I) + SETZ D, + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB TT,Q + CAIGE W,%TNMAX ;If pointer to routine is within range, + JUMPGE W,@TYMDTB(W) ;GO TO DEVICE-DEPENDENT CURSOR POSITIONING ROUTINE + BUG + +TYMDTB: OFFSET -. +%TNPRT::SETZ TYMPRT ;PRINTING +%TNDP:: TYMDP ;DATAPOINT +%TNODP::TYMDP ;LOSING DATAPOINT +%TNIML::TYMIML ;IMLAC +%TNTEK::TYMDP ;TEKTRONIX +%TNTV:: [JRST 4,.+TYMDTB] +%TNMEM::SETZ TYMPRT ;MEMOWRECK +%TNSFW::[JRST 4,.+TYMDTB] +%TNTRM::SETZ TYMPRT ;TERMINET +%TNESC::TYMDP ;ASCII ESCAPE SEQUENCES TTY +%TNDTM::TYMIML ;DATAMEDIA +%TNRAY::TYMDP ;TELERAY 1061 +%TNHDS::TYMDP ;HDS CONCEPT-100 +%TNH19::TYMH19 ;H19 +%TNAAA::TYMAAA ;Ann Arbor Ambassador +%TNMAX::OFFSET 0 + +;DISPLAY TERMINALS THAT HAVE RELATIVE CURSOR POSITIONING +TYMDP: MOVE A,TTYIVP(I) ;CURRENT HARDWARE VERTICAL POSITION + SUB A,D ;SUBTRACT VERTICAL POSITION OF WHERE WE WANT TO BE + MOVMS A ;A IS HOW FAR WE HAVE TO GO UP OR DOWN + CAML TT,TCMXH(I) ;IF TRYING TO MOVE OFF RIGHT MARGIN, + JRST [ MOVE TT,TCMXH(I) ;CODE JUST BELOW CAUSES INFINITE LOOP + SOJA TT,.+1 ] ;SO PRETEND MOVING TO MARGIN + MOVE B,TTYIHP(I) ;COMPUTE NET CHRS TO POSITION + CAML B,TCMXH(I) ;IF WE THINK WE MOVED OFF THE END OF THE LINE, + JRST [ MOVE B,TCMXH(I) ;PRESUMABLY BY PRINTING IN THE LAST COLUMN, + SUBI B,1 ;THE CURSOR ACTUALLY STUCK IN THE LAST COLUMN + MOVEM B,TTYIHP(I) + JRST .+1 ] + SUB B,TT + MOVM C,B ;C IS HOW FAR WE HAVE TO GO HORIZONTALLY + TRNE H,%TPPTB ;IF TERMINAL HAS TABS + JRST TYMTB1 ;USE DIFFERENT CURSOR POSITIONING ROUTINE + CAMLE B,TT ;SKIP IF NOT SHORTER TO CR FIRST + MOVEI C,1(TT) ;# CHARS IF CR FIRST. + ADD A,C ;A NOW HAS TOTAL NUMBER OF CHARS TO SEND TO GET THERE + JUMPE A,TYMOV8 ;WE'RE THERE + MOVE C,D + ADDI C,1(TT) ;C HAS NUMBER OF CHARS IT WOULD TAKE IF WE HOMED UP FIRST + MOVE E,TCMXV(I) + SUBI E,1 + SUB E,D ;E HAS NUMBER IF HOME DOWN FIRST + JUMPL E,TYPCPG + ADD E,TT + CAMGE C,A + JRST TYMHU ;HOME UP SHORTER + CAMGE E,A + JSP A,TYMHD ;HOME DOWN SHORTER +TYPCPG: JUMPL B,TYMDP3 ;H POS TOO SMALL, MOVE FWD + JUMPG B,TYMDP6 ;MOVE BACKWARD (EITHER BS OR CR). +TYMDPL: MOVE B,TTYIVP(I) + SUB B,D + JUMPG B,TYMDP2 ;MOVE UP IF NECESSARY + JUMPL B,TYMDP1 ;OR DOWN. + JRST TYMOV8 ;OR WE'RE DONE. + +TYMDP3: JSP E,TYMDPP ;PAD IF NEC. + MOVE C,[AOS TTYIHP(I)] + SKIPL A,CCFS(W) ;GET FORWARD SPACE CHARACTER + JRST TYMDP7 ;IS ONE CHAR + HRRZS A + JRST TYMVT7 ;IS TWO CHARS + +TYMDP6: CAMG B,TT + JRST TYMDP8 +TYMTB6: MOVEI A,15 ;BETTER TO CR FIRST + CAIE W,%TNODP + CLEARM TTYIHP(I) + MOVEI B,1 + MOVSI C,(JFCL) + CAIE W,%TNODP + JRST TYMDP5 + MOVE E,TCMXV(I) + SUBI E,1 + CAMN E,TTYIVP(I) ;ON LOSERS, AFTER CR MUST GO LF TO TURN OFF SPOW MODE. + JRST TYMDP2 ;IF ON BOTTOM LINE, GO UP BEFORE CR SO CAN GO DOWN AFTER. + MOVE E,TTYCOM(I) + TLCN E,%TCFPD + MOVEM E,TTYCOM(I) + TLNE E,%TCFPD + JRST TYMDP5 ;JUMP IF HAVEN'T DONE CR YET + JSP E,TYMDPP ;AFTER CR, PAD + JRST TYMHU3 ;THEN GO SETZM TTYIHP(I) AND TURN OFF SPOW LATCH + +TYMDP8: JSP E,TYMDPP + MOVE C,[SOS TTYIHP(I)] + MOVEI A,%DPBS ;DATAPOINT BACK-SPACE. + JRST TYMDP7 + +TYMDP1: JSP E,TYMDPP + MOVEI A,%DPDN ;DATAPOINT LINEFEED. + MOVE C,[AOS TTYIVP(I)] + JRST TYMDP7 + +TYMDP2: JSP E,TYMDPP + MOVE C,[SOS TTYIVP(I)] + SKIPL A,CCUP(W) ;GET LINE-STARVE CHARACTER + JRST TYMDP5 + HRRZS A + JRST TYMVT7 ;IT'S TWO CHARS LONG + +TYMHU: SKIPN CCHUP(W) ;SKIP IF TTY CAN HOME UP + JRST TYPCPG + CAMLE C,E ;HOME UP IS BETTER THAN DIRECT ROUTE. + JSP A,TYMHD ;MAYBE HOME DOWN IS EVEN BETTER + CAIN W,%TNODP + JRST TYMHU1 + CLEARM TTYIVP(I) ;NO, HOME UP IS BEST. + CLEARM TTYIHP(I) +TYMHU2: MOVE A,CCHUP(W) + MOVEM A,TTYBYP(I) + JRST TYMOVX + +TYMHU1: MOVE E,TTYCOM(I) ;HERE FOR HOME UP ON DISAPPOINT + TLCN E,%TCFPD + MOVEM E,TTYCOM(I) + TLNE E,%TCFPD + JRST TYMHU2 ;JUMP IF HAVEN'T HOMED UP YET + MOVSI E,%TCPAD ;DON'T PAD AFTER HOME UP + IORM E,TTYCOM(I) + SETZM TTYIVP(I) ;AND TURN OFF THE SPOW LATCH +TYMHU3: MOVSI E,%TCFPD ;FIRST PART WILL HAVE BEEN DONE WHEN + ANDCAM E,TTYCOM(I) ; WE PUT OUT THE ONE CHAR TO GO DOWN ONE LINE + SETZM TTYIHP(I) + MOVEI B,1 ;GO DOWN ONE LINE TO RESET SPOW + JRST TYMDP1 + +TYMDP7: MOVMS B +TYMDP5: JUMPE A,[JRST 4,.] +TYMDP4: XCT C + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY + SOJG B,TYMDP4 + JRST TYMOVC + +;CAN'T OUTPUT ANY MORE: IF REACHED DESIRED POS, FLUSH THE +;%TDMV1; OTHERWISE RETURN LEAVING IT TO COME BACK HERE WHEN +;TTY CAN ACCEPT MORE OUTPUT. +TYMOVY: SOJG B,TYMOVP +TYMOVX: CAMN D,TTYIVP(I) + CAME TT,TTYIHP(I) + POPJ P, +;WE USED UP ALL THE SPACE BUT GOT WHERE WE'RE GOING. +TYMOV9: MOVEM Q,TOOP(I) ;FLUSH THE %TDMV1 COMMAND. + MOVEI B,3 + ADDM B,TORM(I) + POPJ P, + +;WE FINISHED ONE SET OF OUTPUT CHARS, & HAVE ROOM FOR MORE. +;EITHER CONTINUE MOVING CURSOR, OR LOOK FOR NEXT THING TO DO. +TYMOVC: CAME TT,TTYIHP(I) + JRST TYMDP ;HORIZ POS STILL NEEDS CHANGING. + CAME D,TTYIVP(I) + JRST TYMDPL ;VERT POS STILL NEEDS CHANGING. +TYMOV8: MOVEM Q,TOOP(I) ;FLUSH THE %TDMV1 COMMAND + MOVEI B,3 + ADDM B,TORM(I) + JRST TYPLUP ;AND GO GET NEXT THING FROM BUFFER. + +;COME HERE TO PAD DATAPOINT IF NECESSARY. +;CALL WITH JSP E,. CLOBBERS A, C. +;MAY JUMP AWAY TO PAD, IN WHICH CASE TYMDP WILL BE RE-ENTERED LATER. +TYMDPP: MOVSI C,%TCPAD + TDNE C,TTYCOM(I) ;PADDING ALREADY DONE FOR THIS COMMAND => RETURN. + JRST (E) + LDB A,[$TPPCR,,TTYOPT(I)] + JUMPE A,(E) ;RETURN IF THIS TTY NOT PADDED. + MOVE B,A + IORM C,TTYCOM(I) ;AFTER WE PAD, PADDING WON'T BE NECESSARY. + MOVEI A,177 + MOVSI C,(JFCL) + JRST TYMDP5 ;GO OUTPUT THEM. + +TYMOVP: CAIE A,177 + POPJ P, + JRST TYMPAD + +;JSP A,TYMHD IF HOME-DOWN LOOKS BEST +TYMHD: CAIE W,%TNDP + JRST (A) ;BUT HOME-DOWN ONLY WORKS ON DATAPOINTS + SETZM TTYIHP(I) ;HOME DOWN IS BEST. + MOVE C,TCMXV(I) + SUBI C,1 + MOVEM C,TTYIVP(I) + MOVE A,CCHDP + MOVEM A,TTYBYP(I) + JRST TYPLUP + +;HERE TO SEND ONE OR MORE COPIES OF AN ESCAPE SEQUENCE. +;ESCAPED CHAR IN A. # TIMES IN B. INSN TO ADJUST TTYIVP,TTYIHP IN C. +TYMVT7: MOVMS B +TYMVT5: MOVE E,TTYCOM(I) ;STOPPED IN MIDDLE OF ESC SEQ? + TLZN E,%TCFPD + JRST TYMVT4 + MOVEM E,TTYCOM(I) ;YES, SKIP INITIAL ESC + JRST TYMVT6 + +TYMVT4: MOVEI E,33 + IDPB E,DBBBP + SOSG DBBCC ;NO MORE ROOM => + JRST TYMVT3 ;STOPPED WITHIN ESC SEQUENCE +TYMVT6: XCT C ;ELSE SEND THE ESCAPED CHAR + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY ;NO ROOM => DISMISS + SOJG B,TYMVT4 ;ELSE SEND NEXT ESC SEQ + JRST TYMOVC ;FLUSH THE %TDMOV AND RETURN + +TYMVT3: MOVSI E,%TCFPD + IORM E,TTYCOM(I) + POPJ P, + +;CURSOR POSITIONING ON A DISPLAY TTY WITH TABS +TYMTB1: MOVE R,TT + IDIVI R,8 + ADD R,TYMTBC(W) ;COST OF TABBING TO DEST FROM LEFT MARGIN + MOVE W,TCTYP(I) ;RESTORE W, CLOBBERED BY IDIVI + JUMPG B,TYMTB2 ;JUMP IF MOVING BACKWARDS + JUMPE B,TYMTB3 ;JUMP IF NOT MOVING HORIZONTALLY + SKIPGE CCFS(W) + ADD C,C ;MOVING FORWARDS IS SLOW ON ESCAPE-C TYPE TERMINAL + MOVE E,TTYIHP(I) + LSH E,-3 + SUBM R,E ;COST OF TABBING FROM WHERE WE ARE NOW + CAMLE C,E + MOVE C,E ;FASTER IF TABS ARE USED + JRST TYMTB3 ;MOVING FORWARD, SO CR CAN'T HELP + +TYMTB2: CAILE C,1(R) + MOVEI C,1(R) ;BETTER TO CR FIRST +TYMTB3: ADD A,C ;TOTAL # CHARS TO BE SENT IF RELATIVE POSITIONING USED + JUMPE A,TYMOV8 ;WE'RE THERE + MOVE E,D + ADDI E,2(R) ;COST IF HOME-UP FIRST (ASSUMING HOME-UP IS 2 CHARS) + CAMG E,A + MOVE A,E ;RELATIVE POSITIONING SHOULD START WITH HOME-UP + CAILE A,4 ;COMPARE RELATIVE AND ABSOLUTE POSITIONING + TRNN H,2*%TPPTB + JRST TYMTB8 ;RELATIVE POSITIONING BETTER OR ONLY CHOICE +;USE ABSOLUTE POSITIONING, DROP INTO STRAIGHT ABS POS CODE. +;HERE FOR DIRECT POSITIONING ON IMLAC AND DATA MEDIA. SEND MAGIC CHARACTER +;FOLLOWED BY HORIZONTAL AND VERTICAL POSITION, OFFSET BY SUITABLE AMOUNT +;D FOR THE VERTICAL, TT FOR THE HORIZONTAL +TYMIML: MOVE Q,TOOP(I) ;CLOBBER OVER THE 3 CHARS IN OUTPUT BUFFER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + HLRZ A,CCDPSO(W) ;GET ABS-POSITIONING CHARACTER, IT WILL + IDPB A,Q ; BE FOLLOWED WITH VERTICAL, HORIZONTAL COORDS + MOVEM D,TTYIVP(I) ;CURSOR WILL END UP HERE + MOVEM TT,TTYIHP(I) + TRNE A,200000 + EXCH D,TT ;SEND HORIZONTAL THEN VERTICAL + HRRZ E,CCDPSO(W) ;GET TABLE INDEX + MOVE B,D ;FIRST COORD TO SEND + XCT CCDPSM(E) ;MUNG B APPROPRIATELY + ANDI B,177 ;EXTRA BITS CAUSE TROUBLE LATER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + IDPB B,Q + MOVE C,B ;SAVE + MOVE B,TT ;SECOND COORD TO SEND + XCT CCDPSM(E) ;MUNG B APPROPRIATELY + ANDI B,177 ;EXTRA BITS CAUSE TROUBLE LATER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + IDPB B,Q + ANDI A,177 ;DON'T LET TYPLUP THINK THESE CHARACTERS PRINT + TLNN H,%TOSAI + CAIL A,40 + SOS TTYIHP(I) + TLNN H,%TOSAI + CAIL B,40 + SOS TTYIHP(I) + TLNN H,%TOSAI + CAIL C,40 + SOS TTYIHP(I) + SKIPL A,CCDPSO(W) + JRST TYPLUP + MOVEI A,33 ;PUT AN ESC BEFORE IT + JRST TYPOU2 + +TYMTB8: CAMN E,A + JRST TYMHU ;HOME-UP FIRST + JUMPL B,TYMTB4 ;JUMP IF MOVING TO THE RIGHT + JUMPE B,TYMDPL ;JUMP IF NOT MOVING HORIZONTALLY + CAIE C,1(R) ;MOVING TO THE LEFT, SKIP IF SHOULD CR FIRST + JRST TYMDP8 ;NO, JUST BS + JRST TYMTB6 ;GO CR + +TYMTB4: MOVE E,TT ;DESTINATION COLUMN + TRO E,7 ;ENSURE NO BORROW + MOVEI A,1(E) ;COLUMN TO TAB TO THEN BACKSPACE BACK + CAMGE A,TCMXH(I) ;BE SURE NOT TO TAB OFF THE RIGHT MARGIN + TRNN TT,4 ;SKIP IF FASTER TO TAB PAST AND BACKSPACE BACK + JRST TYMTB5 ;JUMP IF BETTER TO TAB THEN FORWARD-SPACE + CAMN B,[-1] + JRST TYMDP3 ;MOVING A SHORT WAY, JUST SEND A FORWARD-SPACE + MOVEI B,8(E) + SUB B,TTYIHP(I) + LSH B,-3 ;# TABS TO GET PAST DESTINATION +TYMTB7: MOVEI A,^I + MOVEI E,7 + ANDCAM E,TTYIHP(I) ;ALIGN TTYIHP WITH TAB STOPS + MOVE C,[ADDM E,TTYIHP(I)] ;EACH TAB ADVANCES TTYIHP BY 8 + AOJA E,TYMDP5 ;GO TAB + +TYMTB5: SUB E,TTYIHP(I) ;COMPUTE # TABS TO GET JUST TO + LSH E,-3 ; THE LEFT OF THE DESTINATION + JUMPE E,TYMDP3 ;WE'RE CLOSE, DO FORWARD SPACES + MOVE B,E ;TAB FIRST + JRST TYMTB7 + +TYMTBC: 0 ? 2 ? 4 ? 6 ;COST OF MOVING RIGHT FROM A TAB STOP + 1+4 ? 1+3 ? 1+2 ? 1+1 ;COST OF TABBING ONE MORE AND BACKSPACING BACK + +;setup routine for TYMH19, TYMAAA. Gets magnitude of horizontal and vertical +;motion in B and A, destinations in TT and D respectively, sets TTYIHP and +;TTYIVP. +TYMPOS: MOVE A,TTYIVP(I) ;current hardware vertical position + SUBM D,A ;subtract from vertical destination + CAML TT,TCMXH(I) ;if trying to move off right margin, + JRST [ MOVE TT,TCMXH(I) ;pretend moving to margin + SOJA TT,.+1 ] + MOVE B,TTYIHP(I) ;compute net chrs to position + CAML B,TCMXH(I) ;if we think we moved off the end of the line, + JRST [ MOVE B,TCMXH(I) ;presumably by printing in the last column, + SUBI B,1 ;the cursor actually stuck in the last column + MOVEM B,TTYIHP(I) + JRST .+1 ] + SUBM TT,B ;now we have horizontal motion in B + MOVEM D,TTYIVP(I) ;put vertical, horizontal destination + MOVEM TT,TTYIHP(I) ;into registers (we'll be there soon). + POPJ P, + +;cursor positioning on an H19. TYMDP occasionally stuffs rubouts into the +;buffer to do its own padding, thereby resulting in ^S ^Q lossage on H19s. I +;could patch TYMDP up, but it's too silly. Generates HCUF, HCUB, HCUD, HCUU, +;or HDCA. +TYMH19: PUSHJ P,TYMPOS ;get horizontal and vertical destinations, etc. + MOVEI C,2 ;now flush the first two chars of cursor + ADDM C,TORM(I) ;motion command (TYEEO2 will flush last) + MOVE C,TOCMBF(I) ;get byte pointer to tty command buffer in C + MOVEI E,33 + IDPB E,C ;send esc + JUMPE A,TYMHOX ;if vertical magnitude 0, only moving in X + JUMPE B,TYMHOY ;same for horizontal and Y +TYMABS: MOVEI E,"Y ;neither is 0, abs. positioning faster + IDPB E,C + ADDI D,40 ;convert line # to H19 coord system. + IDPB D,C + ADDI TT,40 ;convert column # to H19 coord system + IDPB TT,C +TYMHDN: MOVEI E,0 ;top it off with a null + IDPB E,C + MOVE A,TOCMBF(I) ;TYEEO2 wants bp in A + JRST TYEEO2 ;noone seems to think it's necessary to pad + +TYMHOX: CAIN B,1 ;if 1 or -1, then relative positioning is + JRST TYMHX2 ;plenty fast + CAIN B,-1 + JRST TYMHX3 + JRST TYMABS ;otherwise absolute positioning is faster +TYMHX2: MOVEI E,"C ;moving forward one space + IDPB E,C + JRST TYMHDN +TYMHX3: MOVEI E,"D ;moving backwards one space + IDPB E,C + JRST TYMHDN + +TYMHOY: CAIN A,1 ;if 1 or -1, then relative positioning is + JRST TYMHY2 ;plenty fast + CAIN A,-1 + JRST TYMHY3 + JRST TYMABS ;otherwise absolute positioning is faster +TYMHY2: MOVEI E,"B ;moving down one line + IDPB E,C + JRST TYMHDN +TYMHY3: MOVEI E,"A ;moving up one line + IDPB E,C + JRST TYMHDN + +;cursor positioning on an AAA. Generates either CUP, HPA, or VPA, +;whichever involves fewest chars. +TYMAAA: PUSHJ P,TYMPOS ;get X-Y motion and set dests. + MOVEI C,2 ;now flush the first two chars of cursor + ADDM C,TORM(I) ;motion command (TYEEO2 will flush last) + MOVE C,TOCMBF(I) ;get byte pointer to tty command buffer in C + MOVEI E,33 + IDPB E,C ;send esc + MOVEI E,"[ ;[ + IDPB E,C + JUMPE B,TYMAVT ;going vertically only + JUMPE A,TYMAHZ ;horizontally only + JUMPE D,TYMAP3 ;if going to top line, optimize out 1st coord + MOVE E,D + PUSHJ P,SNDNUM ;send vertical coord + JUMPE TT,TYMAP5 ;if moving to leftmost col no second coord +TYMAP3: MOVEI A,73 ;or semicolon + IDPB A,C + MOVE E,TT + PUSHJ P,SNDNUM ;send horizontal coord +TYMAP5: MOVEI A,"H ;absolute positioning char + JRST TYMADN +;going vertically only, use vertical absolute positioning +TYMAVT: MOVE E,D + PUSHJ P,SNDNUM + MOVEI A,"d ;vertical absolute positioning char + JRST TYMADN +;going horizontally only, horizontal absolute positioning +TYMAHZ: MOVE E,TT + PUSHJ P,SNDNUM + MOVEI A,"` ;horizontal absolute positioning char +;fall through into done code + +TYMADN: IDPB A,C ;send that last char + MOVEI A,4 ;padding is A*TT in ms + MOVEI TT,1 ;4 ms of padding ought to be enough + JRST TYDAPD ;go set it up + +;Add one to the number in E, convert it to ASCII decimal, and idpb it +;in the location pointed to by the bp in C. Assumes no more than 2 +;digits in E. Bashes A, B, E (B because of the IDIVI). +SNDNUM: AOS E ;bump + MOVE A,E + IDIVI A,10. ;divide by 10 for high digit + JUMPE A,SNDNM2 ;only one digit + ADDI A,"0 ;make high digit ascii + IDPB A,C ;put in buffer + SUBI A,"0 ;un-ascii high digit + IMULI A,10. ;find out what we printed + SUB E,A ;take it from what we had to get low digit +SNDNM2: ADDI E,"0 ;make low digit ascii + IDPB E,C ;put in buffer + POPJ P, + +TYEBS: SOSGE TTYIHP(I) ;%TDBS: OUTPUT BS. + SETZM TTYIHP(I) + MOVEI A,^H + JRST TYPSIO + +TYERCR: MOVE D,TTYIVP(I) ;%TDRCR: OUTPUT A CR (PLUS PADDING) + SETZ TT, + SKIPN TTYIHP(I) + AOS TTYIHP(I) +TYERC1: SOS TORM(I) .SEE TYMOVX ;WHICH WILL ADD 3 TO TORM. + SOS TORM(I) + JRST TYMPRR + +TYELF: MOVE TT,TTYIHP(I) ;%TDLF: OUTPUT LF (PLUS PADDING) + MOVE D,TTYIVP(I) + AOS D + CAIG D,118. + CAML D,TCMXV(I) + JRST TYELFE ;DETECT A LF THAT SCROLLS. + JRST TYERC1 + +TYELFE: SKIPN TTYROL(I) ;IF NOT A SCROLLING TTY, RESET VPOS TO 0 + TDZA D,D + SUB D,TTYROL(I) ;OTHERWISE, GLITCH UP + MOVEM D,TTYIVP(I) ;STORE VPOS AFTER SCROLLING. + SOS TTYIVP(I) ;MAKE SURE 1 LF IS OUTPUT. + JRST TYERC1 + +TYEFS: CAIN W,%TNAAA ;AAA's use a different format + JRST TYFSAA + MOVSI E,%TCFPD ;ON SOME TTYS, IS TWO PARTS + TDNE E,TTYCOM(I) + JRST TYEFS2 ;FIRST PART DONE, DO SECOND + IORM E,TTYCOM(I) ;ABOUT TO DO FIRST PART + CAIE W,%TNDP ;DATAPOINTS NEED PADDING + CAIN W,%TNODP + JRST TYEFSD ;SO GO DO IT + MOVEI A,33 ;VT52S ETC. NEED ALTMODE PREFIX + SKIPGE CCFS(W) + JRST TYPOU2 ;SO GO DO THAT +TYEFS2: ANDCAM E,TTYCOM(I) ;ABOUT TO DO SECOND PART + HRRZ A,CCFS(W) ;GET CHARACTER TO SEND + AOS TTYIHP(I) ;IT WILL MOVE THE CURSOR + JRST TYPSIO ;SEND IT, AND ABSORB THE %TDFS + +TYEFSD: LDB B,[$TPPCR,,TTYOPT(I)] + PUSHJ P,TYMPAD ;SET UP TTYBYP TO PAD + JRST TYPLUP ;PAD THEN COME BACK HERE + +;handle forward-space on AAA's +TYFSAA: MOVE A,CCFS(W) + JRST TYEEO2 + +;HANDLE CLEAR-EOL: +TYEEOL: SKIPA A,CCEOLP(W) + +;HANDLE CLEAR-EOF +TYEEOF: MOVE A,CCEOFP(W) +TYEEO2: CAILE A,0 + PUSHJ P,TYEEO3 ;JUMP IF OUTPUT SEQ IS mn,,TABLE +TYEEO4: MOVEM A,TTYBYP(I) ;STORE BYTE POINTER OR ZERO +TYEEO1: AOS TORM(I) ;FLUSH THE CURSOR CTL CMD FROM OUTPUT BFR. + MOVEM Q,TOOP(I) + JRST TYPLUP + +;OUTPUT SEQUENCE SPECIFIED AS mn,,TABLE +;m=LOWEST PAD CODE IN TABLE, n=HIGHEST +TYEEO3: LDB B,[$TPPCR,,TTYOPT(I)] + LDB C,[220300,,A] ;n + CAMLE B,C + MOVE B,C + LDB C,[250300,,A] ;m + SUB B,C + SKIPLE B + ADD A,B + MOVE A,(A) ;PICK UP BYTE POINTER OUT OF TABLE + POPJ P, + +;HANDLE CLEAR THE SCREEN +TYECLR: SETZM TTYIHP(I) ;AFTER CLEARING, CURSOR WILL BE AT TOP LEFT + SETZM TTYIVP(I) + SKIPA A,CCCLRP(W) +;HANDLE DELETE FWD, ON OVERPRINTING ERASABLE DISPLAYS, AND IMLACS (ACC TO %TOIML). +TYEDLF: MOVE A,CCDLFP(W) + JRST TYEEO2 + +;HANDLE ENTER-INVERSE-VIDEO AND LEAVE-ALL-SUCH-MODES +TYEBOW: SKIPA A,CCBOWP(W) +TYERST: MOVE A,CCRSTP(W) + JRST TYEEO2 + +TYEINI: MOVE A,CCINIP(W) + JRST TYEEO2 + +;REGION-SCROLL UP AND REGION-SCROLL DOWN HANDLED ONLY ON DM2500 +;FOR NOW. REAL DM2500'S CAN'T DO IT, BUT CERTAIN FAKE ONES CAN. +;SOMEDAY HAIRY CODE COULD BE ADDED TO DO IT ON C100 AND VT100. +TYERSU: +TYERSD: SUBI A,%TDRSU-^U ;SEND ^U OR ^V +; CAIE W,%TNDTM +; JRST TYEEO1 + MOVE B,TORM(I) ;MAKE SURE ARGS IN BUFFER + CAILE B,TOBS-3 + JRST TYPEND ;NO, COME BACK LATER + DPB A,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q ;XOR 140 INTO ARGS + XORI A,140 + DPB A,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + XORI A,140 + DPB A,Q + MOVNI A,2 ;COMPENSATE FOR "PRINTING" CHARS + ADDM A,TTYIHP(I) + JRST TYPLUP + +;HANDLE DELETE AND INSERT CHARACTERS AND LINES +;DOESN'T TRY TO BE TOTALLY HAIRY ABOUT MULTIPLE INSERT/DELETES. +TYEILP: SKIPA A,CCILPP(W) +TYEDLP: MOVE A,CCDLPP(W) + JRST TYEIL1 + +;if we're on an H19 we don't want to call TYDH19 from TYEICP, because +;no multiple insert char. +TYEICP: MOVE A,CCICPP(W) + CAIE W,%TNH19 ;if we're on an H19, no multiple insert char + JRST TYEIL1 ;so hack locally, else go to main routine + MOVE B,TORM(I) ;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER + CAILE B,TOBS-2 + JRST TYPEND ;if it's not, come back when it is + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q ;GET IT + JRST TYEIL2 +TYEDCP: MOVE A,CCDCPP(W) +TYEIL1: MOVE B,TORM(I) ;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER + CAILE B,TOBS-2 + JRST TYPEND ;IT'S NOT, COME BACK WHEN IT IS + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q ;GET IT + CAIN W,%TNAAA ;AAA's have a better way of doing this + JRST TYIDAA + CAIN W,%TNH19 ;so do H19's + JRST TYDH19 +TYEIL2: SOJG B,[DPB B,Q ;NOT LAST TIME, LEAVE DECREMENTED REQUEST IN BUFFER + CAILE A,0 + PUSHJ P,TYEEO3 + MOVEM A,TTYBYP(I) ;AND DO ONCE + JRST TYPLUP] + AOS TORM(I) ;OTHERWISE, REMOVE FROM BUFFER + JRST TYEEO2 ;AND GO DO + +;Handle insert/delete line, delete char on an H19, without weenie +;weenie. Actually enters ANSI mode for multiple insert/deletes. +TYDH19: CAIG B,6 ;if we're doing < 6, non-hairy way is faster. + JRST [ MOVE A,1(A) ;format of table is + JRST TYEIL2 ] ; [ansicommand ? zdscommand] + MOVE A,@A ;get the command char + AOS TORM(I) ;flush the arg + MOVE C,TOCMBF(I) ;pointer to comand buffer + MOVEI E,33 ;send esc and + IDPB E,C + MOVEI E,"< ;< to enter ANSI mode + IDPB E,C + PUSHJ P,TYIDA2 ;send the command and set TT to arg + MOVEI A,19. ;19 ms padding per operation. + MOVE D,H19ZDS ;copy command to enter ZDS mode + ILDB E,D ;into buffer + JUMPE E,TYDAPD ;when done, go do padding + IDPB E,C + JRST .-3 + +H19ZDS: 440700,,[ASCIZ /[?2h/] ;command to enter ZDS mode + +;Handle insert/delete chars/lines on an AAA. This code avoids the +;"weenie weenie" syndrome, where lines get deleted one at a time +;(weenie weenie), and then get inserted one at a time (weenie weenie). +TYIDAA: AOS TORM(I) ;flush arg from buffer + MOVE C,TOCMBF(I) ;get pointer to command buffer + PUSHJ P,TYIDA2 ;send command and set TT to arg + MOVEI A,4 ;4 ms padding per operation + JRST TYDAPD ;send the padding + +TYIDA2: MOVEI E,33 ;send esc + IDPB E,C + MOVEI E,"[ ;send [ + IDPB E,C + MOVE E,B ;SNDNUM takes arg in E + MOVE D,A ;and bashes A + MOVE TT,B ;and B - so save 'em + SOS E ;SNDNUM also adds 1 to its arg. + PUSHJ P,SNDNUM ;send arg + IDPB D,C ;send command char, which is now in D + POPJ P, + +;TYDAPD sets up the end of TOCMBF to include a null and the amount of +;padding needed, and then jumps to TYEEO2. TT contains a number that +;is multiplied by the contents of A to get the number of ms of padding +;desired. TT usually has the number of inserts or deletes in it, and +;A usually has the pad factor. +TYDAPD: MOVEI D,0 ;put a null at end + IDPB D,C ;now do padding - set up for TYEEO2 + HLRZ D,C ;did we just deposit in the lowest + CAIN D,010700 ;byte in this word? + JRST [ HRRZ D,C ;yes, put a 1 in the next + AOS D + MOVEI E,1 + MOVEM E,@D + JRST .+2 ] + JRST [ HRRZ D,C ;turn on the low bit in this one + MOVEI E,1 + IORM E,@D + JRST .+1 ] + AOS D + IMUL TT,A ;ms padding = TT * A + MOVEM TT,@D ;TT usually has arg to command + MOVE A,TOCMBF(I) ;pointer to beginning of buffer + JRST TYEEO2 ;goes in A, where TYEEO2 wants it + +;HANDLE TURN-ON-MOTOR COMMAND. +TYEMTN: CAIE W,%TNTRM + JRST TYEEO1 ;NO-OP EXCEPT ON TERMINETS + LDB B,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYEEO1 ;PADDING CODE 0 => DON'T HACK THE MOTOR. + HRRZ A,TYMTVT(B) + LSH A,1 + IDIVI A,5 + MOVNS A + ADD A,TYEMT1(B) ;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS. + JRST TYEEO4 + +;THIS IS AN ASCIZ STRING OF 90. RUBOUTS. +;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT. +TYEMT0: REPEAT 90./5, -2 +TYEMT2: ASCIZ /H/ + +TYEMT1: 010700,,TYEMT2-1 + 100700,,TYEMT2-1 + 170700,,TYEMT2-1 + 260700,,TYEMT2-1 + 350700,,TYEMT2-1 + +;HANDLE TURN-MOTOR-OFF COMMAND. +TYEMTF: CAIE W,%TNTRM + JRST TYEEO1 + LDB B,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYEEO1 + MOVE A,[440700,,[ASCIZ/J/]] + JRST TYEEO2 + +;CRLF AND CLEAR EOL. +TYECRL: SETZM TTYIHP(I) + AOS B,TTYIVP(I) + MOVN A,TTYROL(I) + CAML B,TCMXV(I) + ADDM A,TTYIVP(I) + MOVE A,CCROLP(W) ;HOW TO SCROLL THIS KIND OF TTY? + JRST TYEEO2 + +SUBTTL TABLES OF CURSOR-CONTROL SEQUENCES + +;Note that a table entry can be (for those tables which are strings): +; mn,,TABLE - m is lowest pad code in table, n is highest +; These pad codes from the $TPPCR. The appropriate +; table entry is selected, indexed by pad code. +; The table entry should look like 440700,,string. +; 440700,,string - the string is output. If the low-order +; bit of the last word in the string is set, the +; following word contains the number of milliseconds +; of padding required. (max is 200 ms at 9600 baud, +; see TYMPAD), or if this word is SETZ, a special kludge +; for Tektronix screen-clear is invoked. +; A negative number is the number of 1/8 msec of padding +; per line below the cursor. Note carefully that is in +; 1/8 msec units! +; 0 - output nothing +; +; (for those tables which are characters): +; "ch - output the character +; SETZ "ch - output esc (033) followed by the character + +;DATAPOINT CURSOR CONTROL CHARACTERS +%DPFS==30 ;30 => FORWARD SPACE + ;31 => (NON-EXISTANT) +%DPUP==32 ;32 => MOVE UP + ;33 => (NON-EXISTANT) +%DPHD==34 ;34 => HOME DOWN (DOESN'T WORK ON OLD DATAPOINTS ABOVE 300 BAUD) +%DPHU==35 ;35 => HOME UP + ;36 => CLEAR EOL + ;37 => CLEAR EOF +%DPBS==10 ;BACKSPACE +%DPDN==12 ;LINEFEED. + +CCDPSO: 0 ;PRT ;LH DIRECT POSITIONING CHAR, RH INDEX INTO CCDPSM + 0 ;DPT ;4.9 ESC BEFORE CHAR, 4.8 HORIZONTAL THEN VERTICAL + 0 ;LSR + 200016,,0 ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 400131,,2 ;ESC + 200014,,1 ;DTM + 400131,,2 ;RAY + 400141,,2 ;HDS + 0 ;H19's have their own routine + 0 ;AAA's have their own routine +IFN .-CCDPSO-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCDPSO + +;INSTRUCTION TO MUNG B TO CONVERT TO TERMINAL'S COORDINATE SYSTEM +CCDPSM: ADDI B,1 ;IMLAC + XORI B,140 ;DATAMEDIA + ADDI B,40 ;VT52, TELERAY, CONCEPT-100, ETC. + +CCFS: 40 ;FORWARD-SPACE CHARACTER, 4.9 => IT NEEDS AN ESC IN FRONT OF IT + %DPFS ;DPT + %DPFS ;LSR + ^Y ;IMLAC + 40 ;TEK + 0 ;TV + 40 ;MEM + 0 ;SFW + 40 ;TRM + SETZ "C ;ESC + 34 ;DTM + SETZ "C ;RAY + SETZ "= ;HDS + SETZ "C ;H19 +;the AAA entry looks strange here, but it's the right thing. TYEFS +;checks for AAA's specially, and AAA's don't use TYMDP. + 440700,,[.BYTE 7 ? 33 ? "[ ? "C ] ;AAA +IFN .-CCFS-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCFS + +CCUP: 0 ;LINE-STARVE CHARACTER, - => IT NEEDS AN ESC IN FRONT OF IT + %DPUP ;DPT + %DPUP ;LSR + 0 ;IMLAC + 13 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + SETZ "A ;ESC + 32 ;DTM + SETZ "A ;RAY + SETZ "; ;HDS + SETZ "A ;H19 + 0 ;AAA +;this entry isn't here because this is a stupid word table instead +;of a winning string table. +; 440700,,[.BYTE 7 ? 33 ? "[ ? "A ] ;AAA +IFN .-CCUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCUP + +CCHUP: 0 ;HOME-UP SEQUENCE POINTER + 440700,,[.BYTE 7 ? %DPHU] ;DPT + 440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU] ;LSR + 0 ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "H] ;ESC + 440700,,[.BYTE 7 ? 2] ;DTM + 440700,,[.BYTE 7 ? 33 ? "H] ;RAY + 440700,,[.BYTE 7 ? 33 ? "?] ;HDS + 440700,,[.BYTE 7 ? 33 ? "H] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "H] ;AAA +IFN .-CCHUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCHUP + +CCHDP: 440700,,CCHD +CCHD: 34_29.+177_22.+177_15.+177_8 + +CCEOLP: 0 ;PRT + 440700,,[.BYTE 7 ? 36 ? 177 ? 177 ? 177] ;DPT + 440700,,[.BYTE 7 ? 36 ? 36 ? 36 ? 36] ;LSR + 440700,,[.BYTE 7 ? ^Q] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "K] ;ESC + 440700,,[.BYTE 7 ? 27] ;DTM + 440700,,[.BYTE 7 ? 33 ? "K] ;RAY + 01,,[ 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 8.] ;HDS 300/1200 + 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ] ;HDS 9600 + 440700,,[.BYTE 7 ? 33 ? "K] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "K] ;AAA +IFN .-CCEOLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOL + +CCEOFP: 0 ;PRT + 440700,,[.BYTE 7 ? 37 ? 177 ? 177 ? 177] ;DPT + 440700,,[.BYTE 7 ? 37 ? 37 ? 37 ? 37 ? 37 ? 0] ;LSR + 440700,,[.BYTE 7 ? ^P] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "J] ;ESC + 440700,,[.BYTE 7 ? 27] ;DTM (CAN'T CLEAR TO EOF, SO CLEAR TO EOL) + 440700,,[<.BYTE 7 ? 33 ? "J>+1 ? 90.] ;RAY + ;HDS PAD CODES ARE 0 1200 OR LESS, 1 9600 OR MORE + ; AT 9600 OR ABOVE, USE ERASE EOL INSTEAD OF ERASE EOS + 01,,[ ; DUE TO INABILITY TO SEND 340 (!!) MILLISECONDS OF PADDING + 440700,,[<.BYTE 7 ? 33 ? 3>+1 ? 170.] ;HDS 300/1200 + 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ] ;HDS 9600 + 440700,,[.BYTE 7 ? 33 ? "J] ;H19 + 440700,,[<.BYTE 7 ? 33 ? "[ ? "J>+1 ? 5.] ;AAA 5 ms padding +IFN .-CCEOFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOF + +CCDLFP: 0 ;PRT + 440700,,[.BYTE 7 ? 31] ;(DPT) FOR BENEFIT OF GT40 + 0 ;LSR + 440700,,[.BYTE 7 ? ^X] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 0 ;ESC + 0 ;DTM + 0 ;RAY + 0 ;HDS + 0 ;H19 + 0 ;AAA +IFN .-CCDLFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDDLF + +CCROLP: 0 ;PRT + 25,,CCCRLP ;DPT + 25,,CCCRL1 ;LSR + 440700,,[.BYTE 7 ? ^M ? ^K ? ^Q] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;ESC + 440700,,[.BYTE 7 ? ^M ? ^J ? 27] ;DTM + ;NOTE: REAL DATAMEDIAS IGNORE THE ^J BUT IMITATION ONES MIGHT NOT + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;RAY + 440700,,[<.BYTE 7 ? ^M ? ^J ? 33 ? 23>+1 ? 16.] ;HDS + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;H19 + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "[ ? "K ? 0] ;AAA +IFN .-CCROLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDCRL + +;CRLF ON DATAPOINTS, DEPENDING ON LOSER-NESS AND SPEED. +CCCRLP: 440700,,[.BYTE 7 ? ^M ? ^J ? 36] + 440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36] +REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36] + +CCCRL1: 440700,,[.BYTE 7 ? ^M ? ^J ? 36 ? 36 ? 36 ? 36] + 440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36] +REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36 ? 0] + +CCCLRP: 0 ;CLEAR THE SCREEN SEQUENCE POINTER + 440700,,[.BYTE 7 ? %DPHU ? 37 ? 177 ? 177 ? 177 ? 0] ;DPT + 440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU ? 37 ? 37 ? 37 ? 37 ? 37 ? 0] ;LSR + 440700,,[.BYTE 7 ? ^L] ;IMLAC + 440700,,[<.BYTE 7 ? 33 ? 14>+1 ? SETZ] .SEE TYPBP ;TEKTRONIX + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0] ;ESC + 34,,[440700,,[.BYTE 7 ? 36] ;DTM + 440700,,[.BYTE 7 ? 36 ? 36]] + 440700,,[<.BYTE 7 ? 33 ? "j>+1 ? 90.] ;RAY + 440700,,[<.BYTE 7 ? 14>+1 ? 48.] ;HDS (RIGHT FOR 9600 BAUD, NEED HALF AS MUCH AT 300) + 440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0] ;H19 + 440700,,[<.BYTE 7 ? 33 ? "[ ? "H ? 33 ? "[ > + <.BYTE 7 ? "J>+1 ? 5.] ;AAA needs 5 ms padding + +IFN .-CCCLRP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDCLR + +CCILPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 01,,[ ;ESC padding mainly based on H19 - CBF + 440700,,[<.BYTE 7 ? 33 ? "L>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]] ; .75 ms/line at higher + 04,,[440700,,[.BYTE 7 ? ^P ? ^J ? ^X ? 0] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 3,[177 ? ] ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 5,[177 ? ] ? ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 10.,[177 ? ] ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 20.,[177 ? ] ^X ? 0]] + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -20.] ;RAY (2.5ms/line) + 01,,[ + 440700,,[<.BYTE 7 ? 33 ? ^R>+1 ? -14.] ;HDS AT 300/1200 (1.75ms/line) + 440700,,[<.byte 7 ? 33 ? ^R>+1 ? -3.*8]] ;HDS AT 9600 (3ms/line) + ["L ? 01,,[ ;H19's use this table differently + 440700,,[<.BYTE 7 ? 33 ? "L>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]]] ; .75 ms/line at higher + "L ;AAA (AAA's use this table differently) + +IFN .-CCILPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDILP + +CCDLPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 01,,[ ;ESC padding mainly based on H19 - CBF + 440700,,[<.BYTE 7 ? 33 ? "M>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]] ; .75 ms/line at higher + 34,,[440700,,[.BYTE 7 ? ^P ? ^Z ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^Z ? 177 ? ^X]] + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -20.] ;RAY (2.5ms/line) + 01,,[ + 440700,,[<.BYTE 7 ? 33 ? ^B>+1 ? -14.] ;HDS AT 300/1200 (1.75ms/line) + 440700,,[<.byte 7 ? 33 ? ^B>+1 ? -3.*8.]] ;HDS AT 9600 (3ms/line) + ["M ? 01,,[ ;H19's use this table differently + 440700,,[<.BYTE 7 ? 33 ? "M>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]]] ; .75 ms/line at higher + "M ;AAA (AAA's use this table differently) +IFN .-CCDLPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDLP + +CCICPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "Q ? 40 ? 10 ? 33 ? "R] ;ESC + 34,,[440700,,[.BYTE 7 ? ^P ? ^\ ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? 40 ? 177 ? ^X ? ^H ? 40 ? ^H ? 0]] + 440700,,[.BYTE 7 ? 33 ? "P] ;RAY + ; The HDS requires a null in its insert char sequence so we + ; resort to non 7 bit char so the typeout loop won't think its + ; the end of an ASCIZ string. + 01,,[ ;HDS + 441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ? + <.byte 9 ? 33 ? 400 >] ; no padding 1200 or under + 441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ? + <.byte 9 ? 33 ? 400 >+1 ? 16.]] ; 16 ms per insert >1200 + 440700,,[.BYTE 7 ? 33 ? "@ ? 40 ? 10 ? 33 ? "O] ;H19 + "@ ;AAA's use this table differently +IFN .-CCICPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDICP + +CCDCPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "P] ;ESC + 34,,[440700,,[.BYTE 7 ? ^P ? ^H ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^H ? 177 ? ^X]] + 440700,,[.BYTE 7 ? 33 ? "Q] ;RAY + 01,,[ ;HDS + 440700,,[.byte 7 ? 33 ? 21] ; no padding 1200 or under + 440700,,[<.byte 7 ? 33 ? 21>+1 ? 16.]] ; 16 ms per del at >1200 + ["P ? 440700,,[.BYTE 7 ? 33 ? "N]] ;H19's also use this table differently + "P ;AAA's use this table differently +IFN .-CCDCPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDCP + +CCBOWP: + REPEAT %TNDTM,0 + 440700,,[.BYTE 7 ? 16] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "D] ;HDS + 440700,,[.BYTE 7 ? 33 ? "p] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "7 ? "m] ;AAA +IFN .-CCBOWP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDBOW + +CCRSTP: + REPEAT %TNESC,0 + 440700,,[.BYTE 7 ? 33 ? "G] ;VT52, ETC. + 440700,,[.BYTE 7 ? 30] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "d] ;HDS + 440700,,[.BYTE 7 ? 33 ? "q] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "m] ;AAA - this is not RIS, +;which could screw you over if your default state were a bad one. It's +;just SGR 0. +IFN .-CCRSTP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDRST + +CCINIP: ;initialize an intelligent terminal + REPEAT %TNESC,0 + 440700,,[.BYTE 7 ? 33 ? "G] ;VT52, ETC. + 440700,,[.BYTE 7 ? 30] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "d] ;HDS + 440700,,[.BYTE 7 ? 33 ? "q] ;H19 +;all sorts of ways the AAA can be messed up. We fix just a few. + 440700,,[ASCII "[>27;29;30;33;34;35;37;40;46;51l[>52h[" + +1 ? 5.] ;First line must be multiple of 5 chars! +;does: turn off insert char, LF is LF, CR is CR, no destructive BS, no +;wrap forward, no wrap backward, no AUTO XON/XOFF, no half-duplex, no +;auto kbd disable(!), no alternate cursor mode. Let us clear entire +;screen, enable sending to host, turn off delete display, turn on META +;key. Finally, clears the screen, about 5 ms padding. +IFN .-CCINIP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDINI + + +SUBTTL TTY CONTROL TABLES + +;TOTAL NUMBER OF TTYS +NCT==NOTYS+NKSTYS+NETYS+NNTYS+NNVTTS+NDZTYS+NDPTYS+NMTYS+NDLTYS+NSTTYS+N11TYS + +IFGE NCT-%TINON, .ERR EXCESSIVE NUMBER OF TTYS + +IFG NOTYS-1, .ERR MORE THAN ONE KA-10 CONSOLE TTY? +IFG NKSTYS-1, .ERR MORE THAN ONE KS-10 CONSOLE TTY? + +NFKSTY==NOTYS ;# OF FIRST KS-10 (BETTER BE ONLY) 8080 CONSOLE TTY +NFETY==NFKSTY+NKSTYS ;# OF FIRST DTE20 TTY +NFNTY==NFETY+NETYS ;# OF FIRST TK-10 TTY +NFNVTY==NFNTY+NNTYS ;# OF FIRST NOVA TTY +NFDZTY==NFNVTY+NNVTTS ;# OF FIRST DZ11 TTY. +; Terminals above this line have slow (char at a time) controllers +; below they have fast controllers. (Check TYPDA1: and TTYDO:) +NFDPTY==NFDZTY+NDZTYS ;# OF FIRST DATAPOINT LINE +NFMTY==NFDPTY+NDPTYS ;# OF FIRST MORTON TTY +NFDLTY==NFMTY+NMTYS ;# OF FIRST DL10 TTY. +NFSTTY==NFDLTY+NDLTYS ;# OF FIRST PSEUDO-TTY +NF11TY==NFSTTY+NSTTYS ;# OF FIRST PDP11-TV TTY. + +IFG NKSTYS, IFN NFKSTY, .ERR KS-10 CONSOLE TTY NOT ZERO? +IFG NETYS, IFN NFETY, .ERR FIRST DTE20 TTY NOT ZERO? + +;INSTRUCTION TO OUTPUT 1 CHAR TO A CHAR-AT-A-TIME CONTROLLER. +;INSNS NEED NOT EXIST FOR FAST CONTROLLERS. +TTYDO: REPEAT NOTYS,DATAO TTY,A + REPEAT NKSTYS, PUSHJ P,TTKSDO + REPEAT NETYS,JFCL + REPEAT NNTYS,DATAO NTY,A + REPEAT NNVTTS,PUSHJ P,TTNDO + REPEAT NDZTYS,PUSHJ P,TTDZDO + +IFN NKSTYS,[ +TTKSDO: ANDI A,177 ; Be sure it is ASCII + TRO A,400 ; Tell 8080 there is something there. + MOVEM A,8CTYOT ; Here is where it looks. + CONO 80INT\APRCHN ; Wake up! + POPJ P, +] ;NKSTYS + +IFN NDZTYS,[ ;DZ-11 Code +TTDZDO: PUSH P,C + ANDI A,177 ;Be sure it is ASCII, and no break bits set + HRRZ C,TTYLT(I) ;Unibus address + IOWRBI A,%DZRTD(C) ;Send it + POP P,C + POPJ P, +] ;NDZTYS + +IFN NNVTTS,[ +TTNDO: ANDI A,177 + CAME I,NVOPTT + JRST TTNDO1 + AOS NVTCC + DATAO NTY,A + POPJ P, + +TTNDO1: MOVEM I,NVOPTT ;MUST SELECT NEW CONSOLE + SETOM NVTSIP ;SIGNAL + MOVEM A,NVTSSC ;SAVE CHR + PUSH P,I + SUBI I,NFNVTY-1 + TRO I,200 + DATAO NTY,I + CLEARM NVTCC + POP P,I + POPJ P, +] + +;INSTRUCTION TO TELL A TTY'S CONTROLLER TO STOP INTERRUPTING FOR IT. +;(BECAUSE THERE IS NO OUTPUT TO BE SENT) +TTYDFF: REPEAT NOTYS,CONO TTY,200+TTYCHN + REPEAT NKSTYS, JFCL + REPEAT NETYS,JFCL + REPEAT NNTYS,CONO NTY,20+TTYCHN + REPEAT NNVTTS,JRST TYP5 + REPEAT NDZTYS,PUSHJ P,DZTYDF + REPEAT NDPTYS,CONO DPK,.RPCNT_12.+400+TTYCHN + REPEAT NMTYS,CONO MTY,.RPCNT_12.+200+TTYCHN + REPEAT NDLTYS,JFCL + REPEAT NSTTYS,JFCL + +;LINE-SPECIFIC INFORMATION +TTYLT: REPEAT NOTYS,500000+TTYCHN + REPEAT NKSTYS, 0 + REPEAT NETYS,0 + REPEAT NNTYS,.RPCNT_12.+400000+TTYCHN + REPEAT NNVTTS,0 + REPEAT NDZTYS, <.RPCNT&DZLNM>,,,BA> + REPEAT NDPTYS,0 + REPEAT NMTYS,.RPCNT_12.+TTYCHN + +;INSN TO EXECUTE TO SIGNAL THAT OUTPUT IS AVAILABLE ON A PREVIOUSLY +;IDLE TTY - TELLS THE CONTROLLER TO CAUSE AN "OUTPUT DONE" INTERRUPT. +TTYST: REPEAT NOTYS,CONO TTY,10+TTYCHN + REPEAT NKSTYS, CONO 10020\APRCHN + REPEAT NETYS,PUSHJ P,TTYSTE + REPEAT NNTYS,PUSHJ P,NTYST + REPEAT NNVTTS,PUSHJ P,NVTYST + REPEAT NDZTYS,PUSHJ P,DZTYST + REPEAT NDPTYS,CONO DPK,.RPCNT_12.+100+TTYCHN + REPEAT NMTYS,CONO MTY,.RPCNT_12.+10+TTYCHN + REPEAT NDLTYS,PUSHJ P,TTYSTD + REPEAT NSTTYS,PUSHJ P,TTYPT + REPEAT N11TYS,JFCL + +IFN DZ11P,[ ;DZ-11 Code +; Disable transmitter ready interrupts from this line +DZTYDF: PUSH P,[ANDCM B,DZLBIT(A)] ;Clear this line's bit + JRST DZTYDS + +; Enable transmitter ready interrupts from this line +DZTYST: PUSH P,[IOR B,DZLBIT(A)] ;Set this line's bit +DZTYDS: PUSH P,A + PUSH P,B + PUSH P,C + HRRZ C,TTYLT(I) ;Unibus address + HLRZ A,TTYLT(I) ;Line number + IORDBI B,%DZRTC(C) + XCT -3(P) ;Frob bit + IOWRBI B,%DZRTC(C) ;Write new state + POP P,C + POP P,B + POP P,A + SUB P,[1,,1] + POPJ P, + +; DZ11 initialization. +; No parity, character length = 8 bits, stop-code = 1 bit. +DZINIT: MOVEI C,NDZTYS-1 ;Relative last DZ TTY + SKIPGE C ;Don't do anything if there aren't any + POPJ P, +DZINI1: LDB A,[$TTOSP,,NFDZTY+TTYTYP(C)] ;Ospeed (assume it is = Ispeed) + HLRZ D,NFDZTY+TTYLT(C) ; Line number on board. + HRRZ B,NFDZTY+TTYLT(C) ; Bus address of controller. + SOSL A ;Is speed = 0? + CAILE A,10 ;Is speed > 9600? + BUG HALT,[BAD SPEED CODE FOR DZ-11. LINE],OCT,C + LSH A,32. ;Assemble byte pointer + IOR A,[400,,[.BYTE 4 ? 16 ? 14 ? 12 ? 10 ? 7 ? 5 ? 4 ? 2 ? 6]] + LDB A,A ;Obtain DZ11 speed code + LSH A,%DZLSS ;Assemble LPR code + IORI A,%DZLRO+3*%DZLCL(D) ;Line # to write and various bits + XCTRI [IOWRI A,%DZRLP(B)] ;Initialize this line + CAIA + BUG HALT,[DZ11 NOT RESPONDING (CHECK THE BREAKER ON THE UNIBUS). LINE],OCT,C + SOJGE C,DZINI1 ;Loop over all DZ TTYs. + +IFN ,[ + MOVEI C, ;First unused line on last used board +DZINI2: IOWRI C,%DZRLP+,BA> ; Disable line + CAIGE C,DZNLN-1 ;Only disable lines on last used board + AOJA C,DZINI2 ;Loop +] + MOVEI C,%DZCTE+%DZCRE+%DZCSE+%DZCMS ;Turn board on + MOVEI D,377_8 ; Set all DTR bits, clear enable bits +REPEAT <_-DZLNLN>,[ + IOWRI C,%DZRCS+ + IOWRI D,%DZRTC+ +] + POPJ P, + +;CALLED AT CLOCK LEVEL TO EMPTY DZ INPUT SILOS TO TTY CODE +; What you really want to do is measure the average interrupt rate of +; each DZ and use this scanning approach only when the DZ is heavily +; active. What fun. +DZSCAN: CONO PI,TTYOFF-1 ;No TTY or lower ints, leave clock on + PUSH P,I ;Just in case +REPEAT <_-DZLNLN>,[ + IORDI A,%DZRCS+ + TRNN A,%DZCRD ;Character in silo? + JRST CONC DZS,\.RPCNT,EN +CONC DZS,\.RPCNT,LP: + IORDI A,%DZRDR+ ;Get character from silo + TRNN A,%DZDDV ;Valid character? + JRST CONC DZS,\.RPCNT,EN ;Nope, done with this DZ + ;Check parity? + LDB I,[.BP %DZLM,A] ;Get line # on DZ + ADDI I,+NFDZTY + CAIL I,NFDZTY+NDZTYS + BUG + PUSHJ P,NTYI1 ;Send char to TTY code + JRST CONC DZS,\.RPCNT,LP +CONC DZS,\.RPCNT,EN: +] + POP P,I + CONO PI,TTYON-1 ;Turn ints back on + POPJ P, +];DZ11P + +IFN TK10P,[ +NTYST: PUSH P,C ;START A TK10 TTY + CONI PI,C + ANDI C,177 ;SAVE WHICH PI CHANNELS ARE ON + CONO PI,TTYOFF + CONO NTY,@TTYLT(I) + CONO NTY,10+TTYCHN + CONO PI,2000(C) ;RESTORE PI STATUS + POP P,C + POPJ P, +] + +IFN NNVTTS,[ +NVTYST: PUSH P,I + SKIPL I,NOVATT + PUSHJ P,NTYST + POP P,I + POPJ P, +] + +TTYPT: PUSH P,B ;TTYST ROUTINE FOR STY TTYS. + PUSH P,C + MOVE B,STYSTS-NFSTTY(I) ;USER +IFN NETP,[ + TLNE B,%SSNET + JRST TTYPT2 +TTYPT3: +];NETP + MOVE C,STYMSK-NFSTTY(I) ;CHANNELS OPEN MASK + AND C,MSKST2(B) + JUMPE C,POPCBJ ;JUMP IF INTS NOT ENABLED + MOVN B,C + AND C,B + MOVE B,STYSTS-NFSTTY(I) + IORM C,IFPIR(B) + JRST POPCBJ + +IFN NETP,[ ;START STY THAT'S DIRECT CONNECTED TO NETWORK +TTYPT2: CONI PI,C + ANDI C,177 ;SAVE WHICH PI CHANNELS ARE ON + CONO PI,NETOFF + MOVSI B,%SSNET + TDNN B,STYSTS-NFSTTY(I) + JRST [ CONO PI,2000(C) ? JRST TTYPT3 ] + SKIPL STYNTL-NFSTTY(I) + JRST TTYPT4 ;ALREADY ON ACTIVATE LIST + MOVE B,STYNTA + MOVEM B,STYNTL-NFSTTY(I) + MOVEM I,STYNTA +TTYPT4: CONO PI,2000(C) ;RESTORE PI STATUS + JRST POPCBJ +];NETP + +IFN NETYS,[ +TTYSTE: CONO PI,400 ;PI OFF + SKIPL DTEOST + JRST TYSTE1 + HRRZM I,DTEOST ;TELL 11 TO SET OUTPUT DONE + CONO PI,200 ;PI ON + CONO DTE,%DBL11 ;INTERRUPT 11 + POPJ P, + +TYSTE1: CONO PI,200 ;PI ON + CONO DTE,%DBL11 ;INTERRUPT 11 + AOS DTEHC ;COUNT NUMBER OF TIMES HAD TO WAIT + SKIPL DTEOST ;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE + JRST .-2 ; OR ANOTHER. THE -11 TRIES TO PICK UP OUTPUT-DONE FAST. + JRST TTYSTE +];NETYS + +IFN DL10P,[ +TTYSTD: SKIPN DL10F + JRST TYPEN1 + CONO PI,400 ;PI OFF + SKIPE DL10SO + JRST TTYSD1 + HRRZM I,DL10SO ;TELL 11 TO SET OUTPUT DONE + CONO PI,200 ;PI ON + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, + +TTYSD1: CONO PI,200 ;PI ON + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + AOS DL10HC ;COUNT NUMBER OF TIMES HAD TO WAIT + SKIPE DL10SO ;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE + JRST .-2 ;OR ANOTHER. THE -11 TRIES TO PICK UP OUTPUT-DONE FAST. + JRST TTYSTD +] + +EBLK + +DEFINE TTYREP WRD +.CRFOFF +REPEAT NCT,CONC T,\.RPCNT,$!WRD +.CRFON +TERMIN + +IFNDEF TIBL,TIBL==41 +IFNDEF TOBL,TOBL==101 +TIBS==TIBL*2-1 +TOBS==TOBL*4 + +IFNDEF MICBAA,MICBAA==50. ;MAXIMUM NUMBER OF INPUT BUFFER CHARACTERS BEFORE AUTOMATIC ACTIVATION + +IFNDEF TYOWNC,TYOWNC==20. ;MIN # BYTES OF SPACE THERE MUST BE + ;IN OUTPUT BUFFER BEFORE IT IS OK TO TRY TO OUTPUT ANYTHING. + +TIB: BLOCK TIBL*NCT ;TTY INPUT BUFFERS (18 BITS PER CHARACTER) +TOB: BLOCK TOBL* ;TTY OUTPUT BUFFERS (8 BITS PER CHARACTER) + +;INPUT BUFFER BITS: +%TXMPE==400000 ;MAIN PROGRAM ECHO CHARACTER +%TXPIE==200000 ;PI ECHO CHARACTER +%TXCOM==100000 ;COM MODE ECHO CHAR; DO PI ECHO EVEN IF HDX TTY. +%TXIGN==40000 ;IGNORE THIS CHAR AT .IOT TIME. +%TXACT==20000 ;THIS IS AN ACTIVATION CHAR. +%TXINT==10000 ;THIS CHAR SHOULD INTERRUPT THE USER. + +;NOW COME THE BITS OF THE CHARACTER ITSELF: +%TXTOP==4000 ;"TOP" KEY. +%TXECI==2000 ;ECHOED DUE TO ECHOIN SYSTEM CALL +;%TXSFT==1000 ;"SHIFT" KEY. +%TXSUP==1000 ;"SUPER" KEY. +%TXMTA==400 ;"META" KEY. +%TXCTL==200 ;"CONTROL" KEY. +%TXASC==177 ;THE ASCII PART OF THE CHARACTER. + ;%TXTOP+CERTAIN LETTERS ARE MAGIC KEYS. %TXTOP+"Z IS DEFERRED CALL. + +;OUTPUT BUFFER BIT: +%TXDIS==200 ;1 => THIS IS A %TD CHARACTER. +IF2 EXPUNGE %TXDIS ;SO %TX BIT TYPEOUT MODE LOOKS NICE. + +TIIP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;INPUT BUFFER INPUT POINTER +TIOP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;INPUT BUFFER OUTPUT POINTER + (002200)TIB-1 .SEE TTEBAK +TIBEP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;END OF INPUT BUFFER POINTER +TOIP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;OUTPUT BUFFER INPUT POINTER + REPEAT N11TYS,0 +TOOP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;OUTPUT BUFFER OUTPUT POINTER + REPEAT N11TYS,0 +TOBEP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL+TOBL ;END OF OUTPUT BUFFER POINTER + REPEAT N11TYS,1 +TOBBP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;BEG OF OUTPUT BUFFER POINTER + REPEAT N11TYS,1 +TINTP: REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL ;INTERRUPT CHARACTER POINTER +ECHOC: REPEAT NCT,0 ;COUNT OF ECHO BUF CHARS THAT ARE REALLY ECHO CHARS +ECHOP: REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL ;POINTER TO INPUT CHARACTER TO BE ECHOED NEXT +TINTC: REPEAT NCT,0 ;COUNT OF CHARACTERS AVAILABLE FOR .ITYIC'ING. +TICC: REPEAT NCT,0 ;TYPE IN CHARACTER COUNT +TACC: REPEAT NCT,0 ;ACTIVATION CHARACTER COUNT +TORM: REPEAT NCT,TOBS ;# CHARS ROOM LEFT IN OUTPUT BUFFER. +TOCMBF: REPEAT NCT,440700,,TCMBLK+.RPCNT*5 ;5-word string buffer for each +TCMBLK: BLOCK NCT*5 ;tty for outputting commands that are longer than a few chars. + +TTYERQ: REPEAT NCT,-1 ;LIST OF TTYS NEEDING ECHO LINKED THRU THESE WDS. (NIL = 200000,,) + ;-1 FOR TTY NOT NEEDING ECHO. +TYOSW: REPEAT NCT,-1 ;AOSE-STYLE SWITCH FOR MP USE OF TTY. +TTNTO: REPEAT NCT,0 ;# CHANNELS TTY IS OPEN ON (IN ALL JOBS.) +TYIMSK: REPEAT NCT,0 ;BIT SET FOR EACH CHANNEL THE TTY IS OPEN FOR + ;INPUT ON IN THE JOB THAT OWNS THE TTY NOW. +TYOMSK: REPEAT NCT,0 ;SIMILAR, BUT FOR OUTPUT CHANNELS. +TTYBYP: BLOCK NCT ;NOT 0 => B.P. TO ASCIZ STRING TO OUTPUT AT INT. LVL. +TTLTM: REPEAT NCT,0 ;TIME LAST CHRWAS REMOVED FROM OUTPUT BUFFER. +TTYOAC: REPEAT NCT,-1 ;-1 IF TTY OUTPUT INACTIVE +TTITM: REPEAT NCT,0 ;TIME OF LAST TYPE-IN ON TTY (NOT USED BY SYSTEM). +TTYLJB: REPEAT NCT,0 ;LAST JOB TO OUTPUT TO THIS TTY. DOES NO HARM IF ABSURD. + +TTYIPC: REPEAT NCT,[ +IFG APL,IFE APL-.RPCNT, TTYIS5 ;JUST STORE AND EXIT FOR AP LINE. + .ELSE TTYI ;TTY INPUT PC +] +TYBPC: REPEAT NCT,TYBN ;PC OF ^\-HANDLING CO-ROUTINE. +TTOALC: REPEAT NCT,-1 ;LH IS -1 TO ALLOW M.P. TYPEOUT, OR 0 TO DELAY IT. + ;RH IS OUTPUT ALLOCATION: -1 => INFINITY (THE NORMAL CASE), + ;ELSE # OF CHARS ALLOWED TO BE OUTPUT. ^\ COMMANDS ARE + ;USED BY THE TTY TO ALLOCATE FOR OUTPUT. + +TCMXV: TTYREP VER ;MAX LINES VERT +TCMXH: TTYREP HOR ;MAX CHR HORZ +TTYROL: TTYREP ROL ;# LINES PER GLITCH WHEN SCROLLING. +TTYIHP: REPEAT NCT,30. ;INT LVL HPOS +TTYIVP: REPEAT NCT,5 ;INT LVL VPOS +TTYLPP: REPEAT NCT,#-1 + ;IDX OF PC PPR ASSOCIATED WITH TTY, + ;OR NEGATIVE => NONE NOW ASSOCIATED, + ;AND IS 1'S COMP. OF IDX OF PC PPR + ;FORMERLY ASSOCIATED. +TTYEPP: REPEAT NCT, ;IDX OF PC PPR TO USE FOR ECHO. +TTYLPS: REPEAT NCT,5,,30. ;IF TTYLPP <0, THIS IS MAIN PRGM VPOS,,HPOS. + +TPBEG: ;BEGINNING OF PC PPR VARS. +TPHB: ;USE 0 ;HPOS OF LEFT MARGIN. +TPVB: BLOCK 1 ;VPOS OF TOP MARGIN (1ST LINE OF PC PPR) +TPHE: ;USE TCMXH ;HPOS OF 1ST COLUMN AFTER RIGHT MARGIN +TPVE: ;USE TCMXV ;VPOS OF 1ST LINE BELOW BOTTOM MARGIN +TPHP: BLOCK 1 ;HORIZONTAL POSITION OF CURSOR +TPVP: BLOCK 1 ;VERTICAL POSITION OF CURSOR +TPVM: BLOCK 1 ;NUMBER OF LINES BEFORE A **MORE** IS ALLOWED +TPSP: BLOCK 1 ;SAVED CURSOR POS (FOR ^PS AND ^PR) +TPFLAG: BLOCK 1 ;HOLDS RANDOM FLAGS. +%TF==0,,777775 +%TFEOP==1 ;1 => HAVE JUST ENTERED LAST LINE OF PC PPR. + ;NEXT ATTEMPT TO OUTPUT SHOULD DO **MORE** PROC. +%TFIGL==2 ;1 => LAST CHAR WAS CR NOT IN IMAGE MODE. + ;IF NEXT CHAR IS LF, IGNORE IT. + + TPLEN==.-TPBEG + .=TPBEG + +REPEAT 2*NCT,[ ;NOW ASSEMBLE INITIAL CONTENTS OF PC PPR VARS. + 0 + 0+IFE .RPCNT&1,30. ;TPHP & TPVP: NONZERO FOR MAIN PRGM. + 0+IFE .RPCNT&1,5 + 0 ? 0 ? 0 +] +EXPUNG TPHB,TPHE,TPVE + +IFN .-TPBEG-NCT*TPLEN*2,.ERR + +COMT1: BLOCK NCT ;COM TEMPORARY STORAGE +COMT3: BLOCK NCT ;DITTO. WHILE QUERYING FOR A LINK, THIS IS -1 IF + ;IN IEC MODE, WHICH MEANS OK TO PASS TYPEIN THROUGH +DZLBIT:: ; Also Line number bits for DZ11 +CHNBIT: REPEAT 20,1_<.RPCNT> + +;DATA POINT CONTROLLER LINE VARIABLES +;THIS ARRAY LOOKED AT BY HARDWARE + +IFNDEF LDBFF,LDBFF==10. ;LENGTH OF OUTPUT BUFFER^2 (PER LINE) + +IFN DPKPP,[ +DPKBAS: REPEAT NDPTYS,[ + -1 ;CHR CNT + (440701,,0) ;BYTE PNTR +] + +DBBFP: REPEAT NDPTYS, 440700,,DBBF+.RPCNT*LDBFF ;PNTRS TO OUTPUT BUFFER +DPKC: REPEAT NDPTYS, DPKBAS+2*.RPCNT ;PNTR TO HARDWARE COUNT WORD +DPKP: REPEAT NDPTYS, DPKBAS+2*.RPCNT+1 ;PNTR TO BUFFER PNTR WD +DBBF: BLOCK LDBFF*NDPTYS ;OUTPUT BUFFER + +DPSPT: 2 ;134 + 6 ;600 + 1 ;110 + 2 ;150 + 3 ;300 + 24. ;1200 + 36. ;1800 + 48. ;2400 + 48. ;4800 +LDPSPT==.-DPSPT +] +DBBCC: 0 ;CHRS REMAINING IN CURRENT BLOCK + ;FOR DPK, SET ACC. TO OUTPUT SPEED, TO + ;REPRESENT APPROX. 100MS TYPEOUT TIME. + ;FOR MTY, SET TO 5. + +DBBCC1: 0 ;INITTED LIKE DBBCC, BUT NOT DECREMENTED. + +DBBBP: 0 ;BYTE PNTR TO DBBF BUFFER OR MTYOW. + +;MORTON BOX LINE VARIABLES +IFN MTYP,[ +MTYOW: 0 ;UP TO 5 CHARS TO BE OUTPUT PUT IN THIS WD. +MTYNC==5 ;NUMBER OF CHARS PACKED IN ABOVE WORD. +] + +;DTE20 VARIABLES OTHER THAN THOSE IN LOW CORE +;I.E. NOT (DIRECTLY) REFERENCED BY 11 +IFN NETYS,[ +DTEHC: 0 ;NUMBER OF TIMES LOOPING AT TTYSTE +DTECNI: 0 ;CONI DTE, AT LAST INTERRUPT +DTEBBY: 0 ;NON-ZERO => BUFFER BUSY WITH TRANSFER IN PROGRESS + ; FOR DEBUGGING, THE NON-ZERO VALUE IS THE DTEOUT COMMAND. +DTEBBT: 0 ;TIME-OUT IN HALF-SECOND UNITS +DTEOBL==200 ;NUMBER OF CHARACTERS IN OUTPUT BUFFER +DTEOBF: BLOCK /4 ;TTY OUTPUT BUFFER +];NETYS + +IFN NNVTTS,[ +NOVATT: -1 ;TTY # NOVA CONNECTED TO -1 IF NONE +NVIPTT: -1 ;CURRENT NOVA PSEUDO TTY ON INPUT +NVOPTT: 0 ;CURRENT NOVA PSEUDO TTY ON OUTPUT +NVTSIP: 0 ;-1 IF NOVA TTY SELECT IN PROGRESS (OUTPUT) +NVTSSC: 0 ;CHAR SAVED HERE DURING NVTSIP -1 +NVTCC: 0 ;# CHARS SENT TO CURRENT TTY SINCE RESCANING OTHER PSEUDO TTYS +NNVSEC: 0 ;LAST CONSOLE TO CHECK IN TYP0 SEARCH +NNVSFL: 0 ;-1 IF SERVING PREV SELECTED + ;IE IF IT CRAPS OUT, SEARCH EVEN THO IT = NNVSEC +] + +IFN N11TYS,[ +;PDP11-TV COMMUNICATION VARIABLES: + +TT11HD: .+1 ;ADDR (IN PDP10 ADDRESS SPACE) OF PDP11 CHANNEL + 0 ;HEADER AREA. IF @TT11HD IS NONZERO, THERE + ;IS INPUT TO BE PROCESSED. + +TT1111: 0 ;# TV'S THE 11 IS SET UP FOR +TT11RL: 0 ;# TV'S IN USE = MIN (TT1111, N11TYS). +TT11OL: 0 ;# PDP10 WORDS IN A PDP11-TV OUTPUT BUFFER. +TT11ER: BLOCK 6 ;FILLED WHEN BAD DATA COMMING FROM PDP11 + .SEE TT11LS + +TT11LO=400000+TTPG0*2000 ;BEGINNING OF PDP11 MEMORY IN PDP10 ADDRESS SPACE. +TT11HA==10+TT11LO ;PDP10 ADDR OF PDP11'S 40 (CHNL HDR AREA ADDR) +TT11UP==TT11HA+2 ;PDP10 ADDR OF "11 UP" FLAG. +TT11DN==TT11UP+1 ;PDP10 ADDR OF "11 ABOUT TO GO DOWN" FLAG. + +$11==1,,777700 ;DEFINE B.P.'S TO PDP11 FIELDS OF A PDP10 WORD. +$11WD0==242000 ;LOW (EVEN) 11 WORD +$11WD1==042000 ;HIGH (ODD) 11 WORD + +$11AD0==261600 ;LOW 11 WORD, SHIFTED DOWN 2 (FOR CONVERTING 11-ADDRESS TO 10 ADDRESS). +$11AD1==061600 ;HIGH 11 WORD, SHIFTED DOWN 2 + +$11BY0==241000 ;LOWEST 11 BYTE. EACH 10-WORD HOLDS 4 11-BYTES. +$11BY1==341000 ;NEXT 11 BYTE +$11BY2==041000 ;THIRD BYTE +$11BY3==141000 ;FOURTH BYTE + +;FORMAT OF AN INPUT BUFFER: (ALL POINTERS ARE PDP11 ADDRS) +;PDP11 WORD #, ... MEANING. +; 0 ... 0 => FREE, ELSE -<# DATA CHARS>. +; 1 ... ZERO, ALWAYS. +; 2 ... -> NEXT BUFFER FOR THIS TTY. +; 3 ... -> NEXT ACTIVE BUFFER. +; 4 ... KEYBOARD NUMBER (= -NF11TY) +; 5+ ... DATA CHARS, 1 PER PDP11 WORD. + +;FORMAT OF AN OUTPUT BUFFER: +;STARTS AT A MULTIPLE-OF-FOUR PDP11 ADDRESS, HAS A BUNCH OF BYTES, +;TT11BY BITS PER BYTE (USED TO BE 16, NOW 8). BYTES ARE IN PDP10 ORDER. +;AFTER THE PDP11 PICKS UP A BYTE OUT OF THE BUFFER, IT STORES BACK -1, +;WHICH TELLS THE 10 THAT IT IS OK TO STORE ANOTHER BYTE THERE. +];N11TYS + +IFN DZ11P,[ +;DZ11 STORAGE +;Temp metering locs +DZXINC: 0 ;Count of DZ transmit interrupts +DZXCHC: 0 ;Count of DZ transmit characters +; +DZDCRQ: 0 ;Disconnect requests +DZCORQ: 0 ;Connect requests. +IFG NDZTYS-36.,.ERR Too many DZ TTYS, fix code using DZDCRQ or DZCORQ +];DZ11P + +LOCTTY: 0 ;CONSOLE INPUT CHAR READ FROM +LTTYIPC:0 ;TTYIPC USED IN LAST INPUT INT (DEBUGGING ONLY) +LTYBPC: 0 ;TYBPC USED IN LAST INPUT INT (DEBUGGING ONLY) +LEPCHR: 0 ;-1 IF CURRENT INPUT CHAR IS A LOCAL EDITING PROTOCOL COMMAND CHAR. + +TTYA: 0 +TTYACS: BLOCK 17-B+1 +IFN KA10P, TTYAPC: 0 ;APR CONI AT TTYBRK. +TTYPDP: -LTTYP,,TTYPDL-1 +TTYPDL: BLOCK LTTYP + +IFN TTLPTP,[ +LPTTTY: TTLPTP ;TTY# THAT IS REALLY LPT +LPTTIME: 0 ;LAST TIME SYSTEM GOT INPUT FROM LPT +] + +STYMAX: NCT ;Highest-numbered STY to be allocated (for limiting load) +STYOSW: -1 ;PSEUDO TTY OPEN SWITCH + 0 + +TTERQS: MOVE ;LIST (THREADED THRU TTYERQ) OF TTYS NEEDING ECHOING. + ;"MOVE" (= 200000,,) IS THE END OF THE LIST. + ;OTHERWISE, A POINTER IS THE NUMBER OF A TTY + ;WHOSE TTYERQ VAR. HOLDS THE NEXT POINTER. + +TTEDMY: 0 .SEE TYOPV0 ;DUMMY VARIABLE BLOCK + 0 .SEE TYOPV1 ;PASSED BY ECHO ROUTINE + TTEDMY .SEE TYOPV2 ;TO .IOT RTNS. + 0 .SEE TYOPV3,TTELUP + +NTTELU: 0 .SEE TTELUP ;ECHOING STATISTICS. +NTTEWA: 0 .SEE TTEWAT +NTTEL1: 0 .SEE TTELP1 + +STYNTO: BLOCK NSTTYS ;NUMBER TIMES PSEUDO TTY OPEN +STYMSK: REPEAT NSTTYS,0 ;BIT FOR EACH CHNL STY OPEN FOR INPUT ON +STYOMS: REPEAT NSTTYS,0 ;OUTPUT +STYSTS: REPEAT NSTTYS,0 ;STY STATUS 0 => FREE SLOT + ;RH = USER INDEX THAT HAS IT OPEN +%SSHNG==400000 ;4.9 = 1 => DON'T HANG ON INPUT IOTS +%SSUSE==200000 ;4.8 = 1 => IN USE +%SSINT==100000 ;4.7 = 1 => HAVE GIVEN INT ON STY OUTPUT CHNS ALREADY +%SSONT==040000 ;4.6 = 1 => DITTO FOR STY INPUT (TTY OUTPUT) +%SSOHG==20000 ;4.5 = 1 => DON'T HANG ON OUTPUT IOT +%SSORS==10000 ;4.4 = 1 => THIS STY WANTS %TDORS WHEN A + ;TTY OUTPUT RESET IS DONE. +IFN NETP,[ +%SSNET==4000 ;4.3 = 1 => THIS STY CONNECTED TO SOME NET SOCKETS. +%SSCHA==2000 ;4.2 = 0 FOR ARPANET, 1 FOR CHAOS NET +%SSTCP==1000 ;4.1 = 1 for TCP internet (%SSCHA must be 0) + +STYNTI: REPEAT NSTTYS,-1; If %SSNET set, holds net connection identifier. + ; NCP: Input IMSOC idx,,Output IMSOC idx + ; CHA: connection index + ; TCP: TCB (connection) index + ; Otherwise -1 +STYNTA: 0 ;HEAD OF LIST OF DIRECT-CONNECTED STYS NEEDING DATA XFER. + ;0 IS NIL; A TTY # POINTS TO A STY. +STYNTB: 0 .SEE STYNTC ;COPIED STYNTA LIST USED INSIDE STYNTC ONLY +STYNTL: REPEAT NSTTYS,-1;STYNTA LIST THREADED THROUGH THIS TABLE. + ;+ NEXT TTY IN LIST, 0 END OF LIST, - NOT IN LIST +STYORC: REPEAT NSTTYS,0 ;OUTPUT-RESET CHARACTERS, 8-BIT BYTES TERMINATED BY 0 +TYPNTF: 0 ;-1 WHILE TYP BEING CALLED FROM STYNT0 +NTORFU: 0 .SEE TYPOR3 +] ;NETP + +STYICH: 0 ;TEMP STORAGE FOR PSEUDO-TTY INPUT CHAR + +TCTYP: TTYREP TCT ;THIS WORD SAYS HOW TO PERFORM + ;CURSOR CTL FUNCTIONS ON TTY. +%TNPRT==0 ;PRINTING TTY. +%TNDP==1 ;TTY USES DATAPOINT CURSOR CTL CODES. +%TNODP==2 ;LOSING DATAPOINT (ML-KA HAS SOME). +%TNIML==3 ;TTY USES IMLAC CURSOR CODES. +%TNTEK==4 ;TEKTRONIX 4000 SERIES +%TNTV==5 ;TTY IS A KNIGHT TV DISPLAY. +%TNMEM==6 ;MEMOWRECK +%TNSFW==7 ;"SOFTWARE" TTY THAT WANTS I.T.S. CURSOR-MOTION CODES. +%TNTRM==10 ;TERMINET +%TNESC==11 ;TTY WANTING STANDARD ASCII ESCAPE SEQUENCES +%TNDTM==12 ;DATAMEDIA +%TNRAY==13 ;TELERAY 1061 +%TNHDS==14 ;HDS CONCEPT-100 +%TNH19==15 ;H19/Z19 +%TNAAA==16 ;AAA +%TNMAX==17 + +;TTYOPT WORD DESCRIBES CHARACTERISTICS OF THE PARTICULAR +;TERMINAL ATTACHED TO EACH LINE. +TTYOPT: TTYREP OPT + +;LEFT HALF BITS ARE: +%TOALT==200000 ;4.8 => STANDARDIZE ALTMODES. +%TOCLC==100000 ;4.7 => CONVERT LOWER CASE TO UPPER. +%TOERS==40000 ;4.6 => THIS TTY CAN SELECTIVELY ERASE. +%TOHDX==20000 ;4.5 => THIS TTY IS HALF-DUPLEX. +$TOHDX==370100 +%TOMVB==10000 ;4.4 => THIS TTY CAN BACKSPACE. +%TOSAI==4000 ;4.3 => THIS TTY HAS SAIL CHAR SET ON OUTPUT. +%TOSA1==2000 ;4.2 INIT %TSSAI OF NEW JOBS. +%TOOVR==1000 ;4.1 => THIS TTY CAN OVERPRINT SUCCESSFULLY. +%TOMVU==400 ;3.9 => THIS TTY CAN MOVE CURSOR UP (IS A DISPLAY). +%TOMOR==200 ;3.8 => DO **MORE** PROCESSING ON THIS TTY + ;(ACTUALLY JUST USED TO INIT %TSMOR FOR NEW JOBS). +%TOROL==100 ;3.7 SIMILARLY, INIT %TSROL FOR NEW JOBS. +%TORAW==40 ;3.6 => SUPPRESS CURSOR MOTION OPTIMIZATION. +%TOLWR==20 ;3.5 => THIS TTY HAS LOWER CASE KEYBOARD. +%TOFCI==10 ;3.4 => THIS TTY CAN INPUT 12-BIT CHARACTERS (HAS FULL KEYBOARD). +%TOIML==4 ;3.3 => IMLAC, HANDLES CURSOR MOTION STRANGELY. +%TOLID==2 ;3.2 => LINE INSERT AND DELETE WORK +%TOCID==1 ;3.1 => CHARACTER INSERT AND DELETE WORK + +;RIGHT HALF: +%TPPLF==100000 +$TPPLF==170300 ;3-BIT FIELD SAYING HOW TO PAD LF. + ;0 - DON'T. 1 - MEMOWRECK, 2741. 2 - TERMINET. +%TPPCR==10000 +$TPPCR==140300 ;3-BIT FIELD SAYING HOW TO PAD CR. + ;7 - UNUSED. 6 - MEMOWRECK. 5 - 2741. 4 - EXECUPORT. + ;0 - DON'T. 1 - NORMAL. 2 - DOUBLE. + ;ON DATAPOINTS, = # CHARS PADDING NEEDED FOR ALL CURSOR MOTION. + ;4 IS RIGHT FOR 2400 BAUD; 3, FOR 1200. + ;ON TERMINETS, 0 => NO PADDING, OTHER CODES ARE + ;1 FOR 10CPS, 2 FOR 15CPS, 3, 4, 5 FOR 30, 60, 120 CPS. +%TPPCW==6 ;FOR MEMO WRECK. +%TPPTB==1000 +$TPPTB==110300 ;3 BIT FIELD SAYING HOW MUCH PADDING NEEDED AFTER TAB. + ;0 => TABS NOT ALLOWED; ELSE 1 +<# PADDING CHARS NEEDED> +%TPMTA==400 ;1.9 => HARDWARE META KEY SETS 8TH BIT +%TPPRN==200 ;1.8 => INTERCHANGE () WITH [] ON INPUT +%TPTEL==100 ;1.7 => TREAT CRLF INPUT AS CR FOR TELNET PROTOCOL +%TPCBS==40 ;1.6 => ENABLE SPECIAL TREATMENT OF 034 ("CONTROL BACK SLASH") ON INPUT. + ;(THE "INTELLIGENT TERMINAL PROTOCOL"). +%TP11T==20 ;1.5 => PDP-11 TV TTY. REFLECTS %TY11T. + ;NOT SETTABLE BY USER. +%TPORS==10 ;1.4 => OUTPUT RESET ON THIS TTY SHOULD REALLY DO SOMETHING. +%TPRSC==4 ;1.3 => THIS TTY SUPPORTS %TDRSU, %TDRSD + +;SMARTS VARIABLE, %TQ IN LH, %TR IN RH, BIT DEFINITIONS IN BITS > +TTYSMT: TTYREP SMT +.SEE %TQ +.SEE %TR + +TTYST1: REPEAT NCT,0 ;FIRST SIX GROUPT (SIX BITS PER GROUP) +TTYST2: REPEAT NCT,0 ;SECOND SIX GROUPS (SIX BITS PER GROUP) +TTYSTS: REPEAT NCT,%TSFRE,,-1 ;MODE BITS FOR TTY + +;GROUP NUMBER CHARACTERS +;[ 0 ^A-^F ^K-^L ^N-^R ^T-^Z ^] ^^ ^_ ^@ ^\ +; 1 A-Z LOWER CASE A-Z +; 2 0-9 +; 3 !"#$(DOLLAR)%&',.:;?@\ (ACCENT GRAVE) (VERTICAL BAR) (TILDE) +; 4 *+-/=^_ +; 5 <>[]() (LEFT BRACE) (RIGHT BRACE) +; 6 ^G ^S (^S IS IN GROUP 0 AS FAR AS %TGIMG IS CONCERNED) +; 7 LF ^I(TAB) +; 10 (ALTMODE) +; 11 CR +; 12 RUBOUT +; 13 SPACE ^H(BACKSPACE) + +;TTYST1 HAS GROUPS 0 THROUGH 5 FROM LEFT TO RIGHT +;TTYST2 HAS 6 THROUGH 13 +;EACH GROUP HAS SIX BITS AS FOLLOWS: +%TGINT==1 ;N.1 => INTERRUPT ON THIS GROUP +%TGACT==2 ;N.2 => ACTIVATE ON THIS GROUP (FOR SWAPPING) +%TGSPC==4 ;N.3 => SPECIAL HACKS. (THIS SET ON GROUP 1 => CONVERT LOWER CASE INPUT) +%TGIMG==10 ;N.4 => IMAGE MODE OUTPUT (N.4=0 => ASCII MODE) + ;N.6-N.5 => ECHO MODE + ; 00 => NO ECHO +%TGPIE==20 ; 01 => PI ECHO (ECHO CHARACTER WHEN TYPED) +%TGMPE==40 ; 10 => MAIN PROGRAM ECHO (ECHO WHEN MAIN PROGRAM RECEIVES CHARACTER) + +;TTYSTS HAS RANDOM BITS ASSOCIATED WITH THE TELETYPE +%TSFRE==400000 ;4.9 => TTY FREE +%TSCLE==200000 ;4.8 => ECHO ^L AS UPARROW-L EVEN ON DISPLAYS + ;(OTHERWISE WOULD ECHO AS CLEAR SCREEN) +%TSHDX==100000 ;4.7 REFLECTS %TOHDX BIT. +%TSFCO==040000 ;4.6 => HANDLE 9-BIT CHARS ON OUTPUT, USING ALPHA, BETA. +%TSALT==020000 ;4.5 => DON'T STANDARDIZE ALTMODE. +%TSROL==010000 ;4.4 => SCROLL MODE. +%TSSAI==004000 ;4.3 => ECHO AND ASCII MODE SHOULD USE SAIL CHAR SET. +%TSACT==002000 ;4.2 => GOBBLE NEXT CHAR REGARDLESS OF ACTIVATION STATUS +%TSNEA==001000 ;4.1 => DON'T ECHO IN THE ECHO AREA. ECHO IN M.P. AREA. +%TSINT==000400 ;3.9 => INT ON NEXT CHAR REGARDLESS +%TSMOR==000200 ;3.8 => INHIBIT **MORE**. +%TSATY==000100 ;3.7 SET BY .ATTY, SAYS TTY WAS TAKEN AWAY & RETURNED. + ;3.6-3.5 UNUSED. +%TSNOE==000010 ;3.4 => DEFER ECHOING, AND MAKE INPUT IOT'S ACT AS IF %TIECH=1. +%TSLCZ==000004 ;3.3 => LAST CHARACTER TYPED WAS ^Z (NOT PRECEEDED BY ^_) +%TSSII==000002 ;3.2 => SUPER IMAGE INPUT MODE +%TSCNS==000001 ;3.1 => CONSOLE +$TSCNS==220100 + ;RH => USER INDEX + ; -1 => NO USER + +TTYSTA: REPEAT NCT,%TACFM,, ;NOT SAVED AT ATTY +%TACFM==400000 ;4.9 = 0 => NEEDS TO HAVE CONSOLE FREE MSG EVENTUALLY TYPED + ; CLEARED BY OPEN OR ZFLAG WHEN INITIALIZING CONSOLE PROCEDURE + ; SET BY SYS JOB AFTER TYPING CONSOLE FREE MSG + ;WHEN THIS BIT IS 0, TTY ISN'T AVAILABLE FOR BEING GOBBLED DOWN + ;FOR ANY NEW USE. +%TACTZ==200000 ;4.8 ON => TTY IS FREE AND BEING ^Z'D, SO EVEN THOUGH IT APPEARS + ;OTHERWISE TO NEED A CONSOLE-FREE MESSAGE IT SHOULDN'T GET ONE. +%TANJS==100000 ;4.7 ON => TTY IS BEING ^Z'D, BUT THERE ARE NO JOB SLOTS. + ;4.8 WILL BE ON AND 4.9 OFF. SYS JOB WILL RESTORE ALL TO NORMAL + ;AFTER TYPING "SYSTEM FULL" ON THE TTY. +%TANEC==070000 ;4.6-4.3 NUMBER OF FOLLOWING CHARS TO INHIBIT ECHO AND INTS FOR. + ;THIS IS USED FOR THE ARG CHARS THAT FOLLOW TOP-E, TOP-S, TOP-Y, ETC. + +TTYCOM: REPEAT NCT,0,,-1 ;COMMUNICATE WORD +;4.9 => TTY IN COMMUNICATE MODE +%TCLFT==200000 ;4.8 => LOCAL FEED THROUGH (SET IF MY PRGM RECIEVING HIS CHRS) +%TCRFT==100000 ;4.7 => REMOTE FEED THROUGH (SET IF HIS PRGM RECIEVING MY CHRS) +%TCICO==40000 ;4.6 => INPUT COMMUNICATE OVERRIDE (SET IF MY CONSOLE FEEDING MY + ; PRGM EVEN THO IN COMM MODE). ALSO IMPLIES OUTPUT OVER-RIDE. +%TCOCO==20000 ;4.5 => OUTPUT COMMUNICATE OVERRIDE (SET IF MY PRGM'S OUTPUT TO APPEAR ON MY CONSOLE ONLY EVEN THO IN COM MODE) +;4.4-4.3 => MESSAGE RECEIPT SWITCH + ;00 => ACCEPT +%TCRFS==10000 ;10 => REFUSE +%TCQRY==4000 ;01 => INTERROGATE +%TCMTR==2000 ;4.2 SET FOR TTY WHOSE MOTOR IS OFF & MUST BE TURNED +;ON BEFORE ANY OTHER OUTPUT IS DONE. +;(ONLY TERMINETS HAVE THEIR MOTORS SHUT OFF BY ITS). +%TCECH==1000 ;4.1 THE OUTPUT BUFFER CONTAINS ECHOING OUTPUT. + ;THIS MAKES OUTPUT RESET DO NOTHING. + ;THE BUFFER MUST NOT CONTAIN ECHO OUTPUT AND NORMAL OUTPUT AT ONE TIME. +%TCDET==200 ;3.8 CONSOLE'S TREE DETACHED BY TOP LEVEL INTERRUPT. + ;SET BY NDETAC AS SIGNAL TO SYSCFM (CNSL-FREE-MSG TYPER) +%TCDNG==100 ;3.7 => TYPE BELL ON TTY (BECAUSE INPUT BFR FULL). +%TCCBK==40 ;3.6 => READING UNAME OR TTY # AFTER ^_K. +%TCCBS==20 ;3.5 => READING UNAME OR TTY # AFTER ^_S. +%TCFPD==10 ;3.4 => FIRST PART DONE (USED FOR %TNESC ESCAPE SEQUENCES, %TNODP CR) +%TCTPN==4 ;3.3 TYPE ^_N ON LEAVING COM MODE (UNLESS USER EXPLICITLY TYPES ^_N) +%TCPAD==2 ;3.2 0 => PADDING NECESSARY ON DATAPOINT. +%TCHNG==1 ;3.1 TTY'S DONE FLAG APPEARS TO BE FRIED, TIME OUT QUICKLY +;RH => USER INDEX COMMUNICATING WITH (-1 NONE) + + +;TTYTYP TABLE +;THIS TABLE HOLDS BITS THAT DESCRIBE THE LINE +;AND ITS CONTROLLER, RATHER THAN THE TTY ATTACHED TO THE LINE. + +%TTLCL==400000 ;BIT 4.9 ONE => LOCAL TTY +%TT340==200000 ;BIT 4.8 ONE => CONSOLE NEXT TO 340 OR A 340 SLAVE +%TT3HP==100000 ;BIT 4.7 HIGH PRIORITY ON 340 +%TTPAR==004000 ;BIT 4.3 THIS TTY NEEDS PARITY BIT SENT. +%TTDDI==002000 ;BIT 4.2 DONT DING ON EXCESS INPUT +$TTISP==260400 ;3.8-3.5 INPUT SPEED CODE +$TTOSP==220400 ;3.4-3.1 OUTPUT SPEED CODE + +%TYDPK==400000 ;BIT 2.9 DATAPOINT KLUDGE TERMINAL +%TYSTY==200000 ;BIT 2.8 PSEUDO TTY +%TYNVA==100000 ;BIT 2.7 NOVA TTY +%TYMTY==040000 ;BIT 2.6 MORTON BOX +%TYDIL==020000 ;BIT 2.5 DIAL UP +%TY11T==010000 ;BIT 2.4 PDP-11 TV TTY. +%TYDL== 004000 ;BIT 2.3 DL10 TTY +%TYOTY==002000 ;BIT 2.2 ORDINARY KA-10 CONSOLE TTY +%TYETY==001000 ;BIT 2.1 DTE-20 TTY (KL-10 CONSOLE) +%TYNTY==000400 ;BIT 1.9 TK-10 TTY. +%TYMDM==000200 ;BIT 1.8 LINE HAS MODEM CONTROL, DETECTS DIALINS AND HANGUPS +%TYKST==000100 ;BIT 1.7 KS-10 CONSOLE TTY +%TYDZT==000040 ;BIT 1.6 DZ-11 TTY ON KS-10 +%TYRLM==000020 ;BIT 1.5 ROLM DATA SWITCH + +TTYTYP: TTYREP TYP ;PART OF TTYTYP MAY BE WRITEABLE. +BBLK + 0 ;DISOWNED JOBS CANT HAVE LPT + %TTLCL,,;SYSTEM JOB CAN GET LPT + +.CRFOFF +IRPS X,,TYP OPT HOR VER TCT ROL SMT +REPEAT NCT,[ +CONC EXPUNG T,\.RPCNT,$!X +] +TERMIN +.CRFON + +OVHMTR UUO ;YET MORE RANDOM UUOS diff --git a/src/system/ttytyp.314 b/src/system/ttytyp.314 new file mode 100755 index 00000000..edca0a6a --- /dev/null +++ b/src/system/ttytyp.314 @@ -0,0 +1,400 @@ + +;THE MASTER COPY OF THIS FILE IS KEPT ON AI:SYSTEM;TTYTYP > +;DUPLICATES ARE KEPT ON OTHER ITS MACHINES BUT THEY SHOULD +;NEVER BE EDITED. IF YOU'RE NOT TOTALLY SURE OF WHAT YOU'RE DOING +;DON'T EDIT THIS FILE; ASK A HACKER FOR ASSISTANCE. + +;HOW TO DESCRIBE EACH TTY. IT ASSUMES THE FOLLOWING: +;EACH MACHINE MUST HAVE A BLOCK OF ENTRIES, WHICH STARTS WITH +;THREE SEMICOLONS, A SPACE , AND THE NAME OF THE MACHINE. +;THEN MUST COME EXACTLY ONE COMMENT PER TTY, STARTING WITH +;"TNM ". THERE MAY BE OTHER COMMENTS NOT STARTING WITH A "TNM ". +;THOSE OTHER COMMENTS WILL BE IGNORED BY "NAME". + +;THIS FILE IS ARRANGED SO THAT IT CAN BE ASSEMBLED BY EITHER MIDAS OR PALX +;THE FOLLOWING MACROS ARE USED IN THIS FILE +; +;SEPARATORS: +; MCONDX CONDITIONAL FOR WHICH MACHINE +; .ENDC TERMINATE ... +; + +;TERMINAL TYPES: +;FIRST ARGUMENT TO TTDXXX MACRO IS THE LINE NUMBER +;FOLLOWING THAT CAN BE SEVERAL OPTIONS, SELECTED BY THE FOLLOWING KEYWORD PARAMETERS: +;TT LH(TTYTYP) ADDED TO SPEED CODE +;TY RH(TTYTYP) ADDED TO CONTROLLER-SELECT BIT +;TO LH(TTYOPT) ADDED TO DEFAULT BITS FOR DEVICE +;TP RH(TTYOPT) ADDED TO PAD CODES, DEFAULT IS DEFAULT %TPORS AND %TPCBS +;TCT TCTYP DEFAULT IS APPROPRIATE FOR TERMINAL BEING DEFINED +;HOR SCREEN WIDTH DEFAULT .. +;VER SCREEN HEIGHT DEFAULT .. +;ROL LINES/GLITCH DEFAULT .. +;SPEED OUTPUT SPEED IN BAUDS DEFAULT IS APPROPRIATE.. +;ISPEED INPUT SPEED IN BAUDS (IF DIFFERENT) +;SOME TERMINAL TYPES DON'T ACCEPT SOME OF THESE OPTIONS WHICH WOULD BE MEANINGLESS. + +.XCREF TT,TY,TO,TP,TCT,HOR,VER,ROL,SPEED,ISPEED ;FOOL @ + +; TTDPRT PRINTING TERMINAL (SPEED=110 => TTY35). DEFAULT SPEED IS 300. +; TTDMRX MEMOREX 1240 +; TTDTRM TERMINET 1200 +; TTDLPT BRIGHT (OR ODEC OR GOULD) LINE PRINTER ON TTY LINE +; TTDLA36 LA 36 +; TTDIML IMLAC +; TTDVT VT-52 +; TTDH19 H19 +; TTDTEK TEKTRONIX +; TTDLSR LOSING DATAPOINT +; TTDDPT DATAPOINT +; TTDGT40 GT-40 +; TTD11 PDP-11 (LOOKS LIKE PRINTING TERMINAL) +; TTDRAN RANDOM TYPE, YOU BETTER SPECIFY EVERYTHING +; TTDTV PDP-11 TV "LINE" VIA TEN-11 INTERFACE +; TTDGRN PDP-11 TV (OR GRINNELL TV) ON NORMAL TTY LINE +; TTD2741 N,CODE 2741 CODE=0 => EBCDIC, CODE=1 => CORRESPONDENCE +; TTDSTY SOFTWARE PSEUDO-TTY +; TTDC100 CONCEPT-100 +; TTDAAA Ann Arbor Ambassador + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX AIKA,{ ;;; AI-KA + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 System Console (9th) + TTDPRT 1,SPEED=150,TY=%TYDIL ;T01 Dialup 15CPS * + ; 8-7874 15CPS + TTDPRT 2,SPEED=110,TY=%TYDIL ;T02 Dialup 10CPS * + ; 258-8794 10CPS + TTDPRT 3,SPEED=110,TT=%TTLCL ;T03 XGP TTY (9TH) + TTDPRT 4,SPEED=110,TT=%TTLCL+%TT340+%TT3HP ;T04 PDP6 TTY (9th) + TTDPRT 5,SPEED=110,TT=%TTLCL ;T05 TTY Near LPT (9th) + TTDPRT 6,SPEED=150,TY=%TYDIL ;T06 Dialup 15CPS * + ; 258-8795 15CPS + TTDPRT 7,SPEED=110,TT=%TTLCL+%TT340 ;T07 Little Robot TTY (9th) + TTDPRT 10,SPEED=134 ;T10 Baudot AP * + ;NEXT 3 USED TO BE 2741S, BUT WERE FLUSHED + TTDPRT 11,SPEED=134 ;T11 TSTC (9th) * + TTDPRT 12,SPEED=134 ;T12 2741 (9th) * + TTDPRT 13,SPEED=134,TY=%TYDIL ;T13 2741 Dialup * + TTDPRT 14 ;T14 Unused * + TTDPRT 15,SPEED=300,TY=%TYDIL ;T15 Dialup 30CPS + TTDPRT 16,SPEED=300,TY=%TYDIL ;T16 Dialup 30CPS + TTDPRT 17,SPEED=300,TY=%TYDIL ;T17 Dialup 30CPS + TTDPRT 20,SPEED=300,TY=%TYDIL ;T20 Dialup 30CPS + TTDVT 21,SPEED=4800,TT=%TTLCL ;T21 814 x7881 Barton,Berwick,Brotsky,Sjoberg + TTDTRM 22,TT=%TTLCL ;T22 Terminet in 813 (Hewitt) + TTDVT 23,SPEED=4800,TT=%TTLCL ;T23 926 Under the Miro x6765 + TTDDPT 24,TT=%TTLCL+%TT340,HOR=71. ;T24 Datapoint Near XGP (9th) + TTDAAA 25,TT=%TTLCL,SPEED=4800,TP=%TPMTA ;T25 810 Marty, Toto, Kansas x7836 + TTDDPT 26 ;T26 Datapoint in 822 (Stansfield) + TTDAAA 27,TT=%TTLCL,SPEED=4800 ;T27 926 Under ee cummings x6765 + TTDTRM 30,ISPEED=150,TY=%TYDIL ;T30 Dialup 120/15 CPS + ; 258-6091 150 IN, 1200 OUT TERMINET + TTDAAA 31,TT=%TTLCL,SPEED=4800,TP=%TPMTA ;T31 936 Lisp Machine Factory x6703 + TTDTRM 32,ISPEED=150,TY=%TYDIL ;T32 Dialup 120/15 CPS + ; 258-6090 150 IN, 1200 OUT TERMINET + TTDAAA 33,SPEED=4800,TT=%TTLCL ;T33 336 Sobalvarro, Delatizky x5834 + TTDVT 34,SPEED=4800,TT=%TTLCL ;T34 908 Oro + TTDDTM 35,SPEED=4800 ;T35 Poggio, Ullman x5781 (Bldg E10) + TTDRAY 36,SPEED=4800,TP=%TPMTA,TT=%TTLCL ;T36 812 Attardi, Barber, Koton (x7891) + TTDRAY 37,SPEED=4800,TP=%TPMTA,TT=%TTLCL ;T37 939 Kornfeld x5835 + TTDGT40 40,VER=29.,HOR=68.,TO=-%TOOVR ;T40 Micro-Automation PDP-11 (9th) +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MLKA,{ ;;; ML-KA + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 System Console + TTDPRT 1,SPEED=1200,TY=%TYDIL ;T01 Dial-up 1.2KB Vadic + ;258-6756 + TTDPRT 2,SPEED=300,TY=%TYDIL ;T02 Dial-up line 30CPS + ;258-6742 + TTDPRT 3,SPEED=300,TY=%TYDIL ;T03 Dial-up line 30CPS + ;258-6743 + TTDPRT 4,SPEED=1200,TY=%TYDIL ;T04 Dial-up 1.2KB Vadic + ;258-7894 + TTDVT 5 ;T05 350 Waters x6037 + TTDDPT 6,TT=%TTLCL ;T06 9th flr near console + TTDLA36 7 ;T07 800D DECwriter + TTDVT 10 ;T10 3rd flr VT52 #833 + TTDPRT 11,SPEED=1200,TY=%TYDIL ;T11 Dial-up 1.2KB Vadic + ;258-6757 + TTDVT 12 ;T12 8th flr VT52 + TTDVT 13 ;T13 8th flr VT52 #433 + TTDVT 14 ;T14 8th flr VT52 + TTDVT 15 ;T15 8th flr VT52 + TTDVT 16 ;T16 3rd flr VT52 #517 + TTDVT 17 ;T17 3rd flr VT52 #256 + TTDVT 20 ;T20 3rd flr VT52 #342 + TTDVT 21 ;T21 3rd flr VT52 #1224 + TTDVT 22 ;T22 3rd flr VT52 #8462 + TTDVT 23 ;T23 3rd flr VT52 #8453 + TTDVT 24 ;T24 3rd flr VT52 #7559 + TTDVT 25 ;T25 3rd flr VT52 #8379 + TTDVT 26 ;T26 3rd flr VT52 #7320 + TTDVT 27 ;T27 3rd flr VT52 #8437 + TTDVT 30 ;T30 VT52 in Library + TTDVT 31 ;T31 5th flr VT52 + ;This is now plugged into the right-hand 4-prong in 512A. That is in + ;parallel with Ann Rubin (Liskov-Dennis's secretary), so she'd + ;need to be asked if someone wanted to do an - ahem - demo. + TTDPRT 32,SPEED=1200,TY=%TYDIL ;T32 Dial-up 1.2KB Vadic + ;258-6733 + TTDC100 33 ;T33 317 Burke x3546 +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX DM,{ ;;; DM + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 930 x2910 CPU + TTDLPT 1 ;T01 215 ODEC LPT + TTDVT 2 ;T02 205 x1440 Lebling + TTDVT 3 ;T03 219 x1450 Vezza + TTDVT 4 ;T04 203 x1429 Sangal + TTDVT 5 ;T05 214A x1410 Apollo Room + TTDIML 6 ;T06 [not in use] + TTDPRT 7 ;T07 214A x1410 APOLLO + TTDVT 10 ;T10 204 x1418 Galley + TTDVT 11 ;T11 801/A x6025/4 Faris/Meyer + TTDVT 12 ;T12 218 x7706 Venckus + TTDVT 13 ;T13 222 x5800 Niamir + TTDPRT 14,SPEED=110,TT=%TTLCL ;T14 [not in use] + TTDIML 15 ;T15 [not in use] + TTDVT 16 ;T16 209 x1430 Ilson + TTDIML 17 ;T17 [not in use] + TTDVT 20 ;T20 218A x7705 Licklider + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MX,{ ;;; MX + TTDLA36 0,TT=%TTLCL,HOR=110. ;T00 System Console + TTDPRT 1,SPEED=1200,TY=%TYDIL+%TYMDM ;T01 Vadic Dialup + ;253-6045 + TTDVT 2,SPEED=9600 ;T02 TRANTOR Math Dept 2-366 x3-6598 + TTDPRT 3,TY=%TYDIL+%TYMDM ;T03 Dialup + TTDPRT 4,TY=%TYDIL+%TYMDM ;T04 Dialup + ;253-7985 + TTDPRT 5,TY=%TYDIL+%TYMDM ;T05 Dialup + ;253-7986 + TTDPRT 6,TY=%TYDIL+%TYMDM ;T06 Dialup + ;253-7987 + TTDPRT 7,TY=%TYDIL+%TYMDM ;T07 Dialup + ;253-7988 + TTDPRT 10,TY=%TYDIL+%TYMDM ;T10 Vadic Dialup + ;253-6985 + TTDPRT 11,TY=%TYDIL+%TYMDM ;T11 Vadic Dialup + ;253-6986 + TTDPRT 12,TY=%TYDIL+%TYMDM ;T12 Vadic Dialup + ;253-6987 + TTDPRT 13,TY=%TYDIL+%TYMDM ;T13 Vadic Dialup + ;253-6988 + TTDPRT 14,TY=%TYDIL+%TYMDM ;T14 Vadic Dialup + ;253-6989 + TTDPRT 15,TY=%TYDIL+%TYMDM ;T15 Vadic Dialup + ;253-6990 + TTDPRT 16,TY=%TYDIL+%TYMDM ;T16 Vadic Dialup + ;Draper Lab + TTDPRT 17,TY=%TYDIL+%TYMDM ;T17 Vadic Dialup + TTDDPT 20 ;T20 not connected + TTDPRT 21,TY=%TYRLM,SPEED=9600 ;T21 ROLM Data Feature + ; #4997 + TTDPRT 22,TY=%TYRLM,SPEED=9600 ;T22 ROLM Data Feature + ; #4996 + TTDPRT 23,TY=%TYRLM,SPEED=9600 ;T23 ROLM Data Feature + ; #4601 + TTDPRT 24,TY=%TYRLM,SPEED=9600 ;T24 ROLM Data Feature + ; #4999 + TTDPRT 25,TY=%TYRLM,SPEED=9600 ;T25 ROLM Data Feature + TTDPRT 26,TY=%TYRLM,SPEED=9600 ;T26 ROLM Data Feature + ; #4603 + TTDPRT 27,TY=%TYRLM,SPEED=9600 ;T27 ROLM Data Feature + TTDPRT 30,TY=%TYRLM,SPEED=9600 ;T30 ROLM Data Feature + TTDPRT 31,TY=%TYRLM,SPEED=9600 ;T31 ROLM Data Feature + ; #4991 + TTDPRT 32,TY=%TYRLM,SPEED=9600 ;T32 ROLM Data Feature + ; #4992 + TTDPRT 33,TY=%TYRLM,SPEED=9600 ;T33 ROLM Data Feature + TTDPRT 34,TY=%TYRLM,SPEED=9600 ;T34 ROLM Data Feature + TTDPRT 35,TY=%TYRLM,SPEED=9600 ;T35 ROLM Data Feature + TTDPRT 36,TY=%TYRLM,SPEED=9600 ;T36 ROLM Data Frobozz + ; #4990 + TTDPRT 37,TY=%TYRLM,SPEED=9600 ;T37 ROLM Data Feature + TTDPRT 40,TY=%TYRLM,SPEED=9600 ;T40 ROLM Data Feature + TTDPRT 41,TY=%TYRLM,SPEED=300 ;T41 ROLM slow + TTDPRT 42,TY=%TYRLM,SPEED=9600 ;T42 ROLM Data Feature + TTDVT 43,TT=%TTLCL ;T43 9th Floor VT52 + TTDPRT 44,SPEED=110,TT=%TTLCL ;T44 DC76 TTY +.ENDC ;} + +REPEAT NSTTYS,[ + TTDSTY \NFSTTY+.RPCNT +.ENDR ;] + +REPEAT N11TYS,[ + TTDTV \NF11TY+.RPCNT +.ENDR ;] + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX AI,{ ;;; AI + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=1200 ;T01 Chronograph + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=2400,TY=%TYDIL ;T03 Dialup + ;258-7814 + TTDPRT 4,SPEED=2400,TY=%TYDIL ;T04 Dialup + ;258-7815 + TTDVT 5,SPEED=9600 ;T05 DZ Line 5 (VT52) + TTDVT 6,SPEED=9600,TT=%TTLCL ;T06 9th Floor VT52 by AI x6765 + TTDVT 7,SPEED=9600 ;T07 DZ Line 7 (VT52) + TTDAAA 10,SPEED=9600 ;T10 DZ Line 8 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MC,{ ;;; MC + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=2400,TY=%TYDIL ;T01 Dialup + ;258-7585 + TTDPRT 2,SPEED=2400,TY=%TYDIL ;T02 Dialup + ;258-7586 + TTDVT 3,SPEED=9600,TT=%TTLCL ;T03 9th Floor VT52 by MC x6765 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDAAA 6,SPEED=9600 ;T06 DZ Line 6 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX ML,{ ;;; ML + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=2400,TY=%TYDIL ;T01 Dialup + ;258-7832 + TTDPRT 2,SPEED=2400,TY=%TYDIL ;T02 Dialup + ;258-7833 + TTDVT 3,SPEED=9600,TT=%TTLCL ;T03 9th Floor VT52 by ML x6765 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDAAA 6,SPEED=9600 ;T06 DZ Line 6 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MD,{ ;;; MD + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDVT 1,SPEED=9600,TT=%TTLCL ;T01 9th Floor VT52 by MD x6765 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDAAA 4,SPEED=9600 ;T04 DZ Line 4 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX SI,{ ;;; SI + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 DZ Line 1 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + TTDPRT 11,SPEED=9600 ;T11 DZ Line 11 + TTDPRT 12,SPEED=9600 ;T12 DZ Line 12 + TTDPRT 13,SPEED=9600 ;T13 DZ Line 13 + TTDPRT 14,SPEED=9600 ;T14 DZ Line 14 + TTDPRT 15,SPEED=9600 ;T15 DZ Line 15 + TTDPRT 16,SPEED=9600 ;T16 DZ Line 16 + TTDPRT 17,SPEED=9600 ;T17 DZ Line 17 + TTDPRT 20,SPEED=9600 ;T20 DZ Line 20 + TTDPRT 21,SPEED=9600 ;T21 DZ Line 21 + TTDPRT 22,SPEED=9600 ;T22 DZ Line 22 + TTDPRT 23,SPEED=9600 ;T23 DZ Line 23 + TTDPRT 24,SPEED=9600 ;T24 DZ Line 24 + TTDPRT 25,SPEED=9600 ;T25 DZ Line 25 + TTDPRT 26,SPEED=9600 ;T26 DZ Line 26 + TTDPRT 27,SPEED=9600 ;T27 DZ Line 27 + TTDPRT 30,SPEED=9600 ;T30 DZ Line 30 + TTDPRT 31,SPEED=9600 ;T31 DZ Line 31 + TTDPRT 32,SPEED=9600 ;T32 DZ Line 32 + TTDPRT 33,SPEED=9600 ;T33 DZ Line 33 + TTDPRT 34,SPEED=9600 ;T34 DZ Line 34 + TTDPRT 35,SPEED=9600 ;T35 DZ Line 35 + TTDPRT 36,SPEED=9600 ;T36 DZ Line 36 + TTDPRT 37,SPEED=9600 ;T37 DZ Line 37 + TTDPRT 40,SPEED=9600 ;T40 DZ Line 40 + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX FU,{ ;;; FU + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 DZ Line 1 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX PM,{ ;;; PM + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 (9600 baud) + TTDPRT 2,SPEED=9600 ;T02 (9600 baud) + TTDPRT 3,SPEED=1200,TY=%TYDIL ;T03 Dialup (1200 baud) + TTDPRT 4,SPEED=1200,TY=%TYDIL ;T04 Dialup (1200 baud) + TTDPRT 5,SPEED=9600 ;T05 (9600 baud) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX DX,{ ;;; DX + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=300 ;T01 DZ Line 1 (300 baud) + TTDPRT 2,SPEED=1200 ;T02 DZ Line 2 (1200 baud) + TTDPRT 3,SPEED=2400 ;T03 DZ Line 3 (2400 baud) + TTDPRT 4,SPEED=4800 ;T04 DZ Line 4 (4800 baud) + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + +.ENDC ;} diff --git a/src/system/tv.132 b/src/system/tv.132 new file mode 100755 index 00000000..e8d87f0d --- /dev/null +++ b/src/system/tv.132 @@ -0,0 +1,5995 @@ +;-*-MIDAS-*- + +.SBTTL MACROS AND CONDITIONAL ASSEMBLY + +;AI PDP-11 TV CONSOLE PROGRAM +; USER WHO-LINE VARIABLES CODE ADDED 7/28/75 BY GLS +; AUDIO SWITCH CODE REWRITTEN 7/12/76 BY ED +; TV IS PDP-11 NUMBER 0 TO THE 10-11 INTERFACE. +; ELEVATOR CODE 2/13/79 BY DANNY & HIC +; REGION-SCROLLING 11/3/79 MOON + +FONTSW==1 ;COMPILE FONTS +FONTMS==0 ;USE MACROS TO COMPILE FONTS + +;REGISTER ASSIGNMENTS + +A=%0 ;ASCII CHARACTER +B=%1 ;META BITS +C=%2 ;C, T, AND TT ARE TEMPORARIES +T=%3 +TT=%4 +U=%5 ;LINE EDITOR OR PAGE PRINTER +SP=%6 +PC=%7 + +.XCREF A,B,C,T,TT,U,SP,PC,...,.... + +.IIF E FONTSW,.TITLE TV NOFONTS + +.IF NE FONTSW +.TITLE TV +.IF NE FONTMS +.NLIST ;WE'RE ONLY INTERESTED IN FONTS +.IF1 +.PRINT /THIS ASSEMBLY WILL TAKE FOREVER! +/ +.ENDC ;.IF1 +.ENDC ;.IF NE FONTMS +.ENDC ;.IF NE FONTSW + +.MACRO PUSH A +.NLIST + MOV A,-(SP) +.LIST +.ENDM + +.MACRO POP A +.NLIST + MOV (SP)+,A +.LIST +.ENDM + +.MACRO REPORT TEXT,NUM +.NLIST +.IF2 +.LIST +.PRINT /TEXT'NUM +/ +.NLIST +.ENDC +.LIST +.ENDM + +.MACRO CHROFF +.NLIST + MOVB PS,-(SP) + MOVB #LKLVL,PS +.LIST +.ENDM + +.MACRO CHRON +.NLIST + MOVB (SP)+,PS +.LIST +.ENDM + +.MACRO BLKOFF A +.NLIST + INCB BLKSWT(A) +.LIST +.ENDM + +.MACRO BLKON A +.NLIST + DECB BLKSWT(A) + BGE .+4 + BPT +.LIST +.ENDM + +.MACRO TENWRD +.NLIST +.IIF NE .&3,.=<.&177774>+4 +.LIST +.ENDM + +.MACRO CHECK TAG,LENGTH +.NLIST +.IF NE .-- +.ERROR TAG WRONG LENGTH +.ENDC +.EVEN +.LIST +.ENDM + +.MACRO TYPOUT A +.NLIST + JSR PC,OUTSTR + .ASCIZ A + .EVEN +.LIST +.ENDM + +.MACRO DECTYPE NUM +.NLIST + MOV NUM,A + JSR PC,DECPNT +.LIST +.ENDM + +.MACRO OCTYPE NUM +.NLIST + MOV NUM,A + JSR PC,OCTPNT +.LIST +.ENDM + +.MACRO ZAPFLG FLAG +.NLIST +%COMPAT==0 + MOV PC,FLAG +%COMPAT==1 +.LIST +.ENDM + +.MACRO CONC A,B,C,D,E,F,G,H,I +A'B'C'D'E'F'G'H'I +.ENDM + +.IF NE 0 ;PROGRAM MAP: +0, TO PDLORG ;TRAP VECTORS +PDLORG, TO KBDBUF ;PUSH DOWN LIST +KBDBUF, TO GO ;KBD BUFFER +GO, TO XTAB ;PROGRAM +XTAB, TO FNTORG ;KEYBOARD TRANSLATION TABLE +FNTORG, TO VARORG ;FONT DEFINITION +VARORG, TO MISORG ;LINE EDITOR/PAGE PRINTER VARIABLES +MISORG, TO PATCH ;MISCELLANEOUS TABLES AND VARIABLES +PATCH, TO LEBUFS ;PATCH AREA +LEBUFS, TO RUGSA ;FREE STORAGE +.ENDC + +.SBTTL HOW IT WORKS +.REPT 0 +channel header pointer (location 40, read only) + + ADDRESS(channel header area) + ADDRESS(pointer area) + I/O version number + source file version number + 0 always 0 + INITED non-zero indicates PDP-11 is running ok(can be cleared by PDP-10) + 0 always 0 + GDOWN used as flag by PDP-10 to acknowledge clear of INITED +channel header area (aligned on PDP-10 word) + + KBD channel: + KBDFLG cleared by 10/set by 11 (chain of activated KBD buffers) + 0 allows PDP-10 to do SKIPN for activation test + DPY channel: (1 per console) + DPYCHN buffer assigned to channel, if zero then DPY channel is closed + DPYKBD .BYTE KBD#, DPY# (377 for either implies not assigned) + KBD flags: (1 per console) + ECOFLG Set by PDP-10. Next time DPYBUF is empty clear ECOFLG + and put flag on KBD ring to signal this condition + CHNCLS if -1, log this guy out!!!! + If non-negative, has keyboard number (377 if none). + WHO flags: (1 per console) + WHOLIN who line variables for this console + WHOUSR -1=>user who line, 0=>system who line + + +format of KBD buffer (aligned on PDP-10 word) + + KBDSTS negative=>-(data byte count), 0=>free + 0 + KBDRNG next KBD buffer associated with this KBD + KBDLST next buffer on activated list (0=>end of chain) + KBDCHN keyboard channel + 0 not used + KBDATA key board data area (1 PDP-11 word/character) + +format of DPY buffer (aligned on PDP-10 word) + (actually, this is the beginning of the "line editor vars" or "channel vars" block). + + DPY10B word PDP-10 is hacking (used only for initailization) + This always points at DPYATA for this buffer these days. + DPY11B word PDP-11 is hacking + 0 + DPYLGL last legal address in this buffer + DPYSIZ size of data area in bytes + 0 not used + DPYATA display data area (1 PDP-11 byte/character) + +format of pointer area (aligned on PDP-10 word) + + ADDRESS(system who line variables) + ADDRESS(PDP-10/PDP-11 communication area) + TENWHO -1=>PDP-10 should update who lines + TENWH1 pads TENWHO + SYMTAB BEGINNING OF TABLE OF SWITCHES WHICH 10 ACCESSES. + +Notes: + +1. All addresses and pointers are in PDP-11 address space. + +2. KBD buffers are ringed two per channel. While the PDP-10 is + emptying one, the PDP-11 can fill the other. + +3. There is only one DPY buffer per channel. When the buffer is filled + with negative ones, it is free. When the PDP-10 writes a character + in the current word: then the PDP-11 processes the data in that + word, sets that word to negative one, and advances to the next word. + (Formerly any negative number would do, but now that the byte size is + 8 rather than 16, -1 [377] must be used since valid characters > 200 exist.) + +WHO LINE VARIABLES + +SYSTEM WHO LINE (ALIGNED ON PDP-10 WORD) + ITSTDP # total # dpy's (read only for PDP-10) + ITSFDP # free dpys (read only for PDP-10) + ITSVER ITS version # + ITSJOB total jobs + ITSCOR total core + ITSRU runnable users + ITSWBJ # jobs swap blocked + ITSJWP # jobs waiting for pages + ITSTRC total runable core + ITSCFU core available for users + ITSDAT date [byte (7) year (4) month (5) day] + ITSDBG system debug flag + ITSTIM time of day (# half seconds since midnight) aligned on PDP-10 word + ITSTI1 low order of time + ITSUSR total number of users + ITSFSH fair share + +USER WHO LINE (ALIGNED ON PDP-10 WORD) + WHJOB job #, -1=>who line not in use + WHJOB1 if negative then clear who line + WHMODE mode 0=>follow keyboard + 1=>freeze + 2=>next higher (when PDP-10 sees this state, it searches + user variables for next higher job index number with same + uname. When it finds it, it stores the number in job # + and changes mode to 1 + 3=>next lower + WHMOD1 pads WHMODE + WHUNAM uname in sixbit (left 18 bits in first two words, right in next two) + WHUNM1 + WHUNM2 + WHUNM3 + WHJNAM jname in sixbit + WHJNM1 + WHJNM2 + WHJNM3 + WHSNAM sname in sixbit + WHSNM1 + WHSNM2 + WHSNM3 + WHSTAT status in sixbit, 0=>job does not exist + WHSTA1 + WHSTA2 + WHSTA3 + WHJ%RT job % run time + WHJTRT job total run time (in tenth's of seconds) + WHRPAG job real memory pages (swapped in) + WHTPAG job total pages + +NOTE: The PDP-11 will not update who lines until it sees that ITSTIM + has changed. + +PDP-10/PDP-11 COMMAND CHANNEL + + CMDFLG aligned on PDP-10 + 0=>buffer is free (PDP-10 can write CMDBUF) + positive=>command # from PDP-10 (PDP-11 can write CMDBUF) + negative=>affirmative reply from PDP-11 (0=>command failed) + PDP-10 can read CMDBUF, then must zero CMDFLG + CMDFL1 always 0 + CMDBUF each arg takes 4 bytes (1 PDP-10 word) + + PDP-10/PDP-11 COMMANDS + + 1 video switch + arg1: video switch input # (set by PDP-10) + arg2: video switch output # ( " " " " ) + + 2 reserve DPY + arg1: DPY reserved (set by PDP-11) + + 3 free DPY + arg1: DPY to free (set by PDP-10) + + 4 read video switch + arg1: < 0 for default setting, > 0 for current setting (set by PDP-10) + 1=>tty chnl, 2=>KBD, 3=>video switch output + arg2: # described by arg1 (set by PDP-10) + arg3: input (set by PDP-11) + arg4: input (set by PDP-11) + arg5: output(set by PDP-11) + + 5 audio switch + arg1: audio switch input # (set by PDP-10) + arg2: audio switch output # (set by PDP-10) + + 6 read audio switch (for this to be useful, 11 must maintain table, since + the audio switch is read-only. + arg1: < 0 for default setting, > 0 for current setting (set by PDP-10) + 1=>tty chnl, 2=>KBD, 3=>audio switch output + arg2: # described by arg1 (set by PDP-10) + arg3: input (set by PDP-11) + arg4: output(set by PDP-11) + +;other 10-11 commuincation issues .. + +;go down resetting video switch vs not +;PDP-11 indicates it has reset video switch + ;(PDP-10 then detaches all jobs with tv ttys) + +;console scroll register 6/23/74 + +CSA==157776 ;selects where video scan starts in video buffer + +__|_____|_____|_____|_____|_____| +15 1211 | +| 3 |1| 12 | +|_____|_|_______________________| + | | | + | | |----------------->scroll offset (start video scan at n*4 PDP-11 words from TVLO) + | | + | |------------------------------->black on white bit (1=>black on white) + | + |----------------------------------->not used + + + +;console register 6/24/74 + +CREG==164044 ;selects video buffer memory + +__|_____|_____|_____|_____|_____| +15 7 | +| 8 | 8 | +|_______________|_______________| + | | + | |-------------->console # (TVLO-TVHI on unibus is video bit map) + | + |------------------------------>ALU function + +video switch 4/17/74 + +VSW==164060 ;sets video switch + +__|_____|_____|_____|_____|_____| +15 12 10 7 3 | +| 3 | 2 | 3 | 4 | 4 | +|_____|___|_____|_______|_______| + | | | | | + | | | | |---------->video source + | | | | + | | | |------------------>not used + | | | + | | |------------------------->| |card section + | | |switch output| + | |------------------------------>| |card select + | + |----------------------------------->switch section number + + +audio switch 7/12/76 + +ASW==170670 ;SETS AUDIO SWITCH. (this is a write-only memory.) + +__|_____|_____|_____|_____|_____| +15 13 10 7 3 | +| 2 | 3 | 3 | 4 | 4 | +|___|_____|_____|_______|_______| + | | | | | + | | | | |---------->audio source + | | | | + | | | |------------------>not used + | | | + | | |------------------------->| |card section (complemented) + | | |switch output| + | |------------------------------->| |card select + | + |------------------------------------>not used + +ASWXOR==1617 ;complemented fields of ASW. + +keyboard multiplexor 3/15/74 + +KBDPC==340 ;interrupt vector +KBDLVL==5_7 ;interrupts on level 5 + +KMS==164050 ;keyboard status + +__|_____|_____|_____|_____|_____| +151413121110 9 8 7 6 5 4 1 | +|1|1|1|1|1|1|1|1|1|1|1| 3 | 2 | +|_|_|_|_|_|_|_|_|_|_|_|_____|___| + | | | | | | | | | | | | | + | | | | | | | | | | | | |------>KMA extension (bits 17 and 16) + | | | | | | | | | | | | + | | | | | | | | | | | |----------->not used + | | | | | | | | | | | + | | | | | | | | | | |--------------->interrupt enable + | | | | | | | | | | + | | | | | | | | | |----------------->direct memory access enable + | | | | | | | | | + | | | | | | | | |------------------->waiting to hack memory + | | | | | | | | + | | | | | | | |--------------------->8th floor elevator + | | | | | | |----------------------->9th floor elevator + | | | | | | + | | | | | |------------------------>extra OC output, pin BBF1. + | | | | | + | | | | |--------------------------->buzz the 9th floor door (dip relay) + | | | | + | | | |----------------------------->generate copy from second source(currently not + | | | enabled) + | | |------------------------------->generate copy from first source + | | + | |--------------------------------->ready line + | + |----------------------------------->waiting to interrupt + +KMA==165052 ;keyboard memory address register + +__|_____|_____|_____|_____|_____| +15 7 1 | +| 9 | 5 | 2 | +|_________________|_________|___| + | | | + | | |----->always 0 + | | + | |------------>binary counter (overflow lost) + | + |------------------------->buffer origin + +;keyboard multiplexor 3/15/74 +;format of data written into memory (each record is two words) + +;first word + +__|_____|_____|_____|_____|_____| +151413 11 9 7 5 | +|1|1| 2 | 2 | 2 | 2 | 6 | +|_|_|___|___|___|___|___________| + | | | | | | | + | | | | | | |--------->key struck + | | | | | | + | | | | | |----------------->shift (7-left, 6-right) + | | | | | + | | | | |--------------------->top (9-left, 8-right) + | | | | + | | | |------------------------->control (11-left, 10-right) + | | | + | | |----------------------------->meta (13-left, 12-right) + | | + | |-------------------------------->shift lock + | + |---------------------------------->always 1 + +;second word + +__|_____|_____|_____|_____|_____| +15 13 7 | +| 2 | 6 | 8 | +|___|___________|_______________| + | | | + | | |----------->high order bits of character (ignored) + | | + | |------------------------->console number + | + |--------------------------------->always 0 + +.ENDR + +;CHARACTER FORMAT WRITTEN BY KBD MULTIPLEXOR + +RCHAR==177700 ;6 BITS FOR KEY STRUCK +RSHBIT==300 ;SHIFT BITS +RTPBIT==1400 ;TOP BITS +RCLBIT==6000 ;CONTROL BITS +RMTBIT==30000 ;META BITS +RSLBIT==40000 ;SHIFT LOCK +RXTRA==100000 ;UNUSED BITS + +;XTAB BITS USED FOR XTAB LOOK UP + +XTPBIT==400 ;TOP +XSLBIT==200 ;SHIFT LOCK +XSHBIT==100 ;SHIFT + +;POSITION OF META BITS, ASCII COMPATIBLE + +ACTBIT==SNB ;CAUSES CHARACTER TO ACT AS ACTIVATOR +ACLBIT==200 ;CONTROL +AMTBIT==400 ;META +ASHBIT==XSHBIT_3 ;SHIFT +ASLBIT==XSLBIT_3 ;SHIFT LOCK +ATPBIT==XTPBIT_3 ;TOP +ACMBIT==AMTBIT+ACLBIT ;CONTROL AND META TOGETHER + +.SBTTL ASSIGNMENTS + +;GEOMETRY + +BITPL==1100 ;BITS PER LINE +NLINS==706 ;LINES ON SCREEN +BYTPL==BITPL/10 ;BYTES PER LINE +WRDPL==BYTPL/2 ;WORDS PER LINE + +CHRWD==6 ;CHARACTER WIDTH ON TEXT LINE +GRIDWD==5 ;WIDTH OF CHARACTER GRID +CHRHT==12 ;CHARACTER HEIGHT +CHRVSP==2 ;BLANK RASTER LINES BETWEEN CHARACTER LINES +LINHT==CHRHT+CHRVSP ;CHRACTER LINE HEIGHT +CHRPL==BITPL/CHRWD ;CHARACTERS PER LINE +CHRLN==NLINS/LINHT ;CHARACTER LINES ON SCREEN + +;MEMORY MAP + +NXMPC== 4 ;BUS ERROR VECTOR +NXMPSW== 6 +RESPC== 10 ;RESERVED INTRUCTION VECTOR +RESPSW== 12 +BPTPC== 14 ;BREAK POINT VECTOR +BPTPSW== 16 +IOTPC== 20 ;IOT VECTOR +IOTPSW== 22 +PWRPC== 24 ;POWER FAIL TRAP VECTOR +PWRPSW== 26 +EMTPC== 30 ;EMULATE TRAP VECTOR +EMTPSW== 32 +TRPPC== 34 ;TRAP INSTRUCTION VECTOR +TRPPSW== 36 +TYIPC== 60 ;TTY INPUT INTERRUPT VECTOR +TYIPSW== 62 +LKPC== 100 ;LINE CLOCK INTERRUPT VECTOR +LKPSW== 102 +KLIPC== 320 ;KL11 INPUT INTERRUPT VECTOR +KLIPSW==322 +KBDPC== 340 ;KEYBOARD MULTIPLEXOR INTERRUPT VECTOR +KBDPSW==342 + +PDLORG==400 ;ORIGIN OF PUSH DOWN LIST +TVLO=60000 ;ORIGIN OF DISPLAY MEMORY +TVFENCE=TVLO+ ;ADDR OF FIRST TEXT LINE THAT SHOULDN'T BE USED + ;(IT'S INCOMPLETE AND CONTAINS THE WHO-LINE). +TVCFENC=TVHI-> ;DON'T TRY TO DISPLAY A CHARACTER AFTER THIS POINT +TVHI=TVLO+-2 ;HIGHEST LEGAL DISPLAY ADDRESS +CSA=157776 ;DISPLAY REFRESH STARTING ADDRESS (STARTS AT 0) + +CREG== 164044 ;UNIBUS CONSOLE REGISTER ADDRESS +CALU== 164045 ;CONSOLE REGISTER LOGICAL FUNCTION ADDR +KMS== 164050 ;KEYBOARD MULTIPLEXOR STATUS +KMA== 164052 ;KEYBOARD MULTIPLEXOR MEMORY ADDRESS +VSW== 164060 ;VIDEO SWITCH +ASW== 170670 ;AUDIO SWITCH +KLIS== 174000 ;KL11 INPUT STATUS +KLIB== 174002 ;KL11 INPUT BUFFER +KLOS== 174004 ;KL11 OUTPUT STATUS +KLOB== 174006 ;KL11 OUTPUT BUFFER + +.EXPUNGE DIV,MUL,ASH ;THESE ARE PREDEFINED AS 11/45 INSTRUCTIONS. +DIV== 177300 ;EAE GOODIES +AC== 177302 +MQ== 177304 +MUL== 177306 +SC== 177310 +SR== 177311 +NOR== 177312 +LSH== 177314 +ASH== 177316 +LKS== 177546 ;LINE CLOCK STATUS +TKS== 177560 ;TTY KEYBOARD STATUS +TKB== 177562 ;TTY KEYBOARD BUFFER +TPS== 177564 ;TTY PRINTER STATUS +TPB== 177566 ;TTY PRINTER BUFFER +CSR== 177570 ;CONSOLE SWITCH REGISTER +PS== 177776 ;PROCESSOR STATUS REGISTER +...==0 +....==0 + +;TEN/11 COMMUNICATIONS AREA + +CHAP==40 ;CHANNEL HEADER AREA POINTER +POINTP==42 ;POINTER TO POINTER AREA +CIOVER==44 ;HOLDS I/O VERSION FOR PDP-10 TO LOOK AT +CVERSE==46 ;ASSEMBLY VERSION FOR PDP-10 + ;50 ;ALWAYS 0 +INITED==52 ;INITED FLAG, SET BY 11 CLEARED BY 10 + ;54 ;ALWAYS 0 +GDOWN==56 ;INTERLOCKS WITH INITED, CLEARED BY 11 SET BY 10 + +;CONSOLE REGISTER FUNCTIONS + +CSETC==0 +CNOR==1 +CANDC==2 +CSETZ==3 +CNAND==4 +CCOMP==5 +CXOR==6 +CANCSD==7 +CEQV==11 +CORCSD==10 +CSAME==12 +CAND==13 +CORSCD==13 +CSETO==14 +CIOR==16 +CSET==17 + +;INTERRUPT LEVELS + +KBDLVL==5_5 ;KEYBOARD MULTIPLEXOR INT. PRIORITY (BUT HANDLER RUNS AT LKLVL). +LKLVL==6_5 ;LINE CLOCK +ERRLVL==7_5 ;PROCESSOR ERRORS + +;MISCELLANEOUS ASSIGNMENTS + +IOVER==3 ;I/O VERSION FOR ITS +PDL==400 ;PUSH DOWN LIST SIZE +MAXKBD==64. ;MAXIMUM # OF KEYBOARDS +MAXTV==16. ;MAX NUMBER OF TV DISPLAYS +MAXBLK==MAXTV ;MAXIMUM # OF BLINKERS +MAXASI==20 ;AUDIO SWITCH INPUTS +MAXASO==100 ;AUDIO SWITCH OUTPUTS +ASWXOR==3400 ;XOR THIS INTO EACH CONTROL WORD TO BE SENT TO THE ASW. +MAXVSI==20 ;VIDEO SWITCH INPUTS +MAXVSO==40 ;VIDEO SWITCH OUTPUTS +VSWSEC==2 ;# VIDEO SWITCH SECTIONS +VSWINC==MAXVSO_10 ;INCREMENTS VIDEO SWITCH SECTION NUMBER +QPYVSW==27 ;VIDEO SWITCH OUTPUT FOR TEKTRONIX VIDEO HARD COPY UNIT +QPTIME==21.*60. ;21. SECONDS BETWEEN COPIES +QPYKMS==20000 ;GENERATE COPY FROM FIRST SOURCE (IN KEYBOARD STATUS, NATURALLY) +QPYKM2==10000 ;GENERATE COPY FROM SECOND SOURCE. +BUZKMS==4000 ;BUZZ DOOR (ALSO IN KEYBOARD STATUS) +BUZTIM==3*60. ;LEAVE THE DOOR BUZZING FOR 3 SECONDS +ELKMS8==1 ;8TH FLOOR ELEVATOR BIT, SWAPPED (IT LIVES IN BYTE 1 OR WORD) +ELKMS9==2 ;9TH FLOOR ELEVATOR BIT, SWAPPED. +ELEKMS==1400 ;ALL ELEVATOR BITS +ELETIM==20 ;PUSH THE BUTTON FOR 1/3 OF A SEC +KBDTIM==10. ;TIME UNTIL KEYBOARD GETS RESET (IN SEMI-SLOW CLOCK TICKS) +MAXBEL==4 ;MAXIMUM # OF BELLS ALLOWED +GLITIM==60.*60.*2 ;# CLOCK TICKS BETWEEN GLITCHES ON CONSOLE FREE DPY +NCQSLT==100 ;# CLOCK QUEUE SLOTS +KBDBFL==200 ;SIZE OF KEYBOARD BUFFER +LBLEN==100 ;PDP-10 INPUT BUFFER SIZE (BETTER BE DIVISIBLE BY 4) +LBCHRS==LBLEN/2 ;# CHARACTERS IN INPUT BUFFER +DPSIZE==600 ;PDP-10 OUTPUT BUFFER SIZE +BOWBIT==10000 ;CSA BLACK ON WHITE BIT +SAMSK==BOWBIT-1 ;MASK FOR SCROLL REGISTER +CSAMSK==170000 ;COMPLEMENT OF SAMSK +BLKTIM==15. ;CLOCK TICKS BETWEEN BLINKS +SNB==100000 ;SIGN BIT +PATL==400 ;SIZE OF PATCH AREA +CMDARG==10 ;# ARGUMENTS WHICH WILL FIT INTO PDP-10/PDP-11 COMMAND BUFFER +RUGSA==57100 ;STARTING ADDRESS OF RUG +TYMSLC==2 ;MAX # 60THS OF A SECOND, MINUS 1, TO CONCENTRATE ON ONE TV + +.SBTTL GO CODE, PDL, AND KBD BUFFER + +.ABS + +;PUSH DOWN LIST AND KEYBOARD BUFFER + +.=PDLORG+PDL +.IIF NE .&177,.=<.&177600>+200 ;ALIGN ON 200 BYTE BOUNDARY +PDBUF==. + +KBDBUF: +.=.+KBDBFL +KBDEND==. + +REPORT GO=,\GO + +GO: RESET ;IN THE PRIVACY OF YOUR OWN HOME + CLR PS + MOV #PDBUF,SP ;SET UP PUSH DOWN POINTER + MOV #ERRLVL,C ;ALL PROCESSOR TRAPS GO ON 7 + MOV #NXMPC,B + MOV #NXMBRK,(B)+ ;BUS TIME OUT + MOV C,(B)+ + MOV #RESBRK,(B)+ ;RESERVED INSTRUCTION + MOV C,(B)+ + MOV (B),T ;BREAK POINT + BNE .+6 + MOV #BPTBRK,T + MOV T,(B)+ + MOV C,(B)+ + MOV #IOTBRK,(B)+ ;IOT TRAP + MOV C,(B)+ + MOV #PWRBRK,(B)+ ;POWER FAILURE + MOV C,(B)+ + MOV #EMTBRK,(B)+ ;EMT + MOV C,(B)+ + MOV #TRPBRK,(B)+ ;"TRAP" TRAP (LEV 7) + MOV C,(B)+ + MOV #CHA,(B)+ ;CHANNEL HEADER AREA + MOV #POINTA,(B)+ ;POINTER AREA POINTER + MOV #IOVER,(B)+ ;I/O VERSION + MOV VERSE,(B)+ ;ASSEMBLY VERSION + CLR (B)+ ;INITED + CLR (B)+ + MOV C,(B)+ ;NON-ZERO SUFFICES + MOV C,(B)+ ;GDOWN + MOV #CLKBRK,LKPC ;CLOCK + MOV #LKLVL,LKPSW + MOV #KBDBRK,KBDPC ;KBD + MOV #LKLVL,KBDPSW + MOV #BPT,0 ;CATCH JUMPS TO ZERO. + +;FALLS THROUGH + +;INITIALIZE VARIBLES FALLS THROUGH + + JSR PC,INIT + +;ENABLE INTERRUPTS + + MOV #100,LKS ;CLOCK + MOV #KBDBUF,KMA + MOV #KBDBUF,OLDKMA + MOV #140,KMS ;KEYBOARD MULTIPLEXOR + MOV #-1,INITED + +;THE MAIN LOOP + +MAIN: MOV #MAXTV-1,U ;CHANNEL + CMP WHOTIM,ITSTI1 ;TIME FOR WHO LINES? + BEQ MAIN1 + ZAPFLG WHOFLG ;TRIGGER WHO LINES +MAIN1: TST INITED + BEQ GO ;RESET THE WORLD + TST CSR + BLT GO2RUG ;SWITCH 15 => GO TO RUG +MAIN3: JSR PC,DPYDPY + MOV CMDFLG,A ;PDP-10 GIVING COMMAND? + BLE MAIN2 + PUSH U + JSR PC,TENCMD ;PROCESS THE COMMAND + POP U +MAIN2: DEC U + BGE MAIN1 ;CYCLED THROUGH ALL CHANNELS? + CLR WHOFLG ;TURN OFF WHO LINES + BR MAIN + +GO2RUG: BPT + BR MAIN3 + +;HERE TO RESTART, NOTIFY THE PDP-10 + +GODOWN: RESET + CLR PS + MOV #INITED-2,B + CLR (B)+ + CLR (B)+ ;INITED + CLR (B)+ + CLR (B)+ ;GDOWN + TST GDOWN ;WAIT FOR THE PDP-10 TO REPLY + BEQ .-4 + JMP GO + +.SBTTL INITIALIZATION + +INIT: CLR TICKS + CLR TICKS1 +;******* TEMPORARY CODE FOR FONT CHECKSUM ******* + MOV #FNTORG,T + MOV T,CKSPNT + CLR CKSSUM + CLR TT +1$: ADD (T)+,TT + CMP T,#FNTEND + BLO 1$ + MOV TT,CKSSMG +;******* END OF TEMPORARY CODE ******* + CLR KBDFLG + CLR KBDFLG+2 + CLR KBDACT + CLR KBDLAST + CLR KBDTSW + CLR CMDFLG + CLR CMDFLG+2 + CLR WHOTIM + CLR ITSTI1 + CLR WHOFLG + CLR TENWHO + CLR QPYSWT + CLR BUZSWT + CLR ELESWT + CLR SSCC + JSR PC,REASW ;FEED EVERY SPEAKER SILENCE. + + MOV #LEBUFS,U ;INITIALIZE FREE LIST OF 11-TO-10 INPUT BUFFERS. + MOV U,FSP + MOV #NLBUFS-1,B +INIT6: MOV U,TT + ADD #,TT + MOV TT,LHFS(U) + MOV TT,U + DEC B + BGT INIT6 + CLR LHFS(U) ;END OF LIST + + CLR BLINK + MOV #BLINKS,A + MOV #BELCNT,C + MOV #-1,T ;SET UP BELL COUNTS + MOV #MAXTV-1,B + CLR ITSTDP +INIT5: CLRB CHNUSE(B) ;EVERY CHANNEL IS FREE. + CLRB BLKSWT(B) ;NO TV HAS BLINKING TEMPORARILY INHIBITED. + TSTB CHCREG(B) ;HOW MANY CHANNELS ARE WORKING? + BLT INIT5A + INC ITSTDP +INIT5A: CLR (A)+ + MOV T,(C)+ + DEC B + BGE INIT5 + MOV ITSTDP,ITSFDP ;# FREE DPY'S + + MOV #MAXBLK,B ;PUT ALL BLINKER BLOCKS ON THE FREE BLINKERS LIST. + MOV #BLKVAR,U + MOV U,FBLINK +INIT7: MOV U,TT + ADD #BLLEN,TT + MOV TT,BLNEXT(U) + CLRB BLON(U) + MOV TT,U + DEC B + BGT INIT7 + CLR (U) + + MOV #MAXTV-1,A + CLR T + MOV #WHVARS,C +INIT2: MOV DPYCHN(T),U + JSR PC,CHCLR ;SET UP THAT CHANNEL + MOV #-1,DPYKBD(T) + MOV #-1,CHNCLS(T) + CLR ECOFLG(T) + MOV C,WHOLIN(T) + MOV #-1,(C) .SEE WHJOB + ADD #WHLEN,C + CMP (T)+,(T)+ + DEC A + BGE INIT2 ;MORE DPY CHANNELS TO SET UP? + + MOV #-1,C + JSR PC,CHCONS ;GET A CHANNEL FOR THE FREE SCREENS. + TST T + BEQ .+4 ;THIS SHOULD ALWAYS GIVE US CHANNEL 0. + BPT + MOV WHOLIN,TT ;WANT SYSTEM WHO LINE ON CONSOLE FREE DPY + MOV #NWHCMD,WHMODE(TT) + MOVB CHCREG,TT ;TT GETS WHICH VIDEO BUFFER IT IS. + MOV TT,DPYFRE ;REMEMBER # OF DPY USED FOR FREE SCREENS. + MOVB TT,CREG ;SET UP CONSOLE REGISTER FOR PRINT + CLR CSA + TYPOUT + MOVB LECREG(U),C ;DPY + ASL C + MOV #MAXVSO-1,B ;SWITCH TO ALL OUTPUTS +INIT1: MOV DPYVSW(C),TT ;VIDEO SWITCH INPUT + MOV B,T ;SWITCH OUTPUT + JSR PC,VSWIT + DEC B + BGE INIT1 + + MOV #MAXKBD,A ;CLEAR KBDLE + CLR B +INIT8: CLR KBDLE(B) + CLR KBDESC(B) + MOV #-1,KBDDEF(B) + TST (B)+ + DEC A + BGT INIT8 + + MOV #NCQSLT-1,C ;INITIALIZE CLOCK QUEUE + CLR CLOCKQ + MOV #CQUEUE,A + MOV A,CLOCKF +INIT9: MOV A,B + ADD #CQLEN,B + MOV B,(A) + MOV B,A + DEC C + BGT INIT9 + CLR (A) + MOVB #CSET,CALU + MOV CREG,T ;SEED QUEUE WITH GLITCH CONSOLE FREE + JSR TT,ADQUE + GLITIM + MSGLIT + RTS PC + +.SBTTL MAIN PROGRAM LEVEL ROUTINES + +;HERE TO GET CHARACTER FROM OPEN CHANNEL +;LOOPS UNTIL NO MORE CHARACTERS AVAILABLE + +DPYDPY: TSTB CHNUSE(U) + BLE DPYD5 ;IGNORE FREE DISPLAYS. + PUSH U ;DPY CHANNEL NUMBER + ASL U + ASL U + PUSH U + MOV DPYCHN(U),U ;U GETS CHANNEL VAR BLOCK ADDR + JSR PC,GETCHR ;ANY OUTPUT FOR THIS CHANNEL? + BEQ DPYDON ;NO, GO CHECK FOR WHO LINES, ETC. + MOV #TYMSLC,TYMSHR ;MAX TIME BEFORE CHECKING OTHER CHANNELS + MOVB LECREG(U),T ;SET UP CONSOLE REGISTER + MOVB T,CREG + PUSH T + BLKOFF T ;TURN OFF ALL BLINKERS ON THIS SCREEN + JSR PC,CLBLIN ;AND CLEAR THEM + PUSH U ;SAVE PAGE PRINTER FOR DPYTVO+5 + MOVB #CIOR,CALU ;ALU FUNCTION FOR DRAWING CHARACTERS + MOV LECPC(U),TT ;RESUMING COROUTINE? + BEQ DPYDP1 ;NO. + MOV LESVB(U),B ;YES, RESTORE B AND PC FOR CORETURN FROM THE + CLR LECPC(U) ;GETCHC THAT DIDN'T FIND ANY CHARS. + BIC #-400,A ;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION + PUSH #DPYXIT ;GETCHC'S CALLER'S RETURN ADDR MUST BE DPYXIT. + JMP (TT) ;GETCHC ENFORCES THAT. + +;FAST CHARACTER OUTPUT LOOP +DPYDP1: MOV (SP),U ;GET PP POINTER + MOVB A,A ;FLUSH HIGH BITS FROM CHAR + BLT DPYCTL ;BRANCH IF NON-PRINTING CONTROL FUNCTION +DPYTVO: MOV LEPHS(U),C ;SET UP TO DRAW CHARACTER + MOV LECC(U),TT ;THIS IS OPEN-CODED FOR SPEED + ASL A ;COPIED FROM CODE AT GENCHR + MOV CTAB(A),T + JSR PC,GENCH1 ;GENERATE CHARACTER, CLOBBER ALL ACS + MOV (SP),U ;RESTORE PP POINTER, CLOBBERED BY GENCH1 + JSR PC,LEDADC ;ADVANCE CURSOR +DPYXIT: TST TYMSHR ;TIME UP? + BMI DPYDX2 ;YES, LEAVE THIS TV FOR A WHILE + MOV (SP),U + JSR PC,GETCHR ;NO, GET NEXT CHARACTER + BNE DPYDP1 ;AND LOOP BACK TO PROCESS IT +DPYDX2: POP U + POP T ;DONE WITH THIS DPY FOR NOW + BLKON T ;ALLOW BLINKERS TO BLINK AGAIN + BR DPYDON + +;HERE IF NO CHARACTER AVAILABLE. TWO WORDS STILL ON THE STACK: +;(SP) IS 4 TIMES CHANNEL NUMBER, 2(SP) IS CHANNEL NUMBER (TO BE POPPED INTO U). + +DPYDON: POP B + TST CHNCLS(B) + BLT DPYFLS ;FLUSH DPY CHANNEL? + TST ECOFLG(B) + BEQ DPYD2 ;CAUSE PSEUDO ACTIVATION? + MOV U,T + ADD #LEZER0,T + + CHROFF + MOV KBDACT,LELIST(TT) ;PUT LINE EDITOR ON ACTIVE RING + MOV T,KBDACT + TST KBDFLG + BNE DPYD0 + MOV T,KBDFLG + CLR KBDACT + CLR KBDLAST +DPYD0: CHRON + +DPYD1: CLR ECOFLG(B) +DPYD2: TST WHOFLG ;DO WHO LINES? + BEQ DPYD3 + MOV WHOLIN(B),T + TST WHMODE(T) + BMI DPYD4 ;DON'T DO WHO LINE, BUT MIGHT WANT TO CLEAR IT + TST WHO1(T) + BMI DPYD4 ;USER WHO MODE VAR CAN ALSO DISABLE WHO LINE + JSR PC,DOWHO ;DO THE WHO LINE FOR THIS GUY +DPYD3: POP U +DPYD5: RTS PC + +;HERE IF NO WHO LINE IS TO BE DONE, WE MIGHT WANT TO CLEAR IT + +DPYD4: MOV WHOLIN(B),T + TST 2(T) ;IF NEGATIVE, THEN CLEAR IT + BGE DPYD3 + CLR 2(T) ;ZAP THE SWITCH + JSR PC,ZAPWHL ;CLEAR THE LINE + BR DPYD3 + +;HERE TO FLUSH DPY CHANNEL + +DPYFLS: MOV (SP),T + TSTB CHNUSE(T) ;ALREADY FREED? + BEQ DPYD3 ;YES, THIS MEANS MAIN LOOP SHOULD SIMPLY IGNORE THIS DPY. + CHROFF + JSR PC,CHRETN + CHRON + BR DPYD3 + +;HERE IF CONTROL CODE FOUND + +DPYCRF: SUB #5,A +DPYCTL: BIC #177600,A ;DISPATCH ON CONTROL CODE + CMP #ILLCTL,A + BLOS DPYTVO ;BRANCH IF ILLEGAL CODE + ASL A + PUSH #DPYXIT ;MAKE THE RETURN ADDR BE "DPYXIT" + JMP @CTLTAB(A) ;SO GETCHC COROUTINING WILL WORK. + +;CONTROL FUNCTION ROUTINES CALLED WITH PP INDEX IN U. +;MAY CLOBBER ALL ACS BUT MUST LEAVE CIOR IN CALU. MANY ARE ALSO +;CALLED FROM ELSEWHERE AND EXPECTED TO PRESERVE U. + +CTLTAB: SETCUR ;200 %TDMOV (FOLLOWED BY TWO IGNORED CHARS, THEN VPOS, HPOS). + SETCR1 ;201 %TDMV1 (FOLLOWED BY NEW VPOS AND NEW HPOS) + CLEOF ;202 %TDEOF (CLEAR TO END OF SCREEN) + CLEOL ;203 %TDEOL (CLEAR TO END OF LINE) + CLRCHR ;204 %TDDLF (DELETE FORWARD) + RTSPC ;205 %TDMTF (MOTOR OFF - IGNORED) + RTSPC ;206 %TDMTN (MOTOR ON - IGNORED) + CRLF ;207 %TDCRL (CRLF AND CLEAR EOL, BUT SCROLL AT END OF SCREEN) + RTSPC ;210 %TDNOP (NO-OP) + DPYBS ;211 %TDBS (BACKSPACE) + LF ;212 %TDLF (LF) + CR ;213 %TDRCR (RAW CR) + RTSPC ;214 %TDORS (OUTPUT RESET - WE CAN'T DO ANYTHING USEFUL) + RTSPC ;215 %TDQOT (DEVICE DEPENDENT DATA FOLLOWS - WELL, THIS DEVICE + ;SAYS IT DOESN'T REALLY DEPEND) + LEDADC ;216 %TDFS + SETCR1 ;217 %TDMV0 (SAME AS %TDMV1 FOR OUR PURPOSES) + DPYCLR ;220 %TDCLR (HOME UP AND CLEAR SCREEN) + BELL ;221 %TDBEL (FLASH THE SCREEN) + RTSPC ;222 %TDINI (REINITIALIZE INTELLIGENT TERMINAL (NOT APPLICABLE)) + LINS ;223 %TDILP (INSERT LINE POSITION (FOLLOW BY # LINES TO INSERT)) + LDEL ;224 %TDDLP (DELETE LINE POSITION (FOLLOW BY # LINES TO DELETE)) + CINS ;225 %TDICP (INSERT CHARACTER POSITION (FOLLOW BY # CHARS)) + CDEL ;226 %TDDCP (DELETE CHARACTER POSITION (FOLLOW BY # CHARS)) + RTSPC ;227 %TDBOW (IGNORED) + RTSPC ;230 %TDRST (IGNORED) + RTSPC ;231 %TDGPH (IGNORED) + RGSCUP ;232 %TDRSU (REGION SCROLL UPWARDS) + RGSCDN ;233 %TDRSD (REGION SCROLL DOWN) +ILLCTL==<.-CTLTAB>/2 + +.SBTTL WHO LINE ROUTINES + +;PRINTS WHO LINE, TAKES 10/11 CHANNEL IN B + +DOWHO: PUSH B ;SAVE 10/11 CHANNEL + MOV ITSTI1,WHOTIM ;TIME WE DID WHO LINE + MOV #WHOPP,TT ;SET DEFAULTS FOR WHO PAGE PRINTER + MOV #LEDFLT,T + MOV #LELEN,U + JSR PC,CALCPY ;ZAP + MOV #WHOPP,U ;SET UP PAGE PRINTER INDEX + CLR A ;CHARACTER X + MOV #CHRLN,B ;CHARACTER Y, PAST LAST LINE + JSR PC,SETXY0 + MOV (SP),B ;RESTORE 10/11 CHANNEL INDEX + MOV WHOLIN(B),A + TST WHO1(A) ;SIGN OF .WHO1 VARIABLE INHIBITS ALL HACKERY + BPL .+4 ;ASSUME USER HAS STUFF THERE AND SHOULDN'T CLOBBER IT. + RTS PC + JSR PC,ZAPWHL ;CLEAR OUT THE WHO LINE +WHINIT: MOV (SP),B ;10/11 CHANNEL INDEX + MOV WHOLIN(B),TT + CMP #NWHCMD-1,WHMODE(TT) + BHI DATIME ;NO VERSION NUMBER FOR USER WHO LINE + TYPOUT /ITS / + DECTYP ITSVER ;TYPE VERSION NUMBER + JSR PC,SPACE + TST ITSDBG + BEQ DATIME + TYPOUT /BEING DEBUGGED / + +;TYPES DAY TIME AND DATE + +DATIME: MOV ITSDAT,A ;PRINT PACKED DATE FIRST + JSR PC,DATTYP ; 7 BITS YEAR, 4 MONTH, 5 DAY + JSR PC,SPACE + MOV #MQ,B + MOV ITSTI1,(B) + MOV ITSTIM,-(B) + JSR PC,TIMTY1 ;TYPE DAY TIME NEXT + JSR PC,SPACE + POP B ;10/11 CHANNEL + MOV WHOLIN(B),TT + CMP #NWHCMD-1,WHMODE(TT) + BHI UWHLDO ;DO USER WHO LINE? + +;SYSTEM WHO LINE +;ITS XXX {BEING DEBUGGED} MM/DD/YY HH:MM:SS ITSFDP/ITSTDP USR RU/JOB SHARE SWBJ JWP TRC/COR CFU + +SWLDO: TYPOUT /TVS: / + DECTYP ITSFDP ;# FREE DPYS + JSR PC,SLASH + DECTYP ITSTDP ;TOTAL DPYS + TYPOUT / USERS: / + DECTYP ITSUSR ;# SYSTEM USERS + JSR PC,SPACE + DECTYP ITSRU ;RUNABLE JOBS/ + JSR PC,SLASH + DECTYP ITSJOB ;# SYSTEM JOBS + JSR PC,SPACE + DECTYP ITSFSH ;FAIR SHARE IN % + TYPOUT /% SB=/ + DECTYP ITSWBJ ;SWAP BLOCKED JOBS + TYPOUT / PG=/ + DECTYP ITSJWP ;JOBS WAITING FOR PAGES + TYPOUT / CORE: / + DECTYP ITSTRC ;RUNABLE CORE + JSR PC,SLASH + DECTYP ITSCOR ;TOTAL CORE + JSR PC,SPACE + DECTYP ITSCFU ;CORE FOR USERS + RTS PC + +;USER WHO LINE +;MM/DD/YY HH:MM:SS JOB UNAME JNAME SNAME STATUS J%RT HH:MM:SS.S JCORE {USER VARS} + +WHNOJB: TYPOUT / JOB SLOT VACANT/ ;HERE IF JOB SLOT VACANT + RTS PC + +UWHLDO: OCTYPE WHJOB(TT) ;JOB # + TST WHSTAT(TT) + BEQ WHNOJB ;VACANT JOB SLOT? + JSR PC,SPACE + MOV #WHUNAM,T + ADD TT,T + JSR PC,SIXPNT ;UNAME + JSR PC,SPACE + JSR PC,SIXPNT ;JNAME + JSR PC,SPACE + JSR PC,SIXPNT ;SNAME + JSR PC,SPACE + JSR PC,SIXPNT ;STATUS + JSR PC,SPACE + DECTYP WHJ%RT(TT) ;JOB % RUN TIME + JSR PC,SLASH + DECTYP ITSFSH ;OUT OF FAIR SHARE + JSR PC,PERCNT + JSR PC,SPACE + MOV WHJTRT(TT),A ;JOB RUNTIME IN .1-SEC TICKS + JSR PC,TIMTEN + JSR PC,SPACE + DECTYP WHRPAG(TT) ;# PAGES REAL CORE + JSR PC,SLASH + DECTYP WHTPAG(TT) ;# PAGES OF VIRTUAL CORE + MOV #'K,A + JSR PC,TVO + JSR PC,SPACE + MOV WHO1(TT),A ;PRINT FIRST USER WHO VAR + MOV #WHO2,T + JSR PC,UWVDO + MOV WHO1A(TT),A ;MAYBE PRINT SPACE + BMI UWHLD1 + JSR PC,SPACE + MOV WHO1A(TT),A +UWHLD1: MOV #WHO3,T ;NOW SECOND USER WHO VAR +;TAKE CONTROL WORD IN A, OFFSET (OFF TT) TO FOUR WORDS IN T, PRINT USER WHO VAR +;CONTROL WORD: +; 15 USED ELSEWHERE - IGNORE HERE +; 14 SUPPRESS SPACE BETWEEN TWO HALVES +; 13-11 MODE FOR FIRST HALF +; 10-08 MODE FOR SECOND HALF +; 07 DOUBLE 06-00 +; 06-00 CHARACTER TO PRINT AFTER FIRST HALF, BEFORE SPACE +UWVDO: PUSH A ;SAVE CONTROL WORD + ADD TT,T ;T POINT TO VAR + MOVB 1(SP),A + ASR A ;GET FIRST MODE + ASR A + ASR A + JSR PC,UWVDO4 ;PRINT FIRST HALF + MOVB (SP),A + BEQ UWVDO1 + BIT #200,A + BEQ UWVDO3 + JSR PC,TVOMSK ;SEPARATOR CHAR(S) +UWVDO3: JSR PC,TVOMSK +UWVDO1: BITB #100,1(SP) + BNE UWVDO2 + JSR PC,SPACE ;INTERVENING SPACE +UWVDO2: MOVB 1(SP),A ;GET SECOND MODE + TST (SP)+ ;POP CONTROL WORD, THEN DO SECOND HALF +UWVDO4: BIC #177770,A + ASL A + JMP @UWVDTB(A) + +UWVDTB: RTSPC ;0 DON'T PRINT + UWVDAT ;1 PACKED DATE AS MM/DD/YY + UWVTEN ;2 TIME IN .025 SECONDS AS HH:MM:SS.T + UWVHAK ;3 TIME IN .5 SECONDS AS HH:MM:SS + UWVHAK ;4 OCTAL (18. BITS) + UWVHAK ;5 DECIMAL (18. BITS) + SIXPN1 ;6 THREE SIXBIT CHARS + RTSPC ;7 RESERVED FOR EXPANSION + +;USER-CONTROLLED WHO-LINE FIELD PRINT-OUT ROUTINES. + +UWVHAK: MOV #MQ,B + TST (T)+ + MOV (T),(B) + MOV -(T),-(B) + CMP (T)+,(T)+ + MOV #-14.,LSH + JMP @UWVDT1-6(A) + +UWVDT1: TIMTY1 + UWVOCT + UWVDEC + +UWVOCT: MOV #10,B + BR UWVDC1 + +UWVDEC: MOV #10.,B +UWVDC1: PUSH RADIX + MOV B,RADIX + JSR PC,DECPN9 + POP RADIX + RTS PC + +UWVTEN: MOV (T)+,A + TST (T)+ + JMP TIMTEN + +UWVDAT: MOV (T)+,A + TST (T)+ + JMP DATTYP + +;SOME WHO LINE UTILITY ROUTINES + +PERCNT: MOV #'%,A +JMPTVO: JMP TVO + +SPACE: MOV #40,A + BR JMPTVO + +SLASH: MOV #'/,A + BR JMPTVO + +;TAKES POINTER TO SIXBIT IN T AND TYPES IT (ADVANCING T) + +SIXPNT: JSR PC,SIXPN1 ;DO TWO SETS OF THREE CHARS +SIXPN1: MOV #MUL,B ;DO ONE SET OF THREE CHARS + MOV #LSH,C + CMP (T)+,(T)+ ;BAG BITING EAE HAS TO LOADED IN JUST THE RIGHT ORDER + MOV -(T),-(B) ;LOW ORDER FIRST + MOV -(T),-(B) + CMP (T)+,(T)+ + MOV #-10.,(C) ;FIRST CHARCTER IN AC, THE REST IN MQ + JSR PC,SIXPN2 ;PRINT FIRST CHAR + JSR PC,SIXPN2 ;PRINT SECOND, FALL IN FOR THIRD +SIXPN2: MOV (B)+,A ;SIXBIT + ADD #40,A ;ASCII + PUSH (B)+ + JSR PC,TVO + POP -(B) + CLR -(B) ;CLEAR AC + MOV #6,(C) ;NEXT CHARACTER INTO AC + RTS PC + +;TAKES TENTHS OF SECONDS IN A AND PRINTS AS HH:MM:SS.T + +TIMTEN: MOV #MQ,T + MOV A,(T) + CLR -(T) + MOV #10.,-(T) ;DO DIVIDE + TST (T)+ + PUSH (T)+ ;TENTH'S OF SECONDS + MOV (T),A + ASL A ;# HALF SECONDS JOB HAS BEEN RUNNING + JSR PC,TIMTYP ;TYPE TIME + MOV #'.,A + JSR PC,TVO + POP A ;TENTH'S OF SECONDS + JMP DECPNT + +;TAKES # HALF SECONDS IN A AND TYPES TIME IN HH:MM:SS FORMAT + +TIMTYP: MOV #MQ,B + MOV A,(B) + CLR -(B) +;TAKE # HALF SECONDS IN EAE AC-MQ AND TYPE AS HH:MM:SS +TIMTY1: MOV #120.,-(B) ;MINUTES SINCE MIDNIGHT + TST (B)+ + PUSH (B) ;REMAINDER IS SS*2 + ASR (SP) + CLR (B) ;CLEAR AC + MOV #60.,-(B) ;HOURS SINCE MIDNIGHT + TST (B)+ + PUSH (B)+ ;REMAINDER IS MM + MOV (B),A ;HH + JSR PC,DECPNT + MOV #':,C ;COLON SEPARATES GOODIES + POP A + JSR PC,MSDPNT ;PRINTS COLON AND PADS WITH LEADING ZERO IF NECESSARY + POP A +MSDPNT: PUSH A + MOV C,A ;PRINT SEPARATING CHARACTER + JSR PC,TVO + CMP #10.,(SP) + BLE MSDPN1 ;PAD WITH LEADING ZERO? + MOV #'0,A + JSR PC,TVO +MSDPN1: POP A + JMP DECPNT ;PRINT NUMBER + +;TAKE DATE PACKED AS 7 BITS YEAR, 4 MONTH, 5 DAY AND PRINT AS MM/DD/YY + +DATTYP: MOV #MQ,B + MOV A,(B) + CLR -(B) ;CLEAR AC + MOV #LSH,C + MOV #7,(C) ;YEAR + PUSH (B) + CLR (B) + MOV #4,(C) ;MONTH + MOV (B),A + CLR (B) + MOV #5,(C) ;DAY + PUSH (B) + JSR PC,DECPNT ;PRINT MONTH + MOV #'/,C ;USE SLASH AS SEPARATOR + POP A + JSR PC,MSDPNT ;PRINT DAY + POP A + JMP MSDPNT ;PRINT YEAR + + +.SBTTL PDP-10 COMMAND PROCESSOR SWITCH VIDEO SWITCH, ETC. + +TENCMD: CMP #MAXCMD,A ;LEGAL COMMAND? + BLOS TENCFL ;NO, COMMAND FAILS + ASL A ;BYTES FOR DISPATCH + JMP @TENDSP(A) + +;PDP-10 COMMAND DISPATCH + +TENDSP: TENCFL ;0 ILLEGAL + TENVSW ;1 VIDEO SWITCH + TENDPC ;2 CONS DPY FOR PDP-10 + TENDPR ;3 RETURN DPY + TENRVS ;4 READ VIDEO SWITCH + TENASW ;5 AUDIO SWITCH + TENRAS ;6 READ AUDIO SWITCH +MAXCMD==<.-TENDSP>/2 + +;HERE TO SWITCH VIDEO SWITCH + +TENVSW: MOV CMDBUF,TT ;SWITCH INPUT + MOV CMDBUF+4,T ;SWITCH OUTPUT + CHROFF ;INHIBIT INTERRUPTS WHILE WE DO THIS + JSR PC,VSWCMD ;CHECKS FOR LEGAL BEFORE SWITCHING + BHIS TENCF1 ;JUMP IF THEY WERE ILLEGAL. +TENCS1: CHRON +TENCSD: MOV #-1,CMDFLG ;COMMAND SUCCEEDS + RTS PC + +;SWITCH AUDIO SWITCH UPON COMMAND FROM PDP-10 + +TENASW: MOV CMDBUF,TT ;SWITCH INPUT + MOV CMDBUF+4,T ;SWITCH OUTPUT + CHROFF + JSR PC,ASWCMD ;SWITCH SWITCH, TESTING LEGALITY. + BHIS TENCF1 ;JUMP IF THEY WERE ILLEGAL, TO SAY COMMAND FAILED. + BR TENCS1 + +;HERE TO CONS UP DPY FOR PDP-10 + +TENDPC: CHROFF ;INHIBIT INTERRUPTS AGAIN + MOV CMDBUF,C ;ARG IS KEYBOARD TO USE, OR -1 FOR NO KEYBOARD. + CMP C,#MAXKBD ;BUT BARF IF ILLEGAL KEYBOARD NUMBER. + BGE TENCF1 + JSR PC,CHCONS ;GET A CHANNEL, CONNECT IT TO THAT KEYBOARD. + TST T + BLT TENCF1 ;CAN'T => COMMAND FAILS. + MOVB LECREG(U),CMDBUF ;ELSE RETURN THE VIDEO BUFFER NUMBER + CLRB CMDBUF+1 + MOV T,CMDBUF+4 ;AND THE 10-11 CHANNEL NUMBER (TTY NUMBER MINUS 52). + BR TENCS1 + +TENCF1: CHRON +TENCFL: CLR CMDFLG ;REPORT FAILURE OF A COMMAND TO THE TEN. + RTS PC + +;HERE TO RETURN DPY ON COMMAND + +TENDPR: MOV CMDBUF,TT ;THE DPY TO RETURN + MOV #MAXTV-1,T +TENDR0: CMPB CHCREG(T),TT ;WHICH CHANNEL DOES IT BELONG TO? GET # IN T. + BEQ TENDR1 + DEC T + BGE TENDR0 + BR TENCSD + +TENDR1: TST CHNUSE(T) ;DO NOTHING IF THE CHANNEL IS FREE. + BEQ TENCSD + CHROFF ;OTHERWISE, FREE THAT CHANNEL. + JSR PC,CHRETN + BR TENCS1 + +;HERE RETURN STATE OF VIDEO SWITCH + +TENRVS: JSR PC,SWTARG ;SET UP 10-11 CHANNEL ARGUMENT + BLOS TENCFL ;ILLEGAL ARG MAKES COMMAND FAIL + JMP @RVSDSP(T) +RVSDSP: TENCFL ;0 IS ILLEGAL + RVSCHN ;1 10/11 CHANNEL # + RVSKBD ;2 KBD # + RVSOUT ;3 VIDEO SWITCH OUTPUT # +NSWTRG==<.-RVSDSP>/2 + +RVSKBD: JSR PC,CHKKBD ;HERE GIVEN KBD #; TEST IT. + BHI RVSCH1 ;IF LEGAL, FALL INTO MAIN LINE CODE + BR TENCFL ;ILLEGAL, TELL HIM SO + +RVSOUT: MOV CMDBUF+4,TT ;HERE GIVEN VIDEO SWITCH OUTPUT #. + MOV #-1,T ;ILLEGAL KBD # + CMP #MAXVSO,TT ;CHECK FOR LEGAL + BHI RVSCH2 ;FALL INTO MAIN LINE CODE + BR TENCFL ;HERE IF ILLEGAL + +RVSCHN: JSR PC,CHNKBD ;HERE GIVEN 10-11 CHANNEL #; GET KBD # IN T + BLOS TENCFL +RVSCH1: MOVB KBDVSW(T),TT ;GET VIDEO SWITCH OUTPUT INTO TT +RVSCH2: MOV TT,CMDBUF+<4*4> ;PUT VIDEO SWITCH OUTPUT INTO COMMAND BUFFER + MOV TT,CMDBUF+<3*4> + TST CMDBUF + BMI RVSDF ;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT. + MOVB VSWTAB(TT),TT ;GET CURRENT INPUT OF THIS OUTPUT AND STORE. + BR RVSCH3 + +RVSDF: ASL T ;MAKE IT BYTE INDEX + BMI RVSNL ;NEGATIVE IF NOT LOGGED IN + MOV KBDLE(T),U + BEQ RVSNL ;KBD NOT LOGGED IN, ITS THE DEFAULT +RVSDF1: MOVB LECREG(U),TT ;THE REGISTER HE HACKS + CMP #MAXTV,TT + BLOS TENCFL ;BRANCH IF ILLEGAL CONSOLE # + ASL TT ;MAKE IT A BYTE INDEX + MOV DPYVSW(TT),TT ;VIDEO SWITCH INPUT +RVSCH3: MOV TT,CMDBUF+<2*4> ;STORE SWITCH INPUT INTO COMMAND BUFFER + BR TENCSD + +RVSNL: MOV DPYCHN,U ;CHANNEL 0 IS CONSOLE FREE CHANNEL + BR RVSDF1 ;AND BACK INTO MAIN STREAM + +;GIVEN 10/11 CHANNEL # AND RETURNS KBD IN T + +CHNKBD: MOV CMDBUF+4,T ;PICK UP CHANNEL # + CMP #MAXTV,T + BLOS CHNKB2 + ASL T ;MAKE CHANNEL # INTO INDEX INTO CHANNEL TABLES + ASL T + TST CHNCLS(T) ;MAKE SURE CHANNEL IS OPEN + BLT CHNKB3 + MOVB DPYKBD(T),T ;PICK UP KBD # +CHNKB1: CMP #MAXKBD,T ;FIX CONDITION CODES FOR SUCCESSFUL RETURN +CHNKB2: RTS PC + +CHNKB3: MOV #MAXKBD+1,T ;HERE IF CHANNEL CLOSED + BR CHNKB1 ;CONS UP ILLEGAL KBD # + +CHKKBD: MOV CMDBUF+4,T ;CHECK FOR REASONABLE KBD # + BR CHNKB1 + +;HERE TO SET UP SWITCH ARG FOR 10-11 COMMAND RETURN IN CONDITION CODES +;IS THE RESULT OF CMP #NCHARG, TO CHECK FOR LEGALITY + +SWTARG: MOV CMDBUF,T ;ARGUMENT TYPE + BPL .+4 ;MAKE SURE WE HAVE A POSITIVE # + NEG T + ASL T ;MAKE IT INTO A BYTE INDEX + CMP #NSWTRG*2,T ;TEST FOR LEGAL + RTS PC + +;HERE RETURN STATE OF AUDEO SWITCH + +TENRAS: JSR PC,SWTARG ;SET UP 10-11 CHANNEL ARGUMENT + BLOS RASLOS ;ILLEGAL ARG MAKES COMMAND FAIL + JMP @RASDSP(T) +RASDSP: TENCFL ;0 IS ILLEGAL + RASCHN ;1 10/11 CHANNEL # + RASKBD ;2 KBD # + RASOUT ;3 AUDEO SWITCH OUTPUT # +.IIF NZ .--RASDSP,.ERROR RASDSP AND RVSDSP DIFFER. + +RASCHN: JSR PC,CHNKBD ;GIVEN A 10-11 CHANNEL #; GET KBD # IN T + BLOS RASLOS +RASCH1: MOVB KBDASW(T),TT ;GET AUDEO SWITCH OUTPUT INTO TT +RASCH2: MOV TT,CMDBUF+<3*4> ;PUT OUTPUT NUMBER IN AS RETURN VALUE. + CLR CMDBUF+<2*4> ;IF HE WANTS DEFAULT INPUT OF THIS OUTPUT, IT'S 0. + TST CMDBUF + BMI RASCH3 ;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT. + MOVB ASWTAB(TT),CMDBUF+<2*4> ;GET CURRENT INPUT OF THIS OUTPUT AND STORE. +RASCH3: JMP TENCSD + +RASKBD: JSR PC,CHKKBD ;HERE IF GIVEN KBD #; TEST FOR LEGALITY. + BHI RASCH1 ;IF LEGAL, FALL INTO MAIN LINE CODE +RASLOS: JMP TENCFL ;ILLEGAL, TELL HIM SO + +RASOUT: MOV CMDBUF+4,TT ;HERE IS GIVEN AUDEO SWITCH OUTPUT + CMP #MAXASO,TT ;CHECK FOR LEGAL + BHI RASCH2 ;FALL INTO MAIN LINE CODE + BR RASLOS ;HERE IF ILLEGAL + +.SBTTL ERROR TRAPS HERE + +NXMBRK: BPT +RESBRK: BPT +IOTBRK: BPT +PWRBRK: BPT +EMTBRK: BPT +TRPBRK: BPT + +;BPT BREAKS COME HERE IF THERE IS NO RUG. +;DON'T WANT TO HALT THE 11 SINCE 11TEN INTERFACE WOULDN'T BE ABLE TO GET TO BUS. +;WANT TO PUT CONTENTS OF REGISTERS IN CORE WHERE CARPET CAN GET AT THEM. + +BPTBRK: .REPT 7 ;SAVE THE ACS + MOV %0+.RPCNT,BPTACS+<2*.RPCNT> + .ENDR + MOV #INITED-2,A ;TELL THE 10 WE'RE DOWN + CLR (A)+ + CLR (A)+ + CLR (A)+ + CLR (A)+ + +; BELOW LOSES - PREVENTS RESTUFFING UNLESS YOU GO HIT SWITCHES +; WAIT ;PUT 000001 IN LIGHTS (11/05) + BR . ;WAIT FOR RELOAD OR MANUAL INTERVENTION + ;BRANCH TO POINT SO STUFF WILL AUTOMATICALLY START IT. + .REPT 7 ;PROCEED + MOV BPTACS+<2*.RPCNT>,%0+.RPCNT + .ENDR + RTI + +BPTACS: .BLKW 7 + +.SBTTL CLOCK ROUTINES CAUSE BLINKING + +CLKBRK: DEC TYMSHR ;COUNT DOWN THIS DPY'S QUANTUM +;******* TEMPORARY CODE TO CHECKSUM THE FONT ******* +;CHECKSUM IT 100 OCTAL WORDS AT A TIME, SO AS NOT TO SLOW THINGS DOWN +;TOO MUCH. WILL GET CHECKED APPROXIMATELY FOUR TIMES A SECOND. + PUSH T + PUSH TT + MOV CKSPNT,T + MOV T,TT + ADD #100*2,TT + CMP TT,#FNTEND + BLOS 1$ + MOV #FNTEND,TT +1$: ADD (T)+,CKSSUM + CMP T,TT + BLO 1$ + MOV T,CKSPNT + CMP TT,#FNTEND + BNE 2$ + CMP CKSSUM,CKSSMG + BEQ .+4 + BPT + CLR CKSSUM + MOV #FNTORG,CKSPNT +2$: POP TT + POP T +;******* END OF TEMPORARY CODE ******* + PUSH T + ADD #1,TICKS1 ;INC DOES NOT AFFECT C-BIT (SIGH) + ADC TICKS + TST KBDFLG + BNE CLKBR1 ;HAS PDP-10 HACKED THE LAST BUNCH? + MOV KBDACT,KBDFLG ;YES, GIVE HIM THE NEW BUNCH + CLR KBDFLG+2 ;PARANOIA REIGNS SUPREME + CLR KBDACT + CLR KBDLAST ;POINTS TO END OF ACTIVE CHAIN + +;CLOCK QUEUE DISPATCH + +CLKBR1: MOV CLOCKQ,T + BEQ CLKBR2 ;ANYTHING ON CLOCK QUEUE? + TST (T)+ ;IGNORE CDR + CMP (T)+,TICKS ;DOUBLE-PRECISION COMPARE TIME NOW + BHI CLKBR2 ;WITH TIME IN QUEUE BLOCK; TO CLKBR2 IF NOT DUE YET. + BLO CLKBR3 + CMP (T)+,TICKS1 + BHI CLKBR2 +CLKBR3: PUSH CLOCKQ ;CDR THE CLOCK QUEUE + MOV @(SP),CLOCKQ + JSR PC,@(T)+ ;CALL CLOCK LEVEL ROUTINE, T POINTS TO ARGUMENT + POP T + MOV CLOCKF,(T) ;PUT OLD SLOT ON FREE LIST + MOV T,CLOCKF + BR CLKBR1 ;CHECK AGAIN IF SOMETHING STILL ON QUEUE + +CLKBR2: DEC BLINK + BGE .+10 + MOV #BLKTIM,BLINK + CMP BLINK,#MAXTV + BHIS CLKR1 + MOV BLINK,T + TSTB BLKSWT(T) + BNE CLKR1 + PUSH U + PUSH CREG + PUSH AC + PUSH MQ + MOVB T,CREG + ASL T + MOV BLINKS(T),T ;BLINK CHAIN FOR THIS DPY + BEQ CLKBR4 +CLKLOP: MOV BLCURS(T),U ;CURSOR TO BLINK + JSR PC,XORCHR + COMB BLON(T) ;CHANGE STATE OF BLINK + MOV BLNEXT(T),T + BNE CLKLOP +CLKBR4: POP MQ ;CLOCK RETURN + POP AC + POP CREG + POP U +CLKR1: TST BLINK + BEQ CLKR3 + CMP BLINK,#BLKTIM/2 + BNE CLKR2 +CLKR3: JSR PC,RPT ;AS OFTEN AS WE BLINK, HANDLE THE REPEAT KEY. +CLKR2: INCB SSCC ;INCREMENT SEMI-SLOW CLOCK COUNT + BNE CLKRET ;WRAP-AROUND => SEMI-SLOW CLOCK TICK + BR CLKBRS + +;ON ALL CONSOLES IN "REPEAT" MODE, PERFORM ONE REPETITION +;BY SENDING AS INPUT TO THE PDP-10 ANOTHER COPY OF THE CHAR +;MOST RECENTLY SENT. ALSO DECREMENTS ALL FINITE REPEAT COUNTS. +RPT: JSR U,ACSAV + PUSH CREG + MOV #LEUVAR,U +RPT4: TST LERPT(U) + BEQ RPT3 + BMI RPT1 + DEC LERPT(U) +RPT1: MOV LELSTA(U),A + MOV LELSTB(U),B + JSR PC,PUTCHR +RPT3: ADD #LELEN,U + CMP #LEUEND,U + BGT RPT4 + POP CREG + JMP ACRES + +;COME HERE EVERY 256./60. = 4.27 SECONDS FOR SEMI-SLOW CLOCK +CLKBRS: PUSH TT + PUSH C + PUSH U + PUSH #69. ;FOR DEBUGGING + TST KBDTSW + BEQ SSCRET + CLR KBDTSW + MOV #KBDDEF+<2*MAXKBD>,T + BR CLKBR5 + +CLKBR9: INC KBDTSW +CLKBR5: CMP #KBDDEF-2,T + BEQ SSCRET + TST -(T) ;FAST LOOP LOOKING FOR ANY KEYBOARD + BGE CLKB10 ; NEEDING ITS CONSOLE'S VIDSW INPUT RESET + BR CLKBR5 +CLKB10: DECB 1(T) + BGE CLKBR9 ;NOT TIME TO RESET THIS SCREEN YET + MOV T,C + SUB #KBDDEF,C ;C HAS 2*KBD NUMBER, FOR VSWDEF. + PUSH T + JSR PC,VSWSGO ;SET UP L.E. INDEX IN U, VSW OUTPUT IN T + BLT CLKBR7 ;VSWSGO IS NEGATIVE IF SOMETHING IS FUNNY. + JSR PC,VSWDEF ;RESET VIDEO SWITCH INPUT +CLKBR7: POP T + BR CLKBR5 + +SSCRET: CMP (SP)+,#69. ;IS STACK SCREWED? + BEQ SSCRE1 + BPT +SSCRE1: POP U + POP C ;SEMI-SLOW CLOCK RETURN + POP TT +CLKRET: POP T +CRTI: RTI + +;CLEARS ALL BLINKERS ON THIS DPY + +CLBLIN: PUSH U + MOVB CREG,T + BIC #177400,T + ASL T + MOV BLINKS(T),T + BEQ CLBL2 +CLBL0: TSTB BLON(T) ;BLINK ON? + BEQ CLBL1 + MOV BLCURS(T),U + JSR PC,XORCHR + CLRB BLON(T) +CLBL1: MOV BLNEXT(T),T + BNE CLBL0 +CLBL2: POP U + RTS PC + +;CLOCK QUEUE ROUTINES + +;ADQUE CALLED WITH ARG IN T, THE CALLING SEQUENCE IS: + +; JSR TT,ADQUE +; DELTA T +; ROUTINE TO CALL AT CLOCK LEVEL + +ADQUE: PUSH T ;ARG FOR ROUTINE + MOV CLOCKF,T ;GET FREE CLOCK QUEUE SLOT + BEQ ADQFL ;IF THERE IS A FREE ONE + TST (T)+ ;IGNORE CDR + MOV TICKS,(T)+ ;MOVE IN CURRENT TIME + MOV TICKS1,(T) + ADD (TT)+,(T)+ ;TIME TO CALL ROUTINE + ADC -4(T) + MOV (TT)+,(T)+ ;ROUTINE TO CALL + MOV (SP)+,(T) ;AND ITS ARG + PUSH TT ;RETURN ADDRESS + MOV CLOCKF,TT ;ADDRESS OF THIS CLOCK QUEUE SLOT + MOV (TT),CLOCKF ;CDR THE FREE LIST + PUSH TT ;ADDRESS OF ONE TO ADD + PUSH #CLOCKQ ;ADDRESS OF PREVIOUS CLOCK QUEUE ENTRY +ADQUE1: MOV @(SP),TT ;CURRENT ENTRY IN QUEUE + BEQ ADQUE2 ;END OF QUEUE? + MOV 2(SP),T ;THE ONE WE WANT TO ADD + CMP (T)+,(TT)+ ;IGNORE CDR'S + CMP (T)+,(TT)+ ;HIGH ORDER OF TIME + BLO ADQUE2 ;GO SPLICE IT IN HERE + BHI ADQUE3 + CMP (T)+,(TT)+ ;LOW ORDER + BLOS ADQUE2 +ADQUE3: MOV @(SP),(SP) ;CDR THE QUEUE + BR ADQUE1 + +;HERE TO SPLICE ENTRY INTO CLOCK QUEUE + +ADQUE2: MOV @(SP),@2(SP) ;CDR OF QUEUE, GOES TO CDR OF NEW ENTRY + MOV 2(SP),@(SP) ;CURRENT SLOT GOES TO CDR OF PREVIOUS + CMP (SP)+,(SP)+ ;CLEANSE STACK + POP TT + RTS TT + +;HERE FOR NO FREE CLOCK QUEUE SLOTS + +ADQFL: CMP (TT)+,(TT)+ ;SKIP OVER ARGS + POP T ;CLEANSE STACK + RTS TT + +;THIS CAUSES CONSOLE FREE DPY TO GLITCH + +MSGLIT: PUSH CREG + MOV (T),T + MOV T,CREG + JSR TT,ADQUE + GLITIM + MSGLIT + MOV CSA,T + PUSH T + BIC #-BOWBIT,T ;CLEAR BOW AND OTHER GARBAGE + ADD #LINHT*BYTPL/10,T ;GLITCH ONE CHARACTER LINE + CMP #LINHT*BYTPL*CHRLN/10,T + BHI .+4 ;WRAP AROUND? + CLR T + BIC #-1#<-BOWBIT>,(SP) + BIS T,(SP) + POP CSA ;ZAP + POP CREG + RTS PC + +;HERE TO RING BELL ON DPY + +BELL: PUSH T + MOV CREG,T + MOVB T,TT ;DOUBLE TV BUFFER # FOR BYTE INDEX + ASL TT + + CHROFF ;INHIBIT INTERRUPTS WHILE WE HACK CLOCK QUEUE, ETC. + INC BELCNT(TT) ;FLASH SCREEN AT LEAST ONCE + BEQ BELL0 ;IF NONE PENDING, FLASH IT NOW + INC BELCNT(TT) ;IF BELLS PENDING THEN FLASH TWICE + CMP BELCNT(TT),#MAXBEL + BLOS BELL0A + DEC BELCNT(TT) + DEC BELCNT(TT) + BR BELL0A + +;HERE IF NO BELLS PENDING, FLASH SCREEN RIGHT AWAY, ADD CLOCK QUEUE ENTRY + +BELL0: JSR PC,BOWXOR ;FLASH THE SCREEN NOW! + JSR PC,BELL1A ;ADD CLOCK QUEUE ENTRY +BELL0A: CHRON + + POP T + RTS PC + +;CLOCK LEVEL BELL ROUTINE + +BELL1: PUSH CREG + MOV (T),T ;THE DESIRED CONSOLE REGISTER + MOV T,CREG ;N.B. THE ALU MODE WAS SAVED AS "XOR" + MOV #BOWBIT,CSA ;FLASH THE SCREEN + BIC #177400,T ;THE DPY # + ASL T ;BYTE INDEX + DEC BELCNT(T) ;WE JUST DID THAT ONE + BMI BELL1B ;ANY MORE PENDING? + JSR PC,BELL1A ;YES, PUT ANOTHER ON QUEUE +BELL1B: POP CREG + RTS PC + +BELL1A: MOV CREG,T ;PUT ANOTHER BELL ON CLOCK QUEUE + JSR TT,ADQUE + BLKTIM + BELL1 + RTS PC + +.SBTTL KEYBOARD INTERRUPT ROUTINES + +;KEYBOARD BREAK ROUTINES THE LINE EDITOR RUNS AT THIS LEVEL + +KBDBRK: JSR U,ACSAV ;PUT AC'S ON STACK + PUSH CREG + PUSH AC + PUSH MQ +KBDLOP: MOV OLDKMA,A + CMP #KBDEND,A ;CHECK WRAP AROUND + BHI .+6 + MOV #KBDBUF,A + CMP KMA,A + BEQ KBDRET ;NO MORE CHARACTERS + MOV (A)+,B ;RAW CHARACTER + TSTB (A)+ ;GARBAGE + MOVB (A)+,-(SP) ;KEYBOARD # + MOV A,OLDKMA + +;GET ASCII REPRESENTATION OF CHARACTER +; ASCII CODE IN A, META BITS IN B + + MOV B,C ;TWO COPIES OF RAW CHARACTER + BIC #RCHAR,B ;KEY STRUCK + BIT #RTPBIT,C ;TOP? + BEQ KBDX1 + BIS #XTPBIT,B + BR KBDX2 +KBDX1: BIT #RSLBIT,C ;SHIFT LOCK? + BEQ .+6 + BIS #XSLBIT,B + BIT #RSHBIT,C ;SHIFT? + BEQ KBDX2 + BIS #XSHBIT,B +KBDX2: MOVB XTAB(B),A ;ASCII REPRESENTATION + BIC #<#-1>,B ;FLUSH ALL UNINTERESTING BITS + ASL B ;XTAB TO ASCII REPRESENTATION + ASL B + ASL B + BIT #RMTBIT,C ;META? + BEQ .+6 + BIS #AMTBIT,B + BIT #RCLBIT,C ;CONTROL? + BEQ .+6 + BIS #ACLBIT,B + MOVB (SP)+,C ;KEYBOARD # + ASL C ;BYTE FOR INDEX INTO KBDLE + TST A + BLT NONASC ;NON-ASCII +KBDUN3: TSTB KBDESC(C) + BNE ESCBRK ;ESCAPE OR BREAK IS IN PROGRESS + TSTB KBDCNT(C) ;IF THIS SCREEN IS SPYING WITH A TIMEOUT, + BLT KBDUN1 + JSR PC,VSWUNS ;UN-SPY IT IMMEDIATELY. +KBDUN1: MOV KBDLE(C),U ;ASSOCIATED LINE EDITOR? + BEQ KBDLOP + TST LERPT(U) ;IF THE REPEAT KEY IS IN EFFECT, + BEQ KBDUN2 ;TURN IT OFF, AND FLUSH THIS CHARACTER. + CLR LERPT(U) + BR KBDLOP + +KBDUN2: MOVB LECREG(U),CREG ;SET UP CONSOLE REGISTER + BIS #ACTBIT,B ;FEED THIS CHAR TO THE PDP-10 + JSR PC,PUTCHR + BR KBDLOP + +;KEYBOARD RETURN + +KBDRET: POP MQ + POP AC + POP CREG + POP A + POP B + POP C + POP T + POP TT + POP U + RTI + +;NON-ASCII CHARACTERS COME HERE + +NONASC: NEG A + CMP #MAXNAS,A + BHIS .+4 +NONAS1: BPT ;ILLEGAL CHARACTER + CMP #,C ;C HAS BEEN DOUBLED + BHI .+4 + BPT ;GARBAGE KBD # + CLRB KBDESC(C) + ASL A ;BYTES + JSR PC,@NASCTB(A) ;DISPATCH TO ROUTINE +JBDLOP: JMP KBDLOP + +;PROCESS ESCAPE AND BREAK COMMANDS + +ESCBRK: JSR PC,UPPER ;CONVERT LOWER CASE TO UPPER CASE + MOV #ESCHAR,T +ESCBR1: CMPB (T),A ;MATCH? + BEQ DOESC + TSTB (T)+ ;END OF TABLE? + BNE ESCBR1 +ESCBR2: CLRB KBDESC(C) ;NO COMMAND + BR JBDLOP + +DOESC: MOV KBDLE(C),U ;IF COMMAND NEEDS LOGGED-IN KBD, + BEQ DOESC2 ; MAKE SURE WE'RE LOGGED IN, + MOVB LECREG(U),CREG ; AND SET UP U AND CREG +DOESC1: SUB #ESCHAR,T + CLRB KBDESC(C) + ASL T ;MAKE A WORD INDEX. + JSR PC,@ESCTAB(T) ;C MUST BE KBD #, SOME ESCAPE ROUTINES RELY ON IT + BR JBDLOP + +DOESC2: CMP #ESCSRN,T ;IF NOT LOGGED IN BUT MUST BE, + BLE ESCBR2 ; THEN WE LOSE TOTALLY + MOVB DPYFRE,CREG ;OTHERWISE SET UP CREG FOR THE + BR DOESC1 ; SAKE OF RANDOM BELLS + +;NASCTB FOR KEYS SUCH AS BREAK, CLEAR, ETC POINTS HERE +;TO TURN THOSE CHARACTERS INTO TOP-LETTERS STARTING WITH "A". +;A HOLDS TWICE THE NASCTB INDEX. +BRKCLR: ASR A + ADD #4000+'@,A +BRKCLX: TST (SP)+ ;FLUSH RETURN POINTER TO JBDLOP + JMP KBDUN3 ;AND GO GIVE CHARACTER TO TEN. + +GAMMA: MOV #4011,A + BR BRKCLX + +DELTA: MOV #4012,A + BR BRKCLX + +CRCPLS: MOV #4015,A + BR BRKCLX + +PLSMNS: MOV #4014,A + BR BRKCLX + +.SBTTL 10/11 INPUT/OUTPUT ROUTINES + +;HERE TO COMPLEMENT STATE OF BOW BIT WHEN PDP-10 FALLS BEHIND ON KBD + +SLOW10: MOVB LECREG(U),CREG + JMP BELL ;RING BELL + + +;PUT CHARACTER WHICH IS A OR'D WITH B INTO BUFFER. ACTIVATES IF +; 1 FINDS ACTIVATION CHARACTER +; 2 BUFFER FILLS +;A AND B ARE SAVED IN LELSTA AND LELSTB IN CASE THE USER DECIDES +;TO REPEAT THE CHARACTER. + +PUTCHR: TST @LEBUF(U) + BGT PUTCH0 ;BUFFER BEING FILLED? + BLT SLOW10 ;HAS PDP-10 FALLEN BEHIND? + MOV #LBCHRS,@LEBUF(U) ;MARK BUFFER BUSY WITH # FREE CHARACTERS +PUTCH0: TST LEFREE(U) ;ANY ROOM LEFT IN BUFFER? + BGT PUTCH2 + BEQ SLOW10 ;NOPE, DO SOME ERROR CHECKING + BPT ;LOSE IF LESS THAN NO ROOM + +PUTCH2: MOV A,@LECHR(U) + BIS B,@LECHR(U) + MOV A,LELSTA(U) + MOV B,LELSTB(U) + ADD #2,LECHR(U) + DEC LEFREE(U) ;BUFFER FULL? + BGT PUTCH4 + BEQ .+4 ;WE MUST ACTIVATE ANYWAY + BPT + MOV LEBUF(U),T + TST LHQUED(T) ;IF ALREADY QUEUED TO ACTIVATE, + BEQ ACTIVA ; DON'T ACTIVATE NOW + RTS PC + +PUTCH4: TST B + BGE RTSPC1 ;NOT ACTIVATING + MOV LEBUF(U),T ;ACTIVATION CHAR, MUST ACTIVATE + TST LHQUED(T) ;IF ALREADY QUEUED TO ACTIVATE, + BNE RTSPC1 ; DON'T ACTIVATE NOW + TST @LHNEXT(T) ;TEST NEXT BUFFER IN RING + BMI QBFR ;IF NOT FREE, TRY ACTIVATION ON NEXT CLOCK TICK + +;HERE TO ACTIVATE BUFFER + +ACTIVA: SUB #LBCHRS,LEFREE(U) ;NEGATIVE OF ACTIVE CHARS + BLT .+4 + BPT ;HAD BETTER BE NEGATIVE + MOV LEBUF(U),T ;THE BUFFER TO ACTIVATE + MOV LEFREE(U),LHFLAG(T) ;THAT ACTIVATES IT + + CHROFF + CLR LHALST(T) ;PUT THIS ONE AT END CHAIN + PUSH KBDLAST + MOV T,KBDLAST + POP T + BNE ACTIV0 ;EMPTY ACTIVATION LIST? + MOV KBDLAST,KBDACT ;YES, MAKE ACTIVE LIST POINT TO THIS ONE + BR ACTV0A +ACTIV0: MOV KBDLAST,LHALST(T) ;OLD LAST POINTS TO NEW LAST +ACTV0A: MOV KBDLAST,T ;IN ANY EVENT THIS THE ONE JUST ADDED + TST KBDFLG ;DOES THE PDP-10 WANT MORE + BNE ACTIV1 + MOV KBDACT,KBDFLG ;ACTIVATE THIS LIST + CLR KBDACT ;AND PREPARE FOR NEXT + CLR KBDLAST +ACTIV1: CHRON + + MOV LHNEXT(T),T ;NEXT ON RING + MOV #LHLEN,TT + ADD T,TT ;FIRST FREE CHARACTER + MOV T,LEBUF(U) ;NEW BUFFER + TST (T)+ ;LHFLAG IS SET AT PUTCHR + CLR (T)+ ;LHZERO +; CMP (T)+,(T)+ ;DON'T HACK LHNEXT AND LHALST + MOV TT,LECHR(U) ;FIRST FREE CHARACTER + MOV #LBCHRS,LEFREE(U) ;FREE CHARACTERS IN BUFFER +RTSPC1: RTS PC + +;HERE AT CLOCK LEVEL TO ACTIVATE BUFFER + +CLKACT: PUSH TT + PUSH U + MOV (T),U ;THE LINE EDITOR + MOV LEBUF(U),T ;THE BUFFER + TST LHFLAG(T) + BGE .+4 + BPT ;CAN'T ACTIVATE AN ALREADY ACTIVATED BUFFFER + TST @LHNEXT(T) ;THE NEXT BUFFER + BMI CLKAC1 ;ACTIVATE IF READY + CLR LHQUED(T) + JSR PC,ACTIVA +CLKAC2: POP U + POP TT + RTS PC + +CLKAC1: JSR PC,QBFR ;NOT, READY TRY ANOTHER CLOCK TICK + BR CLKAC2 + +;HERE IF NEXT BUFFER ON RING IS NOT FREE, TRY ACTIVATION AT NEXT CLOCK TICK + +QBFR: ZAPFLG LHQUED(T) ;SET FLAG THAT SAYS WE'RE QUEUED + MOV U,T ;ARG + CHROFF ;INHIBIT INTERRUPTS WHILE WE DO THIS + JSR TT,ADQUE ;PUT ON CLOCK QUEUE + 1 ;AT NEXT TICK + CLKACT ;CLOCK LEVEL ACTIVATION + CHRON + RTS PC + +;SAVE ALL ACS ON STACK + +ACSAV: PUSH TT + PUSH T + PUSH C + PUSH B + PUSH A + PUSH U ;RETURN ADDRESS + MOV 14(SP),U ;RESTORE U + RTS PC + +;GETS NEXT CHARACTER FROM DPY BUFFER +;DPY CHANNEL POINTER IN U. RETURNS SIGN-EXTENDED CHARACTER IN A, CLOBBERS TT. +;RETURNS 'EQ' IN CONDITION CODES IF NO CHARACTER PRESENT. + +GETCHR: MOV DPY11B(U),TT ;GET POINTER FOR EASE IN INCREMENTING + MOVB (TT),A ;GET NEXT CHARACTER + CMP A,#-1 ;HAS TEN PUT GOODIES THERE? + BEQ RTSPC1 ;NO + MOVB #-1,(TT) ;MARK AS TAKEN + DEC DPY11B(U) ;ADVANCE POINTER + ROR TT ;USING PDP10 BYTE ORDER (1, 0, 3, 2) + BCS GETCH1 ;BRANCH IF 1->0 OR 3->2 + ADD #4,DPY11B(U) ;0->3 OR 2->1 NEXT WORD + ROR TT + BCC GETCH1 ;BRANCH IF 0->3 + MOV DPY11B(U),TT ;OTHERWISE NEXT PDP10 WORD + DEC TT + MOV #-1,-2(TT) ;SO SET PREV ONE TO ALL -1. + MOV #-1,-4(TT) ; IN CASE OF TIMING ERROR + CMP TT,DPYLGL(U) ;PAST END OF BUFFER? + BLOS GETCH1 + MOV U,DPY11B(U) ;YES, RESET TO + ADD #DPDATA+1,DPY11B(U) ;FIRST WORD OF DATA AREA, HIGH BYTE +GETCH1: CLZ + RTS PC ;RETURN CONDITION CODE 'NE' + +;GET NEXT CHARACTER BUT IF NOT AVAILABLE DO A COROUTINE-RETURN +;FROM THE CHARACTER-READING LOOP, SO THAT WHEN THE NEXT CHARACTER +;IS READ THIS CALL WILL BE RETURNED FROM. ASSUMES THAT U CONTAINS THE +;ADDRESS OF THE CHANNEL VAR BLOCK, AND MAY RESET ALL ACS +;BUT B TO WHAT THEY HOLD AT DPYCTL. B IS ALWAYS PRESERVED. +GETCHC: JSR PC,GETCHR + BEQ GETCH2 + BIC #-400,A ;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION + RTS PC + +GETCH2: MOV B,LESVB(U) + POP LECPC(U) + POP B + CMP B,#DPYXIT + BEQ GETCH3 + BPT ;CALLER OF GETCHC HAD WRONG RETURN ADDRESS +GETCH3: JMP DPYDX2 ;CEASE TYPING ON THIS TV FOR A WHILE + +.SBTTL DISPLAY FUNCTION (%TD, ETC) ROUTINES + +TVOMSK: BIC #177600,A ;HERE IF YOU DON'T TRUST THE HIGH BITS + +;TYPE CHARACTER IN A AND ADVANCE OVER IT. PRESERVES A. + +TVO: JSR PC,GENCHR ;GENERATES CHARACTER AND ADVANCES CURSOR + +;LEDADC ADVANCES LINE EDITOR CURSOR + +LEDADC: ADD #CHRWD,LEX(U) ;INCREMENT HPOS IN BITS FROM RIGHT MARGIN. + BEQ LEDAD2 ;REACHED MARGIN => WRAP AROUND. + TST LEPHS(U) ;ELSE, INCREMENT THE AUXILIARY VARIABLES. + BGT LEDAD1 + ADD #20,LEPHS(U) ;HERE IF WE ARE ADVANCING TO A NEW WORD. + ADD #2,LECC(U) + CMP LECC(U),#TVCFENCE + BLOS LEDAD1 + MOV #TVLO,LECC(U) +LEDAD1: SUB #CHRWD,LEPHS(U) + RTS PC + +LEDAD2: JMP CR + +;RETREATS LINE EDITOR CURSOR + +LEDREC: CMP LEX(U),#-BYTPL ;IF AT LEFT MARGIN, DON'T DO ANYTHING. WE COULD WRAP AROUND, + BEQ LEDRE1 ;BUT THAT'S MORE WORK, AND SHOULDN'T EVER HAPPEN ANYWAY. + ADD #CHRWD,LEPHS(U) + SUB #CHRWD,LEX(U) + CMP #<20-CHRWD>,LEPHS(U) + BGE LEDRE1 + SUB #20,LEPHS(U) ;BACKUP A WORD IN DISPLAY + SUB #2,LECC(U) + CMP LECC(U),#TVLO + BHIS LEDRE1 + BPT ;BACKING UP PAST BEGINNING OF SCREEN? +LEDRE1: RTS PC + +;HERE TO CRLF AND CLEAR EOL. +CRLF: JSR PC,CR + CMP #TVFENCE-,LELCC(U) ;IF NOW ON LAST LINE OF SCREEN, + BEQ CRLF1 ;MUST SCROLL. + JSR PC,LF ;ELSE JUST MOVE DOWN AND CLEAR A LINE. + JMP CLEOL + +CRLF1: JSR PC,SCROLL ;MOVE EVERYTHING UP 4 LINES, + JMP LF ;THEN MOVE DOWN 1 LINE. + +;SCROLL THE TEXT, MOVING THE CURSOR WITH IT, UP 4 LINES. +SCROLL: PUSH LEY(U) ;TO SCROLL, HOME UP AND DELETE 4 LINES AT SCREEN TOP. + PUSH LELCC(U) + PUSH LECC(U) + JSR PC,HU + MOV #4,A + JSR PC,LDEL0 + POP LECC(U) ;THEN RESTORE POSITION (TO LAST LINE, USUALLY) + POP LELCC(U) + POP LEY(U) + MOV LELCC(U),A + SUB #4*BYTPL*LINHT,A ;AND MOVE UP 4 LINES (OR TO SCREEN TOP). + CMP A,#TVLO + BHI SCROL1 + JMP HU + +SCROL1: MOV A,LELCC(U) + SUB #4*BYTPL*LINHT,LECC(U) + SUB #4*LINHT,LEY(U) +SCROLX: RTS PC + +;HERE TO BACKSPACE (NO-OP IF AT BEGINNING OF LINE) + +DPYBS: CMP LELCC(U),LECC(U) + BEQ SCROLX + JMP LEDREC + +;HERE TO HOME UP AND CLEAR SCREEN. + +DPYCLR: JSR PC,HU + JMP CLEOF + +;HERE FOR LINE FEED, NO FRILLS. WRAP AROUND AT SCREEN BOTTOM. +LF: ADD #,LELCC(U) + ADD #,LECC(U) + ADD #LINHT,LEY(U) + CMP #TVFENCE,LELCC(U) + BHI LF1 + SUB #TVFENCE-TVLO,LELCC(U) + SUB #TVFENCE-TVLO,LECC(U) + MOV #-NLINS,LEY(U) +LF1: RTS PC + +;HERE TO HOME UP +HU: MOV #TVLO,LELCC(U) ;RESET POINTER TO CURRENT LINE BEGINNING. + MOV #-NLINS,LEY(U) ;AND ITS POSITION ON SCREEN. + +;HERE FOR CARRIAGE RETURN +CR: MOV LELCC(U),LECC(U) ;ORIGIN OF THIS LINE +CR1: MOV #20-CHRWD,LEPHS(U) ;PHASE + MOV #-BITPL,LEX(U) ;RESET X + RTS PC + +;DELETE LINE(S). MOVE UP THE LINES BELOW THE CURRENT ONE, +;FLUSHING THE CURRENT ONE. BLANK LINES ARE SHIFTED IN AT THE BOTTOM. +LDEL: JSR PC,GETCHC ;READ NUMBER OF LINES TO DELETE IN A. +LDEL0: MOV #TVFENCE,B ;ADDRESS OF "END OF REGION" +LDEL00: MOV A,MQ + BEQ LINSX + CMP A,#50 + BHI LINS3 + MOV #BYTPL*LINHT,MUL ;GET # LINES * BYTPL*LINHT, = # BYTES TO SHIFT BY. + MOV LELCC(U),TT ;TT GETS ADDR OF THIS LINE. + MOV TT,T + ADD MQ,T ;T GETS ADDR OF LINE TO COPY INTO THIS. + BCS LDEL4 ;CARRY => T IS PAST BOTTOM OF SCREEN ALREADY. +LDEL3: CMP T,B ;NO MORE LINES AT BOTTOM TO COPY UP => + BHIS LDEL4 ; START CLEARING INSTEAD. + JSR PC,CPYCHL ;COPY THEM, INCREMENTING T AND TT TO NEXT LINES. + BR LDEL3 + +LDEL4: MOV TT,T +;CLEAR TEXT LINES FROM THE ONE T POINTS TO, TO END OF REGION IN B. PUTS CIOR IN CALU. +LDEL5: CMP T,B + BHIS LINSX ;POPJ, SETTING CALU TO CIOR. + JSR PC,CLRCHL + BR LDEL5 + +;INSERT LINE(S). MOVE THE CURRENT LINE AND LOWER ONES DOWN ONE OR MORE POSITIONS. +;BLANK LINES SHIFT IN AT THE CURRENT POSITION. +LINS: JSR PC,GETCHC ;HOW MANY LINES TO INSERT (IN A). + MOV A,MQ + BEQ LINSX ;DON'T WASTE TIME IF INSERTING 0 LINES. + CMP A,#50 ;DELETING INFINITE LINES = CLEAREOF + BHI LINS3 + MOV #BYTPL*LINHT,MUL + MOV #TVFENCE-,TT ;TT POINTS AT LAST ACTUAL LINE ON SCREEN. +LINS4: MOV TT,T + SUB MQ,T ;T IS LINE TO COPY INTO IT (COPYING DOWNWARD). + BCS LINS3 ;IF T IS ABOVE TOP OF SCREEN, GIVE UP. +LINS1: CMP LELCC(U),T ;STOP AFTER COPYING CURRENT LINE DOWN. + BHI LINS3 + JSR PC,CPYCHL ;COPY ONE LINE DOWNWARD. + SUB #2*BYTPL*LINHT,T ;THIS ADVANCES T AND TT TO NEXT LINE DOWN, + SUB #2*BYTPL*LINHT,TT ; WHEN WHAT WE WANT IS NEXT LINE UP. + BR LINS1 + +LINS3: MOV LELCC(U),T + +;CLEAR C(A) LINES OF CHARACTERS, STARTING AT THE LINE T POINTS TO, BUT STOP IF REACH END OF SCREEN. +;SETS CALU TO CIOR. +LINS2: CMP #TVFENCE,T + BLOS LINSX + JSR PC,CLRCHL + DEC A + BNE LINS2 +LINSX: MOVB #CIOR,CALU + RTS PC + +;REGION SCROLLING + +RGSCDN: JSR PC,GETCHC ;NUMBER OF LINES IN REGION + MOV A,B + JSR PC,GETCHC ;NUMBER OF LINES TO MOVE DOWN + MOV B,MQ + MOV #BYTPL*LINHT,MUL + MOV LELCC(U),TT + SUB #BYTPL*LINHT,TT + ADD MQ,TT ;ADDRESS OF LAST LINE IN REGION + BCS LINSX ;IGNORE IF GARBAGE REGION (WRAPPED AROUND ADDRESS) + CMP TT,#TVFENCE + BHIS LINSX ;IGNORE IF GARBAGE REGION + MOV A,MQ ;CONVERT DISTANCE TO MOVE TO BYTES + BEQ LINSX ;EXIT IF NOT MOVING + MOV #BYTPL*LINHT,MUL + BR LINS4 ;GO DO IT, USING INSERT-LINES SUBROUTINE + +RGSCUP: JSR PC,GETCHC ;NUMBER OF LINES IN REGION + MOV A,B + JSR PC,GETCHC ;NUMBER OF LINES TO MOVE UP + MOV B,MQ + MOV #BYTPL*LINHT,MUL + MOV LELCC(U),B + ADD MQ,B ;ADDRESS OF FIRST LINE AFTER REGION + BR LDEL00 ;GO DO IT, USING DELETE-LINES SUBROUTINE + +;INSERT CHARACTER(S). MOVE THE CURRENT CHARACTER AND FOLLOWING ONES TO THE RIGHT. +;BLANKS ARE SHOFTED IN AT THE CURRENT POSITION. +CINS: JSR PC,GETCHC ;A GETS HOW MANY CHARACTERS TO INSERT. + JSR PC,CINSET ;CHECK A FOR VALIDITY; PUSH A, LELCC(U), LINHT, AND LECC(U). +CINSL: MOV 6(SP),A + MOV (SP),T + MOV 4(SP),C + JSR PC,CINS1L + ADD #BYTPL,(SP) + ADD #BYTPL,4(SP) + DEC 2(SP) + BNE CINSL + ADD #6,SP ;FLUSH ALL BIT # CHAR POSITIONS FROM STACK. + POP B + PUSH LEX(U) + PUSH LEPHS(U) + PUSH LECC(U) +CINSC: JSR PC,CLRCHR ;NOW CLEAR OUT THE CHAR POSITIONS WE INSERTED. + JSR PC,LEDADC ;AND MOVE CURSOR PAST IT. + DEC B ;NOTE CLRCHR SETS CALU TO CIOR. + BNE CINSC + POP LECC(U) ;AND RESTORE THE CURSOR. + POP LEPHS(U) + POP LEX(U) +CINSX: RTS PC + +;INSERT C(A) CHARACTER POSITIONS IN ONE RASTER LINE AT PLACE T POINTS AT. +;C POINTS AT FRONT OF RASTER LINE. REQUIRES CALU/ CSET. +CINS1L: MOV A,MQ + MOV #CHRWD,MUL ;COMPUTE # OF BITS TO SHIFT THE LINE BY. + MOV #20,DIV ;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC. + MOV #20-CHRWD,TT + SUB LEPHS(U),TT ;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE. + PUSH TT + PUSH (T) ;ALSO SAVE THE WORD CONTAINING THEM. + PUSH T ;AND ITS ADDRESS + PUSH U ;FIT IN WITH WHAT CINS2 WILL POP. + MOV C,A + ADD #BYTPL,A ;A GETS ADDR TO AUTODECREMENT TO LAST WORD OF LINE. + MOV A,B + SUB MQ,B ;SUBTRACT THE # OF BYTES IN THE DESIRED # OF WORDS. + SUB MQ,B ;B GETS ADDR OF LAST WORD NOT SHIFTED INTO BIT BUCKET, + MOV -(B),TT ;TT GETS ITS CONTENTS, TO INIT THE LOOP. + MOV AC,C + NEG C ;C <= SHIFT COUNT, TO GET 1 NEW WORD FROM PAIR OF OLD. +CINS1: CMP B,T ;NOTE T STILL HAS ADDR OF LOWEST (LAST) WORD TO SHIFT + BEQ CINS3 + MOV TT,MQ + MOV -(B),TT ;FETCH ANOTHER (LOWER) OLD WORD, FROM WHICH + MOV TT,AC ;(COMBINED WITH PREVIOUS OLD WORD) + MOV C,LSH ;WE MAKE A NEW SHIFTED WORD. + MOV MQ,-(A) ;STORE THE NEXT NEW WORD. + BR CINS1 + +CINS3: MOV AC,-(A) ;REMAINDER OF LAST FROM-WORD GOES INTO LAST TO-WORD. + BR CINS2 + +;FOR INSERT/DELETE CHARACTER, CHECK ARG IN A FOR LEGALITY. MAYBE JUMP OFF +;TO CLEAR-TO-END-OF-LINE FOR INSERTING OR DELETING TOO MANY CHARACTERS. +;OTHERWISE, RETURN HAVING PUSHED ON THE STACK THE ARG, LELCC(U), #LINHT, AND LECC(U). +CINSET: POP B ;GET RET ADDR OFF STACK SO WE CAN POPJ OUR CALLER + MOV A,MQ ;OR PUSH ON HIS STACK. + BEQ CINSX ;IF ARG IS 0, OUR CALLER HAS NOTHING TO DO, SO POPJ HIM + MOV #CHRWD,MUL + MOV LEX(U),C ;AT WHAT DOT POSITION DOES REGION INSERTED/DELETED END? + ADD MQ,C + BLT .+6 ;PAST RIGHT MARGIN => THIS OPERATION EQUIVALENT + JMP CLEOL ;TO A CLEAR-TO-END-OF-LINE. + MOVB #CSET,CALU + PUSH A ;SAVE # CHAR POSITIONS TO INSERT. + PUSH LELCC(U) ;SAVE ADDR START OF 1ST RASTER LINE (ADVANCES) + PUSH #LINHT + PUSH LECC(U) ;AND ADDR OF CURSOR IN 1ST RASTER LINE. + JMP (B) ;RETURN TO OUR CALLER, HAVING PUSHED HIS TEMPS. + +;DELETE CHARACTERS. DELETE SOME CHARACTERS AFTER THE CURSOR. THE FOLLOWING ONES +;MOVE LEFT. BLANKS ARE SHOFTED IN AT THE RIGHT MARGIN. +CDEL: JSR PC,GETCHC ;A GETS HOW MANY CHARACTERS TO DELETE. + JSR PC,CINSET ;DECODE A. MAYBE POPJ OR JUMP TO CLEOL. + ;OTHERWISE, PUSH ON STACK A, LELCC(U), #LINHT, LECC(U). +CDELL: MOV 6(SP),A + MOV (SP),T + MOV 4(SP),C + JSR PC,CDEL1L + ADD #BYTPL,(SP) + ADD #BYTPL,4(SP) + DEC 2(SP) + BNE CDELL + ADD #10,SP + MOVB #CIOR,CALU +CDELX: RTS PC + +;DELETE C(A) CHARACTER POSITIONS FROM ONE RASTER LINE +;T POINTS AT WORD CONTAINING CURSOR, IN THAT RASTER LINE. +;C POINTS AT START OF THAT RASTER LINE. ASSUMES CALU/ CSET. +CDEL1L: MOV A,MQ + MOV #CHRWD,MUL ;COMPUTE # OF BITS TO SHIFT THE LINE BY. + MOV #20,DIV ;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC. + MOV #20-CHRWD,TT + SUB LEPHS(U),TT ;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE. + PUSH TT + PUSH (T) ;ALSO SAVE THE WORD CONTAINING THEM. + PUSH T ;AND ITS ADDRESS + MOV T,TT ;(WHICH IS ALSO ADDR TO START SHIFTING INTO). + ADD MQ,TT ;AND ADDR TO START SHIFTING FROM, AND 1ST FROM-WORD. + ADD MQ,TT ;MQ HAS # OF WORDS, BUT TT HAS AN ADDRESS. + MOV (TT)+,A + ADD #BYTPL,C ;C GETS ADDR OF 1ST WORD PAST END OF LINE. + PUSH U + MOV AC,U ;U HAS # BITS SHIFTING BY. +;NOW MAKE TO-WORDS 1 BY 1 EACH OUT OF A PAIR OF FROM-WORDS. +;THE LAST FROM-WORD IS IN A. T HAS STORE ADDRESS, TT HAS FETCH ADDRESS. +CDEL1: CMP C,TT ;STOP AFTER GOBBLING ALL OF THIS RASTER LINE. + BLOS CDEL2 + MOV (TT)+,B + MOV B,MQ ;CLOBBERS AC, SO RELOAD IT FROM T. + MOV A,AC + MOV U,LSH ;NOW SHIFT THE 2 FROM-WORDS BY # BITS SHIFTING BY, + MOV AC,(T)+ ;WHICH GIVES AC THE RIGHT STUFF FOR NEXT TO-WORD. + MOV B,A ;NOW T GETS THE NEWEST FROM-WORD, AND FETCH ANOTHER. + BR CDEL1 + +CDEL2: MOV A,MQ ;REMAINDER OF LAST FROM-WORD IS NEXT TO-WORD. + MOV U,LSH + MOV MQ,(T)+ + JSR PC,CLRRNG ;CLEAR STARTING WHERE T POINTS, ENDING WHERE C POINTS. +;NOW RESTORE THE FIRST FEW BITS OF THE FIRST WORD (WHICH WEREN'T SUPPOSED +;TO BE INCLUDED IN THE SHIFT). +CINS2: POP U + POP C ;GET ADDRESS OF 1ST TO-WORD + POP A ;GET OLD 1ST TO-WORD CONTENTS + POP T ;AND NUMBER OF BITS AT TOP NOT TO INCLUDE IN SHIFT. + MOV #-1,AC + NEG T + MOV T,LSH ;MQ GETS MASK TO BITS WE WANT SHIFTED INTO. + MOV AC,T + BIC T,A ;FLUSH THOSE IN SAVED CONTENTS. + COM T + BIC T,(C) ;FLUSH THE OTHERS IN SHIFTED CONTENTS. + BIS A,(C) ;MERGE OLD BITS WITH NEW. + RTS PC + +CLRRN1: CLR (T)+ +CLRRNG: CMP T,C + BNE CLRRN1 + RTS PC + +;CLEARS TO END OF LINE + +CLEOL: PUSH LECC(U) + PUSH LEPHS(U) + PUSH LEX(U) + JSR PC,CLEOL1 ;DO THE DIRTY WORK +CLEOX: POP LEX(U) + POP LEPHS(U) + POP LECC(U) + MOVB #CIOR,CALU ;RESTORE FOR DPYDP1 LOOP + RTS PC + +CLEOL1: MOV LEX(U),TT ;ALREADY AT END OF LINE? + BGE CLEOLX + CMP LEPHS(U),#20-CHRWD + BEQ CLEOL2 ;IF AT START OF WORD, START CLEARING WORD-WISE + JSR PC,CLRCHR ;ELSE CLEAR 1 CHAR AT A TIME TILL REACH WORD BOUNDARY. + JSR PC,LEDADC + CMP LEX(U),#-BITPL + BEQ CLEOLX ;CLEARED WHOLE LINE AND WRAPPED AROUND => DONE + BR CLEOL1 + +CLEOL2: ASR TT + ASR TT + ASR TT + ASR TT ;-(# WORDS TO CLEAR) + PUSH TT + PUSH LECC(U) ;ADDR OF 1ST WORD TO CLEAR, + PUSH #LINHT ;# LINES TO PROCESS + MOVB #CSET,CALU +CLEOL3: MOV 2(SP),T ;START CLEARING HERE +CLEOL4: CLR (T)+ + INC TT + BLT CLEOL4 + ADD #BYTPL,2(SP) + MOV 4(SP),TT ;-(# WORDS TO CLEAR) + DEC (SP) + BGT CLEOL3 + ADD #6,SP ;CLEANSE STACK + MOV T,LECC(U) + JMP CR1 ;RESET X AND PHASE + +CLEOLX: MOV LELCC(U),T + ADD #,T ;HERE IF ALREADY AT END OF LINE + MOV T,LECC(U) + JMP CR1 + +;CLEARS TO END OF SCREEN + +CLEOF: MOV LELCC(U),T ;IF AT START OF LINE, DO FAST CLEAR FROM THIS LINE. + CMP #-BYTPL,LEX(U) ;IF NOT AT BEGINNING OF LINE, USE CLEOL TO CLEAR + BEQ CLEOF1 ;ONLY THE REST OF THIS LINE. + JSR PC,CLEOL + MOV LELCC(U),T ;AND START FAST CLEAR WITH NEXT LINE. + ADD #BYTPL*LINHT,T +CLEOF1: MOV #TVFENCE,B + JMP LDEL5 + +;HERE TO FORWARD SPACE + +FS: JMP LEDADC + +;HANDLE %TDMOV +SETCUR: JSR PC,GETCHC ;OLD VERTICAL AND HORIZONTAL + JSR PC,GETCHC + +;HANDLE %TDMV0, %TDMV1 ABSOLUTE POSITIONING COMMANDS. +SETCR1: JSR PC,GETCHC ;NEW VERTICAL + MOV A,B + JSR PC,GETCHC ;NEW HORIZONTAL + ;NOTE GETCHC MAY RETURN AND BE REENTERED, + ;RESETTING ALL ACS BUT B. + +;HERE TO SET CURSOR GIVEN A COORDINATE PAIR (X,Y) IN CHARACTERS. +;X AND Y ARE IN A AND B RESPECTIVELY, (0,0) IS UPPER LEFTHAND CORNER +;(1,3) IS THE SECOND CHARACTER OF FOURTH LINE + +SETXY: CMP #CHRPL,A ;CHECK FOR LEGAL POSITION + BLOS SETXY1 + CMP #CHRLN,B + BLOS SETXY1 +SETXY0: MOV #MQ,T ;FOR THE MYRIAD MULTIPLIES AND DIVIDES + MOV B,(T)+ ;Y POSITION + MOV #BYTPL*LINHT,(T) ;FIND ORIGIN OF LINE IN MEMORY + MOV -(T),LECC(U) + MOV (T),LELCC(U) + MOV A,(T)+ ;X POSITION + MOV #CHRWD,(T) + MOV -(T),LEX(U) ;BITS FROM LEFT OF SCREEN + CLR -(T) ;CLEAR OUT AC + MOV #20,-(T) ;DIVIDE GIVES WORDS FROM LEFT AND PHASE + TST (T)+ + MOV (T)+,LEPHS(U) ;PHASE + ASL (T) ;BYTES FROM BEGIN OF LINE + ADD (T),LECC(U) ;LEAVE T POINTING AT MQ + ADD #-BITPL,LEX(U) ;THAT'S ALL DONE + NEG LEPHS(U) + ADD #20-CHRWD,LEPHS(U) ;PHASE IS SET + MOV B,(T)+ ;Y POSITION AGAIN + MOV #LINHT,(T) + MOV -(T),LEY(U) + ADD #-NLINS,LEY(U) ;LEY SET + ADD #TVLO,LECC(U) + ADD #TVLO,LELCC(U) + BIT #1,LECC(U) ;MAKE SURE IT LINES UP ON WORD BOUNDARY + BEQ .+4 + BPT +SETXY1: RTS PC + +;OUTSTR TAKES STRING TO PRINT IN B + +OUTSTR: +OUTS1: MOVB @(SP),A + INC (SP) + TST A + BEQ OUTSX + CMP #12,A + BEQ OUTSLF + CMP #15,A + BEQ OUTSCR + JSR PC,TVO + BR OUTS1 +OUTSLF: JSR PC,LF + BR OUTS1 +OUTSCR: JSR PC,CR + BR OUTS1 +OUTSX: ASR (SP) ;MAKE SURE WE RETURN TO EVEN ADDRESS + ADC (SP) + ASL (SP) + RTS PC + +;TAKES # IN A AND PRINTS AS UNSIGNED INTEGER + +OCTPNT: PUSH RADIX + MOV #10,RADIX +OCTPN1: JSR PC,DECPN0 + POP RADIX + RTS PC + +DECPNT: PUSH RADIX + MOV #10.,RADIX ;FOR DECIMAL PRINTING + BR OCTPN1 + +DECPN0: MOV A,MQ ;INTO EAE +DECPN9: MOV #AC,A ;FOR FAST ACCESS +DECPN1: MOV RADIX,-(A) ;DIVIDE BY RADIX + TST (A)+ ;POINTS AT AC + MOV (A)+,-(SP) ;REMAINDER + ADD #'0,(SP) + TST (A) ;QUOTIENT IS IN MQ + BEQ DECPN2 + CLR -(A) ;FLUSH OUT AC, LEAVING MQ UNTOUCHED + JSR PC,DECPN1 ;RECURSIVE YET! +DECPN2: POP A ;TYPE OUT THAT DIGIT + JMP TVO ;TYPES DIGIT AND ADVANCES CURSOR + +.SBTTL CALL, BREAK AND ESCAPE ROUTINES + +;LEGAL ESCAPE AND BREAK COMMAND TABLE + +ESCHAR: .BYTE '0,'1,'2,'3,'4,'5,'6,'7,'8,'9 ;DON'T DISTURB DIGITS + .BYTE 'S,'Q,'F,'D,'A,'E ;THESE CAN BE DONE ON ANY KBD +ESCSRN: .BYTE 'C,'L,'I,'R,'W,'U ;THESE NEED A SCREEN TO WIN +NESCMD==.-ESCHAR + .BYTE 0 ;MARKS END OF TABLE + .EVEN + +;DISPATCH TABLE + +ESCTAB: .REPT 10. + .NLIST + ESCDIG ;DIGIT + .LIST + .ENDR + VSWSEL ; SELECT VIDEO CHANNEL + ESCQPY ; CAUSE A HARD COPY TO EXIST + ESCFRE ; SAME AS S, BUT TO CONSOLE FREE BUFFER + ESCBUZ ; BUZZ 9TH FLOOR DOOR + ESCAUD ; SELECT AUDIO INPUT. + ESCELE ; CALL THE ELEVATOR +CHECK ESCTAB,<*2> + BOWXOR ; TOGGLE BLACK ON WHITE BIT + ESCCLR ; CLEAR SCREEN UNBEKNOWNST TO TEN. + ESCCSR ; CLEAR SCROLL REGISTER + ESCRPT ; START REPEATING THE PREV. CHAR TYPED IN. + ESCWHO ; WHO LINE CONTROL + ESCWHO ; WHO LINE CONTROL +CHECK ESCTAB,NESCMD*2 + +;HERE FOR ESCAPE + +ESCAPE: BIT #ACLBIT+AMTBIT,B + BEQ ESCAP1 ;ESCAPE WITH CONTROL OR META TURNS INTO TOP-A. + JMP BRKCLR + +ESCAP1: MOVB A,KBDESC(C) ;SAY FOLLOWING CHARS TO BE INTERPRETED AS AN ESCAPE CMD. + CLRB KBDARG(C) ;DEFAULT ARG TO ZERO +RTSPC4: RTS PC + +;ACCUMULATE ARGS FOR ESCAPE AND BREAK + +ESCDIG: ASR T ;DIGIT + MOVB KBDARG(C),A ;MULTIPLY ACCUMULATED VALUE BY 8 + ASL A + ASL A + ASL A + ADD T,A ;ADD IN NEW DIGIT + MOVB A,KBDARG(C) + INCB KBDESC(C) ;READ NEXT CHAR AS A COMMAND CHAR, NOT AS PDP-10 INPUT. + RTS PC + +;TAKES CHARACTER IN A AND CONVERTS IT UPPER CASE + +UPPER: TST A ;MAKE SURE ITS LEGAL ASCII + BLE UPPER1 + CMP #'a,A ;LOWER CASE? + BGT UPPER1 + CMP #'z,A + BLT UPPER1 + SUB #'a-'A,A ;MAKE IT UPPER CASE +UPPER1: RTS PC + +;HANDLE ESCAPE-R. WITH NO ARG, STARTS INDEFINITE REPETITION OF LAST CHARACTER TYPED. +;WITH ARG, STOPS AFTER THAT MANY REPETITIONS. IN ANY CASE, ANY USER-SUPPLIED +;INPUT STOPS THE REPETITION. +ESCRPT: MOVB KBDARG(C),A + BNE ESCRP1 + DEC A +ESCRP1: MOV A,LERPT(U) + RTS PC + +;HERE TO SELECT VIDEO SWITCH INPUT. +;C HAS 2*KBD NUMBER; KBDARG(C) HAS VSW INPUT # OR 0 => DEFAULT. + +VSWSEL: JSR PC,VSWSGO ;SET UP L.E. IDX IN U, VSW OUTPUT IN T. + BLT RTSPC4 + MOV #-1,KBDDEF(C) ;NORMALLY RESET ANY TIME-OUT, BUT + TSTB KBDARG(C) ;IF THERE'S AN ARGUMENT, + BEQ VSWSL0 + TST U + BNE VSWSL0 + JSR PC,VSWSL3 ;SET UP A TIMEOUT, IF WE ARE A FREE SCREEN. +VSWSL0: MOVB KBDARG(C),TT ;GET ARG + BNE VSWSL1 ;SELECT DEFAULT? + +;SELECT THE DEFAULT INPUT FOR A KEYBOARD. +;C HAS 2*KBD #, U HAS L.E. IDX OR 0 IF NONE, T HAS DEFAULT VSW OUTPUT OF THAT KBD. +VSWDEF: MOV #-1,KBDDEF(C) ;SAY THERE'S NO TIMEOUT ON THIS VSW SELECTION. + TST U ;FREE SCREEN => DEFAULT IS THE FREE DPY BUFFER. + BEQ VSWFRE + MOVB LECREG(U),TT ;GET DPY # TO SET DEFAULT + BLT RTSPC4 ;GARBAGE? +;COME HERE WITH DPY BUFFER # IN TT, TO SELECT THAT DPY BUFFER. +VSWDE1: ASL TT + MOV DPYVSW(TT),TT ;DEFAULT VIDEO SWITCH INPUT + JMP VSWIT ;DON'T NEED TO CHECK THIS + +;COME HERE FOR [ESC]S, WITH IN TT. +VSWSL1: BIC #-400,TT ;UNDO SIGN-EXTENSION AT VSWSL0 + CMP TT,NF11TY + BLO VSWSL2 ; TOO SMALL TO BE TTY # => IT IS VSW INPUT #. + CMP TT,#200 + BHIS VSWSL4 ; >= 200 => IT IS DPY BUFFER # PLUS 200. + TST NF11TY ;IF NF11TY ISN'T KNOWN, VSW INPUT #S LOOK LIKE TTY #S + BEQ VSWSL2 ;BUT WE ARE EVEN SMARTER AND KNOW IT'S REALLY VSW INPUT. + SUB NF11TY,TT ;ELSE SHOULD BE TTY NUMBER + CMP TT,#MAXTV + BHIS RTSPC4 ;DO NOTHING IF ARG OUT OF RANGE. + ASL TT + ASL TT + MOVB DPYKBD+1(TT),TT ;GET DPY BUFFER # FOR THIS TV, AND SELECT THAT DPY BUFFER. + BMI RTSPC4 + BR VSWDE1 + +VSWSL4: SUB #200,TT ;TT SUPPOSEDLY HAS 200 PLUS DPY BUFFER NUMBER. + CMP TT,#MAXTV + BLO VSWDE1 + BR RTSPC4 + +;COME HERE TO HANDLE SET-VSW COMMAND FROM PDP10. T HAS OUTPUT #, TT HAS INPUT #. +;IF THEY ARE ILLEGAL WE DO NOTHING. +;ON RETURN, BLO JUMPS IF THEY WERE LEGAL. +VSWCMD: MOV #-1,KBDDEF(C) ;FLUSH ANY TIME-OUT. + CMP T,#MAXVSO ;CHECK FOR LEGAL OUTPUT + BHIS RTSPC4 +;COME HERE WITH VALID OUTPUT # IN T, AND (MAYBE INVALID) INPUT # IN TT. +VSWSL2: CMP TT,#MAXVSI*VSWSEC + BHIS RTSPC4 ;REASONABLE? + JMP VSWIT ;SWITCH THE SWITCH + +ESCFRE: JSR PC,VSWSGO ;SET UP U AND T FOR VSWDE1. + BLT RTSPC5 + JSR PC,VSWSL3 ;THERE IS A TIMEOUT ON THIS SPYING. +VSWFRE: MOV DPYFRE,TT ;GET DPY # OF FREE CONSOLE SCREEN + BR VSWDE1 + +;SET UP A TIMEOUT WHEN A SPY IS ABOUT TO BE DONE. C HAS 2*KBD. +VSWSL3: MOVB #KBDTIM,KBDCNT(C) ;SET UP A TIMEOUT ON THIS KEYBOARD. + INC KBDTSW ;TELL CLOCK LEVEL TO START CHECKING TIMEOUTS. + RTS PC + +;SET UP U := L.E. IDX, OR 0 IF NONE; T HAS DEFAULT VSW OUTPUT; GIVEN 2*KBD # IN C +;NEGATIVE IF SOMETHING FUNNY IS GOING ON, AND CALLER SHOULDN'T HACK. +VSWSGO: MOV KBDLE(C),U + BLT RTSPC5 ;THIS IF TEN SELECTS NON-EXISTENT VSW OUTPUT. + BEQ VSWSG1 + TST LEKBD(U) + BLT RTSPC5 +VSWSG1: MOV C,T + ASR T + MOVB KBDVSW(T),T + RTS PC + +;DO [ESC]S ON KBD SPEC'D BY 2*KBD IN C. +VSWUNS: JSR PC,VSWSGO + BLT RTSPC5 + JMP VSWDEF + + +;HANDLE [ESC] A. +ESCAUD: MOVB KBDARG(C),TT ;ASW INPUT NUMBER. + MOV C,T + ASR T ;KEYBOARD NUMBER. + MOVB KBDASW(T),T ;OUTPUT NUMBER OF KEYBOARD. + BMI RTSPC5 ;WE DON'T KNOW YET OR IT HAS NO SPEAKER. + JMP ASWIT ;CONNECT THEM. + +;CHANGE STATE OF BOW BIT + +BOWXOR: MOVB #CXOR,CALU + MOV #BOWBIT,CSA + RTS PC + +;HERE TO CLEAR SCREEN + +ESCCLR: MOVB CREG,T ;THE SCREEN TO CLEAR + PUSH T + + BLKOFF T + JSR PC,CLBLIN ;CLEAR ALL BLINKERS + JSR PC,CLRSCR ;CLEAR THE SCREEN + POP T + BLKON T + + RTS PC + +;HERE TO RESET SCROLL REGISTER + +ESCCSR: MOVB #CSET,CALU + BIC #SAMSK,CSA ;RESET THE SCROLL REGISTER + RTS PC + +;HERE TO GENERATE VIDEO HARD COPY + +ESCQPY: TST QPYSWT ;IS THE SWITCH LOCKED? + BNE ESCQPB + TST QPYDWN ;IS THE QPY DOWN? + BNE ESCQPB +ESCQP1: MOV KBDLE(C),U + BEQ ESCQP6 + TST LEKBD(U) + BLT RTSPC5 +ESCQP6: MOV #QPYVSW,T ;THE VIDEO SWITCH OUTPUT FOR THE HARD COPY UNIT + JSR PC,VSWSL0 ;PROCESS THE ARG + CHROFF + ZAPFLG QPYSWT ;LOCK THE SWITCH + BIS #QPYKMS,KMS ;CAUSE THE COPY + JSR TT,ADQUE ;SCHEDULE THE UNCOPY + 2 + ESCQP2 + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE SWITCH UNLOCK + QPTIME + ESCQP3 +RTSON: CHRON +RTSPC5: RTS PC + +ESCQPB: JMP BELL ;SOME ONE ELSE IS COPYING, GIVE HIM A BELL + +ESCQP2: BIC #QPYKMS,KMS ;UNCAUSE THE COPY + RTS PC + +ESCQP3: JSR PC,CLKBEL ;BELL WHEN COPY DONE + CLR QPYSWT + RTS PC + +;HERE TO BUZZ 9TH FLOOR DOOR +ESCBUZ: TST BUZSWT ;IS THE SWITCH LOCKED? + BEQ ESCBZ1 + JMP BELL +ESCBZ1: CHROFF + ZAPFLG BUZSWT ;LOCK SWITCH + BIS #BUZKMS,KMS ;BUZZ THE DOOR + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE UNBUZZ + BUZTIM + ESCBZ2 + BR RTSON + +ESCBZ2: JSR PC,CLKBEL ;BELL WHEN BUZZ DONE + BIC #BUZKMS,KMS ;UNBUZZ THE DOOR + CLR BUZSWT ;UNLOCK THE SWITCH + RTS PC + +;HERE TO CALL THE ELEVATOR +; C HAS 2*KBD NUMBER + +ESCELE: TST ELESWT ;IS THE SWITCH LOCKED? + BEQ ESCEL1 + JMP BELL +ESCEL1: CHROFF + ZAPFLG ELESWT ;LOCK SWITCH + MOV C,T + ASR T ;DEVIDE BY 2 + CMP T,#MAXVSO ;IS IT IN RANGE? + BHIS RTSON + MOVB ELETAB(T),TT ;WHICH FLOOR IS IT ON? + SWAB TT ;GET CONSTANT INTO THE LEFT HALF WORD + BIS TT,KMS ;FROB THE CORRECT BIT + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE UNPUSH + ELETIM + ESCEL2 + BR RTSON + + +ESCEL2: JSR PC,CLKBEL ;BELL WHEN DONE + BIC #ELEKMS,KMS ;UNPRESS + CLR ELESWT ;UNLOCK THE SWITCH + RTS PC + + + +CLKBEL: PUSH CREG ;FOR USE BY CLOCK QUEUED ROUTINES + MOV (T),CREG ;T POINTS TO DESIRED CREG + PUSH TT ;DON'T CLOBBER AT PI LEVEL!! + JSR PC,BELL + POP TT + POP CREG + RTS PC + +;HERE TO CONTROL WHO LINE + +; [ESC]W WHMODE +; N=0 TURN OFF WHO LINE -1 +; 1 FOLLOW KEYBORAD 0 +; 2 FREEZE 1 +; 3 NEXT HIGHER 2 +; 4 NEXT LOWER 3 +;ALL OTHERS SYSTEM WHO LINE + +; [ESC]U +;FREEZES WHOLINE ON JOB WHOSE USER INDEX IS N*L (L IS THE ITS SYMBOL). + +NWHCMD==5 ;NUMBER OF WHO COMMANDS + +ESCWHO: MOV LECHN(U),TT ;10/11 CHANNEL + ASL TT ;MAKE IT CHANNEL INDEX + ASL TT + MOV WHOLIN(TT),TT ;WHO LINE VARIABLES + CMPB A,#'U + BEQ ESCWHU + MOVB KBDARG(C),T ;ARGUMENT + DEC T ;HACK + BMI ESCWH2 ;TURN IT OFF? + MOV T,WHMODE(TT) ;SET THE MODE WE WANT +ESCWU1: CLR WHMOD1(TT) ;JUST TO BE SURE + MOV #-1,TENWHO ;TELL PDP-10 TO UPDATE WHO LINES + RTS PC + +;TURNS OFF WHO LINE + +ESCWH2: ;CLEAR WHO LINE AT MAIN PROGRAM LEVEL TOO + MOV T,2(TT) ;(T HAS -1 IN IT) + MOV T,WHMODE(TT) ;AND TURN IT OFF + BR CLRWHL + +ZAPWHL: MOV DPYCHN(B),A ;SET UP CREG + MOVB LECREG(A),CREG +CLRWHL: MOV #TVLO+,T + MOV #CHRHT-1,TT + JMP CLRCL0 + +ESCWHU: MOV #1,WHMODE(TT) + MOVB KBDARG(C),WHJOB(TT) + CLR WHJOB1(TT) + BR ESCWU1 + +;COME HERE FOR CALL KEY + +CALL: PUSH B + TSTB KBDCNT(C) + BLT CALL1 + JSR PC,VSWUNS ;IF DOING A SPY WITH A TIMEOUT, UNDO IT. +CALL1: MOV KBDLE(C),U ;LINE EDITOR VARIABLES + BNE UPTREE ;GET FRESH LINE EDITOR? + ASR C + JSR PC,CHCONS ;ALLOCATE A CHANNEL. +;T HAS CHANNEL NUMBER. U HAS LINE EDITOR ADDR. A HAS WHOLINE VAR BLOCK ADDR. + TST T ;-1 RETURNED AS CHANNEL # => NONE AVAILABLE. + BLT CALLLS + MOVB LECREG(U),CREG + CLR CSA ;CLRSCR SETS UP CALU + +;HERE IF CALL AND LINE EDITOR EXISTS. + +UPTREE: POP B + CLR LERPT(U) + MOV #32,A ;CONTROL-Z (SIGH) + BIS #ACTBIT,B ;ACTIVATES BUFFER + JMP PUTCHR ;SEND THAT CHARACTER TO PDP-10 + +CALLLS: POP B +RTSPC2: RTS PC + +;HERE TO ALLOCATE A DISPLAY CHANNEL. +;CALLED WITH KEYBOARD NUMBER IN C, OR -1 IF NOT ALLOCATING THIS DPY FOR A KEYBOARD. +;RETURNS THE CHANNEL NUMBER (TTY NUMBER MINUS NF11TY) IN T, +;THE LINE EDITOR BLOCK ADDR IN U, +;AND THE ADDRESS OF THE WHOLINE VARIABLE BLOCK IN A. SETS WHMODE TO 0. +;IF NO CHANNEL IS AVAILABLE, OR THE KEYBOARD CAN'T BE USED FOR SOME REASON, +;WE RETURN -1 IN T TO INDICATE THAT. + +CHCONS: MOV C,T ;IF A KEYBOARD IS SPECIFIED, + BLT CHCON4 + TSTB KBDVSW(C) ;DON'T ALLOW IT IF KEYBOARD HAS NO SCREEN + BLT CHCNFL + ASL T + TST KBDLE(T) ;OR IS ALREADY IN USE. + BNE CHCNFL +CHCON4: CLR T ;NOW FIND A FREE CHANNEL +CHCON1: TSTB CHCREG(T) ;DON'T ALLOCATE CHANNELS THAT DON'T HAVE BUFFERS. + BLT CHCON0 + TSTB CHNUSE(T) + BEQ CHCON2 +CHCON0: INC T + CMP T,#MAXTV + BLT CHCON1 +CHCNFL: MOV #-1,T + RTS PC ;NO FREE CHANNEL + +CHCON2: INCB CHNUSE(T) ;FOUND A CHANNEL. MARK IT IN USE. + DEC ITSFDP ;DECREASE COUNT OF FREE CHANNELS. + MOVB CHCREG(T),A + PUSH A ;SAVE VIDEO BUFFER NUMBER FOR POPPING INTO LECREG + MOVB A,CREG ;SELECT THAT BUFFER + PUSH T ;PROTECT T, SMASHED BY CLRSCR (TT ALSO SMASHED) + JSR PC,CLRSCR ;AND CLEAR IT (SLOW, BUT NECESSARY BEFORE SWITCHING VSW) + POP T + MOV T,A + ASL A + ASL A + MOV DPYCHN(A),U ;GET THE ADDR OF CHANNEL'S VAR BLOCK. + JSR PC,CHCLR ;PUT -1'S IN THE 10-TO-11 BUFFER, RESET POINTERS. + JSR PC,LECON2 ;INITIALIZE THE LINE EDITOR BLOCK. + MOVB (SP),DPYKBD+1(A) ;TELL THE 10 WHICH TV BUFFER. + POP LECREG(U) ;TELL THE LINE EDITOR WHICH TV BUFFER IT IS. + MOV C,LEKBD(U) ;AND WHICH KEYBOARD IT IS. + BLT CHCON3 + MOV C,CHNCLS(A) ;TELL THE 10 ABOUT THE KEYBOARD. + CLRB CHNCLS+1(A) ;MAKE SURE CHNCLS IS NON-NEGATIVE EVEN IF KBD WAS -1 + MOVB C,DPYKBD(A) + MOV T,LECHN(U) ;TELL LE WHICH DPY CHANNEL NUMBER IT IS + PUSH T ;SHOW OUR DPY BUFFER ON THE KBD'S SCREEN. + MOVB KBDVSW(C),T ;VIDEO SWITCH OUTPUT + MOVB LECREG(U),B + ASL B + MOV DPYVSW(B),TT ;GET OUR DPY'S VIDEO INPUT NUMBER. + JSR PC,VSWIT ;SWITCH THE SWITCH + MOV FBLINK,T ;CONS UP A BLINKER FOR THE CURSOR + BNE .+4 ;ARE THERE FREE BLINKERS? + BPT + + MOV BLNEXT(T),FBLINK + MOV BLINKS(B),BLNEXT(T) + MOV T,BLINKS(B) ;THE BLINKER + MOV U,BLCURS(T) ;FOLLOW PAGE PRINTER + CLRB BLON(T) ;BLON + + POP T + ASL C ;MAKE THE KEYBOARD AND THIS LINE EDITOR POINT AT EACH OTHER. + MOV U,KBDLE(C) +CHCON3: PUSH WHOLIN(A) + PUSH T + MOV T,TT + MOV LEBUF(U),T + JSR PC,CLRING ;CLEAR THE 11-TO-10 INPUT BUFFER RING. + POP T + POP A + MOV #0,WHMODE(A) + RTS PC + +;CLEAR OUT THE 10-TO-11 BUFFER WHICH U POINTS AT. + +CHCLR: MOV DPY10B(U),TT ;POINTER TO START OF BUFFER + MOV TT,DPY11B(U) ;RESET OUR POINTER INTO THE CHANNEL'S BUFFER. + INC DPY11B(U) ;MAKE POINT AT 1ST BYTE IN PDP10 ORDER! +CHCLR1: MOV #-1,(TT)+ + CMP TT,DPYLGL(U) + BLOS CHCLR1 + RTS PC + +;HERE TO INITIALIZE MOST OF THE WORDS OF A LINE EDITOR BLOCK, +;AND GET A RING OF KEYBOARD BUFFERS FOR IT. +LECON2: PUSH T + PUSH U + MOV U,TT ;SET DEFAULTS + ADD #DPSIZE+DPDATA,TT + MOV #LEDFLT+DPSIZE+DPDATA,T + MOV #LELEN-DPSIZE-DPDATA,U + JSR PC,CALCPY ;DEFAULT IS FOR FREE VARIABLES + POP U + MOV FSP,T ;FIRST FREE BUFFER + BEQ LECON3 + MOV LHFS(T),TT ;NEXT BUFFER + BEQ LECON3 + MOV LHFS(TT),FSP ;TAKE THOSE TWO + MOV T,LHNEXT(TT) + MOV TT,LHNEXT(T) ;ALL NICE AND COZY + MOV T,LEBUF(U) ;POINTER TO RING + ADD #LHLEN,T + MOV T,LECHR(U) ;BUFFER ACCESS POINTER + POP T + RTS PC + +LECON3: BPT ;NO 11-TO-10 BUFFERS AVAILABLE FOR A RING? + +;CLEARS HEADERS OF BUFFER RING, CALLED WITH RING IN T, CHN# IN TT + +CLRING: PUSH T +CLRNG1: CLR (T)+ .SEE LHFLAG + CLR (T)+ .SEE LHZERO + TST (T)+ .SEE LHNEXT + CLR (T)+ .SEE LHALST + CLR 2(T) .SEE LHFS + CLR 4(T) .SEE LHQUED + MOV TT,(T) .SEE LHCHN + TST -(T) .SEE LHALST + MOV -(T),T ;.SEE LHNEXT COMMENT THIS OUT DUE TO PALX BRAIN DAMAGE + CMP (SP),T + BNE CLRNG1 + POP T + RTS PC + +;HERE TO COPY A BLOCK OF CORE +: T SOURCE +; TT DESTINATION +; U BYTE COUNT (ONLY EVEN NUMBERS WILL WORK) + +CALCPY: INC U ;MAKE A WORD COUNT + ASR U +CALCP1: MOV (T)+,(TT)+ + DEC U + BGT CALCP1 + RTS PC + +;HERE TO RETURN DPY CHANNEL. T HAS CHANNEL NUMBER. + +CHRETN: TST T ;DON'T RETURN CHANNEL 0. + BEQ CHRET0 + DECB CHNUSE(T) ;MARK THE CHANNEL AS NOT IN USE + BGE .+4 + BPT + INC ITSFDP ;AND INCLUDE IT IN THE COUNT OF FREE CHANNELS. + BR CHRET1 + +CHRET0: MOV #377,CHNCLS ;IF FREEING THE FREE TV DISPLAY, DON'T REALLY FREE IT +CHRET1: ASL T + ASL T + MOV DPYCHN(T),U + JSR PC,CHCLR ;RESET THE 10-TO-11 BUFFER AND POINTERS. + TST T + BEQ CHRETX ;DON'T RETURN CHANNEL 0 (FREE CONSOLE DISPLAY) + MOV #-1,DPYKBD(T) ;TELL THE PDP-10 WE'RE LOGGING OUT + MOV WHOLIN(T),TT + MOV #-1,WHMODE(TT) ;TURN OFF WHO-LINE GENERATION ON THIS CHANNEL. + +;HERE TO FREE THE 11-TO-10 INPUT BUFFERS, AND MARK THE KEYBOARD AND CHANNEL +;AS DISCONNECTED. ALSO FREE THE BLINKERS. +LERETN: CLR LERPT(U) + MOV LEBUF(U),T ;RETURN BUFERS IN RING + BEQ LERT2A ;BUFFERS TO RETURN? + PUSH T +LERET1: MOV LHNEXT(T),LHFS(T) + CMP LHFS(T),(SP) + BEQ LERET2 + MOV LHFS(T),T + BR LERET1 +LERET2: MOV FSP,LHFS(T) ;CUT RING, PATCH ON TO FREE LIST + POP FSP + CLR LEBUF(U) ;MARK AS FREE +LERT2A: MOV LEKBD(U),T + BLT LERT2B ;A KEYBOARD? + ASL T ;BYTES + CLR KBDLE(T) + ASR T + MOVB KBDVSW(T),T ;VSW THE OUTPUT + BLT LERT2B + MOV DPYFRE,TT ;MESSAGE DPY + ASL TT ;BYTES + MOV DPYVSW(TT),TT + JSR PC,VSWIT ;GIVE HIM THE CONSOLE FREE MESSAGE +LERT2B: MOVB LECREG(U),T ;RETURN ALL THE BLINKERS + BLT LERET5 ;A DPY? + MOVB #-1,LECREG(U) ;INVALIDATE DPY # + ASL T + TST BELCNT(T) ;ANY BELLS PENDING? + BMI LERET6 + CLR BELCNT(T) ;THE NEXT FLASH WILL BE THE LAST +LERET6: MOV BLINKS(T),TT ;RETURN THIS DISPLAY'S BLINKERS TO FREE LIST. + BEQ LERET5 +LERET3: TST BLNEXT(TT) + BEQ LERET4 + MOV BLNEXT(TT),TT + BR LERET3 +LERET4: MOV FBLINK,BLNEXT(TT) + MOV BLINKS(T),FBLINK + CLR BLINKS(T) +LERET5: MOV #-1,LEKBD(U) +CLRUJ: CLR U ;SEARCH FAILED +CHRETX: RTS PC + +.SBTTL VIDEO AND AUDIO SWITCH ROUTINES + +;VIDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS) + +;THE SWITCH IS COMPOSED OF SEVERAL IDENTICAL SECTIONS, THE CORRESPONDING +;OUTPUTS OF EACH SECTION ARE MIXED TOGETHER TO FORM THE FINAL VIDEO THAT IS +;SENT TO THE MONITOR. INPUT 0 OF EACH SECTION OF THE SWITCH IS THE NULL INPUT, +;HENCE WE USUALLY USE THAT INPUT WHEN USING A MONITOR AS A DISPLAY. + +;VSWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE NONNULL INPUT FEEDING THAT OUTPUT. +;THE INPUT NUMBER IS RELATIVE TO THE WHOLE SWITCH, NOT JUST THE SECTION. +;0 MEANS THAT ONLY NULL INPUTS ARE FEEDING AN OUTPUT. + +VSWTAB: .BLKB MAXVSO + + +;HERE TO SWITCH VIDEO SWITCH (OUTPUT IN T, INPUT IN TT). +;CLOBBERS NO ACS. + +VSWIT: PUSH TT + JSR PC,VSWNUL ;FLUSH ALL OTHER INPUTS TO THAT OUTPUT. + POP TT +VSWIT1: PUSH B + PUSH C + MOVB TT,VSWTAB(T) ;UPDATE OUR OWN INTERNAL TABLE. + MOV TT,MQ + MOV #MAXVSI,DIV ;DIVIDE TO TURN INPUT NUMBER + MOV MQ,C ;INTO SECTION NUMBER + MOV AC,B ;AND NUMBER WITHIN SECTION. + TST A ;CLEAR C BIT + ROR C + ROR C + ROR C + ROR C ;GET SECTION NUMBER INTO TOP THREE BITS OF WORD. + BIS C,B + MOV T,C + SWAB C + BIS C,B ;CREATE ARGUMENT FOR VIDEO SWITCH. + MOV B,VSW ;SWITCH IT! + POP C + POP B + RTS PC + +;HERE SEND NULL VIDEO TO OUTPUT SPECIFIED IN T +;CLOBBERS TT +VSWNUL: PUSH #VSWSEC ;# SECTIONS + CLR TT ;INPUT 0 IN SECTION 0. +VSWN1: JSR PC,VSWIT1 ;SWITCH IT + ADD #MAXVSI,TT ;ADVANCE TO INPUT 0 IN NEXT SECTION + DEC (SP) + BGT VSWN1 ;MORE + TST (SP)+ ;CLEANSE STACK + CLRB VSWTAB(T) ;MAKE SURE INTERNAL TABLE SAYS NOTHING FEEDING THIS OUTPUT. + RTS PC + +;AUDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS) + +;INPUT 0 IS SILENCE. RIGHT NOW, THAT IS THE NORMAL SETTING FOR ANY OUTPUT. + +;ASWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE INPUT FEEDING THAT OUTPUT. +ASWTAB: .BLKB MAXASO + + +;GIVEN ASW OUTPUT IN T AND INPUT IN TT, CONNECT THEM IF THEY ARE LEGAL. +;ON RETURN, BLO JUMPS IF THEY WERE LEGAL. +ASWCMD: CMP T,#MAXASO + BHIS ASWITX + CMP TT,#MAXASI + BHIS ASWITX + +;HERE TO SWITCH AUDEO SWITCH (OUTPUT IN T, INPUT IN TT). +;CLOBBERS NO ACS. + +ASWIT: PUSH C + MOV T,C + SWAB C + BIS TT,C ;CONSTRUCT OUTPUT,,INPUT AND GIVE TO SWITCH AS COMMAND. + PUSH B + MOV C,B ;NOW COMPLEMENT SOME OF C (WHAT'S IN ASWXOR). + BIC #<-1>#ASWXOR,B + BIS #ASWXOR,C + BIC B,C + POP B + MOV C,ASW + MOVB TT,ASWTAB(T) ;UPDATE OUR OWN INTERNAL TABLE. + POP C +ASWITX: RTS PC + +;RESET THE AUDEO SWITCH (ALL OUTPUTS RECEIVING SILENCE). +REASW: MOV #MAXASO-1,T + CLR TT +REASW1: JSR PC,ASWIT + DEC T + BGE REASW1 + RTS PC + +.SBTTL CHARACTER GENERATOR ROUTINES + +;CLEARS CHARACTER AT LINE EDITOR CURSOR + +CLRCHR: JSR U,ACSAV + MOVB #CANDC,CALU +CLCHR1: MOV #BLOB,T ;BLOB MASKS ENTIRE CHARACTER +CLCHR2: MOV LEPHS(U),C + MOV LECC(U),TT + JSR PC,GENCH1 + MOVB #CIOR,CALU ;RESTORE FOR DPYDP1 LOOP + BR ACRES + +;BLINK CHARACTER AT CURSOR + +XORCHR: JSR U,ACSAV + MOVB #CXOR,CALU + MOV #BLOB,T + BR CLCHR2 + +;GENERATE A CHARACTER +;CALL WITH CHARACTER IN A AND PAGE PRINTER IN U +;PRESERVES ALL ACS + +GENCHR: JSR U,ACSAV + MOV LEPHS(U),C + MOV LECC(U),TT + MOVB #CIOR,CALU + ASL A ;MAKE IT A BYTE OFFSET + MOV CTAB(A),T ;POINTS AT FONT DESCRIPTION + JSR PC,GENCH1 +ACRES: POP A + POP B + POP C + POP T + POP TT + POP U + RTS PC + +;The lowest level character generator +;Initial AC settings + +;A LSH address of EAE shift counter +;B MQ address of EAE regiseter +;C number of desired shifts +;T points into font description +;TT points into display memory +;U number of bytes per line of display memory + +;initial memory settings + +;AC 0, EAE register +;CREG CIOR,,console number, console register +;;NOTE THAT MQ=AC+2 +;THIS ROUTINE CLOBBERS -ALL- ACS + +GENCH1: MOV #LSH,A + TST C + BLT OVRLAP +EZCASE: MOV #BYTPL,U + MOV #AC,B + CLR (B)+ ;CLEAR AC + +.REPT CHRHT +.NLIST + MOVB (T)+,(B) ;5.2 ;CHARACTER RASTER LINE INTO MQ + MOV C,(A) ;3.7 ;INITIATE SHIFT + MOV (B),(TT) ;5.2 ;OUT OF MQ INTO DISPLAY MEMORY + ADD U,TT ;2.3 ;GET TO NEXT RASTER LINE +; TOTAL 16.4 MICRO-SECONDS +.LIST +.ENDR + RTS PC + +;initial settings same as EZCASE with one exception +;U -2 + +OVRLAP: MOV #BYTPL-2,U + MOV #MQ+2,B + +.REPT CHRHT +.NLIST + CLR -(B) ;3.7 ;CLEAR MQ + CLRB -(B) ;2.3 ;CLEAR HIGH ORDER OF AC + MOVB (T)+,-(B) ;5.2 ;LOAD AC WITH CHARACTER LINE + MOV C,(A) ;3.7 ;INIATE SHIFT + MOV (B)+,(TT)+ ;5.2 ;AC TO DISPLAY MEMORY + MOV (B)+,(TT) ;5.2 ;MQ TO DISPLAY MEMORY + ADD U,TT ;2.3 ;SET TO NEXT RASTER LINE + ;TOTAL 27.6 MICRO-SECONDS +.LIST +.ENDR +RTSPC: RTS PC + +;SOME LOW LEVEL GOODIES + +;CLEARS ONE RASTER LINE + +CLRRST: MOVB #CSET,CALU +CLRRS1: .REPT WRDPL + .NLIST + CLR (T)+ + .LIST + .ENDR + RTS PC + +;CLEARS ONE CHARACTER LINE + +CLRCHL: MOV #LINHT-1,TT +CLRCL0: JSR PC,CLRRST +CLRCH1: JSR PC,CLRRS1 + DEC TT + BGT CLRCH1 + RTS PC + +;CLEAR ENTIRE SCREEN + +CLRSCR: MOV #TVLO,T + JSR PC,CLRRST + MOV #NLINS-1,TT +CLRSC1: JSR PC,CLRRS1 + DEC TT + BGT CLRSC1 + RTS PC + +;COPIES ONE RASTER LINE + +CPYRST: MOVB #CSET,CALU +CPYRS1: .REPT WRDPL + .NLIST + MOV (T)+,(TT)+ + .LIST + .ENDR + RTS PC + +;COPIES ONE CHARACTER LINE + +CPYCHL: PUSH A + MOV #LINHT-1,A + JSR PC,CPYRST +CPYCH1: JSR PC,CPYRS1 + DEC A + BGT CPYCH1 + POP A + RTS PC + +.SBTTL KEYBOARD TABLES + +.MACRO KBDKEY N,PLAIN,SH,SL,SLSH,TOP +.XLIST +.=XTAB+N +.BYTE PLAIN +.=XTAB+N+100 +.BYTE SH +.=XTAB+N+200 +.BYTE SL +.=XTAB+N+300 +.BYTE SLSH +.=XTAB+N+400 +.BYTE TOP +.LIST +.ENDM + +;WHAT FOLLOWS IS THE GRAND CHARACTER CONVERSION TABLE + +;AN 8 BIT QUANTITY IS USED TO INDEX INTO THE XTAB +; 0-5 KEYBOARD KEY NUMBER +; 6 SHIFT +; 7 SHIFT LOCK +; 8 TOP (6 AND 7 GUARANTEED TO BE ZERO) + +;IF THE BYTE PICKED IS NEGATIVE, YOU HAVE STRUCK A KEY THAT DOES NOT +;HAVE AN ASCII CODE. THESE CODES ARE ASSIGNED AS FOLLOWS: + +NASCTB: NONAS1 ; 0 ILLEGAL + ESCAPE ; -1 ESCAPE + BRKCLR ; -2 BREAK + BRKCLR ; -3 CLEAR + PLSMNS ; -4 PLUS-MINUS + CRCPLS ; -5 CIRCLE-PLUS + DELTA ; -6 DELTA + GAMMA ; -7 GAMMA + BRKCLR ; -10 HELP + RTSPC ; -11 BACK -- not really used + RTSPC ; -12 NEXT -- not really used + CALL ; -13 CALL +MAXNAS==<<.-NASCTB>/2>-1 ;MAXIMUM # NON-ASCII CHARACTERS + +.EVEN + +; CHAR NORMAL SHIFT LOCK SHIFT&LOCK TOP + +XTAB: +KBDKEY 0, -2, -2, -2, -2, -2 ;BREAK +KBDKEY 1, -1, -1, -1, -1, -1 ;ESCAPE +KBDKEY 2, '1, '!, '1, '!, '! +KBDKEY 3, '2, '", '2, '", '" +KBDKEY 4, '3, '#, '3, '#, '# +KBDKEY 5, '4, '$, '4, '$, '$ +KBDKEY 6, '5, '%, '5, '%, '% +KBDKEY 7, '6, '&, '6, '&, '& +KBDKEY 10, '7, '', '7, '', '' +KBDKEY 11, '8, '(, '8, '(, '( +KBDKEY 12, '9, '), '9, '), ') +KBDKEY 13, '0, '_, '0, '_, '_ +KBDKEY 14, '-, '=, '-, '=, '= +KBDKEY 15, '@, '`, '@, '`, '` +KBDKEY 16, '^, '~, '^, '~, '~ +KBDKEY 17, 10, 10, 10, 10, 10 ;BACK SPACE +KBDKEY 20, -13, -13, -13, -13, -13 ;CALL +KBDKEY 21, -3, -3, -3, -3, -3 ;CLEAR +KBDKEY 22, 11, 11, 11, 11, 11 ;TAB +KBDKEY 23, 33, 33, 33, 33, 33 ;ALT-MODE +KBDKEY 24, 'q, 'Q, 'Q, 'Q, 4, ;and +KBDKEY 25, 'w, 'W, 'W, 'W, 37 ;or +KBDKEY 26, 'e, 'E, 'E, 'E, 22 ;intersection +KBDKEY 27, 'r, 'R, 'R, 'R, 23 ;union +KBDKEY 30, 't, 'T, 'T, 'T, 20 ;subset +KBDKEY 31, 'y, 'Y, 'Y, 'Y, 21 ;superset +KBDKEY 32, 'u, 'U, 'U, 'U, 5 ;not +KBDKEY 33, 'i, 'I, 'I, 'I, 26 ;xor +KBDKEY 34, 'o, 'O, 'O, 'O, 1 ;down arrow +KBDKEY 35, 'p, 'P, 'P, 'P, 13 ;up arrow +KBDKEY 36, '[, '{, '[, '{, '{ +KBDKEY 37, '], '}, '], '}, '} +KBDKEY 40, '\, '|, '\, '|, '| +KBDKEY 41, '/, 16, '/, 16, 16 ;infinity +KBDKEY 42, -4, -6, -4, -6, -6 ;plus-minus, delta +KBDKEY 43, -5, -7, -5, -7, -7 ;circle-plus, gamma +KBDKEY 44, 14, 14, 14, 14, 14 ;form +KBDKEY 45, 13, 13, 13, 13, 13 ;vertical tab +KBDKEY 46, 177, 177, 177, 177, 177 ;rubout +KBDKEY 47, 'a, 'A, 'A, 'A, 34 ;.leq. +KBDKEY 50, 's, 'S, 'S, 'S, 35 ;.geq +KBDKEY 51, 'd, 'D, 'D, 'D, 36 ;equivalence +KBDKEY 52, 'f, 'F, 'F, 'F, 17 ;delta (partial derivative) +KBDKEY 53, 'g, 'G, 'G, 'G, 32 ;not equals +KBDKEY 54, 'h, 'H, 'H, 'H, -10 ;HELP!!!!! +KBDKEY 55, 'j, 'J, 'J, 'J, 30 ;back arrow +KBDKEY 56, 'k, 'K, 'K, 'K, 31 ;forward arrow +KBDKEY 57, 'l, 'L, 'L, 'L, 27 ;both ways arrow +KBDKEY 60,<';>, '+,<';>, '+, '+ +KBDKEY 61, ':, '*, ':, '*, '* +KBDKEY 62, 15, 15, 15, 15, 15 ;carriage return +KBDKEY 63, 12, 12, 12, 12, 12 ;line feed +KBDKEY 64, 37, 37, 37, 37, 37 ;next, back gives ^_ +;KBDKEY 64, -12, -11, -12, -11, -11 ;next, back +KBDKEY 65, 'z, 'Z, 'Z, 'Z, 2 ;alpha +KBDKEY 66, 'x, 'X, 'X, 'X, 3 ;beta +KBDKEY 67, 'c, 'C, 'C, 'C, 6 ;epsilon +KBDKEY 70, 'v, 'V, 'V, 'V, 10 ;lambda +KBDKEY 71, 'b, 'B, 'B, 'B, 7 ;pi +KBDKEY 72, 'n, 'N, 'N, 'N, 24 ;for all +KBDKEY 73, 'm, 'M, 'M, 'M, 25 ;there exists +KBDKEY 74,<',>, '<,<',>, '<, '< +KBDKEY 75, '., '>, '., '>, '> +KBDKEY 76, '/, '?, '/, '?, '? +KBDKEY 77, 40, 40, 40, 40, 40 ;space + +.SBTTL FONT MACROS AND DEFINITION + +.IIF E FONTSW,CTAB==0 +.IF NE FONTSW +FNTORG==. + .MACRO CTBENT A + .XCREF ...'A + ...'A + .ENDM + +CTAB: .REPT 200 + .NLIST + CTBENT \.RPCNT + .LIST + .ENDR + ...200 ;THIS CHAR IS A BLOB FOR CURSORS. + +.MACRO FONT A +.NLIST +....==0 +...==1_GRIDWD + +.IRPC CHR,A +...==..._<-1> +.IF NB CHR +....==....!... +.ENDC +.ENDM + +.IF NE ...-1 +ERROR \CURCHR +.ENDC + +;...FOO==%XLIST +;.REPT ...FOO +;.LIST +;.ENDR +.BYTE .... +;.XLIST +;%XLIST=...FOO +.LIST +.ENDM + +.MACRO CDEF A +.NLIST +CURCHR==''A +CDEF1 \CURCHR +.LIST +.ENDM + +.MACRO CDEF1 A +.NLIST +.XCREF ...'A +CURCHR==A +;...FOO==%XLIST +;.REPT ...FOO +;.LIST +;.ENDR +...'A==. +;.XLIST +;%XLIST=...FOO + +.LIST +.ENDM + +.MACRO ERROR NUM +.IF1 +.ERROR ;FONT LOSSAGE NUM +.ENDC +.ENDM +.ENDC +.XLIST +.IF NE FONTSW +.IF NE FONTMS +.XCREF CURCHR,FONT,CDEF1,CDEF + +CDEF1 0 +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT < *** > +FONT < *** > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 1 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* * *> +FONT < *** > +FONT < * > +FONT < > +FONT < > + +CDEF1 2 +FONT < > +FONT < > +FONT < > +FONT < ** *> +FONT <* * > +FONT <* * > +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF1 3 +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <**** > +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > + +CDEF1 4 +FONT < > +FONT < > +FONT < > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 5 +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < *> +FONT < *> +FONT < > +FONT < > +FONT < > + +CDEF1 6 +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < * > +FONT < *** > +FONT < * > +FONT < ** > +FONT < > +FONT < > + +CDEF1 7 +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < * * > +FONT < * * > +FONT < * * > +FONT < * * > +FONT < > +FONT < > + +CDEF1 10 +FONT < > +FONT < > +FONT <* > +FONT <* > +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > + +CDEF1 11 +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 12 +FONT < > +FONT < *** > +FONT < *> +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 13 +FONT < > +FONT < * > +FONT < *** > +FONT <* * *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF1 14 +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT <*****> +FONT < > +FONT < > +FONT < > + +CDEF1 15 +FONT < > +FONT < > +FONT < *** > +FONT <* * *> +FONT <*****> +FONT <* * *> +FONT < *** > +FONT < > +FONT < > +FONT < > + +CDEF1 16 +FONT < > +FONT < > +FONT < > +FONT < * * > +FONT <* * *> +FONT <* * *> +FONT < * * > +FONT < > +FONT < > +FONT < > + +CDEF1 17 +FONT < > +FONT < ** > +FONT < * > +FONT < *> +FONT < ****> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 20 +FONT < > +FONT < > +FONT < ****> +FONT <* > +FONT <* > +FONT <* > +FONT < ****> +FONT < > +FONT < > +FONT < > + +CDEF1 21 +FONT < > +FONT < > +FONT <**** > +FONT < *> +FONT < *> +FONT < *> +FONT <**** > +FONT < > +FONT < > +FONT < > + +CDEF1 22 +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 23 +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 24 +FONT < > +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT < * * > +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF1 25 +FONT < > +FONT <*****> +FONT < *> +FONT < *> +FONT < ****> +FONT < *> +FONT < *> +FONT <*****> +FONT < > +FONT < > + +CDEF1 26 +FONT < > +FONT < > +FONT < *** > +FONT <** **> +FONT <* * *> +FONT <** **> +FONT < *** > +FONT < > +FONT < > +FONT < > + +CDEF1 27 +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > + +CDEF1 30 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF1 31 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF1 32 +FONT < > +FONT < *> +FONT < * > +FONT <*****> +FONT < * > +FONT <*****> +FONT < * > +FONT <* > +FONT < > +FONT < > + +CDEF1 33 +FONT < > +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF1 34 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < *** > +FONT < > +FONT < > + +CDEF1 35 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < *** > +FONT < > +FONT < > + +CDEF1 36 +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > + +CDEF1 37 +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < * > +FONT < > +FONT < > + +CDEF <"> +FONT < * * > +FONT < * * > +FONT < * * > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <#> +FONT < > +FONT < > +FONT < * * > +FONT <*****> +FONT < * * > +FONT < * * > +FONT <*****> +FONT < * * > +FONT < > +FONT < > + +CDEF <$> +FONT < * > +FONT < *** > +FONT <* * *> +FONT <* * > +FONT < *** > +FONT < * *> +FONT <* * *> +FONT < *** > +FONT < * > +FONT < > + +CDEF <%> +FONT < > +FONT <*****> +FONT <** *> +FONT < * > +FONT < * > +FONT < * > +FONT <* **> +FONT <* **> +FONT < > +FONT < > + +CDEF <&> +FONT < > +FONT < * > +FONT <* * > +FONT <* * > +FONT < * > +FONT <* * *> +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF <'> +FONT < ** > +FONT < ** > +FONT <** > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <(> +FONT < > +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > +FONT < > + +CDEF <)> +FONT < > +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > +FONT < > + +CDEF <*> +FONT < > +FONT < * > +FONT <* * *> +FONT < *** > +FONT < * > +FONT < *** > +FONT <* * *> +FONT < * > +FONT < > +FONT < > + +CDEF <+> +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF <,> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT <** > +FONT < > + +CDEF <-> +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <.> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < > +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > +FONT < > +FONT < > + +CDEF 0 +FONT < > +FONT < *** > +FONT <* *> +FONT <* **> +FONT <* * *> +FONT <** *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 1 +FONT < > +FONT < * > +FONT < ** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *** > +FONT < > +FONT < > + +CDEF 2 +FONT < > +FONT < *** > +FONT <* *> +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT <*****> +FONT < > +FONT < > + +CDEF 3 +FONT < > +FONT < *** > +FONT <* *> +FONT < *> +FONT < ** > +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 4 +FONT < > +FONT < * > +FONT < ** > +FONT < * * > +FONT <* * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF 5 +FONT < > +FONT <*****> +FONT <* > +FONT <**** > +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 6 +FONT < > +FONT < ** > +FONT < * > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 7 +FONT < > +FONT <*****> +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF 8 +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 9 +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < * > +FONT < ** > +FONT < > +FONT < > + +CDEF <:> +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < > + +CDEF <;> +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < ** > +FONT < ** > +FONT <** > +FONT < > + +CDEF1 74 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF <=> +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 76 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < *** > +FONT <* *> +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < * > +FONT < > +FONT < > + +CDEF <@> +FONT < > +FONT < *** > +FONT <* *> +FONT <* ***> +FONT <* * *> +FONT <* ***> +FONT <* > +FONT < *** > +FONT < > +FONT < > + +CDEF A +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF B +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT < > +FONT < > + +CDEF C +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT <* > +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF D +FONT < > +FONT <**** > +FONT < * *> +FONT < * *> +FONT < * *> +FONT < * *> +FONT < * *> +FONT <**** > +FONT < > +FONT < > + +CDEF E +FONT < > +FONT <*****> +FONT <* > +FONT <* > +FONT <**** > +FONT <* > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF F +FONT < > +FONT <*****> +FONT <* > +FONT <* > +FONT <**** > +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF G +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT <* **> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF H +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF I +FONT < > +FONT < *** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *** > +FONT < > +FONT < > + +CDEF J +FONT < > +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF K +FONT < > +FONT <* *> +FONT <* * > +FONT <* * > +FONT <** > +FONT <* * > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF L +FONT < > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF M +FONT < > +FONT <* *> +FONT <** **> +FONT <* * *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF N +FONT < > +FONT <* *> +FONT <* *> +FONT <** *> +FONT <* * *> +FONT <* **> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF O +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF P +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF Q +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF R +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* * > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF S +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT < *** > +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF T +FONT < > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF U +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF V +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF W +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <** **> +FONT <* *> +FONT < > +FONT < > + +CDEF X +FONT < > +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF Y +FONT < > +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF Z +FONT < > +FONT <*****> +FONT < *> +FONT < * > +FONT <*****> +FONT < * > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF <[> +FONT < ***> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < ***> +FONT < > + +CDEF <\> +FONT < > +FONT < > +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > +FONT < > +FONT < > + +CDEF <]> +FONT <*** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <*** > +FONT < > + +CDEF <^> +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <_> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> + +CDEF <`> +FONT < ** > +FONT < ** > +FONT < **> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF a +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT < *> +FONT < ****> +FONT <* *> +FONT < ****> +FONT < > +FONT < > + +CDEF b +FONT < > +FONT <* > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <**** > +FONT < > +FONT < > + +CDEF c +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT < ****> +FONT < > +FONT < > + +CDEF d +FONT < > +FONT < *> +FONT < *> +FONT < ****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < > +FONT < > + +CDEF e +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <**** > +FONT <* > +FONT < *** > +FONT < > +FONT < > + +CDEF f +FONT < > +FONT < ** > +FONT < * *> +FONT < * > +FONT <*** > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF g +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < *** > + +CDEF h +FONT < > +FONT <* > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF i +FONT < > +FONT < > +FONT < * > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF j +FONT < > +FONT < > +FONT < *> +FONT < > +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > + +CDEF k +FONT < > +FONT <* > +FONT <* > +FONT <* *> +FONT <* * > +FONT <*** > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF l +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF m +FONT < > +FONT < > +FONT < > +FONT <** * > +FONT <* * *> +FONT <* * *> +FONT <* * *> +FONT <* * *> +FONT < > +FONT < > + +CDEF n +FONT < > +FONT < > +FONT < > +FONT <* ** > +FONT <** *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF o +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF p +FONT < > +FONT < > +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > + +CDEF q +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < *> + +CDEF r +FONT < > +FONT < > +FONT < > +FONT <* ** > +FONT <** *> +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF s +FONT < > +FONT < > +FONT < > +FONT < ****> +FONT <* > +FONT < *** > +FONT < *> +FONT <**** > +FONT < > +FONT < > + +CDEF t +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT < **> +FONT < > +FONT < > + +CDEF u +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF v +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF w +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <* * *> +FONT < * * > +FONT < > +FONT < > + +CDEF x +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > + +CDEF y +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT <* > + +CDEF z +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < * > +FONT < *** > +FONT < * > +FONT <*****> +FONT < > +FONT < > + +CDEF1 173 +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > + +CDEF1 174 +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > + +CDEF1 175 +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > + +CDEF1 176 +FONT < ** *> +FONT <* ** > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 177 +FONT < * > +FONT < * *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* * > +FONT < * > +FONT < > + +CDEF1 200 ;BLOB CHARACTER FOR CURSORS +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> + +.ENDC ;.IF NE FONTMS + +.IF E FONTMS +...0==. +.BYTE 000,000,000,016,016,016,000,000,000,000 +...1==. +.BYTE 000,004,004,004,004,025,016,004,000,000 +...2==. +.BYTE 000,000,000,015,022,022,022,015,000,000 +...3==. +.BYTE 000,000,000,016,021,036,021,036,020,020 +...4==. +.BYTE 000,000,000,004,012,021,000,000,000,000 +...5==. +.BYTE 000,000,000,000,037,001,001,000,000,000 +...6==. +.BYTE 000,000,000,006,010,016,010,006,000,000 +...7==. +.BYTE 000,000,000,037,012,012,012,012,000,000 +...10==. +.BYTE 000,000,020,020,010,004,012,021,000,000 +...11==. +.BYTE 000,021,012,004,012,021,021,016,000,000 +...12==. +.BYTE 000,016,001,002,004,012,021,016,000,000 +...13==. +.BYTE 000,004,016,025,004,004,004,004,000,000 +...14==. +.BYTE 000,004,004,037,004,004,037,000,000,000 +...15==. +.BYTE 000,000,016,025,037,025,016,000,000,000 +...16==. +.BYTE 000,000,000,012,025,025,012,000,000,000 +...17==. +.BYTE 000,014,002,001,017,021,021,016,000,000 +...20==. +.BYTE 000,000,017,020,020,020,017,000,000,000 +...21==. +.BYTE 000,000,036,001,001,001,036,000,000,000 +...22==. +.BYTE 000,000,016,021,021,021,000,000,000,000 +...23==. +.BYTE 000,000,021,021,021,016,000,000,000,000 +...24==. +.BYTE 000,021,021,037,021,012,012,004,000,000 +...25==. +.BYTE 000,037,001,001,017,001,001,037,000,000 +...26==. +.BYTE 000,000,016,033,025,033,016,000,000,000 +...27==. +.BYTE 000,004,002,037,002,004,010,037,010,004 +...30==. +.BYTE 000,000,004,010,037,010,004,000,000,000 +...31==. +.BYTE 000,000,004,002,037,002,004,000,000,000 +...32==. +.BYTE 000,001,002,037,004,037,010,020,000,000 +...33==. +.BYTE 000,004,004,012,021,012,004,004,000,000 +...34==. +.BYTE 000,002,004,010,004,002,000,016,000,000 +...35==. +.BYTE 000,010,004,002,004,010,000,016,000,000 +...36==. +.BYTE 000,000,037,000,037,000,037,000,000,000 +...37==. +.BYTE 000,000,000,021,012,004,000,000,000,000 +...40==. +.BYTE 000,000,000,000,000,000,000,000,000,000 +...41==. +.BYTE 000,004,004,004,004,004,000,004,000,000 +...42==. +.BYTE 012,012,012,000,000,000,000,000,000,000 +...43==. +.BYTE 000,000,012,037,012,012,037,012,000,000 +...44==. +.BYTE 004,016,025,024,016,005,025,016,004,000 +...45==. +.BYTE 000,037,031,002,004,010,023,023,000,000 +...46==. +.BYTE 000,010,024,024,010,025,022,015,000,000 +...47==. +.BYTE 014,014,030,000,000,000,000,000,000,000 +...50==. +.BYTE 000,001,002,004,004,004,002,001,000,000 +...51==. +.BYTE 000,020,010,004,004,004,010,020,000,000 +...52==. +.BYTE 000,004,025,016,004,016,025,004,000,000 +...53==. +.BYTE 000,000,004,004,037,004,004,000,000,000 +...54==. +.BYTE 000,000,000,000,000,000,014,014,030,000 +...55==. +.BYTE 000,000,000,000,037,000,000,000,000,000 +...56==. +.BYTE 000,000,000,000,000,000,014,014,000,000 +...57==. +.BYTE 000,000,001,002,004,010,020,000,000,000 +...60==. +.BYTE 000,016,021,023,025,031,021,016,000,000 +...61==. +.BYTE 000,004,014,004,004,004,004,016,000,000 +...62==. +.BYTE 000,016,021,001,002,004,010,037,000,000 +...63==. +.BYTE 000,016,021,001,006,001,021,016,000,000 +...64==. +.BYTE 000,002,006,012,022,037,002,002,000,000 +...65==. +.BYTE 000,037,020,036,001,001,021,016,000,000 +...66==. +.BYTE 000,006,010,020,036,021,021,016,000,000 +...67==. +.BYTE 000,037,001,002,002,004,004,004,000,000 +...70==. +.BYTE 000,016,021,021,016,021,021,016,000,000 +...71==. +.BYTE 000,016,021,021,017,001,002,014,000,000 +...72==. +.BYTE 000,000,000,014,014,000,014,014,000,000 +...73==. +.BYTE 000,000,000,014,014,000,014,014,030,000 +...74==. +.BYTE 000,000,002,004,010,004,002,000,000,000 +...75==. +.BYTE 000,000,000,037,000,037,000,000,000,000 +...76==. +.BYTE 000,000,010,004,002,004,010,000,000,000 +...77==. +.BYTE 000,016,021,002,004,004,000,004,000,000 +...100==. +.BYTE 000,016,021,027,025,027,020,016,000,000 +...101==. +.BYTE 000,016,021,021,037,021,021,021,000,000 +...102==. +.BYTE 000,036,021,021,036,021,021,036,000,000 +...103==. +.BYTE 000,016,021,020,020,020,021,016,000,000 +...104==. +.BYTE 000,036,011,011,011,011,011,036,000,000 +...105==. +.BYTE 000,037,020,020,036,020,020,037,000,000 +...106==. +.BYTE 000,037,020,020,036,020,020,020,000,000 +...107==. +.BYTE 000,016,021,020,020,023,021,016,000,000 +...110==. +.BYTE 000,021,021,021,037,021,021,021,000,000 +...111==. +.BYTE 000,016,004,004,004,004,004,016,000,000 +...112==. +.BYTE 000,001,001,001,001,001,021,016,000,000 +...113==. +.BYTE 000,021,022,024,030,024,022,021,000,000 +...114==. +.BYTE 000,020,020,020,020,020,020,037,000,000 +...115==. +.BYTE 000,021,033,025,021,021,021,021,000,000 +...116==. +.BYTE 000,021,021,031,025,023,021,021,000,000 +...117==. +.BYTE 000,016,021,021,021,021,021,016,000,000 +...120==. +.BYTE 000,036,021,021,036,020,020,020,000,000 +...121==. +.BYTE 000,016,021,021,021,025,022,015,000,000 +...122==. +.BYTE 000,036,021,021,036,024,022,021,000,000 +...123==. +.BYTE 000,016,021,020,016,001,021,016,000,000 +...124==. +.BYTE 000,037,004,004,004,004,004,004,000,000 +...125==. +.BYTE 000,021,021,021,021,021,021,016,000,000 +...126==. +.BYTE 000,021,021,021,021,012,012,004,000,000 +...127==. +.BYTE 000,021,021,021,021,025,033,021,000,000 +...130==. +.BYTE 000,021,021,012,004,012,021,021,000,000 +...131==. +.BYTE 000,021,021,012,004,004,004,004,000,000 +...132==. +.BYTE 000,037,001,002,037,010,020,037,000,000 +...133==. +.BYTE 007,004,004,004,004,004,004,004,007,000 +...134==. +.BYTE 000,000,020,010,004,002,001,000,000,000 +...135==. +.BYTE 034,004,004,004,004,004,004,004,034,000 +...136==. +.BYTE 004,012,021,000,000,000,000,000,000,000 +...137==. +.BYTE 000,000,000,000,000,000,000,000,000,037 +...140==. +.BYTE 006,006,003,000,000,000,000,000,000,000 +...141==. +.BYTE 000,000,000,016,001,017,021,017,000,000 +...142==. +.BYTE 000,020,020,036,021,021,021,036,000,000 +...143==. +.BYTE 000,000,000,016,021,020,020,017,000,000 +...144==. +.BYTE 000,001,001,017,021,021,021,017,000,000 +...145==. +.BYTE 000,000,000,016,021,036,020,016,000,000 +...146==. +.BYTE 000,006,011,010,034,010,010,010,000,000 +...147==. +.BYTE 000,000,000,016,021,021,021,017,001,016 +...150==. +.BYTE 000,020,020,036,021,021,021,021,000,000 +...151==. +.BYTE 000,000,004,000,004,004,004,004,000,000 +...152==. +.BYTE 000,000,001,000,001,001,001,001,021,016 +...153==. +.BYTE 000,020,020,021,022,034,022,021,000,000 +...154==. +.BYTE 000,004,004,004,004,004,004,004,000,000 +...155==. +.BYTE 000,000,000,032,025,025,025,025,000,000 +...156==. +.BYTE 000,000,000,026,031,021,021,021,000,000 +...157==. +.BYTE 000,000,000,016,021,021,021,016,000,000 +...160==. +.BYTE 000,000,000,036,021,021,021,036,020,020 +...161==. +.BYTE 000,000,000,016,021,021,021,017,001,001 +...162==. +.BYTE 000,000,000,026,031,020,020,020,000,000 +...163==. +.BYTE 000,000,000,017,020,016,001,036,000,000 +...164==. +.BYTE 000,004,004,037,004,004,004,003,000,000 +...165==. +.BYTE 000,000,000,021,021,021,021,016,000,000 +...166==. +.BYTE 000,000,000,021,021,021,012,004,000,000 +...167==. +.BYTE 000,000,000,021,021,025,025,012,000,000 +...170==. +.BYTE 000,000,000,021,012,004,012,021,000,000 +...171==. +.BYTE 000,000,000,021,021,021,012,004,010,020 +...172==. +.BYTE 000,000,000,037,002,016,010,037,000,000 +...173==. +.BYTE 001,002,002,002,004,002,002,002,001,000 +...174==. +.BYTE 004,004,004,004,004,004,004,004,004,004 +...175==. +.BYTE 020,010,010,010,004,010,010,010,020,000 +...176==. +.BYTE 015,026,000,000,000,000,000,000,000,000 +...177==. +.BYTE 002,005,004,004,004,004,004,024,010,000 +...200==. +.BYTE 037,037,037,037,037,037,037,037,037,037 +.ENDC ;.IF E FONTMS +.LIST + +BLOB=...200 ;BLOB IS THE CHAR THAT COVERS ENTIRE CHARACTER AREA. + +.IIF E FONTSW,.=.+3000 ;APPROXIMATE SIZE OF FONT + +REPORT FONT SIZE=,\.-FNTORG +FNTEND==. +.NLIST +.ENDC ;.IF NE FONTSW +.LIST + +.SBTTL LINE EDITOR AND PAGE PRINTER VARIABLES +VARORG==. + +.MACRO ...TEN +.=<.+3>&<-4> +.ENDM + +;LINE EDITOR VARIABLE BLOCK FORMAT: +;THIS DOESN'T REALLY HAVE ANYTHING TO WITH LINE-EDITING. THIS BLOCK +;CONTAINS MOST OF THE VARIABLES FOR EACH TV-CHANNEL (OR VIRTUAL TTY), +;COMBINING THE OLD IDEAS OF DPY BUFFER, LINE EDITOR, AND PAGE PRINTER. +;THERE IS ALSO A TV-BUFFER NUMBER, WHICH GOES IN THE CREG, AND INDEXES +;SOME ARRAYS ON THE LAST PAGE, A DPY CHANNEL # WHICH = A PDP10 TTY # MINUS NF11TY +;AND INDEXES SOME 11-10 SHARED ARRAYS, AND A KBD# WHICH IS A HARDWARE KEYBOARD +;NUMBER AND INDEXES SOME ARRAYS ON THE LAST PAGE. + +LEDFLT: .OFFSET -. +;FIRST COMES THE 10-TO-11 DPY OUTPUT BUFFER. NOTE THAT THE "DEFAULT VALUES +;FOR THIS PART ARE NOT USED IN INITIALIZATION. +DPY10B:: .=.+2 ;WORD PDP-10 IS HACKING (USED FOR INITIALIZATION ONLY) +DPY11B:: .=.+2 ;WORD PDP-11 IS HACKING +DPYFS1:: .=.+2 ;WASTED WORD. +DPYLGL:: .=.+2 ;HIGHEST LEGAL BUFFER CELL +DPYSIZ:: .=.+2 ;SIZE OF DATA AREA +DPYFS:: .=.+2 ;NOT USED +...TEN +DPDATA:: .BLKB DPSIZE ;DATA AREA OF BUFFER. + +LECC:: TVLO ;ADDRESS OF CURSOR +LEPHS:: 20-CHRWD ;PHASE OF CURSOR +LEX:: -BITPL ;X POSITON OF LE CURSOR +LECREG:: .BYTE -1 ;CONSOLE REGISTER FOR THIS LE DISPLAY + .BYTE 0 ;UNUSED +...TEN + +LEZER0:: 0 ;FAKE LINE BUFFER HEADER (SENT TO PDP10 IN RESPONSE TO ECOFLG) +LEZER1:: 0 +LEBUF:: 0 ;CURRENT TEXT BUFFER +LELIST:: 0 ;KEYBOARD BUFFER CHAIN +LECHN:: -1 ;DPY CHANNEL NUMBER, SET UP AT INIT TIME. +LEKBD:: -1 ;KEYBOARD DRIVING THIS LINE EDITOR +LEY:: -NLINS ;Y COORDINATE OF LINE EDITOR DISPLAY +LELCC:: TVLO ;ADDRESS OF START OF CURRENT CHARACTER LINE, IN VIDEO BUFFER. +;LEFONT:: CTAB ;FONT FOR WRITING WITH IN THIS L.E. (NOT USED) +LECPC:: 0 ;COROUTINE PC SAVED BY GETCHC. +LESVB:: 0 ;VALUE OF B SAVED OVER CALL TO GETCHC. +LEFREE:: LBCHRS ;FREE CHARACTER COUNT +LECHR:: 0 ;POINTS AT FREE CHARACTER IN BUFFER +;LEBLNK:: 0 ;LINE EDITOR BLINKER (NOT USED, THERE IS NO LINE EDITOR) +LERPT:: 0 ;0 NORMAL, -1 => INDEFINITE REPEAT, ELSE REPEAT COUNT. + ;REPEAT REFERS TO REPEAT-ACTION ON AN INPUT CHARACTER. +LELSTA:: 0 ;A AND B AT MOST RECENT CALL TO PUTCHR. +LELSTB:: 0 ;FOR THE SAKE OF REPEAT-ACTION ON INPUT. +...TEN +LELEN:: .OFFSET 0 + +;LINE EDITOR VARIABLE AREAS. + +TENWRD +;HERE WE ASSEMBLE IN THE "DPY BUFFERS". +LEUVAR: .REPT MAXTV + .+DPDATA + .-2+DPDATA + 0 + .-6+DPDATA+DPSIZE-2 + DPSIZE + 0 + .BLKB LELEN-DPDATA + .ENDR +LEUEND==. + +;THE WHO-LINE LINE EDITOR IS DIFFERENT AND APART FROM ALL THE REST + +WHOPP: .=.+LELEN + +;CLOCK QUEUE ENTRY + + .OFFSET -. ;CLOCK QUEUE ENTRY +CQNEXT:: .=.+2 ;CDR OF QUEUE +CQTIME:: .=.+2 ;HIGH ORDER OF TIME +CQTIM1:: .=.+2 ;LOW ORDER +CQROUT:: .=.+2 ;ROUTINE TO CALL AT CLOCK LEVEL +CQARG:: .=.+2 ;ARGUMENT FOR CLOCK LEVEL ROUTINE +CQLEN:: .OFFSET 0 + + + + .OFFSET -. ;LINE BUFFER HEADER AREA + ;DON'T ADD NEW VARS WITHOUT CHANGING PDP10 CODE + ;IN TT11IN. +LHFLAG:: .=.+2 ;0=>FREE, POS=>BUSY, NEG=>ACTIVE. +LHZERO:: .=.+2 ;BETTER BE ZERO SO THAT PDP-10 CAN TEST LHFLAG +LHNEXT:: .=.+2 ;NEXT BUFFER ON RING OF TWO FOR THIS TTY +LHALST:: .=.+2 ;NEXT BUFFER ON LIST OF ACTIVE BUFFERS. +LHCHN:: .=.+2 ;PDP-10 LINE NUMBER (TTY NUMBER MINUS NF11TY). +LHFS:: .=.+2 ;CHAINS FREE STORAGE BLOCKS +LHQUED:: .=.+2 ;NON-ZERO => THIS BUFFER CLOCK QUEUED FOR ACTIVATION (SEE QBFR) +...TEN +LHLEN:: .OFFSET 0 + + .OFFSET -. ;BLINKER VARIABLES +BLNEXT:: 0 ;NEXT BLINKER ON LIST +BLCURS:: 0 ;POINTS AT CURSOR VARIABLES +BLON:: .BYTE 0 ;PHASE; 0=INVISIBLE, 377=VISIBLE +BLCHAR:: .BYTE 177 ;UNUSED +BLLEN:: .OFFSET 0 + +BLKVAR: .=.+ + .EVEN + + .OFFSET -. ;USER WHO LINE +WHJOB:: .=.+2 ;job # +WHJOB1:: .=.+2 ;if negative then clear who line +WHMODE:: .=.+2 ;mode + ;-1=>who line is off + ; 0=>follow keyboard + ; 1=>freeze + ; 2=>next higher (when PDP-10 sees this state, it searches + ; user variables for next higher job index number with same + ; uname. When it finds it, it stores the number in job # + ; and changes mode to 1 + ; 3=>next lower + ;any other=>system who line +WHMOD1:: .=.+2 ;pads WHMODE +WHUNAM:: .=.+2 ;uname in sixbit (left 18 bits in first two words, right in next two) +WHUNM1:: .=.+2 +WHUNM2:: .=.+2 +WHUNM3:: .=.+2 +WHJNAM:: .=.+2 ;jname in sixbit +WHJNM1:: .=.+2 +WHJNM2:: .=.+2 +WHJNM3:: .=.+2 +WHSNAM:: .=.+2 ;sname in sixbit +WHSNM1:: .=.+2 +WHSNM2:: .=.+2 +WHSNM3:: .=.+2 +WHSTAT:: .=.+2 ;status in sixbit, 0=>job does not exist +WHSTA1:: .=.+2 +WHSTA2:: .=.+2 +WHSTA3:: .=.+2 +WHJ%RT:: .=.+2 ;job % run time +WHJTRT:: .=.+2 ;job total run time (in tenth's of seconds) +WHRPAG:: .=.+2 ;job real pages (swapped in) +WHTPAG:: .=.+2 ;job total pages +WHO1:: .=.+2 ;user who mode control word +WHO1A:: .=.+2 +WHO2:: .=.+2 ;first user who line var +WHO2A:: .=.+2 +WHO2B:: .=.+2 +WHO2C:: .=.+2 +WHO3:: .=.+2 ;second user who line var +WHO3A:: .=.+2 +WHO3B:: .=.+2 +WHO3C:: .=.+2 +...TEN + .=.+30 ;EXTRA SPACE SO NEW HACKS CAN SAFELY BE PUT IN PDP10. +WHLEN:: .OFFSET 0 + +;USER WHO LINE VARIABLES + +TENWRD + +WHVARS: .=.+ + +.SBTTL MISCELLANEOUS TABLES +MISORG==. + +;KEYBOARD/VIDEO SWITCH DEFAULTS +;INDEXED BY KBD #, GIVES NEAREST VIDEO SWITCH OUTPUT, -1=>NO DEFAULT + +KBDVSW: .BYTE 0 ; 0 809 FAHLMAN, HOLLOWAY, KNIGHT + .BYTE 23 ; 1 810 LAVIN, KUIPERS, MILLER + .BYTE 24 ; 2 919 Very Small Data Bases NORTH (FAR END) + .BYTE 20 ; 3 812 YVONNE + .BYTE 6 ; 4 813 HEWITT + .BYTE 7 ; 5 814 SUSSMAN + .BYTE 3 ; 6 808 FREILING, ULLMAN + .BYTE -1 ; 7 + .BYTE 4 ;10 817 JABARI + .BYTE -1 ;11 + .BYTE -1 ;12 + .BYTE 10 ;13 819 GOLDSTEIN + .BYTE 1 ;14 820 MINSKY + .BYTE -1 ;15 + .BYTE -1 ;16 + .BYTE 11 ;17 821A MARR + .BYTE -1 ;20 + .BYTE 2 ;21 824 RICH, DEKLEER + .BYTE 5 ;22 825 Sjoberg + .BYTE 26 ;23 826 Fredkin + .BYTE 31 ;24 815 Horn + .BYTE -1 ;25 + .BYTE -1 ;26 + .BYTE -1 ;27 + .BYTE 15 ;30 925 MOON'S REFRIGERATOR + .BYTE 16 ;31 902 TAENZER, MASON + .BYTE 17 ;32 919 Very Small Data losers + .BYTE 14 ;33 334 EDWARDS, LEBEL + .BYTE 13 ;34 913 BAISLEY, GREENBLATT + .BYTE 12 ;35 914 COHEN, GOSPER, ETC. + .BYTE 21 ;36 912 9TH FLOOR LOUNGE + .BYTE 22 ;37 907 CHESS, LISP MACHINES + .BYTE -1 ;40 906 Lisp Machines + .BYTE 37 ;41 3rd Floor #1 + .BYTE 36 ;42 3rd Floor #2 + .BYTE 35 ;43 3rd Floor #3 + .BYTE 34 ;44 3rd Floor #4 + .BYTE 33 ;45 3rd Floor #5 + .BYTE 30 ;46 3rd Floor #6 + .BYTE -1 ;47 NOT CONNECTED + .BYTE -1 ;50 NOT CONNECTED + .BYTE -1 ;51 NOT CONNECTED + .BYTE -1 ;52 NOT CONNECTED + .BYTE -1 ;53 NOT CONNECTED + .BYTE -1 ;54 NOT CONNECTED + .BYTE -1 ;55 NOT CONNECTED + .BYTE -1 ;56 NOT CONNECTED + .BYTE -1 ;57 NOT CONNECTED + .BYTE -1 ;60 NOT CONNECTED + .BYTE -1 ;61 NOT CONNECTED + .BYTE -1 ;62 NOT CONNECTED + .BYTE -1 ;63 NOT CONNECTED + .BYTE -1 ;64 NOT CONNECTED + .BYTE -1 ;65 NOT CONNECTED + .BYTE -1 ;66 NOT CONNECTED + .BYTE -1 ;67 NOT CONNECTED + .BYTE -1 ;70 NOT CONNECTED + .BYTE -1 ;71 NOT CONNECTED + .BYTE -1 ;72 NOT CONNECTED + .BYTE -1 ;73 NOT CONNECTED + .BYTE -1 ;74 NOT CONNECTED + .BYTE -1 ;75 NOT CONNECTED + .BYTE -1 ;76 NOT CONNECTED + .BYTE -1 ;77 NOT CONNECTED +CHECK KBDVSW,MAXKBD + + +;THIS TABLE SAYS WHICH FLOOR TO CALL THE ELEVATOR TO FOR E + +ELETAB: .BYTE ELKMS8 ; 0 809 FAHLMAN, HOLLOWAY, KNIGHT + .BYTE ELKMS8 ; 1 810 LAVIN, KUIPERS, MILLER + .BYTE ELKMS9 ; 2 919 Very Small Data Bases NORTH (FAR END) + .BYTE ELKMS8 ; 3 812 YVONNE + .BYTE ELKMS8 ; 4 813 HEWITT + .BYTE ELKMS8 ; 5 814 SUSSMAN + .BYTE ELKMS8 ; 6 808 FREILING, ULLMAN + .BYTE 0 ; 7 + .BYTE ELKMS8 ;10 817 JABARI + .BYTE 0 ;11 + .BYTE 0 ;12 + .BYTE ELKMS8 ;13 819 GOLDSTEIN + .BYTE ELKMS8 ;14 820 MINSKY + .BYTE 0 ;15 + .BYTE 0 ;16 + .BYTE ELKMS8 ;17 821A MARR + .BYTE 0 ;20 + .BYTE ELKMS8 ;21 824 RICH, DEKLEER + .BYTE ELKMS8 ;22 825 Sjoberg + .BYTE ELKMS8 ;23 826 Fredkin + .BYTE ELKMS8 ;24 815 Horn + .BYTE 0 ;25 + .BYTE 0 ;26 + .BYTE 0 ;27 + .BYTE ELKMS9 ;30 925 MOON'S REFRIGERATOR + .BYTE ELKMS9 ;31 902 TAENZER, MASON + .BYTE ELKMS9 ;32 919 Very Small Data losers + .BYTE 0 ;33 334 EDWARDS, LEBEL + .BYTE ELKMS9 ;34 913 BAISLEY, GREENBLATT + .BYTE ELKMS9 ;35 914 COHEN, GOSPER, ETC. + .BYTE ELKMS9 ;36 912 9TH FLOOR LOUNGE + .BYTE ELKMS9 ;37 907 CHESS, LISP MACHINES + .BYTE ELKMS9 ;40 906 Lisp Machines + .BYTE 0 ;41 NOT CONNECTED + .BYTE 0 ;42 NOT CONNECTED + .BYTE 0 ;43 NOT CONNECTED + .BYTE 0 ;44 NOT CONNECTED + .BYTE 0 ;45 NOT CONNECTED + .BYTE 0 ;46 NOT CONNECTED + .BYTE 0 ;47 NOT CONNECTED + .BYTE 0 ;50 NOT CONNECTED + .BYTE 0 ;51 NOT CONNECTED + .BYTE 0 ;52 NOT CONNECTED + .BYTE 0 ;53 NOT CONNECTED + .BYTE 0 ;54 NOT CONNECTED + .BYTE 0 ;55 NOT CONNECTED + .BYTE 0 ;56 NOT CONNECTED + .BYTE 0 ;57 NOT CONNECTED + .BYTE 0 ;60 NOT CONNECTED + .BYTE 0 ;61 NOT CONNECTED + .BYTE 0 ;62 NOT CONNECTED + .BYTE 0 ;63 NOT CONNECTED + .BYTE 0 ;64 NOT CONNECTED + .BYTE 0 ;65 NOT CONNECTED + .BYTE 0 ;66 NOT CONNECTED + .BYTE 0 ;67 NOT CONNECTED + .BYTE 0 ;70 NOT CONNECTED + .BYTE 0 ;71 NOT CONNECTED + .BYTE 0 ;72 NOT CONNECTED + .BYTE 0 ;73 NOT CONNECTED + .BYTE 0 ;74 NOT CONNECTED + .BYTE 0 ;75 NOT CONNECTED + .BYTE 0 ;76 NOT CONNECTED + .BYTE 0 ;77 NOT CONNECTED +CHECK ELETAB,MAXKBD + +;CHCREG TABLE, INDEXED BY CHANNEL NUMBER, GIVES TV BUFFER NUMBER. +;NON-WORKING TV BUFFERS SHOULD NOT BE IN THE LIST. +;IF THERE ARE MORE CHANNELS THAN BUFFERS, PUT -1 IN FOR SOME CHANNELS. + +CHCREG: .BYTE 0,1,4,5,6,7,10,11,12,13,14,15,16,17,-1,-1 + + +;VIDEO SWITCH INPUT INDEXED BY DPY #, HIGH ORDER BYTE GIVES SWITCH SECTION + +DPYVSW: 1 ; 0 + 2 ; 1 + 3 ; 2 + 4 ; 3 + 5 ; 4 + 6 ; 5 + 7 ; 6 + 10 ; 7 + 21 ;10 THESE INPUTS ARE IN SECOND SECTION + 22 ;11 + 23 ;12 + 24 ;13 + 11 ;14 1ST SECTION AGAIN + 12 ;15 + 13 ;16 + 14 ;17 +CHECK DPYVSW,MAXTV*2 + +;AUDIO SWITCH TABLES (INDEXED BY KBD #, GIVES AUDIO SWITCH OUTPUT #) + +KBDASW: .BYTE 00 ; 0 + .BYTE 01 ; 1 + .BYTE 02 ; 2 + .BYTE 03 ; 3 + .BYTE 04 ; 4 + .BYTE 05 ; 5 + .BYTE 06 ; 6 + .BYTE 07 ; 7 + .BYTE 10 ;10 + .BYTE 11 ;11 + .BYTE 12 ;12 + .BYTE 13 ;13 + .BYTE 14 ;14 + .BYTE 15 ;15 + .BYTE 16 ;16 + .BYTE 17 ;17 + .BYTE 20 ;20 + .BYTE 21 ;21 + .BYTE 22 ;22 + .BYTE 23 ;23 + .BYTE 24 ;24 + .BYTE 25 ;25 + .BYTE 26 ;26 + .BYTE 27 ;27 + .BYTE 30 ;30 + .BYTE 31 ;31 + .BYTE 32 ;32 + .BYTE 33 ;33 + .BYTE 34 ;34 + .BYTE 35 ;35 + .BYTE 36 ;36 + .BYTE 37 ;37 + .BYTE -1 ;40 + .BYTE -1 ;41 + .BYTE -1 ;42 + .BYTE -1 ;43 + .BYTE -1 ;44 + .BYTE -1 ;45 + .BYTE -1 ;46 + .BYTE -1 ;47 + .BYTE -1 ;50 + .BYTE -1 ;51 + .BYTE -1 ;52 + .BYTE -1 ;53 + .BYTE -1 ;54 + .BYTE -1 ;55 + .BYTE -1 ;56 + .BYTE -1 ;57 + .BYTE -1 ;60 + .BYTE -1 ;61 + .BYTE -1 ;62 + .BYTE -1 ;63 + .BYTE -1 ;64 + .BYTE -1 ;65 + .BYTE -1 ;66 + .BYTE -1 ;67 + .BYTE -1 ;70 + .BYTE -1 ;71 + .BYTE -1 ;72 + .BYTE -1 ;73 + .BYTE -1 ;74 + .BYTE -1 ;75 + .BYTE -1 ;76 + .BYTE -1 ;77 +CHECK KBDASW,MAXKBD + +;POINTER AREA + +TENWRD + +POINTA: ITSWHO + CMDFLG +TENWHO: 0 ;-1=>PDP-10 SHOULD UPDATE WHO LINES +TENWH1: 0 ;FILLS OUT TENWHO + MAXTV ;PUT # OF PDP-10 CHANNELS HERE FOR ITS. + 0 +NF11TY: 0 ;PDP-10 PUTS TTY # OF FIRST CHANNEL HERE. + 0 +QPYDWN: 0 ;THIS NEEDS TO BE READ BY THE 10 FOR LOCK TVQPY CMD. + 0 +.=.+10 ;LEAVE A LITTLE ROOM FOR GROWTH + +;10/11 CHANNEL HEADER AREA + +TENWRD + +CHA==. +KBDFLG: 0 ;KEYBOARD ACTIVATED LIST (SET BY 11 CLEARED BY 10) + 0 ;ALWAYS ZERO +DPYCHN: LEUVAR ;THE CHANNEL VARS BLOCK ADDR +DPYKBD: 0 ;.BYTE KBD #,DPY #, OR -1 FOR FREE CHANNEL. +.REPT MAXTV-1 + LEUVAR+<<.RPCNT+1>*LELEN> + 0 +.ENDR +ECOFLG: 0 +CHNCLS: 0 ;FLAGS DPY CHANNEL AS OPEN (SET TO -1 BY TEN) + .=.+<*4> +WHOLIN: 0 ;POINTS TO WHO LINE VARIABLES FOR THIS CHANNEL + 0 ;NOT USED + .=.+<*4> + +;PDP-10/PDP-10 COMMAND BUFFER + +TENWRD + +CMDFLG: 0 ;0=>TEN CAN WRITE, POSITIVE=>ELEVEN CAN WRITE, NEGATVE=>TEN WON + 0 ;FULL PDP-10 WORD BOUNDARY +CMDBUF: .=.+ ;EACH ARG IN COMMAND BUFFER IS PDP-10 WORD + +;SYSTEM WHO LINE + +TENWRD + +ITSWHO==. +ITSTDP: 0 ;# total # dpy's (read only for PDP-10) +ITSFDP: 0 ;# free dpys (read only for PDP-10) +ITSVER: 0 ;ITS version # +ITSJOB: 0 ;total jobs +ITSCOR: 0 ;total core +ITSRU: 0 ;runnable users +ITSWBJ: 0 ;# jobs swap blocked +ITSJWP: 0 ;# jobs waiting for pages +ITSTRC: 0 ;total runable core +ITSCFU: 0 ;core available for users +ITSDAT: 0 ;date [byte (7) year (4) month (5) day] +ITSDBG: 0 ;system debug flag +ITSTIM: 0 ;time of day (# half seconds since midnight) aligned on PDP-10 word +ITSTI1: 0 ;low order of time +ITSUSR: 0 ;total number of users +ITSFSH: 0 ;fair share in % + +.SBTTL MISCELLANEOUS VARIABLES AND FREE STORAGE + +;CHANNEL USE FLAGS NON-ZERO MEANS CHANNEL IN USE +CHNUSE: .BLKB MAXTV ;BYTES INDEXED BY DPY CHANNEL # + .EVEN + + +;BLINKERS. INDEXED BY TV-BUFFER # (CREG) +BLINKS: .BLKW MAXTV ;ADDRESS OF 1ST BLINKER OF THIS TV'S BLINKER LIST. + +BLKSWT: .BLKB MAXTV ;NONZERO => DON'T DO ANY BLINKING ON THIS TV NOW. + .EVEN + +;BELLS PENDING COUNTS. INDEXED BY TV-BUFFER # +BELCNT: .BLKW MAXTV + + +;PER-KEYBOARD INFORMATION. INDEXED BY KBD#. +KBDLE: .BLKW MAXKBD ;KEYBOARD/LINE EDITOR ASSOCIATION + +KBDESC: .BYTE 0 ;NON-ZERO => KEY HAS BEEN TYPED, READING ARG +KBDARG: .BYTE 0 ;NUMERIC ARGUMENT FOR + .=.+<*2> ;THE ABOVE TWO BYTE ARRAYS ARE INTERLEAVED. + + 0 ;THIS ZERO WORD NEEDED - SEE CLKBR5 +KBDDEF: .BYTE 0 ;DEFAULT VIDEO SOURCE FOR THIS KBD WHEN LOOKING AT ANOTHER +KBDCNT: .BYTE 0 ;COUNTDOWN UNTIL RESET TO DEFAULT VIDEO SOURCE, OR -1 + .=.+<*2> + + +;CLOCK QUEUE + +CLOCKF: 0 ;CLOCK QUEUE FREE LIST +CLOCKQ: 0 ;FIRST ENTRY ON CLOCK QUEUE +CQUEUE: .=.+ + +;MISCELLANEOUS VARIBLES + +FSP: 0 ;POINTS TO LEBUFS FREE SPACE +OLDKMA: 0 ;LAST KMA +BLINK: 0 ;TV-BUFFER # OF NEXT GUY TO BLINK. ALSO, COUNTS CLOCK TICKS + ; UNTIL NEXT BLINK. IT'S PRETTY KLUDGEY, SEE CODE AT CLKLOP. +FBLINK: BLKVAR ;LIST OF FREE BLINKERS +TICKS: 0 ;HIGH ORDER OF TIME +TICKS1: 0 ;LOW ORDER OF TIME +SSCC: .BYTE 0 ;SEMI-SLOW CLOCK COUNTER (WRAPS AROUND EVERY 256./60. SEC) + .BYTE 0 ;UNUSED +QPYSWT: 0 ;INTER LOCK TO SAVE COPY PAPER +BUZSWT: 0 ;INTERLOCK FOR BUZZING 9TH FLOOR DOOR +ELESWT: 0 ;INTERLOCKING THE ELEVATOR +RADIX: 0 ;HOLDS OUTPUT RADIX +VERSE: %FNAM2 ;SOURCE FILE VERSION # +KBDACT: 0 ;KEYBOARD ACTIVE LIST (NOT YET SEEN BY PDP-10) +KBDLAST:0 ;POINTS TO LAST BUFFER ON ACTIVE LIST +KBDTSW: 0 ;NON-ZERO => EXAMINE KBDCNT ARRAY AT SSC LEVEL. +WHOTIM: 0 ;LAST TIME WE DID WHO LINES +WHOFLG: 0 ;DO WHO LINES FLAG +DPYFRE: 0 ;DPY # OF FREE-CONSOLE CHANNEL. +TYMSHR: 0 ;# CLOCK TICKS TO GO BEFORE CHECKING NEXT DPY CHANNEL + +;PATCH AREA +PATCH: .=.+PATL + +;******* TEMPORARY VARIABLES FOR FONT CHECKSUMS ******* +CKSPNT: 0 ;RUNNING POINTER +CKSSUM: 0 ;RUNNING CHECKSUM +CKSSMG: 0 ;GOOD CHECKSUM OF [FNTORG,FNTEND) + +;LINE EDITOR BUFFER RINGS + +TENWRD +NLBUFS==/ + +.IIF LT NLBUFS-, .ERROR NOT ENOUGH LEBUFS +REPORT NLBUFS=,\NLBUFS + +LEBUFS: .=.+> + +REPORT HIGHEST USED=,\. + +.END GO diff --git a/src/system/utape.952 b/src/system/utape.952 new file mode 100755 index 00000000..d41f5fe2 --- /dev/null +++ b/src/system/utape.952 @@ -0,0 +1,2009 @@ +; I T S UTAPE SERVICE ROUTINE + +UTBLKS==3 + +;UT CHANNEL STORAGE + +EBLK +UTCHNT: ;BEG FOR GETSYS (UTAPE) +UTBFP: REPEAT NUTIC+NUTOC,400000,,377 ;L H BUFFER LINK PTR (INPUT PI) + ;RH " " OUTPUT MAIN PROG +UTUSR: ;USER OR -1 IF FREE (LH) +UTUL: REPEAT NUTIC+NUTOC,-1 ;LINK TO CHANNEL ON SAME UTAPE OR -1(RH) +UTDIRP: BLOCK NUTIC+NUTOC ;BYTE POINTER TO UTDIR +UTDBC: BLOCK NUTIC+NUTOC ;RH BLCK COUNT CORRESP WITH UTDIRP + ;L H 3.1 3.5 READ FILE NO 4.9 ERROR 4.5 4.8 ERROR CNT + ;3.6 =0 FORD EXT =1 BACK EXT 3.7 4.2 PUT FILE NO + ;4.4 DELETE ON READ CLOSE +UTBFS: BLOCK NUTIC+NUTOC ;BUFFERS IN USE +UTLSTM: BLOCK NUTIC+NUTOC ; TIME LAST BUF TAKEN BY PROG +UTMBN: BLOCK NUTIC+NUTOC ; MN PROG ACTIVE BFFR NO OR -1,IF NO BUFFER ACIVE (LH) +UTRAC: BLOCK NUTIC+NUTOC+1 ;ACTIVE BUFFER NO PI RH + ;FLAG TO MAIN PROG TP FULL (WRITE) RH + ;SIGN SET =>CHANNEL LOCKED + ;4.8 READ EOF REACHED AT PILEVEL OR CHNL CLOSED + ;EXTRA WORD FOR FILE DIR CHNL + ;4.7 DONT RELOAD AT PI +UTN1=.-NUTIC+1 + BLOCK NUTOC +UTN2=.-NUTIC+1 + BLOCK NUTOC ;NAME OF FILE BEING WRITTEN +UTBKNP=.-NUTIC+1 + BLOCK NUTOC +MPRP: BLOCK NUTIC+NUTOC ;MAIN PRGM BUFFER PNTR +MPRC: BLOCK NUTIC+NUTOC ;CNT REMAINING +UTTNO: BLOCK NUTOC+NUTIC ;TAPE NO (RH) + ;LH CLOSE FLAG WRITE ORG FILE NO READ +UTEOF: BLOCK NUTIC ;END OF FILE CHR + +UTLDD: BLOCK NUTIC+NUTOC+1 ;IF -1, DC IS ACTUALLY SET UP AND TRANSFER CAN + ;BE EXPECTED IN LESS TAH 100 MS. + ;IF D CHANNEL LOCKED FLAG(4.9 UTRAC) WELL BE CHECKED + ;BEFORE GOING TO THE -1 STATE + ;EXTRA WORD FOR DIR CHNL +UTDERR: BLOCK NUTIC+NUTOC+1 ;4.9 ERROR 4.8 ABORT 4.7 UTAPE FULL + +NUTCA: 0 ;NUMBER UTAPE CHANNELS ACTIVE +NUWCA: 0 ;# WRITE CHNLS ACT + +UPCHFS: 0 ;FAIR SHARE BFS PER CHNL + +LUTWBF==40 ;LENGTH OF BLK # PASSING LIST +UTWBF: REPEAT LUTWBF,.+1 ;LIST FOR PASSING BLK NOS FROM M.P. TO PI ON WRITE (INIT FS) + 0 ;TERMINATOR FOR FS LIST +UTWBFS: UTWBF ;FS PNTR + +IFNDEF MXUTBF,MXUTBF==40 ;MAX BUFFERS FOR AN INPUT CHANNEL. + +;TABLE AREAS + +DEFINE TAG A +IRPS TAGX,,A +BBLK +TAGX: 0 +EBLK +TERMIN +TERMIN + +UTCH: ;BEG FOR GETSYS (UTAPE) +TAG ULCTM:, REPEAT NUNITS,-1 ;LAST TIME EUPOS RECOMPUTED + ;IF DG2=0.E. 0 THEN ACT POS =EUPOS+*UDIR +TAG DRTM:, REPEAT NUNITS,177777,,-1 ;177777,,-1 => NO TIMING OP + ;N => DEAD RECKON UNTIL T=N + +TAG UDIR:, BLOCK NUNITS ;0=>STOP -1=>BACK 1=>FORW +IFN NEWDTP, TAG OUDIR:, BLOCK NUNITS ;DIR OF LAST OP +TAG UGOAL:, REPEAT NUNITS,-1;POSIT GOAL OR -1 IF UNIT FREE +TAG EUPOS:, BLOCK NUNITS ;ESTIMATED UNIT POSITION + ;SEE ULCTM IF DGW .NE. 1 +TAG DCHNT:, REPEAT NUNITS,-1;HEAD CHANNEL LIST OF UT OR -1 IF NO CHN ACT +TAG UMEMAD:, IFE NEWDTP,REPEAT NUNITS, BLKO DC, ;GOAL MEMADR-1 + IFN NEWDTP,REPEAT NUNITS,BLKO DTC, +TAG URDWR:, BLOCK NUNITS ;0 READ -1 WRITE(LOADED OPERATION) +TAG DG2:, REPEAT NUNITS,-1;+ => ACCURATE + ;0 => EUPOS FAIRLY ACCURATE + ;-1 => DO NOT DEAD RECKON WITHOUT UTC +TAG UTASS:, REPEAT NUNITS,0 ;0 IF NOT ASSIGNED, SYSTEM NAME IF ASSIGNED +TAG UDIRO:, REPEAT NUNITS,-1;ORGIN OF DIRECTORY +;OR -1 DIR NOT LOADED OR 4.9 DIR LOCKED OR 4.8+4.9 DIR DOUB LOCKED +;4.7 DIR CHANGED +;IF DIR LOCKED, IT MAY BE REFERENCED BUT NOT CHANGED +;4.5=0 => DIR AT LEAST ON WAY IN +;4.4=1 => TAPE IN UBLAT MODE + + +TAG UFLAPF:, BLOCK NUNITS ;4.9 FLAPPING RQSTED OR IN PROGRESS + ;4.8 RQ TO ABORT FLAPPING + ;4.7 DRIVE ACTUALLY ON THE WAY + ;4.6 (TD10 ONLY) 0 PHASE 1 STOP 1 PHASE 1 STOP DONE + ;RH TIME TO STOP AFTER FLAPPED + +TAG ULDCH:, BLOCK NUNITS ;NUMBER OF LOADED CHANNEL IN LH + ;BUFFER NO OF DIR (INDEX INTO IOBFT) IN RH + ;LH 4.9 = LOW PRIORITY POSIT + + +TAG UDPWF:, REPEAT NUNITS,-1 ;DIRECTORY PAWED OVER FLAG + +TAG UMNFB:, BLOCK NUNITS ;MAIN PRGM FREE BLOCKS ON TAPE + +TAG UTERP:, BLOCK NUNITS ;LH ERROR CODE (CONI UTS,) RH # ERRORS + +TAG UMNTR:, BLOCK NUNITS ;UNAME OF LAST JOB TO READ IN DIRECTORY + +SUNIT: 0 ;SELECTED UNIT OR 0 +IFE NEWDTP, SUNITL: 0 ;SAME _ 3 +SMODE: -1 ;-1 POSIT 0 DATA +UIDLE: -1 ;-1 UTAPES COMPLETELY IDLE + +IFN NEWDTP, CUINT: 0 ;-1 CLK HAS CAUSED BREAK +WRITE: 0 ;0 READ -1 WRITE +TAPCNT: 0 +TAP1: 0 +TAP2: 0 +TAP3: 0 +UTTM1: 0 ;UNIT COULD START IN SEARCH LOOP +UTTM2: 0 ;MOST PRESSING UNIT SO FAR +UTTM3: 0 ;TIME FOR ABOVE OR -1 IF NONEî +UTTM4: 0 ;TAPE TO START FLAPPING (FLAG FLAP IN PROG IF NEWDTP=1) +IFE NEWDTP,[ +UTTM5: 0 ;TAPE TO STOP FLAPPING +FLPUNT: 0 +] +UTENB: 0 +LUTOTM: 0 ;TIME OF LAST UT OPER +UTHERR: 0 ;UT HANGUP ERR +USTSW: 0 ;UT START SWITCH +UDCC: 0 ;-1 IF UTAPE HAVE DC FOR BLK CYCLE +UTCHE==.-1 ;END FOR GETSYS (UTAPE) + +BBLK + +;UTAPE CONTINUOUS NON-FILE IO + +AUBL2: CONO PI,UTCON ;DIRECTORY LOCKED, MAYBE ITS BEING FLAPPED + PUSHJ P,UDELAY +AUBLAT: XCTR XRW,[SKIPLE I,(J)] ;GET TAPE NUM, C(AC), SKIP IF NEG OR ZERO + CAIG I,NUNITS ;SKIP IF TOO BIG + PUSHJ P,UTSNMK ;DON'T ALLOW UTAPE HACKERY UNLESS ASSIGNED + POPJ P, ;ERR EXIT, BAD TAPE NUM + CONO PI,UTCOFF + MOVE B,UDIRO(I) + AOJE B,AUBL1 ;DIR NOT IN + TLNN B,10000 + JRST UTCONJ ;NOT IN UBLAT MODE + JUMPL B,AUBL2 +AUBL1: MOVSI B,10000 + MOVEM B,UDIRO(I) + CONO PI,UTCON + JRST POPJ1 + +;.ASSIGN - ASSIGN A DECTAPE UNIT. +AASSIGN:XCTR XR,[MOVE I,(J)] + CAILE I,NUNITS + POPJ P, + JUMPLE I,CPOPJ + MOVE A,UNAME(U) + CONO PI,CLKOFF + CAMN A,UTASS(I) + JRST CLKOJ1 + SKIPE UTASS(I) + JRST CLKONJ + MOVEM A,UTASS(I) + JRST CLKOJ1 + +ADESIGN:XCTR XR,[MOVE I,(J)] ;DEASSIGN UTAPE + CAILE I,NUNITS + POPJ P, + JUMPLE I,CPOPJ + SKIPN A,UTASS(I) + JRST POPJ1 + CAME A,UNAME(U) + POPJ P, + SETZM UTASS(I) + JRST POPJ1 + +;SET UTAPE NAME ;.UTNAM AC, ;LH(AC)=6BIT NAME, RH(AC)=TAPE # + +AUTNAM: XCTR XR,[MOVE Q,(J)] + HRRZ I,Q ;GET TAPE # + JUMPE I,CPOPJ ;TOO SMALL + CAIG I,NUNITS ;TOO LARGE? + PUSHJ P,UTSNMK ;ASSIGNED TO SOMEONE ELSE? + POPJ P, ;YES, LOSE + TLO D,1 ;SET FLAG TO EXIT FROM OPEN ROUTINE + PUSHJ P,UTO0 ;GET DIR IN CORE, LOCK, ETC. + TLNE TT,210000 ;CHECK FOR DIRECTORY NOT READ IN, UBLAT MODE + JRST LSWPOP ;JUMP ON LOSSAGE + HLRZ A,Q ;GET TAPE NAME + AOSN UDPWF(I) ;DIRECTORY PAWED OVER YET? + PUSHJ P,UDPW ;NO, GO DO IT + MOVE J,UDIRO(I) ;GET POINTER TO DIR + XOR A,177(J) ;GET DIFF BETWEEN OLD & NEW NAMES + TRNN A,-1 ;IS THERE ANY? + JRST AUTN2 ;NO, SKIP SOME CRUFT + TLZ A,-1 ;IGNORE DIFFERENCES IN LH + XORM A,177(J) ;MODIFY NAME TO NEW NAME + TLO J,100000 ;SET DIR CHANGED BIT +AUTN2: MOVEM J,UDIRO(I) ;STORE MODIFIED POINTER + JRST LSWPJ1 + +UDPW: HRRZ J,UDIRO(I) + MOVEI TT,37 + DPB TT,[370500,,177(J)] + ADD J,[500,,23.*2-1] + MOVEI TT,0 +UDPW2: ILDB Q,J + SKIPN Q + AOS TT + CAIE Q,37 + JRST UDPW2 + MOVEM TT,UMNFB(I) + POPJ P, + +;INITIALIZE UTAPE DIRECTORY ;.UINIT AC, ;C(AC)=TAPE # +;TAPE MUST BE ASSIGNED + +AUINIT: XCTR XRW,[SKIPLE I,(J)] ;TAPE # TOO LOW? + CAILE I,NUNITS ;OR HIGH? + POPJ P, ;YES + PUSHJ P,UTSNMK ;OR NOT ASSIGNED TO THIS USER + POPJ P, + TLO D,1 ;SET EXIT FLAG FOR OPEN ROUTINE + PUSHJ P,UTO0 ;GET DIR, LOCK IT, ETC. + TLNE TT,210000 ;CHECK FOR UBLAT MODE, DIRECTORY NOT READ (TT=UDIRO(I)) + JRST LSWPOP + SETZM (TT) ;CLEAR FIRST LOC + HRLI A,(TT) ;SET UP LH OF BLT POINTER + HRRI A,1(TT) ;& RH + BLT A,177(TT) ;ZAP + MOVE A,[757367573674] ;GET WORD OF 7 5-BIT BYTES VALUE 36 + MOVEM A,56(TT) ;INDICATE FIRST 7 BLOCKS RESERVED + MOVSI A,660000 ;ONE 5-BIT BYTE, VALUE 33 + MOVEM A,67(TT) ;MARK FILE DIRECTORY BLOCK + HRROS 177(TT) ;MARK END OF DIR + SETZM UDPWF(I) ;INDICATE DIR PAWED OVER + MOVEI A,559. ;# OF FREE BLOCKS IN EMPTY TAPE + MOVEM A,UMNFB(I) ;STORE FOR FUTURE REFERENCE + TLO TT,100000 ;INDICATE CHANGED + MOVEM TT,UDIRO(I) ;UPDATE POINTER + JRST LSWPJ1 + +;UTAPE DISMOUNT + +AUDISM: XCTR XRW,[MOVE A,(J)] ;OPER 22 +NFLAP: JUMPLE A,CPOPJ + CAILE A,NUNITS + POPJ P, + MOVSI C,-NUTIC-NUTOC + CONO PI,UTCOFF +AUTDM1: SKIPGE UTUSR(C) + JRST AUTDM2 + HRRZ D,UTTNO(C) + CAMN A,D + JRST UTCONJ ;SOME ONE USING TAPE +AUTDM2: AOBJN C,AUTDM1 + CONO PI,UTCON + MOVSI C,(SETZ) + IORM C,UFLAPF(A) + JRST POPJ1 + +;ATTEMPTED DIRECTORY READ GOT FLUSHED +UTOLOS: TLNE D,1 ;CHECK EXIT FLAG + JRST NULSET ;NOT .OPEN, SEIZE NOTHING AND RETURN + JRST OPNL7 ;.OPEN, SIGNAL DEVICE NOT READY + +UTOF1: MOVSI TT,200000 + IORM TT,UFLAPF(I) ;RQEST ABORT OF FLAP + CONO PI,UTCON + SKIPGE UFLAPF(I) + PUSHJ P,UFLS ;HOPE FOR BEST +UTO: PUSHJ P,UTSNMK ;MUST BE ASSIGNED + JRST NCA + JUMPE I,OPNL1 ;UTAPE OPEN + CAILE I,NUNITS + JRST OPNL1 +UTO0: CONO PI,UTCOFF + SKIPGE UFLAPF(I) + JRST UTOF1 ;FLAPPING IN PROGRESS + SKIPGE TT,UDIRO(I) + AOSE TT + JRST UTO4 ;FILE DIR IN OR ON THE WAY + MOVEI TT,200000 + MOVEM TT,DCHNT(I) + MOVE TT,UNAME(U) + MOVEM TT,UMNTR(I) ;TELL WHO FIRST CAUSED DIR TO BE READ IN + MOVSI TT,20000 + ANDCAM TT,UDIRO(I) +UTO4: CONO PI,UTCON + MOVSI TT,400000 + MOVNI T,1 + PUSHJ P,LWAIT + CAMLE T,UDIRO(I) ;WAIT FOR DIRECTORY TO COME IN OR GO OUT + IORB TT,UDIRO(I) ;IF IN THEN LOCK IT + CONO PI,UTCON + CAMN TT,[-1] + JRST UTOLOS ;DIDN'T GET READ IN + PUSHJ P,SGNSET ;MAKE SUURE DIRECTORY GETS UNLOCKED ON PCLSR + UDIRO(I) + TLNE D,1 ;CHECK SPECIAL EXIT FLAG + POPJ P, ;EXIT + TLNE TT,10000 + JRST UTOBL1 ;IN UBLAT MODE + AOSN UDPWF(I) + PUSHJ P,UDPW +UDPW1: TRNE D,200000 + JRST UTDEL1 ;DELETE OR RENAME + JUMPL D,UTOW1 ;WRITE + PUSHJ P,FLDRCK + JRST UTO5B ;NORMAL FILE WANTED + MOVEI J,0 ;UTAPE DIRECTORY WANTED + PUSHJ P,LSWPOP + JRST LISTFE ;JOIN DIRECTORY CODE FOR OTHER DEVICES + +UTOBL1: CAIN W,4 + JRST OPNL4 ;DELETE ILLEGAL IN UBLAT MODE + CLEARB A,B + JRST UTO8 + +UTO5B: PUSHJ P,UTLK3 ;MUST NOT CLOBBER TT + JUMPE B,OPNL4 +UTOW2:UTO8: CONO PI,UTCON + MOVSI TT,-NUTIC + TLNE C,1 + MOVE TT,[-NUTOC,,NUTIC] + SKIPL UTUSR(TT) + AOBJN TT,.-1 + JUMPG TT,UNCA ;NO CHANNEL AVAILABLE + CONO PI,UTCOFF + SKIPL UTUSR(TT) + JRST UTO8 + MOVEI J,DCHNT-UTUL(I) + JRST .+2 +UTO2: MOVE J,Q + HRRE Q,UTUL(J) + JUMPGE Q,UTO2 ;INSERT CHNL ONTO LIST FOR TAPE + HRLOM U,UTUSR(TT) + HRRM TT,UTUL(J) + HRRZM I,UTTNO(TT) + HRRZ J,UDIRO(I) + ADD J,A + MOVE Q,133(J) + MOVEI J,EOFCH + TRNN Q,1 + MOVEI J,141 + MOVEM J,UTEOF(TT) ;STORE EOF CHR + SETZM UTDBC(TT) + DPB A,[300500,,UTDBC(TT)] + JUMPL D,UTOW3 ;WRITE + DPB A,[220500,,UTDBC(TT)] +UTOW4: HRLM A,UTTNO(TT) + HRRZ J,UDIRO(I) + ADD J,[500,,23.*2-1] + MOVEM J,UTDIRP(TT) + MOVE J,[SETZ 377] + MOVEM J,UTBFP(TT) + CLEARM UTBFS(TT) + MOVE J,TIME + MOVEM J,UTLSTM(TT) + HRROS UTMBN(TT) + HLLOS UTRAC(TT) + HRRZS UTRAC(TT) + CONO PI,UTCON + CLEARM MPRC(TT) + AOS NUTCA + PUSHJ P,FSCMP + HRRZS UTRAC(TT) + PUSHJ P,LSWPOP ;RELEASE FILE DIR + MOVSS C + HRL A,TT + JSP Q,OPSLC7 + DNUACII,,DNUACCO ;ASCII UNITS INPUT ;ASCII UNITS OUTPUT + DNUBKI,,DNUBKO ;BLOCK INPUT ;BLOCK OUTPUT + DNUDTI,,DNUDTO ;WORD INPUT ;WORD OUTPUT + DNUBKI,,DNUBKO ;BLOCK INPUT ;BLOCK OUTPUT + +UTOW1: SKIPN UMNFB(I) + JRST OPNL6 ;FULL + PUSH P,B + PUSH P,A + PUSHJ P,UTSNMK + JRST UTWNA ;NOT ASSIGNED + SETZB A,B + PUSHJ P,UTLK3 + JUMPE B,UFILDF ;FILE DIR FULL + JRST UTOW2 + +UTSNMK: SKIPN T,UTASS(I) ;TAPE MUST BE ASSIGNED TO THIS LOSER + POPJ P, + CAME T,UNAME(U) + CAMN T,USYSN1(U) + AOS (P) + POPJ P, + +UTOW3: HRROM TT,1(B) ;RESERVE FILE NAME + POP P,UTN1(TT) ;STORE NAMES + POP P,UTN2(TT) + MOVSI J,100000 + IORM J,UDIRO(I) ;SET FILE DIR MODIFYED + MOVSI J,UTBKNP(TT) ;GET LIST PNTR PNTR + MOVEM J,UTBKNP(TT) ;MAKE LH SELF-REFERENT SO INIT LINK WILL GO IN RH + AOS NUWCA ;INCR # ACT UWRITE CHNLS + JRST UTOW4 + +UNCA: JUMPGE D,NCA +UTWNA: SUB P,[2,,2] +NCA: JRST OPNL10 + +UFILDF: SUB P,[2,,2] +FILDF: JRST OPNL5 + +S1NL14: SUB P,[1,,1] + JRST OPNL14 + +UDATAI: SKIPA E,[444400,,1] +UASCII: MOVE E,[440700,,5] + MOVEI B,UBLKI2 + JRST CHRKTI + +UBLKI: MOVE E,[444400,,1] + JSP B,BLKT +UBLKI2: MPRP(A) + MPRC(A) + UTBGB ;4.9 = 0 UTAPE 1 DISK + UTBRB + JRST 4,. + SKIPG UTBFS(A) + +;INPUT BLK BUFFER-GET RTN + +UTBGB: LDB Q,[IOLO,,UTBFP(A)] + CAIN Q,377 + JRST 4,. ;PNTRS OUT OF PHASE + CAIN Q,376 + JRST POPJ2 ;END OF FILE + CONO PI,UTCOFF + SKIPL UTRAC(A) + SKIPGE IOBFT(Q) + JRST UTBGB1 + LDB J,[IOLO,,IOBFT(Q)] + HRRM J,UTBFP(A) + MOVEI TT,(SETZ) + CAIL J,376 + HRLM TT,UTBFP(A) + CONO PI,UTCON + SOS UTBFS(A) +UTBWG4: MOVE J,TIME + MOVEM J,UTLSTM(A) + MOVEI J,-3 + DPB J,[IOLO,,IOBFT(Q)] + LDB TT,[IOSA,,IOBFT(Q)] + LSH TT,6 + HLL TT,E + MOVEM TT,MPRP(A) + MOVEI TT,200 + IMULI TT,(E) + MOVEM TT,MPRC(A) + HRLM Q,UTMBN(A) + JRST POPJ1 + +UTBGB1: CONO PI,UTCON + SKIPL IOBFT(Q) + SKIPGE UTRAC(A) + PUSHJ P,UFLS ;REALLY? + JRST UTBGB + +UBLKO: MOVE E,[444400,,1] + JSP B,BLKT +UBLKO2: SETZ MPRP(A) + MPRC(A) + UTBWG + UTBWW + JRST 4,. + TRNA + +UASCCO: SKIPA E,[440700,,5] +UDATAO: MOVE E,[444400,,1] + MOVEI B,UBLKO2 + JRST CHRKTO + +;OUTPUT BLKT BUFFER-GET RTN + +UTBWG: MOVE Q,UTBFS(A) ;GET # BUFS IN CHNL + IMUL Q,NUWCA ;SCALE TO # ACT UWRITE CHNLS + CAIL Q,LUTWBF ;IF BEING TOO GREEDY WITH BLOCK LIST SPACE + POPJ P, ;LOSE + PUSH P,A + PUSH P,B + MOVE D,A + HRRZ Q,UTBFP(D) + CAIL Q,376 + JRST UTBWG1 ;NO BUFS NOW RELOAD + SKIPGE UTDBC(D) + JRST POPBAJ ;CHNL IN ERR + +UTBWG2: HRRZ J,UTBFS(D) + CAMG J,UPCHFS + JRST UTBWG1 + PUSHJ P,TCALL + JRST UIMRQ + JRST POPBAJ + PUSHJ P,TCALL + JRST UTMGB + JRST UTBWG2 + +UTBWG1: HRRZ Q,UTTNO(D) + SOSGE UMNFB(Q) + JRST UTBWG5 + PUSHJ P,AOSSET + UMNFB(Q) + PUSHJ P,LSWTL ;WAIT FOR + UDIRO(Q) ;DIR TO UNLOCK + PUSH P,E ;SAVE E + PUSHJ P,TCALL + JRST IUTCONS + JRST UTBWG6 + PUSH P,A ;SAVE A + PUSH P,B + PUSH P,C + MOVE C,Q + MOVE B,UDIRO(C) + MOVEI E,0 ;INDICATE ADVANCE TO UDIRAD + PUSHJ P,UDOUT2 ;ADV DIR PNTRS (SKIP LOCK CHECK IN UDIRAD) + JRST 4,. ;SHOULDN'T GET HERE + JRST UTPFUL ;NO ROOM FOR EXT + PUSHJ P,LSWPOP ;UNLOCK DIR + PUSHJ P,LSWDEL ;UNHACK UTFAOS + POP P,C + POP P,B + POP P,Q ;GET BACK BUF # + POP P,E ;RESTORE E + POP P,B + POP P,A + AOS UTBFS(A) + JRST UTBWG4 + +UTBWG5: AOS UMNFB(Q) + JRST IOCER9 + +UTBWG6: PUSHJ P,LSWCLR ;UNLOCK DIR & ADJ BLK CNT + POP P,E + JRST POPBAJ + +UTPFUL: SUB P,[2,,2] + POP P,A ;GET BACK BUF # + PUSHJ P,BRTN ;RETURN BUF + JRST IOCER9 ;BARF ABOUT TAPE FULL + +UTBWW: HLRE Q,UTMBN(A) + JUMPL Q,CPOPJ + PUSHJ P,LWAIT ;WAIT FOR + SKIPN UTWBFS ;SPACE IN BLK LIST & GET PNTR + MOVE J,UTWBFS ;(DO NOT COMBINE WITH PRECEDING INST) + HRRZ H,(J) ;GET PNTR TO NEXT FREE WD + MOVEM H,UTWBFS ;UPDATE FS PNTR + CONO PI,UTCON ;TURN ON UTC NOW TO MINIMIZE OFF TIME EVEN THOUGH OFF AGAIN LATER + HRRZ D,UTDBC(A) ;GET NEXT BLK # + MOVSM D,(J) ;PUT IN NEW WD + HLRZ D,UTBKNP(A) ;GET PNTR TO LAST WD IN LIST + HRRM J,(D) ;STORE LINK IN END OF LIST + HRLM J,UTBKNP(A) ;UPDATE END PNTR + MOVEI J,377 + IORM J,IOBFT(Q) + SKIPGE UTTNO(A) + SOS IOBFT(Q) ;CHANGE TO EOF + CONO PI,UTCOFF + HLRE J,UTBFP(A) + JUMPL J,UTBWW1 + DPB Q,[IOLO,,IOBFT(J)] + +UTBWW2: HRLM Q,UTBFP(A) + CONO PI,UTCON + HRROS UTMBN(A) + POPJ P, + +UTBWW1: HRRM Q,UTBFP(A) + JRST UTBWW2 + +UTOCL: MOVSI Q,(SETZ) + IORM Q,UTTNO(A) + LDB E,[300600,,MPRP(A)] ;NOW FILL OUT BLOCK WITH EOF CHARS + CAIN E,7 + JRST UTOCL6 +UTOCL1: HRROI C,[EOFWRD] + SKIPG MPRC(A) + JRST UTOCL2 + PUSHJ P,UDATAO + JRST UTOCL1 + +UTOCL6: HRROI C,UTEOF(A) + SKIPG MPRC(A) + JRST UTOCL2 + PUSHJ P,UASCCO + JRST UTOCL6 + +UTOCL2: SKIPG MPRC(A) + PUSHJ P,UTBWW ;MAKE SURE BUFFER WRITTEN OUT SINCE MAYBE GOT + ;PCLSRED FROM UTBWW DURING .IOT THAT JUST FILLED BUFFER + PUSH P,R + MOVE D,A + SKIPE UTBFS(D) + PUSHJ P,UFLS + HRRZ C,UTTNO(D) + PUSHJ P,LSWTL + UDIRO(C) + HRRZ Q,UTBFP(D) + CAIL Q,376 + JRST UTOCL4 ;NORMAL CLOSE + MOVEI Q,%PIIOC ;ABORT WORKS + IORM Q,PIRQC(U) + MOVEI A,0 + HRROI B,(D) + PUSHJ P,UDELETE +UTOCL5: PUSHJ P,LSWPOP + POP P,R + SOS NUWCA ;DECR # ACT UWRITE CHNLS + JRST UTOCL3 + +UTOCL4: MOVE A,UTN1(D) + MOVE B,UTN2(D) + PUSHJ P,UDELETE + LDB Q,[220500,,UTTNO(D)] + LSH Q,1 + ADD Q,UDIRO(C) + MOVE A,UTN1(D) + MOVE B,UTN2(D) + MOVEM A,-2(Q) + MOVEM B,-1(Q) + LDB Q,[220500,,UTTNO(D)] + ADD Q,UDIRO(C) + MOVEI A,1 + IORM A,133(Q) + JRST UTOCL5 + + +UTDEL1: MOVE C,I ;DELETE + SKIPE SRN3(U) + JRST UTRN1 ;RENAME + PUSHJ P,UTSNMK + JRST NCA + PUSHJ P,UDELETE + JUMPE TT,OPNL4 + JRST LSWPJ1 + + +UTRN1: JUMPE A,UTRN3 ;RENAME OF OPEN FILE + PUSHJ P,UTSNMK ;ALLOW RENAME OF OPEN FILE + JRST NCA + PUSHJ P,UTLOOK + JUMPE B,OPNL14 + PUSH P,Q + MOVE A,SRN3(U) + MOVE B,SRN4(U) + PUSHJ P,UTLOOK + POP P,Q + JUMPN B,OPNL13 + MOVE A,SRN3(U) + MOVE B,SRN4(U) + MOVEM A,0(Q) + MOVEM B,1(Q) +UTRN4: MOVSI A,100000 + IORM A,UDIRO(C) + JRST LSWPJ1 + +UTRN3: ADDI B,IOCHNM(U) + HLRZ TT,(B) + MOVE A,SRN3(U) + MOVE B,SRN4(U) + MOVEM A,UTN1(TT) + MOVEM B,UTN2(TT) + JRST UTRN4 + +UDELETE: MOVEI TT,0 ;TT=0 IF NOTHING DELETED + OTHERWISE +UDELA: PUSHJ P,UTLOOK + JUMPE B,CPOPJ ;TAPE NO IN C,FILE NAME IN A,B + MOVEI E,NUTIC-1 +UDELE4: HRRZ J,UTTNO(E) + SKIPL UTUSR(E) + CAME J,C + JRST UDELE3 + HLRZ J,UTTNO(E) + CAME J,A + JRST UDELE3 + MOVSI J,10000 + TDNE J,UTDBC(E) + JRST UDELE3 ;THIS IS LOSER WHO IS CLOSING FILE + IORM J,UTDBC(E) + CLEARM (Q) + SETOM 1(Q) + AOJA TT,CPOPJ + +UDELE3: SOJGE E,UDELE4 +UDELE1: CLEARM (Q) + CLEARM 1(Q) + MOVE J,A + ADD J,UDIRO(C) + MOVEI B,1 + ANDCAM B,133(J) + MOVSI J,100000 + IORM J,UDIRO(C) +UDELE6: HRRZ B,UDIRO(C) + ADD B,[500,,23.*2-1] + MOVEI J,0 +UDELE2: ILDB E,B + CAMN E,A + AOS UMNFB(C) + CAMN E,A + DPB J,B + CAIE E,37 + JRST UDELE2 + MOVE B,A + MOVEI A,0 + AOJA TT,UDELA + + +UTICL: PUSH P,R + MOVE D,A + MOVSI C,200000 + IORM C,UTRAC(D) ;SET EOF + MOVEI T,400000 + TDNN T,UTRAC(D) + PUSHJ P,UFLS ;WAIT FOR ACTIVE BUFFER TO TRANSFER + PUSHJ P,UTBRB1 ;RETURN ACTIVE BUFFER MAIN PROG + HLRZ A,UTTNO(D) + MOVE B,UTDBC(D) + TLNE B,10000 + PUSHJ P,UDELE5 ;FINISH FILE DELETE + POP P,R +UTOCL3: HRRZ A,UTBFP(D) +UTICL2: CAIL A,376 + JRST UTICL3 + LDB C,[IOLO,,IOBFT(A)] + PUSHJ P,BRTN + MOVE A,C + JRST UTICL2 + +UTICL3: PUSHJ P,UCPAT0 ;UT CHANNEL PATCH OUT + CLEARM UTDIRP(D) + SETOM UTUSR(D) + CLEARM (R) + POPJ P, + + + +UCPAT0: HRRZ B,UTTNO(D) ;PATCH OUT CHANNEL + MOVEI C,DCHNT-UTUL(B) + CONO PI,UTCOFF +UCPAT2: HRRE E,UTUL(C) + JUMPL E,UTCOP + CAMN E,D + JRST UCPAT1 + MOVE C,E + JRST UCPAT2 + +UCPAT1: HRRZ E,UTUL(E) + HRRM E,UTUL(C) + SOS NUTCA +UTCOP: JRST UTCONJ + +UDELE5: HRRZ C,UTTNO(D) + PUSHJ P,LSWTL + UDIRO(C) + HLRZ Q,UTTNO(D) + MOVE A,Q + LSH Q,1 + ADD Q,UDIRO(C) + SUBI Q,2 + PUSHJ P,UDELE1 + JRST LSWPOP + +UTBRB1: MOVE A,D +UTBRB: PUSH P,A + HLRE A,UTMBN(A) + JUMPL A,POPAJ + PUSHJ P,BRTN + POP P,A + HRROS UTMBN(A) + POPJ P, + +UTRL1: JUMPE B,UTRLDR + HRRZ B,UTBFP(D) + CAIE B,377 + JRST JDB6C +UTRLDR: LDB R,[270100,,UTDBC(D)] + JUMPN R,UTRLD1 + SKIPL R,UDIRO(C) ;SPECIAL KLUDGE TO RUN FAST + TLNE R,10000 ;SKIPN ON NOT IN UBLAT MODE + JRST UTRLD1 + LDB TT,[220500,,UTDBC(D)] + ILDB B,UTDIRP(D) + AOS UTDBC(D) + CAME B,TT + JRST UTRLD2 +UTRLD3: PUSHJ P,IUTCONS ;RTN BUFFER NO IN A + JRST UTRLR1 ;MEM LOCKED (OR SOMETHING) + CLEARM URDWR(C) + HRRZ B,UTDBC(D) ;GET BLK # TO READ + JRST UTRLD + +UTRLD2: CAIN B,37 + PUSHJ P,UAR + +UTRLD1: PUSHJ P,UDIRAD + JRST JDB6C2 ;DIR DOUBLE LOCKED + JRST UTREOF + JRST UTRLD3 + + +JDDTA: HLRZ D,ULDCH(C) ;FINISHED DATA TRANS TAPE IN C GET CHNL NO + CLEARM UTLDD(D) + SETOM SMODE +IFE NEWDTP, CONSZ DC,7 +IFN NEWDTP, CONSO DTS,100000 + JRST UDATER ;DC STILL ENABLED => ERROR + SETOM UGOAL(C) + CAIL D,NUTIC + JRST JDDT1 ;WRITE OR FILE DIRECTORY + MOVE E,UTRAC(D) + HLLOS UTRAC(D) + MOVEI B,377 + IORM B,IOBFT(E) + HLRE B,UTBFP(D) + JUMPL B,JDDT5 + DPB E,[IOLO,,IOBFT(B)] +JDDT6: HRLM E,UTBFP(D) + AOS UTBFS(D) + + +JDDT2: PUSHJ P,JDB6W + JRST JDDT3 ;SAME TAPE CAN RELOAD, DONT CHECK OTHERS +JDDT4: HRRZS ULDCH(C) +IFE NEWDTP, JRST JDB4A ;UNIT NOW IDLE STOP IT +IFN NEWDTP,[ + PUSHJ P,JDSTP + JRST JDB3 +] + +JDDT1: CAIL D,NUTIC+NUTOC + JRST UDRDD3 ;FILE DIR IN OR OUT + HRRZ A,UTRAC(D) + PUSHJ P,IBRTN + HLLOS UTRAC(D) + SOS UTBFS(D) + JRST JDDT2 + + +JDDT5: HRRM E,UTBFP(D) + JRST JDDT6 + UTREOF: MOVSI E,200000 + IORM E,UTRAC(D) + HLRE E,UTBFP(D) + SKIPL E + SOSA IOBFT(E) ;TURN END OF LIST TO END OF FILE + SOS UTBFP(D) + AOS UTBFS(D) ;TO START MAIN PROG + JRST JDB6C + +JDB6W: HRRE D,DCHNT(C) + JUMPL D,JDB6W1 ;NO CHANNELS ACTIVE + CAIN D,200000 + JRST UDRDD ;READ FILE DIR +JDB6C1: SKIPL E,UTRAC(D) + TLNE E,300000 + JRST JDB6C2 ;CHANNEL LOCKED + CAIL D,NUTIC + JRST JDB6A ;WRITE CHANNEL + HRRZ B,UTBFS(D) + CAILE B,MXUTBF ;READ CHANNEL; SHOULDN'T LET IT GET TOO MANY BUFFERS. + JRST JDB6C + HRRZ B,UTFS + CAIN B,377 + JRST JDB6E ;TRY TO GET MORE MEMORY + MOVE B,UTBFS(D) + SOJLE B,UTRL1 ;RELOAD CHANNEL WITH ONE OR NO BUFFERS + MOVE B,UTLSTM(D) + SUB B,TIME + CAMG B,[-300.] + JRST JDB6C2 ;NO RELOAD +JDB6F: HRRZ B,UTBFS(D) ;NUMBER BUFS THIS CHANNEL HAS + CAMGE B,UPCHFS + JRST UTRLDR +JDB6E: PUSHJ P,UIMRQ ;TRY TO GET MORE MEMORY (IO) + JRST JDB6C2 ;NOT AVAIL + PUSHJ P,UTMGB ;ADD TO MEM ALLOC UTAPE + JRST JDB6F + +UTRLR1: PUSHJ P,UDIRR ;BACK UP + JRST 4,. + JRST 4,. ;LOSSAGE +JDB6C2: +JDB6C: HRRE D,UTUL(D) + JUMPGE D,JDB6C1 + JRST POPJ1 + +JDB6W1: LDB D,[410300,,UDIRO(C)] + SOJN D,POPJ1 ;DIR CHANGED AND NOT LOCKED + HRRZ D,UDIRO(C) + LDB D,[370500,,177(D)] + CAIE D,37 + JRST 4,. ;DIRECTORY CLOBBERED SINCE READ IN + MOVEI D,100 ;INITIATE FILE DIR WRITE + SKIPL ULDCH(C) ;SKIPN ON ALREADY LOW PRIORITY POSIT + PUSHJ P,ILLP ;INITIATE LOW PRIOR POSIT + JRST POPJ1 + +ULLP1: SKIPGE UDIRO(C) + POPJ P, + SETOM URDWR(C) ;SET FILE DIR WRITE CYCLE FROM LOW PRIORITY CYCLE + MOVSI D,400000 ;LOCK DIR + IORM D,UDIRO(C) + MOVEI D,NUTIC+NUTOC + HRRZ A,ULDCH(C) ;BUFFER NO OF DIRECTORY + JRST JDB6W2 + + +JDB6A: HRRZ A,UTBFP(D) + CAIGE A,376 + SKIPGE IOBFT(A) + JRST JDB6C2 ;LOCKED OUT SNIFFLE + MOVE E,UTBKNP(D) ;GET BLK LIST PNTR + MOVE J,UTWBFS + EXCH J,(E) + HRRZM E,UTWBFS + HLRZ B,J ;GET BLK # FROM HEAD OF LIST + HRR E,J ;SET LINK TO NEXT WD IN LIST + TRNN E,-1 ;IF LIST EMPTY + MOVSI E,UTBKNP(D) ;SET END PNTR TO PNTR SO NEXT LINK WILL GO HERE + MOVEM E,UTBKNP(D) ;UPDATE PNTR + SETOM URDWR(C) + HRRZ A,UTBFP(D) + LDB E,[IOLO,,IOBFT(A)] + HRRM E,UTBFP(D) + MOVEI J,(SETZ) + CAIL E,376 + HRLM J,UTBFP(D) + +UTRLD: HRRM A,UTRAC(D) +UDRR2: MOVEM B,UGOAL(C) + MOVEI B,-4 + DPB B,[IOLO,,IOBFT(A)] + LDB B,[IOSA,,IOBFT(A)] + LSH B,6 + SOS B + HRRM B,UMEMAD(C) + HRLM D,ULDCH(C) + MOVE B,TIME + MOVEM B,DRTM(C) + POPJ P, + +JDB6: PUSHJ P,JDB6W + JRST JDBRK7 ;SUCCESFUL RELOAD + SKIPL ULDCH(C) +IFE NEWDTP,[ + JRST JDBRK4 ;CAN NOT RELOAD + JRST JDF2A +] +IFN NEWDTP,[ + JRST JDBRK6 + JRST JDS1 +] + +UDRDD: MOVE D,UDIRO(C) ;TAPE WANTS FILE DIRECTORY READ + TLO D,20000 ;OK FOR 4.5 CLEAR + AOSE D ;REST SHOULD BE -1 + JRST 4,. ;FILE DIRECTORY READ REQUEST WHEN ALREAD IN + MOVEI D,NUTIC+NUTOC ;GET DIRECTORY CHANNEL NUMBER IN D + PUSHJ P,IUTCONS + JRST POPJ1 ;NO MEM + LDB B,[IOSA,,IOBFT(A)] ;GET ORIGIN _ -6 + LSH B,6 + TLO B,600000 ;SET LOCK, DOUBLE LOCK BITS + MOVEM B,UDIRO(C) ;STORE ORIGIN + HLLOS DCHNT(C) ;NO CHANNEL ACTIVE THIS UNIT YET + CLEARM URDWR(C) ;SIGNAL WANT READ + HRRM A,ULDCH(C) ;STORE BUFFER NUMBER +JDB6W2: MOVEI B,100 ;DIRECTORY BLOCK NUMBER + JRST UDRR2 + +UDRDD3: HRRZ D,ULDCH(C) ;FILE DIR IN OR OUT + HRRZS UDIRO(C) ;UNLOCK DIRECTORY + DPB C,[IOLO,,IOBFT(D)] + HRRZS ULDCH(C) + JRST JDDT2 + UDIRAD: TDZA E,E ;ADVANCE DIR PNTRS OF CHANNEL IN D +UDIRR: MOVEI E,1 ;REV DIR PNTRS THIS WINS FOR READS ONLY HA HA + SKIPGE B,UDIRO(C) + JRST UDOUT3 +UDOUT2: TLNE B,10000 + JRST UDBL1 ;UBLAT MODE +UDOUT7: LDB R,[270100,,UTDBC(D)] + XOR R,E + MOVEI Q,0 + CAIL D,NUTIC + MOVEI Q,UTBLKS + LDB TT,[220500,,UTDBC(D)] + +UDIR1: PUSHJ P,UITAB(R) + TRNE J,-1 ;BLK NO RTN IN RH J + CAIN B,37 + JRST UDOUT ;END OF EXTENSION + CAME B,TT + SOJA Q,UDIR1 + SOJG Q,.-1 + LDB B,[300500,,UTDBC(D)] + DPB B,UTDIRP(D) +UDARET: JRST POPJ2 + +UDBL1: AOS A,UTDBC(D) + CAILE A,1101 + JRST POPJ1 ;EOF + JRST POPJ2 + +UDOUT: JUMPN E,UDOUT5 + CAIL D,NUTIC + JRST UDOUT1 + MOVEI A,0 ;READ + MOVE B,TT + PUSHJ P,UTLOOK ;TAP NO IN C NAME IN A,B + JUMPE B,POPJ1 ;EOF OR ADR OF FIRST WD +UDOUT6: DPB A,[220500,,UTDBC(D)] ;FILE NO +UDOUT4: DPB A,[300500,,UTDBC(D)] + MOVSI A,1_5 + XORM A,UTDBC(D) + JRST UDOUT7 + + +UDOUT3: TLNN B,200000 ;DIRECTORY DOUBLE LOCKED + CAIL D,NUTIC + POPJ P, + JRST UDOUT2 + +UDOUT1: SETZB A,B + PUSHJ P,UTLOOK + JUMPE B,UDOUT8 ; FILE DIR FULL + LDB J,[300500,,UTDBC(D)] + MOVEM J,1(B) + JRST UDOUT4 + +UDOUT8: XORI R,1 ;REVERSE DIR + AOS (P) ;SKIPN ONCE + JRST UITAB(R) ;BACK UP PNTRS AND RETURN + +UDOUT5: LDB A,[220500,,UTDBC(D)] + LSH A,1 + ADD A,UDIRO(C) + SKIPE -2(A) + JRST UDARET + MOVE A,-1(A) + JRST UDOUT6 + +UTLK3: SKIPA Q,UDIRO(I) +UTLOOK: MOVE Q,UDIRO(C) ;B=0 => NOT FOUND + HRLI Q,-23. + PUSH P,[1] +UTLK2: CAMN A,(Q) + CAME B,1(Q) + AOJA Q,UTLK1 + MOVE B,Q + JRST POPAJ + +UTLK1: AOS(P) + AOBJN Q,UTLK2 + MOVEI B,0 + JRST POPAJ + +UITAB: AOSA J,UTDBC(D) + JRST UAR + +UAF: ILDB B,UTDIRP(D) + POPJ P, + +UAR: MOVSI B,50000 + ADD B,UTDIRP(D) + SKIPGE B + SUB B,[430000,,1] + MOVEM B,UTDIRP(D) + LDB B,B + SOS J,UTDBC(D) + POPJ P, + +EBLK + IFN NEWDTP,{ +; T S UTAPE ROUTINES PI SERV (NEW UTAPE CONTROL) + +TAPE: 0 +UTP1: 0 ;JRST PIPOS OR DATAI DC, OR JRST UTP3 + +BBLK + + SOS .-1 + AOSGE TAPCNT + JRST 12,@TAPE + +UTP3: CONO DTS,770001 + JRST 12,@TAPE + +PIPOS: MOVEM A,TAP1 + MOVEM B,TAP2 + MOVEM C,TAP3 + MOVE C,SUNIT + DATAI DTC,B + TDZE B,[1777#-1] + JRST PIPOS7 + MOVEM B, EUPOS(C) + HRRZM C, DG2(C) + SKIPGE UGOAL(C) + JRST PIPF1 + SUB B,UGOAL(C) + JUMPE B,PIPOS2 + ADD B,UDIR(C) + MOVMM B,UTENB + SKIPGE ULDCH(C) + JRST PIPOS3 + JUMPN B,PIPOS3 +PIPOSL: MOVEI A,40000+DCCHN_3 + DPB C,[110300,,A] ;SET SELECTED UNIT CONO DTC,FOO(A) + MOVE B,UDIR(C) + XCT UTST2(B) +PIPOS5: MOVE C,TAP3 + MOVE B,TAP2 + MOVE A,TAP1 + JRST 12,@TAPE + +PIPOS7: AOS BDBLKC + JRST PIPOSL + +EBLK + +BDBLKC: 0 + BBLK + +PIPOS3: MOVE A,UDIR(C) + LSH A,2 + SUB B,A + XOR B,UDIR(C) + MOVEI A,40000 + DPB C,[110300,,A] + JUMPG B,PIPOS4 ;GOING WRONG DIR +PIPOS6: MOVE B,TIME + MOVEM B,ULCTM(C) + ADD B,UTENB + MOVEM B,DRTM(C) +PIPF2: MOVE B,UDIR(C) + TRNN A,40000 + TRO A,30000 + XCT UTST2(B) +; CLEARM UDCC +; SETOM DCFREE + CONO DTS,770001 ;ENABLE ALL INTERUPTS AND SET FUNCTION STOP + JRST PIPOS5 + +PIPF1: MOVEI A,40000 + DPB C,[110300,,A] + MOVE B,TIME + MOVEM B,ULCTM(C) + JRST PIPF2 + PIPOS4: TRZ A,40000 ;TURN TAPE AROUND + CLEARM DG2(C) + MOVNS B,UDIR(C) + MOVEM B,OUDIR(C) + JRST PIPOS6 + +PIPOS2: HLRZ A,ULDCH(C) + SKIPL ULDCH(C) + SKIPGE UTRAC(A) + JRST PIPOS3 ;CHANNEL LOCKED + SETOM UTLDD(A) ;CHANNEL ACTUALLY LOADED TRANSFER IMMINENT + AOS SMODE + MOVEI A,0 + MOVE B,UMEMAD(C) + SKIPGE URDWR(C) + TROA A,400 ;WRITE + TLZ B,(BLKO-BLKI) + SKIPL UDIR(C) + JRST TAPFOR + TRO A,100000 + ADD B,[DATAI-BLKI 200] + MOVEM B,UTP1 + MOVNI B,200 + MOVEM B,TAPCNT + +TAP4: CONO DTC,300+DCCHN_3+UTCCHN(A) + CONO DTS,770000 + MOVE B,URDWR(C) + MOVEM B,WRITE + MOVE C,TAP3 + MOVE B,TAP2 + MOVE A,TAP1 + JRST 12,@TAPE + +TAPFOR: TRO A,200000 + HRRM B,TAPCNT + HRRI B,TAPCNT + MOVEM B,DCMLOC + MOVE B,[-200,,UTP3] + HRRM B,UTP1 + HLLM B,TAPCNT + JRST TAP4 + UTERR: CONI DTS,E + SKIPL SMODE + JRST UDATER +; SKIPGE UDCC +; SETOM DCFREE +UTER5: SKIPN C,SUNIT + JRST JDB3 + SETOM DG2(C) + SKIPL UFLAPF(C) + JRST UTER6 + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + CLEARM UDIR(C) + CLEARM OUDIR(C) + CONO DTC,400000 ;STOP DRIVE + JRST JDB3 + +UTER6: AOS UTERP(C) + HRLM E,UTERP(C) + TRNN E,20000 + JRST JDB3 ;END ZONE + MOVNS B,UDIR(C) + MOVEI A,0 + SKIPGE B + MOVEI A,1103 + MOVEM A,EUPOS(C) + MOVE A,TIME + MOVEM A,ULCTM(C) + MOVEM A,DRTM(C) + JRST JDB7 + +UDATER: CONO DTS,770001 ;ENABLE ALL INTERUPTS AND STOP FUNCTION + SETOM SMODE + HLRZ D,ULDCH(C) + CLEARM UTLDD(D) + JRST JDB3 + UTCB0: MOVE C,SUNIT + AOSE CUINT ;SKIP IF CLOCK CAUSED INTERUPT + JRST JDBRK ;NOT TIME FLAG +UTCB1: MOVE B,UDIR(C) + AOSN UTHERR ;HANG UP ERROR SENT FOR SLOW CLOCK ROUTINE + JRST UTERR + JRST JDB3 + +JDDT3: MOVE A,EUPOS(C) ;AFTER DATA XFER + SUB A,UGOAL(C) + MOVMS E,A + ADD A,TIME + MOVEM A,DRTM(C) + MOVE C,[-NUNITS,,1] + MOVM B,DRTM(C) + CAMGE B,TIME + JRST JDB3 ;SOMETHING ELSE DUE + AOBJN C,.-3 + MOVE C,SUNIT + SOJLE E,JDB7 ;RELOADING FOR NEXT BLOCK + JRST JDB3 + ILLP: MOVEM D,UGOAL(C) ;LOW PRIORITY POSIT ENTRY + MOVSI A,(SETZ) + IORM A,ULDCH(C) + +UTDC: SKIPGE UGOAL(C) + POPJ P, ;UNIT IDLE + SKIPGE DG2(C) + JRST UTDC3 +UTDC1: MOVE A,EUPOS(C) ;ESTIMATE UNIT TIME AND UPDATE EUPOS + SKIPG DG2(C) ;SKIP ON EXACT POS KNOWN + SKIPN UDIR(C) ;SKIP ON UNIT RUNNING + JRST UTDC4 + MOVE B,TIME + SUBM B,ULCTM(C) + EXCH B,ULCTM(C) + IMUL B,UDIR(C) + ADD A,B ;ACTUAL ESTIMATED POSITION + MOVEM A,EUPOS(C) ;UPDATE EUPOS +UTDC4: SUB A,UGOAL(C) + MOVM B,A + CAIG B,2 + JRST UTDC2 + ADD A,UDIR(C) + MOVMS Aî + CAMLE A,B + SETZB A,B ;GOING WRONG DIR +UTDC2: CAILE B,200. + MOVEI B,200. ;LIMIT LONGEST DEAD RECKON + ADD B,TIME + MOVEM B,DRTM(C) + POPJ P, + +UTDC3: MOVEI B,0 ;NOT KNOWN EXACT POS REQUIRES IMMEDIATE ATTENTION + JRST UTDC2 + +JDBRK: CONSZ DTC,7 + CONSO DTS,2 + JRST POPRET + CONSZ DTS,670300 + JRST UTERR + CONSO DTS,100000 + JRST POPRET + SKIPL SMODE + JRST JDDTA ;DATA MODE +JDB3: +; SKIPGE UDCC +; SETOM DCFREE + HRLOI B,177777 + MOVEM B,UTTM2 + SETZM UTTM4 + SETOM UTTM3 ;UNIT MOST URGENT + CLEARM UTTM1 ;UNIT COULD START + MOVE C,[-NUNITS,,1] + JDBRK7: SKIPGE B,UFLAPF(C) + JRST JDF1 ;FLAPPING OP +JDF2: SKIPL ULDCH(C) ;SKIP ON LOW PRIOR POSIT + SKIPGE UGOAL(C) + JRST JDB6 ;UNIT FREE +JDS1: SKIPE UDIR(C) + JRST JDBRK4 + SKIPN UTTM1 ;UNIT TO START + HRRZM C,UTTM1 + JRST JDBRK6 +JDBRK4: MOVE B,DRTM(C) + SUB B,TIME + MOVE E,B + SUB E,UTTM2 ;TIME SOME OTHER UNIT NEEDS ATTN + JUMPL B,JDCV1 ;ALREADY OVERDUE + MOVM D,E + CAIG B,20. ;CONFLICT MORE THAN 20 BLKS AWAY + CAIL D,20. ;THEY ARE SEPARETED BY 20 BLKS + JRST JDCV1 + HRRZS C ;RELIEVE CONFLICT BY STOPPING UNIT DUE LATEST + CAMG B,UTTM2 + HRRZ C,UTTM3 +JDF5: PUSHJ P,JDSTP ;STOP UNIT + JRST JDB3 + +JDCV1: JUMPGE E,ULLP + MOVEM B,UTTM2 ;UNIT DUE SOONEST + HRRZM C,UTTM3 +ULLP: SKIPL ULDCH(C) + JRST JDBRK6 + MOVE B,TIME ;LOW PRIORITY POSIT IN PROGRESS + SUB B,ULCTM(C) + IMUL B,UDIR(C) + SKIPE DG2(C) + MOVEI B,0 + ADD B,EUPOS(C) + SUB B,UGOAL(C) + MOVMS B + CAIGE B,10. + PUSHJ P,ULLP1 ;TERM LOW PRIORITY DIRECTORY POS (COMMIT TO ACTUAL WRITE) + JDBRK6: AOBJN C,JDBRK7 + MOVE C,UTTM3 ;MOST PRESSING RUNNING UNIT + MOVE B,UTTM2 + CAIGE B,30. + JRST JDB7 ;STAY WITH PRESSING UNIT + SKIPE UTTM1 + JRST JDB5 ;START UNIT IF POSSIBLE +JDF6A: CAMG B,[10000000.] + JRST JDB7 + AOSE UTTM4 ;DON'T IF FLAP OP STILL IN PROGRESS + PUSHJ P,JDDS + SETOM UIDLE + JRST POPRET + +JDF1: MOVE E,UDIRO(C) + AOJE E,JDF1A + TLNE E,100000 + JRST JDF2 +JDF1A: SKIPGE UGOAL(C) ;FLAPPING OP + SKIPGE ULDCH(C) + JRST JDF2 + SKIPE UDIR(C) + SKIPG DG2(C) + JRST .+2 + JRST JDF3A ;HAVE JUST READ IN TAPE POS + TLNN B,100000 + JRST JDF3 ;UNIT TO START FLAPPING (I.E. READ IN TAPE POS, THEN FLAP) + LDB D,[4000,,B] + TLNN B,100000 + JRST JDBRK6 + TLNN B,200000 ;ABORT FLAPPING + CAMG D,TIME + JRST JDF4 ;UNIT TO STOP FLAPPING + SETOM UTTM4 ;INDICATE FLAP OP STILL ACTIVE + JRST JDBRK6 + +JDDS: CONO DTC,10000 ;DESELECT + CLEARM SUNIT + POPJ P, + +JDSTP: MOVEI A,430000 + SETZM UDIR(C) + SETZM OUDIR(C) +JDCNN: HRRZS C + CAME C,SUNIT ;DIR CONO IN A TO UNIT IN C + SKIPN SUNIT + JRST JDSTP1 + PUSHJ P,JDDS +JDSTP1: DPB C,[110300,,A] + CONO DTC,(A) + MOVEM C,SUNIT + POPJ P, + +JDF3: MOVE A,UDIRO(C) ;WANT TO FLAP + AOJE A,JDF3A1 ;DIR NOT IN + TLNE A,10000 + JRST JDF3A2 ;TAPE IN UBLAT MODE (COMMENT USED TO SAY DIR ON WAY IN) (??) + HRRZ A,ULDCH(C) + LDB Q,[IOCH,,IOBFT(A)] + CAIE Q,NUTIC+NUTOC + JRST 4,. + LDB Q,[IOLO,,IOBFT(A)] + CAIE Q,(C) + JRST 4,. + PUSHJ P,IBRTN ;RETURN DIR BUFFER +JDF3A2: SETOM UDIRO(C) + SETZM UTASS(C) +JDF3A1: SETOM UDPWF(C) + SKIPGE DG2(C) + JRST JDF6 +JDF3A: SETOM DG2(C) ;FLAP UNIT INC(KNOWING WHERE IT IS) + MOVE E,EUPOS(C) + IMULI E,50. ;50 MS/BLOCK + IDIVI E,33. ;33 MS/(1/2 SEC) + ADDI E,30. ;15 SECS EXTRA + ADD E,TIME ;NET TIME TO STOP FLAPPING + TLO E,100000 + DPB E,[4200,,UFLAPF(C)] + LSH C,9. + CONO DTC,130000(C) ;GO REVERSE + PUSHJ P,JDDS + JRST JDB3 + +JDF6: HRRZS C + SETOM UDIR(C) + JRST JDB7 + +JDF4: TLNE B,40000 + JRST JDF4A + MOVEI A,230000 ;A SHOT OF FOWARD + PUSHJ P,JDCNN ;REEL WILL STOP + AND B,[700000,,] + ADD B,[40000,,2] + ADD B,TIME + MOVEM B,UFLAPF(C) + JRST JDB3 + +JDF4A: PUSHJ P,JDSTP + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + SETOM DG2(C) + JRST JDF5 + JDB5: HRRZ C,UTTM1 + MOVE E,UGOAL(C) + CAML E,EUPOS(C) + SKIPA B,[1] + MOVNI B,1 + MOVEM B,UDIR(C) +JDB7: SKIPN B,UDIR(C) + JRST 4,. ;NOT TRYING TO GO + MOVEI A,DCCHN_3 + SKIPN SUNIT + JRST DCGB1 + CAME C,SUNIT + JRST DCGB2 + CAMN B,OUDIR(C) + TRO A,40000 ;INHIBIT START DELAY (SAME UNIT, SAME DIRECTION) +DCGB1: MOVEM C,SUNIT + MOVEM B,OUDIR(C) + TRNN A,40000 + TRO A,30000 + DPB C,[110300,,A] + XCT UTST2(B) + CONO DTS,770000 + MOVE C,[JSR TAPE] + MOVEM C,DCMLOC + MOVEM C,DCMLOC+1 + MOVE C,[JRST PIPOS] + MOVEM C,UTP1 + JRST POPRET + +DCGB2: PUSHJ P,JDDS + JRST DCGB1 + + CONO DTC,130200+UTCCHN+(A) +UTST: CONO DTC,430000+UTCCHN+(A) + CONO DTC,230200+UTCCHN+(A) + + CONO DTC,130200+UTCCHN(A) +UTST1: CONO DTC,430000+UTCCHN(A) + CONO DTC,230200+UTCCHN(A) + + CONO DTC,100200+UTCCHN(A) +UTST2: CONO DTC,400000+UTCCHN(A) + CONO DTC,200200+UTCCHN(A) +};IFN NEWDTP + IFE NEWDTP,{ + +; T S UTAPE ROUTINES PI SERV (OLD UTAPE CONTROL) + +JDENB==40000 ;ENABLE JOB DONE (CONO UTC,) +20MSEN==5000 ;20MS, ENABLED (") + +TAPE: 0 +UTP1: 0 ;DATAI DC, OR JRST UTP3 + +BBLK + + SOS .-1 + AOSGE TAPCNT + JRST 12,@TAPE + + +UTP3: SKIPN WRITE + CONO DC,0 + CONO DC,400000 ;CLEAR PIA + JRST 12,@TAPE + +PIPOS: CONSO DC,1000 + JRST PIPX + SKIPN C,SUNIT + JRST PIPOS8 ;NO UNIT SELECTED? + DATAI DC,B ;UNIT SELECTED, GET BLOCK NUMBER + TDZE B,[1777#-1] ;CLEAR OUT GARBAGE IN BLOCK NUMBER WORD + JRST PIPOS7 ;GARBAGE THERE, BAD BLOCK NUMBER + MOVEM B,EUPOS(C) ;STORE POSITION + HRRZM C,DG2(C) ;SIGNAL EUPOS IS ACCURATE + SKIPGE UGOAL(C) ;GOING SOMEWHERE? + JRST PIPF1 ;NO + SUB B,UGOAL(C) ;GET CURRENT - DESIRED + JUMPE B,PIPOS2 ;JUMP IF THERE + ADD B,UDIR(C) + MOVMM B,UTENB + SKIPGE ULDCH(C) + JRST PIPOS3 + JUMPN B,PIPOS3 +PIPOSL: MOVE A,SUNITL ;HOLD DC + MOVE B,UDIR(C) + XCT UTST(B) + CONO DC,4010+UTCCHN +PIPOS5: JRST PIPX + +PIPOS7: AOS BDBLKC + JRST PIPOSL + +EBLK + +BDBLKC: 0 + +BBLK + +PIPOS3: MOVE A,UDIR(C) + LSH A,2 + SUB B,A + XOR B,UDIR(C) + MOVE A,SUNITL + JUMPG B,PIPOS4 ;GOING WRONG DIR +PIPF2: TRO A,JDENB ;ENB JD SO NEXT BREAK TO UTC ON BLOCK +PIPOS6: MOVE B,TIME + MOVEM B,ULCTM(C) + ADD B,UTENB + MOVEM B,DRTM(C) + MOVE B,UDIR(C) + XCT UTST(B) +PIPOS8: CONO DC,0 + JRST PIPOS5 + + + +PIPF1: MOVE A,SUNITL + JRST PIPF2 + +PIPOS4: CLEARM DG2(C) + MOVNS UDIR(C) + TRO A,6000 + JRST PIPOS6 + +PIPOS2: HLRZ A,ULDCH(C) ;TAPE NOW POSITIONED + SKIPL ULDCH(C) + SKIPGE UTRAC(A) + JRST PIPOS3 ;CHANNEL LOCKED + SETOM UTLDD(A) ;CHANNEL ACTUALLY LOADED TRANSFER IMMINENT + AOS SMODE + MOVE A,SUNITL + MOVE B,UMEMAD(C) + SKIPGE URDWR(C) + TROA A,400 + TLZ B,(BLKO-BLKI) + SKIPL UDIR(C) + JRST TAPFOR + TRO A,10000 + ADD B,[DATAI-BLKI 200] + MOVEM B,UTP1 + MOVNI B,200 + MOVEM B,TAPCNT + + +TAP4: CONO UTC,360300+UTCCHN(A) + MOVE B,URDWR(C) + MOVEM B,WRITE + CONO DC,400000+DCCHN ;GIVE CHN FOR READ + SKIPGE B + CONO DC,3410+DCCHN + JRST PIPX + + +TAPFOR: HRRM B,TAPCNT + HRRI B,TAPCNT + MOVEM B,DCMLOC + MOVE B,[-200,,UTP3] + HRRM B,UTP1 + HLLM B,TAPCNT + JRST TAP4 + +UTERR: CONSZ UTC,4000 ;CHECK TIME ENABLE + CONSO UTS,20 ;CHECK TIME FLAG + JRST .+2 + JRST UTCB1 ;ELIMINATE TIMING ERROR IF FLAG COMES ON + CONI UTS,E + SKIPL SMODE + JRST UDATER ;DATA ERROR + CONO DC,0 + SKIPN C,SUNIT + JRST JDB3 ;NO UNIT SELECTED, IGNORE ERROR + SETOM DG2(C) + SKIPL UFLAPF(C) + JRST UTER6 ;NOT FLAPPING + CLEARM UFLAPF(C) ;ERROR WHILE FLAPPING, JUST FORGET ABOUT IT + CLEARM EUPOS(C) + CLEARM UDIR(C) + JRST JDB3 +UTER6: AOS UTERP(C) ;INCREMENT ERROR COUNT + HRLM E,UTERP(C) ;STORE UTS CONI + MOVE B,UDIR(C) + TRZ E,7650 ;CLEAR RANDOMNESS, WRITE, PARITY ERROR + JUMPE E,JDB3 ;JUMP ON ONLY PARITY ERROR (IF ANYTHING), TRY AGAIN NOW + TRNN E,2 ;CHECK EOT FLAG + JRST UTER1 ;NOT SET + MOVNS B,UDIR(C) ;EOT, WANT TO GO OTHER DIRECTION + MOVEI A,0 + SKIPGE B + MOVEI A,1103 + MOVEM A,EUPOS(C) ;STORE NEW ESTIMATED POSIION + MOVE A,TIME + MOVEM A,ULCTM(C) + MOVEM A,DRTM(C) +UTER1: JRST UTER3 ;GIVE MAX DELAY + +UDATER: SETOM SMODE ;DATA ERROR, TRY REPOSITIONING + HLRZ D,ULDCH(C) + CLEARM UTLDD(D) + JRST JDB3 + + UTCB0: MOVE C,SUNIT + CONSZ UTC,4000 + CONSO UTS,20 + JRST JDBRK ;NOT TIME FLAG +UTCB1: MOVE A,SUNITL + MOVE B,UDIR(C) + AOSN UTHERR ;HANG UP ERROR SENT FOR SLOW CLOCK ROUTINE + JRST UTERR + AOSN USTSW + JRST DCGBL1 + AOSN USTPF + JRST JDB7D + MOVEI C,0 + EXCH C,FLPUNT + JUMPN C,JDF8 + EXCH C,STPUNT + JUMPN C,JDB4B + JRST JDB3 + + +JDDT3: MOVE A,EUPOS(C) + SUB A,UGOAL(C) + MOVMS E,A + ADD A,TIME + MOVEM A,DRTM(C) + MOVE C,[-NUNITS,,1] + MOVM B,DRTM(C) + CAMGE B,TIME + JRST JDB3 ;SOMETHING ELSE DUE + AOBJN C,.-3 + MOVE C,SUNIT + MOVE B,UDIR(C) + MOVE A,SUNITL + SOJLE E,DCGBL1 ;RELOADING FOR NEXT BLOCK + JRST JDB3 + + +ILLP: MOVEM D,UGOAL(C) ;LOW PRIORITY POSIT ENTRY + MOVSI A,(SETZ) + IORM A,ULDCH(C) + +UTDC: SKIPGE UGOAL(C) + POPJ P, ;UNIT IDLE + SKIPGE DG2(C) + JRST UTDC3 + MOVE A,EUPOS(C) ;ESTIMATE UNIT TIME AND UPDATE EUPOS + SKIPG DG2(C) ;SKIP ON EXACT POS KNOWN + SKIPN UDIR(C) ;SKIP ON UNIT RUNNING + JRST UTDC4 + MOVE B,TIME + SUBM B,ULCTM(C) + EXCH B,ULCTM(C) + IMUL B,UDIR(C) + ADD A,B ;ACTUAL ESTIMATED POSITION + MOVEM A,EUPOS(C) ;UPDATE EUPOS +UTDC4: SUB A,UGOAL(C) + MOVM B,A + CAIG B,2 + JRST UTDC2 + ADD A,UDIR(C) + MOVMS Aî + CAMLE A,B + SETZB A,B ;GOING WRONG DIR +UTDC2: CAILE B,200. + MOVEI B,200. ;LIMIT LONGEST DEAD RECKON + ADD B,TIME + MOVEM B,DRTM(C) + POPJ P, + +UTDC3: MOVEI B,0 ;NOT KNOWN EXACT POS REQUIRES IMMEDIATE ATTENTION + JRST UTDC2 + +JDBRK: CONSZ UTS,16 ;CHECK PARITY ERROR, ILLOP, EOT + JRST UTERR +JDBK1: CONSZ UTS,1 ;SKIP ON NO JOB DONE + CONSZ DC,7 + JRST POPRET ;NO ERRS + HAS DC CHNL, GO AWAY + SKIPL SMODE + JRST JDDTA ;DATA MODE + JUMPE C,JDB3 ;POSITIONING, JUMP ON NO UNIT SELECTED + MOVE A,UDIR(C) + ADDM A,EUPOS(C) + MOVE A,TIME + MOVEM A,ULCTM(C) + PUSHJ P,UTDC ;COMPUTE DELAY + + JDB3: CONO DC,0 + HRLOI B,177777 + MOVEM B,UTTM2 + SETOM UTTM3 ;UNIT MOST URGENT + CLEARM UTTM1 ;UNIT COULD START + SETOM UTTM4 ;TAPE TO START FLAPPING + SETOM UTTM5 ;TAPE TO STOP FLAPPED + MOVE C,[-NUNITS,,1] +JDBRK7: SKIPGE B,UFLAPF(C) + JRST JDF1 ;FLAPPING OP +JDF2: SKIPL ULDCH(C) ;SKIP ON LOW PRIOR POSIT + SKIPGE UGOAL(C) + JRST JDB6 ;UNIT FREE +JDF2A: SKIPGE DG2(C) + SKIPN UDIR(C) + JRST JDS1 + MOVEM C,UTTM1 ;UNIT IS RUNNING BLIND (OR NOT RUNNING) + JRST JDBRK6 +JDS1: SKIPE UDIR(C) + JRST JDBRK4 + SKIPN UTTM1 + HRRZM C,UTTM1 + JRST JDBRK6 +JDBRK4: SKIPN UDIR(C) + JRST ULLP ;TAPE MAY NOT BE RUNNING IF IDLE + MOVE B,DRTM(C) + SUB B,TIME + MOVE E,B + SUB E,UTTM2 + JUMPL B,JDCV1 ;ALREADY OVERDUE + MOVM D,E + CAIG B,20. ;CONFLICT MORE THAN 20 BLKS AWAY + CAIL D,20. ;THEY ARE SEPARETED BY 20 BLKS + JRST JDCV1 + HRRZS C ;RELIEVE CONFLICT BY STOPPING UNIT DUE LATEST + CAMG B,UTTM2 + HRRZ C,UTTM3 +JDF5: CAME C,SUNIT + SKIPN SUNIT + JRST JDB4B ;STOP UNIT + MOVEM C,STPUNT + JRST JDB7D ;DESLECT FIRST +JDCV1: JUMPGE E,ULLP + MOVEM B,UTTM2 + HRRZM C,UTTM3 +ULLP: SKIPL ULDCH(C) + JRST JDBRK6 + MOVE B,TIME + SUB B,ULCTM(C) + IMUL B,UDIR(C) + SKIPE DG2(C) + MOVEI B,0 + ADD B,EUPOS(C) + SUB B,UGOAL(C) + MOVMS B + CAIGE B,10. + PUSHJ P,ULLP1 ;TERM LOW PRIORITY DIRECTORY POS (COMMIT TO ACTUAL WRITE) + + + +JDBRK6: AOBJN C,JDBRK7 + MOVE C,UTTM3 ;MOST PRESSING RUNNING UNIT + MOVE B,UTTM2 + CAIGE B,30. + JRST JDB7 ;STAY WITH PRESSING UNIT + SKIPE UTTM1 + JRST JDB5 ;START UNIT IF POSSIBLE + SKIPL D,UTTM4 + JRST JDF3 +JDF6A: SKIPL D,UTTM5 + JRST JDF4 + CAMG B,[10000000.] ;SKIP ON ALL TAPES IDLE + JRST JDB7 + SKIPE SUNIT + JRST JDB7D + SETOM UIDLE ;NO UNIT SELECTED + CONO UTC,0 + JRST POPRET + +JDF1: MOVE E,UDIRO(C) + AOJE E,JDF1A + TLNE E,100000 + JRST JDF2 ;DONT FLAP IF DIR NOT WRITTEN +JDF1A: SKIPGE UGOAL(C) + SKIPGE ULDCH(C) + JRST JDF2 ;FILE DIR WRITE IN PROG + SKIPE UDIR(C) + SKIPG DG2(C) + JRST .+2 + JRST JDF3A ;JUST READ IN TAPE POS + TLNN B,100000 + HRRZM C,UTTM4 ;UNIT TO START FLAPPING + LDB D,[4100,,B] + TLNN B,100000 + JRST JDBRK6 + TLNN B,200000 ;ABORT FLAPPING + CAMG D,TIME + HRRZM C,UTTM5 ;UNIT TO STOP FLAPPING + JRST JDBRK6 + + +JDF3: MOVE C,D + MOVE A,UDIRO(C) + AOJE A,JDF3A1 + TLNE A,10000 + JRST JDF3A2 + HRRZ A,ULDCH(C) + LDB Q,[IOCH,,IOBFT(A)] + CAIE Q,NUTIC+NUTOC + JRST 4,. + LDB Q,[IOLO,,IOBFT(A)] + CAIE Q,(C) + JRST 4,. + PUSHJ P,IBRTN +JDF3A2: SETOM UDIRO(C) + SETZM UTASS(C) +JDF3A1: SETOM UDPWF(C) + SKIPGE DG2(C) + JRST JDF6 +JDF3A: SETOM DG2(C) + MOVE E,EUPOS(C) + IMULI E,50. + IDIVI E,33. + ADDI E,30. + ADD E,TIME + DPB E,[4100,,UFLAPF(C)] + MOVSI E,100000 + IORM E,UFLAPF(C) + SKIPE SUNIT + CAMN C,SUNIT + JRST JDF8 + MOVEM C,FLPUNT + JRST JDB7D + +JDF8: LSH C,3 + CONO UTC,235000+UTCCHN(C) + JRST JDF9 + +JDF6: SKIPE SUNIT + CAMN C,SUNIT + JRST .+2 + JRST JDB7D + SETOB B,UDIR(C) + MOVEM C,SUNIT + DPB C,[30300,,SUNITL] + JRST JDF6B + +JDF4: MOVE C,D + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + JRST JDF5 + +JDB5: HRRZ C,UTTM1 +JDB7: EXCH C,SUNIT ;SELECT UNIT IN C + JUMPE C,JDB7A ;NO UNIT SELECTED + CAMN C,SUNIT + JRST JDB7A + PUSHJ P,URLS + JUMPGE E,JDB7E ;OK TO LEAVE IT ALONE, CLEAR SELECTION CYCLE + SKIPN UDIR(C) + JRST JDB7E +JDB4B: HRRZM C,SUNIT ;ENTER UNIT STOPPING CYCLE + DPB C,[30300,,SUNITL] +JDB4A: MOVE A,SUNITL + SKIPG UDIR(C) + TRO A,10000 + CONO UTC,205000+UTCCHN(A) ;CLEAR GO BIT + SKIPE DG2(C) + JRST JDB4A1 + MOVE B,TIME + SUB B,ULCTM(C) + IMUL B,UDIR(C) + ADDM B,EUPOS(C) +JDB4A1: CLEARM UDIR(C) + HRLOI B,177777 + MOVEM B,DRTM(C) + SETOM DG2(C) +JDF9: SETOM USTPF ;UNIT STOPPING CYCLE + JRST POPRET + +EBLK + +USTPF: 0 +STPUNT: 0 ;UNIT TO STOP DUE TO CONFLICT + +BBLK + +JDB7E: SKIPA A,C +JDB7D: MOVE A,SUNIT + JUMPE A,JDB7D1 + SKIPLE DG2(A) + CLEARM DG2(A) +JDB7D1: CLEARM SUNIT ;DESELECT CYCLE + CONI UTC,A + TRZ A,200070 + TRO A,5000 + CONO UTC,(A) + JRST POPRET + + +JDB7A: MOVE C,SUNIT + MOVE A,EUPOS(C) + SUB A,UDIR(C) + SUB A,UDIR(C) + MOVEI B,1 + CAML A,UGOAL(C) + MOVNI B,1 + DPB C,[30300,,SUNITL] + MOVE D,UDIR(C) + MOVEM B,UDIR(C) + CAME D,B + JRST JDS4 ;CHANGING DIR (OR STARTING), ALLOW RELAY DLYS +JDBK3A: MOVE E,DRTM(C) + SUB E,TIME +JDDT8: MOVE A,SUNITL +IFN IMXP,[ + SKIPL IMPXF + SUBI E,2 +] + SKIPGE E + MOVEI E,0 + SKIPL D,DG2(C) + CAIG E,2 + JRST JDB3B + CAIGE E,20 + JUMPE D,JDB3B ;GETTING CLOSE READ BLOCK NO +JDB3A: +DCGBL2: TRO A,JDENB +JDB8A: XCT UTST(B) + JRST POPRET + + + +JDB3B: +DCGBL1: XCT UTST(B) + MOVE C,[JSR TAPE] + MOVEM C,DCMLOC + MOVEM C,DCMLOC+1 + MOVE C,[JRST UTP1] + MOVEM C,UTP1 + CONO DC,4010+UTCCHN + JRST POPRET + + + + CONO UTC,330200+UTCCHN(A) +UTST: CONO UTC,5000+UTCCHN(A) + CONO UTC,320200+UTCCHN(A) + + +JDS4: JUMPN D,UTER3 + MOVE D,TIME + MOVEM D,ULCTM(C) +JDF6B: SETOM USTSW ;STARTING OUT +UTER3: MOVE A,SUNITL ;PICK UP UNIT SELECT FIELD OF CONO + TRO A,6000 ;SET FOR MAXIMUM DELAY + JRST JDB8A + +URLS: SKIPE E,UDIR(C) ;SKIPN ON UNIT NOT RUNNING + SKIPG E,DG2(C) ;RELEASE UNIT IN C E HAS PREV STATE OF DG2 + POPJ P, + JRST UTDC +};IFE NEWDTP diff --git a/src/system/whovar.5 b/src/system/whovar.5 new file mode 100755 index 00000000..0aa8b2d7 --- /dev/null +++ b/src/system/whovar.5 @@ -0,0 +1,158 @@ +;channel header pointer (location 40, read only) +; +; ADDRESS(channel header area) +; ADDRESS(pointer area) +; I/O version number +; source file version number +; 0 always 0 +; INITED non-zero indicates PDP-11 is running ok(can be cleared by PDP-10) +; 0 always 0 +; GDOWN used as flag by PDP-10 to acknowledge clear of INITED +; +;channel header area (aligned on PDP-10 word) +; +; KBD channel: +; KBDFLG cleared by 10/set by 11 (chain of activated KBD buffers) +; 0 allows PDP-10 to do SKIPN for activation test +; DPY channel: (1 per console) +; DPYCHN buffer assigned to channel, if zero then DPY channel is closed +; DPYKBD .BYTE KBD#, DPY# (377 for either implies not assigned) +; KBD flags: (1 per console) +; ECOFLG Set by PDP-10. Next time DPYBUF is empty clear ECOFLG +; and put flag on KBD ring to signal this condition +; CHNCLS if -1, log this guy out!!!! +; WHO flags: (1 per console) +; WHOLIN who line variables for this console +; WHOUSR -1=>do system line, 0=>user who line +; +;format of KBD buffer (aligned on PDP-10 word) +; +; KBDSTS negative=>-(data byte count), 0=>free +; 0 +; KBDRNG next KBD buffer associated with this KBD +; KBDLST next buffer on activated list (0=>end of chain) +; KBDCHN keyboard channel +; 0 not used +; KBDATA key board data area (1 PDP-11 word/character) +; +;format of DPY buffer (aligned on PDP-10 word) +; +; DPY10B word PDP-10 is hacking (used only for initailization) +; DPY11B word PDP-11 is hacking +; DPYPP page printer variables +; DPYLGL last legal address in this buffer +; DPYSIZ size of data area in bytes +; 0 not used +; DPYATA display data area (1 PDP-11 word/character) +; +;format of pointer area (aligned on PDP-10 word) +; +; ADDRESS(system who line variables) +; ADDRESS(PDP-10/PDP-11 communication area) +; TENWHO (SET TO -1 WHENEVER ANYONE TYPES WHO LINE COMMAND, RESET TO 0 WHEN 10 +; UPDATES WHO LINES +; TENWH1 PADDING +; +;Notes: +; +;1. All addresses and pointers are in PDP-11 address space. +; +;2. KBD buffers are ringed two per channel. While the PDP-10 is +; emptying one, the PDP-11 can fill the other. +; +;3. There is only one DPY buffer per channel. When the buffer is filled +; with negative numbers, it is free. When the PDP-10 writes a positive +; number in the current word: then the PDP-11 processes the data in that +; word, sets that word to a negative number, and advances to the next word. +; WHO LINE VARIABLES +; +;SYSTEM WHO LINE (one PDP-11 word/line unless otherwise indicated) +; ITSTCH # total # 10/11 dpy channels (read only for PDP-10) +; ITSCHN # 10/11 dpy channels in use (read only for PDP-10) +; ITSVER ITS version # +; ITSJOB total jobs +; ITSCOR total core +; ITSRU runnable users +; ITSWBJ # jobs swap blocked +; ITSJWP # jobs waiting for pages +; ITSTRC total runable core +; ITSCFU core available for users +; ITSDAT date [byte (7) year (4) month (5) day] +; ITSDBG system debug flag +; ITSTIM time of day (# half seconds since midnight) aligned on PDP-10 word +; ITSTI1 low order of time +; ITSUSR total number of users +; +;USER WHO LINE (One PDP-11 word per line unless otherwise noted) + WHJOB==0 ;job #, -1=>who line not in use +; WHJOB1 ;pads WHJOB + WHMODE==1 ;mode 0=>follow keyboard +; 1=>freeze +; 2=>next higher (when PDP-10 sees this state, it searches +; user variables for next higher job index number with same +; uname. When it finds it, it stores the number in job # +; and changes mode to 1 +; 3=>next lower +; WHMOD1 ;pads WHMODE + WHUNAM==2 ;uname in sixbit (left 18 bits in first two words, right in next two) +; WHUNM1 + WHUNM2==3 +; WHUNM3 + WHJNAM==4 ;jname in sixbit +; WHJNM1 + WHJNM2==5 +; WHJNM3 + WHSNAM==6 ;sname in sixbit +; WHSNM1 + WHSNM2==7 +; WHSNM3 + WHSTAT==10 ;status in sixbit, 0=>job does not exist +; WHSTA1 + WHSTA2==11 +; WHSTA3 + WHJ%RT==12 ;job % run time +; WHJTRT job total run time (one millisec units) +; WHRPAG job number of pages real mem assigned +; WHPAG job number of pages virtual mem assigned +; WHO1 user who line control word +; WHO1A +; WHO2 first user who line variable +; WHO2A +; WHO2B +; WHO2C +; WHO3 second user who line variable +; WHO3A +; WHO3B +; WHO3C +; +; +;NOTE: The PDP-11 will not update who lines until it sees that ITSTIM +; has changed. +; +;PDP-10/PDP-11 COMMAND CHANNEL +; +; CMDFLG aligned on PDP-10 +; 0=>buffer is free (PDP-10 can write CMDBUF) +; positive=>command # from PDP-10 (PDP-11 can write CMDBUF) +; negative=>affirmative reply from PDP-11 (0=>command failed) +; PDP-10 can read CMDBUF, then must zero CMDFLG +; CMDFL1 always 0 +; CMDBUF each arg takes 4 bytes (1 PDP-10 word) +; +; PDP-10/PDP-11 COMMANDS +; +; 1 video switch +; arg1: video switch input # (set by PDP-10) +; arg2: video switch output # ( " " " " ) +; +; 2 reserve DPY +; arg1: DPY reserved (set by PDP-11) +; +; 3 free DPY +; arg1: DPY to free (set by PDP-10) +; +;;other 10-11 commuincation issues .. +; +;;go down resetting video switch vs not +;;PDP-11 indicates it has reset video switch +; ;(PDP-10 then detaches all jobs with tv ttys) diff --git a/tools/itstar b/tools/itstar new file mode 160000 index 00000000..63ecbaa4 --- /dev/null +++ b/tools/itstar @@ -0,0 +1 @@ +Subproject commit 63ecbaa4989cf9abf0235c114bcb72575ae657f9 diff --git a/tools/tapeutils b/tools/tapeutils new file mode 160000 index 00000000..2d4559f2 --- /dev/null +++ b/tools/tapeutils @@ -0,0 +1 @@ +Subproject commit 2d4559f2da7838031b7d85100b923519b17cdcb7

LO1Ucf|OQeu9nv4Nkfv*ReWx%X1+3#V@Y^9kFLW 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 UTF^AOiIkmP9PNUqJn@5B7%wv-tWberl@Hq zr{h?aX(s8kX(mb2Oxn{XX_GOTo=lpP$t0OhPTEO3X_{z~X@i2B4FnD6_gkAwo70*9 zJkS4m{?Fe$&zJSB^|f)$#c%| z2Gdn*pu8ACz(?q!rm1@4{0~n-v!`27%m~uzCMWMGccxO#10xTOxl;NaDhzL?4gaqn z?WT^H-Tgf(3MJ`lN46`Kee0XQ30l~HOw9$WYaQzA`Vkx z=1H;^-1_GG>RSX^dP}LVTf(1Y41C&&8N_IK$VXwB?DL*wM+!@u%#gBE(nWHyHPEMZFU-K|ShD&YR=Z;lf zK{+kx0=#ZGIr5dh{!29;T~xth4UZ*C7oCmLZ7Hm5*XS{Ic@LUl-8>53M(`~2|3K8RePQZy92#nRidCPT?WK`6kA6r8*vF-p zwAka$9a;;zp1mHzcBiwH1%+qOLF|aR{>c)h6H03VZ~PWs(>=$OuCR2v52=Q&{)6_E1pRBS~9o-Im2EEU!F0a(kH#+~gWvZ0yScg*nYsz5CZ&3zo7GJd%_;nE^wBXej zhIaYFzKn`gD%$0N)ThpY=lCiGphVzk>x;_Z{~7WEP*@KIx(qZ) zl9&ovN?|Mf^YT37=~m(klV-6y&t|46gI;ts^7TGt%4lLXP_sq-K^>CA|1m0pio-^} zP|?WaeTD)E3=95L^Zj)g6ToMPnN^7|%&2sl9{94#(ER`2P?$$}nlya;mNW=@`2Xx5 z48oA$i|RA19C@nGu-6x*3>9zFE0Mw(9P#=vXr&C@$tPr+0&mCg{^l6>Gy0E>P!znMF5G9PqT;EjHjgfa(gl=OQ5s3^l-5(akkUnzrc=6+ z(iq>jmtHpjvf(1JG>DEu3roXyvl&)4WeAzJ-FYtV3k6~5j za%EU5@U%E(NRn59N9mdwX)>iLGg2?5bu-e1l%~x{H&WUluYbxs;TsK`J~v|=c}Y#K z`1Xl4las$U{6K~fyZ=d=NrOx`(kh?tzn#2~t+KHr(O8{zE<5Ly{zgL!w4!rx2I?a2 zCuh6=_~5!-OPDK!x_E)Q$b>H7jQ^+M1*lf%mhNXCzO6|I!=|5-&dr_f+&BD%O0AS6 zP_k}2UUe@|zp4gt+UCUW20c8@Ie4CE!_HyUQ-I2J?%R`Zw-@&-!%lWw1C{a=v%Vy+ zm~3=zc`Vkb54vRbvRm5IMysbs*f$Hb?Ub?vj5W36WbLv3Hj9-5VIK!V92Bi{NUdX& z7k;)87QRoaDP-ZI#M}2h{OtVxT^8Fd6>NCVflTvfP`*L?c+cy>^b8=uX9@FtsTnF6SreKqP;qIhK2~W7sI9d!fY7uOjnIer49d2wX&&bMrfOx2@2G~0W+|gu@@A)} zts7&OuXnZNT&JhCTX_^IZHl+qskL>ZyqP2#l4z2|v#i@)w|sK)dBfe2IrmIXj=Tg{ zT$ij*^7ubSoLrZzj2<9WhLKm)`BlUJ-lq)t)ym}Y=OHmPX!7J%s=3sqP|>7}&eqE5 z$<*OV?}b+wJBNVLVMIYXYa(px=~v-xjpjmavn#b=u`)(zWy%(}1R6?Z0SP;*;d@%E z1DK65{_4J??J{%tbikJtq>ipaV~q1*A^Xp2$YB@h$c?`9Yobzh*5oBh(+{TWG-DWg z!C1w|I3FJgrD6W5ZQTj)6e!fJ&abVA-Rw#lO98^M#C?CWl=$Y2jb;o~_{_AlIvq2kC`@j?Q1XRjSPHj5^;Qssj!rt+JtpwW7xvu&um4R@V-9uMjS1TpCovsLF!n_WRo=%b)K zG*BJ^fi#PH@kl!)F+vbqycUAT#BaVk5JCgiW$C-1(;k@5$p5}Ixrg{x($;F=Ae4Eu z6&5`DA|7ah@f{IJ1M3!Jdh;NwL0ZX@8z!-cw{A42WttX7#l$yIO7_hCC zK}toTU^6Q^0R6%Az%rtg{bzk3o|^4dpB}yHrrB<1sK=sq!Ds1f;piMQue})~AE_%3 zWXCF-E3ZTudnBEdM=QBDTi!(Lvxm17pdGu$Qoft}9PzcWfhNX#deM~_!$c{X70{JS z*>b3j*Jzy|h?*GX=}DRRuv3Zg92Kcky${>1XhDN#r6R~lQ#uu}1DZf?S`QWq%9h(e4sd1J%vhBCj%1ByT=ET#RIsv47{UGU|Uvd=FP{cCD>T z#`xk0Z(!Xq{*N;T%qZB@>rO+LmxcgEPqfl+D}dXjzw7BlI@3Y~x=I(d1Fo*gh$M(- z4{n)gL)<$2yT0=q{cufz6~t$`5cuCj7PfRjZi3P)Jk(t2S(I$t2D7)VU?-GmNlIBi zH#*Dq0-h<9#iwgYSm!jBvkusjAv+kpcX&dbZ}8caeR8bc*thJJAU3O1du;RjBEr z7qX5_7MeAg@!Rj`5+4VKEmLw}+B(0*hdHhw8&1!e1q(OjcPUd&RwZ72b5Nz2hDM8^ zF*Hjyjw&5S6-McA`mQ|Sw>+y%s3>gr$cufpf-FoL&g_I9WhzKeVS9XyC?yMZaKkKY z58NNJ{TA7>;RrQ8TqA#vY$t1WNAD-Tr3GoqwBnCdlAV=|Vt_y&Mf6z$1C*XSb0&Q& z$B6J?)4|bL%eo5SPn2gVJ&U*(iTaqh0`r9{B8^k+MA-8K+hn5ic#b<;Kg%l_*d`H9 zcY^Z3-RpxD;uB3tEK$^3Y21hXBvUn{%5$f-@BB9OM_m8sQP>udIv9`c@aZ^f8;@hw zc2j>}Q>Jf?4V4U3AiQ)%z!$d2{>MW#*Zk;=3|^2>wmn-9~_ zsU8gscM@x?Q(qqe_nPHy|zPx?zO5x1bTw|#9%=l9RH zPZacpMwWKQv_i}0Om9PJQ#&b5u^4hWC4fv9`0L@D>in0uMzGVM4rnEdG5?*KhC*+p zw4k{bN!D3T_F}SB+?l!QMMbJ91hu7B zqv#4yy4*Ba3hE6qmsUf=t39zRRuSLrvEjbUF{P`i|DnFiPED_icIT#9qgzG8e}p;6 zESR}u)Dt-8h#)gxjeNDrE7w1PibgL(Dy3+v(GG33J4&xryQ9p0xCHBRVAL11sGvca zW1HZa3^}O*A{q$F^gphGoHNoGnS3#rF<6SJ zummWl7|J=2duG~PSdr1E;1YIPAxOvJmz=wDQ?dMMMiB0Z}dgS;Vphk zpE7i(8mIh%7K_f55aY1Xc+fjJ`C?EuUOnv4p!A7O_)tF@osI!%R27U&q_^-2Gabd~ zl~>rH+w4xF4Q|HX8pe{+&yJ-v-KX;o_xD<&u<{IAf#z5}SX2Dyxyi}D2wEW{Mg|6l z!y_^fLMuoeCptfnw9&?GvY`8X zp1$7Am_K?m{a5;ePD*XroM*NbX6>={Ye6NLVR|>Co~bDXHb3ul7BI%=CFtfIl|sln z3iZr8?Sl=N{Ef)Ls6w}VVfyZFF4-5c@nsr1s1k#}ck}4v+rPmMe^42spd9L0>-erT)gCl?fbZ$qBH{k)QRcWfEdb1<93>U5k+^mIiPiia!5P ze@7uQo(sAUtxws?N3?glZr+JBfIQ(p*B5j-Td2yu^N$k!WoYioN~AMm(+GhFdm_h| zeb3}=#`HzLijpgBsj=ppXGY!wm3Im}CMg=())#a&0XYgOJ)H$Xq3;1@eq+RJn7p0E zB)$rDWj|l=#US~o!VSALQVyDQR4(C@z0 zMFU}}(Zuqniw5e({P68rB~a3$5~z!9`vKSP^Vzo8bd3e5zAMiq zCzxw1vry<3>{MTQj=X1PcrBB^|8V1@#Pi5z%A(D_8L(CplY#me=g{{q)6MYf_mKv=HL5o8OxsLSUqy5-dOg_ z8Q~#0Ccd3<8&SXYkHf*fD#nR;|)GRv}j{Z$w&~5+UaH;;YzALMQCxcCj zLJmU@3_jY8I?Ou%o5q2F2Vu#_SnnCyqy6suuRgOE_813yG#hA-kM(yHtp#AS0TcC= zdudZEK@E7d1f6Lf290w^poU-!x||Gn9C^(`G@OtNRccxbC|LYuHyuD=c{KcK-}xue zGTW-@vm&!|Dg;10B;k?7_x`RvWkWiI^%_b^$DnFpNau_yK|qf=QR$ioQ>|sh=N{Gi z%ucTKv0lJ5GKPjO^i}oAt1U>6^UNc5!{j9PV3b)liV9(3ps)bP)Taz> zEs#iKx?2#^35EC`J4oD|k)qh5bP+%$YCcS7bt(tfO70F$W?@)l-~DgjeO^a=E9k}V z1vEn>AV!xLGM(gIqPnOy*f$hr&0!BMfF)t7sxkL#HAse4Ee=JI676EY|Hh)l-*u9(PXIV{L}vTy2G%mdd|EB@sMq; z2Lf!yU=GaV7$lS;|1AtoQiTaYy)Hv)khwo=H3*;X*{d(Zvqvu&`2T2 z^Rt5iFQJv)_pY*)vabzeF`zUGn1oZMxv&sGlYzkeB<5<1TD)A@636NgZc}H8S{}zy z-jr%K6?SH4Au>2;zUse~6j0JepDt;@kZr7T88v+s)^fl3_JB1B&TuoAl)7Zvrv|BM zB#b5^uVr}ksc#P$G*E$TJ_oX8<#EOUmdn&!BQ#_-(lf0Q4G9+Xsj?@a+vCOBu#~V> zeD?U+$w>h@n)Rix4H4fnY+IXuf6~=gXOOlo+JSogC%!$vC6O6JqEA_Udb~=#t& z%aWJxP$7%DVWH%GGGl{#0TSCxb0I~a2c#eQbg+`v9q0xo{vc4^1!B?7z523$LBrjP z#CID@Xk8;!aw^-n(AnDAcwE<9+{G50qw+dJzoSvL_}l z>Tw!%&Jrepuk3_yscjY?H)6x|la*Yg)XYBklzaPK9}YV&_MQKMIE?KrKt!bJt?S_O z&`L|>a&_F<&cW1J$UQ?!Q(D*2cC+wE1!bwovN+W61d1Bpo{F*@Fd(loCG{ zcXjQP#FtID3;pY-R;=+%TtDW(t9Y1DbliR%|L)?9|hoKwoMyO1k+_<5aMR@s=jB4zb~ty$$<)`)8eH%E`I z*B>OlwP_{CT`DR;XKi8-@bt)=&kq>*2-A`*hC^Aaj=L;AbIH}0vvKI%?(3%_9N=ZO z9CsPAT0ANQBM-YR7}Mi^CvNLtR|^l_^Ha<8ww(bBv$S^`u|60cSLc7||HqPnEmZar zL^+q~Ypn_J5pvzYvIc%AGUKxko!{9{e0!K~*+ggGl^622f`UJ=&dpyQpe!dTT};#C z>993!(@^GwGIzK!YV68+i}t zOHOqjDJ8x~^OgsEw$-&5T}BUL`P7g8tpF8#kN>Tbfhtl@`fp8{D9#IyyVj2MOug=- z>RS9Cs`JnIFbPx7mTkbSjD$OHnFFuFE7Xp=60&m80Z_@6-f2Gxzx#2C?1x(3VGnk= zOW-#?dn^BL3h})xb}tr|g?MQ`?^d*v()>r!=L~#W7N0uq%DTf6Rlkc|? z-v_gRq)?om2Askdi^oF2Rw_xT$+~F-@Ued)$86$7?4HFQ^o%$+|2tSev(Z~fRgr3& z+V0X>cg!kcFw|AB75J<=Y)Rlyf24 zsU6|GHH7i2Y4lNLjq&NCFKyP!b0afJwUf&8#}uJgzoo2U=vqj(_C{uEWxbJkQw~`d zS?GTNYXsa)u?B0wI%}tI_v$0mpLPDonxadavG08T4N~ps0BbOIhc9i0tKwFu&f4XR zc=pm}DQfhMzDt`6|*p_$($_E9Wykfa5=UaN5De0ROoEa{#wV+Dq`s(X=T;7BI!K<&ON9wG5 z+?u}8Yg~|SR`oD(ji|4GzrB4!M(8hANnnzJMXvQvi zEOx8;(6}O6Kwc@AMS)3NoB-jPIngDf$Ihon98O&auV7aavlku>0qt482Ioi*9J4b7= zq9N}!S>Vh@=j6RQR+ltjnvP|y+XY&|8D(wYT;t?wD6n?Jb-bhH0sE~&Ph+&$a^y86 zu6$lA@%>zuPNJ9Pt;m~`tW@BbcNPl)$xXN*H_rn6P8220XKhKCTd#12u?~q2hCk^$ z|H~1p#AjHIau5R1VaQA%o`VUik36lW%@dLGm#wJfOIbd30h zG^4UbQyZD6V@`~$%80p20zobBxKpc3HkNzp^6+4PMEU0S*|LW}QRm+s{w*TOC_Q+b z#6$dljsiw|kXQV1;2@WU3Lq(-^EcO(b8LId&{6bW`vl}7qLL&NWe5qwPVVYH34C+x z%PLifLn{YJDluJD%yiNVxqnKr(jtsETl(m8%6eCNOFCJWAEIn2PtM~5orj~T_uyk} zh3IJsl|v#Cv_z+JqoEKvLM;B@!9)Z0jQ;Qrt$aKV7r)NU$)q$E?iqUm5nPsKpi}BH zuoG}+5xSx-1J_8RFgF-lYtSjJHE6VyB0B+62L~*7!sj^s4`B5my^lUW+V6iKRZ>Ge zGFDkpRvXtFV(p@0;rVnJy0Xe(DRtRK1OW5G7guP+w<%1iVr=x!GuTEPyK zN8?%}rMQzg=&(RDvo9lo%I21m{Z$y^l7vgTWbAp_)&@e5b~p+-z^p)AV-B2M&P2Kr zGRUE(wia%DNh}^dL&?;6=H1QvUu1YXXBUo8FE;q?>f$@tuZRc?D|T6?te-jZ9!=ot zHLytaLZ>oTc@e`ny_^og?1V)$)~8orrVbwDN*Zf3oecXq4=(mpxiTpD8t<#Ojh1c$+M9tueHznb$9tXO6UHM4G? za~P{@M1Jz924-CUnR?`Ea{k@l;phC8_Zind+^9M~Bt4_%=(Wc;J z7GlAYgjMb_na*+5Pw8&;%nf~v_2mbKcXo>Y}naiz7PMMdbj{<+cerRd|NWTcqUN#jG4h z4IlZ8eM*;EqV_NvoHI1?l-hG0bw&;)#G+cpKYbgQD3;f z5}3vq;xII5$VxT_t0v6TvDd#JFrsH|FEB|xhvLptOzZu42bAxACM`sE5q zL|R5EtjQMpSst#LW3%V{DDyr#g8i@FK(=bM&9?@X`_eFe7i+0ymHvomDKSXtNYA0l`Gumoa*t?hB4|!~1Au6=zNI<<#jg1=Ij315L={ZN610e zfs43^ef}S|4zcMRXh$1244G{tbsdh?bM^rmoUg4ocO9tqt!*m?iSMS|FqOT+CEQr# zF>RyIfaasi4sQ|F1spAoRwkr-+z5HpSUtKz>|Uf&z|>_`o%M`63r@ex3q1#NF!quD z9jn7#F3k)<+fK};2!(7bgJSmr=nI3m2@zQ=Y~%c08IsZ|*ssUsvO2V*IjCrbnWyt|uk0p* zHiZp;@ap&=$byMBe4g@I?w1d4kqd0Mw*K{BJw$xza)Avnia(e|06<~y`~Ur6hSM;q zvElCyREWU|G;J>KC;1|A+ZrY7BWSF%AG8>Fx6uwe#ZvqbCJQ#--Gr_*wH`uj%ceFr zCOM;9@yfVK1!rpsPUn7KSjpAbct4<&yp%ihi_;cNPJTPMYQzJc*!XaC-}ym?nFg_KqPo$V^W<{p=1vPby)nAA9wDQGe6pafj2b*pU+4;Br%#5%yY5e zM8Y^K)Mrh**Y@KALU0j6Nu?I8M|&Yad_YP<5-2SAwD9uQV=~;EXRxU5JVg0yV6S8g zB<5#o+#BZdHMoEX0;>d{!VV$grr-^X))_wsSB`(VWMEAxHh+`aF`SKz3f2a0HDGJ$ z$+2>vzjFu|x^C@%!4X4zvc<>)nBb~AJxGkoEl;ANkb~e^T0F2?<#Rkg@E{c7!hSf^ zRKYz;j8L5_1C`)I670qtccrkD^`BMXmHW9>45REhdB>zhmd9A~BUsUEYOz-8N|1v< z;my_-Se4hJS#?Y5_v0kq5xj{>9+L)=da4vR(H4~Bk&K&YmZuON4f0~tG+daA=Oyp)XUXAz3W@#u)de2%gtSwtryx?KEZ$UTL08Bt zrH0wOV{VKEdj4M{R0~^_U7P%gOqaTtN6r@`@`wo*p^pJ9P-DB&5RVJ9Vyy89LkUUgSudk%F~5d^4F_D z<7Y+KV*n2iKOU+1NK%(qtJID>IN#KK^UV_&?8-VE-ghBv zKkn=#GOPc?=dZp!)4qtp@Z&C?sSc)4`Ul8}B9fu9odVmP-(ZwVy0JRg(HIVOs>X)V z(G@jNpH>T{h4=&8)| z%_tIETKJ{LnzU0YcsKeu_>zAJ-Bt)ErIUE7n{zdF7&Y5ZT1gK+Zvn{Qy}TwF07+x# zTB<6b`Vy#K4urTv$RRx#;Z6fc*&4lb0Q*(xsz<3K%}ZmB5ue+ghN5N#fm1|;&w;}M zK(jo8T{*`eY&+6N7YDvFq}HTGnDH+-0~Zdk+o>(qVEcPZu&+>u`(vJ{G`#x%yf37k z2UZ2x+LYxC#zPCfrhz9w@fh$pgvO^gJSp!9K9-fgg7|XMujQ0AyRgVb@q4>mFtcr zZw1^WQvRdxKvI-ULb9KMdc)rT?C<-$4aA2F+1P^So_#6=A(t7J+{6YcvNfm+F|1>) zgetPR#Ux+DZl~TP8@N*&z33j%>FoCI?1uOBmiAyh&RRl3sj!>G95|T9HC^!2l1^Vj5xxmg`VZ^-c@|(HNCSg%|gA6sT1}R2vGdH==|*5El9zV zo~UD5@Lk!XuS})b;Vv=jwa=nT25``Z+2}uLOHaUNcp}A(jj$?y8@(SYy;3^z)h7#I zC%i3=?Ya=Vd^BB0DZiY)%f#>d9f-FV;nv!|K!3ieF7uGM{~1|lV(Se3j+#HgHut+sGR)bI*{`;?xs3l@qd6Gl_FNTSGR4!<;D59zc+Xs zAG3voD+Hi>HI zR-r$aZbhqH3t8`|Kj-Ji`DIV2#Z!vIJz8-hj*Big1TGS*(Zw6z`H=eI>VqO9`VxAt@`@_l1x?N5m>*_VxRP(hx1IVOy<0EJm(tN}U@ z>mPYTU1=jAOG}B~XhC^6xJ0~cM`N%zN;fCzun&46mp8laVyPD56pFk>^iqT|u!oP0 z(v8yHS_wik^lzZMx6=)n*sS(Z-^dME*@&mgleFf*m zp-Ul+Zgo?!P|lT?XfM~`mP|d=)m`dfl1|4#P13kr3dV&^Y&s&M;>pn;_^@yCdn)F7 z3u&FZNd27t)5X{BTjsAWd7JRcDflG})_IzOeWYF?@7JJ0J|gw5M69e4w>1!=vIV#- zaNLzi+b=+pfo3-2H5&WQ&$5?JPU5nKvx~gfXEaCWjgMwf-m6soA1qb)YVuj1AJ{CP z=gSxJ!*wm??-E}e6G=Wug@KM1>6(4JuIGJUxHCoJFUc!?e$A^*F zFsD?{hncT-Qbtl%QZx!z;3jz~iZ5U(fxCekuHo_QA~Y>sQ%Vh4`jmOdf!~I(v|^DG zpfEck&IR+9idcSdWqq9UXkAczO@jv+)aK>E@_%I>!<${Uz&e&L9c(1NUN}{y`vWJJ zph6E|ErNN@1s%YlrTtpGpN~Fj*rhHMigAAqleSVXvFtI%kj^^U140ga;D;{QZDtLN zfP&WTm{lpL!|*pm-cqoS39J`i;5UqRY|vhLLC&=q+blsk?Y*|x*p}76XIEN2oCA0% zqy9`dhtUPfF8iGJLYPnohQHl8aiu7uUFJC42+QEj4ts=8J)03Da~!H1Yz1a#hdWuP z9C%HuLwOg9Dd?3X13)!p|Q{TaOxT&s*}}ZVOB#wGsL2@&=Z=gOR2@4{lbct$rAkJ&B&Sdz6Wa|QPQV^ ziH56dibsYlUeM*$Uq*NKL2*Rl3dIj2uRV&eQy8BIwz7wGFR=ro>9{CvMX_)@kv3b@n^kg1y3LtM7KY$G@6m{X% zo-Wn`D!7P(PbSLyP&=<0ppM|96BQ_`<TE=P!KNOD0M&=6ll|N}r#m?2844mY9Rh!bB`B`5g&=G6qK& zn3T+|ye*vCf_0c?K$5Nm_}8xOc)ApUP{o}R z1a>&7J;e)YAxSx9D%6u(rsTI|?CYb{$w+6?=7pfq|2Rb?Mb1bEnITny-AumjL z{MaQ*>Sc~Ky%wOCRl@KXUhjMrT{K;}!bcV`xdm%z?9u+fuWp#1zk0WE8FYW=0UXf< zrX|eE-mVgT3qI5`-|QhGr|ixm*qK_86FJv@_>}_|fa&J)E?8plSvD?Ge#q#Esm8IK z@aAc;TnunM$Q-#a$Eo$8tn6qT+$?k8Lz_UM&Ix+!YqQIp^iqx|ATd(7Ke)P z>5EK)jv_4A@v$X<@2ze*+L1+k`LYB6w6ItS{Id}uaCPEXgzsdgFtd*L#T6{^fQQ!$ zTg2zEs5+_>K4N;Q`N!%!E3ZsPcW<4<3N0YMm0B!b z1&j2XXq=dF9Xm)*orc*6oO_CY*jvxleW?ZqkunoWD5rR)3;G42wmr72*b5g}sVeQ+ntvCJz@vR@}aX5a$2ELHiq8w{y zixNPyMPXys@f2=?D0`MZ%z1RSsC19!XcGT0nxY(!F4ipUGCbHUJs*Lsb%`KkpNr^U z;^Wn3J&Y#543;Q8xJ<7c+oYp1;&r()KH8ReP!yUKc8WV@{Ib#kUw|eAUZ=bEnpBB& z;d;4{Qo&1pqH#(0A86e1%CrE#UxuRW)2|_a{2KJfuc2!4`)5~8P=9m)VRo_8&$4lF zH(h}7i(NY{5Z^vi5!~gh2~4@>fNjVTkYi-lHfBbdQOh~*s`ua0WUDz$FE@X`@cMb= zt2f>!KAidd2kAtKS{%M+4`_S|hf5O-Mymx?*Fq{5k30OXsE$0U^DNt&k`~;BrJNbo zuF*Tn>ufv3asnQnVHjKf1; zg{@$YPi97_8KFO_MBK_BT8PHZ8~iCt&SK}uHHyH6Mp4OsHQR*w860g-BV8lWxeTF> zGZ+W4(ML}2BtBk-9BlFb0`7|oI{sux$VKk1=Cp1Ha9pDe%axlnff@WM9D$Ft7KOF5 z348dEsHL0(Y#Coq^Kma<3rQXJnPJpkx=krS`uq#8Q^)pyl;rMT{F~!`;#(>oBxY@g zRK64xB}ysF)pQO{kZxZJtZ8!#cA1oeae<>rr9t8U+&-G~gv1Bt2+q6DRPAC=4qEOLF@*+;IC> zPrksPVF~MET#}JqDof1pz@EowD_T11_yvV1Lnx8XgwKJIA){|8hpGr>sXz|V93lwo zYymSvD-ci0>r6!kzw^@DqQ0ZE1qAeuQUbg5h}o1!q~g}7^&WvCuOgUzr8IWt^`V(; z4+u2_SI4~9rt9z-BWXlEKnQv8Obw@-zbiIgFOBCjjU~NkY^gdku$l4 zJOfJcn8-7a-^iaY7oLpX=%%i%q5Itz2@e}5SfYEQw?~N(Sqqz9CC`Rr2dhD-AaC@V z#A@E4F=Ud2|?~QKh7L7W*(L2|bljjDi1{VkwHhv@He*8F{ zQi_YA$MP>Ty%d>r6NUtJl-&TQgyZ`08!^#>V}ydOfYa(T+Yh!s?x#T3EfF zR^OZr!!|0T*O_{3D|uG0GbcrO$gy=dj2$=8yv~IN7`qY1?sP7yZrl~Uf@_cPR!U*9 zTZ^SOv)8#e17@$M**9W^iX0Y{XOAN<4D~h(0@UGg!0z?1d*_n9uzMp*X*`2o(9`ZW ztcKm=UeEZAn*Ra2*Q58Haj}vv79ov?c&?Y{m&8+nOd zr>g~aZ=~Hf?iHj9fS?F=Z)7{7yL3zkYu``=Yd6x`Yr0^?dRV(Nz7>6Lgtdbz8FkP3 z=S1Q=Ln-XOsSS2-gxx!Xmq?CG^y*I7y^$?n-U7SV!|p-B5{mv%?GY&(xu$`4oOc=&xTH2YEFMta(&Qf1-{0yjZHTJmD8iA!o-1`AVBw|P zYgaqt6N>u*4nN;P7mj3mDAapPD`Iw%XCl=_9;IQa5O`tU($*+(h$wGU zN_v{3W(Q9>Bhr~S0+4xK52biZH!PV;UZl5l>&{B@Y^cM#io7ULNxkF+L)y8RJbb6I zzpIVB!SP$$?inI4hWMmyp+qm~;=rrOVLCeyB=eW4Vb-PF`Ac|M4TG18?xQ;gz9Xx4 z@2}(;e8dt;fxaOso6LCMVTp(ZeP9f1f=WvV|9{lp0VL%O$WCMBdQb& zM7qA`5Xg#j?o!y9PL@+& z94Mks3zZm01J!w&JfM%%iA@4uWWl|(2;hrZkN*#*)s7E`#-K$g2vo{9r;x^`V5kDA zw=#AK>!6-vm)JoOXFJ7CdwxK>74vpa^P&O+O7m94ug57PmUZJpZ+z$Vo!+#a z{0*qN;&YU@Vty-sTNpMp^rqo{5a^={&0r_bK;DDo>5=Y$)M27jut568civ(;GbxN2 zG!E%%){F-+cIWN>Q7;DNviYA|Z%SrQU}TV$j=y*X8?8=qDk>mq;n9UXx!edvWxv>e;%Ka$p_fxgSCPh!x7Mr+a zs^&ky`4(_e@M_8O1|NS%jFu3&z8hC?97g1c(vzt_gnuopZIDa#n8VMvzjIjr{Y<>HwF|Ojc0LIJg6W_W2Od= zXR(VDNeH9~^yVfwI8R~|3<9GNRPiDff*fHFPYqB{VmAB8Luob$IuK8y{ERS$<*l$S z>;*WuTVa>bA`Z)2VXv>s&0n_AM0_+gwD(rni_|@ar6+Nn6yx!hBeas90d-KDqB_@O zVmJ4D%R4iUl64otCfG2p>y8gCdi*$f6QCMjAn!D&@7@f6FYm0zylGT#ly}xR8UIXr ztE$+!aN^^`9f{}zwy~=EVDo1$Tuph5==Mo#y;W=UXroS~?bHwZssq0X&US;Eb1x`N zOI6jW&7dr*=0IaQT1%()jVE5dE_rJXGN= zhHk$ez~ZgwtenC!bo-|PEa0sTU;(u+fCYIYrmzh8bO9{jsVOW&zPVdin+H6700E`l ziKY35GT@60rqtnGP4y{rpLew(!z;!-K6Li?Z-WPeTy1cgLBWJ;b}bKd`1tLDF9qgV zQc|!E)G=9X8c11@1753U_ok&R&jemL%^HrRX7|ZD^2}aWK~gJu3RE==2>SDeb{%Tn z-yM4>p710Gc)MI8HF#a+hgz9I?{%#T@J!y&W97m#fZ8qT5MNpuoKU%?A$wv1ExNTT znr6U2cvbl>Qiyd!b`+7q?~<=-7bzmrkTc?Q5%Jk#lf*Q}Kf3h(M4*(9F8z;)TaVoy z>m)wL0l*xezFlHE1JeEW4f6EhrO4c20`K(*@(kd$VX4BF$ETgv$TNbMzll5>s3vwV z7Kica-X-LPfQoaFXGST{-AA5%{G+eG3oKZ&g8Cjx#*!7(uTU=*s^0iaw>=?c<96P_ zi!5e3Ao%(#k`4$mn`N;C1eqI98<(Q-nN_F_3s7(QI{GROx1p5py$%vXVJI~mjs#+F zxwp&?3dU5vH7#HV-tukL`Q$;mEvcROFn?x0vym(vcw44ia{0DqEP_xBq&;ts<(F^b zp;n|s{wDB#^$w+&NwfbAhrrZO`PS2B@{HcH}ERj=Q{`^z2P)ck5K~RWns$07_R9SMH zm39S9R<~|C3JT6NFTE2ZMep{2*J%~~0YTd|)n-9^xdBprnqi754fS42c`v@P?NAQ! z?VQrVHT($%6pWJ3gt9iqTYq=^T~Ms|OnoURVmY&BKPVzNv(70L%1b>73RtR7?>2y9 z+y3s?8(Hs{yw#iNA>bIQ8|Lp2AtakIy0&KW`oY8HCj2W0uUYoX&Vv_CmRbdBSvb?(H$MEtcV8fHHF!m0YWE|@ zAt|o{(uZGSx(C3+cTf0N32Jj8d0&I{E9^j3g}gxv^5<<`&I_RPu*;*=MWpMbL8xj- zjlJYu0|^ zs2>Bh>Hv8gL6wVMo&XiMmb^{g>Rq)kAq2hN>fJ~B$ODlc*bo4SsFiI&_WIxOkyRm}Gs34Dd``%?b z8>q6^$qPblp1tISfH&_R^3341ttHQndZ&GNb$57**!B4EkK)n!uoF-j%aF{2c667} zi(|Cq6_PUaXy9$#3FB_rOMJPIawPodEJFg?|6X+(6vssOo-9xt+dta+9w^#>_m=IT z;NPmdPxXP&AUyF)vK(MFiVzFXALYoj1jp1}UPvia)xBvYDJZf#K9S7;wU?%84n@E0 zV}uXz-n`=7YW||Zs(ixpfY;LsY1ev)5uM}}lhS!w$A_QkdJH^F8P)stFb2es%_}CQ zb5PniJ!JRoKE-r^ykAF`Ld?%ZQ9;DKw^n$-{LBuhPrB%tqvF7Td9Nc6Xa*4Onzq-2$Iu{@ z0$z1HD0=Qg8D3Dd*F&qegQCBFZsH;-4e8d5l7ev_TE_J;!T)&o8d7M`kIiw$I(wp< z@J>k=jsO0keyUH?yww}Rk%}=>^~QMn6y%L7Q5#e`KK%HF_aXL>`r9^88mXT?2#S~= zzqS$-$JoYXEC7HR<@G`Zf_Y;c+d<45_Rw^R`SHEtU^P%31>|9$RR8j;Q|&lhfyoH% zfV7rT8|VC=n0^WhNb^cl;4AcPl#*h-d8IYI;JL}Gkx2n{{F#ccF16MY9=5Wu_QLe} z$s<#hy;vC`m5mR-xDen`8K?wy4Ey=x3J~n(0gg$G_Uez1u_7kQMn>u7Yqyx3Ug^cu zpMzq=@ghD3#y^jDjfy--O7m9#ZaxVp>_tz&8ogx)PpCT!JIi8-ZDGLUmmS&|#7-{t zf)ZnJladg0C8+wfECqkr?#G)VnQj%O;!hI6+aLjN9jJ|e$#e@z{f_DCk*+zJR2!)y zl;(nJi6^fe)Mj?P%0rG8nGiZCjoowXOsOJ14rjFp(&nYifm@hAZhn`%V&+IE@1VEr zaOgf#2-ko7XRnb818;p92zb}BLx;rpt>EQKBw=6<4n&wda@3OwVY*sU2Jl{vBxM6t z`8LZlL%L341%&@UUiW(4imfLHiH}`{4dk-JZvIUGY~hq0UKK)~3F#h^P8dYqeOTZ! za4$R5$-PEQY-NYdG314KtJg=vvq;cd&#!i2j^66}MWJFLpuz*g3RD*jox|#}L&QwW zs4tEI#lch`UI~g0;IU__(rcF(wh$ltlCGdWjBy5rRbJfD{a`VSTz_;w5g=q-kbwU) zm><44vw?T9t6>U3GS7izKqO08PXrfB-N>Th5_<0DmLUh^L)TZPOjR!G(4r`1r2>@eCS^CLhO#zUg4pX)W;tn&u)*dOU`FHi#>c^w<0fW z=*EMWw~=QZ`tYPboxBKpMC$%Z@d%8Yo47vx7}VmS9oDVA3U@~>P;N_FzD~9Mn?X+lCC-0z#QR2H;RHfnPUN3 zUhpOIBJAPIj%*+=#qQYWF_JeI`uk-Fc?*Yb6!tcghqkpYiy|+5==#52c!0clLm&KA z>@xB)?XJQ_>EuO0KhzB3`*o zeBqQXvd?qv6a+4`H#eBP0%)@K9_EO#J5$nDkXJ|@w2&8TpBJ5yL|(ByY@z8Gd2x2f z$z##vErm{393n5?9x=}>`dc=1t%|ZS-3oj3@wL_DX?A?%FB&SPhVI#z zd174)@wq8=+oRWYMli=pd-U3Za`F=Fj@T1x$y;T2u3X99q53bzA@iqtdhj0DceN1N``rzu;`^cMbk2rEz zBhP_j*Hv1RrR>B;;*%UOzaGs&Y1q(*e|!E7=18=McJI{43%5sZj}xQ|>=9v}RPrM1 zp_(U^=~BomA#W~uCFCu%J3@m!r&t*Ydtb-aLCqp5rEYnL{`F@x=`OMcG}! z9diDd4XUkj;#YS+v=N`IM5DqCi`sr{7?C@k1X)UlVOCvxlwT*hSuaQm3lw z%oXDPPO{_`_K4&?8l@VXlvk)!P$eGna_mv7wn|>l(Dip}o&Zbdu}5W9b01E37Owqq zJ9(ws%Ca<7U%%F&HmAf_6?W!jw5U7R|M^$H>x^2k!BaJF?@3QZ-kDQimmjPzOGeap{hwd^0Cl|fK~+lJ>7!L!&n(2oLsAO_KUuza^YUejKzz=X)%!A9_k`?-LptLcHb1(x*&JV0 zyw{t&Ol^ruif-K!m7JsQJo2v(J~F=Wa`oQM#H^~QmDPKX*KY}5m!sCs%kZc*O@kiQ zF)wMer#=Sw_N+e?qwPsP9H%;VX2g2#eE09yX5RUBfA!vu(ACRShb<{bRTUbSsLrjS zN;R*?N4ewIfBfm*El~?%nks@iJZgVz%O0G#6**JK7yi?~9^AYlwpQ(`9_-578?jHhD7T;c7a!eX1&hG$l3Ro>*xd7TYFu({sY?Ag06HpbJoBDr|Uo~2pEXrQLl zwzAAtJkZlp(Vlf#9<{1E!_|7n*T44QSo@!~+?F2!kk6`bw`Wgg2{k3 zF!1}WcR#oE4e+PP`vk!Fwt~t?e3XKa+v4Qj(S?Kk9b4BE>zBUp+4+|6Ds3H-robsV zOECaK@Ed8v|MpCOm$Q_Yd6&!Iosd%Rp8wYIT<8HFC)jzf52c<49A#ed#Iid4ZjbX` zetl9f(yCmE{9uv4W8r)me_0`<)bCXn?%``^!B*w0)N+t5&7pH;Xtla1{HXxm_uQ_W zU*pFyIr6t={XZ*`KL+N!szvjw%3}yTr2u|K+AfOYr*ONY@^v9)+J@t|XBve6m{gEKz`Y}po!~gi^A0VH^ zkLF%(BlUtnlY6xU&flT{@K|8R-@R~U$e-&KDH9*(N92$4i=oGa$JZzL`s7TKAMj_X zcv0H<Cgg#O+6fA{anvozZVcJLb- z(#nL04qg$BkE+0;Ny|`I|Vu!EXSK z!MN~8n(+NFb+VQ}siGU_kL8H;4i*^v`90^S(tBcRJ(m3PbeLKu2hf3GwD2mLsf)z- zT`xY_-{WNDqXL6%|3loHfX7)}X`|JPq*i2E-Lfpn z+WM0$YwK34)mpu`7E4~WdXXjBZh4bz%UJS)cW4KQ!GiD;u#L^|6CPj~0>mT?7cvP0 z48sJHVG_b+94^BUhatc)U`cMZWJ^Z(ea|PWiO2bG?)~#TSI^^eeO*eQ*K zQ%|pLMpjvTg|fZ@s9?Xu8G8x!G3MNZoZBb{_u>$(QJ#RmD4fGH@VremV^lsRRX74q zlg&6F7h~wJVx^2v-syrTjL@}nT&|KqDrEu1nvJ*IPdtSq`)BJ5GT@`bQ)!4^MZO=G zXFYg`K1cjjT=U>DcrERvtS@iY>!!r!`w1MM;T;ARo^7KF;Oebc=NW{zO;k3g;rE|D|tKrDr} zmLxL*`%y1q5ZjQH!DzoSdBgFmR&y}PL)Tsg`k&ntyx>1^F1{)~W-jqdcb6hTKQir8 zcKWhNT0*K9GVr)~`&w>iW`VDD$DlHD+l&pk8Er-oFj~^fd|lyQbb^MaLsqx&NIhPw z!6)IZ(SuX?4gMn#fY+mXOB2yls^P5|6Ggpde9~ROk9g0%qyGmPS%t*Utr0(vB*{Y> z=ts^$@yytO)1TCd-!h{*_L_}e)M4K+YRggS9nk#wX}i!i75Hh@<&~E792f#>7ngg} zC81+8R{q%Fz|FDiOBXm%- zZN=Bx@c316|11}DTQZPu@IL`c3pYf!YH=u`8F4{q=sUv@SE%v@qSh9C$)9u&0jvxG zxOBGrHv`14j`?1^t}L3B^n{eK-eibwXO^FYJ_TqA_-}=ra2JB{))t+}XU>*bZ-(_+ z=fR=_N4z>EliGTtkM?sL@bG%Rtfns2CfEK4y|4eh&f?09oa4&=tZsmCJlzae^P z-@hI^J`pq>yMJik50Bl`ydt8#YX}RI(*!jgnmO(>?OAE4a;#ZrSTwZn>tlDZY~=w+ z$Gsza$5ShY_WfVS?vlWIU z$|{YXT~#`Dj<2dLwb(n-^Q3cARaKl@Etr)uY>dexE{78qq_Sg|u3eaMQyuT~U+ zhAWyjS{Z2SN)eV-&4h^nYro{M6mK&DHxsaH>WWkzJxDHVW);nIGf{%|teW%HT5T1d zn{JDUvm%JMV9k{3R&A`O4fV9e-{e(oRmJ$KYt^vcK;8{ivy%6ZrT@>QSsmdEa>_cg zQkQ!>vf~qdTbgdt)RxsZdsSyb{I=Phgg!R(`jm5>YcrI(>Zy6?`Kz9#4?VxFImxOJ zXb950DtTMj()mQMW?S=OL}8}kZ?cy$m!Fc^6r;JjE)0U%KJDnLa#H^m}c~Z@Oi3E9jSEgHXrK zQcRxbMo>Y-*c?o}_$_6&C(oL^+?5H9gRyyxSs5#4%)*$PF*9Q>#*B>RGX@{`cP6hL zdJD0lrPgF;5HzPhVtbYrZB6bjUaeBniam6(?n0Kr^%$WeUjSz}yf|~RJMsG0J9bs@ zLSBl7-{b+?lqJD$`6r+Zex8yXgSX7>E9PaYl$ycMEy>g1O-Mx+ueM?u*ylg-hWJ9F zvS8#SCT>II0%;UKBR7K`4Ad*BYNt>m)F(Faiyp-(PHqW@@xq{S6f(;&)Pv3ophpZc zjkbEL+?;(==qxiOeY6@HA=Tv~l5PvVy3mbm%5i+^#*0my>woTB3JA>7yJe|akKG!) z+n;0;puHAgPlRFtG|48~kdOJgccYm6)@z02>UASvJH-8Tqy~+~%-XgPacP1n@Z!J^ zJ|KPzq{L9WO4%pyq|uzxH;X0}s!huFW}qu1ADQMHFtuIy2K(?6Zu*m>U0F*KeZiCd z6K{=%5e*VYGMB7Iuku+x={GBz`pD*`;1|Xoa^b;)NDVWh3V#1X(GF7R3D5_7bSg5OD}qAlBcq#20WQsgm% z!OQ*=zwE}`q;eKVT)bIgwd_TyRxXgjd49@IG;?H929#KX-uh@;>(s?0Upu>ZT>vc* zk21alP;M)J`>GdpeC6xTf&3UdAue4b;nJ0B3~g~FoSWrPTlFZU68exq{?!8ApeC=`-tBT-LEKI`n=6|zr<<9 zuw=PX`S_XFY9Nh_74T@(IX2C&44dH7I=Vq zu!E0cN7ENnj9^f_7`kt;NuBsr(PBe%7rUb%SOhjeEHzx{5;$?@s^E7BpDDb;o*D+a zB<0F#H$sPGsfMD(xknKv5oiUja(WRlz_2z;n9z zJF;iZ}Nl+XwokM(Xvx3CULm&r!L- z3qJz}m6!(vtKhGJP;fT@ux-{>V=nrm_kpvG9^yyeWf5$Cwrdhe=9?1i1r!e!lDTEz zH7bbgEj8IWBY6|GtJFk1 z7I5kUev7#nu%QHeJJF_k!bN+a^+@Kt5SfS*aJr0dU|)Q4ey@p6_+ zeFZV`z?`}XF-^g4ho=*vFd4?~F%67&7n^MKE^ky_#rjG*^@8Lh8oNSeHy2|?OL!N$ ziVfS<$fxtaK12LAwG^vVx&cakfB1JGi>Oqk5wgjt?+@MNIgkpcL2 z9)1;>>954V2aXFuB~X!%PU&@=d&ru@lGy=14kK3E80-_&q+ZEFLwked^R0yMw>f34 z%Y}ZsndNh9*B_N-i2TFT#d{?-0skv@V0lwF$LzFDT#QvEYW}Bqp#Da zC_`^}BJ488d1sqPH-ZzJdB=veHE^Ti5dlD>e;sQpz*8n^1py3i)5hh7=$>HWn?HPr z_)&eZ*W(>7s0CIxl!gbCy>oQ4rd{gzR^G|j(7_XW7Vv&WmDZ@|&Km~HYz5EN9 z;WDCGM+Ms9poe1nOd9y|*tTyNCb;aO^ztVD`G4w5*8J1#W|DaBM3N-3C%cnKt zcrslljLi~Y-I*^`0*-v3I4ng6x7Z3vShde(O&;&&|dn1;Mzy>VVq;4|r2G|h+C6w_LQr8ttqEHBDphcluf5QUZ& zwqWQpW+?N5Q?zyj*y~Jd3idNg4%oL0nT;}v_?sy`%j8o_GfM6BNuSmxL%pmHSxBl4 z^gDU9d!7OF8e@E(*%W- zN@0-LDxBvQWoZ=_{6B!f&`Ja$(y{V){~x*>oo^z%(Bdu%m}U=ikVXx^iq!}^-zZ}? zG=zmAh8F#JiLl?nt`e}ujd%eo9=kzUh|=m|%B^~l?6U9C%57EQ!ND)VMm5IfX&OTa^fGAvori@~g3njx6^vV2ZfG)i13Q|tvH@RCK!vN1=cqd0~e z@YKuMM?_R=acGtdt-*IMKeCMYC1`l6q>ftY!=zQcP*<`@<@)C#pb;XDfYNdKj{n5f z5CG|@kz5Q=??zOl<)D~grRAY9g4NIulzqpa5nRdruYIS9U)GtqQelF0%`_8J(Dn^$TFP~^N@;7(H(0Y8ptfeh=Ey)$B;=j9JLn^z3M;& z1@m|O_Md}~Vxw7a3Ums%xWdp9H(C+F(@=OZE88xRKlloE=4=s!f(!QOR4M^HN_&Wr zdf(j1PXkk}^2yBH!v(`KGioDH_(dzkyk->1;stn>i`l~z(`{LvO#GT%#Q@-?iO{{0 zBCG`915uzvAwI1VD_*YbEffdzQfPl!Vo(XhHe-J|__wHS@;5yTTXep#9RQ?W%{hVO z%fpWWAqq1yX%!&^>rL@0)#AoyLiaVg1U~6q@hjrDv6m;TNGo0Ig1*@YH36HI^syLz zrTV$_(Q3x|X>BIr*Lxk5;1s`oht#G4KNHolFup%X$zprA zHx_k_`hbBu1M@J@NU{+qeMj4O3ImTG0AFz+N3v{$HWehf;sgL!Y5j4mQTlW`h~yM2 z&y_H@M#q^N1Ph!1%AQhPdFs+spr`3}7{L*aGo#FGZe#-J6($WI-TZhuOfW#|3d~9A zn{y((*cqkBC-;P!Hd>8*LLlAL5DpuJP$XamW)&XO??!$PjD3|DDDpdAoCNNksnr(Q z$E`qXQ--X5C?@}i0#}}BvtK28F;~!9sx7t)TCAmOhHp2PH?~1XB#!@gUna@mnO60ZLiuKy$HvrX=N4{PMv;c%>`R;_Uzj%zq(Zc&_q&&4NXP zE8ODk(c~DoiYxfORT@yeO z3&MnN3w#S)B15iZDV`ye(W{FN$PZ4}wiMAmi*8yOx0d)V1UZ z-86erMC-np6CgPw@OqTiBuzk;Df@fF(bJ>f0{Gcxob?ihqsb*!xC9&IQQXZHLcYZYpKjCz;A7augcBKiC?QoE6Lnygt(LAC9TE= zEaE;@ebMka92F6G6GIK0-4`P#9)_P%+RJDH7E|alC__Cw*w=*$aA0NzR_akAb}Y_$ zfHHJ1M!mqpQ&veugJb?a@gY4!)6d@%@hiRlkw0@Arf_(O)Rq@8-R_#FG7ofn&_JW!7}GZzI*f^*RZu0`~7O=Og&I)Wg$`}!0VgL z7YatC*dGV|7G{wES9@>kSDNiS2Kr&jk)tWs1?cO;`3%zfz3OlqgQ9Q5jH>Fb{#aGL zr=PLlf>rMxzj#Yd`c(W@bxD5HV^EDNfYmnw?wJ+pffWQjsNjI?;EiJa8qxhz0Y+yO zx6sf8gIZR_pdu6-y6Jmw;LPDzIxR^_kytLa9|Qf;*~yqF4P$O~IG5x!0N&v#R@}zUaeLL`G^8$GF*g5^dtrsm zNp~RM;@PoG^)MCr3g_XoZ~^ia-U^%xUk^5@!k+`7!YxS6KMW}OhkfK=CRKz1GM_wu&}{3i56JC-|A4p%;|5hey%q-tn zgM+i_r$GW7EhzpEWs-mss8NE^7k*?lTo+v3^Gj>ke-9LYgGs`p zImehXwB*`;V>!AL)Ufx@_%0#siCgs%PoC8;@ws&wd1I*q!O0D{D1IgP|tTXPD)c z?!=ch)~F$F2(vbE6|JTiy0H41P?c&IU`ASk`CfH)CL%UB&W8X%F6aKD@5yaTq4lm^ zkm}a8sdcM;*dD1zYA2PeRSOVXw4edUUGfkUC9Kv1wWijC)LIXqiY7Mx+@qNXfnP>M zXB88ulZke=Z8Pfa!ap5eCm^Y<{M1!BCt@88eE6r@n0f@R?u*9#s)F6VyquPk0Dl9gILaa#B$j?xhay0Ap7F5_5P|+;#Y;w9G;0-&MeD$;zWBLF>O17 z8Jxf*$kh-_vLVRgd5Rg0$k+ALYrk!y$ljKWAa9+dUJJIZMl7og30W^AwvENMJ%O0k zjzHiEs2vya8LBP&tI;)Y?L9;MI#42eI#N@YBFH<$;1>Lri=Azin~oqm5m`#zm<^U(XEITzk^`g^9XF``PMJ?gSs+~BX#Bu1Ua=x$eD@2@dZC47_bT3 zHX(3;d-QtKP*SIJ%7$yd3Az(OZ#eiqc$YupT+voT)Re+3HB)~b&=rmykaDYc0dAPw znei|*S^X4%Blwwm@D8vFUY+0rQy9L9)z~|I@QwnO7_#}5L8~z&Rv|SaUDlgWmTYBQ zm(B=|AfKpGvVn$#lsmow8IMz44|&9j-*8@AhnIb=-Uv|~)a7%p@4SQf{S=^#c#;jR z1-uBnbb}J|o4)P*TjIw(J6y7O@D8s2#9{R@5ca{UfWiOZ23YkUeAHzzBsOZ%$Ol_| z)K>wMzb`q%iXCxWJ;Jke|BS;wS}ZY_tsm!JBv!?7Z3%aXDcS^HAnA`JYd85>)5ZonEzPWn{e<_|2T&NuZqsifd{QeLVIDWbVwm1!ol(;)d1OAU~Hn zQ*2|GPUk-{cIh{%C32CfvuX3eIi1bR56-M($h!j2?d zE&fCM#|U;5ZDWaT&A8`=plkNFw)v5>uio_IkuR?9`NjJ?chtvs&EA=nnO~Iqt(!bV zuV`mh)_mWtjH64-cFkOo+}djoOUC)~zt|bZ|Bs-)zPa|)Y~t7WCjnsDndDJsmAj_j zpq5WZFmt%ykdl2BG5Clws}*zmA5+_-@wx3?1or95Y$-Vcv6H)`-(W7SP?;*ngM_>l z_$>L-u+mb`gpzZ}R~m+xHVi2CjER^ll9No`R2w-!4^Mo|J}sbwwyv z(2UFlw;^!XGDzlco6K>_?c`@ZYO6bgSjp2^$7FtqCgf7^Wt9Oy&NTdHk1|*+_6#JX z^%$n8%qk>A@0$oLC2W>m+LlZxPf(D4ip=&H2Ka5tf!l~*+rpeV<&=Ii?_s`&7~IdY z^OZT#z5~TdJ_Rlylf_c90cBTw#m`0jT-k2~;s{C}=`Tu2>Lo4}{5(zi?FJMsHdKa> z)G*+4xd~;LeSmyj_5CL0cmbb|xAEzyMT_8f(ySa=OkIswos+>VQ=xT#F7bPs^@gF? z^0#53th3>>ZWFS^q~i17G_3SeKt%Kc03bkFH_*_+`y*A?BS7Pu6T)Bcb8NxxnQg@H zt^aMHm`pM?2!DGK1Kx?k^_lPZXI_-aL^odWsfv(ApZojv;Io)KTjOzQ%vB0GjVC)V z9_fv1f%3+)5b>#T=4#^iDL&=4z)Y_0GiL|PFJWWd(}2lj4FCl1K`=baKl2kU#W&M2 z2Au)+ypTFhLcLDf@LiQ5u)0>8{K&phAEC>MUy5X(5sn3b_Tj9D1l z#h96~os1b7>t@UltaoReANm)>irRe{J9JA76(C1oHiQzum{HSeu(es3s!|#b6Tb~qj>liMZAN!n1pC4DXa8;&@jE(rRrNWka zpCc+3_9G0mUYb4%nEkNP@>HusLmgtD)XyM;x40jcxu=5?5Si^8TCt&7)W+kuvJH&B zoOt(|sKx7hp4=cUo9}A!yhL5Vfc?^57`j!-VwLGb z+064^Zw?k%7=ybKO2Ksr#UOTdvBG(&67*nqF)T>j|Bup;pgLB90drQ;3?2`bAA0)% zWzbfF34?h`jnB5I%%&^(&)}q!)u{|Er7dXmiU&;Nng!@;r8!3RwfgyyO~mgf!QCJ% z+S`}kSelM!mRCGri~&MR&Un4B<)-JLULD;Wpc}$3IGub&gjm~lX@UkTYy)Cb_BTW3 z7;~C1NJhk_h4qx>(sp86n zEw(ilU3;baaqa3_#zZm*gXsIBz~vBG<&$7Bnpy}XiJ#rIK4URf$Huwt6~u2S#5CX> zIfZ23zyVw2M)PS$x37?W^WdHSS+CmW5k@fi+ySavP>c zP4N=wtjSK{>$Quo%A$%5Okm5mVUM6PD`z?Qpw#QuYx{&Z;p>*QYKz;6Um^2tNOwbM z)iwa~=+=2>ALY&PM|t3c#{OC9>29}CHTocdU1)CjXbrQZfo%g=W5m$*Ux&)4?B}>l z0+Lh81JOKrHXR2SG^i6CoC|&=2rW>Sg{$WvC_}#a?Ibp*%)}ggrrr`zV`m@nRbp(d z>N!{q)9;V1`1xDk!H0W<2AO~T>^d~zh$Gv*q}RDC5m4LBj&mV%+{&gg*!VfKo(J2ea<foh+9MlY(5GbI~tXq+90mq!Z;QX6V5SR|Oz=1>@+QaceX;v2U;V6I^Z3{M{ z7bZTjB}BP#aJFV@SxEf)wCZacMx1}8Y+I=L+^s5e<4&>g_-i3_b%K=&!Thsc6Cp_a zUc-tQPqE{AqufF^3d7~pAm8R1h${IUxd53Xq9x&Gh=PQzNafaBgpjzR82vkVw`WN3 zduq#4d=m1rwV301`fJvYa(IGMC^-kb(K1)zq4tFB0Kh|;Zw%wC_Bo*>Gw%^1YR(3@ zhI0bc#+8Pslv*eF86??}1QxIt{!z2K6UY{=^1KuP*tZGkcrd~g+@N~b;?o*Fe%F0< zpOAh(53%S1TKy!D`4T(93wdW}_IqU*8v6EmVJ4tZo*EK1qvZfU|5=eQWf|xwAx(bSxDZnqwG}`gAvyT>JL2v}m__L<3 zBdz#grm2*%0w7@E*@9Hr$<#0hE0+ZfjD0s{(iVev)Ac*!kWIm-RNvey5KAUk4RMK7 zSqXw#YcxJLgd-UGy&u-F|MV*Z4)delr5w}PG;AzBqOxoS;IN2h)EjY=tF*U>_@%qr zQ7mUEpOF48iisA)SeO=#?k>v17$jX5iny7afE-x_t{vY@&ySdeU#&*wV+Z>>z#%rMF`QI~3V`S=(nRwaWy@xq} zWUUis)g2e$qzebrlyaHSgva$!M#R}HH}%f>l7M3sh6AD<%9HAa8}W%Owj<0pTP}%| zG{Kz$Rm2$GQ1@$GQz_N(2)yJAHXuP(EEr(vY9oeK2Fo^JxL8$x(c7y#h~MF&O04~` zyPnlF(RuikxtpEB0hYtL2amr4NxdQ@*q+Wa;{p*bG@zr*hA2C)HtZKry%^#+6{2dq zya#bne)~EX1WV5}w!q6l z=dz;u5i4#nped8h)%=Z7CvS;qqrpswBo zykGyJW<)+A80eyjVv~WGvdWbdF@uV-11LS&NC18$U8oK;KjkOm33o5~5%GJGZ;USj zcx(8TbEaFzN#~jJDY*0+7lZFNLfR6mO;Rs+KX*7SM`WL*<0MY~+ zvR@`HUm(FNhbMUoI_pa~GAE`7*i%P2jMT7cbXeIb7ssAwV3F3E&jhP~i zk$giJ{b$!oX28of!6^%L0lJ?F6rik&@c6Q%p-dwv!lO>OgW`HEN|;PnBheTh+H^^Y z(F!00!I&Kt>;(glwoD*?Sw7L{556q$h?Sv$@Jf!TY)q4D8dHE@Hm;4}*cXt@P6WZS zsWztE!B5gTJ0UB>*y!b_{ZA$2-zcH660(!U^5r5-n{ndPKAh>-!58)Bfpdf;%vbbv z-s6}TSUEd+#wOhS4kLaAk_8K$Q#|CGo%(ewnsC+P4}Wbe5z7MkE%4c~Z+$uRJO8Om zQ1bbbE7rup&-|wbq%03`>38N>Q6`u072xsg4vlk<9>Yx^m4$)rk%g9=tPq#eB2Mo;7p6QA!f#vyEo zM5>{XLA@Zv%G0FsP)x@UT(Su278Y@r{e4vlAY_CK2UaqqUbbi<+MC@glb7^X@Pxl_ zQD#rhwE4tu2M-a=bb-qZa@1$=vg)ht<`qPc4sYFp5YGn|`(X?E9!Qt48JS7b)g9YW zqzr_}gaqzeGW2Uu7dN9oNiPUH)QN_paxdPupQwxk*_DZ1!%|J6t@>F)i{44}C1DSB#35W6C^g~g<69G6!nebkB z_9|k(LvV4l&d#F#lKmv9dp~fZ)d*DvbNs5!jmc{|4;7kr@~#VJu&5ltrJEm14oW)1x#R1Em%D}EQ>Rkb|=Zpdr)jLIR<(ul%0Cd|^17(^aUVox>4utvsV3)tI zk!ZZ(-H1;O6T#7||NQf~7l_{*V^+VqRR?fwkZilbAlY`^Ad$WdSkaBbLjphuHe>@< zS~V(SM}5lveFcN5lCEvACvR4j4Z-smjlunp=)~$mAOW$F0abZVX*>9!s2%b?_>bn8 z4~XB#?6N%?f0HZ%g;ipbQ>QLc-O}$5Xcm;s!Z`FKY&S&ZvKRC<1Ua@j0XvX+SbChg z*b)xZNTCDRN{l}sh_BCDy=DIpRvj@uT#-8j?E;~VHmDi&ywcqi_d@0oAr(F1t8Ciq#d2IO8 z^hs4GN(z@vy37l8<=_{pZw(%zvb%zBT5yUPi=YicCEM&B(GKF*#%p`8l{i&SVMjMe z;I4Fwo{&=r43_7Lun~AdX8P(1({E%Lfpf=pWmLV<5Gn!86k*T=!~&4BUkL7N$56*| z3;#Q6u=>=uml3~% zVo&M~FOcpqew~p3BRcCLYgH0@OfQ&1L4f5{mTH)XNdHB&GcBW0G)p>0@D?Qk&B(b| zbD}RdE~kgPOHeF?eS6K|QsIK@I72%6GS-kQMAIhtRU>zozWqAUJ56zE9$EXdv$e}% zy38E;{k*fw#7|y5kWwQV>aGJaDmi$VdxjPpDk%k0fngn8r(-FAa5DOwm@5Jcu!XmT}Cc+*8qK% zZJn&GRSWOg8dHIz>9Yd0=)ekedBn)T?Pr%rKHf%1W~|eVSc?26K!b0+)Rho|SEluB z&Ak+e`29KJ_pam%7+&h40+REFG@1j-6+EYMJ}5}RX@cH)i*asaBWi<$z%AKKu$5;c z5=I8*oec|F010Zh2k)HgS7iYu`X>BlJHk<(%^(AH*mV^g-5B#s5-+HK$3OKU8D8Fs zgYYEaQ&T_g|IV%Fz-M>n49JB788M|9hQv9n;s{h<71_ETpU8|G^J_2?i2T*yn@Hf{ ziHU?~{7B_hdclH>W5pUpQga3f>Ttk}ve#XPxn|qV4Hw%k^4VQO)yStOfW_75#n|V# zHqVU-#NB?j7m#f!#HDQXQ!Jlmx1&VJi2&|Y+OtMKMMsw-Axp*+O;iRkB}m(X{Z?^k zkejWgq$lMTLC4MwHvEsXji@}An{xK-RwQK0dIS~OSGaN@tBZ1UcL%wt*ZczXaj~14 ze5FL2N84m>e(+5+A5%7th`Xm&|#i0G}y$1S0(rbT!wj^2qFvTVzz zQ!+yh)&+&mnx<^(e!0ug`?}r1squtc@oJTuC!G=^cHwS);SHM3!%cba<+(?_*kdZg zN}C*ID+o+cxlg0zc{DNS(oKM^fI?kA`K~RnOgN4}mY9peYw{cHa%WzHFylRLLsTJD z^W05ZN*6NM+OkK9-!{#RTN@+ks&7lcR(|#gs;Wh`RFXL7cVaC=dyJ*4h(XrScW>`n z%L&Vni7eq6W-CsEm@QiyIIVD{t-NJktbJ>%EnVJ#p$v8wvn{DGeV!Tnnbojmj|`i; z_5jJ1>6~g{p)*7k<09>u*Kv_{Mu+@{b=8cGde z5)A`G)v87YkZ`31f#{74Vn!du1V6`%I)+~bZ^%NPTR(+d&1d+~ZDz3v2zOp{+Yob6 zVia|`^y|Tn&wT<-!|kgH_Z_*9iu;b?cb7f$2Jw4hqAdA}Gp*1by_I(ynC7h&Oc~oM zawo(L^S}pfR9p>1&-j<0))*sUBiO+9(#&fPI)qh1yLDw5!XPTw=cYRqWVX9lqN7w> zBDNR1%Q*+F9QymJx!jx1eO-1+$tvQzGBU(S#hEI1C!7CB@K=_uJ#6Yb(orL8@LAbz z?J8np9$~^K>#f&5%X}c6j|aSw(6=pp9)$GRev|-(;Hwjv-_i%uB*$u*=&gXk0#4iv zPLzs*w~zgj(_8KZqOl8Qm*+}{jvkZYY}slPmKycGI6i)D7(l2S(8-ffE`FmJ^I@MO zuM)rI(SDpam!DOFOPL0imjum>*zjir&oy_zREE2O>cO*(t+DKYZ&@Df=;n6cB2WHq zq2IU{UwExjolckW1}F!bbPi*c@F1!TTqNRl@{}{Lb#%#4Q+cL(*pRZzT&NB0%_|ta zFv*S-RYG=vs@o=WO=Wd?S5bfltXjreDiQP~;?14OAs!Kkcyavd=#vn>Wa@~qZ{MFl zzw9SKJaQKejGZ>elAhs4Q7zFNj)Mv>a2Wg?=X4YQmKKker#sn~tJ#;!(U+5-=30E}ntJd}j2Nj+ z)+zNVN*@W0#O3}#lzMQNfa(Agg9f)6Wg5y_L=cRXfUshj6yeooZor|ESOiV^>krH% zekXBR66(cnU?5pGn@zvlOm+*xLcLIa3LwWqUQ61^BO&L9f6K9VNU*>F)QTgMA{&db zV02V~kMj1ayr#xt)5Rn5>B146vf#@qj}`!&vEYP9GMn{1JdE$H;6@C0Frr+Y!&Ll7Bz+w!-;p52E6YSTWF6F(}nv$E8U5NFv4Bi+1 z$f;4@`XEUKg!0~!vh3q9y{SeJ1MaKD*-aj(jum5T3OZ)^w913?9`o5J!6{$$j$U5+ zOI(4xGw&TJF-bGE^2nrSjTX^~!Kkpg2cz%-832t~wK;3&g@>y^8BV!sE%=n$sDEW} zFzQPv^ykz85mq`BjPMvwgNn)`bMCA6BDMf071GmT1y&=?^Umt~tN_pr8N#mM0WD}# zXRCHM7OirPk3XIV0gD7d1KZJO-q5-B5IV2dyckQU&sE>dHJB5Q{5?v)&y9iDd1oJ^ z%GX34r5m__rM}~LEE>c@aSxAlncLk5P%DI9F)>|O=B`M}_F~nh0_N|Z-KMz#RT6@Y znI~Vt0b>LoXP*3&*xQ56Sh94L9O>XgpN?3piSb)g=BXIuLx6mzC7-7f`6P98Q|8HC zV?`;l^m5p5glX{CnWxGE>hV)$jBN-Q5HNN;V0ir0amLOCj0k+oL1%(bAO3sgNFb6` zqyPB$$z8!`{0=+bcW_KCX;6-@Y`668Y9xN?V(Ei!bn1QS1sc8Hr%7k0{>g+=`J9;6 z9gCo_I(TzHh1JlP2*^I+NJc2>DeWO~$|nxo;Ixz@7t|HqH-6{#43yA#u|otk@!Nni zb&d_86^O{~;GOC7Um<>OWPuZF%j4$DzKv8i-o)5)D0D!2Iqs8|WGY8_FORGQpY=O- z$jP^6ULGlGGDOY6;XQO?lMjpH)sQ)G^5W?9dhwZe0L7$%((%Oa1GMPW``6(oMv3bx zFMtb|#CJEWC?$FeM}KYxaqm@*yRKB0pWJozoN0VGU_@-FQT6TX%>iaZzk=l}?}&0# zXc_x&SBC{#xlM<2+Cvjb=u*WELF^U*~Pl9Waldo4*?wmAbA)QRX8T;)BvOYjzF z*|;*P;5WdBwZ}i9%HVgE<43{W?vtlWvv)5oBz|?lrsqz+!YY>s_qb1f8f<><6sI`H z@+*r_c5^X>z#=!wu0qi6>jH~UM~tWGc$XE$eofY3=PytgE$~Bf>iiH(j7~?DqpSJp zQ;svEzXfWdU`g8qNomYjxh@23JZ9opA|xGKRr!H|_^k_G1OQZI&!h>vI}lrb@^m2f zrIW7&rj?)kG%)R@Q!!!~ljb88qagMr41j6n;C-Z?3xuQIp&H`yuK)!D=*eAItS{j= zl1?zt8Rs)F&d_Im^JSv@o*tXzOTjtR)bb;)X$i!yTXwTp;=}cj;KiJCi%T#7dbf}p zfw(ONEO2()<$eUk^VpYJ7yvr0{vB8qmn+9!=_5kilSTa=H51b^$I*aU8Nml-q#sXP-MS{f#MNRKIM#R$v9w!28k9? zF2bi0LG6By&ip!(a)FC8VSRK*Qnq`24sKVj2Pa~}NAtsK?7hb=&S+tSQOk4Y%K`)^ zU9p%i*BA2>sW^WBXZ;P%*lpQ^_b;5F3alT0Mu5EYzZ@U`H|J0LaVUKcgToANW6;Oo zeg+RQc#Of*44&^#{I>UH5ZAd?@M1+u{8E+W9h||#0euJEdDIv)=ZP0z4VSr>;+zif;Nf-s>LpdsuU=KyXnIo>Nettmt`n_s!XX3gB|ZMWTRqi= zC@+88Bfp6R69+Mj85lFdvexi1@!QAWOo657)O2^m#Um3eq?}uWUue!`V4ClM%R@Z7 zaYSjHu=1ym0xLLL3OhuDOMZOtGtD{Ey&Oo(Co*G>#EFQ;;C{_HH`uH>t0aNHH8J(E z;2zCc6kMY@mq~)?>!Vu%bhK7;?kH@B=rwG2#L(AZzB#yBb2jUcO`6l;>kgL#Q~B|& zu*;f9tZ`0mU)xf;oxm?J4YX?HrVW0}-%NCG6Yv3+6->9#*O!hEw4o*);+)AWTg0I4I#Aqyhzum4MN~6oIUqWz>}-UbH0f^5#LrJ* z%|xdZWX*5)@HNZ)3?8Ry%mS}ryyE0dPBrN4%Eb9V9NOtS1_N$X1=e|ew*jjIoIYZs zgtnD?=Q_mh=VuW=8yI_<`5s~H`4UX? zRW$ln4@E(a@wXkpz4mi-c$DuQtw8?O0 zMS-{naC9C`s2lvleXaD^lV4AC_b~Irj6K9u`Ry^i8xKM7j8>6;ofEHy+GxW2*mUCI z8F@Dc;IHf+JVAGZ`8!9}m?0Vd2F=Ix>l7P?tnG9+(E0*z4wiKRqaOo;2+2x~fh-dv z854ttzHs9-7*ES*Z4gEnlT2Q4X^K8F;FBjnj65@EtmQqZMJ z6e#$^Mv;FQ$Cr^z1 z_UHe7F6ifqs+bpXM8V-(-+g3ifwF|)?|1Rppd!dHUV?E=Awr|UcgoM!d#c%QWXx7` zZ<06(jNqBqiG{Dp;@rU_&W0sq^x)IbB?A1dhM!|aV4sk3$juE?St97t%Rr9Hi37B& zUyj&bBz{R(I!PvavmvX{SC)%!mbg-Z75sad%+4L+{*k?~mZ#^I!gsZ6Ss=dr%w;*P zj~y$gBRz*a*@T$vL%`Q>-^rm$G)CU#!eW7(h^btfMew;+I4W5dyztVQ0ZAZ9PP2~v z2&Nn!9W(xN9r4R;oCm#&x3f9yr!3ISy)zD2p*t;~07amLM}FQx09yuQRo@v=kpwa> zvPLJe#EQ^w!5>_!h@D&;%=60{+O?l$A1aH^IozdV6=av8Y+a}%(BOa`|l?hPkme6UAg0$myk^-6W@el1#mc z+C&c$9;bYCPZZhvn|)M}0FH1yGBEtNRg}-JT4_Gb6uR$1mW5AER76vQiS2!)ECqh= zq`e))S%(ZCMGg!X^D%4-YYKq{2|Z98$e0=_q{U;{5B>oZ5|V@nfu_3d6*dbo7mzPJm=g&;O^Tcm&NQ$n5!e^|_yT(4eFBKMIA0a1OsdJ9*zV(ke zC&VR`0zV0H3C{yWLEUog#?gWTsbT1}IUv%L~LG)j5|G; zle;~by*6)`PYjoCkMgRH-3BiQQvny{QxP0epqIc#>~0*5CJJ>vo{a9;ExkDTjFy+}z08*z%P` zL*MiX(TV~fQj4D;*i&p4Hgh0P3#$Q?CB72G0WXv4?-ZC6+Y6?<+`Th)H8$N`D*fw* zx7Pw}Y{MPdjwBg;VcmpTt~owh@Qn=_!H1gwC<&Gx&}QIUbMd(t!ExHw?rLI+qKU{611ps z#LP29CjB?))H`(25jA4<`ec@{v8a3-jhAlS5!@&<$61n?-01PZWgW>#@PpgLRE&3^b`>HntKyWTBMIAhT9NGW*3%{qk zefNw}VCCR%=AjFig-SB5?&P7Tl)EZFQ@QPdY4oQUOV5gE!rXvu!l~i~L44$OI9lW* zB-|jeuNZk3pRyVYd5#TChs#CzErg5EKzKLQ81i2-_j9dY@Tm&s-eG@-`0+ADUL$xT zs#OkC71w|X0~P26o~XhZP@JeDF2iNzx?#({Ecm8dY%j z`NNC1w75C4Me)4#_ zt@n73ySX2eL+_uF1?i@OHbmEHF+xR;-cFZVm$_thh|gumUUWuOBC)@R&& zTo>!k{%72`vFy8^^)2qDh}oBE7zD;8<`#D?4=Zw`65jEdN_e$nGl0vL{~Z5hfcWho zP;ObSMvDRL@ zKJNY^Jp<~7Ac-@+$_E;_4@eURNBn)Su-GNuetae9zBV3!hVAL7swcvT-XZSVMq%2M zYTct8az?GX#a+i$Bh@(fMaIIkYUQqDs^WKFuciGDT=T%I64N9$_$A5?v$sX&3Dso=9cuuYLGZ#f^1^+L z?M7pYmxCA{+|g@sR|~rYVA8>vwH9|(@H6B?<%I?8qWh5Vwy>-7zt{>^4&2$PRAONQ z?EF!iz^Te`Y5ZU9w;gXOOaPFcU1b`03D_1UX-34P=-?0E?3jy(k4x~db72unZk;Uo zQw)*9A}JaKFY*X_VTzQh=<2E1#tL_`Seb@m+sHuoj3^@=Cp=iltC@v6$-?)O(UuB* zr18Nwfwlk@24}*(l5is;iAqs4Z;}iVpf}xISV@5uA^J=%P_TUR4CqWeig-wE^pgjC4P!3Gi!#0=_j|5Y4Ucs2-;1AF9)pFEjEo?%E_FXu>)yl^z3Y&tTfwfrUYQZeTUo-=MiSj+~ zl`JxM&Lweu=^1>Y*h;mQGLn~D;kLL9p6;7duyN^vU;ZRnjgEDR4 z$lg`!_7J}wFTj`*HX5Q12F&Of6g$G%z!M>a6#${;BLOM{2Fl5yPr)^FLNet#K_zptNGqUGxRc9OIHYm9&!}6bCi9hK&s1${i+cr0cgA;!pB%N#D=(FNt#AkR^`qhH?hwpRYorRh_^UO z9GpXkXum#OYeYUSA%?w(DG@%RyARiF-+h_*rLx!&9B4#7Ov0B5zV0gKSpyS}N@i)k z0AQBUNl->fWxiX4589#|FeSp##~bOM73(aUqrv#V&vwD!G&@&}sUoBedg46xH z=;}l5%Ck=vWOF264@&G#iP&eA>psM%qO@JP7syjvppu8Xzn-S%sX&kU;#wpY8?i5* zpVJ#-DQzGd&-C2Vo4~{5p1ZU<@RqQZlohr@AA6OPwGrq+DU0hwUX5Am_QZn()NaBs zj8xmEtDpM|FlG*CC0(*ysI;0{3ur{JGt&GKu ze01@x)ba6GJx{h=`)&G_GUa}Osqv!;h~W_gcWc1xcfY_H&muydW2w3xoZ|H&Sb%2v z$go~jhI$~la2RaxpKSMk%)?;&`{7aR#X+yS+k`YX9dNo|7#Y9&qjl&?&x<+@SmNp{ z9dBQtQi2`-DW0ET!oNF8GD8bma}SC56ZUF%X$F)Z#CqV160v6bcNiG}muXhRlt?WF zYs$cJ@QllfUXUFn*tYJTCZAdZ1PJp*%O@G+d9W!aatfp}z^es0ZQa-OC0q9m=I}*n|)#>vES!o(DCR(47pyD@GLv#_HgrK5yJ*-?u* z>b=)A5Kj|6Ez;9X=@}eL4G?u;mAj{Ft3mtqFf|;ePF*QTig+%n)U|8RVa%D(JC;K{ zUoGu?hqtLcLu9kz&}>eHbjctz=}Q?t4BBP}EdYQEjLO}{pkjj&u_4MB;%t*o+|+m1 z@pBpu_aoJcRH*FmDrt<^8g|u>&#!&A{UHjx+rZ!U#Zvw4Wz0HsyYkS8QDhTEuQ?N| zjKBjinIDdi|5wp8v=^_!voGPJE7HNsLM9pd!B@8bYUc4?3y#}Zi*O%Y-JNiJYg{^( zq(xJN3xpp)B&ErkWdY|1VbC%kVrX|!y70e{8dCd!o&DGJ4N^mX_YkoJaI;tEW-;(e zK4Ix~bw>@0frJ<0rwDt@>TWxbz-j6JB3|Pzvdz)Z7oq$kTTA!-6!|NdAFvEl;>O1> z#hn}<|Er=xVPy_%L%`;A-vzo9U1ska7XnBX`>0B?2wO1UDiHwJ=;vwD%;+BJDE8|3 zjo3%SQnJbo_U01S(?ms=&ZllG7|iZX83tzPYirRgVwOP6-oq?YGz;S)B({5Sl*lk8 zNjQbV--IPtq~kjFYs|!^^{o5 z`I1z`D({dkBE!^xUu|05jL=JUW7bEX+<&X99+2 z-1mSLVTLBHm~R<08neXGQNnB);m~KoQ~}C`unePROkFIg09Bk!h2(nH-W;n;YWlM2 zZN0>gLPc3O#~RFP3wfRxJU!X0AF+8T1pdBpHs7o( zdWMa>0S%LHL_=U!Y`czzsHd3g4iAmt#kP(=lZH2vV1lxcD){=7=eP(co;ubGq7m|} z5YeQpJ^)a8jFgZW*~?)R5|GSd5Go1eNhlE_sR_??jhe+X{v^G0;us)xy8&Jkx!Tcv zOF<*?OBD$#3`Xz^QJbtRJWVp-fq_OYD_(?rw)4^*B$$SAsN6CR^?Bw7v$@nOokai# zMMSXjX+*p&B;K!acd;{6`Q|cSqPDI7vMZcamt#QJpUN-+8aPF4ne-I z>|`(G|1p#s;Wsw~W$%*Iq*&rNH$5{PmSm19=>VK!!wa@hf6@X8PIuoQ1JzLzo%EWj zU5rQDkgteWbxEfCgw7V%`eG+fZUtBNBDn8|cc`;o;d76ZQN!SSCh(kv* zvnq+-Qgm7Ij1Un8$v-iwCUh_9x8Se!#cFYrkev(NI|ynm*PnL`{}zl%Bv;)am3CMi zwR6|HtT-9`GGPQ33_2Z|%XosYcMGB8UX)I zZ9~Htyt#CBmV@~5t@NU)*h!m`BJWA!GszZuPqLL8NN!Ya3nuziwy0aOr_5f5>1L*uUYjyCMp^C2^7h)CeyXU2K-9+fN$aMkRLo* zbD)lr=>MC!caM&%xblThKV-Ec$$D5uvTUOxA z2bOJ&9~fv4VGKcn5QcyWe1_%W5{B_548w49leyqLE^wK-Np8XrzFa==>Ru;!fw+eAVGX(ksC7KVT zU;1Owom`hC3Ja?$5;t)<0T5>RePB|51pJB#emo6ab^{yY*?zHQ>Q2&ti;omzm@NZ`h(otmV!nYHKwPJzd(jX?=uTL2yb z6&R}jp;Q`$IjRVf%*0hLS}V4QW{S+ibKPch*TFzJE%eGt7B`l#Bl%0)&PDZ^fuT})IRf&}3-sW?H#679^v7Ebcv=lqUXe#$Jv7E|1x4XC)twWVKW%rLO%JO2M<+Y69BWvL(h`O!)jb zgmk^XaHdnBj&9rveG!0(f@O zoGdz~Yw$qZIbSr2*iPZVAG_t${Z$rHa$ReqsWxy#1*#fQa zc&%JabhXc8_t^#PX3@!U**4-YUjM~Ul4+q*cDJCDMs4P6#t2U*zKqNjd~3C$QEUkr z#Ditv5z6ftU*R;~?F(&4%_>ML8;h$PCuQ|JRiD-{i)Dv{Tn_&aKECkh(=0$|d3=G{ zhZp|vZ5ztgZYTa4LEaz`6H0h%x2(Jo@Rd(W&tadQa8up}bkLVjQ5%54?YNijqGNE~ z)T+QJFd?@g51ZcbI|)j>Xk<}oIc;8Rx5Hx^^uKRl;L#cHJ*oqpC*Kky&WGDxFmKx<2i2V-mwGhd{oH#Z^;gd%%p4&k1`m3@w7r z5w>w3ZWq;7>R(f8E7`^!XtLbHLwg#Ml{X^aJShW=ige=+P(Z0V$r!1#GMg1R^{=y* zM^KCHz`oQL!pCFXDqisx@0wLL0t@P^si%5l&1@=g#Wp%aRvba8-S&pv-Khu|YaeI^ z1k4Ov37O$V(!M6UHb#23tL^ss40VZy$6RSjKrp=7d04>du=-nGZnP(xE+UM&D!HuY*StAp0>ODF@z^rfO3 z*#)r|4>(#Y6ve4l)YEjb{AVS-71}^`ae`|V(KiD4H0m_Ue+DdNttX^I0H}He##1qS z+tK@Zc7+(V!)8$tGZ4$d7*6hW0Q}mS8~zPadB!Sc&M|#yKsa&J6Z#R@b0O9c>*YTx z<2`7|>j}lcGe!ECDIuRH9^!?~>gu~~9WOtZ-@$L@KhIOuYk2BrA269JOQS4^A@s)N zC3e}j*CGuV+3+8e<{~6ItG)`ixsc$5IVIM;5|@VQ>sMuroy%!lY7PGeC8jrED5E%y zqVw*Q77y$qlASRNh;=R##4e!IxlCPJp=IOPLd*fP)}u8T_iYP04ND3-kN6h8Wl?{g zRYtEbCPxnFh~K)(HQp^imZzDTN9LHc4UXI5)C{{epqi0N=dOGUtNakMIC)l9TM2Z^ zbaSrD9qHNBNBGht0r_fQRg*yx;U8gwB45>JsTr}FIna+fW~uDB}oA7Av6=#$p-7hfGhv)o32rx@w2%Evq+A^*+94KjFJ+ z=I`JiAQThCQct>z+4KcPxO~#N7jNt$S zy>#x81j(G8V?_yE1Tu-FCjFgKgU($Ngsgx$l%QH7(Sc`u#SR}Ds1n$e*|7fP7)gAhQD><7%%|7uLqrv zLRiO&=Mlj0n;Tcg(_`kzVp2`OWoIp!# zC?UfVQOiMk#?QnvbCG?2?89M5va?^)Mqy^~o1hXW`w)i@on&K!cskj+i@QM?+3n%q zp-v_=I$av6Q8lO$UO8x&YQoRx7?-!AQg-rP)wTarC0fb^DWL$KmB)81{7gJnf^UYG;;7xI{&+CuJqY|};y<}sT!qklHQuoo*whjfu-+wkR_?B_ zYhxh`7-_i!ObP!Pa*mxwK5r40uO}qU{egJx;E-1{RyA81w2&WFRFt@yF^&A#i^)$F zuRqc|syNcFs0jZH2BD}JbC!cTqTg9Xi;9y8i-5S7^G~xZGB4xqvg*>f zn5e?MaQWcDV8y!_!P?#HRRsxcK?6A(7YD!+aRd5@h6Po=7382>e4>DEAC#Ewz=fk?7&h6imm#IsJ2`vEJG5-0 zDhSEn6-+XqI92(f@e^%O|CY4{B(;Kjf~+19)zMm3nS5LATypvQL@6=YC8&~BkKDqiGWqcPpuUMj9eD>VE+K)R6_g8$vl?qx;#q}^NH(oJft1^;2 zwXcdrPDpJ+aOa~}s@=l53VLdpd-A0r`R&pHocP*7Fo&~SQX5q?ers>&QubVx%$ zJ!G?&gOyHR?pUeAZ}|lwb>6g{yt1a%{1d{*Eo>|OQB>A)JIE_Qm1R@f_n-WhBM0IY zerCxu#ycNqk`50n;U8e^!v6zZ`!sS64I-10o=W(-l}blZ_dIBY zdTCHuIaClkrd$qTCb6OQl8>N3`lWu%NEx6u}&X{HoVl`Y~ z0kvnQyYUmZze#Ipz+aE@;5`_Hdkf76cip{|Hfax{txA}um=Yj-e4fqQCYAMSzFkQW z3d1VpdKe}-;|EIHK{-wh*q+kx4Iau2nmox#Vc1S$R@EmNq(>eSidQO*aP#g&Oox_5x!1!6-tE6|HT-= z%yNyxh!Hg90;){7?E!gXO3%9(PaFfJNG;)TXG)fm{87vqKJ}uuB2`5e#31OfQd21P zDc58CW?}4cO{;LVPG>@jQLSj#pKH|u1-aNG8Vk>Nf|dVV3=hT1(fZr1Hxa%aQyMat z@LQFFva%V_cUQlFr=zLtjErw$#v)*b0QQ!F4$)^e5UKyi88xrVxeMteb*nBp7?O-~(W%$*T;o)fg z+8C7Mmst7x1cL^-Jij^c!Bjs^Y2AfTwQAsiLZY?>kp-Haia< z?0SFd=z^L~>H})!x>A*KW>ubp+eQwsC|u)51ydKT^Ey2~_4uBC$vTg&KhqW6kCkO> z>xpFE#IITb>{k_)Re-Hr*CJ;`Y$yp(@a+@6c_9FdA0idTf?&iqUF{hpRJnngTL0o{ zhM#4v5f3JM_(v)vu3}R{wf;B3s;-hIO@x%HyaERp0x^0M-ol3dJ`EE7lm@24>a9c7 zYgbdzRb{-Gz{W*BIh&o2(bRtl#=){11vm421UwB;Rr#GNL=L7FB394G>8c$0yCpMF zWoX%`&f|szww3n!CI-;1rqx}9d|W@oU@cQE6qg(L^Jd1f5%A?Sd&9Qy{r{GIFX40Y zCyw6m=%KnD+a&y~zrC*)>K??jG4&QeF!k{Qp93r@tMs4Loc`Pa>B``J5wQNGV%J!` zO@^{dLkuhvobfp3kdrDUbgNnj&(PNB@cI2TzSUN$R4D;Dq7klokl)IHlFpIOMj!vT zhY25VHdJ|y1R&NBVCjIjGyD*)f1|AI>T2qdW&DWfkfK}$RaI@4h7gnOp5&`KQ{0I$ zl1g#-r{I-#gsyfCtgtmmX#$#Amc2&xB)%K*EhPiR;3f6dwy*GNY;(}9s;lY-X88mXL5~gKM!u2(9^RUv#5wjh8+3o`hQ4O1SO1n06~JK3#27>} z1fdk{tOWYPWK>X?il7+tLm+_nU(_6F1fPmcRqA;TQFW*<4XKoX5A-EExHE8IXV4lj zT072fV@0iiie0cc@_VuA%lFNv7C@*m_q8GmWag^dIq>p+m|P8!)y8l}LnbE*Uc>QB zpAAjU5{xUo-mO;{ji_Int3U>sZzA`?}E(^Bq@R z0BB(YRTYjBAyR7+)dXO7cBLZhp?Wf^oEM!ubg|XT$_kX~rJyF!zgKUTVjO_yMJ&b7 z>iC7!+I2|4>{%pq$^5J2{cQvDJn%>zkUF`m-)KTWR-j26txRE%7%dW|GZeLq+|Umt7MFTk~Y zv>`cO#U3P~jzcManCF)|47u?%70>VZMqKj4m#_~!d&!0w1lM}d68)o6jn!37W|Zps zE)2dh75eQ6cB;wMg}B%;eisEkKZHdk4kuRCEh^+#YxpBzG8>+u4iq&v%O<26cd(jC zq0L%@>|F_;d>g|z?q^Z8e1k-bai6%<77^Ij1GF{tNcpb;4E z|1Utftc`vC_Vde+5WYH5oD)rj3vTnPk8q4)pnHWniX^0FsM>(KRMm>m{n}SW&0N4* z)Ko}#M)fGc1E=cs!d^I0%u=jNQ|Gxg0C#g2TYY4`3JlTLhDDB)7EY3?+i;RpeU=^E z+0t=J+6$C48PU>TS-bC2DPe`YnqJ!G$`n@|7aa>6aaD zKf7>izZJNXBjFH^@=b6^Q$3pOiN>30&oJ>1SErjKHGEgNgqjvcPw z9(w|(yr3p3;-Pi@jvKEod|ffA=23$Yj&K@44S*hL2RW9Ikee~^Za*ix0UvBQt+a#i)+o3#|uKzPpv`<5#|>4{s!V$JJJ(hRnc0gzDX? zw*XKi88L1K%p3({^Nkf>iK`t{Kt4dkA$E&))#LXGK!`o)7J%d@%%T&FpCmK$OfKg% zWbb$3QfQod>6*BOqw?xQg}D^jkxw-AX0%abv-PIg>H%L(9Mxaj^lbmX;@QVa5 zbShH4{+Z%_9$8Y&p;%xyl#ZX0rEgU-JZ98jpf;m3u~+Q(LyO^3YF2eE1@zleZO|0n zPS65M&3YX@7fs1I@MtBDZYhAaYj5rDMRSz1 zGJwATc1p5IO2<%`q1viRMFq9zLbg+Q_r=%x1+yRtqMAYtiF^mawE634h?k=>=JQ{^LVM1B7oa`_?lvz)Is1u+X(6$RSrv zo@jUAg&isZ=y~uyAD+Kr%pCssTXT_!4~P(~!dEWE!so#@RVxN+fLN0X zh`K_u7EuFUquvotgJU8sTb?oCi>u(1U=&hSC=Ct{VHEMTmt<`ucH<%*kas8{7iY6S zf;2Y_#y84#feLjm&5&yvE0-uWy&S=6e1B zv!cYMQRS=(oz`>+r@@VTV|+VBi>zaRNeQgx5l(E2R8XbJ5lu~p;R`Z=Gh6s<8Q-jT z2OoIN4=aFFdicF4-Q|nWu_a9ifYY4vfk_1JLW?@4$hu3QvwcNwB={5&-lb<20$}{gMKJA>aCZI0jpW z?`kJL38vY?clB+5TB`WAg;KM3B=4k+YRy4ret#Wdhd1$>T{zmT849%-45wyDe;`;h zCCUvMG}5Aon{rGj1Zkd115JdKvw*+~BB*sJDF;IdH$gp4VqsSRXRTEp$&fBmTxz=f z9~j6lA*FVCl|pt)9L@aazp4Hnz^f(OtF^)Do)R0_3%wlbtc~L>ZyKJ|nxSig2cu;$ zt&>AU5u9Yc$a);YGvj9j3bJaWmhcaQ;}fL?D2obe?jB&JQXl2^6lq8@58Q?XX+uom z7@HLOE+(bdx5P}^2w(Cg1vI~K$}d(q^SVFI7qKp)`+_VkohuCU75!rv7O}nzgJmur z@bTLU7>U#_C(IY{vyyiUvvQ>@V{0YG`Y2AX;OU(h7On8h^p1G2F)1M7e(}rZuf9+C zvK)?PtKr!$dWI^L&$$~@Pz=^rQj9@GeYJTiA2Ax`V-Y1T48_KLrMA5|2QlO`YtR9h zRLRUy*!-6=n^Yx}`(hg-*A@G6W;-*dEw)kd7c-|Z zbK+vn$NpmG#F}kvWzzV1=y9Cu;pkm`t7HwS?y!+xQ~Nv zBD;8y-&i6#MkHn9)kGl%83h)5m;=>3(ss;3*`>BUT1$xswMc4luC$RxW^AYIqKIN< zL5YlkPcojqxDl^F^xb$AoI4%rWMctAyX1C4#dIkSp-Y%4>E-%jj$4>2>&};p-Pl)i z#~|U`hMU^+-1yH`pr>P1x~>9P{$XY^p#6}N%YZIEl>`Pj3sscn1OzSyH4MrbI2hzJ z$YpRNgA4|#3=$YDVW2ShqWDKGzb1UU3Dx!XHJl$-CWw)ZI9-;@yD|D(3*f3tC}pJt zT`!5MPP(AK|5XSp!wTjbQIeYnE>#X$S8>?0;C6y44-659;~Fv9D$0R|BG9<+GF7sD~^s>Y*j{W{L{_BJPLZesDHkg_viW1@9%tt&6+-djJo|3$+(@&_EVysf)S% zOMH{y>YXv`{u%Jq*~0&7uwtYxlz4eNb|{r;ri5meile1zY;J*~Bo)A!eKv06rOy?b z6$oiRg**^?1HIDi0F=#kL)24Jx${WXQZY=CMi5Wv1pB!J; zZKXAT3wO;e*>>tzR$-sG-ma!K6TI|t6fKBaCWoTJuN!U@Xwqs7~?cVv^R zAUHrQA@Bv;)%py{C!3;q+s*@}s(kXze!`b06%+}=QcVf1m8nYI8fgta*M&{g;ZQgTN&}FxHLy;-uGDQ7Ns^h< z)NUV+vY;QS)|5S8cu1epEMw{n5Ey!kl zHKBEYG!h4ji1sbq@}Qv;pW-OAV{(t}U75N+8wRR%J(m>FDn$_qqADGcp5)D->n*K> z)v6g7Hp&mLhGH=R3NVUeRNtJ2sX%=OI0RMQHfXsI+UhA?)V≫PxGT;W}QoPwhr3 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 XELvL7G`NYB{n?k{kMB(49?1U>I4(i? literal 0 HcmV?d00001 diff --git a/bin/_/its.rp06 b/bin/_/its.rp06 new file mode 100644 index 0000000000000000000000000000000000000000..bc9f40a317c6adc9e4f79ee49a956372410b9ad5 GIT binary patch literal 241500 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⁡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 Tg65G;q-@jt4$t{SZjAi@<*b3} literal 0 HcmV?d00001 diff --git a/bin/_/its.rp07 b/bin/_/its.rp07 new file mode 100644 index 0000000000000000000000000000000000000000..2ea1fefd3a570da394729531870707779e4b6430 GIT binary patch literal 241732 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±mg?Q)UqWDY<`0-msL*6gK2QG45t}E11mFb`l%_0S)ndVdUTc)?+b#;Z@ zbs3CLz_j;8rv#AEIi`1Rex}ae!zF@)26aFy zS&I4Z#0(UAE2Ra^w= zn{JKTDH{G0%t2Ppp3~*_)tF@oq+*q zRF#ZOq_^-0GabX|l}FfMyg5FJHn;_QYZyyPKR1@vcAqQ^9_+J3Vc{86iso3$v84FP z%TrT-6;vuCMg|6l!(%cqI7BvchPz8j$I9l?eQ00MTN9TCzIBI5PH~FVjgMipabHhk zBeTAM>#=F&x+v~lUV4fHqcXmPpjx@%$Dndt8@TjzWsEMW36bTcr}I!z6K7WaqRO86 zbyyB!qdY2TF=DB+XOTQ=%fiQl7`g{7_BoNBz?w8T_)N~p!PHSZhxbx~tyu~x7n`b4 z*}3R64pI9Zu0F2#|5;sHhiUuLI{z9f#s99lv=NVHD|)ni zVg3Gv<%JEdQl}pyN_oHs_h$NgEC6gIZ7tW|+Qa)H6M$z~&=W z7BI%;CFm9$lS05-a182+R6f{%$=`?^()N{UnffDKu@|uMJUW9`p*rh&^yM@64K@a?O5i|CPJnHW{&GOAkPurcNUnO`hk8o+%h`t0`xI|{LiJri^vTA#9wKT+Q8x& zSmt{`nXitT4O6$Wn8a79E*<9Mozb^J@$sec|2sPA4)HxQT_|`grClCbO1tERPOY1u z`%5n+!|s-ACFpnGnxY|BY80{jPf%J^pF6dz2(yd-^`fCI<9_(|tP&_`NeR@&wmr?I z`$D!YCPQNZYT(k9MT2zS(N6XCz#!vbkY)o7 z@`=HYq6Ppq8!%H}x{pS+2Gr1IEkS3B#Hev~1!@S!sLRQO%L$Z=a5y0sy4185P%!z6 zDf9q=_0i2w2hKi)mf2R%92S{f(=h-7B8iVA!1s3zC>zotuGdgX21XTKnBEmxf`}fI zqSEc^^XfJcU;LOhV0Lk(j|Btfk#RIM%~w4jkG32!AW5Pn_ebrd(=(4cuu8=qj55nc zQ6X#$6c*r^`;?)*1rljYcMD=Vp%CC>2Z@_AQWRSh2rZ!!wGg(mCY7UW4R;5pvM?_4 z?wo)8r3ZA*j!7P7N{-W~~9?(>;6nHMsVu)X|Tj z<-A>euFmoLB1EPi6%8@aF|Ux}Oe%-zQaF-3eA$Mn5ntJ}myWZf(KkTg0Ns2Lhz;dL zoFa(FH=vMykM~3Z(H-|A@?*4XF3isC1-e?DHCG=0ajEvr`97G?(nUP2qY@3+c^F#~Em8k9x>lW?vy7Zw6&8W5PDz+`PvOIIpe;&?sc zZR#vh%i}o8n^w&xPxEJoBZ%*^|3*?kNgI8-q#;|jvD$6X^wn6*{r>wyp-J$D&0JIJ zl4+kBq}I_;nut7>Q!^`arcf<9G_1ay0x zSR2+7w#v^RJv}ugAjcnxyOctF&#-On{+^`EZ_FZXTe1`N`j35oD4fzZ?&DZ}dOS+K z2!_0_-v|C;!2VGXToq)JX?8`E5!{w>P3c3LGEEaM~dha8AcY}~2WNB9iP+l=vq@+>;6 z_HFAlYg>B z+Ols~M6N+!pRt5Wf~T*F65>mr73OeX}ekYNd;x8%(6Ju%}EqB=D{8-LDql4Sh5!@ z7AYleeCzX1yheQ4gq!ByFui1rW8#K!CmzLv-QEn7lA$|JYI4?!1;5`JD6FUxGqToHtUh`dC(Ry3CM zyA9*^H}ArCwaq8Xa8>Awf z;AP=TgE_0kqwE-Y*lxj?p76VHT?gA*_|d&Ey-si66|gYNj&36m+?-HnpY#7i$xsKC zy$oT_Mcy*7CcsC?eFMu{_@RjG+xH#Y!)V5`m+4kab`D(nMgBHW@CVlU`6~mI!w#JTr04%=wD83*^S(e0eD_YhhOt*wO(21GxN5jlzD^Q zm08|P!pmBNSg~-Xy(@?yg=XQMZCf3vK-<>Rd{UQY1vcibiPB2315$Cb=~jq9gC!ju zeHZAfKTv0X>cb>VJzH9VSs4j;!3rlHg;%KcyOXnW&;e-7r6V(b5`Ooi64?;7 zyv-i$h%bTPn7n?`LjP=eS?pdcEDQ0{LSC-uB&GR}pwAijY+HJw-<@}x%S57=@-~us zNHf3^N1Ygmqc6f@Q_BI1sJLdgJTzyvD>ZZ;3+440ONamBfJkAYzXY_IqeRQWIT*|G zPlO*OzW3(n56IWqEuR|w@~F4?AwS}|Q4V@5Vm{NG%oIez2W`z3IF zXyw~V&mD8|7S_0#O+#yTIxk*LhK8jJz7_B#Rt?4DG8UjEFy?m54zL1j;OO=A8+!Qc z%WuIo2Nz)JtsJtbMU@P)G57e&KnW^D{rb8w&%pWUoCIBX78VQPA=oK6AKlnunci3F zHev+SSKu+e1irYDUO62E(3-8!ZTv|QuNWbKs8 zA2NSnI;m4Km}GWgW8xSo9~6A@hy}BpaOrWXq;FF2X1K!Ef-0fx%WvW5Vjp%0FTa@) zp|kFb*Yu4ZpJPDj(xC)1Vx+Ub%`oY#`wI~mCYN@GXLb@_zjR81jM^CPSMx9mC(YO= zkHLO5f3z(8EF!Or>!QFcE?$6e9h~Ws(Pd{dBoL>vgG|n^<|v_j*xqq$J)tWMC%%h;F)fY}3VT4i3$+z$Fg*m7C^-@lN`4lnlVg0; zVSAmY0U0^FP^IwvR|jkvv-NJmah+`e2P~H>)=jjlEp#JxD0|*MT2pI$0{VCS2Btu5 z4HDzRhAm^xV%cxM9f|zM1o~&|k7?dH;(RIiDW+&mrYxRKS$`YoK|+&9?Ef4&%X&M< z>ae6C?^m+InG4U!dv&}%X~;ek%v!e#w1QL0x|x%Wi_4+FaugTxj;szCa5Z`w!^M^( zj|;Y07W5O}o3eHiy{v3Q-kfBm>;b*ZVj&>83l|j6(*VB;XVfYI8kVEnF6rTJhv6o-s&0OSyzS)(#$b*pC3V0sMGd8hHT?3*8}v+v&gH-wUr zdhp=a^mhMWqJXhpdu)Q}1 z_~toQR4Kbts{lwUF+)_$bkYmCe@?N|B8)d%#@KVpdPjOoI$72qqHHNo4&(!!hr_A& z;bd%u=xK?S?GcDtqB6MCP>39Mi~kdtXrSNF9~(zjJ>L2z@hzq_2L2hF0^wYjWujB+ zGqDwLdkMOtJ`?vyA~87_+G^1$ZMA5$lp5kO^&my-R}7~+zIYr16YdfC>A_u&zyLyj;jgVFrJ>E&#w zD=~u{YijG@$Ct(6$7d*+KGD2$d+Iea@$JST>iMmHhdTcbHY~yedm`+z#j=3r$a^?} z%h$jv)eD`}KzeXK=hf8TJ&U7;D=Y40Xr`pYP_<7&tg%#b* zs%_rAelOOwD?*gLnv2`bOviBAUj6x#S0AE(o;TRG6DwEt!omC`o%Ik`G5SKS+MOK8 z_ED1TSfGH9k}khm%%YgY;NLv}ix4d8`-uMa)mZ!0gU906jrIo5doUo?|8Cxcuwt1Z zlyzp|KJPG=*9iUOrv{jD|7ZFqFTL7rj?FGHttP&Q=eOiC-<|in7Yuk319x=b)gt6+9 z9Fy$|P9_a2mLx25kIH9hc?~%$#!SutPA$Mc^Pbu5OzBEi!%R-bb zT5idVVpB(_t;Zvdq4lkWyf8AE5>?6l7uykZk8RNZ%b4;93)_myYvfS^w90a%Lk?rB z&+=_KY^gDej`6!xOD(VR ze>A_Gj?s4Bzh{2=dG6pd-VvJBlh#d3-^OYssAOtya&qvxrC z;D~s5AFaF+t&C5W>GP{{7s%K;;(Yx1=ZNoV-iSGcYc{sRi3w#Zz6oU;WT#C==(tk0 zs~iw!|0BwFM;vnHYLq9J4zNviWVP%MA<)Do7Dqf!*YEi20&$70Ods*j91C_s+%I@;Db^ z^RZ_x!WJo-VL!+^a1j@w&;P^LAvT=@&1mO_A+wF9uE)80&VE3H@3j@@t_QU%V^Qfk z;`>Z)n95$^GHxvLoVM9#KLkkBCQ&H=rlP>_sXCOkY;j*;RZN ze15qXY7XRJ=p)@bUXROMni+!jU6@P}3E4{Jk}R4U9E>pARt$kh-3tE2kIn;MFyb=^ zWNR~WKT4*9+aP9-Y!)6^?|%TT48~n`3_&q_0raIY+=PHE2BvXNCnHii1^e~5T~?2F zGzS%xnt43Wi)D7)lLDocgICWVf-IP9$NMRt=YI8ItK49_ai-&!-y^;Zxxoe)#qZA{ z0HDzK{Qv8_jHc21<2N54@`}9)G;KaEDET6A+ZrY7!)dE?Z?qVAxzPbL#Zvqb<_b1H zz6o7vYCD9`mQ8JLOmao-#3REd6`ZXlxLgN)p(U5!&O?yT2KGs|Kw`e9#v3EN)f!wt1SYB6r?5kauqpU12J3w3E4XUnt0hAXW!U^p z-GR|;WKd8axYmHJr6BW*uc4n z(a)Vg2qU@ z7^RYKydHKmjzgXL@tf%A%37#TtAo<=i_~yf!BYHanXs1~5Tr6k*!V5k*j2%0n|A9L z#t~i^?qUa*6;$Adp2{pQjUut7g>Pzj(@&`2J?P`$3;q#wTOpj3PQs~fPSw<5^jtq_ zCB1mP1t3HA@t$M=B#oU*srrEGOQ3o=5aI?QhxBlGd^$kN*68g6*sjV@y-FR~+p^h7 zeDU$=C~8g+I7LMC95@^RG|NNSlym;kt|NVPN#Hd@YE4>%3IAMd;KD%(He;4*u>E}{ z*jA{=1u{=$Iv)LhIbh#`EkIoXb~a@-gYnSP@9KspK=ByxIE2QlH#{lt4Q)*-h#aQmkM)Q1ahbyI!1cW0d~Nm? zDwmVkfd`MBVx2o)MCH1p$=d)oiIo2cJdhM6laOp@px)5;Cf^Kt<4NMfjcjZ|bI(2# z0{cZSJPg<$MYhfA+(Oo|PC^yg+hUS$VzX0klKtE1eO`2r=yYy(cW%RbW=ngx0cS1P zV}irPfg~>aN-J?s*PZFXp|Mncnn-z6Y`@^HsBSn)eCr8=svE9@p5^l1<#*;{CutVy zZA_hXlt94Zo6&?Nxm%%j7WG&?JAi^EW3L2~xVqv?%zEwf$dVze+!X$I8q*sv8Xie; zVo3bMs8qcp707&RH?(22S_cdA$EUyl<(;DpYT3OF4Lr z+wh3UWx9Bgjx99&-OG5BbGRE`-5JDeyXMOKQsUVpZC}D%s#$U5!|+9#AXi%D*kLi> z{!!3=ovoD4(gMm4|c(r9R1=xkn1FFr@CJ8zmG1J zB38$*>DZ3zix_TE!~J-h&5lV2Sv8fEs;J(6trq7Fk`*PLTg>~lycXy>iQ5gA-w{M| z76HS@-3JUp4hz>I(Xs!k=VCjvWyhBUITNp2@z1kW$eYrw92<*S@07p$0|UE1#NsK#=^o8E1?NQ<+wuNDWDc&OU2MjX zzu3N#S1YOf&j2IzV_)R6D48!Q5{3c5qml$hjgx60RYT zcNJqPv)9uf#RDfKajTFdpQB_bjoQF#NB!<$Shaf?gKH?7I!L3DALm#brCSb8tOF zA>Gs#W;@8AtuTpu!&7aM5*;l zPE1~@g5dIRkl2M6wM#DlmL4>QkG(fd$3ii@ogozzya$VQouuFZsaMFm2Fm^+srMyj zWtAxep1~&I_HVyCm&RX=BttvcjyGxTdp^%zJ~f5w7Ormc-kMciGb+b>Gbm5G@sAcO z>>JY5Q<$*f`@f4uyu=T8F@r?bqB;kysE ztR=kd6yViJ?3hy;#2*_UBS~3Eg_7bl;f5E%ykCami&;wGf{})cc*{8Y(lg-1)QDw3 znMa)XJcOkU%aj0x`4N#Wm^W1T%7d#KVqHh-gW_s8dyqkGSs5(fCw0@U&Mg<~{sJ~_rC#FLV~iqQ^|A?s z9FD-ZF4%2m4ab}u#ZWs7=OXH7#-N5z4Qw?*=BUZDz$ezDoS1l zJcrWq;T*t98S^iOa~NBs9J0^pD1-&=#_)HzCNC9b?vObSSHd#+=?X`{fS%T$s(N!C*#9 z9j*~;*EPNx=IuuzA)mbz~l| z3LtMN-+&D*6m{Xzks-zcD!7P(k0&bzP&@A$ppM`pliV)fdZ27MUW{@&7UTFwuO`c1 z7&^Q-Q#n?0#~>lULOGVmBdu*U8+e~ImD0p7(&j6}ie1W)J)5MmDF|a%?k<3GZ;-2m zv*jh_CSzQ%y+`8Pl+xwQKF$_UJy%DTU1whuvhifX0pcr}EW?=ZOLr=Le!6lj6&PA# z4t5I@vAE=`B*&2#XBe23%x%0coZ5nwm}Wqdt^{l}bZy5E%-t-a(w^3|dKi5teD{y96n)$w0O`-!iKmE$-Le#+yi!|NtICPKV^ z`L)1~6`bD|&J!sz7Q{*d^E+Q(2_Q%{>75)(G98#`W(EyvMtS6MFw^QfIV!}%n^+qK z!+oecbboUU>P3V<9pX0e@s9QMJ={5R?4Il_((bhL`lHl#=P7JMFmIcro0igdwJFDk z1&5U5aA5fZ?anQKbaJm=TEsBalwD$V4i(6{} zPaZRu>FlY#RhT0ZVlYQ^ooG#4JXqv7nvTs7+bH%+BD0115L96nW?0GPZ$P&Z*#vsx z9&>Qfg78+ptg;FpZg5Q8M6_IgL!sgLyu`Pjo|<~xF|kxDc4r{Rxh+|>#VGmhn4y4G z1iT&A|G|N1Zg!;z9Xd_eT5|_;@yxtVygYzzqtkbAe7vx*!rif zh}#p9+i3=fbIpStYpbDh=k!+x_}QqyJy{BNyg4y&{yQ9c_c#WzG~%f-KZENq2o^ZoQLH z#?iwi5v~1-JhGx_B*v0$b`b?bQkMD_Brc4{4+~wZtpEk9!ybAz4`Ug4E@^@9ymiHr z_A&7-5;I%M9J6(tUdAft3JCaO#^RWt7xYQ^npJ{9BMQS}6>Cil7l*G9s8X6DS7H2|Q6#z^F!jR=7ox6UPa zRc0D9>v&IG!7>kccs$oGK8HosQ=RY;Gi%L1Rp)7WWV*vr%3QiR%zwq~7A;wp%8Wa&d)$LEU5@Mz8^@egAu%K7k8&B89j51WPY zg(@YskPt$4x`_TI{=C|(htcGh!xE(jSLl_qRXQp&!&HZy!J71X*;1gyj$}#h3|I^2yKYa{QQ$IPq zntPp2I)G4zMmzmHyAaMCy~VCIez|LB1mfFgD}uY6Gl6N>94J5zft;grwlO=(j9N~= zd$a$BCY#Nndb#`irN=KKUj67j;`{7Ng1JXgq85wKjRZ8ljKie~2BX!1s&63`gP+@c zv#6dts`E74o01-k_WI1Qc8%Uq9_QL2mJ{&sjKkRSFJTT(2(g^l2YjI+e~Lc*KYk2g zCbYSQ@|=^Y#AImj6+$mfb%Fh@Fnpr`NQuBa9YDfz3gP%=_v;g}I>OBj_yY{OKo z*(S};;B0#a>Dsv=)Nu;qK-+dCE1mdc`>e(P&v0K{(DA!5_Ve6d&1>5Z;J8Q|nk!dn z0yFrNI0GMTD+=AgChX;pL@gB@U@Q1|l0WzIv5?eZpBYB&rQ4JOq|d+fIDKyaCrQ32 z`B&%t#J61DNzB>~sk|#FN|aJos+k;|AX9uPu%<07;KjE=YhrbEeB{lVz$Ip~B6IUl-35KLCUq{OImPRv>ui|-q$X&74k~$UI8Shep9AXFI(q=ILVF>`41xN1ce|-nwg$0R#yhXD~?u=d^ zI2X7k2kNYME(ryJx8J-`2huAP|9PVhRz<&ops8XKE{X29)A4k!PN`p1)9TJQ=-FO~qkE&aM~VYuRtDuE^7KZve}}A4)VfycN5KbFC3)fA zsP3&^CPN{)`}tnFikP^*cq!s}R5o#a(f2dDXkaC3qdIlTp%wNyzPPj@D}~$R`M2lqguK}qfT$suJsk<#RJu5 zHwYCvaXs^Xe7I1lL~m4W?R@gWfOM-MU4(l1Wg}@vO{1nCsF#P#&Q zxkX+n^wKSTq=DMMlhRaD(()V_NkKJv9&c3VUSiRCpo32i9^JOFp_%x&n$(^4M(sPK zQCjA8d6uD%jIerFStG1o4_kMwY=PC|s+iZ6a0*thr`5MDh9Tm;w~6Z;dtmi?T79Df zeQt!+yF7KUdOfYaIU9y;R7S5W_2@S8tX@}6itvzQ+a4G@uA+HeX$Ba(5ytLvEvaeT z9aWk|d~KA%Vz(7bZDy})X(r5GPqS~t3KcmlD9;f~UMT8q76hon|T%Fcg4m?x?tqp2y55F+Fhym=nm2i1C<%pu4iA~ z)pOydzxV4r2o39@6n0lWn-5Y85?O*I=x+Ubn?v1c}S4k%zj&5~pFJ}8uay{uHXj=Z3W8+~=TMd)F6o-iNHl<{wJ8O6LQh6E78xF|4u!mB-Wp^#Z7mn!i%C_yQBF~08ysOEJ1eMfB zUNEGcOUc8F8a-X@BZwGKc9LK#bPJ4| zkJol^t1!G;u|T97cn*QANartyoe8z?BX|O}$G0E;dU-hUHG-$3 z^hhTtIPt1fdmAZ@>BO-+L0K-4XJN~WNf|*+{ECzwIZO*k>5#5R>`&*dN@KSTQ@iO+ zxOOJ!)0=@5=qGMQtU`+feR^60C=CeGb#RS9k5Wd?`~I!{5Rd7?iHhxr=wdpyBfT~q zl%AB6del*R>^V?GpB^GHjs~jpBzZs|p%a?~zKDW*X%WB|y#fCpPOqD|84`^ap&(Ex ze>;sdCIv$kNWE1t%UB2X9J9;;ib!Ll^2WkbU#=&L|(SI*#D zj=Q4)e9N0=@RbzheeuytFYp_I^Gz%mSmKt>;45+Efk%9C3myhV%*(sk)3lAa-1k8d zX-RG$C?bvh?F`c8wKGVU>)9fM$6M*f>PdRKGRBb~&~D{|Ju|$>z<|=cm2n$z%7|s% z#K_ejytd1mzH0;ViO*5q%7tzG1{`c?k zAH2bIW>Oe4XdKejt|QNibhR_}zW&|UC`E1YO@Z3Hl?g$FD)oLBAqKrIcwN39gnVo# zzC=n1z#x`z% z>S&m*R@uaj>nBED%)FmGG*ao;G94;YHKEg$y}08$^UGG)I|z?miRQ*6%qaK6&_7Jq z7Lyb;U0Y1zvgz7ll1$UJ#Uy4-*Y;uPKTOvalelNPjt|2E3Wp+bS#Y}B{^=iQ+L3l_ zrX6W9Gwn$0oM}he@WF}l&aQ6~Um5YCMgR1}nHHth&a~s7u1TjFy=xN^kZL$xdGq#{ z^Q0?J^R7)y?U*+EH@-uIpo4qky-^mYCjRiuehhAXf(G6&;wWlzReckX>YtqQX2c#t zDY`O`HzO{z2||PNdJ1R;K{{-LEM4Qd)&0glE+oD>NHO$pM6aQV!>M?d?u!NmN8?$V z6$dJa(&*{I<5}wFL}G_Df!^E%2j@v_fIlbFpu@=%%$f)2!! zC?68Wu)GnvmAwE5cO&!yTEt;_BlNY^x%n&7OvFc1Lwj$8zDV6;Sb7rIOEDgA1wt$7 z8BhncX{vJrCU*0nx1uxi2w8U^Y=RBr+gTGMOCIefZxU4F&&WFo>haG4;43<7FmD>w z)r!tq7vrBPZ*?_07fyWQW=A6WfNiXF$9 z1!ucK&AS&Arlsnd)Mii?RePW@1FfY~`}SimUz5DG2R3`C3*`9rV?X7jr6Jws)tmsF zq;`2{^4gYyf~LOx*aUT^r}QYD0j7d)KOVgGi~N6i>0aWaRCyph7D`HEx^7ZVZ{@B- z_&+D8%C05TSVnHW7Qo`I?5vu`GIHw|0W9FH3t$1YKY#^!!>6%~_;dj*;HhaWBfj}t zS(^tueE{< zboj)rg0BSTSyEE44%AUuY#K;ekpo_*K!6QL~1`JJ{J+6Ehb4!W8%XL?@b0u z`S8Mj3%~Kmt?^FcV;lg?aT(hsrZXVjzg;Cy4_=DQ9VYNz3n$M2UOSd5Y=2_hNAvm*HJTo*h)IlRPs@dG0>)91|aY>$kvyB`c^OqGT*tLH!Q(Vxj7d zTO995NZGiZ7vv*~nGOiP^@^keg2m0USOS8@ccC^eMdKD%qc$u+y%p=}t2o?7QhxXv zNDPIM)G#;_h`klwatA0FQ^mIQfE{=%T5IyjgS0hi2k~M4%zkDgSvv5xPP^oa)@Ce% zPz$HF5Jt zt73^BgZrr!0m@smeMK693a>%>4ZO;ID8!>casQppuVx3otST|dQ{@*xF}iz-?h*we z-SO?k?!DE?#J3qd#w1UD<2)$Fc~5O;4#p%;HC-X4d28C%1?m8*zxN(Z_qh>$HmgfS`SbYPX=h+yJRL$uPx~j(V@8 zyc^fpekh0dc1`QxO7Wny+*@-hgtal=`uVNjf?~a=8p=Qs%c-?JporkqdY4crFZDPm zV5vE|#{i0L`}sQ?S?^c8HJj)m;23H)FWf0YP+B{Mry<P{V$hz zWFB#t(sJhTPP2hV;tAb@bP`WA--^y(tvaeQ<&pn zmYhM}U7$+EQ9lA|^#SrWf~pX`JO(Ou9eJC)HM{FzLI`@jHGA$JAP+=FU_$`Z{?%mZ zK-Gw<3==nhd_Qd%o}^~4Q@YIr-u7(rC>?z7^Q5AOzejip1Z4*AfiX(4BKvWk*o_rb zW+i#dJMdekvwJqPt7z#WC9Q3P~AyHSo6Wf^oO-NN_^_$mSK3(m5$@oEftF_ncrlKd@2e9YFh8>s>XR;d=7=~jVBY7< zLwQCZ=&?&QeHzqCwKQ&RMKJNfzRdT$<*n&0S_~vq{j)_|r8~fDgTmROnqKcdv{I-{ z853xEZ)Wba4tftavtBHGpY7=&g?jrIl#_zFJRAHLDGPX3J1Jo9%}oSx0wwo3NEv{y zk8`xCD8gHFU{UIkz6cLj9t*JQGZNKvi(;oy9asgYE2s|iy1Lo_vF{^5gzq@dFu-cQ3J z=7UgVAWD7S-E+V_KPi*=pcldSd=MrIJvDSFDWJ89o6kqZBMb2zJO&e28l^i2Xa*4O zp0U@1N6{dZ0$$AyQ1sk~GQFT^uZLD|2StDV+~j#u8q%#DBL(9;w1Vqnf`5L`T2g4x z^X6D%y(2N6@J>hPPLM zG*Z9#4k%)N^vWtw9Ag`ku>b&Ol-CCp2@g7MUQ?>Vo4a?;Y`Se(~o*QC7r6*~lop zeB}m{(<{B0`X(qw953Q^VEprV*Q$tvq%?2MCkshHVJ~_D*61xicud_+>nx8ZwzPo9 zFF&*~h@D*K1trE1Pf9}2RiGNyv6O^~8_#cwV7k?mia$vN?=A^=>p^Y&Yo<#h^$F88 zAYF4ZsdiF#Q<@8^C62rupti8%RUUG*$b`^AY0TcEr^@)|N+gG~!uKtnZ(hzEeWZR% z9xjhR-;zPzL2votko}|(u0Q{cUy%w0Z$mimFX;*zLK$aZSmnhY=>dyj#CFHi~V&_Y8ZL{diUFunn$jG`^kIBGde;% zB`3(UI-Kd6{LyHP1m_yu(pEUwEM-??1Rq>P;N^An51SqoaRUMb{iqSAG%&`b9FZc?1;f}Bsci%-`io?0zV=a_wKv zJwV=qk@x>5W(9eR9qz&<8RSJm<12TNmp$^qKmX=s@}fqrZSR~SFV_*B5*ALLYvkJf zJ62D=5&p_8;tQj6iDQ9#mmqMXy}7~U6+n}9_b^Aa!&TMnI;9wIN!5x&4I`dcw_{fUOF4N8W0OYt@D>@)Ad`9s26K zwc^GqZZB;j_Bk?7RxbEBiF9gL|W*o9qz`YA}a_r^8WuAyWgsj zy1wn&16Ggl9w_*+wGEWRypJaX;bc3DLj9pQ_%<}jVr5mB2iPTu5j zm1WDmH3r!~J+Pd4gGS!}wnH4hedPKUi_~FuM6T4!siOmRY?EcB1%}v;BX10Dhr4B? z<>sLqzk7rD*0U5V3}OL}?l~x;4rqh{!c;jF1V>-vk`(!i;hK_vjqqA3;BheAky-Oo6%n`9YR*)`o zgok=k$qRRcXr5H2OChg>y!qsnkeB9gh6H=aivYzd12VX;L{P>2L>k$oXS7sP?MK-`)9uFV{rLN;HZ*L4aZ2>ZxK57b)Q_A=OKs8oIwKd|<*8n<@3^Nj?^LmN zXUE^)zP73%#i^?K(@+}Ja;TxybV5xeLQw5pbV7}#{=ONz*iM)I_V<7N*Bu?(rfF&qsIcEni=}tRpgJs~SJ>lRFPhB>w!!yeVKAZd%IAsYDhZa5UJ?M*%$t2%aN#&~W&{@>RvzWx2dntdH1YgVWZTT+gy zE;KGvo!df`YTkgiawo1m|LMN1k&B|6DuX&aswbvpFHYQwT&WXj|M)Klx0J@zsogch zU3vS0c5Tu2Hq4LqRF=*c-fk)^rfFT+;%cqho4j~I=Vl<-(qL@%>{}lb?P)JfE?%~G zc~&tRs43N2zPJrP=xM2F@A@o{T3wUrZoBOpTz7DM$2VGT$!7rMz3N*#vZr$KUUd>) zHgWCdd(}(uTHob&d@5`cKB?n#?e>}Q5?TA*2*o5r-wU``TOPK?ECDS=x z`Rr7eYw6@_ya=Z8wL`x7bvUO{-=zu~@f|z9`L#Ts6s|YA_V<;*|L}vR@AQ?lDYXnH z8Z@~8kAZi$+dY60IWT1U!ZI*qSwzY2Q5Vj6e7VPUFW){X9&J5zRCAu^5w71`hQs@e-F%cS&QOZl}B~*_5}Xw0$!xrD~jW*aQh?k zb@mGFu6{SZgE{Wz$NgRPa=&%V10@Mny2CV|AJ%n!Pd;&TyKdkdKB%g*uSUJDow%(U zT!a_uBJ=R+f4uY$kWb*NxfeT0{Y;?Ay;=fq=9?EPJqDQZmoMBo@&|iG%EbMAi~LEx zG4z!1`1mv*e>|JyX?~cB7o}ZKOyK6R{CTyG5trke-`O3C7SmEHTmU`J~SyZ6=qvwIWq)v@t2h~k|tgdIA24f^-p z`_R9;{?GnBPJ2GHg&llVL)zNu4lYf?OI2XeB;}$rQQjMm*EK!kjW59VG5_*9va1^} z0D4q6-nPNta^+WXevhvJji;bq`J4cCvXLKE(M|AkIU>CcX#D=3>r?4HF|}U%>iAli zS{4V;ftzUI|0eED;NvW=e9`(^tu2!5ZdsOOZT(4>wRNl2YOUT|vMhO%wRw>x*=~82 zY#B>l@DA+&F(3%TfDIPIki3Lp7{dU=Fu+YRkYN}gnM^{MTql>|5{FA5VX$SnyCu72 z^#1?z$!_pC_vO8t-|vZ^i>m&rPMtb+>eQ*KQ>PwBGqvfs-}U;NC;Del^HIiN3q0}b z-@itzH!|;D4z?D2o3Y1sX5B_)mBm*$>sx?|1$*j@eT4cHbM8gX{S<@yU_@(@SKu!R z=gMejRl5#T?a%#fCdnAz~q zAe4iDqO|z`lR)mXZBl770vA+ToS@u+dw5kTeOf|$0J|PjdHMeZR4dONq$O72w$nN= zr?Q0B{m0{P61_wzCjBfiaLeRNgEAP!x>-gp_#99C>7YGEAN(w$-jZ-xwr{!z!OSsC z{?W*l!zFUgU5I6%>r|Qz;BAluJZOodC&#A#G zvJ0>g(6FT1!)txkbKP68^2Y%O>>WY1l2X)R^27iaeF+-vH@Vm%vxnH*8rh;w3}LyY zYbzN~^{J`DGyWz>qvy1RL~S+atC!0+;XzBG3%$x~-X0Op({RfG)G#iO8FayfW$N%k z@1pU4WOt7VIw;!K_=P??aaH_3%LU!`9ON7MJwWMET0)negc7<57lZ=e7=^e(m9G-D z^}$zsY4;PrsxW{{|D*5y7l_|V=KJ0aWznp(C#8f1-tIOq%MZdy0a^k6YZME2AsBCM z(T#lWY>5rzSgv&*c68v0*Pvut=Rg8J^c3M8#@-zW2(&v;i#{itnON@+g2mv2z(V)8 zL&R_W_{U&|>`If_Bh28W@%{MhJ0QHOQ4H58(&!5~Q7+oYl3*I~+b9)%kqviwe)G#9 zG4sJMY{D!y=C$BGD(y`vhG#of1Fy*~`Gslr#;UbGkQVI*|JN$|aI0GISg zd=RfrY45}PARYm^UgFAPkYxORU-U%Jt;(g0pc1h@Jh)3%PLK553V8I>8&O(kf|Tp1 z%&j4QM}SMZIShGA9*#r$@|5!6H!nLNofWAFA+dn!$y5ERXBz?})84=Kb)ScPbrmHN zjZr4dN@907(#dt`h3Rr1WFY6-&>j1FQu_2U69PE)OrL&WqN^dhvn4zTD#v+E?zH$#&4wbQl55=`t({)->Ctw2G7 zf1JU|E4M~}a7SBvGqL)&_*2W`g?sdYL z{5pL#U!3lYPO>0Kj=`EK)1^9DPbcc>OuogVIv15AwX#FUdINbkE}E5oU_ART(`I!? zEhwn!&dXfk>CR71^=@swMORzb-0D%=Q<8gUZzuHez#H+;ZC{szd;ISD$6mbZUiR3F zy=`e0g+ND;2z53p^CCFF#K;ibCdHXzSCjsnal{=d-Ms~I(BUp1xsa@Q{ z*_{I%5$FtD>Wd^=|TFI zKQ&~?P=y5;Hewi1g;ALdYzz_@q~M=QWPnK&+cf-5&NAjQDVZats^r{R#832CDJ#2e zvIRAb`H~pKF*wg)3WKQx70Xx@W08zm7{oAXWh{a*80=zfGT=6dn#DlS$mVa!NNUFs z(LDUX{Sh8ZOakEfhE_B0Xp3A~$T0CkH1kz35QL=BRs10PZl(NC!lcF^g-L0GlvPX$ z02-R8SSBUk493d%TN-2Y8IyyfV!zp^3_masd#mOzxv8ttfwaB=p{C?ScnLv_#ysV?)5ZpK!6b)h5K46g2t&5Ny^>woNB1_;bDuyvW) zh}|B%&zEKupaU_$o(LrZXqr{DAusdw?Ljg5ZNLJ_HQ++Pc8LG!SRERTnYC>t;?jf& z|K)+dd7t<#kP?9|m9byoNuxQXZxc-_T$_{~$U#>~J~GVLHCxHSlQEJ3h^)v@J!-qsD%Y4+Lf83we-~H!q})D|qC>_^PAw zc({OibUWY0PM|X=`kJwxD_;WLH`uD~eXneZmav1}Q4%Zz8z7b$C3JB$tz1L#oN*Y* z3|?W+j09cMieby$Y)#vuhb0(Hnz>ZZ7Zg0z%Mh_sP}D1 zzAAW*Dh{6eJ}{`oJRn#Fe+GntdjNoKvvimW(H{d353O?(Kl(0Ie}T4TrUyQA zx!xdtsdz2m)F=3D>IJ_QCFqT-7#nBmya44GhR;8;Ew&8iV$bMQ$ao93Lrdl>ZuCj0 zP8lx^kAO?gve>ziD{3+ZU-2>)GWmY=d2ezb~w{hT| zyBb^W`-J%A4?}%=mJeTWeDrQ1HA*DOimEC-DCSSh9pbKn^;{J=v2Uyhna94a?){bB zQ<$&|@G{rqYvwLJCN`}gJ2wIzF2GzL(Eqs^9{NxJD)=+>M`=Ai_^oC*E6fE^JELM} z>yR`AmnmZ6gO>JVHS|A~S?NzS53QEDK?b|L?1y6O04Cm8q?2+8rotPaWUG;e83>0*67RlV^s*k8N}`5^UZ>K+%aG>g2@+|S%y1brNm4Hp1o}#$&lQc zk7N7A!&xr#HN?aRbLM8mbcKC8Je~-JNgKaE;^IVKd4$yqFYqSSQ*NxJGtWsrqOm(% zc1t-{w1juAr(D~i#y(ka+iBvrxxHLv(hX4NuSS0jvWQ9rT*Mb`=6-Ajq`IMwM4RPJ z2X_wY9lHqc&ZDm*GyRoleB#(0E`f@?3J4iE_mee8C9@rTOy6pmy$tpXYErLc;YRx^ z$>&`K-*594=XD(+etVeZcb1;7lx2yFQl-4+O?U^Stgr@W=6=~1l%)8?$74&UM=g*h ztI8ZeSNK@I(xLRZfsB55|0ad{5P0Q-hy|T~tl&E;fgTV03#iH%ucuxa9C)o4_+@FL zu?(1?O;9Z`rQE6|aMH?}Dw}?yVW4dO1x~6Fk}staSxVO+GZ44gbqBodU9rc*%S(JJ zUM_>@|Bt@Nj#t`1R4VpmO!J01Lz}>fZM3Km2U`;!;(}UWaY1Q#SlPCRw&?m*Z!;V@;%o8A?q<`qt-eHL;og)M zr~xQ{;n!DuhHbc<1lCc5cG&5n*fx_Jd``CQOB-^0Nac6#T1)n!qAe;b9WQESIrMl- zP6DZBcuNu*2;%95#rqZ#KN}$5`!Romml7>uANPJD1GS*l70m~KrPV+q@U@7E2`M)I zPwHO!w^>P-(OGSHI?1*;_>#}o=fX<}O?bdvT@pvb(=6x6uK^$h%BZQlR%OjAtz9C;vTn!QEm`X- zYj>Z(6n4+|qzbvnbU6ej!EN>0N7%Frqfh&?w&NMggu@k1m6b_vBdY_azCZLdV{3Sl z;pDRgXR`Am?E~n*oNPFkS+JM$gp+Pu0z~f!n_B}(m32EWP{mv=-{dJIdh?-g6p>&MTY$DyUA?HKxuX;mI@ir$3)XPsHC!C_`80Q*)Uvq?q~e~ZY@i}0#tIdJGj^g3mz zSFJ=Al4>LUP9E!reGh>6|#1;l$&e3 z$zIZhNABqX+qqTQk_ts;Z}01N`F5QIs`%HR8c=yG&^1mT4jcX7Zpf0TnXZuE7m zM%ei#8MEObEDRA?{P#=WA%2H?D!>{y;{~jEY?`nTrPY&^TWuoQ<;1ds$Ew1EBcFqh zNZ9jV5^bQGCJxVJms@5YIb4u#6fP5wM%m@yD-j)N@4c6qSyaiAtKS?doelhKG5Rtv zv40vc&{tCNB32|$h_$s&iXG~^72qL42}zdhaxklh+YrorS(4W)njkKeDYlX@c*!DV z*_dO}Q5?go@Yu`HQz9z$Bs5Egmj5s2H1oc>Ek(y;C9Tv-pCql?gu0SNDmRjcfkv1( z0?NSU8@@p;3_v<+tPlg#vk4XH1t=z1=|yOaU={cqW!w2j1fkD-`yU~Gd4ELa{~xl9 zRkggvV^v#)RL&DdVJqWoupr;N0V>|mPVYYO$3OwbO-B;=Er|0AV-W)iTT@f^@%$08 zY%0{vIF5hoQNI~%AZK}8bZGu~P}2|UMF=B`EHfCf2w!n1y0gQsgUm9F7?|~B44I7j zQX3~XTb)0eg83Uh+gsqH#01ux0i6Oat}wL3jaGE<5on~Cm96K+Q!=2 zoaF%E;TEB56-8JD!29DsiBcpj5-VS!Z0!^W^ipX1fyAH^$li?Y2f@EbZP$M@vam&G zOS=F->eU^SNd92-J3xrS%uHHE3&935JW92@kWA^jMi>9b1C2i=ewzkpVMSUQS{L-q zL8_3sarChmb*1k4>_;m0XmQ3K&d7iI24g!Dmt@y+7cN3(nUo@pj{{=Pu7Vki;u&l# z03=2V04dSI5_W|wvfgbXHK@u(NO!Z*Z%I4C>dv(J={tFBX&bl!N-*AM+bOl_z%PR8 zSR@}Hl%10I1`<(6$O{ZyIhcomMw*pC={(xDOBgtG5PZdf9LuuN`V^4liURVCSh49(uYqgadwaIS)s;7rMf331}QMm@E z$|^qay07+roj#ilkSo4%64ocepyxZ{d&G%yYu#M z<2ej;r^$T#NkMmK3wWfVtN^D!E88c7<;yJ!=O&iu%bM$a9lJ{5dEJY5CzUv=kX9ZM0JPl|ZwgH2~(U<>mN8#tYL_-6wO-{4VCp_JZP;KFn(|!aYI=qmF2^1FyALV|OHK z0J}1unjJG`6iFSG9uCbkrO&&DkYg?oax4Nuj^%#SosKqinWK!v8NK+AUtjwe@tYUC zXm%JH7Kgeh8_~?SdDN3T)Cim{?++`)#_z#gs-t80RH%NEVn<8iu3I;@O?YCe-y3hgfe;!(E<6v>Drnh+Glz4s-$(qZ#f5_ z;d)*~kv|%!VS{IIDr&oB?sXAu_-0Ol!3Bz&A zB~iEp2jp=v*jS2Dn_+UE&2~Jen__CYk835%*BpX>R}WFsJDiCzwRt7@ty8P0PFg|y zIz(DY<_;6YotT$&n3}PO`$P@Gh);`)^}mgw2F@OwCKeB)Pb>WgXaW{f=rSln{WR?B zK?N|F$;3)M4$m^Fv>3-cKnXm6Q7`cDm{nTU$hdECI?d!VWi3RK&{jcTPeMeB*X=P2 zO1N^jtX)j}dWC(Ar8HK!-(nTx3!%OO<+Q1RN08Uig?gk4@gFMCMO|l`<$({Qgg_ek zTn$ba(Z*`|T9y7``ARJgPd)%j30Ew7QuB82SO70YND0y*g>;BF3~6GJPrq&T%#ITl z{h!pM#Lj=1x*tES8I1$3egB3?!S{ z#&p&6WYD6T&vtuM^CtXu;3$4OaM^DGJp6Xx7+QX4Gj<;iRpofpp>F(ks1h^Fq0Lyq z9ulBD;Y^#UdsG@@#})&?vE?Hkb*yvDtB$S5Z-;-1uZIuf!;y$_mpWnx&?6?mJ96HF z+t`IJk6L2G*CkEk-+%n4zaahW$hTx}BEP!%75Pf%Az8Wr`ATmG&ZTbzn^oysK&W&p zz7`(=l;R`6w0J*$E8dUH#Ya%K_{cEcn|J{&a+ct$a}OXp4-I?xTQhzW`l02^IuR^S z0H({G$hUkppe&yg{F|J@of8wUWDg8CblJ9F{BYd1k+F>zn}$~&yV&%~%4a2M{PuY} zK3vZ-{Cci!weg{(Yx%1eOX`-tjAYu(a0!V`QyccQv5)Q;e*1OX#;BbBO=Wn5D!Z0n zw|^EYwwFBu&^{w?P7T?-nzz&^fz25R;s1n2Lz zZFFi?=MS7Xn7w@Xom|wITfM0shO^m^fCMltDF0t7LIO^pCJ90>y4Y*u?YS&V?oO-8s?Q7x4piGSSX@x1io0{4?Nf2PCzPNkf%$AlA*m zi+`$y z*)0LFa!7!$t}Zz}m$}rH2jdG)`qqGVMb2Es*f46aBpT8wDf%x4nQ1DyDal{fj5G#KdLGMcltY`fi zw8wzAC+7sd&fJNhKsse6zS=)yGMWLKAe?Il_ZanNp`=0QjE&cR6Lcqofhh2O@E%{z zb7kAKxGAN1YG#t?I?gDZfK=*zuLB``$H$on>;5XQ78}Rb4 z)f+8}gSxWp#Z|M2-}eB@G?6_Itp&X3mL`^v-;87DUlKo_+2NAKqk~-iiNosSAnc<{ z{hII5t=QFn^eJbImbyw$KtAln$4&J|_y%n`7MzIV>Ji?h`&StM=!r;TdmYbl4(H+o z8^3A6@B4DzWh>9g&7DPUxvBf)X4de^!ViB({C*|ZeB|C%!(4bfY?zxhd(PN}AKC2< z3zJt?U!L`M>t`{zuoPFF_F+DnGheP88TYYPZs@IRo!#D;w{>Y%W8VIZ zeT{Ai!NxM@9M!lmX|^u6zb5a2>A3XHOH`{DBvn@;I5cPVg6ZiUSDw4~v5!_SNG_an z<+;Ja{izEo{+{TKA~nBE?whTf)3q*Do-tduV1Bv>!Ld1V@u}0@xWgNI^5=HDTwdy) zR*ZLGvhq5syKM`K=4_32E>p(6s;QAjy;~D+iRsvyy!D`a{7D$~A^70J*5uocc;w>P z)|9NmwDG_C^UPV}e}%7G(<67y7=MAu7ys=qpWIGR+o$aEsJ*LVn>@g8=Jf3Zx}89A zP3^Id#(#^<+w*RNt>Qx5uo@p>a+xE;I)3Sq;wQ&1{XDZmE>dl8-EwHo_O=y==JYH+ z-(}q0;svf-5%eZAn1`Ux+q*pSXv)>{-*$b3U}qVO77oqnZNoh`1U<8RJLkvFzIw~w zjeT}??~i`9YiCn(&+J`!xy5CLU%SOk^vZVS<<0l*&N;TMYWK{>^o{{rWIF82|713d z{~tkpacje=*~G8q4+6llGtI5cs&MVFrdFgNm^nJEW#nH)tZ_F!G|n6Tj@mI5$=+We zuuWIyn2MtiJB3S!HFIT+%2fq!d?;!}vf^`X75rZ?_8jt6Mk1z<0*WnXG8UuX3h?@S z%3Q5?kG^Uz{fPMOR&~{BS;)7t9K}l7kh$az1g-`K>HKZ8IZ3%3OctZIm5(7-aR%#{ z+|SX3LJGdTDgY>$hTm*)T1<>B2OqNfwRn}g2pe0f6n6DG%B8JgKi{NDLL28zifSBLPo@zHEs0c0(%&wRr-^MXt! z#^wc|stE7s^L#%$_$(&Rj$~XKb5=r53(H-4E>#suW__X>P%?F1nppWh5yk z4|CZcM>R1HGOJ2v(wZ(7vqp+i-Cu?!j^h{*dyHJcJ(qWA;m>+x@(=9H2#3coP2IVL? z!>96jvW~6dc-x|Z42x2ihF<>ZQ^c=^kBq&Do=LNQ0bk&nTzitP2(yp$f?kR1dptiV zG-GP{Z;1M82$jp zjGJDMqs@w(sEiimygPRzl_UG?WR;t@F`4^OKf#VQE=R^C^X=}q;A?0qpjbZ?D1^6* zC5q+XjvHMxXUyH$!jsPN)ke~KR%~D#&(dz<_Za%}%MWYPUZT~nq3i%Qx>dyzmFq>>+_N4}0Tx&ogS%5I!F4I+Aa-53 zg1uA)da$n?J4ihLkJIr%b*};g7OdhncrsW%@RNs?rmq4M28)!Mm>r{XTdx#914}21 zLuu`m?Pzr4!x0mD4A9jp3ry;Z{--{5iZd5`u^ox%+ADS6)vvB&OeBLah;c3o zTn>{}J_(kisii=Y_}QEra+YA3JFl)(TZ8+;V|J0Guu7P}i&-a%8(2a)azRD?u_}|1E~B*V<_U z;=Ve7Plq-^=1fWT%%%LBHO zJ#Q>&9_g)g7<>A&lEW-t<&9am6&P5ebPJDR`c=G#KxbX=6wY}|@MX|{Z-zfjgA<-H&dSbq zxlF3X3kmE*bE87_%#sDR^<#}Om3#lKs674v$0b*O@zwqWTAodZ;ezhsaQ=pG!3%=W z0u{4x%^U<($Tz=>#O9QlYDY5jHoqDlddgdiv9;D6Z!RQ$P2O58+=#|pzZvz)Az^tl zk{roxj5)`0)!^)cW?0B}W?<;La{94@u?f_bV&qBUhv#82bj`t&YSvZ`1LOD@_3ocT_!%VGnGP1Pm42mJ zeKW`w9rC;s0N8qkbTo{J2yRpZok&`uCLZV>>m`0~g;{g~cl{)g`4T6=3wdW}_Ajb1 zG>qf((p*5HJk?URpydER|5=eQRXOM=AxEOwEdLMWMm( zgX^Y&>-diQlP!6qJ>*6cucSW-D0v(G5y*l!Z3pL*Ob2ipIqO(E;dMD-$XIdf*6a`6VTmdMHqvm z%R&)1*C#ncpvcsgk^^|%6k6T2Xp9IbmYDCx+jz`p`HX=f<|r9LI=mOO>bU99mYsvm zIegu*oh3HY!$KSBH*LJ>^F@QiZ=pPm#(@*b+BEb>UXIb|JRshZhe0PjICl$L36k8L zoX!}0xPhGP-=jCB{qO&4W@(H}9WoO)9jS=hNBq_cvl@;IVClla6kjb9n((+W%7{3d z<)YqMBOhQ^p&big3b6K zD;5l}Y_$o)DvxEGFNtn z8WrJ#^-Pf&7l?470Uc%5;<9 z!*7tRyvmWMZ-|8{pT@f&R`bx4xMfoO5%D`s5njxS+QuxnCE@Yl{sm)A*|`wcwY&y` z=9`bhBL^N0J&elP%Ck#ylY(EN;7FUIe3&nJE_^NsOFP{<++I4CrIafNeV6lrX}F}O^~+4 zYO~Z!Q-MewDvn!#4$Q-{>I(?oDK6ugZHD z;3K9Ft9e7+{17P*brSqevd<#K(yZ$??=H?Je!t+24rBqXm_>AuoFIg`*eO^$K;6iI z71ObMazUPE?eb#4dN+Yf_G6PFAOyjf9~T?|1Bcot5x*=+^!cN2 z2s~n?l@MOVQI)Tviu?NdfL}hYjX+}rlKH7R4jJudzD9OAWQ;Ua5n%UpBAReD#uxR&@zgse_=;kFrvKC9U;8}pYu~BMQ1bbbE7rupPkpCG1w0M7xWKZW zV@0`K!Y>Ao=XdLzdyE)v`lvh%Shpk_Oj?|ALwB^s2L{21sNkWy^Bd=zRsO8NImALE zFR$bNL4Kpuq4+n9e>O&V*rhrd9AXmc_hj-HjByBSyg{s$GH4QnSb3II9*!CKflC%c z-NGX7vTv{<1%!-t!eAx$I_VaoZTSN-c}Z^t@AVBX&Fy!kQoqXINh6|JvE3}NRUkwjB=BHk;AfyNZbpHU9uPJ# zi~zb>@=+NsmCFz#b;(24qs*7Z5q9}~ZOq)M6EWLVjC zkSDmrH`v6o1=30;TbL{)C}5Al4vV}gG4fS_1`qlM+qTC*=kk9IO)W9$`KyE)+y-3Y)rDgy6y=dULAI|Y}ZIqM%%h~HDB?nA(dyGE!o zSm0BgE=*q2X;c`oi+5cxgT)mIE`79=cFLGxH~V8Afh|5VFY(9Rtu%J6$><7fd(J39 zQKM6gR=%xHjY79QHCm->$%o~)IS}TDgFU{%)kNb>&n6`GS}jFg{mEOlw}{`H;})N~ z-2iZHko4YUko4X#NTe_Q7IY&!YM}rSf(5L=O0Ppj?5I!Jzpr61)!q-{;7s1EYMX;+ zF&cvhAkm4{Ie!XbV;5EJ{gqwdgR(Bj`=GynU_0^qh+Vc<=WmilpvXXkTssw@x@FuS z&|^?G5983CvO|lrvlomt1UYtX3Qiy$SbCfav_}CoQs@Yd5|fVz;v4eTY~35cs$;4b zSL6HK{`Q zeDqV?s%r8ei?B1G7vM$~7()~aT2FgGk+fLDtd9#NDTXN-=Ymvt%5yM0fEuIgmM04_T|0(5DT6DHH@) zL2adud5H91%zdUdZi*I3#|Yk{M4%Z359ki`<)#(%aCZrcg%EAP3@#NexPddIqc39( zxmq-Bf?qxM&EArkMDG!bOY_*e?+-Ptz}98K*l*?ywTYj+CLpE8a@0L7o9a1&QSVbV zSkV-W9S3T`7kmXzao4hizZKRYD8j~<^(?Q(S@e3`i4?5lvhlbZoX7UA3;xuMTkylx zTMtN5B>C6~RAJ^T94mrBRY8v`=-eMYV+nj%-d*q#^X=prLL^)uZT~3nqdSM@cVvLV z)BrWt(MiZ#M{q2#u_LO#r<^V$7rN?!KFfAoudPFm>fdImfoXc7zX2UsgD#IAyLjhN zi{#^N1nwmiYGNy(x|6fN}+& zQw8srWWbtWVBQkgZEQkqkPx^fn+vvbZ^DPMi}QvO!aINjwa1Nj&W)?GfRfOU->gSD z%IysDP>0P>!O@LVpGo5d^>6s5JSM}-Q*#KO1iWg>N5d~X_f!MXyC@e5WW-eFXsKNA z7aWD^t71DgAc@SlF~1fgfyiGCzKstwo|ydbj1OOVm0qwQ<5;jpk*@_83F?U7jIuXe zhPk%4TNovKyU1sA2I`Q{_y87HlxW;#bwa3i-XO7Hna|v7xGZfmfwL7 zc3F?0B3q-g0J6HQz;Jg^n0d`Fz##X$Gt)!s^UMztzvAHAXg;QFn22BxcpazHj~VM^ zu%4rIFK=({_FEPG2V8R)@P!Utm-4c3AO@W;15b>aWpfD_WUhs8zCj!34K6z}?()a_ zqUmaGa5HRC;9cNXzEh!rJd_RHjTo}@me47gR*!W-#oQeC=3~TfIeOpNcPPRaj}0qpT(VcvW}?EiYOJc!hKmU@f6gH!R=v z1u>J3Bamh41>rUM4f}GZ-+?gWJ#HSjMEu6l%n|ptSC*;ZxP3NP77a*F*FLf@SHi?FTp=wcM7xCdrI|9)g8B7g*8x#B- z59%0w9lRk6c^>^#a5bOjMYow{Pe8cyn%jn{7bHeeS4_ViybDqIB$~!OR>OTq;kU(o z$5`sV3ys9@$;qbufWV{4JD?XvWgvoTNb!^aye*OFCUkj{G)_~OIh zuIzab(&GnE0u+L;PGo+^7);kWR?kIm`L!5u;udhCR5W_m$qOG5zjH)mH_EOkk`4_W zm*E_{o*?W05SUBN93a?eFN5K5xD?mBeW^fp* zga=Wjagm7I$?>P(>F$xCrivn(u!m%?a-uf0x2Pm^?m9bCR0-JuYUK`@YijGNd&>RX zz-nNuy%s@#D&E|=KE$K_(JxP24Lt?nOQwz<|Lo=eJOliSG64l_3zj$ZHpr%XdCZt` zj9fQOH}5{-twR%pYnjR}0GDwrnrh*P#%NRsoEu?`op1P793aLOMDaLJGmG_B3(<;I2=hj39A+9+FEwGirg)J&euNp0UqyUC)tL?WA$^zM|ST3j{P*}b)0)sQ&( z$k)J_%qUWuv`j=a8Sl7I+1Pr;^plDW7V9}^Ng@OCszO^p`TADydZ-Su@DP!sN*NeB z4JCLv)YuS~yOSbUwWfMA4cCg$?dYc9Ds-%rAiAaE%JrHyn`RZ=RO}7HqnDe5&xVNN6E05BcNNqx%I^H=t-b z+-l6xQ8r!#!FUA-D?5`SygJRzFe*tz(3V&_YZ37~iOZ5uFZKWf$+E>9@#`&Qw;*7FBr5n@G>!ZlDM<#n z2j>ADSd2jwd>lpe2Zs%(OGQ8I$S6#+mtwsvgZHJcI5jHT5G1L9P|-V5mVIpOKl)7| z2HaPPvzwwH0=4trjtq3n=p(A=U2ft&2TnOZ5W4)Ijqeh_clCMrs#nLRt<||BDh_-+vdEItStIF3I3 z6N76Hqw@yLOK^brJ2kjh%m{QjgI9OLj6h;BlqXc0vU5-y^nw_%WtoHD>=Culx=O}c zu(*|W$O;)q+OZ6++7%an+{=_jBuZ9d`0CE32CK;egd*=RN5d zC4QdJ1WQzd0KEvH00o5{-D^0Epz`-L{XVbuC(au>LzQn0b(Gz}1uXRqpMCKN7K#UG z(q-;)9Yn1Vdey{qVU?>U&F;afP5I5=8XC}DfGQt?Ex9M(gn==Fk8)3bPV8;LHY{0o zMXs%&vs`;3*2MU&HTTqXNWa(wM-3-&<&vH-A_p9%o zn$Or)zlMOZ`~BK?Pu}i zWj~*ix2u;fZ|vE!(+Az?)Q8dw-1Pd8TRQzlk{>E1IXSJ{7eisS7Y>6Mk@fT?0PdqeSWDRpL0!>(llyn%poGqg9U`cS-^Sp>KKsV-3Pj}gsO1G-7q!@3 z$O0$UG2b#~0-9Y4i}kmBH5MPrk`2R|NOEPJSM2d;ZjPNnTluvRle21Qxqcb~S=7Zx2{} zI%2e@<6Tx1`x#k-oxea~w7?I^sSg4y5t@!FLu;5sFP;wl5~zuSC2bSpN@K>W4IyBq znTdU=ko4-t@4Z8JbN2PY3jlzMY`NUR-tAAUKKZym@s*Qr`lnT&{Mr4J9)ElTLF8>{%umO5<{}szC_>H6!3=GEk6pR!2)Mw@r&Hf7` zcAYN;=WtVN_7<0~CVqW#n#B?yY=8u>=A2tyfdMeEmD~u#tr=i}A-pt)pnM+tG7kg5 zpw<5bR^`>ozEApyP(BLO_)dKgYBBJ$e;_`)!Ta_Qd2k`RB$+!2_D(J^k1%%RhOdP3 z!1&qQ26-)e@@rpC1UP;PI3CS1q)0E%w2OJ+3bO*VQ>e7K?V;oc#Oe!7@T47;&AHMJ$&xQ zu}$z|MN0fqRTUkY(Tg?@9&;6m?tn=#xb|VkW|kVB!?Y5 zcx1z{dPS8CtJf6{n%-7r62o{{N#B_cIAq{{NxyIK4tJdv2L~3)u~&W*2__C=7}FRt z1unhW`4REk&)*{a%h0LWuILN&VMG>Ej%~rubVoWcEw;nuA)ehhs&r0R#nVH;3XYZ{ z4|6N6I63&K?wILX0i-2~%$Or#5wSXWKzGayw&@NY@fIiZH$Go6bSAi0ca#O!>W<~| zLG<;|HUJGZ=#HJGT@bz69%nk|mSS^ojqacgMRBq}LU-7`eNkdCRh-;`eOdFECCM=p zG_Yp$Ie?#k8fewRLmT{7yoKoAA>gH~V7isQz6^w*4Xq)P4>8}&VE?xqM}jT7^e(Kg9Y|&?2gtvK$bdR8BU+PMQq2X5#0kw0^QvO7iA+ zx%rx9aSqL?*5!fMFkWGKQ&0ywJ9A+l2&0|ByRd;92d52c@C2|rNOSeX1R)sJ(XfxU z$Rol$iNu7i<*t3xiC^h;ixT?wwVq+U;$li%?oMSgGSrsj*sL!rozXkl zm*6n=^brPgh1VFngTW%45DcARY>>fngX<7`h{-Z0S21>m`CvMg~>P9>E&IAyaE1YOnv@(nzdE*RND!0s^^e{~4 z(S+8K@&BuHCh=<`x_g=VNyZ-I*EYt!V|3$TjOEZG($8Ir)sY*kqwH#k7TtnTHhwGI z{sp>x#ZN=Evz{$s7JPt51%K*Li<3#R@|la!!J{u)uw@?OMSmDEsv8$A_#g&s!zyvb zXQ*rPZ|u!~IP)s;+u-3Za>nHHgl#1-s3FkBDZ^$llqhs)+5TK1R;OPCpjYj zj?$13w-^9mAUTzNX?C;;pN8V_Ayn(bS8^5xk>CU|EmCw71NXR8on;$wtAxf=OC;gZeaRPNG1cxXquTtj}G~q)0s4l{x_d-v#_TW;q_xm}TQqH6 zCl|gEF^-)yan_cS(Sv88OZfR)J(J^QV4tvZ$it0@s#MTrfPt9Hi37AR>hE6n8u3fJ zvYlk2Hyg4FePucMW{EQsSi!$ngxRrE+&{7x*3o)y1$iwG@N}RSjgfb`uvj1`Vk(zr5qzNqj!GJX=UzE|Sw4^?kFgH!h{YcXjc;Cg zjQAC{%!A&=+u0oU@e6eGz>K37=uRsqK@lk7k)L_@!?|@NQ4KyWDw06PMb?BgmS_t9 z7W|uQ6|s|-28(>MhISrc*(a(J3XZ_A50FQK>@t*X4wt2ely4s@Ny(!tduMfbPb9i8 zMvH5?p$=~k7+4xZ{B((ln;=2l7zWoXm*3W7n421MQA~z`ST6-_5n}a|7BP^jPxc_; zamq*c#F4$f+(#uT;0WgvBc1=chz{wT4bps$TEllC%fhE7D&kf{1l#+astowOllFEK zX9F^P6xlIc%*SyotSbaD_|OlLV7ZW{m5@YAt6ba5NN9N0b#Q+a}h}>CxF7Q z&vmQZxz)sP4G@~-I()F6lM%`+HrgS!-T>uGnZc*8-h@Tp5*EcZ7pK=B`N|L%d`_K> zE*zQW8+`H)GMr?&&O`47-Y$CY9^xn5^hCJ#{|Ij4EiPP)xyDjti?%PZ)W^R6La-Y+ zM|y!YFvh}-Ohef@x^?Mn>Zi_qVJW&Eg2L2Lbd7y@Un(-pK0;2m(%>A!ed|{_C(I?3 z0{#8X>NZKjl0bV&^CyNgaJ(cVCtvBU53WQA0dfT!@o7naxE$%eu)*; zTHLCN0wB2&!!ODWc^}1?DaQ-J*an(LwUe-+Eg)y93kwc5btBI(qPHwV#$9gA$$f6j zUR!oZ62qm>tvsrGkLKZED&e9$e!&(Cz7nX}=|arC1+fl9%sDR9dBblbi+{V9KFdn7 zyZH=*r~!Qm$jwP4+FuP^{76MQX~{Q|=o>uKu>%`L2rEnh=43WbPa zT2TPR>dBJ?dzQ_@VGg8TX&r#F#Cbs+@N(~93>$S_CDWa*ff;*S)@mE6AC$P@?X?64 zn;xZD(ON>;%Cb(Jeqmy%0g{3hf6Hgja9_5hQnKiEC?+MmJGd>44;h4aNV--kC(w3& zm@BAB+qiPzq*+o*crP%vfPphy%yV%1p{2xcApxvo9mm4}q)HF!j^^YVg)6TjmL{!f zsIJ<(x1k%E?+H9@1zRF0xOTsW