|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 218112 (0x35400) Types: TextFile Names: »monprocs«
└─⟦621cfb9a2⟧ Bits:30002817 RC8000 Dump tape fra HCØ. Detaljer om "HC8000" projekt. └─⟦0364f57e3⟧ └─⟦80d78256e⟧ »kkmon4filer« └─⟦this⟧
\f m. monprocs - monitor procedures b.i30 w. i0=81 04 09, i1=12 00 00 ; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime; c.i0-a133 c.i0-a133-1, a133=i0, a134=i1, z. c.i1-a134-1, a134=i1, z. z. i10=i0, i20=i1 i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000 i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000 i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100 i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10 i2: <: date :> (:i15+48:)<16+(:i14+48:)<8+46 (:i13+48:)<16+(:i12+48:)<8+46 (:i11+48:)<16+(:i10+48:)<8+32 (:i25+48:)<16+(:i24+48:)<8+46 (:i23+48:)<16+(:i22+48:)<8+46 (:i21+48:)<16+(:i20+48:)<8+ 0 i3: al. w0 i2. ; write date: rs w0 x2+0 ; first free:=start(text); al w2 0 ; jl x3 ; return to slang(status ok); jl. i3. ; e. j. \f ; list of monitor procedures: b16: ; start: e0 ; 0 : set interrupt e1 ; 2 : reset, priv e2 ; 4 : process description e3 ; 6 : initialise process e4 ; 8 : reserve process e5 ; 10 : release process e6 ; 12 : include user e7 ; 14 : exclude user e8 ; 16 : send message e9 ; 18 : wait answer e10 ; 20 : wait message e11 ; 22 : send answer e12 ; 24 : wait event e13 ; 26 : get event e14 ; 28 : (type w0, not icluded in rc8000) e15 ; 30: set cpu mask (or lookup cpu mask) 'cpumask' e16 ; 32: select or remove master process 'systemaddr' e17 ; 34: move-buff 'sendfurther' e18 ; 36 : get clock e19 ; 38 : set clock e20 ; 40 : create entry e21 ; 42 : lookup entry e22 ; 44 : change entry e23 ; 46 : rename entry e24 ; 48 : remove entry e25 ; 50 : permanent entry e26 ; 52 : create area process e27 ; 54 : create peripheral process e28 ; 56 : create internal process e29 ; 58 : start internal process e30 ; 60 : stop internal process e31 ; 62 : modify internal process e32 ; 64 : remove process e33 ; 66 : test event e34 ; 68 : generate name e35 ; 70 : copy e36 ; 72 : set catalog base e37 ; 74 : set entry base e38 ; 76 : lookup head and tail e39 ; 78 : set backing storage claims e40 ; 80 : create pseudo process e41 ; 82 : regret message e42 ; 84 : general copy e43 ; 86 : lookup aux entry e44 ; 88 : clear statistics in entry e45 ; 90 : permanent entry in aux catalog e46 ; 92 : create entry lock process e47 ; 94 : set priority e48 ; 96 : relocate process e49 ; 98 : set address base e50 ; 100 : start io e51 ; 102 : prepare backing storage e52 ; 104 : insert entry e53 ; 106 : insert backing storage e54 ; 108 : delete backing storage e55 ; 110 : delete entries e56 ; 112 : connect main catalog e57 ; 114 : remove main catalog e58 ; 116 :set process extensions e59 ; 118 : lookup bs claims e60 ; 120 : create aux entry and area process e61 ; 122 : remove aux entry e62 ; 124 : send pseudo message e63 ; 126 : select or remove buff e64 ; 128 : start cpu(1) b17=k-b16 ; max monitor call number b. i20 w. i0: 0 ; saved w0 i1: 0 ; saved w1 i2: 0 ; saved w2 i3: 0 ; saved w3 i8: 0 ; internal ; procedure deliver answer; ; comment: delivers an answer from a receiver to a sender. if the sender is waiting for the ; answer, it will be started. if the message is regretted (or sender removed), the ; buffer is returned to the mess buf pool. ; call: w2=buf, w3=link ; exit: w0, w1=unchanged, w2, w3=undef ; return address: link d15: ds. w1 i1. ; save registers; rs. w3 i3. ; i9: dl w1 x2+6 ; internal:=sender(buf); (w0 := receiver(buf)) sh w1 -1 ; if internal<0 then jl. i12. ; goto regretted; rl w3 x1+a10 ; sn w3 64 ; if kind(sender)=pseudo process then rl w1 x1+a50 ; internal:=mainproc(sender); sz w3 -1-64 ; if kind(sender) is neither internal nor pseudo process then rl w1 x1+a250 ; internal:=driverproc(sender); rl w3 x1+a192 ; process type sl w3 3 ; if mirror proc then rl w1 x1+a190 ; calling proc:=master proc rs. w1 i8. ; save(internal); bz w3 x1+a13 ; w3:=state(internal); sn w3 a103 ; if state<>wait answer or se w2 (x1+a30) ; save w2(internal)<>buf then jl. i13. ; goto event; rs w0 x1+a28 ; save w0(internal) := result := receiver(buf); jl w3 d109 ; increase buf claim, remove release buf(internal, buf); rl. w3 i8. ; restore(internal); al w1 x2+8 ; from:=buf+8; rl w2 x3+a29 ; answer:=save w1(internal); wa w2 x3+a182 ; get physical address of answer area jl w3 d14 ; move mess(from, answer); i10: rl. w1 i8. ; jl w3 d10 ; link internal(internal); i11: dl. w1 i1. ; exit: restore(w0, w1); jl. (i3.) ; return; i12: al. w3 i11. ; regretted: remove release buf; jl d106 ; goto exit; i13: jl w3 d5 ; event: al w1 x1+a15 ; remove(buf); jl w3 d6 ; link(event q(internal), buf); bz w0 x1-a15+a13; se w0 a104 ; if state<>wait event then jl. i11. ; goto exit; al w0 1 ; result:=1; (i.e. answer); rs w0 x1-a15+a28; save w0(internal) := result; rs w2 x1-a15+a30; save w2(internal):=buf; jl. i10. ; goto set result; ; procedure deliver message; ; comment: delivers the message to an internal process, and starts it if it is waiting for a message; ; call: w2=buf, w3=link ; exit: w0, w1=unchanged, w2, w3=undef ; return address: link d16: ds. w1 i1. ; save registers; ds. w3 i3. ; rl w1 x2+4 ; internal:=receiver(buf); rl w0 x1+a10 ; sn w0 64 ; if kind(internal)=pseudo process then rl w1 x1+a50 ; internal:=mainproc(internal); sz w0 -1-64 ; if kind(internal) is neither internal process nor pseudo process then rl w1 x1+a250 ; internal:=driverproc(internal); rl w0 x1+a192 ; process type sl w0 3 ; if mirror proc then rl w1 x1+a190 ; calling proc:=master proc sn w1 0 ; if internal not defined then jl. i16. ; goto unknown; rs. w1 i8. ; save(internal); bz w0 x1+a13 ; w0:=state(internal); se w0 a102 ; if state<>wait message then jl. i15. ; goto event; rl w2 x2+6 ; rs w2 x1+a28 ; save w0(internal):=sender(buf); rl w3 x1+a31 ; name:=save w3(internal); wa w3 x1+a182 ; get phys. addr. dl w1 x2+a11+2 ; move 4 words process name; ds w1 x3+2 ; dl w1 x2+a11+6 ; ds w1 x3+6 ; rl. w1 i8. ; rl w2 x1+a29 ; mess := save w1(internal); wa w2 x1+a182 ; get phys. addr. rl. w1 i2. ; restore(buf); al w1 x1+8 ; jl w3 d14 ; move mess(buf+8, mess); i14: rl. w1 i8. ; start driver: jl w3 d10 ; link internal(internal); rl. w1 i8. ; rl. w2 i2. ; jl w3 d108 ; claim buffer (internal, buf); notice: error exit if exceeded rs w2 x1+a30 ; save w2(internal) := buf; dl. w1 i1. ; restore(w0, w1); jl. (i3.) ; return; i15: al w1 x1+a15 ; event: jl w3 d6 ; link(event q(internal), buf); se w0 a104 ; if state<>wait event then jl. i11. ; goto exit; al w0 0 ; result:=0; (i.e. message); rs w0 x1-a15+a28; save w0(internal) := result; jl. i14. ; goto start driver; i16: al w0 5 ; unknown: rs w0 x2+4 ; receiver(buf) := 5; i.e. result := 5; jl. i9. ; goto deliver answer; ; procedure deliver general event ; ; comment: when a process issues one of the following monitor calls: ; a. initialize process (switch = 0) ; b. reserve process (switch = 2) ; c. release process (switch = 4) ; concerning an external process, this procedure is called. ; the sender is stopped, and the process description is linked to the eventqueue ; of the driver process. ; ; the driver process must call ...wait event... in order to get the request. ; as soon as the driver process reaches a process description in the eventqueue, ; the process description will be removed from the eventqueue, and a message buffer ; (taken from the driver process) will be initialized with: ; ; links = out of queue ; receiver = - external process descr. addr. (odd) ; sender = senders - - - ; operation= switch ; ; this message buffer is given to the driver process. ; ; the driver process should now pay attention to the request and (sooner or later) ; answer the sender (and thereby restart it) by calling the monitor procedure ; ...send answer..., and return to another call of wait event. ; ; --- ; ; this is the normal way it should work, but there are - of course - some exceptions ; to the rule. the sender may be stopped and started - or even worse: it may have ; its instruction counter modified (i.e. parent break) before it is started. ; ; the special cases are: ; a. the sender is stopped while the process description is still in the event- ; queue of the driver process (i.e. not remarked by the driver). ; b. the sender is stopped after the driver process has started processing the ; request, but before the driver has answered the sender. ; c. the sender is answered after case b. ; d. the sender is started by its parent, after case b. ; e. the sender is modified (or removed) by its parent, after case b. ; ; ad a. the instruction counter of the sender may be decreased by 2 (i.e. the call ; will be repeated later) because the driver has not started processing of ; the request yet. ; ad b. the driver process has started processing of the request, i.e. the call may not ; be repeated as in case a. ; the sender must be left in a special state, so that a following ...start ; internal... , ...modify internal... or ...remove internal... will take ; special actions. ; ad c. the driver process has now terminated the request, but the sender is stopped by ; its parent. ; the state of the sender should just be changed to the usual ...waiting for start... . ; ad d. the sender may not be started yet, because the driver process has not termi- ; nated the request-handling. just leave the sender-state as it was before it ; was stopped (i.e. as before case b.). ; ad e. the parent of the sender must have rights to force the sender to proceed. ; since the driver process still presumes that the sender is stopped, the ; change is signalled by regretting the message buffer that contains informa- ; tion of the old request. ; (i.e. the driver process need not be aware of the state of the sender, ; because the call ...send answer... is completely blind, if the buffer is ; regretted). ; ; ; call: w0 = switch, w1 = sender, w2 = proc ; exit address: c99 (interrupt return) d100:ls w0 -1 ; wait address(sender) := wa w0 4 ; switch shift (-1) wa w0 4 ; + 2 * proc; rs w0 x1+a40 ; (only nescessary in case driver is busy) rl w3 x2+a10 ; driver := proc; sn w3 64 ; if receiver is pseudo process then rl w2 x2+a50 ; driver := main proc(receiver); sz w3 -1-64 ; if receiver is neither internal nor pseudo process then rl w2 x2+a250 ; driver := driver process(receiver); ; evt teste at w2 eksisterer ds. w2 i2. ; save(sender, driver); al w0 a101 ; jl w3 d9 ; remove internal(sender, waiting for procfunc); rl. w1 i2. ; w1 := driver; rl. w2 i1. ; w2 := timequeuelink(sender); al w2 x2+a16 ; bz w0 x1+a13 ; sn w0 a104 ; if state(driver) <> waiting for event then jl. i17. ; begin al w1 x1+a15 ; link(eventq(driver), sender descr); al w3 c99 ; goto interrupt return; jl d6 ; end; d120: ; take general event: i17: rs. w1 i8. ; save (driver); bz w3 x1+a19 ; if bufclaim(driver) = 0 then sn w3 0 ; jl. i14. ; goto start driver; al w3 x3-1 ; decrease(bufclaim(driver)); hs w3 x1+a19 ; bz w3 x2-a16+a19; decrease(bufclaim(sender)); al w3 x3-1 ; (it is just to facilitate regretting etc, hs w3 x2-a16+a19; so don't care for claims exceeded) al w0 1 ; make save ic (sender) odd; lo w0 x2-a16+a33; i.e. signal that the request rs w0 x2-a16+a33; is being processed; al w0 2.11 ; unpack switch: la w0 x2-a16+a40; switch := wait addr(sender) extract 2 shift 1; ls w0 1 ; al w3 x2-a16 ; w3 := sender; rl w2 b8 ; buf := next(mess buf pool); rs w0 x2+8 ; operation(buf) := switch; al w0 4 ; rs w0 x1+a28 ; save w0(driver) := 4; i.e. result = imm. message ; unpack proc: al w0 -1<2 ; proc := wait addr(sender) shift (-2) shift 1; la w0 x3+a40 ; ls w0 -1 ; rx w3 0 ; sender(buf) := sender; ac w3 x3+1 ; receiver(buf) := -proc-1; (i.e. odd, claimed) ds w0 x2+6 ; (odd == immediate message) jl w3 d5 ; remove(buf); rs w2 x1+a30 ; save w2(driver) := buf; al w3 c99 ; link internal(driver); jl d10 ; goto interrupt return; e. c.(:a90>0 a.1:)-1 ; coredump. ; only used in connection with power up. the dump is executed ; using the fpa with io device number 2. ; call: return: ; w0 destroyed ; w1 destroyed ; w2 destroyed ; w3 link destroyed b. c10, d40, i50, r20 w. d140: rs. w3 d32. ; coredump: ; start of coredump: ; change eventually contents of devicebase, unless already done. i0: al. w0 d11. ; device base := local base; rx w0 b65 ; se w0 (b65) ; if device base <> old base then rx. w0 d30. ; save(old device base); sn w0 0 ; if saved old device base = 0 then jl. i40. ; goto end coredump; ; restart coredump: ; the coredump starts from coreaddress zero i10: al w1 -512 ; coreaddr := -512; rs. w1 d21. ; ; next coreblock: i11: rl. w1 d21. ; addr := coreaddr + 512; al w1 x1+512 ; di w0 x1+8 ; if addr = top core then sx 2.111 ; al w1 -1 ; endblock := true se w1 -1 ; else rs. w1 d21. ; coreaddr := addr; rs. w1 d22. ; al w0 0 ; retries := 0; rs. w0 d31. ; ; send coreblock: ; initialize transfer-variables ; start the device and wait for interrupt i15: al w0 0 ; rs. w0 d13. ; interrupt := false; rs. w0 d23. ; received command := illegal; do. w0 (d10.) ; start device(irrell register); rl. w1 d0. ; (get loopcount) i16: ; se. w0 (d13.) ; wait until interrupt jl. i30. ; or timeout; al w1 x1-1 ; se w1 0 ; if interrupt then jl. i16. ; goto after interrupt; ; the transfer did not terminate within a certain time: ; reset the device, and wait some time i17: am. (d10.) ; do w0 +2 ; reset device(irrell register); ; sx 2.010 ; if disconnected then ; jl. i40. ; goto end coredump; rl. w1 d1. ; (get loop count) i18: ; al w1 x1-1 ; wait some time; se w1 0 ; jl. i18. ; ; prepare repeat of transfer: ; increase retries ; if too many then halt ; goto send coreblock i20: rl. w1 d31. ; al w1 x1+1 ; increase(retries); rs. w1 d31. ; sh w1 100 ; if retries < max then jl. i15. ; goto send coreblock; jl -1 ; halt; ; definition of dumpdevice: r20 = 3 ; 3=fpa transmitter ; definition of coredump startchar and commandchars: r10 = 253 ; coredump block r0 = 128 ; send next block r1 = 2 ; start coredump r2 = 12 ; end coredump (= reject from ncp) r3 = 1 ; retransmit ; timercounts: d0: 100000 ; loopcount for transfer d1: 100000 ; loopcount for reset ; device address: d10: 1<23 + r20 < 3 ; ; device descriptor: d11 = k - r20 < 3 ; device base for coredump c0 ; channel program start d12 ; standard status d13 ; interrupt address -1 ; interrupt data ; status area: d12 = 0 ; (not used) ; interrupt word: d13: 0 ; 0==false, else true ; coredump channel program: c0: 0<8 , 0 , 12 ; clear core(0:7) d20: r10<16+3<8+1<7, d20, 1 ; send startchar (from left char in the command) d21 = k+2, 3<8+1<7, 0 , 768 ; send coreblock 3<8 , d22, 2 ; send coreaddr (two leftmost chars) 1<8 , d23, 1 ; receive command char 15<8 ; stop ; coreaddress: -1==endblock, else blockaddress d22: 0 ; ; command character d23: 0 ; (received in leftmost char) ; miscellaneous: d30: 0 ; saved device base d31: 0 ; retries d32: 0 ; saved link ; after interrupt: ; don't care if the output was not actually made. ; switch out, depending on received command-character. i30: rl. w0 d23. ; ls w0 -16 ; w0 := received command, rigth justified; sn w0 r0 ; if command = next then jl. i11. ; goto next coreblock; sn w0 r1 ; if command = start coredump then jl. i10. ; goto restart; sn w0 r2 ; if command = end then jl. i40. ; goto end coredump; sn w0 r3 ; if command = retransmit then jl. i15. ; goto send coreblock; jl. i20. ; goto prepare repeat; ; end of coredump: ; restore device base: i40: rl. w0 d30. ; rs w0 b65 ; device base := old device base; jl. (d32.) ; exit: return; e. z. ; ; procedure test other computers ; if current proces has performed a call of ; create internal process (other computers) ; start internal process (other computers) ; stop internal process (other computers) ; modify internal process (other computers) ; remove internal process (other computers or own computer) ; then there is selected and initialized a message buffer ; ; - 10 0 ; - 8 0 - 6 0 ; - 4 0 ; - 2 0 ; buf + 0 next buf ; + 2 prev buff ; + 4 receiver (=master process) ; + 6 sender (=calling process) ; + 8 1<22 + monitor procedure number (56,58,60,62 or 64) ; +10 saved w0 (from calling process) ; +12 - w1 - ; +14 - w2 - ; +16 - w3 - ; ; and the buffer is linked to the master process (this computer) ; ; call w2=curr+a16 w3 =return ; return: w2 is unchanged ; b. h10,i10 w. ; d40: rl w1 b105 ; w1:= master se w1 0 ; if master not present sn w1 x2-a16 ; or calling proc =master proc then jl x3 ; return rl w1 x2-a16+a33; w1:=ic.cur al w0 2.11111111; la w0 x1-2 ; w1:= monitor procedure number sh w0 64 ; if number > 64 or sh w0 55 ; number <56 then jl x3 ; return rs. w0 h1. ; save monitor procedure number ds. w3 h3. ; save(w2,w3) se w0 56 ; if not create internal process then jl. i0. ; goto search name rl w1 x2-a16+a29; w1:=saved w1 rl w1 x1+8 ; w1:=mode se w1 -8 ; if mode<>-8 then jl x3 ; return jl. i2. ; else goto select buff i0: rl w2 x2-a16+a31; w2:=saved w3 jl w3 d11 ; search name jl. i5. ; if not found then return rl w3 x3 ; else w3:=proc rl w0 x3 ; w0:=kind se w3 (b105) ; if masterproc or se w0 0 ; not internal proc then jl. i5. ; return rl w0 x3+a194 ; w0:=proc addr other comp. sh w0 0 ; if not mirror process or a proc with mirror proc thenen jl. i5. ; return rl w0 x3+a34 ; w0:=parent addr se w0 (b1) ; if curr<>parent then jl. i5. ; return i2: rl w1 b105 ; w1:=master proc rl w2 b8 ; w2:=next buff al w0 -2 ; set up message buff rs w0 x2+a158 ; buf -10 := -2 (mon call buff) ld w0 -100 ; buf - 8 := 0 rs w0 x2+a156 ; buf - 6 := 0 ds w0 x2+a154 ; buf - 4 := 0 rl. w3 h2. ; al w3 x3-a16 ; rs w3 x2+a142 ; + 6 :=sender rs w1 x2+a141 ; + 4 :=receiver rl. w0 h0. ; wa. w0 h1. ; rs w0 x2+a145 ; + 8 := 1<22 + monitor procedure no dl w1 x3+a29 ; +10 := w0.sender ds w1 x2+a145+4 ; +12 := w1.sender dl w1 x3+a31 ; +14 := w2.sender ds w1 x2+a145+8 ; +16 := w3.sender rs w0 x2+a139 ; w2.sender jl w3 d5 ; remove buf al w3 c99 ; jl. d16. ; deliver message and goto interrupt return i5: dl. w3 h3. ; jl x3 ; return h0: 1<22 h1: 0 h2: 0 h3: 0 e. \f ; procedure set interrupt(address, mask); ; call: return: ; save w0 mask unchanged ; save w1 unchanged ; save w2 unchanged ; save w3 address unchanged b. i2 w. e0: rl w2 x1+a31 ; address:=save w3 (cur); al w0 x2+a180 ; (w0 = top of regdump) se w2 0 ; if address <> 0 then jl w3 d112 ; check within(address, top regdump); rl w3 x1+a27 ; sn w3 (x1+a170) ; if old intaddr = old escape address then rs w2 x1+a170 ; escape address := address; rl w0 x1+a176 ; se w0 0 ; if monitor function <> set interrupt address then am a170-a27; escape address := address rs w2 x1+a27 ; else intaddr := address; se w0 0 ; am 4 ; dl. w3 i1. ; la w2 x1+a28 ; mask := save w0(cur) extract relevant bits; la w3 x1+a32 ; status := status(cur) remove the corresponding bits; sn w0 0 ; ls w2 -3 ; (if set intaddr then oldfashioned rc4000 style) lo w2 6 ; status(cur) := status 'or' mask; rs w2 x1+a32 ; gg w3 b91 ; move: user exception address(cur) dl w1 x1+a170 ; user escape address(cur) ds w1 x3+a325+a328; to: previous interrupt stack element; jl c99 ; goto interrupt return; 8.3000 0000 ; i1-2: extract aritmetic bits (nb: oldfashioned rc4000-way) i1: 8.7477 7777 ; : remove - - 8.2477 0000 ; i1+2: extract escape bits 8.5300 7777 ; i1+4: remove - - e. ; procedure process description(name, result); ; call: return: ; save w0 result (=0, proc descr addr) ; save w1 ; save w2 ; save w3 name b. i0 w. e2: jl w3 d101 ; check and search name al. w3 i0. ;+2 not found: w3:=zero address rl w0 x3 ; result := proc descr; jl r28 ; goto return prepared result; i0: 0 ; e. ; procedure initialize process(name, result); ; - reserve - ( - , - ); ; call: return: ; save w0 result (=0, 1, 2, 3) ; save w1 unchanged ; save w2 unchanged ; save w3 name unchanged e3: am 0-2 ; initialize: e4: al w0 2 ; reserve: prepare result, in case of internal proc; jl w3 d101 ; check and search name; jl r3 ;+2 not found: goto result 3; rl w2 x3 ;+4 proc:=name table(entry) rl w3 x2+a10 ; if kind(proc) neither internal process sz w3 -1-64 ; nor pseudo process then jl. d100. ; deliver general event (w0=switch, w1=cur, w2=proc) ; and goto interrupt return; jl r28 ; goto return prepared result; ; procedure release process (name); ; call: return: ; save w0 unchanged ; save w1 unchanged ; save w2 unchanged ; save w3 name unchanged e5: jl w3 d101 ; check and search name; jl c99 ;+2 not found: goto interrupt return; rl w2 x3 ;+4 proc:=name table(entry); al w0 4 ; switch:=4; rl w3 x2+a10 ; if kind(proc) neither internal process sz w3 -1-64 ; nor pseudo process then jl. d100. ; deliver generel event (w0=switch, w1=cur, w2=proc) ; and goto interrupt return; jl c99 ; goto interrupt return; ; procedure include user(name, device, result); ; - exclude - ( - , - , - ); ; call: return: ; save w0 result (=0, 2, 3, 4) ; save w1 device unchanged ; save w2 unchanged ; save w3 name unchanged b. i0 w. e6: am d126-d123; include: switch := insert user; e7: al w0 d123 ; exclude: switch := remove user; rs. w0 i0. ; save(switch); jl w3 d101 ; check and search name; jl r3 ;+2 not found: goto result3; rl w2 x3 ;+4 child:=name table(entry); rs w2 x1+a28 ; save w0(cur) := child; rl w3 x2+a10 ; w3:=kind(child); sn w3 0 ; if kind<>0 or se w1 (x2+a34) ; cur<>parent(child) then jl r3 ; goto result 3; rl w3 x1+a29 ; device:=save w1(cur); ls w3 1 ; wa w3 b4 ; entry:=2*device+first device; sl w3 (b4) ; if entry<first device or sl w3 (b5) ; entry>=first area then jl r4 ; goto result 4; rl w2 x3 ; proc:=name table(entry); jl w3 d102 ; check user(cur, proc); jl r2 ;+2 not user: goto result 2; rl w1 x1+a28 ; restore(child); jl. w3 (i0.) ; insert/remove user(child, proc); rl w1 b1 ; restore(cur); jl r0 ; goto result 0; i0: 0 ; saved switch e. ; procedure send pseudo message(pseudo proc, name, mess, buf); ; call return ; save w0 pseudo proc descr unch. ; save w1 mess unch. ; save w2 mess flag unch. ; save w3 name unch. ; procedure send message(name, mess, buf); ; call: return: ; save w0 unchanged ; save w1 mess unchanged ; save w2 mess flag unchanged ; save w3 name unchanged b. i10 w. ; send pseudo message: e62: rl w3 x1+a28 ; proc:= savew0(cur); sh w3 0 ; if savew0 <= 0 jl c29 ; then goto internal 3; rl w2 x3+a10 ; se w2 64 ; if kind(proc) <> pseudo kind jl c29 ; then goto internal 3; rl w2 x3+a50 ; se w2 (b1) ; if main(proc) <> cur jl c29 ; then goto internal 3; am -1 ; function:= send pseudo message; ; send message: e8: al w0 0 ; function:= send message; rs. w0 i7. ; save function; rl w3 x1+a31 ; if savew3(cur) <= last of name table then sh w3 (b7) ; jl. i3. ; goto driver message; i6: jl w3 d110 ; check mess area and name area(name); wa w2 x1+a182 ; get phys. addr. rl w3 x2+8 ; entry:=word(name+8); sl w3 (b3) ; if entry<name table start or sl w3 (b7) ; entry>=name table end then jl. i1. ; goto search; rl w3 x3 ; proc:=name table(entry); dl w1 x2+2 ; sn w0 (x3+a11) ; if name in call<>name in monitor then se w1 (x3+a11+2) ; jl. i1. ; goto search; sn w0 0 ; if name(0)=0 then jl. i2. ; goto unknown; dl w1 x2+6 ; sn w0 (x3+a11+4) ; se w1 (x3+a11+6) ; jl. i1. ; ; the receiver is found. now check bufclaim and deliver the message ; w3=proc i0: rl. w0 i7. ; if function = send pseudo message then sn w0 0 ; begin jl. i10. ; rl w0 x3+a10 ; if kind(receiver) <> internal se w0 0 ; then goto internal 3; jl c29 ; end; i10: rl w1 b1 ; bz w0 x1+a19 ; if buf claim(cur)=0 then sn w0 0 ; goto decrease buffer claim; jl d108 ; (which exits with save w2=0); bs. w0 1 ; decrease (bufclaim(cur)); hs w0 x1+a19 ; rl w2 b8 ; buf:=next(mess pool); rs w3 x2+4 ; receiver(buf):=proc; rl. w3 i7. ; se w3 0 ; if function = send pseudo message jl. i8. ; then sender(buf):= pseudo proc rs w1 x2+6 ; else sender(buf):= cur; jl. i9. ; i8: rl w3 x1+a28 ; rs w3 x2+6 ; i9: rl w3 x1+a30 ; rs w3 x2+a139 ; mess flag(buf):=saved w2; rs w2 x1+a30 ; save w2(cur):=buf; rl w3 x1+a29 ; mess:=save w1(cur); wa w3 x1+a182 ; get phys. addr. dl w1 x3+2 ; ds w1 x2+10 ; move 8 words from mess to buf; dl w1 x3+6 ; ds w1 x2+14 ; dl w1 x3+10 ; ds w1 x2+18 ; dl w1 x3+14 ; i4: ds w1 x2+22 ; move last: jl w3 d5 ; remove(buf); al w3 c99 ; deliver message(buf); jl. d16. ; goto interrupt return; ; the name table address was illegal or not correct: i1: rl w1 b1 ; w1:= cur ws w2 x1+a182 ; logical address jl w3 d11 ; search name(name.entry) jl. i2. ; not found: goto unknown wa w2 x1+a182 ; physical buffer address rs w3 x2+8 ; word(name+8):=entry; rl w3 x3 ; proc:=name table(entry); jl. i0. ; goto found; i2: rl w1 b1 ; unknown: rl w2 b8 ; buf:=next(mess pool); rl w3 x1+a30 ; rs w3 x2+a139 ; mess.flag=saved w2 jl w3 d108 ; claim buffer(cur, buf); rs w2 x1+a30 ; save w2(cur) := buf; al w0 5 ; receiver(buf):=result:=5; rl. w3 i7. ; if function = send pseudo message se w3 0 ; then sender(buf):= pseudo proc rl w1 x1+a28 ; else sender(buf):= cur; ds w1 x2+6 ; sender(buf):=cur; al w3 c99 ; deliver answer(buf); jl. d15. ; goto interrupt return; i3: sl w3 (b6) ; driver message: sl w3 (b7) ; if save w3(cur) outside nametable then jl. i6. ; continue normal;; ; test that save w1(cur) is an external proc description rl w2 b4 ; rl w3 x1+a29 ; for w2 := first device in name table i5: sl w2 (b5) ; step 2 until top device do jl c29 ; al w2 x2+2 ; if save w1(cur) = entry(w2) then se w3 (x2-2) ; goto found; jl. i5. ; not found: goto internal 3; rl w0 x3+a10 ; found: sz w0 -1-64 ; if kind(proc) = internal process or pseudo process se w1 (x3+a250) ; or cur <> driverproc(proc) then jl c29 ; goto internal 3; rl w2 b8 ; buf := next (mess buf pool); jl w3 d108 ; claim buffer(buf); rl w3 (x1+a31) ; receiver(buf) := name table(save w3(cur)); rl w0 x1+a29 ; sender(buf) := proc; i.e. save w1(cur); ds w0 x2+6 ; ld w1 -65 ; ds w1 x2+10 ; clear rest of message; ds w1 x2+14 ; ds w1 x2+18 ; jl. i4. ; goto move last; i7: 0 ; save function; e. ; procedure wait answer(buf, answer, result); ; call: return: ; save w0 result (=1, 2, 3, 4, 5) ; save w1 answer unchanged ; save w2 b uf unchanged ; save w3 unchanged b. i5 w. e9: jl w3 d103 ; check message area and buf; rl w3 x2+6 ; proc:= sender(buf); rl w0 x3+a10 ; if kind(proc) = pseudo kind then se w0 64 ; begin jl. i0. ; if main(proc) <> cur rl w0 x3+a50 ; then goto internal 3 se w0 (b1) ; else goto ok; jl c29 ; end jl. i1. ; else i0: se w1 (x2+6) ; if proc <> cur jl c29 ; then goto internal 3; i1: ; ok: rl w0 x2+4 ; w0:=receiver(buf); sz w0 -8 ; if answer not send then jl d104 ; goto remove wait answer; rs w0 x1+a28 ; save w0(cur):=result; jl w3 d109 ; increase claim, remove release buf(cur, buf); rl w3 b1 ; w3:=cur; al w1 x2+8 ; rl w2 x3+a29 ; move mess(buf+8, answer); wa w2 x3+a182 ; get physical address of answer area al w3 c99 ; jl d14 ; goto interrupt return; e. ; procedure wait message(name, mess, buf, result); ; call: return: ; save w0 result (=sender descr addr) ; save w1 mess unchanged ; save w2 buf ; save w3 name unchanged b. i20 w. e10: jl w3 d110 ; check mess area and name area; al w3 -8 ; al w2 x1+a15 ; buf:=event q(cur); i2: rl w2 x2+0 ; next: buf:=next(buf); sn w2 x1+a15 ; if buf=event q(cur) then jl d105 ; goto remove wait message; sz w3 (x2+4) ; if answer then jl. i3. ; jl. i2. ; goto next; i3: sl w2 (b8+4) ; if buf not message buffer then sl w2 (b8+6) ; jl. i2. ; goto next; (i.e. some kind of general event); sh w3 (x2+4) ; if message buffer not claimed then jl w3 d108 ; claim buffer(cur,buf); jl w3 d5 ; remove(buf); rl w3 x2+6 ; rs w3 x1+a28 ; save w0(cur):=sender(buf); rs w2 x1+a30 ; save w2(cur):=buf; sh w3 0 ; if sender(buf)<=0 then al w3 x1 ; sender:=dummy name address; rl w2 x1+a31 ; move 4 words process name wa w2 x1+a182 ; add base of current process dl w1 x3+a11+2 ; from sender ds w1 x2+2 ; dl w1 x3+a11+6 ; ds w1 x2+6 ; to name parameter; rl w2 b1 ; rl w0 x2+a182 ; get base of current process dl w3 x2+a30 ; mess:= save w1(cur) wa w2 0 ; get physical address of message area al w1 x3+8 ; w1:=buf+8; al w3 c99 ; move mess(buf+8, mess); jl d14 ; goto interrupt return; ; procedure send answer(buf, answer, result); ; call: return: ; save w0 result unchanged ; save w1 answer unchanged ; save w2 buf unchanged ; save w3 unchanged e11: jl w3 d103 ; check message area and buf(cur); rl w3 x2+a158 ; w3:=buffer type se w3 -2 ; if it is not a moncall buffer then jl. i9. ; goto i9 rl w3 b105 ; se w3 0 ; if rhdriver exist then jl. i12. ; goto i12 i9: ac w3 (x2+4) ; check state: sh w3 -1 ; if receiver(buf)>0 jl c29 ; goto internal 3; (i.e. not claimed); sz w3 2.1 ; make receiver even; al w3 x3-1 ; (in case of immediate message) rl w0 x3+a10 ; if kind(-receiver(buf))=pseudoproc then sn w0 64 ; rl w3 x3+a50 ; receiver:=-mainproc(-receiver); sz w0 -1-64 ; if receiver is neither internal process nor pseudo process then rl w3 x3+a250 ; receiver := driverproc(receiver); se w1 x3 ; if -receiver<>cur then jl c29 ; goto internal 3; (i.e. cur not receiver); rl w3 x2+4 ; if receiver(buf) odd then sz w3 2.1 ; goto immediate message; jl. i4. ; rl w0 x1+a28 ; result:=save w0(cur); sl w0 1 ; if result<1 or sl w0 6 ; result>5 then jl c29 ; goto internal 3; rs w0 x2+4 ; receiver(buf):=result; bz w3 x1+a19 ; al w3 x3+1 ; increase buf claim(cur); hs w3 x1+a19 ; rl w0 x1+a182 ; rl w1 x1+a29 ; wa w1 0 ; get physical address of answer area al w2 x2+8 ; jl w3 d14 ; move mess(answer, buf+8); al w2 x2-8 ; al w3 c99 ; deliver answer(buf); jl. d15. ; goto interrupt return; ; ; if the buffer contain an answer from mon call other computer then ; set result in calling proc i12: dl w1 x2+a142 ; w0:=receiver w1:=sender ds. w1 i11. ; ld w0 -100 ; ds w0 x2+a156 ; clear buff(other comp),receiver-sender, rs w0 x2+a154 ; proc descr addr bz w0 x2+a145+1 ; w0:=mon call number rl w3 x2+a145+6 ; w3:=saved w2 (mon call) sn w0 60 ; if stop internal proc then rs w3 x1+a30 ; saved w2.proc:=stop ip buf jl w3 d106 ; remove buff rl. w1 i11. ; restore sender sh w1 0 ; if regretted then jl c99 ; return rl. w3 i10. ; w3:=receiver sh w3 0 ; ac w3 x3 ; bz w2 x3+a19 ; al w2 x2+1 ; increase bufferclaim.master hs w2 x3+a19 ; rl w2 x3+a28 ; w2:=answer rs w2 x1+a28 ; set result se w0 60 ; if not stop internal then jl. i13. ; rl w2 x1+a30 ; jl w3 d5 ; remove buf al w1 x1+a15 ; jl w3 d6 ; link buf al w1 x1-a15 ; rl w0 x1+a28 ; w0:=answer ds w1 x2+6 ; set answer,sender bz w0 x1+a19 ; bs. w0 1 ; decrease buffer claim hs w0 x1+a19 ; i13: al w3 c99 ; and return interrupt jl d10 ; i10: 0 ; receiver i11: 0 ; sender ; immediate message ; originates from a call of initialize process etc ; entry: w1=cur, w2=buf, w3=receiver (negative, odd) i4: ac w3 x3+1 ; make receiver even; rs. w3 i8. ; save(receiver); dl w0 x2+8 ; ds. w0 i7. ; save(sender(buf), switch); jl w3 d109 ; increase bufclaim, remove release buf(cur, buf); ; now the receiving driver has no responsibilities any longer rl. w1 i6. ; restore(sender); sh w1 0 ; if sender <= 0 then jl c99 ; goto interrupt return; (i.e. regretted) al w0 -1<1 ; make save ic(sender) even to la w0 x1+a33 ; indicate that answer is received; rs w0 x1+a33 ; bz w3 x1+a19 ; increase(bufclaim(sender)); al w3 x3+1 ; (remember: the earlier decrease was just hs w3 x1+a19 ; to facilitate...) ; maybe transfer result: rl. w3 i7. ; restore(switch); rl w2 b1 ; w2 := cur; rl w0 x2+a28 ; result := save w0(cur); se w3 4 ; if switch <> 4 then rs w0 x1+a28 ; save w0(sender) := result; (i.e. unless release process) ; maybe do the final insertion/removal of user/reserver: se w0 0 ; if result = 0 then jl. i5. ; begin rl w0 x2+a29 ; if save w1(cur) odd sz w0 2.1 ; al w3 x3+1 ; and switch = 0 then sn w3 1 ; al w3 2 ; switch := 2; i.e. reserve process; rl. w2 i8. ; restore(receiver); jl. x3+2 ; case switch(buf) of: am d126-d125; switch=0: initialize proc: insert user(sender, receiver proc) am d125-d124; switch=2: reserve proc: insert reserver( - , - - ) jl w3 d124 ; switch=4: release proc: remove reserver( - , - - ) i5: ; end; bz w0 x1+a13 ; if state(sender) = waiting for proc func then sn w0 a101 ; link internal(sender); jl w3 d10 ; (i.e. start unless already stopped by parent) jl c99 ; goto interrupt return; i6: 0 ; saved sender(buf) i7: 0 ; saved switch i8: 0 ; saved receiver(buf) e. ; procedure wait event(last buf, next buf, result); ; call: return: ; save w0 result (=0, 1) ; save w1 unchanged ; save w2 last buf unchanged ; save w3 unchanged ; procedure test event(last buf, next buf, result); ; call: return: ; saved w0 result (-1: empty, 0: message, 1: answer) ; saved w1 unchanged/sender(mess)/message flag ; saved w2 last buf next buf ; saved w3 unchanged b. i20 w. c96: rl w1 b1 ; entry to wait first event: rl w2 x1+a302 ; goto wait-first-event entry jl (x2+a304) ; in the driver process; e33: am -1-0 ; test event: function:=inspect; e12: al w0 0 ; wait event: function:=wait; rs. w0 i0. ; rl w2 x1+a30 ; last buf:=save w2(cur); se w2 0 ; if last buf<>0 then jl. i4. ; check event(cur, last buf); al w2 x1+a15 ; else last buf:=event q(cur); i3: al w3 x2 ; al w0 0 ; jl. i6. ; goto test buf; i4: jl w3 d19 ; check event: call check event jl. i3. ; ; scan the event queue, from last buf, until last buf or already waited buf. ; in the last case: release the claim. ; ; w0=0, w2=buf, w3=last buf i5: rl w2 x2+0 ; next buf: buf:=next(buf); sn w2 x3 ; if buf=last buf then jl. i9. ; goto all buffers released; i6: se w2 x1+a15 ; test buf: if buf=event q(cur) or sh w0 (x2+4) ; receiver(buf)>=0 then jl. i5. ; goto next buf; sl w2 (b8+4) ; sl w2 (b8+6) ; if buffer not message buffer then jl. i5. ; goto next buf; (i.e. some kind of general event); ; an already claimed buffer is found sh w0 (x2+6) ; if sender(buf)<0 then jl. i7. ; begin comment regretted, perform the actual release; sn w3 x2 ; if last buf=buf then rl w3 x2+2 ; last buf:=last(buf); al w0 x3 ; save last buf; jl w3 d106 ; remove and release buf(buf); rl w3 0 ; restore last buf; rl w1 b1 ; restore cur; jl. i8. ; end i7: ; else ws w0 x2+4 ; receiver(buf):=+receiver(buf); rs w0 x2+4 ; i8: ; bz w2 x1+a19 ; al w2 x2+1 ; increase(buffer claim(cur)); hs w2 x1+a19 ; i9: ; buf released: ; at this point there should not be any claimed buffers in the queue... ; examine the next event in the queue ; ; w3=last buf rl w2 x3+0 ; buf:=next(last buf); sn w2 x1+a15 ; if buf=event q(cur) then jl. i13. ; goto empty; rs w2 x1+a30 ; save w2(proc):=buf; ; the buf may either be a message buffer, an interrupt operation ; or a general event sl w2 (b8+4) ; if buf is not message buffer then sl w2 (b8+6) ; jl. i11. ; goto other operation; rl w0 x2+4 ; save w0(cur):= sz w0 -8 ; if 0<=receiver(buf)<8 then am -1 ; 1 else 0; al w0 1 ; i.e.: 0==message, rs w0 x1+a28 ; 1==answer; rl. w3 i0. ; se w3 -1 ; if function=test event then jl. i10. ; if event=message then sn w0 0 ; saved w1:=sender(message) am a142-a139; else rl w3 x2+a139 ; saved w1:=message flag(answer); rs w3 x1+a29 ; i10: ; sn w0 0 ; if message then jl w3 d108 ; claim buffer(cur, buf); jl c99 ; goto interrupt return; i11: ; other operation: rl w3 (b6) ; sl w2 x3 ; if operation <> internal process then sl w2 (b8+4) ; jl. i12. ; goto interrupt operation; jl w3 d5 ; remove(operation); jl. d120. ; goto take general event; i12: ; interrupt operation: jl w3 d5 ; remove(operation); al w3 c99 ; take interrupt operation; jl d127 ; goto interrupt return; ; the queue was empty. i13: rl. w0 i0. ; empty: se w0 -1 ; if function<>test event then jl d107 ; goto remove wait event; rs w0 x1+a28 ; save w0:=-1(:=function); jl c99 ; goto interrupt return; i0: 0 ; function e. ; procedure get event(buf); ; call: return: ; save w0 unchanged ; save w1 unchanged ; save w2 buf unchanged ; save w3 unchanged b. i0 w. e13: rl w2 x1+a30 ; buf:=save w2(cur); jl w3 d19 ; check event(cur, buf); rl w3 x2+4 ; if 0 <=receiver(buf)<8 then sz w3 -8 ; begin comment answer; jl. i0. ; al w3 c99 ; increase claim, remove release buf(cur, buf); jl d109 ; goto interrupt return; i0: ; end; ; message: if not claimed by means of wait event then claim it now: sl w3 0 ; if receiver>=0 then jl w3 d108 ; claim buffer(cur, buf); al w3 c99 ; remove(buf); jl d5 ; goto interrupt return; e. ; procedure regret message; ; call: return: ; save w1 unchanged ; save w1 unchanged ; save w2 buf unchanged ; save w3 unchanged e41: jl w3 d12 ; check message(buf); rl w3 x2+6 ; proc:= sender(buf); sh w3 0 ; ac w3 x3 ; rl w0 x3+a10 ; if kind(proc) = pseudo kind sn w0 64 ; then proc:= main(proc); rl w3 x3+a50 ; bz w0 x2+8 ; sn w3 (b1) ; if proc <> cur or sz w0 1 ; operation(buf) odd then jl c29 ; goto internal 3; al w3 c99 ; regretted message(buf); jl d75 ; goto interrupt return; ; procedure privileged operation b. i5 w. i0: 1<23 ; monitor mode e14: ; rl w1 b1 ; w1:= current rl w0 x1+a24 ; w0:=mode se w0 0 ; if mode<>0 then jl r28 ; return (monitor mode not set) rl w0 x1+a32 ; lo. w0 i0. ; status:=status add monitor mode rs w0 x1+a32 ; al w0 0 ; result=0 jl r28 ; return (monitor mode set) e. ; procedure get clock(time); ; call: return: ; save w0 time high ; save w1 time low ; save w2 unchanged ; save w3 unchanged e18: jl w3 d7 ; update time; dl w3 b13+2 ; ds w3 x1+a29 ; save w0w1(cur):=time; jl c99 ; goto interrupt return; ; procedure set clock(time); ; call: return: ; save w0 time high unchanged ; save w1 time low unchanged ; save w2 unchanged ; save w3 unchanged e19: bz w0 x1+a22 ; mask:=function mask(cur); so w0 1<4 ; if mask(7)=0 then jl c29 ; goto internal 3; jl w3 d7 ; update time; dl w3 b70+2 ; last inspected:= ss w3 b13+2 ; last inspected aa w3 x1+a29 ; -time ds w3 b70+2 ; +newtime; dl w3 x1+a29 ; ss w3 b13+2 ; clockchange:= aa w3 b15+2 ; clockchange+ ds w3 b15+2 ; newtime - time; dl w3 x1+a29 ; c. tested by clock driver; ds w3 b13+2 ; time:=save w0w1(cur); jl c99 ; goto interrupt return; ; call of process functions: ; ; make a primary check on the parameters to ensure that they are inside the calling process. ; notice especially that it is not always possible to check the consistence of the parameters, ; because the circumstances may change before procfunc has time to perform the function. ; special care must be taken, so that the call may be repeated: if the calling process is ; stopped before procfunc reaches the process, the call is deleted, and the ic of the process ; will be decreased to repeat the call as soon as the process is restarted. b. i20 w. e61: ; delete aux entry: jl w3 d111 ; check name (save w2) area; rl w2 x1+a29 ; first param := save w1(cur); al w0 x2+a88-2 ; last param := first + entry size - 2; al. w3 i3. ; check within (first, last); jl d112 ; goto link call; e60: ; create aux entry and area process: jl w3 d111 ; check name (save w2) area; e56: ; connect main catalog: e52: ; insert entry: am i6 ; switch := test entry area; e51: ; prepare bs: al. w0 i3. ; switch := link call; rs. w0 i7. ; save switch; rl w2 x1+a31 ; first param := save w3(cur); al w0 x2+a88-2 ; last param := first param + catentrysize - 2; jl w3 d112 ; check within(first,last); bz w0 x2+28 ; last param := last slice(chaintable) al w2 x2+a88-2 ; + first param + catentrysize - 2; wa w0 4 ; jl w3 d112 ; check within(first,last); jl. (i7.) ; goto (saved switch); i7: 0 ; saved switch e53: ; insert bs: e54: ; delete bs: e55: ; delete entries: jl w3 d111 ; check name (save w2) area; jl. i3. ; goto link call; e39: ; set bs claims: e59: ; lookup bs claims jl w3 d111 ; check name(save w2) area; ; get size of param (save w1(cur)): ; set bs claims (continued): am a110*4+4-12 ; size:=(maxkey+1)*4; e28: ; create internal: e31: ; modify internal: am 12-8 ; size:=12; e23: ; rename entry: am 8-a88 ; size:=8; e38: ; lookup head and tail: i0: ; insert entry (continued): am a88-a88+14 ; size:=catentry size; e20: ; create entry: e21: ; lookup entry: e22: ; change entry: al w0 a88-14-2 ; size:=catentry size-14; notice -2; rl w2 x1+a29 ; first param:=save w1(cur); wa w0 4 ; last param:=first param+size-2; al. w3 i2. ; check within(first, last); jl d112 ; goto check name(save w3); e43: ; lookup-aux-entry: al w0 a88-14-2 ; size:= catentrysize-14; NOTICE -2 rl w2 x1+a29 ; first param:= save w1(cur) wa w0 4 ; last param := first param+size-2; jl w3 d112 ; check within(first,last) e44: al. w3 i2. ; clear-stat-entry: jl d111 ; check name( save w2) area; e46: ; create entry lock process: rl w2 x1+a31 ; first param:=save w3(cur); al w0 x2+8 ; last param:=first param+8; am d112-d111; check within(first, last) ; instead of e45: ; permanent entry in auxcat: jl w3 d111 ; check name(save w2) area; ; check param (save w3(cur)): e24: ; remove entry: e25: ; permanent entry: e26: ; create area process: e27: ; create peripheral process: e32: ; remove process: e34: ; generate name: e36: ; set catalog base: e37: ; set entry interval: e40: ; create pseudo process: i2: jl w3 d17 ; check name area; e57: ; remove main catalog: ; link the calling process to the process function queue. ; procfunc is activated if it is waiting for a call. i3: i6=i0-i3 ; al w0 a101 ; link call: jl w3 d9 ; remove internal(wait proc func); (w2 := cur + a16) ; elem:=process q(cur); jl. w3 d40. ; check mirror process rl w1 (b6) ; proc:=name table(first internal); i.e. proc func; al w1 x1+a15 ; jl w3 d6 ; link(event queue(proc func), elem); al w1 x1-a15 ; bz w0 x1+a13 ; if state(proc func)=wait message then sn w0 a102 ; jl w3 d10 ; link internal(proc func); jl c99 ; goto interrupt return; ; procedure reset device: special meaning when called form proc func. e1: rl w2 (b6) ; proc:=name table(first internal); i.e. proc func; se w2 x1 ; if proc<>cur then jl. i4. ; goto reset device; rl w2 x1+a15 ; proc:=next(event q(cur)); i.e. calling process; jl w3 d5 ; remove (proc) from proc func queue; rs. w2 i7. ; save (proc); al w0 a102 ; sn w3 x1+a15 ; if next(proc)=event q(cur) (i.e. queue empty) then jl w3 d9 ; remove internal(wait mess); rl. w2 i7. ; restore (proc); al w1 x2-a16 ; al w3 c99 ; link internal(proc); jl d10 ; ; reset device ; call: return: ; save w0 resettype result (=0,4) ; save w1 device unchanged ; save w2 unchanged ; save w3 unchanged i4: rl w2 x1+a29 ; device := save w1(cur); lx w2 g49 ; exchange bit 0; wa w2 b65 ; sl w2 (b67) ; if device address outside sl w2 (b68) ; controller table then jl r4 ; goto result 4; rl w2 x2+a311 ; status addres := status(contr descr); al w2 x2-a230 ; jl w1 d130 ; clear device(proc); rl w1 b1 ; w1 := cur; al w0 0 ; result:=0; rx w0 x1+a28 ; if save w0(cur) = 0 then sn w0 0 ; result := power restart am 6-3 ; else al w0 3 ; result := timeout; al w2 x2+a241 ; w2 := interrupt operation(proc); al w3 c99 ; deliver interrupt; jl d121 ; goto interrupt return; e29: rl w2 (b6) ; start internal process se w2 x1 ; if cur <> first internal (i.e. proc func) then jl. i2. ; goto check name(save w3); ; proc func has issued a call of start process. ; all processes to be started are linked together, via wait-address, and the start of the ; chain is given in save w3. i5: rl w1 x2+a31 ; rep: proc := save w3(proc func); sn w1 0 ; if end chain then jl c99 ; goto interrupt return; rl w0 x1+a40 ; save w3(proc func) := wait address.proc; rs w0 x2+a31 ; rl w2 x1+a34 ; father := parent.proc; bz w3 x2+a12 ; al w3 x3+1 ; increase(stopcount(father)); hs w3 x2+a12 ; rl w0 x1+a192 ; w0:=type sz w0 2.1 ; if mirror proc then jl. i15. ; skip start internal al w0 a101 ; hs w0 x1+a13 ; state.proc := waiting for process function; (prepare for not starting) rl w0 x1+a33 ; so w0 1 ; if save ic(proc) even then jl w3 d10 ; link internal(proc); i15: rl w2 (b6) ; jl. i5. ; goto rep; e30: ; stop internal process: bz w0 x1+a19 ; if buf claim(cur)=0 then sn w0 0 ; goto claim buffer(cur, irrellevant); jl d108 ; (there are no buffers, so save w2:=0 and exit); ; you may not actually claim the buffer for returning the answer yet, because the calling ; process may get stopped itself, before procfunc reaches it. when the call is repeated, the ; buffer might be claimed more than once. jl. i2. ; goto check name area; b.j10 w. ; procedure copy. ; call return ; save w0 x z ; save w1 x z ; save w2 x z ; save w3 x z e35: ; copy message: jl w3 d12 ; check message buf; rl w3 x1+a29 ; first:=saved w1; rl w0 x1+a31 ; last:=saved w3; sl w3 (x1+a17) ; check: sl w0 (x1+a18) ; if first<first addr(cur) jl c29 ; or last>=top addr(cur) ws w0 6 ; or first>last then sh w0 -1 ; goto internal 3 jl c29 ; ; ac w3 (x2+4) ; rec:= -(-receiver(mess)) so w3 2.1 ; if rec odd sh w3 0 ; or rec<=0 then jl c29 ; goto internal 3 rl w0 x3+a10 ; sn w0 64 ; if rec is a pseudo process then rl w3 x3+a50 ; rec:=main(rec); rl w0 x3+a10 ; sz w0 -1-64 ; if rec neither internal nor pseudo process then rl w3 x3+a250 ; rec:=driver proc(rec); se w3 x1 ; if rec<>cur then jl c29 ; goto internal3; bz w3 x2+8 ; so w3 2.1 ; if operation(mes) even then jl r3 ; goto result3; rl w3 x2+6 ; w3:=sender rl w0 x3+a192 ; sl w0 3 ; if sender is a mirror process then jl. i14. ; goto move to master ; further checking is postponed until procfunc. jl. i3. ; goto link call; ; w1 = cur ; w2 = buf ; w3 = sender i14: ; move buf to master rl w3 x3+a190 ; w3:=master rl w0 x3+a19 ; bs. w0 1 ; rs w0 x3+a19 ; decrease bufferclaim.master ds. w3 j1. ; save buf, master jl w3 d5 ; remove buf bz w3 x1+a19 ; al w3 x3+1 ; increase bufferclaim.cur hs w3 x1+a19 ; al w0 a101 ; jl w3 d9 ; remove calling proc rl. w1 j1. ; w1:=master al w1 x1+a15 ; jl w3 d6 ; link buf al w1 x1-a15 ; am (b1) ; rl w0 a29 ; w0:=first addr rl w3 b109 ; w3:=computer number rl. w2 j0. ; w2:=buf ds w3 x2+a153+2 ; al w0 -1 ; set buffer state to rs w0 x2+a158 ; copy buffer rl w0 x1+a13 ; w0:=state sn w0 a104 ; if waiting for event then jl w3 d10 ; link proc and jl c99 ; and return ; procedure general copy ; copies an area in the calling process to or from an ; area described in a message buffer. ; the first word to be copied is defined by its position ; relative to the first address in the messagebuffer. ; call return ; save w0 result (=0,2,3) ; save w1 params halfwords moved ; save w2 buf ; save w3 ; params+0 function (addr pair<1 + mode) ; +2 first ; +4 last ; +6 relative(mess data buffer) j10=512 ; max number of bytes immidiately transferred e42: ; general copy: jl w3 d12 ; check message buf rl w3 x1+a29 ; param:= parameter address(=cur.w1) al w0 x3+6 ; if param<first addr(cur) or sl w3 (x1+a17) ; param+6>=top addr(cur) then sl w0 (x1+a18) ; jl c29 ; goto internal 3 wa w3 x1+a182 ; w3:= abs addr of param rl w0 x3+0 ; rs. w0 j4. ; function:=function(param); ls w0 -1 ; if addr pair>12 then sl w0 14 ; goto internal 3 jl c29 ; rs. w0 j0. ; pair:=function>1; ; rl w0 x3+6 ; rel:= param.relative sh w0 -1 ; if rel<0 then jl c29 ; goto internal 3 rs. w0 j1. ; relative:=rel; ; dl w0 x3+4 ; first:=param.first addr ; last:=param.last addr sl w3 (x1+a17) ; check: sl w0 (x1+a18) ; if first<first addr(cur) or jl c29 ; last>=top addr(cur) or ws w0 6 ; first>last then sh w0 -1 ; goto internal 3 jl c29 ; wa w0 x1+a182 ; abs first(cur):=first(cur)+base(cur); ds. w0 j3. ; size(cur)-2:=last(cur)-first(cur); ; rl w2 x1+a30 ; mess:=saved w2; ac w3 (x2+4) ; rec:= -(-receiver(mess)); sh w3 0 ;*****aht. driver proc ac w3 x3 ;***** so w3 2.1 ; if rec odd sh w3 0 ; or rec<=0 then jl c29 ; goto internal 3; rl w0 x3+a10 ; sn w0 64 ; if rec is a pseudo process then rl w3 x3+a50 ; rec:=main(rec); rl w0 x3+a10 ; sz w0 -1-64 ; if rec neither internal nor pseudo process then rl w3 x3+a250 ; rec:=driver proc(rec); se w3 x1 ; if rec<>cur then jl c29 ; goto internal3; rl w3 x2+a142 ; w3 := sender(mess); bz w0 x2+a150 ; sz w0 2.1 ; if operation(mess) even sh w3 0 ; or sender <= 0 (i.e. regretted) then jl r3 ; goto result 3; rl w0 x3+a10 ; if kind(sender) = pseudo kind sn w0 64 ; then sender := main(sender) rl w3 x3+a50 ; bz w0 x3+a13 ; if state(sender) = stopped then sz w0 a105 ; jl r2 ; goto result 2; am. (j0.) ; first(mess):=first(mess+pair)+relative; dl w1 x2+8+2 ; last(mess):=last(mess+pair+2); wa. w0 j1. ; sl w0 (x3+a17) ; if first(mess)<first(sender) sl w1 (x3+a18) ; or last(mess)>last(sender) then jl. i13. ; goto result3; ws w1 0 ; size-2:=last(mess)-first(mess); sh w1 -1 ; if size-2 < 0 jl c29 ; then goto internal 3; wa w0 x3+a182 ; abs first(mess):=first(mess)+base(sender); sl. w1 (j3.) ; if size>size(cur) then rl. w1 j3. ; size:=size(cur); al w3 x1+2 ; rx w3 0 ; rl. w2 j2. ; ; w0: size, w2: abs first(cur), w3: abs first(mess) rl. w1 j4. ; so w1 2.1 ; if mode=1 then from:=cur, to:=mess rx w2 6 ; else from:=mess, to:=cur; ; rl w1 b1 ; sl w0 j10+1 ; if size>max number trf immidiately then jl. i3. ; goto call link; rs w0 x1+a29 ; saved w1:=size; ; move. ; w0: size, w1: , w2: from-addr, w3: to-addr i8: ac w1 (0) ; remaining := - bytes; so w1 1<1 ; if even number of words to move then jl. i10. ; goto move fast; rl w0 x2+0 ; rs w0 x3+0 ; al w3 x3+2 ; increase(to-address); al w2 x2+2 ; increase(from-address); al w1 x1+2 ; decrease(remaining); (remember: negative) i10: ; move fast: rs. w1 j5. ; save(remaining); sl w1 i12 ; if remaining does no exceed size of move-table jl. x1+i11. ; then switch out through table; ; (otherwise move a whole portion) i9: ; start of move-table: dl w1 x2+30 ; ds w1 x3+30 ; dl w1 x2+26 ; ds w1 x3+26 ; dl w1 x2+22 ; ds w1 x3+22 ; dl w1 x2+18 ; ds w1 x3+18 ; dl w1 x2+14 ; ds w1 x3+14 ; dl w1 x2+10 ; ds w1 x3+10 ; dl w1 x2+6 ; ds w1 x3+6 ; dl w1 x2+2 ; ds w1 x3+2 ; i11: ; top of move-table: i12=i9-i11 ; size of move-table (notice: negative) al w3 x3-i12 ; increase(to-address); al w2 x2-i12 ; increase(from-address); rl. w1 j5. ; restore(remaining); al w1 x1-i12 ; decrease(remaining); (remember: negative) sh w1 -1 ; if not all moved yet then jl. i10. ; goto move fast; ; now return to result0. rl w1 b1 ; jl r0 ; exit: goto result0; i13: rl w1 b1 ; exit3: jl r3 ; goto result3; j0: 0 ; pair j1: 0 ; relative j2: 0 ; abs first(cur) j3: 0 ; size(cur)-2 j4: 0 ; function j5: 0 ; remaining bytes (multiplum of 4 bytes) e. e. ; end of proc func block ; set cpu mask ; saved w0 new cpu mask result=if new cpu mask=0 then old cpu mask else ; new cpu mask ; saved w1 ; saved w2 ; saved w3 b. w. e15: rl w2 x1+a28 ; w2:=new cpu mask se w2 0 ; if new cpu mask<>0 then hs w2 x1+a187 ; set new cpu mask bz w2 x1+a187 ; load result rs w2 x1+a28 ; jl c99 ; return e. ; ; procedure select or remove masterproc ; saved w0=0 for remove ; 2 for select ; 4 for select hcdriver process addr ; saved w3= proc addr (in the 3 last cases) b. i5 w. e16: rl w2 x1+a28 ; w2:=saved w0 sl w2 3 ; if set proc addr then jl. i0. ; goto i0 rs w2 x1+a192 ; select or remove master se w2 0 ; if select then al w2 x1 ; set current master rs w2 b105 ; else remove current master jl c99 ; return interrupt i0: rs w1 b106 ; set proc addr jl c99 ; return interrupt e. ; ; procedure move buff(sender,receiver); ; saved w0 return: =0 buffer claim execeeded (receiver) ; =1 buffer moved ; saved w1 ; saved w2 buf ; saved w3 receiver ; b. h5,i5 w. e17: jl w3 d101 ; check and search name jl r3 ; if process do not exist then result 3 rs. w3 h0. ; save receiver jl w3 d12 ; check buf rl. w3 (h0.) ; w3:=receiver bz w0 x3+a19 ; sh w0 0 ; jl. i0. ; jl w3 d5 ; remove buf al w0 1 ; rs w0 x1+a28 ; set result ba w0 x1+a19 ; rl w3 x2+a141 ; w3:=receiver sh w3 0 ; if buffer is claimed then hs w0 x1+a19 ; increase buffer claim(sender) rl. w1 (h0.) ; w1:=reciever al w1 x1+a15 ; jl w3 d6 ; link buf al w1 x1-a15 ; bz w0 x1+a13 ; w0:=state rl w3 b1 ; w3:=sender sn w0 a102 ; if waiting for message jl. i1. ; goto message se w0 a104 ; if not waiting for event then jl c99 ; return from interrupt al w3 0 ; else set result i1: rs w3 x1+a28 ; =0 (i.e. message) or proc addr rs w2 x1+a30 ; saved w2:=buf al w3 c99 ; jl d10 ; and link proc i0: al w0 0 ; rs w0 x3+a28 ; set result jl c99 ; and return h0: 0 e. ; set priority. ; saved w0 result(=0,3) ; saved w1 priority ; saved w2 ; saved w3 name addr(child) b.i10,j10 w. e47: jl w3 d17 ; check name(saved w3); rl w2 x1+a31 ; name addr:=saved w3; jl w3 d11 ; search name(name, entry); jl r3 ; not found: goto result3; rl w3 x3 ; found: rs. w3 i0. ; child:=proc(entry); se w1 (x3+a34) ; if parent(child)<>cur then jl r3 ; goto result3; rl w0 x3+a10 ; se w0 0 ; if child not internal proc then jl r3 ; goto result3; rl w0 x1+a29 ; prio:=saved w1; sh w0 -1 ; if prio<0 then jl c29 ; goto internal3; ws w0 x3+a301 ; increment:=prio-priority(proc); rs. w0 i1. ; ; search descendents of process and the process itself, and increment their ; priority values. if they are in timeslice queue, then reinsert them to ; assure proper displacement in priority-queue. rl w3 b6 ; j0: rl w2 x3 ; j1: sn. w2 (i0.) ; jl. j3. ; rl w2 x2+a34 ; se w2 0 ; jl. j1. ; j2: al w3 x3+2 ; se w3 (b7) ; jl. j0. ; jl r0 ; exit: goto result0; j3: rl w2 x3 ; rl w0 x2+a301 ; wa. w0 i1. ; priority(proc):=priority(proc)+increment; rs w0 x2+a301 ; ;* rl w0 x2+a16 ; ;* sn w0 x2+a16 ; if proc in time-slice-queue then ;* jl. j2. ; ;* rs. w3 i2. ; save w3; ;* al w2 x2+a16 ; ;* jl w3 d5 ; ;* jl w3 d10 ; ;* rl. w3 i2. ; jl. j2. ; i0: 0 ; proc(child) i1: 0 ; increment i2: 0 ; saved w3 e. ; procedure relocate(name,start address,result) ; call: return: ; save w0 result (= 3,6 ) ; save w1 start address ; save w2 ; save w3 name address b.i10,j10 w. e48: jl w3 d17 ; check name(save w3) rl w2 x1+a31 ; name addr:= save w3 jl w3 d11 ; search name(name,entry) jl r3 ; not found: goto result 3 rl w3 x3 ; found : rs. w3 i0. ; child:= proc(name table entry) rl w0 x1+a182 ; rs. w0 i2. ; save address base of calling process se w1 (x3+a34) ; if parent(child) <> cur jl r3 ; then goto result 3 rl w0 x3+a10 ; se w0 0 ; if kind(child) <> internal jl r3 ; then goto result 3 bz w0 x3+a13 ; if state(child) <> waiting f. start by parent se w0 a99 ; then goto result 3 jl r3 ; rl w0 x1+a29 ; rl w2 x3+a18 ; if child is relocated outside relevant part ws w2 x3+a17 ; of core then goto internal 3 wa w2 0 ; sh w2 0 ; if overflow jl c29 ; then goto result 3 al w2 x2-1 ; sl w0 (x1+a17) ; sl w2 (x1+a18) ; jl c29 ; rl w0 x1+a29 ; displ:= new start address - old start address ws w0 x3+a17 ; rs. w0 i1. ; rl w3 b6 ; search: j0: rl w2 x3 ; proc:= next internal in name table j1: sn. w2 (i0.) ; if proc = child then goto update else jl. j3. ; begin rl w2 x2+a34 ; while parent(proc) <> 0 do se w2 0 ; if parent(proc)=child then goto update jl. j1. ; else proc:= parent(proc); j2: ; end; al w3 x3+2 ; next: se w3 (b7) ; if more internals in name table jl. j0. ; then goto search rl w1 b1 ; jl r0 ; exit: goto result 0 j3: rl w2 x3 ; update: proc:= proc(name table entry) rl. w0 i1. ; current base(proc):= current base(parent)+displ; wa. w0 i2. ; rs w0 x2+a182 ; dl w1 x2+a174 ; current lower write limit(proc):= wa. w0 i1. ; initial lower write limit(proc)+displ; wa. w1 i1. ; current upper write limit(proc):= ds w1 x2+a184 ; initial upper write limit(proc)+displ; jl. j2. ; goto next; i0: 0 ; save child i1: 0 ; save displacement i2: 0 ; save address base of parent e. ; procedure change address base(name,displacement,result); ; call: return: ; save w0: result (= 3,6 ) ; save w1: displacement ; save w2: ; save w3: name address b.i10,j10 w. e49: jl w3 d17 ; check name(save w3) rl w2 x1+a31 ; name addr:= save w3; jl w3 d11 ; search name(name,entry); jl r3 ; not found: goto result 3 rl w3 x3 ; found: proc:= proc(name table entry) rl w0 x1+a29 ; rs. w0 i0. ; save displacement se w1 (x3+a34) ; if parent(proc) <> cur jl r3 ; then goto result 3 rl w0 x3+a10 ; se w0 0 ; if kind(proc) <> internal jl r3 ; then goto result 3 bz w0 x3+a13 ; se w0 a99 ; if state(proc) <> waiting f. start by parent jl r3 ; then goto result 3 al w1 x3 ; rl w3 b6 ; check if actual process has any children. j1: rl w2 x3 ; in this case goto result 3 sn w1 (x2+a34) ; jl r3 ; al w3 x3+2 ; se w3 (b7) ; jl. j1. ; dl w0 x1+a18 ; first addr(proc):= first addr(proc)-displ ws. w0 i0. ; last addr(proc):= last addr(proc)-displ ws. w3 i0. ; ds w0 x1+a18 ; dl w0 x1+a170 ; if exception addr(proc) <> 0 then sn w3 0 ; exception addr(proc):=exception addr(proc)-displ; jl. j2. ; ws. w3 i0. ; j2: sn w0 0 ; if escape addr(proc) <> 0 then jl. j3. ; escape addr(proc):=escape addr(proc); ws. w0 i0. ; j3: ds w0 x1+a170 ; rl w0 x1+a182 ; address base(proc):= address base(proc)+displacement; wa. w0 i0. ; rs w0 x1+a182 ; rl w0 x1+a33 ; ic(proc):= ic(proc)-displacement; ws. w0 i0. ; rs w0 x1+a33 ; rl w1 b1 ; jl r0 ; exit: goto result 0 i0: 0 ; save displacement e. ; procedure set process extension(first ext,last ext) ; ; save w0: result (return) ; save w1: first process ext (call) ; save w2: second process ext (call) ; save w3: - e58: c.a400-1 rl w2 x1+a29 ; first:= save w1(cur) rl w0 x1+a30 ; last:= save w2(cur) sl w2 (0) ; if last < first then rx w2 0 ; exchange(first,last) jl w3 d112 ; check within(first,last) rl w3 x1+a30 ; w3:= sec. proc. ext. rl w2 x1+a29 ; w2:= first proc. ext. ds w3 x1+a306 ; insert log. addr in process description wa w2 x1+a182 ; wa w3 x1+a182 ; ds w3 b28 ; insert phys. addr in monitor table jl r0 ; goto result 0; z. c.a400 jl c29 ; z. ; procedure start i/o; ; call: return: ; save w0 function select result (=0,1,2,3) ; save w1 cp start (logic addr) unchanged ; save w2 0 or buf unchanged ; save w3 device address unchanged ; the channelprogram is started using the device address in proc desc+a235. ; at start time the working register holds the io-device number extracted ; from the save w3 (only of importance in connection with rc8601). ; result = 0: channel program etc ok, the interrupt operation will arive ; (except after 'reset device') ; 1: message regretted, i.e. no transfer started ; 2: sender stopped , i.e. no transfer started ; 3: sender address error, i.e.no transfer started ; data command specifies buffers outside senders limits ; (should give the reaction: message unintelligible) ; the procedure returns always immediatly to the calling process ; (i.e. the driver), to the instruction just following the call. ; the driver may however specify (via function select) that ; execution should be resumed via 'wait first event' (unless ; result <> 0, in which case the normal resumption is made). ; in case of parameter errors the driver process is break'ed, as usual. ; parameter errors: ; illegal function select ; save w3 is not a device address ; device descriptor not governed by current process ; previous transfer not awaited (if not 'reset...') ; save w2 not message buffer ; state of message buffer not legal for transfer (***not implemented***) ; channel program too long for device description (or outside driver process) ; wait-command in channel program ; illegal address code ; address error (i.e. buffers outside limits (except sender limits) ) ; illegal data- or skip-chain ; ; function select: ; function a. 1 = 0 : return to just after call ; = 1 : exit via the std return address ; ; function>1 a. 1 = 0 : no reset ; = 1 : reset device before start of operation ; ; function>2 = 0 : no operation ; = 1 : start channelprogram ; = 2 : start std wait program ; = 3 : start std control program ; address code: ; code = 0: data area in senders process (i.e. sender(buf)) ; 2: - - - drivers process ; 4: - - - device descr ; 6: - - - message buffer ; 8: - - - core (no check) ; ; first logic address depends on address code: ; code = 0: logic address in senders process ; 2: logic address in drivers process ; 4: relative address in device descr (relative to a10) ; 6: relative address in message buffer (relative to a140) ; 8: absolute address, with no limit check ; timeout: (unit: 0.1 msec) ; if a channel program is not terminated with an interrupt within ; the specified period, a software timeout will be generated, which ; will deliver the interrupt operation to the driver. ; the device will be reset, exept after a wait-program. ; notice: if timeout = 0, no software timeout will be provided. ; channel program: ; the channel program must be in the drivers area, and will be ; copied to the device description. ; ; the channel program may contain commands with the following format: ; comm + a321: irrell < 12 + 4095 ; comm + a322: irrell ; comm + a323: irrell ; in this case the command will be interpreted as a dummy-command, ; i.e. will not be copied into the device description ; ; if the program contains the commands 0,1,2,3 (i.e. sense, control, ; read, write with data buffer) without the skip-modification, the ; commands must have the following format: ; comm + a321: address code < 12 + command < 8 + modifs ; comm + a322: first logic address ; comm + a323: char count ; char count must be >= 0 (unless in sense commands, where is must be >= 12) ; (furthermore: if the command is a sense, the 'top chp addr' in the ; sense-area will be cleared) ; ; the stop-command must have the following format: ; comm + a321: 0 < 12 + 2.1111 < 8 + 0 ; comm + a322: 0 ; comm + a323: timeout ; (this may prepare for introducing 'jump'-commands with the same ; format as the 'stop', except for: ; comm + a322: continue-address ) b. f20, h40, i60, j50 w. ; function select table: h0: f0 ; 0 : no operation f1 ; 1 : start channelprogram f2 ; 2 : start std wait program f3 ; 3 : start std control program j0=-h0.<1 ; top value of function select ; address code table: h1: f10 ;0: sender area f11 ;2: driver area f12 ;4: device descr f13 ;6: message buffer f14 ;8: abs core address (no limit check) j1=-h1. ; top address code h5: 0 ; device descr address h10: 0 ; sender area used: 0=false, else true h11: 0 ; =h10+2 ; driver area used: 0=false, else true h15: 0 ; first of sender area (logic addr) h16: 0 ; =h15+2 ; top - - - ( - - ) h17: 0 ; sender process description address h20: 0 ; abs first of channel program area in device descr h21: 0 ; =h20+2 ; abs top - - - - - - - h22: 0 ; last of current chp prog entry in device descr h23: 0 ; old command h25: 1<23 ; change bit 0 h26: -1<1 ; make addresses even h27: 3 ; number of characters per word h30: 2.1100 < 8 + 1 < 6; mask: databuffer-command without skip h36: j36 ; mask: sign extended command field h40: j32 ; std wait channel program ; format of channel program, in driver area: ; (used relative to w3 = last of entry) j11 = -a320 + 2 ; (base of command) j12 = j11 + a321 ; command field j13 = j11 + a322 ; param 1 (=first logic address) j14 = j11 + a323 ; param 2 (=char count, or timeout) ; format of channel program, in device description: ; (matches the format prescribed by the controller) ; (used relative to w2 = last of entry) j20 = 6 ; (size of entry) j21 = -j20 + 2 ; (base of command) j22 = j21 + 0 ; command field j23 = j21 + 2 ; param 1 j24 = j21 + 4 ; param 2 j30 = 2.0011 < 8 ; mask: sense command j31 = 12 ; minimum char count in sense command j34 = -1 < 8 + 1 < 6 ; mask: sense command without skip (sign extended) j32 = 2.0100 < 8 ; wait command (sign extended) j33 = -1 < 8 ; stop command (sign extended) j37 = -1 < 0 ; dummy command (sign extended) j35 = 1 < 7 + 1 < 6 ; data- + skip-chain j36 = -1 < 8 ; sign extended command field j40 = -1 ; status bit: status transfer error e50: ; start i/o: ; this first part of the code checks some of the most important ; parameters. ; it should be possible to skip this checking, in case the driver ; contains no errors ??? rl w3 x1+a31 ; devaddr := save w3(cur); sz w3 2.111 ; if devaddr not multiplum of 8 (bytes) then jl c29 ; goto internal 3; i.e. not legal at all; lx. w3 h25. ; change bit 0 in devaddr; wa w3 b65 ; controller descr := controller table(devaddr); sl w3 (b67) ; if controller descr outside sl w3 (b68) ; controller table then jl c29 ; goto internal 3; rl w3 x3+a311 ; status addr := std status(controller descr); al w3 x3-a230 ; device descr addr := proc(status addr); rs. w3 h5. ; se w1 (x3+a250) ; if cur <> driverproc(device) then jl c29 ; goto internal 3; rl w2 x1+a30 ; se w2 0 ; if save w2(cur) <> 0 then jl w3 d12 ; check message buf; rl w3 x1+a28 ; function select := save w0(cur); sl w3 0 ; if function select outside limits then sl w3 j0 ; jl c29 ; goto internal 3; ; at this point the following has been checked: ; save w3 is a legal device address, governed by the current process ; save w2 is zero or a legal message buffer address ; save w0 is a legal function select ; w1 = cur, w3 = function select so w3 1<1 ; if function select.reset is on then jl. i6. ; device descr := saved device descr; rl. w2 h5. ; clear device(device descr); jl w1 d129 ; rl w1 b1 ; w1 := cur; rl w3 x1+a28 ; function select:=save(w0); i6: ls w3 -1 ; function select := function select > 1; jl. (x3+h0.) ; switch out through function select table; ; general return actions: ; a result is delivered to the driver, indicating the result of the call. ; if result = ok and function select is odd, return to the driver is made ; via 'wait first event', else a normal return is made i3: am 3-2 ; result 3: address error: i2: am 2-1 ; result 2: sender stopped: i1: am 1-0 ; result 1: message regretted: i0: al w0 0 ; result 0: ok: rl w1 b1 ; w1 := cur; rl w2 x1+a28 ; function select := save w0(cur); rs w0 x1+a28 ; save w0(cur) := result; sn w0 0 ; if result <> 0 or so w2 2.1 ; function select even then jl c99 ; goto interrupt return; rl w2 x1+a302 ; get save area address; rl w0 x2+a304 ; save ic(cur) := wait-first-event entry; rs w0 x1+a33 ; jl c99 ; goto interrupt return; ; function select actions: ; function select = no operation. ; w1 = cur f0=i0 ; goto result 0; ; function select = start std control program ; w1 = cur f3: am. h40. ; first := std wait program; ; continue with std wait program; ; function select = start std wait program ; w1 = cur f2: al w0 0 ; first := 0 (i.e. no start) rs. w0 h20. ; abs first of channel program := first; rl w0 x1+a29 ; timeout := save w1(cur); al w3 0 ; transfer code := 0; ; (i.e. 'wait' not considered a transfer...) jl. i50. ; goto init transfer code; ; function select = start channel program: ; w1 = cur f1: ld w3 -100 ; ds. w3 h11. ; sender area used := driver area used := false; rs. w3 h23. ; old command := 0; (i.e. at least not data-chain) ds. w3 h16. ; first,top sender area := 0; i.e. presume empty rl w3 x1+a30 ; buf := save w2(cur); sn w3 0 ; if buf = 0 then jl. i10. ; goto buffer consistency checked; ; when a message buffer is specified, it is generally concerning a ; data-transfer to/from the sender area ; ; therefore the message buffer is checked once and for all, and the proper ; buffer limits are found ; ; if any errors are found, the buffer limits will be set to en empty ; buffer, thus any attempt to specify addresses within the sender area ; will provoke a buffer limit violation ; w1 = cur, w3 = buf dl w2 x3+a142 ; w2 := sender(buf); (w1 := receiver(buf) ) sh w2 0 ; if sender <= 0 then jl. i1. ; goto message regretted; bz w0 x3+a145 ; if operation(buf) is even then so w0 2.1 ; jl. i10. ; goto message buffer checked; ; check that the buffer is a message sent to the driver: sh w1 -1 ; if message received then ac w1 x1 ; receiver := - receiver; sh w1 7 ; if receiver <= 7 then jl. i10. ; goto message buffer checked; i.e. an answer rl w0 x1+a10 ; w0 := kind(receiver); sn w0 64 ; if kind = pseudo process then rl w1 x1+a50 ; receiver := mainproc (receiver); sz w0 -1-64 ; if receiver is neither internal process nor rl w1 x1+a250 ; pseudo process then se w1 (b1) ; receiver := driverproc (receiver); jl. i10. ; if receiver <> cur then goto message checked; ; now buf has shown out to be a message, sent to this driver ; w2 = sender(buf), w3 = buf rl w0 x2+a10 ; w0 := kind(sender); sn w0 64 ; if kind = pseudo process then rl w2 x2+a50 ; sender := mainproc (sender); sz w0 -1-64 ; if sender neither internal nor pseudo process then rl w2 x2+a250 ; sender := driverproc (sender); ; w2 = internal process, which sent the message buffer ; w3 = message buffer dl w1 x3+a152 ; w0w1 := first,last address(buf); (logic addresses) la. w0 h26. ; make the limits even; la. w1 h26. ; sl w0 x1+1 ; if first address > last address then jl. i10. ; goto message checked; sl w0 (x2+a17) ; if first,last address area outside sl w1 (x2+a18) ; the senders area then jl. i10. ; goto message checked; al w1 x1+2 ; first of sender area := first address; ds. w1 h16. ; top - - - := last address + 2; rs. w2 h17. ; save sender process description address; ; message buffer consistency checked: ; prepare moving of the channel program, i.e. get first,last of ; channel program area in device descr, and transform them to absolute ; addresses. ; check that the channel-program-source starts within the driver process. ; ; (all regs irrell) i10: ; message checked: rl. w1 h5. ; device descr := saved descr; dl w3 x1+a227 ; abs first of chp area in device descr := wa w2 2 ; device descr + relative first of chp area; wa w3 2 ; abs top of chp area in device descr := ds. w3 h21. ; device descr + relative top of chp area; rl w1 b1 ; w1 := cur; rl w3 x1+a29 ; first of channel program := save w1 (cur); sl w3 (x1+a17) ; if first of channel program sl w3 (x1+a18) ; is outside current process then jl c29 ; goto internal 3; wa w3 x1+a182 ; w3 := first of channel program al w3 x3-2 ; + base (cur) - 2; i.e. last of entry al w2 x2-2 ; w2 := last of current entry in device descr; ; next command: ; w1 = cur ; w2 = last of current entry in device descr (abs addr) ; w3 = last of current entry in driver process (abs addr) i15: al w2 x2+j20 ; next command: increase(device pointer); sl. w2 (h21.) ; if outside top of device descr area then jl c29 ; goto internal 3; i.e. channel program too long rs. w2 h22. ; save (last of current device entry); i16: rl w1 b1 ; skip command: al w3 x3+a320 ; increase(driver pointer); sl w3 0 ; if overflow or sl w3 (x1+a18) ; outside top of driver process then jl c29 ; goto internal 3; ; move the command unchanged from driver area to device description: dl w1 x3+j14 ; move (param 1, param 2); ds w1 x2+j24 ; rl w0 x3+j12 ; move (command); rs w0 x2+j22 ; sz. w0 (h30.) ; if command is not databuffer without skip then jl. i30. ; goto test chain; ; the command is sense, control, read or write with databuffer. ; param 1 (i.e. the first logic addr) must be transformed to an absolute ; address, using the address code. ; check that the char count is not too small (command dependant). ; ; w0 = command word ; w1 = param 2 (=char count) sz w0 j30 ; minimum := if not sense command then am -j31+1-1; 0 else sense-char-count; sh w1 j31-1 ; if char count < minimum then jl c29 ; goto internal 3; ; compute size (and thereby last) of data buffer area al w0 0 ; words := chars // number of chars per word; wd. w1 h27. ; ls w1 1 ; last byte used := words * 2 sn w0 0 ; - if chars mod (chars per word) = 0 then al w1 x1-2 ; 2 else 0; rl w0 x3+j13 ; w0 := first logic address; wa w1 0 ; w1 := last logic address; (=last byte+first logic) sl w0 x1+3 ; if first address > last address then jl c29 ; goto internal 3; i.e. buffer wraps around top of core ; w0 = first logic address ; w1 = last logic address ; w3 = abs last of current chp entry bz w2 x3+j12 ; w2 := address code(current command); sh w2 j1-1 ; if address code inside limits then jl. (x2+h1.) ; switch out through address code table; jl c29 ; else goto internal 3; i.e. illegal address code ; address transformation actions: ; address code = sender area: ; w0 = first logic address ; w1 = last logic address f10: sl. w0 (h15.) ; if buffer area outside sender area then sl. w1 (h16.) ; jl. i3. ; goto address error; rl. w2 h17. ; sender descr := saved sender process descr; rs. w2 h10. ; sender area used := true; wa w0 x2+a182 ; transform first address to absolute address; jl. i20. ; goto first address transformed; ; address code = driver area ; w0 = first logic address ; w1 = last logic address f11: rl w2 b1 ; driver := cur; sl w0 (x2+a17) ; if buffer area outside driver process then sl w1 (x2+a18) ; jl c29 ; goto internal 3; rs. w2 h11. ; sender area used := true; wa w0 x2+a182 ; transform first address to absolute address; jl. i20. ; goto first address transformed; ; address code = device description ; w0 = first relative address ; w1 = last relative address f12: rl. w2 h5. ; sl w0 (x2+a220) ; if buffer area outside sl w1 (x2+a221) ; private area (device descr) then jl c29 ; goto internal 3; wa w0 4 ; transform first relative address to absolute addr; jl. i20. ; goto first address transformed; ; address code = message buffer ; w0 = first relative address ; w1 = last relative address f13: sl w0 a145 ; if buffer area outside sl w1 a146 ; message part of message buffer then jl c29 ; goto internal 3; rl w2 b1 ; buf := save w2 (cur); wa w0 x2+a30 ; transform first relative address to absolute addr; sh w0 x1 ; if buf <> 0 then jl. i20. ; goto first address transformed jl c29 ; else goto internal 3; ; address code = abs core address ; w0 = absolute first address ; w1 = absolute last address f14: ; continue with first address transformed ; the legality of the buffer addresses has been checked, ; and the first address is now an absolute core address ; w0 = abs first address ; w3 = last of current chp entry i20: ; first address transformed: rl. w2 h22. ; restore (device pointer); rs w0 x2+j23 ; move abs first address to channel program; ; now a complete command has been moved. ; check that the command does not change during data- or skip-chain ; w2 = last of device descr chp entry ; w3 = last of current chp entry i30: ; test chain: bl w0 x2+j22+1 ; command := command byte(current entry); sn w0 j37 ; if command = dummy command then jl. i16. ; goto skip command; rl. w1 h23. ; prev command := old command; rs. w0 h23. ; old command := command; sz w1 j35 ; if previous command contained any chains then jl. i31. ; begin jl. i32. ; test that the two commands are equal: i31: lx w1 0 ; if prev command <> command then sz w1 j36 ; goto internal 3; jl c29 ; end; i32: ; ; to facilitate the drivers interpretation from the sense-commands, ; the first word of the sense area is cleared. ; thereby the driver can detect in a simple way, if that sense ; has been executed. ; ; w0 = command (sign extended) ; w2 = last of device descr chp entry ; w3 = last of current chp entry sz w0 j34 ; if command = sense without skip then jl. i33. ; begin al w1 0 ; top chp addr (sense area) := 0; am (x2+j23) ; rs w1 +a315 ; i33: ; end; ; a driver-supplied channel program may not contain a 'wait'-command, ; because this migth delay the terminating interrupt infinitly, ; thereby preventing the processes from being stopped. ; ; w0 = command (sign extended) ; w2 = last of device descr chp entry ; w3 = last of current chp entry la. w0 h36. ; w0 := command bits of command; sn w0 j32 ; if command = 'wait' then jl c29 ; goto internal 3; ; if the channel program has not encountered the 'stop'-command ; then move and translate the next command ; ; w0 = command (sign extended) ; w2 = last of device descr chp entry ; w3 = last of current chp entry rl w1 b1 ; w1 := cur; se w0 j33 ; if command <> 'stop' then jl. i15. ; goto next command; ; (maybe it should be tested, that param 1 = 0, i.e. not a 'jump' ?) ; rl w0 x2+j23 ; ; se w0 0 ; ; jl. jump-command ; get the timeout-parameter from param 2 of the 'stop' command: rl w0 x2+j24 ; timeout := param 2; ; in case of transfer to/from senders area: ; check that the sender is not stopped ; increase stopcount to prevent further stopping of sender ; ; w0 = timeout ; w1 = driver rl. w3 h10. ; if sender area used then sn w3 0 ; jl. i40. ; begin rl. w3 h17. ; sender := saved sender descr addr; bz w2 x3+a13 ; if state(sender) shows se w2 a99 ; 'waiting for start' then sn w2 a100 ; jl. i2. ; goto sender stopped; bz w2 x3+a12 ; increase (stopcount (sender)); al w2 x2+1 ; hs w2 x3+a12 ; i40: ; end; ; the driver should actually be put in such a state, that all pending ; transfers would be aborted, in case the driver is stopped. ; however, until further, this is only done by means of increasing ; the stopcount of the driver ( *** independant of transfer/no transfer ; to/from the driver area *** ) ; ; w0 = timeout ; w1 = driver ; w3 = transfer code: 0 = no transfer to sender area ; >0 = sender descr addr c.-1 ; ++++ not implemented ++++ rl. w2 h11. ; sn w2 0 ; if driver area not used then jl. i41. ; goto init transfer code field; z. ; ++++ al w3 x3+1 ; make transfer code odd; i.e. driver transfer bz w2 x1+a12 ; increase (stopcount (driver) ); al w2 x2+1 ; hs w2 x1+a12 ; c. -1; ++++ not implemented i41: sn w3 0 ; if no transfers to the involved processes then al w3 -1 ; transfer code := -1; i.e. transfer pending; z. ; ++++ ; initialize the 'transfer code' field in the device description ; (the field will be used, when the interrupt arrives, ; to decrease the involved stopcounts) ; w0 = timeout, w1 = cur, w3 = transfer code i50: rl. w2 h5. ; rl w1 x2+a225 ; if transfer code (device descr) <> 0 then se w1 0 ; goto internal 3; jl c29 ; (i.e. transfer still in progress) rs w3 x2+a225 ; move transfer code to device descr; ; prepare timeout-operation: ; ; w0 = timeout ; w2 = device descr ; initialize controller table: am (b1) ; rl w3 +a31 ; entry:=logical device addr(device); wa. w3 h25. ; + 1 < 23 wa w3 b65 ; base of controller table; rl. w1 h20. ; chp start (controller table entry) := rs w1 x3+a310 ; abs first of channel program area; se w1 0 ; if chpg start = 0 then jl. i54. ; begin al w2 x2+a242 ; oper:= timeout operation address; jl. i53. ; goto check timeout; ; end; ; prepare for receiving an unusual status, i.e. in case the controller ; could not deliver the standard status informations i54: al w3 0 ; rs w3 x2+a230 ; chp addr (std status) := 0; al w3 j40 ; rs w3 x2+a233 ; event status (std status) := status transfer error; al w2 x2+a242 ; oper := timeout operation address; ; start the device: ; ; at this point the monitor migth introduce another strategy, ; instead of just starting the device immediatly. ; if the interrupt numbers are sparce, or if the bus migth ; get overloaded, the actual starting can be delayed until ; the resources are sufficient. ; ; notice that the monitor/driver conventions do not imply that ; the transfer is started at once, i.e. buserrors or bustimeout ; etc. are not returned to the driver at the calltime, but ; when the interrupt-operation is received by the driver. ; ; under any circumstances the driver should have the result 0, ; indicating that the transfer has been accepted to start. ; ; w0 = timeout ; w2 = timeout operation am (b1) ; bz w1 +a31+1 ; ls w1 -2 ; w1:=io-devno<1; do w1 (x2-a242+a235) ; start device(device addr(device desc)); sx 2.111 ; if any exceptions then jl. i55. ; goto not started; ; if the operation is in queue, there may be three reasons: ; 1. a wait program is still in progress, i.e. in timeout-queue ; (remove the operation and proceed, i.e. regret the wait-program) ; 2. a wait program is terminated by an event, i.e. in event queue ; (the operation may not be removed, because the driver has to ; reset the controller in order to proceed) ; 3. an uspecified channel program has terminated, i.e. in event queue ; (this situation is treated as if it was a wait-program, ; because it does not harm the monitor, but only confuses ; the driver process) i53: ; check timeout: sn w2 (x2+0) ; if timeout operation in queue then jl. i52. ; begin ; search through the timeout-queue. ; if the operation is found here, then simply remove it and proceed, ; as if it had not been in queue ; if not found here, it must be in the event-queue of the driver. ; (just leave it there, because the driver must take proper action on it) al w1 b69 ; elem := timeout-queue head; i51: rl w1 x1+0 ; rep: elem := next(elem); sn w1 b69 ; if end of timer-queue then jl. i0. ; goto result 0; i.e. in event queue se w1 x2 ; if elem = timeout operation then jl. i51. ; goto rep; ; found in timeout-queue: jl w3 d5 ; remove(timeout operation); i52: ; end; ; w0 = timeout ; w2 = timeout operation al w1 b69 ; head := timeout queue head; rs w0 x2-a242+a244; save timeout in timeout-field(operation); se w0 0 ; if timeout <> 0 then jl w3 d6 ; link (timeout queue, timeout operation); jl. i0. ; goto result 0; i.e. transfer started ok; ; the transfer could not actually be started, because of ; some kind of bus/controller error. ; ; the interrupt operation must be returned to the driver, ; together with indication of the kind of malfunction. ; ; w2 = linkfield of timeout operation ; ex = error kind i55: sx 2.1 ; errorkind := am 1-2 ; if rejected then 1 al w0 2 ; else 2; al. w3 i0. ; deliver interrupt(oper, error kind); jl d121 ; goto result 0; e. ; end of start i/o; ; ; ; procedure get or release buf ; if w20=0 a free buffer is selected and the bufferclaim of the calling ; process is decreased by one ; else it is checked that w2 is a buffer address and the buffer is then ; released and the buffer claim of the calling process is increased by ; one. ; ; call return ; saved w0 ; saved w1 ; saved w2 0/bufferaddress buffer address ; saved w3 ; b. i4 w. e63: rl w2 x1+a30 ; saved w2 se w2 0 ; if remove buffer then jl. i1. ; goto i1 ; else select: rl w2 b8 ; w2:=first buffer bz w0 x1+a19 ; sh w0 0 ; if bufferclaim<= 0 then jl. i0. ; goto i0 al w0 x1 ; ds w1 x2+6 ; save calling proc both as sender and receiver i0: jl w3 d108 ; and goto claim buffer rs w2 x1+a30 ; jl w3 d5 ; remove buf from free queue jl. i2. ; i1: jl w3 d12 ; check buf jl w3 d109 ; increase claim, remove and release buf i2: jl c99 ; goto return from interrupt e. ; ; ; ; start cpu(1) e64: al w2 0 ; select cpu(1) c. a430 jl. w1 d23. ; reset cpu(1) jl. w3 d27. ; start cpu(1) z. jl c99 ; ; ; ; c. a430 m. start of cpu(i) service ; ; ; the following procedures are all used to service other cpu's ; than the commen cpu (cpu0) b. i20,h20 w. ; data-out instruction at cpu(i); ; ; interrupt cpu1 1<23 + 20<3 + 0<1 ; reset cpu1 1<23 + 20<3 + 1<1 ; stop cpu1 1<23 + 20<3 + 2<1 ; start cpu1 1<23 + 20<3 + 3<1 ; ; call: w2=relative addr of cpu(i), w1=return ; return: w2,w3 are unchanged, w0 are changed ; if cpu(i) is started then w1<h9 else w1=h9 h9=2 d21: am 1<1 ; start cpu(x2) d20: am 1<1 ; stop cpu(x2) d23: am 1<1 ; reset cpu(x2) d22: al w0 0<1 ; interrupt cpu(x2) wa w0 x2+f23 ; interrupt address(cpu(i)) rs. w1 h1. ; ds. w3 h3. ; al w1 0 ; do_count:=0; i0: do w3 (0) ; data_out(cpu(i)) sx 2.111 ; if buserror then jl. i2. ; goto count; i1: dl. w3 h3. ; jl. (h1.) ; return; i2: al w1 x1+1 ; do_count:=do_count+1; se w1 h9 ; if do_count<h9 then jl. i0. ; goto repeat data_out instruction else ls w2 -1 ; set cpu(x2) as not able to use; al w3 2.10 ; w3=mask for cpu(1) ls w3 x2 ; w3=2**(x2//2) ; mask for cpu(i) ac w3 x3+1 ; la. w3 b59. ; remove bit for cpu(i) rs. w3 b59. ; jl. i1. ; return h1: 0 h2: 0 h3: 0 b59: 2.000 000 000 011 ; mask for cpu's in use b51: 0,r.a350 ; b51+2*i = 0 cpu(i) is not initialisized ; = 1 a interrupt is send to cpu0, but ; not recieved. ; (special meaning at init cpu(i)) ; = 2 cpu(i) is ready for start ; = 4 cpu(i) is running or stopped ; without reg. dump ; ; ; stop cpu(i) i=1,...,last cpu ; call: w3=return ; return: all reg unchanged d25: ds. w1 h5. ; ds. w3 h7. ; al w2 -2 ; i5: al w2 x2+2 ; next cpu sl w2 a351+1 ; if all cpu's is stopped then jl. i6. ; return rl w1 x2+b56 ; sn w1 0 ; if no proc then jl. i5. ; goto next proc al w0 0 ; hs w0 x1+a186 ; clear cpu running mask rl. w0 x2+b51. ; sn w0 4 ; if a proc is running then jl. w1 d22. ; interrupt at cpu(x2) jl. i5. ; goto next cpu i6: dl. w1 h5. ; dl. w3 h7. ; jl x3 ; return ; start cpu(i) i=1,...,last cpu ; call: w1=curr int proc at cpu0 before interrupt, w3=return ; return: all reg. are changed d26: rs. w3 h7. ; jl. w3 d28. ; error test at cpu1 rl w0 b57 ; w0:=cur proc(cpu0) sl w0 1 ; if current proc at cpu0 is not restored then rs w0 b1 ; restore cur proc(cpu0) al w2 -2 ; rs w2 b57 ; no proc to restore before a new interrupt at cpu(i) al w3 1 ; w3:=mask(cpu0); i10: ls w3 1 ; w3:=mask(next cpu); al w2 x2+2 ; w2:=addr(next cpu); sl w2 a351+1 ; if all cpu is started then jl. i13. ; goto test first proc al w0 a353 ; w0:=mask for allowed cpu; rl. w1 b59. ; w1:=mask for cpu in use; sz w1 x3 ; if the cpu can not be used or so w0 x3 ; the cpu is not allowed then jl. i10. ; goto next cpu else rl. w0 x2+b51. ; sh w0 1 ; if cpu(x2) is not waiting for cpu0-interrupt then jl. i10. ; and goto next cpu al w1 b2 ; w1:=chain head i11: rl w1 x1 ; w1:=next proc in time slice queue; al w0 x1-a16 ; process addr rs w0 x2+b56 ; rl w0 x1-a16+a186; w0:=mask for allowed cpu; sh w0 2047 ; if cpu(x2) is started or so w0 x3 ; this cpu can not be used then jl. i11. ; goto next proc; i12: rl w1 x2+b56 ; else hs w3 x1+a186 ; set cpu running mask; i14: al w0 4 ; rs. w0 x2+b51. ; set start signal jl. i10. ; goto next cpu i13: al w2 b2 ; i16: rl w2 x2 ; w2:= next proc rl w0 x2-a16+a186; w0:=cpu-mask so w0 2.1 ; if cpu0 is not allowed then jl. i16. ; goto next proc else sl w0 2047 ; if proc is started then jl. i16. ; goto next proc else sn w2 (b2) ; if proc already is in front then jl. (h7.) ; return jl w3 d5 ; else remove proc rl w1 b2 ; and jl w3 d6 ; link proc in front jl. (h7.) ; return ; init cpu1 d27: rs. w3 h7. ; rl w3 b65 ; w3:=base of controller descr table; al. w1 c26. ; w1:=power up entry for cpu1; rs w1 x3+20<3+a310; al w2 0 ; select cpu1 jl. w1 d22. ; start cpu(i) sl w1 h9 ; if cpu1 is not ready then jl. i17. ; return i15: rl. w0 b51. ; wait for ready signal sh w0 0 ; from cpu1 jl. i15. ; al w0 2 ; rs. w0 b51.+0; i17: jl. (h7.) ; h4: 0 h5: 0 h6: 0 h7: 0 d28: ; error test at cpu1 rl w0 b55 ; w0:=last service addr.cpu1 se w0 c99 ; if no errors then jl x3 ; return al. w2 i18. ; else restart cpu1 rs w2 b55 ; jl. w3 e64. ; and init cpu1 i18: jl c99 ; if not init then return e. ; b. h16,i10 w. c15: ; interrupt at cpu1 al w1 0 ; rx w1 b56 ; w1:=current process cpu1 rx w1 b1 ; b1:=current process cpu1 rs w1 b57 ; save(current process) al w1 2 ; rs. w1 b51.+0 ; set after intterupt dl. w2 h7. ; w1:=top reg dump; w2:= 2*interrupt number jl (b55) ; goto interrupt service for cpu1-process 0 ; w1 = top reg. dump h7: 0 ; w2 = 2*interrupt number ; c26: al. w3 h0. ;#1 init cpu1 gp w3 b91 ;#1 set inf register addr; rl w3 b65 ;#1 base of controller descr addr al. w1 c27. ;#1 rs w1 x3+20<3+a310;#1 set start addr ri a179 ;#1 return interrupt; h9: am 1 ;#1 c27: ;#1 al w3 1 ;#1 rs. w3 b51.+0 ;#1 h8: rl. w2 b51.+0 ;#1 se w2 4 ;#1 if cpu0 is not ready then jl. h8. ;#1 goto test and wait else c28: gg w1 b91 ;#1 w1:=inf reg(cpu1) rl w2 b56 ;#1 w2:=proc addr(cpu1) dl w0 x2+a170 ;#1 set user exception addr and ds w0 x1+a325+a328;#1 user escape addr al w0 x2+a28 ;#1 rs w0 x1+a325+a326;#1 set register dump addr; ri a179 ;#1 return interrupt; ;#1 system table: monitor mode 0 ; -5 monitor call service addr h6 ; -3 interrupt service addr 1<23+0 ; -1 status interrupt limit h0=k-13 h1=k-1 ; inf addr: monitor mode h2=k+11 ; inf addr: user mode h3 ; +1 register dump addr 0 ; +3 exception service addr 0 ; +5 escape service addr ;#1 system table: user mode h4 ; -5 monitor call service addr h5 ; -3 interrupt - - 1<23 + 6 ; -1 status < 12 + interrupt limit 0 ; +1 register dump addr 0 ; +3 exception service addr 0 ; +5 escape service addr ;#1 monitor register dump addr h3: 0 ; w0 0 ; w1 0 ; w2 0 ; w3 1<23 ; status monitor mode c27 ; ic start cpu1 process 0 ; cause 0 ; sb 0 ; cpa 0 ; base 8 ; lower write limit 8.3777 7777 ; upper write limit 0<12 + 6 ; interrupt limits ;#1 interrupt service cpu1 ;#1 interrupt level = 14 timer interrupt (or interrupt from cpu0) ;#1 = 16 channel input finis ;#1 = 18 channel input start ;#1 = 20 channel output finis ;#1 = 22 character device interrupt ;#1 ;#1 h6: am c99-c0 ;#1 internal interrupt level 2 h4: am c0-c1 ;#1 internal interrupt w3:=monitor call service addr ;#1 external interrupt h5: al w3 c1 ;#1 w3:=interrupt service addr (level 1) ds. w2 h7. ;#1 save (w1,w2) sn w3 c0 ;#1 if internal interrupt then jl. i6. ;#1 goto i6 sn w2 14 ;#1 if cpu(i) is interrupted from cpu0 then jl. h9. ;#1 goto start sl w2 14 ;#1 if interruptlevel > 7 then jl. c20. ;#1 go interruptservice for other computers i6: rs w3 b55 ;#1 set interrupt service addr al w0 1 ;#1 rs. w0 b51.+0 ;#1 rl w1 b56 ;#1 adrr of curr.cpu1 al w0 0 ;#1 hs w0 x1+a186 ;#1 clear cpu user bit am -3<3 ;#1 level20 i8: al w3 23<3 ;#1 level23 wa w3 b65 ;#1 base of controller table i7: rl w1 x3+a313 ;#1 w1:=interrupt level do w1 (x3+a312) ;#1 interrupt(cpu0) sx 2.111 ;#1 if buserror then jl. i7. ;#1 repeat data out; jl. h8. ;#1 goto wait for interrupt ; ; interrupt service for interrupt caused of data out instructions on ; other computers (HC8000's) ; ; do wreg addr ; wa 1<23+level<3+ 2.001 send data transfer request ; wa>= 0 contents irr ; request to send data specified by level location ; wa =1<23 + message ; ; ; ; di wreg addr ; wb 1<23+level<3+ 2.001 start input ; wb >=0 input to addr specified in level location ; wb = 1<23 + message ; ; level location (8) + level < 3 ; *----------*----------*----------*----------* ; ! number of! input or ! interrupt! ! ; ! bytes to ! output ! address ! level ! ; ! transfer ! address ! ! ! ; *----------*----------*----------*----------* ; c20: ; interrupt 16 channel input finis ; interrupt 18 channnel input start (input request) ; interrupt 20 channel output finis ; interrupt 22 character device interrupt rl w1 b106 ; w1:=addr(hcdriver) sn w1 0 ; if no proc then jl. c28. ; ri(cpu1) am x2-16 ; else rs w2 x1+a302+2 ; save interrupt level al w0 1 ; rs. w0 b51.+0 ; rh.state:=wait interrupt service jl. i8. ; goto interrupt cpu0 ; ; ; z. c21: ; interrupt received at cpu(0) level23 c. a430 al w0 2 ; rs. w0 b51.+0 ; rh.state:= interrupt served z. rl w1 b106 ; w1:=addr of hcdriver proc rl w2 b8 ; w2:=next buf rs w1 x2+4 ; rs w1 x2+6 ; set sender and rec. jl w3 d5 ; remove buf al w1 x1+a15 ; jl w3 d6 ; insert buf al w1 x1-a15 ; al w0 -14 ; rs w0 x2+a158 ; set buffer state al w0 0 ; rx w0 x1+a302+2 ; sn w0 0 ; if not interrupt 16 then rx w0 x1+a302+4 ; load next sn w0 0 ; if not interrupt 18 then rx w0 x1+a302+6 ; load next rs w0 x2+8 ; save interrupt level bz w0 x1+a13 ; w0:=state se w0 a104 ; if state<>wait event then jl c99 ; bz w3 x1+a19 ; al w3 x3-1 ; claim buf hs w3 x1+a19 ; rs w2 x1+a30 ; save buf in proc al w0 0 ; rs w0 x1+a28 ; al w3 c99 ; jl d10 ; link proc c. a430 e. m. end of service for cpu(i) z. c.a400-1 \f m. coroutine monitor ;************************** c o r o u t i n e m o n i t o r ************************* ; locations in process extension 1 are used by cmonprocedures as described below: ; ; -2: signalch ; b27 +0: start ; +2: check_eventqueue ; +4: check_eventqueue ; +6: ; +8: generate_testoutput ; +10: inspect_chained ; +12: inspect_chained ; +14: timermess ; +16: timerscan ; +18: timerscan ; +20: generate_testoutput ; +22: " - " ; +24: " - " \f b.h50 w. ; procedure remove(elem); ; ; removes a given element from its queue and leaves the element ; linked to itself. ; ; call return ; w0: - unchanged ; w1: - next(elem) ; w2: elem elem ; w3: link link h0: rl w1 x2 ; begin rx w2 x2+2 ; prev(elem):= elem; rs w1 x2 ; next(prev(elem)):= next(elem); rx w2 x1+2 ; prev(next(elem)):= old prev(elem); rs w2 x2 ; next(elem):= elem; jl x3 ; end; ; procedure link(head,elem); ; ; links the element to the end of the queue; ; ; call return ; w0 - destroyed ; w1 head head ; w2 elem elem ; w3 link old last(head) h1: al w0 x3 ; begin rl w3 x1+2 ; old prev:= last(head); rs w2 x1+2 ; prev(head):= elem; rs w2 x3+0 ; next(old prev):= elem; rs w1 x2+0 ; next(elem):= head; rs w3 x2+2 ; prev(elem):= old prev; rl w3 0 ; jl x3 ; end; \f ; procedure get_mess_ext(ref); ; ; returns a reference to the first free message buffer extension ; or 0 if no extensions are available. the extension is removed from the chain. ; ; call return ; w0: - destroyed ; w1: - destroyed ; w2: - ref or 0 ; w3: link link b.j5 w. h7: rl w1 b28 ; begin rl w2 x1+a588 ; ref:= cur.ext2.buffer_extension_head; sn w2 0 ; if ref <> 0 then jl. j0. ; begin rl w0 x2 ; cur.ext2.buffer_extension_head:= next(ref); rs w0 x1+a588 ; al w2 x2+2 ; ref:= ref+2; ; end; j0: jl x3 ; end; e. \f ; procedure answer arrived(buf,ref); ; ; is called from procedure 'check_event_queue' when an answer appears in ; the event queue and 'ref.open' is true, i. e. when a coroutine has ; called 'cwaitanswer(buf)'. the coroutine is activated and the answer ; descriptor is closed. ; ; call return ; w0: - destroyed ; w1: ref destroyed ; w2: buf buf ; w3: link link b.j5 w. c106: am (b27) ; begin ds w3 +6 ; ext1(4,6):= (buf,link); am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate testoutput(1<6); jl. w3 h4. ; 3<22+1<6 ; j0: al w0 0 ; hs w0 x1 ; ref.open:= false; rl w2 x1+2 ; corout:= ref.param1; al w1 1 ; result:= ok; rl w0 x2+a698 ; priority:= corout.priority; jl. w3 c100. ; start(corout,priority,ok); am (b27) ; dl w3 +6 ; (buf,link):= ext1(4,6); jl x3 ; end; e. \f ; procedure central wait; ; ; central waiting point in coroutine system. checks the eventqueue ; and schedules pending events. if the active queue is empty the ; monitor procedure wait event is called otherwise the first co- ; routine is started. if 'corout.user_exit' <> 0 a jump to 'user_exit' is ; made with register contents: ; w0: - ; w1: - ; w2: current_coroutine ; w3: link b.j5 w. h2: ; begin ; repeat j0: jl. w3 h6. ; check event queue; rl w2 b28 ; if active queue empty then rl w3 x2+a546 ; begin se w3 x2+a546 ; buf:= cur.ext2.last event; jl. j1. ; wait event(buf,result); rl w2 x2+a582 ; jd 1<11+24 ; jl. j0. ; ; end; j1: al w2 x3-2 ; until active queue not empty; rs w2 (b28) ; corout:= first in active queue; rl w1 x2+a720 ; if corout.user_exit <> 0 se w1 0 ; then jump to user_exit; jl w3 x1 ; rl w3 (b28) ; dl w1 x3+a712 ; rl w2 x3+a714 ; restart corout;; jl (x3) ; end; e. \f ; procedure check eventqueue; ; ; inspects the eventqueue starting at 'last event'('last event' = 0 ; if the queue must be inspected from the start). pending events ; which have arrived after 'last event' are scheduled if ; 'event descriptor.open' = true. the scheduling is performed by calling ; either a 'cmon'-standard procedure (even procedure number in event ; descriptor) or a user defined procedure (odd procedure number which ; is used as index in the procedure table in process extension 2). ; ; a procedure ('user' or 'cmon') which is used for scheduling answers or messages ; must return with w2=0 if the answer/message is removed from the event queue ; - otherwise with w2='buf' ; i. e. the event queue must be inspected from the ; start when an event is removed by a scheduling procedure. ; exit to 'cmon'- or user-procedure with: ; w0: - ; w1: ref(event descriptor) ; w2: buf ; w3: link b. j10 w. h6: am (b27) ; begin rs w3 +2 ; ext1(2):= link; rl w3 b28 ; rl w2 x3+a582 ; last_buf:= cur.ext2.last_event; j0: jd 1<11+66 ; repeat rl w3 b28 ; sh w0 -1 ; test_event(last_buf,buf,result); jl. j5. ; if result <> empty then se w0 0 ; begin jl. j2. ; if result = message rl w1 x2+4 ; ac w1 x1 ; se w1 (b1) ; then ref:= jl. j1. ; if buf.receiver = cur then cur.ext2.messdescr rl w1 x3+a584 ; else buf.receiver.messdescr <* pseudoprocess *> jl. j2. ; j1: rl w1 x1+a60 ; else <* answer *> ref:= buf.ref; j2: hl w0 x1 ; sn w0 0 ; jl. j0. ; if ref.open then hl w0 x1+1 ; begin sz w0 1 ; if even procedure number jl. j3. ; then call cmonproc(buf,ref); am (0) ; jl w3 (130) ; jl. j0. ; else j3: ; begin <* odd procedure number *> rl w3 x3+a586 ; <* use procedure number in event *> hl w0 x1+1 ; <* descriptor as index in proce- *> ls w0 +1 ; <* dure table in cur.ext2 *> wa w0 x3 ; am (0) ; jl w3 (0) ; call userproc(buf,ref); jl. j0. ; end; ; end; ; end; ; until result = empty; j5: sn w2 0 ; <* if 'last_buf' points at a message , 'last_event' jl. j6. ; <* must be reset as the message may be regretted rl w0 x2+4 ; <* before next scan. se w0 0 ; sz w0 -8 ; cur.ext2.last_event:= if last_buf points at message al w2 0 ; then 0 j6: rs w2 x3+a582 ; else last_buf; am (b27) ; link:= ext1(2); jl (2) ; end; e. \f ; procedure entry pass(priority); ; ; pending events are scheduled and calling coroutine is restarted ; with the priority given in call. ; ; call return ; w0: priority destroyed ; w1: - destroyed ; w2: - destroyed ; w3: link current coroutine b.j5 w. c102: am (b28) ; begin rs w3 (0) ; current_coroutine.ic:= link; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate testoutput(testkind); jl. w3 h4. ; 3<22+1<2 ; j0: rl w2 (b28) ; rl w1 x2+a710 ; result:= current_coroutine.result; jl. w3 c100. ; start(current_coroutine,priority,result); jl. h2. ; central wait; e. ; end; \f ; procedure entry inspect(priority,result); ; ; schedules pending events and checks if the active queue contains ; coroutines with priority higher than the call parameter 'priority'. in ; this case 'result' returns true (1). ; ; call return ; w0: priority result ; w1: - destroyed ; w2: - destroyed ; w3: link current coroutine b.j5 w. c103: am (b28) ; begin rs w3 (0) ; current_coroutine.ic:= link; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput is active then jl. j0. ; generate testoutput(1<3); jl. w3 h4. ; 3<22+1<3 ; j0: rs w0 (b27) ; ext1(0):= priority; jl. w3 h6. ; check_event_queue; rl w0 (b27) ; priority:= ext1(0); rl w3 b28 ; rl w3 x3+a546 ; corout:= first in active queue; sl w0 (x3-4) ; am -1 ; result:= corout.prio > priority; al w0 1 ; rl w3 (b28) ; jl (x3) ; end; e. \f ; procedure entry start(corout,priority,result); ; ; removes the coroutine from its queue (normally the timer queue) and ; inserts it in active queue according to the call parameter 'priority'. ; the call parameter 'result' is returned in w0 of ; the coroutine which is activated. ; ; call return ; w0: priority destroyed ; w1: result destroyed ; w2: corout corout ; w3: link current coroutine b.j5 w. c100: rs w3 (b27) ; begin am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput is active then jl. j0. ; generate testoutput(1<0); jl. w3 h4. ; 3<22+1<0 ; j0: rs w1 x2+a710 ; corout.result:= result; rs w0 x2+a698 ; corout.priority:= priority; al w2 x2+2 ; jl. w3 h0. ; remove(corout); rl w1 0 ; al w0 x2 ; rl w2 b28 ; worse:= rear of active queue; al w3 x2+a546 ; while worse.prio > prio and al w1 x1+1 ; worse <> active queue head do j1: rl w3 x3+2 ; worse:= prev(worse); sn w3 x2+a546 ; jl. j2. ; 'insert corout in the rear of sh w1 (x3-4) ; other coroutines of the same jl. j1. ; priority' j2: rl w1 x3 ; rl w2 0 ; jl. w3 h1. ; link(worse,corout); al w2 x2-2 ; rl w3 (b28) ; am (b27) ; jl (0) ; end; e. \f ; procedure entry wait(timer,result); ; ; calling coroutine is suspended for max 'timer' seconds. ; 'timer' = 0 indicates no timeout. the return parameter 'result' ; indicates whether the coroutine was started by timeout or by ; the arrival of an internal or external event. ; ; call return ; w0: timer result ; w1: - destroyed ; w2: - - ; w3 link current coroutine b.j5 w. c101: am (b28) ; begin rs w3 (0 ) ; current coroutine.return:= link; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active then jl. j0. ; generate testoutput(1<1); jl. w3 h4. ; 3<22+1<1 ; j0: rl w2 (b28) ; current coroutine.timer:= timer; rs w0 x2+a706 ; al w2 x2+2 ; jl. w3 h0. ; remove(current coroutine); rl w3 b28 ; al w1 x3+a552 ; jl. w3 h1. ; link(timer queue head,current coroutine); jl. h2. ; central wait; ; end; e. \f ; procedure entry csendmessage(mess,name,buf); ; ; allocates a message buffer extension and prepares it for cwaitanswer. ; then calls sendmessage. ; ; return parameter 'buf': 0 buffer claims exceeded ; 1 no free extensions ; >1 message buffer address ; ; call return ; w0: - destroyed ; w1: mess destroyed ; w2: name buffer address (or 0 or 1) ; w3: link current coroutine b.j5,i5 w. c104: am (b28) ; begin rs w3 (0) ; current_coroutine.ic:= link; am (b28) ; rl w3 +a544 ; sn w3 0 ; jl. j0. ; if testoutput active jl. w3 h4. ; then generate_testoutput(1<4); 3<22+1<4 ; j0: ds w2 (b27) ; jl. w3 h7. ; get_mess_ext(ref); sn w2 0 ; if ref <> 0 <* extension available *> then jl. j1. ; begin rl. w0 i0. ; <* initialize answer descriptor *> rs w0 x2 ; ref.open:= false; ref.proc:= 12; rl w3 b27 ; rs w2 x3+2 ; ext1(2):= ref; rl w1 x3-2 ; rl w3 x3 ; send message(mess,name,buf,ref); jd 1<11+16 ; se w2 0 ; if buffer claims exceeded jl. j2. ; then release message buffer extension; am (b27) ; rl w1 (+2) ; rl w3 b28 ; al w0 x1-2 ; rx w0 x3+a588 ; rs w0 x1-2 ; jl. j2. ; j1: al w2 1 ; end j2: rl w3 (b28) ; else buf:= 1; <* no free extensions *> jl (x3) ; end; i0: 0<12+12 ; answer descriptor init (open=false,proc='answer_arrived') e. \f ; procedure entry cwaitanswer(buf,timer,result); ; ; prepares the message buffer extension for receiving the answer. if ; the buffer has been answered, 'last_event' is reset as the buffer ; may have been skipped during an earlier inspection of the event queue. ; the coroutine waits for max. 'timer' seconds for the answer. when the ; coroutine is restarted the action depends on 'result': ; ; result = timeout : the answer descriptor is closed ; ; result = answer arrived : the answer is received in the answer ; area in process extension 2 and the message ; buffer extension is released. ; ; call return ; w0: timer result (timeout:0,wait_answer result:1,2,3,4,5) ; w1: - answer area in ext2 if result <> timeout ; w2: buf buf ; w3: link current coroutine b.j10 w. c105: rs w3 (b27) ; begin am (b28) ; rl w3 +a544 ; sn w3 0 ; jl. j0. ; if testoutput active jl. w3 h4. ; then generate_testoutput(1<5); 3<22+1<5 ; j0: rl w3 (b28) ; rl w1 (b27) ; current_coroutine.return:= link; ds w2 x3+a724 ; current_coroutine.buf:= buf; rs w0 (b27) ; ext1(0):= timer; rl w1 x2-2 ; with buf.ref do al w0 1 ; begin hs w0 x1 ; open:= true; rs w3 x1+2 ; corout:= current_coroutine; ; end; rl w0 x2+4 ; sz w0 -8 ; if buf.state = answer pending jl. j1. ; then last_event:= 0; <* inspect from start *> al w0 0 ; am (b28) ; rs w0 +a582 ; j1: rl w0 (b27) ; timer:= ext1(0); jl. w3 c101. ; wait(timer,result); rl w2 x3+a724 ; buf:= current_coroutine.buf; rl w1 x2-2 ; ref:= buf.ref; se w0 0 ; if result = timeout jl. j2. ; then ref.open:= false hs w0 x1 ; jl. j4. ; else j2: ; begin <* result = answer arrived *> rl w3 b28 ; release message buffer extension; al w0 x1-2 ; rx w0 x3+a588 ; rs w0 x1-2 ; se w2 (x3+a582) ; jl. j3. ; al w0 0 ; if buf = last_event then last_event:= 0; rs w0 x3+a582 ; j3: al w1 x3+a590 ; jd 1<11+18 ; wait answer(buf,cur.ext2.answer_area); j4: rl w3 (b28) ; end; jl (x3+a722) ; end; e. ; end; \f ; procedure entry signal binary(sem); ; procedure entry signal(sem); ; ; call return ; w0: - destroyed ; w1: - destroyed ; w2: sem destroyed ; w3: link current coroutine b.j5 w. c107: am 1 ; signal_binary: c108: al w0 0 ; signal: am (b28) ; begin rs w3 (0) ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<7); jl. w3 h4. ; 3<22+1<7 ; j0: rl w1 x2+4 ; with sem do al w3 x1+1 ; begin se w0 0 ; count:= count+1; la w3 0 ; if binary rs w3 x2+4 ; then count:= count and 1; sl w1 0 ; if count <= 0 then jl. j1. ; begin rl w2 x2 ; corout:= next(sem); jl. w3 h0. ; remove(corout); al w2 x2+6 ; rl w0 x2+a698 ; priority:= corout.prio; al w1 1 ; result:= ok; jl. w3 c100. ; start(corout,priority,result); j1: rl w3 (b28) ; end; jl (x3) ; end; e. ; end; \f ; procedure entry wait_semaphore(sem); ; ; call return ; w0: - destroyed ; w1: - destroyed ; w2: sem destroyed ; w3: link current coroutine b.j5 w. c109: am (b28) ; begin rs w3 (0) ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<8); jl. w3 h4. ; 3<22+1<8 ; j0: rl w1 x2+4 ; with sem do al w1 x1-1 ; begin rs w1 x2+4 ; count:= count-1; rl w3 (b28) ; sl w1 0 ; if count < 0 then jl (x3) ; begin rl w1 x3 ; rs w1 x3+a722 ; current_coroutine.return:= link; al w1 x2 ; head:= sem.coroutine_queue_head; al w2 x3-6 ; elem:= current_coroutine.sem_queue_elem; jl. w3 h1. ; link(head,elem); al w0 0 ; timer:= 0 <* no timeout *> jl. w3 c101. ; wait(timer); rl w3 (b28) ; end; jl (x3+a722) ; end with; e. ; end; \f ; procedure entry signal_chained(sem,oper); ; ; signals an operation to a chained semaphore. if the coroutine queue of ; the semaphore contains a coroutine which is waiting for an operation ; of this type,the coroutine is started. otherwise the operation is ; queued to the semaphore. ; ; two reserved types exist: ; 1<0: message ; 1<1: answer ; ; call return ; w0: - destroyed ; w1: operation destroyed ; w2: semaphore destroyed ; w3: link current coroutine b.j10 w. c110: am (b27) ; begin rs w3 -2 ; am (b28) ; rl w3 +a544 ; sn w3 0 ; jl. j0. ; if testoutput active jl. w3 h4. ; then generate_testoutput(1<9); 3<22+1<9 ; j0: rl w3 x2 ; head:= sem.coroutine_queue_head; j1: sn w3 x2 ; corout:= next(head); found:= false; jl. j4. ; while corout <> head and -, found do rl w0 x3-a694+a708; if logand(corout.mask,oper.type) <> 0 then la w0 x1+4 ; begin se w0 0 ; jl. j3. ; found:= true; rl w3 x3 ; jl. j1. ; j3: rs w1 x3-a694+a724; corout.latop:= operation; rl w0 x1+4 ; type:= oper.type; al w2 x3 ; jl. w3 h0. ; remove(corout); al w2 x2-a694 ; rl w1 0 ; result:= type; rl w0 x2+a698 ; priority:= corout.prio; jl. w3 c100. ; start(corout,priority,result); jl. j5. ; end ; else corout:= next(corout); j4: rx w2 2 ; if -,found al w1 x1+4 ; then link(sem.operation_queue,oper); jl. w3 h1. ; j5: rl w3 (b28) ; am (b27) ; jl (-2) ; end; e. \f ; procedure entry inspect_chained(sem,mask,oper,result); ; ; checks if 'sem_operation_queue' contains an operation which matches 'mask'. ; if no matching operation is found, 'oper' returns = 0, ; otherwise 'oper' refers to the first matching operation. ; 'result' returns 'true' (1) if the active queue contains coroutines of ; priorities higher than the priority of calling coroutine. ; ; call return ; w0: - (result= 0,1) ; w1: mask oper or 0 ; w2: sem sem ; w3: link current coroutine b.j10 w. c111: am (b28) ; begin rs w3 (0) ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<10); jl. w3 h4. ; 3<22+1<10 ; j0: am (b27) ; rs w2 +12 ; save(sem); al w0 x1 ; rl w1 x2+4 ; head:= sem.operation_queue_head; j1: ; oper:= next(head); found:= false; sn w1 x2+4 ; while oper <> head and -,found do jl. j3. ; if logand(oper.type,mask) <> 0 rl w3 x1+4 ; then found:= true la w3 0 ; else oper:= next(oper); se w3 0 ; jl. j4. ; rl w1 x1 ; jl. j1. ; j3: al w1 0 ; if -,found then oper:= 0; j4: rl w3 (b28) ; rl w0 x3+a698 ; priority:= current_coroutine.prio; rl w2 b28 ; rl w2 x2+a546 ; corout:= first in active queue; sh w0 (x2-4) ; am -1 ; al w0 1 ; result:= corout.prio > priority; am (b27) ; rl w2 +12 ; jl (x3) ; end; e. \f ; procedure entry wait_chained(sem,mask,timer,oper); ; ; if 'sem.operation_queue' contains an operation ; which matches 'mask', the operation is removed from the queue . a 'pass' ; is executed if the active queue contains coroutines of priorities higher ; than the priority of calling coroutine. if no matching operation is found ; pending events are scheduled and the calling coroutine waits for max. 'timer' ; seconds for an operation to arrive. ; ; if the operation contains a message or an answer ('oper.type' = 1<0 or 1<1 , ; resp ) , the buffer contents is copied to the common message-answer area in ; process extension 2. a buffer containing an answer is removed from the event ; queue by 'waitanswer'. ; ; ; call return ; w0: timer result ( 0(timeout) or oper.type) ; w1: mask oper (undefined if result = timeout) ; w2: sem destr. ; w3: link current_coroutine b.j10 w. c112: rs w3 (b27) ; begin am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<11); jl. w3 h4. ; 3<22+1<11 ; j0: rx w1 (b27) ; rl w3 (b28) ; rs w1 x3+a722 ; current_coroutine.return:= link; rx w1 (b27) ; current_coroutine.waitch_mask:= mask; ds w1 x3+a708 ; current_coroutine.timer:= timer; jl. w3 c111. ; inspect_chained(sem,mask,oper,result); se w1 0 ; if oper = 0 then jl. j1. ; begin <* wait in semaphore queue *> al w1 x2 ; head:= sem.coroutine_queue_head; al w2 x3+a694 ; elem:= current_coroutine.sem_queue_elem; jl. w3 h1. ; link(head,elem); rl w0 x2-a694+a706 ; timer:= current_coroutine.timer; jl. w3 c101. ; wait(timer,result); se w0 0 ; if result = timeout then jl. j3. ; begin rs w0 x3+a710 ; current_coroutine.result:= timeout; al w2 x3+a694 ; elem:= current_coroutine.sem_queue_elem; jl. w3 h0. ; remove(elem); jl. j6. ; goto exit; ; end; ; end; j1: rs w1 x3+a724 ; current_coroutine.latop:= oper; rl w2 x1+4 ; rs w2 x3+a710 ; current_coroutine.result:= oper.type; al w2 x1 ; jl. w3 h0. ; remove(oper); rl w3 (b28) ; if waiting <* coroutines of higher sn w0 0 ; priority in active queue *> then jl. j2. ; begin rl w0 x3+a698 ; priority:= current_coroutine.prio; jl. w3 c102. ; pass(priority); ; end; j2: rl w0 x3+a710 ; j3: sz w0 -4 ; if oper.type = message or answer then jl. j6. ; begin rl w2 x3+a724 ; oper:= current_coroutine.latop; rl w3 b28 ; rl w2 x2+8 ; buf:= oper.buf; se w0 1<1 ; if oper.type = answer then jl. j5. ; begin se w2 (x3+a582) ; jl. j4. ; if buf = last_event al w0 0 ; then last_event:= 0; rs w0 x3+a582 ; j4: al w1 x3+a590 ; area:= common message-answer area; jd 1<11+18 ; waitanswer(buf,area); jl. j6. ; end j5: al w1 x3+a590 ; else dl w0 x2+10 ; begin <* message *> ds w0 x1+2 ; dl w0 x2+14 ; ds w0 x1+6 ; dl w0 x2+18 ; <* copy to common massage-answer area *> ds w0 x1+10 ; dl w0 x2+22 ; ds w0 x1+14 ; end; ; end; j6: rl w3 (b28) ; exit: rl w0 x3+a710 ; result:= current_coroutine.result; rl w1 x3+a724 ; oper:= current_coroutine.latop; <* undef if timeout *> jl (x3+a722) ; e. ; end; \f ; procedure entry sem_sendmessage(name,message,oper,sem.result); ; ; sends a massage to the process given by 'name'. when the answer arrives ; it is signalled to the chained semaphore 'sem'. the calling coroutine must ; provide the operation 'oper' which is used as: ; ; 1) message_buffer_extension and 2) answer_operation(sem_answer_proc) ; -6 (next operation) oper +0 next operation ; -4 (prev operation) +2 prev operation ; -2 (type) +4 type=answer(1<1) ; ext. +0 open,'sem_answer_proc' +6 - ; +2 answer_sem +8 buffer address ; ; ; call return ; w0: sem destr. ; w1: params destr. ; w2: oper buffer addres ( or 0 = claims exceeded ) ; w3: link current coroutine ; ; 'params' points at a parameter area containing: ; ; params +0: name(1) ; +2: name(2) ; +4: name(3) ; +6: name(4) ; +8: name table address ; +10: mess(1) ; +12: mess(2) ; etc. b.j5,i5 w. c113: am (b28) ; begin rs w3 (0) ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<12); jl. w3 h4. ; 3<22+1<12 ; j0: rs w0 (b27) ; with oper.answer_descriptor do rl. w0 i0. ; begin rs w0 x2+6 ; proc:= sem_answerproc; rl w0 (b27) ; open:= true; rs w0 x2+8 ; answer_sem:= sem; al w3 x1 ; end; al w1 x1+10 ; name_address:= params; ; message_address:= params+10; al w2 x2+6 ; ref:= oper.answer_descriptor; jd 1<11+16 ; sendmessage(name_addres,message_address,ref,result); rl w3 (b28) ; jl (x3) ; end; i0: 1<12+28 ; answer_descriptor init; e. \f ; procedure sem_answer_proc(ref,buf); ; ; this procedure is called from procedure 'check_event_queue' when an ; answer to a message, sent by 'sem_sendmessage, has arrived. 'ref' ; contains the address of the answer_descriptor and 'buf' contains the ; message buffer address. the answer is signalled to the chained semaphore ; given in answer_descriptor. ; ; call return ; w0: - destr. ; w1: ref destr. ; w2: buf buf ; w3: link link b.j5 w. c114: am (b27) ; begin ds w3 +6 ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<13); jl. w3 h4. ; 3<22+1<13 ; j0: al w0 0 ; with ref do hs w0 x1 ; begin al w0 1<1 ; open:= false; rs w0 x1-2 ; type:= answer; rx w2 x1+2 ; sem:= answer_sem; al w1 x1-6 ; buffer:= buf; jl. w3 c110. ; signal_chained(sem,operation); am (b27) ; end; dl w3 +6 ; jl x3 ; end; e. \f ; procedure message_received(buf,ref); ; ; this procedure is called from 'check_event_queue' when a message is ; received and mess_descr.proc = 'message_received'. the message descriptor ; must contain an operation and the address of a chained semaphore. ; ; message_descriptor message_operation ; -6: next operation - ; -4: prev operation - ; -2: type type = message (1<0) ; mess_descr +0: open,'message_received' - ; +2: semaphore address buffer address ; ; ; call return ; w0: - destr. ; w1: ref destr. ; w2: buf 0 (the message buffer is removed) ; w3: link link b.j5 w. c115: am (b27) ; begin rs w3 +6 ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<14); jl. w3 h4. ; 3<22+1<14 ; j0: jd 1<11+26 ; getevent(buf); al w0 0 ; with ref do hs w0 x1 ; begin al w0 1<0 ; open:= false; <* the message class must be ; explicitly opened by a ; receiving coroutine *> rs w0 x1-2 ; oper.type:= message; rx w2 x1+2 ; oper.buffer:= buf; al w1 x1-6 ; sem:= message_sem; jl. w3 c110. ; signal_chained(sem,oper); am (b27) ; end; rl w3 +6 ; al w2 0 ; buf:= 0; <* has been removed *> jl x3 ; end; e. \f ; procedure entry timer_message; ; ; sends a delay-message to 'clock'. ; ; call return ; w0: - unchanged ; w1: - destr. ; w2: - buf or 0 ; w3: link current_coroutine b.j5 w. c116: am (b27) ; begin rs w3 +14 ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_testoutput(1<15); jl. w3 h4. ; 3<22+1<15 ; j0: rl w3 b28 ; al w1 x3+a626 ; mess:= cur.ext2.delaymess; al w2 x3+a630 ; ref:= cur.ext2.answer_descr; al w3 x3+a616 ; name:= <:clock:>; jd 1<11+16 ; sendmessage(name,mess,ref,result); rl w3 (b28) ; am (b27) ; rl w1 +14 ; jl x1 ; end; e. \f ; procedure timerscan(ref,buf); ; ; this procedure is called from 'check_event_queue' when an answer arrives ; from 'clock'. the timer queue is inspected and coroutines which time out ; are started with result = timeout. after the inspection a delay-message is ; sent to 'clock'. ; ; call return ; w0: - destr. ; w1: ref destr. ; w2: buf 0 (the message buffer is removed) ; w3: link link b.j5,i5 w. c117: am (b27) ; begin rs w3 +16 ; ext1(16):= link; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate_test_output(1<16); jl. w3 h4. ; 3<22+1<16 ; j0: rl w3 b28 ; al w1 x3+a566 ; <* release messagebuffer *> jd 1<11+18 ; wait_answer(cur.ext2.test_mess_area,buf); j4: ; al w2 x3+a552 ; corout:= first in timer queue; j1: rl w2 x2 ; while corout <> timer queue head do j3: sn w2 x3+a552 ; begin jl. j2. ; corout:= next(corout); rl w1 x2+4 ; with corout do sh w1 0 ; begin jl. j1. ; if timer > 0 then al w1 x1-1 ; begin rs w1 x2+4 ; se w1 0 ; timer:= timer-1; jl. j1. ; if timer = 0 rl w0 x2 ; then start(corout,prio,timeout); am (b27) ; rs w0 +18 ; al w2 x2-2 ; rl w0 x2+a698 ; end; al w1 0 ; end; jl. w3 c100. ; am (b27) ; rl w2 +18 ; rl w3 b28 ; jl. j3. ; end while; j2: jl. w3 c116. ; timer_message; am (b27) ; rl w3 +16 ; link:= ext1(16); al w2 0 ; buf:= 0; <* has been removed *> jl x3 ; end; e. \f ; procedure entry cregretmessage(buf); ; ; this procedure is used to regret a message sent by csendmessage, i. e. the ; monitor procedure 'regretmessage' is called and the corresponding message ; buffer extension is released. ; ; call return ; w0: - destr. ; w1: - destr. ; w2: buf buf ; w3: link current_coroutine b.j5 w. c118: am (b28) ; begin rs w3 (0) ; am (b28) ; rl w3 +a544 ; sn w3 0 ; if testoutput active jl. j0. ; then generate test_output(1<17); jl. w3 h4. ; 3<22+1<17 ; j0: jd 1<11+82 ; regretmessage(buf); rl w1 x2-2 ; ref:= buf.ref; rl w3 b28 ; ext:= next(message_buffer_ext_head); al w0 x1-2 ; next(message_buffer_ext_head):= ref; rx w0 x3+a588 ; next(ref):= ext; rs w0 x1-2 ; rl w3 (b28) ; jl (x3) ; end; e. \f ; procedure entry testout ; ; ; this procedure creates a user test record defined by the registers ; as follows: ; ; call return ; w0: testrecord ident unch. ; w1: start address unch. ; w2: no_of_halfwords unch. ; w3: link current coroutine b.j5 w. c119: am (b28) ; begin rs w3 (0) ; am (b28) ; if test output active then rl w3 +a544 ; sn w3 0 ; jl. j0. ; jl. w3 h4. ; generate testoutput(1<18) 3<22+1<18; j0: rl w3 (b28) ; jl (x3) ; end; e. \f ; procedure generate testoutput(testkind); ; ; this procedure creates a testrecord or initiates the creation of a test ; record as follows: ; ; 1) if word 128 in monitor table is set ( <> 0 ) a message defining the ; test record is sent to the coroutine test output process. ; ; 2) otherwise a test record is written in the cyclical test output buffer. ; formats in the cyclical buffer: ; ; user test record coroutine function (signal etc.) ; +0 testkind testkind ; +2 time1 time1 ; +4 time2 time2 ; +6 user_ident,length w0 ; +8 test information w1 ; +10 - " - w2 ; +12 - " - coroutine ident ; +14 etc. address of current coroutine ; ; testkind values: ; 1<0 : start ; 1<1 : wait ; 1<2 : pass ; 1<3 ; inspect ; 1<4 : csendmessage ; 1<5 : cwaitanswer ; 1<6 : answer_arrived ; 1<7 : signal_sem-signal_binary ; 1<8 : wait_semaphore ; 1<9 : signal_chained ; 1<10 : inspect_chained ; 1<11 : wait_chained ; 1<12 : sem_sendmessage ; 1<13 : sem_answer_proc ; 1<14 : message_received ; 1<15 : timer_message ; 1<16 : timer_scan ; 1<17 : cregretmessage ; 1<18 : user defined testrecord ; ; call return ; w0: - unchanged ; w1: - unchanged ; w2: - unchanged ; w3: link current coroutine b.j10,i5 w. h4: am (b27) ; begin rs w3 +8 ; ext1(8):= link; rl w3 b27 ; ds w1 x3+22 ; save working registers rs w2 x3+24 ; rl w1 x3+8 ; rl w3 (b28) ; rl w0 x3+a716 ; if testkind is included in curr.corout.testm then la w0 x1 ; begin sn w0 0 ; jl. j6. ; rl w3 b141 ; if core(128) <> 0 then sn w3 0 ; begin jl. j1. ; rl w3 b28 ; al w1 x3+a566 ; rs w0 x1 ; cur.ext2.testmess(1):= testkind; al w3 x3+a556 ; jd 1<11+16 ; send message(testmes,cmontest); jd 1<11+18 ; wait answer; jl. j6. ; else j1: rl w3 b28 ; begin ! create record in cyclical buffer ! am (b27) ; if testkind = user record rl w1 +24 ; se. w0 (i0.) ; then length:= length(user record) al w1 8 ; else length:= 8; rl w2 x3+a540 ; if (start(next record)+length+8) > wa w1 x3+a540 ; top(test buffer) then al w1 x1+8 ; begin sh w1 (x3+a542) ; jl. j2. ; al w1 0 ; insert dummy end record rs w1 x2 ; rl w2 x3+a538 ; start(next record):= start(test buffer); ; end; j2: rs w0 x2 ; insert testkind in record rl w3 0 ; jd 1<11+36 ; get clock ds w1 x2+4 ; insert time in test record sn. w3 (i0.) ; if testkind = coroutine function then jl. j3. ; begin rl w3 (b28) ; am (b27) ; dl w1 +22 ; ds w1 x2+8 ; insert w0,w1 am (b27) ; rl w0 +24 ; rs w0 x2+10 ; insert w2 rl w0 x3+a718 ; ds w0 x2+14 ; insert coroutine_ident, addr. of curr,corout. al w2 x2+14 ; jl. j5. ; end j3: rl w3 b27 ; else dl w1 x3+22 ; begin <* user defined test record *> rl w3 x3+24 ; hs w0 x2+6 ; insert user identification hs w3 x2+7 ; insert length al w2 x2+8 ; j4: rl w0 x1 ; transfer test information rs w0 x2 ; al w3 x3-2 ; sh w3 0 ; jl. j5. ; al w2 x2+2 ; al w1 x1+2 ; jl. j4. ; end; ; end; j5: rl w3 b28 ; al w2 x2+2 ; update start(next record) in procees ext2 rs w2 x3+a540 ; j6: rl w3 b27 ; dl w1 x3+22 ; load working registers rl w2 x3+24 ; rl w3 x3+8 ; return:=ext1(8); jl x3+2 ; end; i0: +1<18 ; testkind f. user test record e. e. z. ; procedure errorlog. ; called from driver when a abnormal result is received, ; or when a internal interupt is received. ; if the external process errorlog has received a buffer this procedure ; will produce a record. the format of the record depends on ; the kind of error. ; the procedure is called with w1 holding the process description of the failed ; process e.g. the current internal process in case of a internal ; interupt or the physical disc in case of a discerror. ; ; ; ; call return ; w0 unchanged ; w1 failed process unchanged ; w2 link unchanged ; w3 unchanged b. i15 , j20 w. g66 :ds. w1 i0. ; save all registers ds. w3 i1. ; dl w1 b19 ; save current buffer , current receiver ds. w1 i3. ; rl w1 b30 ; set current receiver := errorlog rs w1 b19 ; jl w3 g64 ; examine queue jl. j15. ; +0 : queue empty ; return rl w2 b30 ; +2 : mess in queue al w2 x2+a70 ; c. w2= errorbuffer start al w3 0 ; rs w3 x2 ; dl w1 b13+2 ; insert time in errorbuf ds w1 x2+32 ; rl. w1 i0. ; record type : goto case kind of rl w0 x1+a10 ; hs w0 x2+0 ; sn w0 0 ; jl. j0. ; internal interupts, monitor call break sn w0 62 ; jl. j1. ; discerror se w0 86 ; sn w0 88 ; jl. j3. ; fpa transmission error se w0 84 ; sn w0 85 ; jl. j5. ; subprocesserror jl. j15. ; otherwise ... return ; ; before exit the registers contain ; w0 : kind.failed process ; w1 : process description of failed process ; w2 : errorbuffer start ; ; j0: dl w0 x1+a11+2 ; internal interupt . ds w0 x2+4 ; move name.failed process dl w0 x1+a11+6 ; ds w0 x2+8 ; al w2 x2+10 ; al w0 8 ; copy from process descr. w0,w1 w2 w3 al w1 x1+a28 ; status ic(logical) cause sb jl. w3 j9. ; rl w3 x1-a28+a182; copy last two instructions wa w3 x1-a28+a33 ; dl w1 x3-2 ; ds w1 x2-10+28 ; al w3 32 ; save size-2 of record and jl. j13. ; goto copy errorbuf ; ; j1: rs w1 x2+28 ; discerror rl w3 x1+a244 ; copy i-o result, rem char.std status rl w0 x1+a231 ; ds w0 x2+20 ; dl w0 x1+100 ; status: sum of all statusbits ds w0 x2+24 ; e.g. std. status "or" statusarea1 rl w3 x1+102 ; ( "or" statusarea2) rs w3 x2+26 ; rl. w1 i2. ; copy from "current" buffer dl w0 x1+a151 ; mess(1) - mess(2) ds w0 x2+12 ; mess(4) - mess(5) dl w0 x1+a153+2 ds w0 x2+16 ; rl w1 x1+a141 ; get process descr. rec sh w1 (b3) ; if receiver defined then jl. j2. ; dl w0 x1+a11+2 ; ds w0 x2+4 ; dl w0 x1+a11+6 ; ds w0 x2+8 ; j2: al w3 32 ; save size-2 of record jl. j13. ; goto copy errorbuf ; ; j3: zl w0 x1+44 ; fpa transmission error wa w0 x1+42 ; copy from failed process ds w1 x2+28 ; startbyte, statusbyte dl w0 x1+a11+2 ; name ds w0 x2+4 dl w0 x1+a11+6 ; ds w0 x2+8 ; dl w0 x1+a231 ; std status ds w0 x2+12 ; dl w0 x1+a233 ; ds w0 x2+16 dl w0 x1+28 ; status from first sense ds w0 x2+20 ; dl w0 x1+32 ; ds w0 x2+24 ; dl w0 x1+36 ; copy status from second sense ds w0 x2+36 ; dl w0 x1+40 ; ds w0 x2+40 ; al w0 18 ; copy channelprogram wa w1 x1+a226 ; al w2 x2+42 ; jl. w3 j9. ; al w3 74 ; save size-2 of record jl. j13. ; goto copy errorbuf ; ; j5: rs w1 x2+28 ; subprocess error hl w0 x1+36 ; copy from subprocess hs w0 x2+1 ; subkind dl w0 x1+a11+2 ; ds w0 x2+4 ; name dl w0 x1+a11+6 ; ds w0 x2+8 dl w0 g29 ; copy first four words of mess from save area ds w0 x2+12 ; dl w0 g30 ; ds w0 x2+16 ; dl w0 g21 ; copy the answer from std answer area ds w0 x2+20 ; dl w0 g23 ds w0 x2+24 ; rl w3 g24 ; rs w3 x2+26 ; al w3 32 ; save size-2 jl. j13. ; goto copy buf ; ; ; ; help procedure move doublewords. ; move the specified number if words as doublewords. ; odd number of words will cause one extra word to be moved. ; call return ; w0: no of words destroyed (zero) ; w1: from adr unchanged ; w2: to adr unchanged ; w3: link unchanged ; ; j9: ds.w2 i13. ; ds. w0 i15. ; j10: dl w0 x1+2 ; ds w0 x2+2 ; al w1 x1+4 ; al w2 x2+4 ; rl. w3 i15. ; decrease word count al w3 x3-2 ; rs. w3 i15. ; sl w3 1 ; jl. j10. ; dl. w2 i13. ; restore registers dl. w0 i15. ; jl x3 ; ; ; 0 ; from adr i13: 0 ; to adr 0 ; link i15: 0 ; word count ; ; j12: rl w1 4 ; copy direct: setup parameters to procedure move doublewors rl. w2 i10. ; rl w2 x2+a151 ; first adr in messbuf wa. w2 i9. ; + no of hw already moved al w0 34 ; record size: 34 hw jl. w3 j9. ; al w1 34 ; goto update no of hw moved rl. w2 i10. ; jl. j14. ; ; ; j13: rl w2 b30 ; copy errorbuffer (general copy) rl w1 x2+a54 ; check buffer. al w0 0 ; if buffer<> last used buffer then se. w1 (i10.) ; set bufferadr and clear relative adr. ds. w1 i10. ; rl w0 x1+a150 ; change operation to odd wa. w0 i11. ; to use gen. copy rs w0 x1+a150 ; al w2 x2+a70 ; zl w1 x2+0 ; if kind of record = internal then sn w1 0 ; goto move direct. jl. j12. ; (we are in monitor mode and cant use general copy) wa w3 4 ; else store first and last adr ds. w3 i8. ; al. w1 i6. ; rl. w2 i10. ; setup parameters and call jd 1<11+84 ; general copy se w0 0 ; if not ok then !!!!! jl. j11. ; j14: wa. w1 i9. ; (copy direct continues here. w1=no of hw moved rs. w1 i9. ; w2= mess buf adr) rl w0 x2+a150 ; change operation to even ws. w0 i11. ; makes it possible to regret the mess. rs w0 x2+a150 ; wa w1 x2+a151 ; update relative adr and check restsize in buf al w1 x1+74 ; sh w1 (x2+a152) ; if restsize < max record size then jl. j15. ; deliver answer else goto return j11: al w0 1 ; deliver result 1 rl. w1 i9. ; rl w3 b30 ; check kind.record rl w3 x3+a70 ; if kind.record =internal then se w3 0 ; deliver answer else jl. j16. ; deliver result rs w0 x2+a141 ; set result in buffer ds w1 x2+a151 ; no of bytes =sum of bytes moved jl w3 d15 ; deliver answer (continue with restore parameters ) j17: al w0 0 ; reset special watched receiver rs w0 b32 ; jl w3 g64 ; if more messages in queue jl. j15. ; then set next special watched receiver adr rl w0 x2+a153 ; rs w0 b32 ; (placed in connection to "deliver result" ) j15: dl. w1 i3. ; return : restore all parameters ds w1 b19 ; restore current receiver and buffer dl. w1 i0. ; restore all registers dl. w3 i1. ; jl x2 ; j16: ds w1 g21 ; deliver result jl w3 g19 ; jl. j17. ; restore parameters ; ; ; parameter list : ; 0 ; save w0: i0: 0 ; save w1: pd.failed process 0 ; save w2: link i1: 0 ; save w3: i2: 0 ; save current buffer i3: 0 ; save current receiver i6: 2<1+1 ; parameters for general copy: funtion i7: 0 ; first adr in errorbuf i8: 0 ; last adr in errorbuf i9: 0 ; relative start to mess buf adr (no of hw moved) i10: 0 ; buffer adr i11: 1<12 ; change op even-odd e. ; end of errorlog entry b.i0 ; begin w.i0: al. w2 i0. ; make room: jl x3+0 ; autoloader(end monitor procedures); jl. i0. ; after loading: j0=k - b127 + 2 k = i0 ; goto make room; e. ; end e. ; end of monitor segment \f ; segment 3: external processes s. k = k, h132 w.b127=k, g70, k=k-2 m. driver proc save area - g,b names, reg dump (18, 16 hw) ; common driver central logic ; compatible with old conventions ; save area for std g-names, b-names b086: 0,r.5 ; g20, g21, g22, g23, g24 0, r.3 ; b18, b19, work b085 ; b20 = address of wait-next action ; interrupt routine b087:0, r.a180>1 ; save area for registers jl. 0 ; wait forever c.-1 al. w1 b086. ; rl w3 x1 ; print the whole save area and the registers jd 1<11+34; al w1 x1+2 ; se. w1 b087.+a180; jl. -8 ; rl. w3 b087.+10; w3 := old ic + 2; bz w0 x3-2 ; jd 1<11+28; print(instruction code incl regs); bl w0 x3-1 ; jd 1<11+28; print(address part); bl w0 x3-2 ; h. se w0 , ks ; if instruction = <ks> then w. jl. b085. ; dl. w1 b087.+2; restore all registers dl. w3 b087.+6; xl. b087.+9; jd. (b087.+10; and return disabled; ; else goto wait next; z. b. e10, r5 w. b. i0 w. r5: am 5-3 ; result 5: r3: am 3-2 ; result 3: r2: am 2-1 ; result 2: r1: am 1-0 ; result 1: r0: al w0 0 ; result 0: finis the call: e0: ; finis with prepared result: ; entry: w0=result al. w1 0 ; answer area := dummy; e1: rl. w2 i0. ; mess buff addr := saved mess buf; jd 1<11+22; send answer; b085:al w2 0 ; wait next: jd 1<11+24; wait event; b088:am (0) ; result: 0=message, 1=answer, jl. +2 ; 2=interrupt, 4=immediate message jl. e2. ;+2: message or answer: jd x2 ;+4: interrupt: goto service address; ;+6: immediate message: ; immediate message is a call of ; initialize process ; reserve process ; release process rs. w2 i0. ; save(buf); rl w0 x2+8 ; switch := operation(buf); rl w1 x2+6 ; internal := sender(buf); sh w1 0 ; if sender <= 0 then jl. e0. ; goto finis, undef result; (call is regretted) ac w2 (x2+4) ; proc := -receiver(buf); al w2 x2-1 ; (i.e. positive, even) am (0) ; jl. (+2) ; goto case switch of: e5 ; switch=0: initialize process e6 ; switch=2: reserve process r0 ; switch=4: release process ( finis the call ) i0: 0 ; saved message buffer address ; message or answer: ; entry: w0=result from wait event, w2=buf e2: rl w1 x2+6 ; sender := sender(buf); jd 1<11+26; get event(buf); (buffer contents is irrell if answer) se w0 1 ; if result from wait event = 0 then jl. e3. ; goto message; ; answer: ; entry: w0=1, w1=sender ; skip the answer, unless message originated from a terminal sl w0 (x1+a10) ; if kind(sender) = 0 then jl. b085. ; goto wait next; (maybe testoutput message...) bz w3 x1+a71+1 ; al w3 x3+1 ; increase(attention buffer claim(terminal)); hs w3 x1+a71+1 ; jl. b085. ; goto wait next; ; message: ; entry: w1=sender, w2=buf e3: rl w3 b1 ; w3 := cur; bz w0 x3+a19 ; increase (bufclaim(cur)); ba. w0 1 ; hs w0 x3+a19 ; i.e. unclaim the buffer again... ac w3 (x2+4) ; proc := -receiver(buf); (positive) rs w3 x2+4 ; receiver(buf) := proc (i.e. positive); ds w3 b19 ; save(buf,proc) in std locations; ; before exit to the different drivers, the registers contain: ; w0=undef, w1=sender, w2=buf, w3=proc am (x3+a10) ; jd. (+2) ; goto case kind(proc) of: h3 ; (0: internal process h4 ; 2: interval clock h5 ; 4: backing store area g2 ; 6: g2 ; 8: g2 ; 10: g2 ; 12: g2 ; 14: g2 ; 16: g2 ; 18: g2 ; 20: g2 ; 22: g2 ; 24: g2 ; 26: g2 ; 28: g2 ; 30: g2 ; 32: g2 ; 34: g2 ; 36: g2 ; 38: g2 ; 40: g2 ; 42: g2 ; 44: g2 ; 46: g2 ; 48: g2 ; 50: g2 ; 52: h7 ; 54: errorlog process h22 ; 56: remoter process g2 ; 58: g2 ; 60: h6 ; 62: disc (logical- and physical disc) h3 ; 64: pseudo process g2 ; 66: g2 ; 68: g2 ; 70: h72 ; 72: rc8602 (sscir) h74 ; 74: rc8602 (isrpy) h76 ; 76: rc8601 (sscir) h78 ; 78: rc8601 (isrpy) h80 ; 80: mainproc(fpa) g2 ; 82: hostproc(fpa) h84 ; 84: subproc(fpa) g2 ; 86: receiver(fpa) g2 ; 88: transmitter(fpa) h90 ; 90: host); h3=g6 ; internal process, pseudo process g2=g3 ; not defined e. ; end common part of central logic ; initialize and reserve process: ; entry conditions: w0 = switch, w1 = internal, w2 = proc b. i51 w. e5: ; initialize process: switch = 0 e6: rs. w0 i9. ; reserve process: switch = 2 am (x2+a10) ; jl. (2) ; goto case kind(proc) of: i30 ; (0: internal process, i31 ; 2: interval clock, i11 ; 4: backing store area, r3 ; 6: r3 ; 8: r3 ; 10: r3 ; 12: r3 ; 14: r3 ; 16: r3 ; 18: r3 ; 20: r3 ; 22: r3 ; 24: r3 ; 26: r3 ; 28: r3 ; 30: r3 ; 32: r3 ; 34: r3 ; 36: r3 ; 38: r3 ; 40: r3 ; 42: r3 ; 44: r3 ; 46: r3 ; 48: r3 ; 50: r3 ; 52: r3 ; 54: i34 ; 56: remoter process r3 ; 58: r3 ; 60: i17 ; 62: disc (logical- and physical discs) i30 ; 64: pseudo processes r3 ; 66: r3 ; 68: r3 ; 70: i51 ; 72: rc8602 (sscir) (reservation not allowed ) r3 ; 74: rc8602 (isrpy) (does not exist) i48 ; 76: rc8601 (sscir) i48 ; 78: rc8601 (isrpy) i36 ; 80: mainproc(fpa) i37 ; 82: hostproc(fpa) i38 ; 84: subproc(fpa) i39 ; 86: receiver(fpa) i40 ; 88: transmitter(fpa) i41 ; 90: host); i9: 0 ; saved switch i11: ; backing store area: jl w3 d102 ; check user(internal, proc); jl. r3. ;+2 not user: goto result 3; jl w3 d113 ; check any reserver(internal, proc); jl. r1. ;+2 other reserver: goto result 1; jl. r0. ;+4 internal is reserver: goto result 0; rl. w0 i9. ; sn w0 0 ; if initialize then jl. r0. ; goto result 0; dl w0 x2+a49 ; w3w0 := interval(proc); al w3 x3+1 ; sh w0 (x1+a44) ; if upper(proc) > upper(max(internal)) or sh w3 (x1+a44-2) ; lower(proc) < lower(max(internal)) then jl. r2. ; goto result 2; jl. r0. ; goto include reserver; i36: ; mainproc(fpa): jl w3 d102 ; check user(internal, proc); jl. r2. ;+2 not user: goto result 2; jl w3 d113 ; check any reserver(internal, proc); jl. r1. ;+2 other reserver: goto result 1; jl. r0. ;+4 internal is reserver: goto result 0; ;+6 rl w3 b3 ; i50: al w3 x3+2 ; for dev:=0 step 1 until found do se w2 (x3) ; if proc(dev)=proc then found; jl. i50. ; rs. w3 i46. ; rl w2 x3+2 ; rec:=proc(dev+1); jl w3 d113 ; check any reserver(internal, rec); jl. r1. ;+2 other reserver: goto result 1; am 0 ;+4 internal is already reserver: rl. w3 i46. ; rl w2 x3+4 ; trm:=proc(dev+2); jl w3 d113 ; check any reserver(internal,trm); jl. r1. ; if other reserver then goto result 1; am 0 ; if already res. then goto result 0; jl. i49. ; goto set result; i39: ; receiver(fpa): i40: ; transmitter(fpa): jl w3 d102 ; check user(internal, proc); jl. r2. ;+2 not user: goto result 2; jl w3 d113 ; check any reserver(internal, proc); jl. r1. ;+2 other reserver: goto result 1; jl. r0. ;+4 internal is reserver: goto result 0; ;+6 rl w2 x2+a50 ; main:=main(proc); jl w3 d113 ; check any reserver(internal, main); jl. r1. ;+2 other reserver: goto result 1; am 0 ;+4 internal is already reserver: jl. i49. ; goto setresult; i29: ; reserve: jl w3 d113 ; check any reserver(internal, proc); jl. r1. ;+2 other reserver: goto result 1; jl. r0. ;+4 internal is reserver: goto result 0; ;+6 i49: al w0 0 ; setresult: result := 0; al. w1 1 ; w1 := odd, i.e. transform initialize to reserve; jl. e1. ; goto include reserver; i38: ; subproc(scc): jl w3 d102 ; check user(internal, proc); jl. r2. ;+2 not user: goto result 2; jl w3 d113 ; check any reserver(internal, proc); jl. r1. ;+2 other reserver: goto result 1; am ;+4 internal is already reserver: al w3 1 ; external state(proc) := initialized; hs w3 x2+a56+1 ; rl. w0 i9. ; bl w3 x2+a63 ; if subkind(proc) <> typewriter sn w0 0 ; or reserve process then se w3 8 ; am 1 ; make w1 odd; i.e. indicate reserve... al. w1 0;here ; else w1 = even; al w0 0 ; result := 0; jl. e1. ; goto include reserver; i17: ; disc driver: jl w3 d102 ; check user(internal,proc); jl. r2. ; if not user then goto result 2; jl w3 d113 ; check any reserver(internal,proc); jl. r1. ; if other reserver then goto result 1; jl. r0. ; if already res. then goto result 0; rl. w0 i9. ; sn w0 0 ; if switch = reserve then jl. i45. ; begin rl w2 x2+a50 ; main:= mainproc.proc; sn w2 0 ; if main <> 0 then jl. i42. ; begin c. logical driver; jl w3 d113 ; check any reserver(internal,main); jl. r1. ; if other res. then goto result 1; jl. r0. ; if already res. then goto result 0; jl. i45. ; end else i42: rs. w2 i46. ; begin c. physical driver; rl w2 b4 ; i:= addr of 1st device in nametab; i43: rs. w2 i47. ; repeat rl w2 x2+0 ; proc:= nametable(i); rl w3 x2+a10 ; rl w0 x2+a50 ; sn w3 62 ; if kind.proc = 62 se. w0 (i46.) ; and mainproc.proc = main then jl. i44. ; begin c. logical driver; jl w3 d113 ; check any res.(internal,proc); jl. r1. ; if other then goto result 1; jl. i44. ; end; i44: am. (i47.) ; al w2 2 ; i:= i + 2 se w2 (b5) ; until i = 1st area in nametable; jl. i43. ; end; i45: al w0 0 ; end; result:= 0; al. w1 1 ; w1:= odd; c. change initialize to res.; jl. e1. ; goto include reserver; ; i46: 0 ; saved mainproc i47: 0 ; saved nametable address i48: ; rc8601: jl w3 d102 ; check user(internal, proc); jl. r2. ; not user: goto result2; jl w3 d113 ; check any reserver(internal, proc); jl. r1. ; other reserver: goto result1; am ; allready reserver: jl. i49. ; goto deliver answer; i30 = e0 ; internal process ; pseudo process i31 = e0 ; interval clock i34 = e0 ; remoter process i37 = e0 ; subhost process i41 = e0 ; host process i51=e0 ; rc8602 e. ; end of initialize/reserve process e. ; end of driver central logic \f ; pej 23.01.78 clock driver ; ----------------------------------------------------------------- ; c l o c k d r i v e r c o d e ; ----------------------------------------------------------------- ; this section contains the code executed by driverproc for ; processing messages to the clockdriver and for executing other ; actions related to the real time clock. ; ; messages have the following format: ; ; delay 0<12+mode ; seconds or interval(0:23) ; interval(24:47) ; ; wait for clockchange 2<12+mode ; seconds or interval(0:23) ; interval(24:47) ; ; wait for power restart 4<12+mode ; seconds or interval(0:23) ; interval(24:47) ; ; a maximum delay is specified by seconds or interval equal to -1. ; ; mode consists of a sum of one or more of following values: ; ; 2 time interval in 0.1 msecs. if not used then seconds. ; 4 real time delay, i.e. the message is returned when the ; clock reaches the value: ; curr value of real time clock + delay ; if not used, an effective delay is specified, i.e. the ; message will be returned when it has been in the event ; queue as long as specified. ; ; the answer has the following format: ; statusword, bit0 = intervention (see below) ; 0 ; 0 ; ; messages received are linked to the clock process in ascending ; order with respect to calculated time for expiration of delay. ; at each clock interrupt the queue is scanned and messages which ; have reached the expiration time are returned. also at each ; clock interrupt the timeout queue of devices is scanned. ; timers which have run out cause the clock to reset the device ; with timeout status. ; ; after power restart all devices are reset with power restart ; result and messages waiting for power restart are returned with ; status intervention. ; ; after a change of clock (monitor procedure set clock) messages ; waiting for clockchange are returned with status intervention. ; the same is performed at mode 4-messages if the new clockvalue ; exceeds the calculated expiration time. messages not using mode ; 4 will have the expected expiration time adjusted according to ; the clockchange and the entire message queue is resorted. m. monclock (monitor interval clock driver) b. i10, j60, a0=1<23, w. ; block including clock driver \f ; pej 23.01.78 clock driver ; m e s s a g e r e c e i v e d ; --------------------------------------------------------------- ; ; this routine is entered when driverproc receives a message for ; the clock. the message is checked and time (clockvalue) for ; expiration of delay is inserted into the buffer. h4 : dl. w1 i0. ; c. w2 = curr buf; jl w3 g16 ; check operation(mode mask,oper mask); rs. w2 i8. ; save received buffer rl w1 b19 ; check for clockchange c.w1=cur receiver jl. w3 j24. ; rl. w2 i8. ; restore buffer dl w0 x2+a152 ; delay:= interval(0:47).curr buf; bz w1 x2+a150+1 ; sz w1 2.10 ; if time in secs.mode.curr buf then jl. j10. ; begin al w0 x3+0 ; seconds:= delay(0:23); sn w0 -1 ; if seconds = -1 then goto maxdelay jl. j14. ; else delay:= seconds * 10000; wm. w0 i1. ; end; j10 : sl w3 0 ; if delay >= 0 sl w3 52 ; and delay <= 872415231 then jl. j12. ; begin c. 24 hrs + 841.5231 secs; sn w0 0 ; if delay = 0 then se w3 0 ; begin jl. j16. ; bytes:= chars:= 0; goto result 1; ds w3 g22 ; end; jl g7 ; end j12 : sn w3 -1 ; else se w3 -1 ; if delay <> -1 jl g5 ; then goto result 3 j14 : dl. w0 i2. ; else ss w0 b13+2 ; maxdelay: delay:= max clock val - time; j16 : aa w0 b13+2 ; ds w0 x2+a152 ; time.curr buf:= delay + time; ; insert the messagebuffer in eventqueue of the driver (the event ; queue is sorted after delay expiration time) and continue at ; waitnext in driverproc. please note that the messagebuffer is ; not claimed. rl w3 b20 ; jl. j50. ; insert buf(curr buf); \f ; pej 23.01.78 clock driver ; i n t e r r u p t r e c e i v e d ; --------------------------------------------------------------- ; ; this routine is entered when driverproc receives an interrupt ; operation for the clock. ; ; if a power restart has been executed, all devices are reset ; and messages queued to wait for power restart returned. c35 : al w0 0 ; c. w1 = curr receiver; al. w3 j38. ; set continue adr rx w0 b75 ; p:= after power; after power:= 0; sn w0 0 ; if p <> 0 then jl. j24. ; begin rl w2 b67 ; entry:= 1st controller tab entry; j18 : rl w3 x2+a311 ; repeat rl w1 x3+a235-a230; device:= al w0 0 ; deviceaddr.proc.entry; jd 1<11+2 ; reset device(device,power); al w2 x2+a314 ; entry:= entry + entry length se w2 (b68) ; until entry = top entry; jl. j18. ; rl w1 b19 ; buf:= al w2 x1+a54 ; addr of mess q head.curr receiver; j20 : rl w2 x2+a140 ; rep: buf:= next.buf; j22 : al. w3 j38. ; prepare continue adr sn w2 x1+a54 ; rep1: if buf<>addr mqhead.curr rec then jl. j24. ; begin bz w0 x2+a150 ; if operation.buf <> 4 se w0 4 ; then goto rep; jl. j20. ; deliver intervention(buf); al. w3 j22. ; goto rep1; jl. j51. ; end; ; end; \f ; pej 23.01.78 clock driver ; if the clock has been changed some messages may be returned ; (those waiting for clockchange and those waiting in real time ; delay). expiration time in messages waiting in effective time ; delay is adjusted and the message queue is resorted. ; called when a message or an interrupt is received ; called with w1=cur receiver and w3 holding the return adr j24 : rl w0 b15 ; c. w1 = curr receiver; lo w0 b15+2 ; sn w0 0 ; if clockchange <> 0 then jl x3 ; begin rs. w3 i9. ; save return adr al w2 x1+a54 ; sn w2 (x1+a54) ; if mess q.curr rec -,empty then jl. j36. ; begin dl w0 x1+a55 ; help q head:= ds. w0 i4. ; mess q head.curr receiver; rs w2 x1+a54 ; rs w2 x1+a55 ; mess q head.curr receiver:= empty; al. w0 i3. ; next.last.help q head:= rs. w0 (i4.) ; addr of help q head; rl. w2 i3. ; buf:= next.help q head; rs w0 x2+2 ; last.buf:= addr of help q head; j26 : sn. w2 (i5.) ; rep: if buf <> addr of help q head then jl. j36. ; begin bz w0 x2+a150 ; se w0 2 ; if operation.buf = 2 then jl. j30. ; begin j28 : jl. w3 j51. ; send: deliver intervention(buf); jl. j26. ; goto rep; j30 : dl w0 x2+a152 ; end; bz w1 x2+a150+1 ; so w1 2.100 ; if real time.mode.buf then jl. j32. ; begin ss w0 b13+2 ; if time > time.buf sx 2.1 ; then goto send; jl. j34. ; end jl. j28. ; else j32 : sn. w3 (i7.) ; se. w0 (i2.) ; if time.buf <> max clock val aa w0 b15+2 ; then time.buf:= time.buf ds w0 x2+a152 ; + clockchange; j34 : rl w0 x2+0 ; next:= next.buf; rs. w0 i6. ; jl w3 d5 ; remove(buf); c. from help q; jl. w3 j50. ; insert buf(buf); rl. w2 i6. ; buf:= next; jl. j26. ; goto rep; ; end; j36 : ld w0 -100 ; end; ds w0 b15+2 ; clockchange:= 0; rl w1 b19 ; end; jl. (i9.) ; \f \f ; pej 23.01.78 clock driver ; scan the message queue and return buffers with delays expired. j38 : rl w2 x1+a54 ; c. w1 = curr receiver; sn w2 x1+a54 ; rep: buf:= next.mess q head.curr rec; jl. j40. ; if buf = addr of mess q head.curr rec dl w0 x2+a152 ; then goto check timeouts; ss w0 b13+2 ; sx 2.1 ; if time < time.buf jl. j40. ; then goto check timeouts; rs w2 b18 ; curr buf:= buf; al. w3 j38. ; no operation; c. result 1, status 0; jl g26 ; goto rep; ; scan the timeout queue of devices and reset with timeout result ; for timers which have run out. return to waitnext in driverproc. j40 : dl w2 b13+2 ; check timeouts: dl w0 b70+2 ; timeused:= time - last inspected; ds w2 b70+2 ; last inspected:= time; ss w2 0 ; if timeused >= 1<24 se w1 0 ; then timeused:= maximum; al w2 -1 ; c. timeused is unsigned integer; al w3 b69 ; dev:= addr of timeout q head; j42 : rl w3 x3+0 ; rep: dev:= next.dev; j44 : sn w3 b69 ; rep1: if dev = addr of timeout q head je (b20) ; then goto waitnext; c. in driverproc; rl w0 x3-a242+a244; ws w0 4 ; timer.dev:= rs w0 x3-a242+a244; timer.dev - timeused; sx 2.1 ; if timer.dev was > timeused jl. j42. ; then goto rep; c. unsigned comparison; rl w1 x3-a242+a235; device:= deviceaddr.timeout op; rl w3 x3+0 ; dev:= next.dev; al w0 1 ; jd 1<11+2 ; reset device(device,timeout); jd. j44. ; goto rep1; ; variables a0>0+a0>2+a0>4 ; operation and mode masks i0 : a0>0+a0>2+a0>4+a0>6 i1 : 10000 ; constant 10000 i7 : 8.37777777 ; max clock value (doubleword) i2 : 8.77777777 ; i3 : 0 ; doubleword used for help q head i4 : 0 ; i5 : i3 ; addr of help q head i6 : 0 ; work, saved buf in loop i8 : 0 ; saved buffer from message received i9 : 0 ; return adr for j24 \f ; pej 23.01.78 clock driver ; procedure insert buf(buf); ; --------------------------------------------------------------- ; inserts a messagebuffer in the eventqueue in front of a buffer ; with higher delay expiration time. ; ; registers: call exit ; w0 destroyed ; w1 destroyed ; w2 buf unchanged ; w3 link destroyed ; ; entry: j50; return: link+0 b. i3 w. j50 : rl w1 b19 ; insert buf: al w1 x1+a54 ; elem:= endq:= rs. w1 i0. ; addr of mess q head.curr receiver; rs. w3 i1. ; i2 : rl w1 x1+0 ; rep: elem:= next.elem; sn. w1 (i0.) ; if elem <> endq jl. i3. ; dl w0 x2+a152 ; ss w0 x1+a152 ; sx 2.1 ; and time.buf <= time.elem jl. i2. ; then goto rep; i3 : rl. w3 i1. ; jl d6 ; link(elem,buf); c. return from there; ; procedure deliver intervention(buf) ; --------------------------------------------------------------- ; the procedure answers buf with status intervention and returns ; with the value of next.buf at calltime. ; ; registers: call exit ; w0 destroyed ; w1 curr receiver ; w2 buf next.buf ; w3 link destroyed ; ; entry: j51; return: link+0 j51 : rs. w3 i1. ; deliver intervention: rs w2 b18 ; curr buf:= buf; rl w0 x2+0 ; rs. w0 i0. ; save next.buf; rl w0 g49 ; rs w0 g20 ; status.i/o answer:= bit 0; al w0 1 ; result:= 1; al w1 0 ; bytes:= characters:= 0; jl w3 g28 ; no operation; rl. w2 i0. ; w2:= saved next.buf; jl. (i1.) ; return; ; variables i0 : 0 ; for saving next.buf or endq i1 : 0 ; saved link e. e. ; end of block containing clock driver \f ; remoter process. ; jr 79.02.28 m. remoter b.i4,j4 w. h22: al w1 x3+a54 ; remoter: jl w3 d6 ; link event(event queue(proc), buf); rl w1 b3 ; j0: al w1 x1+2 ; for dev:=first dev in name table until last do sl w1 (b5) ; begin jl (b20) ; rl w3 x1 ; proc:=proc(dev); rl w0 x3+a10 ; kind:=kind(proc); sn w0 18 ; main:=main(proc); jl. j1. ; if kind=18 rl w2 x3+a50 ; or (kind=84,85 and main<>0 and subkind=18) then se w0 84 ; sn w0 85 ; sn w2 0 ; jl. j0. ; bl w2 x3+a63 ; se w2 18 ; jl. j0. ; j1: rl w2 x3+a70 ; if state(proc)=2 then se w2 2 ; answer(0):=0; jl. j0. ; answer(2):=proc; al w2 0 ; deliver result(1); ds w3 g21 ; goto exit; jl w3 g18 ; end; jl (b20) ; exit: return; e. ; errorlog process ; hsi 80.07.22 m. errorlog process b. i10, j10 w. i0=1<23 i0>19 j0: i0>0 i1: 1<12 h7: al w0 0 ; reset interrupt adr. (set by remove process) rs w0 x3+a56 ; dl. w1 j0. ; check operation jl w3 g16 ; rl w2 b18 ; if buffer size < max record size rl w1 x2+a150 ; ws. w1 i1. ; rs w1 x2+a150 ; make operation even. ( allowing it to be regertted) rl w1 x2+a151 ; then send answer: unintelligble al w1 x1+74 ; sh w1 (x2+a152) ; else link operation and retur to driverproc jl. j1. ; ld w1 -100 ; buffer too small : send answer ds w1 g22 ; al w1 8 ; rs w1 g20 ; status: 1 shift 3 jl g5 ; j1: jl w3 g17 ; link up (return if first in queue ) rl w0 x2+a153 ; if first in queue then rs w0 b32 ; set pd of special watched receiver jl (b20) ; return via wait event in driverproc e. ; rc8601 driver. ; jr, 78.04.28 c.(:a80>11a.1:)-1 m. rc8601/02 (cdc1604/gier emulator) b.i15,m6,p6,s6 w. ; the rc8601 and rc8602 are a rc800 cpu used for emulating the cdc 1604 and gier. ; the device responds two devicenumbers, and it is then controlled ; from two external processes - ; sscir, stop-start control and io-request, ; and ; isrpy, io-status reply. ; these processes are working totally independent, but as they should be ; driven in almost the same way they are using the same driver-code. ; ; the processes accept the operations- ; sscir : sense 0<12+0 , dummy , dummy ; autoload 1<12+0 , base addr, dummy (rc8601) ; 1<12+0 , first , last (rc8602) ; restart 2<12+0 , dummy , dummy ; 3<12+0 , first , last (rc8602) ; isrpy: (sense 0<12+0 , dummy , dummy ;only rc8601(stop 2<12+0 , dummy , dummy ; (ready 4<12+mode, dummy , dummy , channelnumber ; where ; base addr-448, base addr+131072 must be inside the sender process, ; and channelnumber <256, ; and ; mode holds any combination of the mode bits ; 1<0 channel ready ; 1<1 equipment ready ; 1<2 equipment error ; ; the format of the answer- ; event status ; function ; unitno<18+exf addr (only autoload) ; (io-result) ; where ; event status is the status delivered from the hardware, ; and ; function -2 power up ; -1 monitor timeout ; 0 stopped ; 1 ok after immidiate operation ; 2 error stop ; 3 exfer request ; ; format of the privat part of the process description- s0=a56+2 ; current sender ident. bit s1=s0+2 ; state s2=s1+2 ; stopped(sender) (only sscir) ; state - ; 0 device ready ; 2 sscir busy with sense operation ; 4 sscir busy with autoload operation ; 6 sscir busy with rc8601 restart operation ; 8 sscir busy with rc8602 restart operation ; 10 isrpy busy with sense operation ; 12 isrpy busy with stop operation ; 14 isrpy busy with ready operation ; ; stopped - ; = 0 running ; <> 0 stopped ; ; parameters: p0=76 ; kind of sscir process p1=78 ; kind of isrpy process p2=-448 ; rel first (start of sim area relative to base addr) p3=131072 ; rel last (last of sim area relative to base addr) ; channelprogram: i0: 0<12+0<8+0 ; address code (sender), operation 0 ; base addr 0 ; channelnumber 15<8 ; stop 0 ; dummy i11: 0 ; timeout (in units of 0.1 millisec) i1: p3 ; a0=1<23 a0>0+a0>1+a0>2+a0>3 ; mask0 i2: a0>0 a0>0+a0>2+a0>4 ; mask1 i3: a0>0 a0>0+a0>2+a0>4 ; mask2 i4: a0>1+a0>2+a0>3+a0>4+a0>5+a0>6+a0>7+a0>8+a0>9+a0>10+a0>11+a0>12+a0>13+a0>14+a0>15 ; table concerning channel program. i5=k-2, 2<12+0<8, 0<12+1<8, 0<12+3<8, 0<12+1<8, 2<12+0<8, 0<12+1<8, 0<12+3<8 i6=k-2, 12, 0, 1, 0, 12, 1, i7: 0 i12: 120*10000 ; timeout f. 8601 i13: 15*10000 ; timeout f. 8602 ; dummy status area. i8: 0, r.4 ; i9: 1<3 ; ; start. b.j6 w. h76: jl w3 g15 ; start(sscir): check reservation; h72: bz w3 x2+8 ; if rc8602 then skip user/reserver check; ls w3 1 ; index:=operation*2+2; al w3 x3+2 ; jl. j0. ; goto checkmess; h78: jl w3 g15 ; start(isrpy): check reservation; bz w3 x2+8 ; index:=operation+10; al w3 x3+10 ; goto checkmess; ; check message. ; the message buffer is checked and the content is changed to - ; mess+8 command, mode(mess) ; +10 first address ; +12 last address ; +14 channelnumber(mess) ; +16 address code<12+command<8+mode ; +18 address ; +20 character count ; +22 index j0: ; checkmess: rs w3 x2+22 ; mess(22):=index; sl w3 2 ; if index<2 sl w3 14+1 ; or index>14 or (isrpy and rc8602) then h74: jl g5 ; goto result3; jl. (x3+i10.) ; goto case index of i10=k-2 j1 ; (check1, 2: sscir-sense j2 ; check2, 4: sscir-autoload j4 ; check4, 6: sscir-restart j2 ; check2, 8: sscir-restart (rc8602) j1 ; check1, 10: isrpy-sense j4 ; check4, 12: isrpy-stop j3 ; check3); 14: isrpy-ready j1: al. w1 i8. ; check1: addr:=addr(dummy status area); jl. j5. ; goto cont; j2: rl w1 b19 ; check2: rl w0 x1+a10 ; se w0 p0 ; if proc=rc8601 then jl. j6. ; al w0 1 ; size:=1; rs. w0 x3+i6. ; rl w1 x2+10 ; al w0 x1+p2 ; wa. w1 i1. ; first:=first(mess)+rel first; ds w1 x2+12 ; last:=first(mess)+rel last; ws. w1 i1. ; addr:=first(mess); jl. j5. ; goto cont; j6: al w1 2 ; else wa w1 x2+12 ; ws w1 x2+10 ; size:=2+last-first; al w0 x1 ; ls w0 -1 ; size:=size.2*3; wa w1 0 ; rs. w1 x3+i6. ; rl w1 x2+10 ; addr:= first(mess) jl. j5. ; goto cont; j3: rl w0 x2+14 ; check3: sl w0 1 ; if channelno<1 sl w0 1<8 ; or channelno>=256 then jl g5 ; goto result3; rs. w0 i7. ; char count(10):=channelno; j4: am (x2+6) ; check4: rl w1 +a17 ; addr:=first(core(sender)); rs w1 x2+10 ; first address:=address; al w0 x1+256 ; last address:=address+max size(:max channelnumber); rs w0 x2+12 ; ; w1: addr, w2: buffer, w3: index. j5: rl. w0 x3+i5. ; cont: ba w0 x2+9 ; command:=command(index)+mode(mess); ds w1 x2+18 ; mess(16:18):=command, addr; rl. w0 x3+i6. ; char count:=char count(index); rs w0 x2+20 ; mess(20):=char count; dl. w1 i2. ; mask:=mask0; sl w3 10 ; if index>=10 then dl. w1 i3. ; mask:=mask1; sl w3 14 ; if index>=14 then dl. w1 i4. ; mask:=mask2; jl w3 g16 ; check operation; rl w1 b19 ; jl w3 g17 ; link operation; ; goto next; e. ; execute operation. b.j4 w. m0: rl w3 x2+a142 ; next: get current sender sh w3 0 ; if -parent then ac w3 x3 ; sender := - sender rl w3 x3+a14 ; get ident(sender); rs w3 x1+s0 ; store current sender ident in device descr; rl w3 x2+22 ; get index; sl w3 4 ; if -,operation = sense sl w3 10 ; and kind(proc) = sscir (<=>index < 8) then jl. j1. rl w0 x1+s2 se w3 4 ; if index(mess) = autoload then jl. j0. lo w0 x1+s0 ; stopped(sender) := 0 lx w0 x1+s0 rs w0 x1+s2 ; else jl. j1. j0: so w0 (x1+s0) ; if stopped(sender) then jl. j1. al w0 0 rs w0 g20 ; status (mess) := 0 rs w0 g21 ; function(mess):=0; rs w0 g23 ;*** jl. m3. ; goto result1; j1: rs w3 x1+s1 ; state:=index; al w0 2.111<8 ; la. w0 x3+i5. ; operation(mess):=command; ls w0 -8 ; hs w0 x2+8 ; ; setup channelprogram. dl w0 x2+18 ; command(chpg):=command(mess); ds. w0 i0.+2 ; addr(chpg):=addr(mess); rl w0 x2+20 ; char count(chpg):=char count(mess); rs. w0 i0.+4 ; rl w3 b19 ; rl w3 x3+a10 ; timeout: rl. w0 i12. ; se w3 p0 ; if kind(rec) = rc8601 then sn w3 p1 ; timeout:= 120 m.sec else jl. j2. ; timeout:= 15 m.sec; rl. w0 i13. ; j2: rs. w0 i11. ; start channelprogram. ; if the device is isrpy the device addr in the call must have value ; io device number + 1. rl w3 x1+a235 ; iodev addr:=iodev addr(proc); al w0 1<2+1 ; function select:=start chpg, standard return; al. w1 i0. ; start:=start of chpg; jd 1<11+100 ; start io; rs w0 g23 ;*** se w0 2 ; if io-result<>2 then jl. m4. ; goto result3; ld w0 -100 ; sender stopped: ds w0 g21 ; status, function:=0,0; jl. m3. ; goto result1; e. ; after interrupt. b.j6 w. c38: ; service int(sscir): c39: ; service int(isrpy): rl w0 x1+s1 ; sn w0 0 ; if state=0 then jl. j3. ; goto get next; rl w3 x1+a230+6 ; rl w0 x1+a230+2 ; status(answer):=event status(std status); ds w0 g21 ; function(answer):=rem char count(std status); rl w3 x1+a230+4 ; unitno<18+exf addr(answer):=curr status(std status); rs w3 g22 ; rl w3 x1+a244 ; rs w3 g23 ;*** se w3 0 ; if io-result<>ok then jl. j0. ; goto error; se w0 2 ; if function=2 then jl. m3. rl w0 x1+s2 ; stopped(sender):= 1; lo w0 x1+s0 rs w0 x1+s2 ; return answer to sender of messsage. m3: am 1-3 ; result1: result:=1; m4: am 3-4 ; result3: result:=3; m5: al w0 4 ; result4: result:=4; rl w3 x2+16 ;*** rs w3 g24 ;*** jl w3 g19 ; deliver result; al w0 0 ; rs w0 x1+s1 ; state:=ready; j3: jl w3 g25 ; getnext: next operation; jl. m0. ; goto next; ; after io-error. j0: rl w0 x1+s2 ; error: lo w0 x1+s0 ; stopped(sender):= 1; rs w0 x1+s2 sn w3 6 ; if io-result=6 then jl. j2. ; goto power up; se w3 3 ; if io-result<>3 then jl. m5. ; goto result4; j1: am -1+2 ; timeout: function:=-1; j2: al w0 -2 ; power up: function:=-2; al w3 0 ; ds w0 g21 ; status:=0; jl. m3. ; goto result1; e. e. ; end of rc8601. z. h72=g2, h74=g2, h76=g2, h78=g2 ▶EOF◀