|
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: 115968 (0x1c500) Types: TextFile Names: »mcentral «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer └─⟦2ba378e4a⟧ └─⟦this⟧ »mcentral «
\f m. moncentral - monitor central logic 17.0 beta ;-------------------------------------------------------------------------- ; REVISION HISTORY ;-------------------------------------------------------------------------- ; DATE TIME OR INIT DESCRIPTION ; RELEASE ;-------------------------------------------------------------------------- ;88.03.24 R14.1A HSI start of description ;88.03.24 14.53 hsi insert ap procedure (d4) ; 18.30 hsi addr 138: max number of processors ; initialized at power up ;88.04.19 15.0 tsh c45, c46 rewritten and c47 added ;88.04.24 14.24 hsi addr 138 count instead value in monitor call ;88.04.24 11.16 kak io-test change in decrease stopcount (x2+8 --> x2+a138+1) ;88.05.09 10.05 kak w1=main at c45 and c46 before test ; 14.33 kak at return from c45 check-result in w0 instead of w2 ;88.05.24 07.50 kak change of cpa and address base included ;88 05 30 10.59 hsi define global constants in monitor table ;88 06 01 09.15 hsi add constants to table ;88 06 02 07.00 tsh updates of c45 and c47 due to protocol changes ;88 06 16 11.12 kak function table at 'check itc function' extended ;88 08 16 13.32 hsi update constant table ;88 08 17 17.45 hsi add new function: stop normal communication ;88 09 12 13.54 d132: answer to removed link: use driverproc ;88 09 16 16.36 update constant table ;88 09 19 11.37 hsi move constant table to hw addr 160 ;88 10 06 13.07 hsi error in calculate hw (c47) (R15) ;88 10 13 13.55 kak queue in ioc/lan main is checked after answer device and ; deliver interrupt ;88 11 21 13.39 kak bit 12-14 in message buffer state field is used to result or ; a disjunction of results (chained operations) ; and the final result is extracted from this field ;88 12 06 15.36 kak only the first status from chained operations are used ;89 01 23 12.53 kak deactivate process after program error (c2) ;89 03 08 09.09 kak no check of waiting operation to mainprocesses after deliver interrupt to driverproc, ; the check is performed when driverproc has token care of the interrupt ;89 03 15 15.10 kak decrease number of outstanding operation is delayed until answer device operation (c47) ; or after deliver interrupt to driver (c48), in the last case the main process ; is removed from the timer queue before the interrupt is delivered ;89 03 20 10.36 kak it is checked that clock process is not in queue before the clockinterrupt is delivered ;89 04 03 20.44 hsi error in c5: set process in running after error ;89 05 25 14.10 kak call of deliver answer changed: result must not be set in receiver field, but kept in w0 ;-------------------------------------------------------------------------- ;90 05 10 09.36 kak release 17.0 ;90 05 10 09.37 kak new test point (41) at deliver interrupt to itc-main (c48) ;90 05 29 14.37 kak errorlog called at ioc and lan errors ; special watched receiver introducted for ioc and lan devices b.i30 w. i0=91 02 01 i1=09 36 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 ; segment 1 : enter monitor after load ; the monitor is entered in word 8. the words +2,+4 must at entry contain - ; +2 load flag, writetext ; +4 medium ; where ; load flag: 1 autoload of device controllers ; 0 no autoload s. i3 w. i0: i2. ; length of segment 1 0 ; init cat switch: writetext i1: 0 ; init cat switch: medium ; entry from autoloader: al. w3 i0. ; calculate top address of rl w2 x3 ; last segment; wa w3 4 ; ds. w3 i3. ; --------- se w2 0 ; (i.e. until segment size = 0) jl. -8 ; -6 al. w2 i2. ; insert start address of segment 2; dl. w1 i1. ; get init cat switches jd x3-2 ; jump to segment 10 0, i3:0 ; ----------- i2: ; first word of segment 2 ; exit with: ; w0, w1 = init cat switches ; w2 = start address of segment 2 e. ; end segment 1 b. v100, r28, l60, g70, f30, e70, d160, c200 \f ; segment 2: monitor s. k = 8, j0 w.b127=k, j0, k=k-2 ; segment structure: ; monitor table (b names) ; interrupt response (c names) ; utility procedures (d names) ; monitor procedures (e names) ; name table (f names) ; process descriptions (f names) ; buffers (f names) ; ITC functions (l names) ; ITC states (l names) ; ; (g and h i and j names are used locally) ; monitor table ; all addresses are absolute addresses ; an integer after the semicolon means, that the address can't ; be changed, because it - unfortunately - has been published ; or because they have a hardware-function b65: 0-0-0 ; 8: base of controller description table b66: c25 ; 10: power up entry b67: 0-0-0 ; first controller table entry b68: 0-0-0 ; top controller table entry b69: b69 ; queue head: software timeout b69 ; (for devices) b70: 0 , 0 ; time when last inspected b72: 0-0-0 ; b53 ; start of interrupt table b73: 0-0-0 ; b54 ; max external interrupt number b0: 0-0-0 ; b53 - b16 ; (relative start of interrupt table b74: a198 ; device address of i/o cpu b75: 0 ; after powerfail (0==false, else true) b18: 0 ; current buffer address b19: 0 ; current receiver b20: c96 ; address of simple wait event procedure b21: 0-0-0 ; process description address of driverpoc b101:0 ; return from subprocs b102:0-0-0 ; a66 ; start of table(subproc-drivers) b103:0 ; address of entry for send message for linkdriver areas b76: 0 ; start of secondary interrupt chain b30: 0-0-0 ; errorlog proc b31: g66 ; errorlog entry b58: 0 ; 54: device address register (used by ifp) b59: 0-0-0 ; pu-information table address b38: 0-0-0 ; rtc-table address r. (:64-k+2:) > 1 ; 60-62 reserved for testprograms a135<12+a136 ; 64: release, version of monitor b42: -1000000 ; 66: current process (single cpu) b2: b2 ; time slice queue head: next process b2 ; last process b3: 0-0-0 ; 72: name table start b4: 0-0-0 ; 74: first device in name table b5: 0-0-0 ; 76: first area in name table b6: 0-0-0 ; 78: first internal in name table b7: 0-0-0 ; 80: name table end b8: b8 ; mess buf pool queue head: next buf b8 ; last buf 0-0-0 ; 86: first byte of mess buf pool area 0-0-0 ; 88: last byte of mess buf pool area;( last word of last monitor table) a6 ; 90: size of message buffer b22: 0-0-0 ; 92: first drum chain in name table b23: 0-0-0 ; 94: first disc chain in name table b24: 0-0-0 ; 96: chain end in name table b25: 0 ; 98: main cat chain table b1: 0-0-0 ;cur process in monitor b10: a85 ; maximum time slice b11: 0 ;104: time slice (of current process) 0 ;106: zero (earlier: micro seconds) b13: 0 , 0 ;108:110: time (unit of 0.1 milli seconds) b14: 0 ; last sensed clock value b9: 0-0-0 ; pu kind offset b12: 0-0-0 ;116: number of storage bytes a111<12 + a109 ;118: min global key, min aux cat key ????? b15: 0 , 0 ; clockchange, after set clock: ; newtime - oldtime b79: 0-0-0 ; interrupt statistical table (init in tabinit) b81: b80 ; monitor call statistical table b82: 0 ; current number of processors b83: 0, 0, 0, 0 ; rescedule counter r. (:160-k+2:) > 1; start of constant table: b200: 0 , 0 ; double nul b201: 1 b202: 2 b203: 3 b204: 4 b205: 5 b206: 6 b207: 7 b208: 8 b209: 9 b210:10 b211: 8.00030000 ; format identifier (in SSP/clock interrupt word) b212: 8.37777777 ; last 23 bits b213: 8.77777776 ; first 23 bits b214: 8.00017777 ; last 13 bits b215: 8.00007777 ; last hw b216: 8.00003777 ; last 11 bits b217: 8.77770000 ; first hw b218: 8.77600000 ; first byte b219: 8.00177400 ; midt byte b220: 8.00000377 ; last byte b235: 8.77777400 ; first tree byte b236: 8.77777777 ; full house b221: 512 ; b222: 768 b223: 1<12 b224: 1<13 b225: 1<14 b226: 1<15 b227: 1<16 b228: 1<17 b229: 1<18 b230: 1<19 b231: 1<20 b232: 1<21 b233: 1<22 b234: 1<23 b237: 8.00177777 ;redefinition of old constants g48 = b203 g49 = b234 g50 = b213 g51 = b217 g52 = b215 g53 = b220 g62 = b229 g63 = b201 g65 = b212 g67 = b216 g68 = b214 b26 = b5 ; use area proceses as pseudo processes l50 = (:a80>16a.1:)-1 ; ida/ifp device driver included (not used anymore) l53 = (:a84>16a.1:)-1 ; ida/ifp device driver testoutput 0=yes, -1=no ; Sending a message to the main process the test mask may set, the mask contain 48 bit, ; default bit 45 and 46 and 47 are set, the meaning of the bits are: ; no procedure output no of hw ; 1: area driver part 1 message 18 ; 2: area driver part 2 message 18 ; 3: area driver part 2 message state 2 ; 6: disc driver part 1 message 18 ; 7: disc driver part 2 message 18 ; 8: disc driver part 2 message state 2 ; 11: tape driver part 1 message 18 ; 12: tape+printer+gsd driver part 2 message 18 ; 13: tape+printer+gsd driver part 2 message state 2 ; 16: main driver part 2 message 18 ; 17: main driver part 2 message state 2 ; 24: tape+printer+gsd driver part 1 message 18 ; 25: csp terminal driver part 1 message 18 ; 26: csp terminal driver part 2 message 18 ; 40: special set up reserve and ; release process ext proc 14 ; 41: interrupt, supervisor message comm. area 24 ; 45: interrupt buffer addr. 2 ; 46: start controller comm. area 24 ; 47: interrupt comm. area 24 c.(:a399>23a.1:)-1 ; definition of dump area used in prepare dump (only RC9000-model 10) 0 ; lower dump area: first address b27: 0 ; lower dump area: no of segments 0 ; upper dump area: first address b28: 0 ; upper dump area: no of segments z. ; definition of general registers in rc8000 b90 = 8.14 * 2 ; ilevc : interrupt level limit copy b91 = 8.15 * 2 ; inf : current interrupt stack element address b92 = 8.17 * 2 ; size : top available core address b93 = 8.20 * 2 ; montop : 1 < 11 - top monitor procedure number b94 = 8.62 * 2 ; clock b95 = 8.57 * 2 ; ir : used to clear selected bits in interrupt reg b96 = 8.04 * 2 ; status : cpu status register b97 = 8.60 * 2 ; dswr : data swithes b98 = 8.61 * 2 ; regsel : register swithes b99 = 8.60 * 2 ; display ; b100= 8.21*2 ; cpukind: 0: /45 ; -1: /15, /25, /35 ; 50: /50 ; 55: /55 ; 60: /60 ; 65: /65 ; the following registers are only defined in a mp: b104= 8.24*2 ; cur process register b105= 8.26*2 ; pu table register b106= 8.27*2 ; exception offset register b107= 8.30*2 ; dump offset register b108= 8.25*2 ; pu index register ; definition of interrupt stack. ; parameters are relative to base of stack element (i.e. 1,3,5,..) b.j0 j0=-1 , j0=j0+2 ; base of stack element a326=j0 , j0=j0+2 ; regdump a327=j0 , j0=j0+2 ; exception routine a328=j0 , j0=j0+2 ; escape routine a329=j0 , j0=j0+2 ; monitor call entry a330=j0 , j0=j0+2 ; external interrupt entry a331=j0 , j0=j0+2 ; interrupt limits, disabled/enabled a325=j0-a326 ; size of interrupt stack element e. ; parameter errors in monitor call: ; ; all monitor procedures check that the parameters are ; within certain limits. ; if the parameters are wrong, the calling process is break'ed. ; ; (all regs irrellevant) c29: jl. (+2) ; goto internal break c28 ; ; interrupt return: ; a new internal process may have been put up in front of ; the time slice queue, due to an external interrupt, or because ; the current monitor call was 'send message' or the like. ; therefore it must be tested, that the current process is still ; the one in front. if not: select that one. b. i2, j0 w. c99: ; interrupt return: b. h1 w. ; if mp then am (b9) ; h0=k jl. 0 ; begin jl c24 ; goto mp activation c.(:h0+a8-k-1:) am 0, r.(: h0+a8+2-k :)>1 ; fill up z. e. ; end mp rl w1 b1 ; proc := cur sh w1 0 ; if cur defined and jl. i0. ; zl w0 x1+a13 ; proc.state <> running then sn w0 a94 ; begin ri a179 ; i0: jl. w3 d8. ; activate process rs w1 b42 ; rs w1 b51 ; cur:= proc rs w1 b1 ; cur process in monitor := proc; al w2 x1 ; gg w3 b91 ; w3 := inf (= address of current stack element); dl w1 x2+a170 ; move: user escape address (cur) ; user exception address (cur) ds w1 x3+a325+a328; al w0 x2+a28 ; address of regdump area (cur) rs w0 x3+a325+a326; to: previous interrupt stack element; ri a179 ; return interrupt; c24: rl w2 b2 ; proc:=first in queue ; activated:=true al w1 x2-a16 ; se w2 b2 ; do while queue not empty and activated jl w3 d4 ; activate process; 88.03.24 14.53 ri 1 ; return to user; jl. w3 d8. ; rl w3 b82 ; if no of cpues = 1 then sn w3 1 ; cur process := proc; rs w1 b42 ; jl c24 ; endwhile ; end ; return e. ; procedure check itc function ; ; ; call ; ; w0 - ; w1 - ; w2 - (8000 special: main + a241) ; w3 - ; b. i10, j21 w. c45: ; procedure check_itc_function ; begin c.l53 b. f4 w. ; ****** test 47 ****** rs. w3 f1. ; al w1 x2-a241 ; rs. w1 f0. ; jl. w3 (f3.) ; 47 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a500 ; dump main.communication area al w1 x1+a517 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 47 ****** ; -----> 8000 special <------ al w1 x2-a241 ; ; -----> end 8000 special <------ al w0 8.0377 ; la w0 x1+a500 ; if main.gen_info.result = no_credit or se w0 6 ; main.gen_info.result = illigal_link then sn w0 7 ; panic; <* protocol error *> jl -1 ; rs. w0 i6. ; <* save result *> ; rl w0 b227 ; if main.gen_info.answer then <* bit 1<16 *> la w0 x1+a500 ; begin sn w0 0 ; jl. j1. ; main.free_buffers := al w0 1 ; main.free_buffers + 1; ba w0 x1+a78+0 ; hs w0 x1+a78+0 ; end; j1: ; rl w0 b219 ; <* middle octet *> la w0 x1+a500 ; ls w0 -8 ; rl w3 x1+a503 ; sn w3 0 ; if process-id = 0 then jl. j2. ; skip errorlog check; se w3 (b32) ; if special watched receiver or se w0 0 ; check<>0 then sz ; jl. j2. ; begin rx w1 6 ; jl w2 (b31) ; < call error-log > al w1 x3 ; al w2 x1+a241 ; ; end; j2: ; rl w3 b218 ; <* left octet *> la w3 x1+a500 ; ls w3 -15 ; sl w3 63 ; if main.function > 15 then jl -1 ; panic; ; rl. w0 i6. ; <* w0: result, w1: main, w2: main+a241 *> jl. (x3+j3.) ; goto case function of ;func, a : j3: -1 ; 0 0 : undef -1 ; 0 1 : undef -1 ; 1 0 : undef c47 ; 1 1 : answer device operation c48 ; 2 0 : create link - deliver interrupt c48 ; 2 1 : answer create link - deliver interrupt -1 ; 3 0 : undef c48 ; 3 1 : answer remove link - deliver interrupt c48 ; 4 0 : attention - deliver interrupt -1 ; 4 1 : undef -1 ; 5 0 : undef c48 ; 5 1 : answer regret - deliver interrupt -1 ; 6 0 : undef c48 ; 6 1 : answer reserve device - deliver interrupt -1 ; 7 0 : undef c48 ; 7 1 : answer release device - deliver interrupt c48 ; 8 0 : remove link request - deliver interrupt -1 ; 8 1 : undef -1 ; 9 0 : undef c48 ; 9 1 : answer initialize controller - deliver interrupt -1 ; 10 0 : undef c47 ; 10 1 : answer supervisor_operation -1 ; 11 0 : undef c48 ; 11 1 : answer reset -1 ; 12 0 : undef c48 ; 12 1 : answer stop normal communication -1 ; 13 0 : undef c47 ; 13 1 : answer operator message -1 ; 14 0 : undef -1 ; 14 1 : answer close system: just panic -1 ; 15 0 : undef -1 ; 15 1 : answer reload system: just panic i6: 0 ; save result ; e. ; end; ; interrupt acknowledge procedure ; ; the controller has read it's communication area ; ; call ; w0 - ; w1 - ; w2 - (8000 special: main + a229) ; w3 - ; b. j5 w. c46: ; procedure acknowledge interrupt ; begin c. l53 b. f4 w. ; ****** test 45 ****** rs. w3 f1. ; al w1 x2-a229 ; rs. w1 f0. ; jl. w3 (f3.) ; 45 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a551 ; dump message buffer address al w1 x1+a551 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 45 ****** ; ; ------> RC8000 special <------- al w1 x2-a229 ; ; ------> end RC8000 special <------- ac w0 2.010000+1; la w0 x1+a78 ; main.com_state := ready; hs w0 x1+a78+1 ; ; c42: ; entry2: <* after answer device *> rl w2 x1+a81 ; element := main.waiting_q.first; sn w2 x1+a81 ; if element = none then jl c99 ; return_from_interrupt; al w0 0 ; force := sl w2 (b8+4) ; sl w2 (b8+6) ; if element <> message then no jl j2 ; al w0 2.1000000 ; else message.state.force; la w0 x2+a138 ; ls w0 -6 j2: ; jl. (+2) ; test_ready_and_setup(force, message); d142 ; ; end; e. ; procedure deliver clock interrupt. ; only the clock interrupt from the i-o mp (or the cpu) is transferred to ; the monitor clock driver. ; return: interrupt return c49: al w0 0 ; b. h0 w. ; if mp then am (b9) ; get pu index h0=k ; jl. 0 ; gg w0 b108 ; c.(:h0+a8-k-1:) am 0, r.(:h0+a8+2-k:)>1 z. e. ; end sn w2 (x2) ; if in queue or se w0 0 ; not i-o pu or cpu then jl c99 ; return jl c50 ; else deliver interrupt ; procedure deliver external interrupt ; ; when an external interrupt is accepted by the monitor, ; control is transferred out into the corresponding ; device description, which should contain: ; ; dev descr + a240 : jl w2 c51 ; ; return must be made to the standard interrupt return action, ; which will take care of a possible selection of the driver. ; ; call: w2 = dev descr + a241 ; return address = interrupt return c51: rl w3 x2-a241+a230; w3 := top of executed channel program; al w0 4 ; result := 4; (i.e. prepare for abnormal termination) se w3 0 ; if top command address defined then bl w3 x3-6+1 ; w3 := last command executed; sn w3 -1<8 ; if last command = 'stop' then al w0 0 ; result := 0; sn w3 4<8 ; if last command = 'wait' then al w0 5 ; result := 5; c50: al w3 c99 ; link := interrupt return; ; continue with deliver interrupt ; procedure deliver interrupt ; function: delivers the interrupt operation in the event queue ; of the corresponding driver process. ; the driver process is started, if it was waiting for ; an event. ; ; call: w0 = result (=0, 1, 2, 3, 4, 5, 6), w2 = operation, w3 = link ; exit: all regs undef ; return address: link b. h10 w. ; d121:rs w3 h0 ; save (return); jl w1 d131 ; set result and descrease all stopcounts; ; w2 = device descr rl w1 x2+a250 ; driver := driverproc (device descr); sh w1 0 ; if driver undefined then jl -10 ; test test ; jl (h0) ; return; al w2 x2+a241 ; oper := timeout operation (device descr); rl w3 h0 ; restore (return); bz w0 x1+a13 ; state := state(driver); sn w0 a104 ; if driver is waiting for event then jl d127 ; goto take interrupt; al w1 x1+a15 ; link (event queue (driver) , oper); rl w3 x1+2 ; rs w2 x1+2 ; rs w2 x3+0 ; rs w1 x2+0 ; rs w3 x2+2 ; jl (h0) ; h0: 0 ; saved return; e. ; ; procedure take interrupt ; function: let the driver receive the interrupt operation at once ; ; call: w1 = driver process, w2 = interrupt operation, w3 = link ; exit: all regs undef ; return address: link d127:al w2 x2-a241+a246; rs w2 x1+a30 ; save w2 (driver) := address of driver service inst al w0 2 ; save w0 (driver) := 2; i.e. indicate interrupt; rs w0 x1+a28 ; link internal (driver); zl w0 x1+a13 ; if process not running then se w0 a94 ; link process to running queue jl d10 ; jl x3 ; ; procedure prepare driver(proc) ; function: initializes current external process and current buffer ; exits to the interrupt address given in proc: ; int addr : normal exit ; ; the call must be made like this: ; ; proc + a246: jl w1 c30 ; driver service instruction ; --- ; proc + a245: interrupt address ; --- ; proc + a54 : next message buf ; ; call: w1 = proc + a247 ; exit: w0 = result(proc), w1 = proc, w2 = buf(proc) ; int.addr : normal exit c30: al w1 x1-a247 ; rs w1 b19 ; current receiver := buf; rl w2 x1+a54 ; rs w2 b18 ; current buffer address := next mess(proc); rl w0 x1+a244 ; result := timeout(proc); jl (x1+a245) ; goto interrupt address(proc); ; procedure clear device ; ; function: everything is cleared-up in the device description, ; i.e. the controller is reset (except after 'wait'-program) ; a possible pending interrupt is cleared ; a possible pending interrupt operation is removed ; if any stopcounts were increased, they will be decreased ; ; call: w1 = link, w2 = device descr ; exit: w2 = unchanged, w0, w1, w3 = undef ; return address: link b. i5, j5 w. i1: 0 ; saved return ; d129: ; unconditionally reset: am a235-a225; <point at something <> 0> d130: ; conditionally reset: rl w0 x2+a225 ; note: the controller is not reset when a rl w3 x2+a235 ; wait program is timed out; sn w0 0 ; if transfer in progress then jl j1 ; begin rs w1 i1 ; <w3: physical device address> al w1 3 ; if proc.kind = ifpmain then rl w0 x2+a10 ; reset device(ifp-reset) sn w0 q26 ; device address := physical address; rs w3 b58 ; se w0 q26 ; else am 2.01<1 ; reset device(normal reset); do w1 x3+0 ; note: ifp: sub address must be zero - reset is rl w1 i1 ; signaled in work register! j1: ; end; ls w3 1 ; entry := device address ls w3 -1 ; (remove bit 0) wa w3 b65 ; + controller table base; rl w0 x3+a313 ; w0 := interrupt number(controller table (entry)); gp w0 b95 ; clear interrupt bit in cpu; al w2 x2+a242 ; oper := timeout operation(device descr); ; continue with set result and decrease all stopcounts ; (result = undef) e. ; procedure set result and decrease all stopcounts ; ; call: w0 = result: 0 = transfer terminated by stop ; 1 = bus reject when started ; 2 = bus timeout when started (i.e. disconnected) ; (3 = software timeout) ; 4 = transfer terminated, before stop ; 5 = wait-program terminated ; (6 = power restart) ; w1 = link w2 = timeout operation ; exit: w2 = device description, w0, w1, w3 = undef d131:rs w0 x2-a241+a244; save result in timeout-field; se w2 (x2) ; (if in timer queue then jl w3 d5 ; remove(timeout operation); ) al w2 x2-a241 ; w2 := device descr; ; continue with decrease all stopcounts ; procedure decrease all stopcounts ; ; function: if any stopcounts increased, then decrease them again ; transfer code(device descr) := 0 ; ; call: w1 = link, w2 = device descr b. h10, i10 w. ; ds w2 h1 ; save (link, device descr); rl w1 x2+a225 ; get transfer code(device descr); sn w1 -1 ; if no transfer to processes then jl i1 ; goto clear up; so w1 2.1 ; if transfer code odd then jl i0 ; begin i.e. transfer to/from driver area; rl w1 x2+a250 ; driver := driver process (device descr); jl w3 d133 ; decrease stopcount(driver); rl w2 h1 ; restore(device descr); al w1 -1<1 ; la w1 x2+a225 ; restore (transfer code) (even) i0: ; end; sn w1 0 ; if transfer code shows transfer to/from sender the jl i1 ; begin jl w3 d133 ; decrease stopcount(sender); rl w2 h1 ; restore (device descr); ; end; i1: al w1 0 ; clear up: rs w1 x2+a225 ; transfer code(device descr) := 0; i.e. no transfer jl (h0) ; return; h0: 0 ; saved return h1: 0 ; saved device descr e. ; ; procedure decrease stopcount(sender.mess): d132 ; procedure decrease stopcount(process): d133 ; ; function: the stopcount of the process is decreased by 1. ; if the stopcount becomes zero, and the process is waiting ; to be stopped, the process is stopped now (i.e. put in ; the state 'waiting for start by...'), and the following will ; be done: ; if the process was stopped by its parent, the stop-answer ; will be send to the parent (as defined by the wait-address ; in the process), indicating that the stopping has been ; accomplished. ; the decrease-action is repeated for the parent etc.etc. ; ; call: d132: w2= message or d132: rl w1 x2+a142 ; proc= sender(mess) sh w1 0 ; if regretted then ac w1 x1 ; proc= -sender(mess) rl w0 x1+a10 ; if kind.proc = pseudo then sn w0 64 ; proc = main proc.sender rl w1 x1+a50 ; sz w0 -1-64 ; if proc is neither internal nor pseudo then rl w1 b21 ; proc = driverproc (there is only one) ; (continue with d133) ; call: d133: w1 = process, w3 = link ; exit: all regs undef ; return address: link b. i10 w. ; d133:rs w3 i3 ; decrease stopcount: i0: al w0 -1 ; loop: ba w0 x1+a12 ; stopcount (process) := hs w0 x1+a12 ; stopcount (process) - 1; bz w2 x1+a13 ; sn w0 0 ; if stopcount <> 0 or so w2 a105 ; process not waiting for being stopped then jl (i3) ; return; al w0 x2+a106 ; state (process) := state (process) hs w0 x1+a13 ; + 'waiting for start'; ; prepare for repeating the loop: rl w2 x1+a40 ; buf := wait address(process); rl w1 x1+a34 ; process := parent (process); se w0 a99 ; if state <> 'waiting for start by parent' then jl i0 ; goto loop; ; prepare the buffer for returning the answer: al w0 1 ; receiver(buf) := result := 1; jl. w3 (i1.) ; deliver answer(buf); jl i0 ; goto loop; i1: d15 ; i3: 0 ; saved return; e. ; ; procedure activate_process(internal) ; ; sw-implementation of 'ap'-instruction. ; when using this procedure it is possible to connect and disconnect ; cpu's during normal operation only by increase and decrease b82. ; ; call return ; w0 - destroyed ; w1 internal internal ; w2 - destroyed ; w3 link destroyed ; ; return: link + 0: no free pu ; link + 2: internal has been activated ; b. i5, j5 w. d4: ; procedure activate_process(internal) rl w2 (b59) ; begin rl w0 x2+0 ; sh w0 0 ; if pu_table.free_pu = 0 then jl x3+0 ; return(link); ; rs. w3 i3. ; rl w3 x1+a186 ; am x3 ; rl w0 x2+2 ; ls w3 -1 ; if internal.last_pu < no_of_pu and sl w3 (b82) ; pu_table(internal.last_pu) = 0 then jl. j1. ; begin ls w3 +1 ; sn w0 0 ; selected_pu := internal.last_pu; jl. j3. ; end j1: ; else rl w3 b82 ; begin ls w3 +1 ; selected_pu := no_of_pu; j2: am x3 ; while pu_table(selected_pu) <> 0 do rl w0 x2 ; begin al w3 x3-2 ; selected_pu := selected_pu - 1; se w0 0 ; jl. j2. ; end; j3: ; end; al w0 -1 ; wa w0 x2+0 ; pu_table.free_pu := rs w0 x2+0 ; pu_table.free_pu - 1; am x3 ; rs w1 x2+2 ; pu_table(selected_pu) := internal; rl. w3 i3. ; jl x3+2 ; return(link+2); ; i3: 0 ; saved link e. ; end; ; elementary link-procedures: ; procedure remove(elem); ; comment: removes a given element from its queue and leaves the element linked to itself. ; call: w2=elem, w3=link ; exit: w0, w1, w2=unchanged, w3=next(elem) ; return address: link b. i1 w. d5: rs w3 i0 ; save return; rl w3 x2 ; w3 := next(elem); rx w2 x2+2 ; w2 := prev(elem); prev(elem) := elem; rs w3 x2 ; next(w2) := next(elem); rx w2 x3+2 ; w2 := elem; prev(next(elem)) := old prev(elem); rs w2 x2 ; next(elem) := elem; jl (i0) ; return; ; procedure increase bufclaim, remove release buf; ; comment: bufclaim(cur) is increased, continue with release buf ; call: w1=cur, w2=buf, w3=link ; exit: w0, w1=undef, w2, w3=unchanged ; return address: link d109: ; al w0 1 ; ba w0 x1+a19 ; increase(bufclaim(cur)); hs w0 x1+a19 ; ; continue with d106 ; procedure remove release buf; ; comment: removes the buffer from its queue, continue with release mess buf ; call: w2=buf, w3=link ; exit: w0, w2, w3=unchanged, w1=undef ; return address: link d106: ; al w1 x3 ; save return jl w3 d5 ; remove (buf); al w3 x1 ; restore return; ; continue with d13 ; procedure release mess buf(buf); ; comment: clears sender and receiver and links the buffer to the pool. ; call: w2=buf, w3=link ; exit: w0=unchanged, w1=undef, w2, w3=unchanged ; return address: link d13: al w1 0 ; sender(buf):=0; rs w1 x2+4 ; receiver(buf):=0; rs w1 x2+6 ; al w1 b8 ; head := mess buf pool head; (i.e. link in rear); ; procedure link(head, elem); ; comment: links the element to the end of the queue ; call: w1=head, w2=elem, w3=link ; exit: w0, w1, w2=unchanged, w3=old last(head); d6: rs w3 i0 ; save return; rl w3 x1+2 ; old last:=last(head); rs w2 x1+2 ; last(head):=elem; rs w2 x3+0 ; next(old last):=elem; rs w1 x2+0 ; next(elem):=head; rs w3 x2+2 ; last(elem):=old last; jl (i0) ; return; i0: 0 ; saved return: remove, link e. ; ****** stepping stones for absolute addresseable monitor routines ****** ; ; procedure claim buffer(cur, buffer); <* d108 *> ; ; call return ; w0 - destroyed ; w1 cur cur ; w2 buffer buffer ; w3 link link ; d108: jl. (+2) ; claim buffer d58 ; ; procedure regretted message(buffer); <* d75 *> ; ; call return ; ; w0 - unchanged ; w1 - unchanged ; w2 buffer buffer ; w3 link destroyed ; d75: jl. (+2) ; regretted message d65 ; ; procedure check mess area and name (save w3) area; ; procedure check name (save w3) area; ; procedure check name (save w2) area; ; comment: checks that the areas are within the process ; ; call: w1=cur, w3=link ; exit: w0=undef, w1=unchanged, w2=name, w3=unchanged ; return addr: link: within process ; c29 : not within process d110: jl. (+2) ; check message area and name area: d66 ; d17: jl. (+2) ; check name (save w3) area: d67 ; d111: jl. (+2) ; check name (save w2) area: d115 ; ; procedure check within(first, last); ; comment: checks that the specified area is within the process ; call return ; w0 last last ; w1 cur cur ; w2 first first ; w3 link link ; return: link: within process ; c29 : not within process d112: jl. (+2) ; check within: d116 ; ; procedure check message area and buf ; call return ; w0 - destroyed ; w1 cur cur ; w2 - buf ; w3 link link ; return: link: ok ; c29 : mess area outside cur ; c29 : buf not message buf d103: jl. (+2) ; check message area and buf d117 ; ; procedure check message buffer; ; checks whether the save w2 of the internal process is a message buffer address ; call return ; w0 - destroyed ; w1 cur cur ; w2 - buf ; w3 link link d12: jl. (+2) ; check message buffer: d68 ; ; procedure check event(proc, buf); ; checks that buf is the address of an operation in the event queue of ; the internal process ; call return ; w0 - destroyed ; w1 proc proc ; w2 buf buf ; w3 link link ; return: link: buffer address ok ; c29: buf is not in the queue d19: jl. (+2) ; check event: d69 ; ; procedure conditional reschedule ; procedure unconditional reschedule ; If the 'conditional' entrypoint is used, the internal process is ; rescheduled if 'no of free pu' in the pu-table is 0 otherwise no ; rescheduling is performed. This test is done because there is no ; need for rescheduling if ther is an idle pu; if done the process ; may change pu and the cache will be destroyed. ; call return ; w0 - destroyed ; w1 internal internal ; w2 - destroyed ; w3 link destroyed ; d20: jl. (+2) ; conditional reschedule d40 ; d21: jl. (+2) ; unconditional reschedule d41 ; ; procedure check and search name (=d17+d11); ; ; call: w1=cur, save w3(cur)=name, w3=link ; exit: w0, w1=unchanged, w2=name, w3=entry ; return address: link: entry not found ; link+2: entry found ; c29 : name area outside current process d101:jl. (+2) ; check and search name; d43 ; ; the following procedures searches the name table for a given entry and delivers its entry in ; the name table. if name is undefined, the entry is name table end. ; procedure search name(name, entry); ; call: w2=name, w3=link ; exit: w0, w1, w2=unchanged, w3=entry ; return address: link : name not found, w3=(b7) ; link+2: name found d11: jl. (+2) ; search name; d44 ; ; procedure search name(name, entry, base); ; call: w0, w1=base, w2=name, w3=link ; exit: w0, w1=undef, w2=unchanged, w3=entry ; return address: link : name not found, w3=(b7) ; link : name found, w3 <> (b7) d71: jl. (+2) ; search name; d45 ; a107 ; max base lower d72: a108 ; max base upper a107-1 ; extreme lower d73: a108+1 ; extreme upper ; procedure update time(slice); ; comment: senses the timer and updates current time slice and time; ; ; call: w3=link ; exit: w0=undef, w1=unchanged, w2=new clock, w3=unchanged ; return address: link b. i9, j4 w. d7: gg w2 b94 ; al w0 0 ; b. h1 w. ; if mp then am (b9) ; h0=k jl. 0 ; begin gg w0 b108 ; get pu index c.(:h0+a8-k-1:) am 0, r.(: h0+a8+2-k :)>1 ; fill up z. e. ; end mp sn w0 0 ; if not i-o pu or cpu then jl. i6. ; begin rl. w0 i9. ; rct(i-o mp) := undefined rs w0 (b38) ; get clock from i-0 mp al w0 a194 ; wait until rct(i-o mp) defined do w0 (b74) ; j4: rl w2 (b38) ; sn. w2 (i9.) ; jl. j4. ; end i6: al w0 x2 ; new value:=sense(timer); ws w2 b14 ; increase:=new value-clock; rs w0 b14 ; clock:=new value; sh w2 -1 ; if increase<0 then wa w2 i9 ; increase:=increase+size of clock; ; comment: timer overflowed...; rx w0 4 ; wa w0 b13+2 ; rs w0 b13+2 ; time low:=time low+increase; sx 2.01 ; jl i8 ; if carry then jl x3 ; i8: al w0 1 ; time high:=time high+1; wa w0 b13 ; rs w0 b13 ; jl x3 ; return; i9: 1<16 ; increase when timer overflows; ;procedure activate process ;comment: unlinks the first proc in running queue, increases stopcount ; and sets the state to running, ; call: return: ; w0: undefined ; w1: proc ; w2: proc+a16 (running queue link) ; w3: link undefined d8: rs w3 j0 ; save return; rl w2 b2 ; get first in running queue al w1 x2-a16 ; w1:= proc al w0 1 ; proc.stopcount:= ba w0 x1+a12 ; proc.stopcount + 1 hs w0 x1+a12 ; al w0 a94 ; proc.state:= running hs w0 x1+a13 ; jl w3 d7 ; update time; al w0 x2 ; al w2 x1+a16 ; ws w0 x1+a35 ; proc.quantum := starttime rs w0 x1+a35 ; rl w3 x2 ; unlink proc rx w2 x2+2 ; rs w3 x2 ; rx w2 x3+2 ; rs w2 x2 ; jl (j0) ; return ; the following entries removes the current process from the timequeue, and initializes state. ; call: w1=cur ; return address: interrupt return d105: ; remove wait message: ; bz w0 x1+a19 ; ; sn w0 0 ; if buf claim(cur)=0 then ; jl d108 ; goto claim buffer (and exit with save w2=0); am a102-a104 ; state:=wait message; d107: ; remove wait event: am a104-a103 ; state:=wait event; d104: ; remove wait answer: al w0 a103 ; state:=wait answer; al w3 c99 ; return:=interrupt return; ; continue with remove internal; ; procedure passivate process (new state) ; passivates the current process i.e ; - decreases stopcount (eventually stopping the process) ; - updates the time quantum used by the process ; - sets the state to new state if the process has not been stopped ; ; call return ;w0 new state process state ;w1 proc undefined ;w2 proc.timeq (proc +a16) ;w3 link undefined d9: ds w0 j1 ; save state , return, and proc rs w1 j2 ; jl w3 d7 ; update time sh w2 (x1+a35) ; if stoptime > starttime then wa. w2 i9. ; stoptime := stoptime + size of clock ws w2 x1+a35 ; proc.quantum:= stoptime-starttime rs w2 x1+a35 ; dl w3 b13+2 ; proc.start wait:= now ds w3 x1+a39+2 ; jl w3 d133 ; test and decrease stopcount al w0 0 ; rescedule count := 0 al w1 0 ; b. h1 w. ; am (b9) ; h0=k ; jl. 0 ; gg w1 b108 ; c. (:h0+a8-k-1:) ; am 0, r.(:h0+a8+2-k:)>1; z. ; e. ; rs w0 x1+b83 ; rl w1 j2 ; if proc.state still is running then zl w0 x1+a13 ; sn w0 a94 ; rl w0 j1 ; proc.state:= new state hs w0 x1+a13 ; al w2 x1+a16 ; b. h1 w. ; if mp then am (b9) ; h0=k jl. 0 ; begin dp ; deactivate process; c.(:h0+a8-k-1:) am 0, r.(: h0+a8+2-k :)>1 ; fill up z. e. ; end mp jl (j0) ; j0: 0 ; return j1: 0 ; new state j2: 0 ; current process ; return; i0: 0 ; saved return ; procedure link internal(proc); ; comment: links the internal process to the timer queue. the timer queue is kept as a ; sorted list, according to the priority. (the smaller the priority is, the better ; is the priority). ; if the time quantum is less than the maximum time slice, the process will be ; linked up in front of other processes with the same priority. otherwise in the ; rear (the time quamtum of the process is transferred to runtime(proc), except ; the amount which is already used of the next quantum). ; call: w1=proc, w3=link ; exit: w0, w1, w2, w3=undef d10: rs w3 i0 ; save(return); al w0 a95 ; hs w0 x1+a13 ; state(proc):=waiting for cpu; al w2 x1+a16 ; rl w3 x1+a301 ; priority:=priority(proc); rl w1 x1+a35 ; sl w1 (b10) ; if quantum(proc)>=max slice then jl i3 ; goto insert in rear; al w3 x3-1 ; (code facility); al w1 b2 ; worse:=timer q head; i1: rl w1 x1 ; next: worse:=next(worse); sn w1 b2 ; until last jl i2 ; sl w3 (x1-a16+a301) ; if priority(worse)<priority then jl i1 ; goto next; i2: ; insert process: rl w3 x1+2 ; rs w2 x1+2 ; rs w2 x3+0 ; rs w1 x2+0 ; rs w3 x2+2 ; jl (i0) ; internal then return; ; the process has been in front of the queue for more than the max time slice. ; the run time should be updated with all the quantum, but this would give the process a ; complete time slice next time. instead the used quantum is split in two parts: ; the amount by which it exceeds a multiplum of the max slice, and the rest. these parts ; are the increase in runtime and the new quantum. ; finally the process is inserted in the rear of the timer queue, according to priority. i3: al w0 a85-1 ; w0 := mask for extracting new quantum; la w0 2 ; quantum(proc) := quantum(proc) extract slice; rs w0 x2-a16+a35; ws w1 0 ; al w0 0 ; aa w1 x2-a16+a36+2; add the remaining part of quantum to ds w1 x2-a16+a36+2; runtime(proc); al w1 b2 ; insert process in rear of queue al w3 x3+1 ; (code facility) i4: rl w1 x1+2 ; next: worse:=last(worse); sn w1 b2 ; if worse<>timer q head and jl i5 ; sh w3 (x1-a16+a301) ; priority(worse)>priority then jl i4 ; goto next; ; notice: the loop went one step to far . . .; i5: rl w1 x1 ; now w1 has been repaired; jl i2 ; goto insert proc; e. \f m. end of link internal ; to facilitate the error recovery the interrupt stack and the ; stationary pointers of the monitor table are placed at fixed ; addresses. b128=1200, 0,r.(:b128-k+2:)>1-7 a125 ; job host identification a130 ; date of options a131 ; time of options t. m. copies of some mon table entries, int stack, mon reg dump (26, 32, 26 hw) ; copy of some monitor pointers: 0-0-0 ; b3: 72: name table start 0-0-0 ; b4: 74: first device in name table 0-0-0 ; b5: 76: first area in name table 0-0-0 ; b6: 78: first internal in name table 0-0-0 ; b7: 80: name table end 0-0-0 ; b8+4: 86: first byte of mess buf pool area 0-0-0 ; b8+6: 88: last byte of mess buf pool area 0-0-0 ; b22: 92: first drum chain in name table 0-0-0 ; b23: 94: first disc chain in name table 0-0-0 ; b24: 96: chain end in name table b50 ; start of interrupt stack 0-0-0 ; b86: driver proc save area a135<12+a136 ; 64: release, version of monitor 0-0-0 ; b59: 56: pu inf table 0-0-0 ; b79: 124: interrupt stat table 0-0-0 ; b81: 126: monitor call stat table 0-0-0 ; reserved 0-0-0 ; reserved 0-0-0 ; reserved ; definition of interrupt stack: b50: 0 ; end of stack b49=k-1 ; terminating stack-address ; power fail element: 0 ; (irrellevant regdump) 0 ; (exception disabled) -1 ; (escape disabled) 0 ; (monitor call not permitted in monitor) c8 ; external interrupt, second level 1 < 23 + 0 ; monitor mode + totally disabled ; monitor element: b52 ; monitor regdump 0 ; monitor exception routine b51: -1 ; current process in monitor (escape not used in monitor mode c0 ; monitor call entry c1 ; external interrupt entry, first level 1 < 23 + 6 ; monitor mode + disable all but power/bus error ; user element: 0-0-0 ; user regdump (initialized by select internal) 0-0-0 ; user exception ( - - - - ) 0-0-0 ; user escape ( - - - - ) ; monitor regdump area ; ; used when initializing the whole system, ; and to hold the working registers etc. in case of ; powerfailure or buserror during monitor code b52: 0 ; w0 = 0 (irrellevant) 0 ; w1 = 0 (irrellevant) 0 ; w2 = 0 (irrellevant) 0 ; w3 = 0 (irrellevant) 1 < 23+1<5 ; status = monitor mode + no process active c99 ; ic = interrupt return 0 ; cause = 0 (irrellvant) 0 ; sb = 0 (irrellvant) 0 ; cpa = 0 (irrellevant) 0 ; base = 0 (irrellevant) 8 ; lower write limit 8.3777 7777 ; upper write limit = all possible core 0 < 12 + 6 ; interrupt limits 0 ; puindex ; procedure move message(from, to); <* d14 *> ; ; call return ; w0 - destroyed ; w1 from from ; w2 to to ; w3 link destroyed ; d14: jl. (+2) ; move message d64 ; ; return result in save w0(cur); ; entry: w1=cur r5: am 5-4 ; r4: am 4-3 ; r3: am 3-2 ; r2: am 2-1 ; r1: am 1-0 ; r0: al w0 0 ; r28: rs w0 x1+a28 ; save w0:=result; jl c99 ; goto interrupt return; ; procedure remove user(internal, proc); <* d123 *> ; procedure remove reserver(internal, proc); <* d124 *> ; ; call return ; w0 - destroyed ; w1 internal internal ; w2 proc proc ; w3 link link ; d123: jl. (+2) ; remove user d53 ; ; d124: jl. (+2) ; remove reserver d54 ; ; procedure insert reserver(internal, proc); <* d125 *> ; procedure insert user(internal, proc); <* d126 *> ; ; call return ; w0 - destroyed ; w1 internal internal ; w2 proc proc ; w3 link link ; d125: jl. (+2) ; insert reserver d55 ; ; d126: jl. (+2) ; insert user d56 ; ; procedure lock monitor ; returns disabled! b. h0 w. d80: ; am (b9) ; if mp then h0=k ; je. 0 ; (lock must be called with interrupts enabled) lk b51 ; lock(monitor); c.(:h0+a8-k-1:) am 0 ; r.(:h0+a8+2-k:)>1 ; z. jd x3 ; return disabled ; procedure unlock ; returns enabled d81: ; am (b9) ; if mp then h0=k ; jl. 0 ; ul b51 ; unlock(monitor) c.(:h0+a8-k-1:) am 0 r.(:h0+a8+2-k:)>1 z. je x3 ; returns enabled e. \f ; comment: the following utility procedures are used by external ; processes during input/output; ; procedure deliver result(result) ; comment: moves the general input/output answer to the beginning of the driver process. ; (the last 3 words of the message buffer are copied too, so they will remain unchanged). ; the answer is send with the specified result to the sender of the buffer. ; ; call: w0 = result, w3 = link, b18 = buffer ; exit: w0 = undef, w1 = proc (= b19), w2 = undef, w3= unchanged ; return address: link: answer delivered ; (internal 3 if buf not claimed and claims exceeded) b. i10 w. g3: am 5-4 ; result 5: g4: am 4-3 ; result 4: g5: am 3-2 ; result 3: g6: am 2-1 ; result 2: g7: al w0 1 ; result 1: w0 := result; rl w3 b20 ; return := wait-next action in driver process; jl g19 ; goto deliver result; g18: al w0 1 ; result 1: w0 := result; g19: ; deliver result: jd k+2 ; disable; ds w0 i3 ; save(link, result); rl w1 b21 ; cur = driverproc rl w2 b18 ; buf := current buffer; ac w3 (x2+4) ; sl w3 0 ; if receiver(buf) > 0 then jl i0 ; begin comment: buf not claimed, see link operation; bz w0 x1+a19 ; if bufclaim(cur) <> 0 then sn w0 0 ; begin jl i0 ; decrease(bufclaim(cur)); bs. w0 1 ; receiver(buf) := -receiver(buf); hs w0 x1+a19 ; end; (i.e. claims exceeded will provoke a break below); rs w3 x2+4 ; end; i0: rl w0 x1+a182 ; rl w1 x1+a302 ; wa w1 0 ; get physical address of save area dl w0 x2+a151 ; save first four words of mess. ds w0 g29 ; (used by errorlog ) dl w0 x2+a153 ; ds w0 g30 ; dl w0 x2+22 ; move last 3 words from buf ds w0 x1+14 ; to area; rl w0 x2+18 ; (to retain compatibility with old conventions) rl w3 g24 ; ds w0 x1+10 ; move the 5 std answer words dl w0 g23 ; to area; ds w0 x1+6 ; dl w0 g21 ; ds w0 x1+2 ; (you are disabled, so do not worry about timeslicing...); dl w0 i3 ; restore (link, result); am (b21) ; rl w1 +a302 ; get logical address of save area jd 1<11+22; send answer(result, area, buf); rl w1 b19 ; w1 := current receiver; rl w2 x1 ; if kind of receiver=subprocess then se w2 84 ; check status sn w2 85 ; else return jl. i1. ; jd x3 ; i1: rl w2 g20 ; if one or more of statusbits 1,2,4,9,10,11 se. w1 (b32.) ; or if receiver = special watched receiver sz. w2 (i5.) ; then jl w2 (b31) ; call errorlog jd x3 ; restore link and return i2: 0 ; saved link i3: 0 ; saved result b32: -2 ; proc adr for special watched receiver m. statusmask for errorlog i5: 8.36070000 ; status mask: bit 1 2 3 4 9 10 11 ; procedure link operation (buf) ; comment: links a message to the receiver and returns to the receiver, in case it is the only ; message in the queue (and interrupt address is even). ; otherwise it returns to the wait-next action in the driver process. ; ; call: w2 = buf, w3 = link ; exit: w0 = operation, w1 = proc, w2 = unchanged, w3 = unchanged ; return address: link: single in queue ; (b20): others in queue ; (b20): interrupt addr odd (i.e. driver busy) g17: jd k+2 ; link operation: rs w3 i3 ; save return; ac w3 (x2+4) ; sh w3 0 ; if receiver(buf) < 0 then jl i4 ; begin comment: buf claimed. now release claim; rs w3 x2+4 ; receiver(buf) := -receiver(buf); i.e. positive; rl w1 b21 ; cur = driverproc bz w3 x1+a19 ; increase(buf claim(cur)); al w3 x3+1 ; hs w3 x1+a19 ; end; i4: am (b19) ; al w1 +a54 ; jl w3 d6 ; link(mess q(proc), buf); se w3 x1 ; if old last <> mess q(proc) then c33: jl (b20) ; goto wait next(driver process); al w1 x1-a54 ; w1 := proc; rl w0 x1+a56 ; w0 := interrupt addr(proc); so w0 2.1 ; if interrupt addr(proc) is odd then jl w3 g64 ;+2 goto wait next(driver process); jl (b20) ;+2 examine queue: empty => goto wait next; jl (i3) ; return e. ; procedure check user ; comment: checks whether an external process is used ; by the current internal process. if the external is reserved ; it is also checked whether it is reserved by the current ; internal process. ; call: return: ; w0 destroyed ; w1 cur cur ; w2 buf buf ; w3 link destroyed b. i5 w. g14: ; check user; sn w1 (b 21) ; if curr.intproc=driverproc then jl x3 ; return ds w3 i3 ; save w2 w3; rl w2 b19 ; w2:= extproc; jl w3 d113 ; check reserver; jl g6 ; return 0 other reservers goto result 2 else jl i0 ; return 2 intproc is reserver goto nornal return else ; return 4 no reservers jl w3 d102 ; check user jl g6 ; if not user then result 2 else i0: rl w2 i2 ; jl (i3) ; normal return; i2: 0 ; save w2; i3: 0 ; save w3; e. ; end ; procedure check reservation ; comment: checks whether an external process is reserved ; by the current internal process. ; call: return: ; w0 reserved ; w1 cur cur ; w2 buf buf ; w3 link link b.i24 ; begin w. g15: ; check reserver; sn w1 (b 21) ; if curr.intproc= driverproc then jl x3 ; return ; am (b19) ; rl w0 a52 ; w0:=reserver.extproc; sn w0 (x1+a14) ; if intproc is reserver then jl x3 ; normal return else jl g6 ; result 2; e. ; end ; procedure check operation(oper mask, mode mask) ; comment: checks whether the operation and mode are ; within the repertoire of the receiver. the legal values are ; defined by two bitpatterns in which bit i=1 indicates ; that operation (or mode) number i is allowed. if the ; operation is odd, it is checked whether the input/output ; area is within the internal process. ; call: return: ; w0 oper mask destroyed ; w1 mode mask destroyed ; w2 buf buf ; w3 link destroyed b.i24 ; begin w.g16:rs w3 i0 ; bz w3 x2+9 ; ls w1 x3+0 ; bz w3 x2+8 ; ls w0 x3+0 ; sh w0 -1 ; if mode mask(mode(buf))=0 sl w1 0 ; or oper mask (operation(buf))=0 jl g5 ; then goto result 3; so w3 1 ; jl (i0) ; rl w1 x2+6 ; dl w0 x2+12 ; if odd(operation(buf)) la w3 g50 ; make first and la w0 g50 ; last address in buf even; sl w3 (x1+a17) ; and (first addr(buf)<first addr(sender) sl w0 (x1+a18) ; or last addr(buf)>=top addr(sender) jl g5 ; sh w0 x3-2 ; or first addr(buf)>last addr(buf)) jl g5 ; then goto result 3; ds w0 x2+12 ; message even; jl (i0) ; i0: 0 ; e. ; end ; input/output answer: w.g20: 0 ; status g21: 0 ; bytes g22: 0 ; characters g23: 0 ; file count g24: 0 ; block count g40: 0 ; word5 g41: 0 ; word6 g42: 0 ; word7 0 ; mess(1) operation g29: 0 ; mess(2) first 0 ; mess(3) last g30: 0 ; mess(4) segment no ; procedure next operation ; comment: examines the message queue of the receiver and ; returns to the receiver if there is a message from a ; not-stopped sender. otherwise it returns to the current ; internal process. ; call: return: ; w0 oper ; w1 proc ; w2 buf ; w3 link sender b.i24 ; begin w.g25:rs w3 i2 ; jl w3 g64 ; examine queue( jl c33 ; dummy interrupt); jl (i2) ; i2: 0 ; e. ; end ; procedure examine queue(queue empty) ; call: return: ; w0 operation ; w1 proc ; w2 buf ; w3 link sender b.i24 ; begin w.g64:rs w3 i2 ; i0: rl w1 b19 ; exam q:proc:=current receiver; rl w2 x1+a54 ; buf:=next(mess q(proc)); sn w2 x1+a54 ; if buf=mess q(proc) jl (i2) ; then goto queue empty; rs w2 b18 ; rl w3 x2+6 ; internal:=sender(buf); xl x2+8 ; sh w3 -1 ; ac w3 x3+0 ; bz w0 x3+a13 ; rl w3 x2+6 ; if state(internal)=stopped sx 2.1 ; and operation(buf)(23)=1 so w0 a105 ; or internal<0 sh w3 -1 ; then jl i1 ; begin bz w0 x2+8 ; am (i2) ; no operation; jl 2 ; goto exam q; i1: jl w3 g26 ; end; jl i0 ; oper:=byte(buf+8); i2: 0 ; e. ; end ; procedure no operation ; call: return: ; w0 destroyed ; w1 proc ; w2 destroyed ; w3 link destroyed b.i24 ; begin w.g26:al w0 1 ; g27:al w1 0 ; rs w1 g20 ; status:= g28:rs w1 g21 ; bytes:= rs w1 g22 ; character:=0; jl g19 ; deliver result(1); e. ; end ; procedure increase stop count ; comment: increases the stop count of the sender by 1. ; call: return: ; w0 unchanged ; w1 unchanged ; w2 buf buf ; w3 link destroyed b.i24 ; begin w.g31:rs w3 i0 ; am (x2+6) ; bz w3 a12 ; al w3 x3+1 ; stop count(sender(buf)):= am (x2+6) ; stop count(sender(buf))+1; hs w3 a12 ; jl (i0) ; i0: 0 ; e. ; end ; procedure decrease stop count ; comment: the stop count of the sender is decreased by 1 ; if the operation is odd. if stop count becomes zero and the ; sender is waiting to be stopped, the sender is stopped ; and the stop count of its parent is decreased by 1. ; if the parent has stopped its child, an answer is sent to ; the parent in the buffer defined by the wait address of ; the child. ; call: return: ; w0 destroyed ; w1 destroyed ; w2 destroyed ; w3 link destroyed b.i24 ; begin w.g32:rs w3 i3 ; rl w2 b18 ; zl w0 x2+a138+1 ; rl w3 x2+6 ; internal:=sender(buf); sz w0 2.0000001 ; if io_operation(buf)) sh w3 -1 ; and internal>=0 then jl (i3) ; begin bz w0 x3+a12 ; bs. w0 1 ; stop count(internal):= hs w0 x3+a12 ; stop count(internal)-1; i0: se w0 0 ; exam stop: jl (i3) ; if stop count(internal)=0 bz w1 x3+a13 ; and state(internal)=wait stop so w1 a105 ; then jl (i3) ; begin al w1 x1+a106 ; child state:= hs w1 x3+a13 ; state(internal):=wait start; rl w2 x3+a40 ; buf:=wait address(internal); rl w3 x3+a34 ; internal:=parent(internal); bz w0 x3+a12 ; bs. w0 1 ; stop count(internal):= hs w0 x3+a12 ; stop count(internal)-1; se w1 a99 ; if child state<>wait start parent jl i0 ; then goto exam stop; ; let the driver claim the buffer, so that ; it may send the answer: rl w1 b21 ; ac w0 x1 ; receiver(buf) := -cur; (i.e. claimed) rs w0 x2+4 ; bz w3 x1+a19 ; decrease(bufclaim(cur)); al w3 x3-1 ; (even if claims would be exceeded) hs w3 x1+a19 ; rl w1 x1+a17 ; answer area := first addr(cur); al w0 1 ; result := 1; jd 1<11+22; send answer; jd (i3) ; return disabled; i2: 0 ; i3: 0 ; e. ; end ; procedure exam sender(sender stopped) ; call: return: ; w0 unchanged ; w1 unchanged ; w2 unchanged ; w3 link link b.i24 ; begin w.g34:rs w3 i0 ; am (b18) ; rl w3 6 ; internal:=sender(buf); sh w3 -1 ; jl (i0) ; if internal<0 bz w3 x3+a13 ; sz w3 a105 ; or state(internal)=stopped jl (i0) ; then goto sender stopped; rl w3 i0 ; jl x3+2 ; i0: 0 ; e. ; end ; procedure check i-o transfer (document size, message); ; ; call return ; w0 size of document size of document ; w1 - unchanged ; w2 message message ; w3 link destroyed ; g37: ; jl. (+2) ; goto check i-o transfer; d146 ; ; procedure follow chain(no. of slices,chain table index, slice) ; the return value is the chain table index of entry number <no. ; of slices> in the chain starting at <chain table index> ; call: return: ; w0 n.o.s. destroyed ; w1 unchanged ; w2 c.t.i. slice ; w3 link destroyed b.i8 w.d74:rs w3 i3 ; save return ac w3 (0) ; as w3 1 ; count := -2 * no. of slices jl. i2. ; goto test; repeat: i0: sl w3 -30 ; if count >= -30 jl. x3+i1. ; then goto advance(-count) ba w2 x2 ; r. 16 ; i1: al w3 x3+32 ; count := count + 32 i2: sh w3 -2 ; test: if count < 0 jl. i0. ; then goto repeat jl (i3) ; return i3: 0 ; e. ; ; procedure test users , reserver, and writeprotecters(intproc,extproc); ; reg call return ; w0 undef ; w1 intproc unchanged ; w2 extproc unchanged ; w3 link result ; the procedure set result = 2.000001 if intproc is user ; = 2.000011 if intproc is reserver (and user) ; = 2.000101 if intproc and other ip are users ; = 2.000100 if there only are other users ; = 2.001100 if another ip is reserver (and user) ; = 2.01---- if intproc has writeprotected ; = 2.10---- if other(s) has writeprotected ; = 2.11---- if intproc and other(s) has writeprotected ; writeprotection bit can only be set if the extprocess is an areaprocess. ; of extproc else result is set to zero b. i5,j5 w. d76: ds. w3 j1. ; save(link,extproc); rl w0 x2+a52 ; w0:=reserver.extproc; al w3 2.10 ; sn w0 (x1+a14) ; if intproc is reserver then jl. i3. ; goto test other users; al w3 0 ; se w0 0 ; if there is another reserver then al w3 2.1000 ; set other-reserver bit; i3: ba w2 x1+a14 ; w2:=addr(bitpattern.intproc); bz w0 x2 ; w0:= bitpattern.intproc; sz w0 (x1+a14) ; if userbit.intproc is on then al w3 x3+1 ; w3:=w3+1 <* set intproc is user *> else al w2 a402 ; i0: am. (j0.) ; bz w0 x2 ; w0:=next pattern.userbittable; sn w0 0 ; if no users then jl. i1. ; goto f1; hs w2 0 ; sn w0 (x1+a14) ; if only intproc is user then jl. i1. ; goto f1 else al w3 x3+4 ; result:=result add 2.0100; jl. i2. ; goto return; i1: al w2 x2+1 ; w2:=next rel addr; se w2 a402+a403 ; if not end bittable then jl. i0. ; goto f0; i2: rl. w2 j0. ; if extproc=area then rl w0 x2+a10 ; begin se w0 4 ; jl. i5. ; rs. w3 j0. ; <* save result *> jl. w3 d114. ; check writeprotect(intproc, extproc); jl. i4. ;+0: none: am -2 ; j3;+2: intproc: am -2 ; j4;+4: other(s): rl. w0 j5. ;+6: intproc + other(s): rl. w3 j0. ; ea w3 1 ; <* add writeprotection bits *> sz ; end; i4: ; rl. w3 j0. ; i5: jl. (j1.) ; return; j0: 0 j1: 0 j3: 2.010000 ; intproc j4: 2.100000 ; other(s) j5: 2.110000 ; intproc + other(s) e. ; procedure check writeprotect(internal, proc); ; call return ; w0 - unchanged ; w1 internal unchanged ; w2 proc unchanged ; w3 link unchanged ; ; return: link + 0: no internal has writeprotected ; link + 2: only named internal has writeprotected ; link + 4: other than named internal has writeprotected ; link + 6: internal + other has writeprotected ; b. i10, j10 w. d114: ; begin ds. w3 i3. ; save registers; ds. w1 i1. ; zl w0 x1+a14+1 ; <* save internal.idbit mask *> rs. w0 i4. ; ea w2 x1+a14 ; al w2 x2+a404 ; <* save addr of id-bit element *> rs. w2 i5. ; rl. w3 i2. ; al w2 x3+a405 ; <* w2: first writeprotect bit element, al w3 x3+a250 ; w3: top of writeprotect bit array, al w1 0 ; w1: state = <no internal has writeprotected> *> j0: ; repeat begin zl w0 x2 ; if element <> 0 then sn w0 0 ; begin jl. j2. ; sn. w2 (i5.) ; if element.addr = int.bitelement and so. w0 (i4.) ; element.bit(int.idbit) is on jl. j1. ; al w1 x1+ 2 ; then state := state and <int has writeprot>; sn. w0 (i4.) ; if element.addr <> int.bitelement or jl. j2. ; other than int.idbit is on j1: sh w1 2 ; then state := state and <others has writeprot>; al w1 x1+ 4 ; end; j2: ; end until al w2 x2+ 1 ; element = top element; se w2 x3 ; jl. j0. ; ; dl. w3 i3. ; <* restore registers and wa w3 2 ; modify return addr with state *> dl. w1 i1. ; jl x3 ; end; ; 0 ; save w0: i1: 0 ; save w1: int i2: 0 ; " " : proc i3: 0 ; " " : link i4: 0 ; id bit of internal i5: 0 ; writeprotect id bit element addr in proc e. ; procedure check user; ; ; call: w1=internal, w2=proc, w3=link ; exit: w0=undef, w1, w2, w3=unchanged ; return address: link+2: cur was user ; link : cur was not user d102: ; begin ba w2 x1+a14 ; bz w0 x2 ; w0:=internal.userbit; bs w2 x1+a14 ; reset w2; sz w0 (x1+a14) ; if internal is user then jl x3+2 ; return(link+2) else jl x3 ; return(link); ; end; ; procedure check any reserver; ; ; call: w1=internal, w2=proc, w3=link ; exit: w0=undef, w1, w2, w3=unchanged ; return address: link : other process is reserver ; link+2: internal is reserver ; link+4: not reserved by anyone d113: ; begin rl w0 x2+a52 ; if proc.reserver=0 then sn w0 0 ; jl x3+4 ; return(link+4); se w0 (x1+a14) ; if proc.reserver<>internal.idbit then jl x3 ; return(link+0); <* other reserver *> jl x3+2 ; return(link+2); <* internal reserver *> ; end; ; procedure insert writeprotect(internal, proc) ; ; call w1=internal, w2=proc, w3=link ; exit w0=undef, w1, w2, w3=unchanged ; d118: ; begin ea w2 x1+a14 ; element:=proc.userbit element; zl w0 x2+a404 ; w0:=proc.writeprotect element; lo w0 x1+a14 ; w0:=proc.writeprotect element or internal.idbit; hs w0 x2+a404 ; proc.writeprotect element:=updated writeprotect element; es w2 x1+a14 ; jl x3 ; end; ; procedure remove writeprotect(internal, proc); ; ; call: w1=internal, w2=proc, w3=link ; exit: w0=undef, w1, w2, w3=unchanged ; d119: ; begin ea w2 x1+a14 ; zl w0 x2+a404 ; element:=proc.userbitelement - displacement; sz w0 (x1+a14) ; if element.bit(intproc.idbit) is on then lx w0 x1+a14 ; element.bit(intproc.idbit):=0; hs w0 x2+a404 ; es w2 x1+a14 ; jl x3 ; end; ; ****** indirect addressed monitor routines ****** ; procedure conditional reschedule (eq d20) ; procedure unconditional reschedule (eq d21) ; conditional: if 'no fo free pu' = 0 the internal is rescheduled. ; call return ; w0 - destroyed ; w1 internal internal ; w2 - destroyed ; w3 link destroyed ; b. i10 w. d40: rl w2 (b59) ; conditional reschedule: rl w2 x2 ; begin se w2 0 ; if no of free pu > 0 then jl x3 ; return; ; d41: rs. w3 i3. ; unconditional reschedule: al w0 a95 ; jl w3 d9 ; deactivate process(internal, waiting for cpu); sn w0 a95 ; if not internal.stopped then jl w3 d10 ; link internal(internal); jl. (i3.) ; ; i3: 0 ; e. ; end; ; procedure check and search name (=d17+d11 -> d67+d44) (eq d101) ; ; call: w1=cur, save w3(cur)=name, w3=link ; exit: w0, w1=unchanged, w2=name, w3=entry ; return address: link: entry not found ; link+2: entry found ; c29 : name area outside current process b. i25 w. d43: ; ds. w1 i1. ; save(w0, cur); rl w2 x1+a31 ; name:=save w3(cur); al w0 x2+6 ; sh w0 0 ; if overflow or jl c29 ; sl w2 (x1+a17) ; name<first addr(cur) or sl w0 (x1+a18) ; name+6>=top addr(cur) then jl c29 ; goto internal 3; dl w1 x1+a43 ; w0w1:=catbase(cur); jl. i14. ; goto search name(name, entry, base); ; the following procedures searches the name table for a given entry and delivers its entry in ; the name table. if name is undefined, the entry is name table end. ; procedure search name(name, entry); (eq d11) ; call: w2=name, w3=link ; exit: w0, w1, w2=unchanged, w3=entry ; return address: link : name not found, w3=(b7) ; link+2: name found d44: ds. w1 i1. ; save(w0, w1); am (b1) ; dl w1 +a43 ; base:=catbase(cur); i14: al w3 x3+1 ; link := link + 1; i.e. destinguish between normal and error return; ; procedure search name(name, entry, base); (eq d71) ; call: w0, w1=base, w2=name, w3=link ; exit: w0, w1=undef, w2=unchanged, w3=entry ; return address: link : name not found, w3=(b7) ; link : name found, w3 <> (b7) d45: ds. w3 i3. ; save (name, return); ds. w1 i20. ; save search base; i4: al w1 x1-1;used ; bs. w0 i4.+1 ; ds. w1 i6. ; base:=base+(1, -1); dl w1 d73 ; ds. w1 i8. ; min base:=extreme; rl w1 b7 ; rs. w1 i9. ; found:=name table end; rl w1 b1 ; get physical name address b. h1 w. ; if mp then am (b9) ; h0=k jl. 0 ; begin gg w1 b104 ; get cur register; c.(:h0+a8-k-1:) am 0, r.(: h0+a8+2-k :)>1 ; fill up z. e. ; end mp wa w2 x1+a182 ; dl w1 x2+6 ; ds. w1 i13. ; move name to last name in name table; dl w1 x2+2 ; sn w0 0 ; if name(0)<>0 then jl. i18. ; ds. w1 i11. ; rl w3 b3 ; for entry:=name table start jl. i17. ; i15: dl. w1 i11. ; i16: al w3 x3+2 ; step 2 until name table end do i17: rl w2 x3 ; sn w1 (x2+a11+2) ; begin se w0 (x2+a11+0) ; proc:=name table(entry); jl. i16. ; dl. w1 i13. ; sn w0 (x2+a11+4) ; se w1 (x2+a11+6) ; if name.proc=name and jl. i15. ; sn. w2 (i21.) ; jl. i18. ; dl w1 x2+a49 ; sl. w0 (i7.) ; lower.proc>=lower.min and sl. w0 (i5.) ; lower.proc<=lower.base and jl. i15. ; sh. w1 (i8.) ; upper.proc<=upper.min and sh. w1 (i6.) ; upper.proc>=upper base then jl. i15. ; begin ds. w1 i8. ; min:=interval.proc; rs. w3 i9. ; found:=entry; sn. w0 (i19.) ; if base.proc = search base se. w1 (i20.) ; then goto found; jl. i15. ; end; i18: ; end; dl. w0 i0. ; restore(w0, w1, w2); dl. w2 i2. ; w3:=found; sn w3 (b7) ; if w3=name table end then jl. (i3.) ; return to link am. (i3.) ; else jl +1 ; return to link+1; i9: 0 ;i0-2: found (i.e. current best entry, or (b7)) i0: 0 ;i1-2: saved w0 i1: 0 ;i2-2: saved w1 i2: 0 ;i3-2: saved w2 i3: 0 ; saved return i5: 0 ;i6-2: lower base+1 for search i6: 0 ; upper base-1 for search i7: 0 ;i8-2: lower minimum i8: 0 ; upper minimum ; the last entry in name table must point here: c98 = k-a11 i10: 0 ; name to search for i11: 0 ; i12: 0 ; i13: 0 ; i19: 0 ; search base i20: 0 ; i21: c98 ; e. ; ; procedure remove user(internal, proc); <* eq d123 *> ; procedure remove reserver(internal, proc); <* eq d124 *> ; ; removes the id-bit of the internal from the reserver and/or user fields. ; ; call return ; w0 - destroyed ; w1 internal internal ; w2 proc proc ; w3 link link ; d53: ; remove user ba w2 x1+a14 ; begin zl w0 x2 ; if proc.userbits(internal.id-bit) is on then sz w0 (x1+a14) ; proc.userbits(internal.id-bit) := 0; bs w0 x1+a14+1 ; hs w0 x2 ; bs w2 x1+a14 ; if proc.reserver = internal then remove reserver; ; end; ; d54: ; remove reserver rl w0 x2+a52 ; begin sn w0 (x1+a14) ; if proc.reserver = internal then al w0 0 ; proc.reserver := 0; rs w0 x2+a52 ; jl x3 ; end; ; procedure insert reserver(internal, proc); <* eq d125 *> ; procedure insert user(internal, proc); <* eq d126 *> ; adds the id-bit of the internal to reserver-/user-fields of proc. ; ; call return ; w0 - destroyed ; w1 internal internal ; w2 proc proc ; w3 link link ; d55: ; insert reserver rl w0 x1+a14 ; begin rs w0 x2+a52 ; proc.reserver := internal.id; ; goto insert user; ; end; ; d56: ; insert user ba w2 x1+a14 ; begin zl w0 x2 ; lo w0 x1+a14 ; proc.idbit(internal.id) := 1; hs w0 x2 ; bs w2 x1+a14 ; jl x3 ; end; ; procedure claim buffer(cur, buffer); <* eq d108 *> ; ; call return ; w0 - destroyed ; w1 cur cur ; w2 buffer buffer ; w3 link link ; b. i0 w. d58: ; claim buffer zl w0 x1+a19 ; begin sn w0 0 ; if cur.bufferclaim <> 0 then jl. i0. ; begin bs. w0 1 ; cur.bufferclaim := cur.bufferclaim - 1; hs w0 x1+a19 ; ac w0 (x2+a141) ; buffer.receiver := -buffer.receiver; rs w0 x2+a141 ; jl x3 ; <* ok return *> ; end i0: ; else rs w0 x1+a30 ; begin cur.saved w2 := 0; jl c99 ; goto return from interrupt; ; end; e. ; end; ; procedure regretted message(buffer); <* eq d75 *> ; simulates the release of a messge buffer, as in wait answer. the bufferclaim ; of the sender is increased. the buffer is removed and released (unless in ; state = received). ; ; call return ; w0 - unchanged ; w1 - unchanged ; w2 buffer buffer ; w3 link destroyed ; b. i10, j10 w. d65: ; regretted message rs. w3 i3. ; begin ds. w1 i1. ; rl w1 x2+a142 ; sh w1 0 ; if message.sender < 0 then exit; <* buffer already regretted *> jl. j6. ; ac w0 x1 ; message.sender := -message.sender; <* indicates message regretted *> rs w0 x2+a142 ; rl w0 x1+a10 ; if sender.kind = pseudo proc or se w0 64 ; sender.kind = csp_terminal then sn w0 q8 ; sender:= sender.main; rl w1 x1+a50 ; sz w0 -1-64 ; if sender.kind<>internal and sender.kind<>pseudo then rl w1 x1+a250 ; sender := sender.driverproc; ; zl w3 x1+a19 ; sender.bufferclaim := sender.bufferclaim + 1; al w3 x3+1 ; hs w3 x1+a19 ; ; rl w1 x2+a141 ; receiver := abs(message.receiver); sh w1 0 ; ac w1 x1 ; if receiver < 5 then sh w1 5 ; goto remove and release; jl. j5. ; <* message contains an answer *> ; rl w0 x1+a10 ; if receiver.kind <> internal and rl w3 x1+a250 ; receiver.kind <> pseudo and se w0 0 ; receiver.driverproc < 0 then sn w0 64 ; begin sz ; <* ida/ifp process - receiver driven by monitor *> sl w3 0 ; jl. j2. ; ; j0: sn w0 q20 ; proc := receiver; jl. j1. ; sn w0 q26 ; jl. j1. ; while proc.kind <> main do rl w1 x1+a50 ; proc := proc.main; rl w0 x1+a10 ; jl. j0. ; ; j1: al w3 2.1000 ; if message.state = stopped then zl w0 x2+a138+1 ; return sz w0 x3 ; else jl. j6. ; message.state := stopped; lo w0 6 ; hs w0 x2+a138+1 ; ; sn w2 (x1+a81) ; if message = main.waiting_queue.first then jl. j6. ; return; jl w3 d5 ; unlink(message); al w0 1 ; jl. d142. ; test ready and setup(message,force)); ; <* it will exit with return from interrupt - the ; setup procedure of the receiver will take care ; of a proper action on the regretted message *> ; end; j2: ; <* receiver is not an subprocess *> rl w1 x2+a141 ; if message.claimed then sl w1 0 ; begin jl. j3. ; se w0 q20 ; sn w0 q26 ; if receiver.kind = main then sz ; jl. j6. ; begin al w3 2.1000 ; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 x3 ; return; <already stopped> jl. j6. ; lo w0 6 ; message.state := stopped; hs w0 x2+a138+1 ; ac w1 x1 ; if message = main.waiting_queue.first or se w2 (x1+a81) ; not message.in_queue then sn w2 (x2+a140) ; return jl. j6. ; else begin jl w3 d5 ; unlink(message); al w0 1 ; jl. d142. ; test ready and setup(message,force); ; end; ; end ; else return; ; end; j3: ; <* the message is neither answer nor claimed *> se w0 0 ; if receiver.kind = internal or sn w0 64 ; receiver.kind = pseudo then jl. j5. ; goto remove and release; se w0 4 ; if receiver.kind = area then jl. j4. ; rl w1 x1+a50 ; receiver := receiver.main.main; <* physical disc proc *> rl w1 x1+a50 ; j4: se w2 (x1+a54) ; if receiver.event_q.first = message then jl. j5. ; begin al w0 -1 ; wa w0 x1+a56 ; if receiver.interrupt_addr is even then sz w0 2.1 ; receiver.interrupt_addr:=receiver.intterupt_addr-1; rs w0 x1+a56 ; end; ; j5: jl w3 d106 ; remove and release(message); ; j6: dl. w1 i1. ; exit: jl. (i3.) ; return; ; i0: 0 ; saved registers i1: 0 ; i3: 0 ; ; e. ; end; ; procedure move message(from, to); <* eq d14 *> ; moves 8 words (message or answer) from a given storage address to another. ; ; call return ; w0 - destroyed ; w1 from from ; w2 to to ; w3 link destroyed ; b. i0 w. d64: ; move message rs. w3 i0. ; begin dl w0 x1+2 ; ds w0 x2+2 ; <* move the words *> dl w0 x1+6 ; ds w0 x2+6 ; dl w0 x1+10 ; ds w0 x2+10 ; dl w0 x1+14 ; ds w0 x2+14 ; jl. (i0.) ; ; i0: 0 ; ; e. ; end; ; procedure check mess area and name (save w3) area; ; procedure check name (save w3) area; ; procedure check name (save w2) area; ; call return ; w0 - destroyed ; w1 cur cur ; w2 - name ; w3 link link d66: ; check message area and name area: rl w2 x1+a29 ; begin al w0 x2+14 ; mess := cur.save w1; sh w0 0 ; if overflow or jl c29 ; mess < cur.first address or sl w2 (x1+a17) ; mess >= cur.top address then sl w0 (x1+a18) ; goto internal 3; jl c29 ; d67: ; check name (save w3) area: am a31-a30 ; d115: ; check name (save w2) area: rl w2 x1+a30 ; al w0 x2+6 ; ; continue with d116! ; procedure check within (first, last); ; checks taht the specified area is within the process ; call return ; w0 last last ; w1 cur cur ; w2 first first ; w3 link link ; return: link: within process ; c29 : not within d116: ; check within: sh w0 0 ; if overflow or jl c29 ; first < cur.first address or sl w2 (x1+a17) ; last >= cur.top address then sl w0 (x1+a18) ; goto internal 3; jl c29 ; jl x3 ; end; ; procedure check message area and buf ; call return ; w0 - destroyed ; w1 cur cur ; w2 - buf ; w3 link link ; return: link: ok ; c29 : mess area outside cur ; c29 : buf not message buf d117: ; check message area and buf: rl w2 x1+a29 ; begin al w0 x2+14 ; mess := cur.save w1; sh w0 0 ; if overflow or jl c29 ; mess < cur.first address or sl w2 (x1+a17) ; mess+14 >= cur.top address then sl w0 (x1+a18) ; goto internal 3; jl c29 ; ; continue with check message buf ; procedure check message buf; ; checks whether the save w2 of the internal process is a mess buf addr. ; call return ; w0 - destroyed ; w1 internal cur ; w2 - buf ; w3 link link ; return: link: buffer ok ; c29 : save w2 not mess buf b. i0 w. d68: ; check message buf: rl w2 x1+a30 ; buf := internal.sawe w2; sl w2 (b8+4) ; if buf < mess buf pool start or sl w2 (b8+6) ; buf >=mess buf pool top then jl c29 ; goto internal 3; al w1 x2 ; ws w1 b8+4 ; if (buf-poolstart-4) modulo size of message <> 0 al w1 x1-a7 ; then goto internal 3; al w0 0 ; wd w1 b8+8 ; rl w1 b1 ; w1 := cur sn w0 0 ; jl x3 ; return jl c29 ; e. ; end; ; procedure check event (proc, buf); ; checks that buf is the address of an operation in the event queue of the internal process ; call return ; w0 - destroyed ; w1 proc proc ; w2 buf buf ; w3 link link ; return: link: buffer address ok ; c29 : buf is not in the queue b. i0 w. d69: ; check event: al w0 x2 ; begin al w2 x1+a15 ; oper := proc.next; i0: rl w2 x2+0 ; next: oper := oper.next; sn w2 x1+a15 ; if oper = proc.eventq then jl c29 ; goto internal 3; <*not in queue*> se w0 x2 ; if buf <> oper then goto next; jl. i0. ; jl x3 ; return; e. ; end; ; external interrupt entry: ; ; when an external interrupt occurs, or when 'user exception first' ; or 'user escape first' are zero, the cpu will save all registers ; in the current process descrition. ; exit is made to here with: ; w2 = 2 * interrupt number ; ex = 0 b. i3 w. c1: al w1 x2 ; interruptstat(intno) := ls w1 1 ; interruptstat(intno) + 1; wa w1 b79 ; rl w0 x1+2 ; ba. w0 +1 ; rs w0 x1+2 ; se w0 0 ; jl. i3. ; rl w0 x1+0 ; <* count in double words *> ba. w0 +1 ; rs w0 x1+0 ; i3: ; wa w2 b0 ; rl w1 b51 ; w1 := current process sh w1 0 ; if cur defined then jl. c3. ; begin rs w1 b1 ; process in monitor := cur; al w0 1 ; if rescedule count.cpuno > max then al w3 0 ; rescedule process b. h1 w. ; am (b9) ; h0=k ; jl. 0 ; gg w3 b108 ; c. (:h0+a8-k-1:) ; am 0, r.(:h0+a8+2-k:)>1; z. e. ; ds. w2 i2. ; wa w0 x3+b83 ; if reschedule count > max or rs w0 x3+b83 ; internal.state <> running zl w3 x1+a13 ; then sh w0 a83 ; unconditional reschedule se w3 a94 ; else am d21-d20; conditional reschedule; jl w3 d20 ; dl. w2 i2. ; jl. c3. ; switch out through interrupt-table; i1: 0 ; saved proc i2: 0 ; saved intno e. ; monitor call entry: ; ; if the current process executes a montor call, the cpu will ; save all the registers in the current process description. ; exit is made to here with: ; w1 = top register dump ; w2 = monitor function ; ex = 0 c0: rl w1 b51 ; rs w1 b1 ; process in monitor := cur; zl w0 x1+a13 ; if internal.state =waiting for stop then so w0 a105 ; begin jl. c7. ; jl w3 d9 ; deactivate process rl w2 x1+a33 ; internal.ic := internal.ic - 2 al w2 x2-2 ; rs w2 x1+a33 ; (repeat monitor call later if started) jl c99 ; c7: al w3 x2 ; moncalltable(call no) := ls w3 -1 ; moncalltable(call no) + 1; ls w3 +2 ; <* make odd calls even *> wa w3 b81 ; rl w0 x3+2 ; ba. w0 +1 ; rs w0 x3+2 ; se w0 0 ; jl. c3. ; rl w0 x3+0 ; ba. w0 +1 ; <* count in double words *> rs w0 x3+0 ; c3: am. (+4) ; switch out through monitor procedure entry table; jl (x2+0) ; b16 ; <*address of monitor entry table*> ; second level external interrupt entry: ; ; exit is made to here with: ; w1 = top register dump ; w2 = 2 * interrupt number c8: sn w2 2*7 ; if clock interrupt then ri a179 ; exit to monitor; sn w2 2*6 ; if cause = powerfail then jl. c6. ; goto power fail routine; jl -3<1 ; halt; ; program errors in the current process are transferred to here, ; (as external interrupts): ; ; w1 = cur c2: ; internal interrupts, overflow, spill, escape errors: ; monitor bugs (i.e. exception- or escape-addresses ; outside write-limits of process) c4: ; bus error in operand transfer: (no strategy yet) c5: ; bus error in instruction fetch: (- - - ) jl w2 (b31) ; call errorlog al w0 a96 ; state := running after error; al w3 c99 ; zl w2 x1+a13 ; if process active then se w2 a95 ; deactvate process (and return) jl d9 ; hs w0 x1+a13 ; else begin al w2 x1+a16 ; process.state := running after error; al w3 c99 ; unlink proc from active queue jl d5 ; end; return ; power failure: ; ; may occur at any level ; ; save the current interrupt stack entry address, unless ; already saved ; (this should prevent powerfail-cascades from disturbing the system) b. h10, i10 w. ; c6: gg w2 b91 ; w2 := current stack element; rl. w3 h0. ; w3 := previous power up element; sn w3 0 ; if previous element is free then rs. w2 h0. ; power up element := current stack element; al w2 0 ; ilevc := 0; gp w2 b90 ; (i.e. the following will provoke a systemfault) jl -1<1 ; halt; h0: b49 ; power up element: initially monitor element ; power up: ; ; initialize: montop (i.e. max monitor function) ; size (i.e. core size) ; inf (i.e. power up element) ; ; initialize pu information table and if the pu is a mp then start all remaining cpus. ; clear any pending interrupt bits, because they may be irrellevant ; ; entry conditions: ; inf register = 1 ; totally disabled c25: al w3 -1<11 ; montop := 1 < 11 ac w3 x3+b17 ; - top monitor function number; gp w3 b93 ; rl w2 b59 ; pu inf table.montop := montop; rs w3 x2+a352 ; rl w3 b12 ; size := number of storage bytes; gp w3 b92 ; rs w3 x2+a353 ; pu inf table.size := size; am +12 ; al w3 b49 ; rs w3 x2+a351 ; pu inf table.inf := inf; rl w3 b9 ; sn w3 a8 ; if pu kind = mp then jl. i3. ; begin rl w3 x2+a350 ; iopu.pu tabel register := pu inf table.pu tabel; gp w3 b105 ; rl w3 x2+a354 ; iopu.exofs register := pu inf table.exception offset; gp w3 b106 ; rl w3 x2+a355 ; iopu.dmofs register := pu inf table.dump offset; gp w3 b107 ; ; ; start all remaining cpus al w0 1 ; no of cpues := 1; rs w0 b82 ; al w0 a194 ; interruptlevel := 8; <*start pu*> rl w1 b67 ; for i := 1 step 1 until max dev do i5: al w1 x1+a314 ; if controllertabel(i).chpadr = pu inf tabel then sl w1 (b68) ; begin <*pu-element*> jl. i2. ; rl w3 x1+a310 ; se w3 (b59) ; jl. i5. ; puaddr := (controllertabel(i) - rl w3 b82 ; al w2 x1 ; controllertabel(0)) * 8 and (1 shift 23); ws w2 b67 ; lo w2 g49 ; do w0 x2 ; start pu(puaddr, interruptlevel); sx 2.111 ; if pu is started then sz ; ba. w3 1 ; no of cpues := no of cpues + 1; rs w3 b82 ; jl. i5. ; end; ; end; i3: ; else al w0 0 ; set free pu := 0 rs w0 (x2) ; (* always rescedule when external interrupt *) i2: ; c.(:a90>0 a.1:)-1 al. w3 i1. ; dump core via fpa jl. (2) ; d140 ; i1: ; z. al w3 6 ; ilevc := 0 < 12 + 6; gp w3 b90 ; i.e. enable for powerfail; rl. w3 h0. ; w3 := power up element; sn w3 0 ; if power up element = 0 then jl -2<1 ; halt; i.e. power fail was not serviced; rs w3 b75 ; after powerfail := true; ; (should be tested by clockdriver) rl w2 b73 ; intno := max external interrupt number; i0: gp w2 b95 ; rep: clear (intno) in cpu; al w2 x2-1 ; intno := intno - 1; sl w2 6+1 ; if intno > powerfail then jl. i0. ; goto rep; al w1 0 ; (prepare a new h0...) je. +2 ; (if any power fail during this start up, jd. +2 ; it will be 'serviced' now, i.e. systemfault) ; the following sequence of instructions have to be executed ; without any disturbance, else the system won't work rs. w1 h0. ; clear previous power up element; ; (i.e. prevent two consecutive powerups) gp w3 b91 ; inf := power up element; ri a179 ; return interrupt; ; (the limit-copies must be initialized) e. ; end of power fail/restart ; parameter errors in monitor call: ; ; all monitor procedures check that the parameters are ; within certain limits. ; if the parameters are wrong, the calling process is break'ed. ; ; (all regs irrellevant) b. j10 w. ; ; definitin of exception regdump: j0 = a29 - a28 ; w0, w1 j1 = a31 - a28 ; w2, w3 j2 = a33 - a28 ; status, ic j3 = a177- a28 ; cause, sb a180 = j3 + 2 ; top of exception regdump = new rel ic j4: c2 ; c28 : ; internal 3: rl w1 b1 ; rs w3 x1+a339 ; make footprint! al w3 6 ; rs w3 x1+a176 ; cause (cur) := 6; i.e. monitor call break; rl w2 x1+a27 ; w2 := exception address (cur); sn w2 0 ; if exception address = 0 then jl. (j4.) ; goto internal interrupt; al w3 x2 ; save w2 and jl w2 (b31) ; call errorlog al w2 x3 ; restore w2 wa w2 x1+a182 ; w2 := abs exception address; dl w0 x1+a29 ; move: save w0 ds w0 x2+j0 ; save w1 dl w0 x1+a31 ; save w2 ds w0 x2+j1 ; save w3 dl w0 x1+a33 ; save status ds w0 x2+j2 ; save ic ; rs w0 x1+a28 ; save w0 := save ic; ; al w0 14<2+0 ; ; rs w0 x1+a29 ; save w1 := 'jd'-instruction; dl w0 x1+a177 ; save cause (= 6) ds w0 x2+j3 ; save sb to user exception addres; ; rs w0 x1+a30 ; save w2 := save sb; ; rs w3 x2+a31 ; save w3 := save cause (= 6); ws w2 x1+a182 ; w2 := logic user exception address; al w2 x2+a180 ; rs w2 x1+a33 ; save ic := exception address + no of regdump bytes jl c99 ; goto interrupt return e. ; ; answer device operation ; ; the controller has delivered an answer to a 'device operation' ; message. prepare the RC8000/RC9000 answer ; ; call ; w0 result ; w1 main ; w2 - ; w3 function < 1 b. i10, j30 w. ; answer device operation c47: ; begin ds. w1 i1. ; al w0 x3 ; jl. w3 d156. ; decrease no_of_outstanding; rl w2 x1+a501 ; message := main.message_buffer; rl. w3 i6. ; sl w3 5 ; if result >= 5 then jl -1 ; panic; rl. w0 i6. ; ls w0 9 ; message.state.result:= lo w0 x2+a138 ; message.state.result or last_result; hs w0 x2+a138+1 ; ls w3 +1 ; case result of jl. (x3+j5.) ; ; j5: -1 ; 0 ; - j6 ; 1 ; ok -1 ; 2 ; - j15 ; 3 ; unintelligible j15 ; 4 ; malfunction ; j6: ; ok: ; ----- zl w0 x2+a138+1 ; begin al w3 2.0100000 ; sz w0 x3 ; if message.state.answer = 0 then jl. j7. ; begin ; lo w0 6 ; message.state := message.state or answer; hs w0 x2+a138+1 ; dl w0 x1+a520+a151 ; <* move answer from main.mess_0 - mess_7 ds w0 x2+a151 ; to message.mess_0 - mess_7 *> dl w0 x1+a520+a153 ; ds w0 x2+a153 ; dl w0 x1+a520+a155 ; ds w0 x2+a155 ; dl w0 x1+a520+a157 ; ds w0 x2+a157 ; ; jl. j9. ; end j7: ; else ; begin rl w3 x1+a520+a150 ; if not statuserror then sn w3 0 ; begin sz w0 -1024 ; if result=1 then jl. j4. ; begin rl w0 x1+a520+a152 ; wa w0 x2+a152 ; message.octet_count := rs w0 x2+a152 ; message.octet_count + main.mess_2; j4: ; end; ; end; rl w0 x2+a150 ; <* w3 = new status *> sn w0 0 ; if old statuserror then rs w3 x2+a150 ; skip new status; rl w0 b219 ; la w0 x1+a500 ; check := main.gen_info.check; sn w0 0 ; if check then jl. j8. ; begin ; rl w0 x1+a520+a150 ; <* move mess_0, mess_3 - mess_7 to rs w0 x2+a150 ; message *> dl w0 x1+a520+a154 ; ds w0 x2+a154 ; dl w0 x1+a520+a156 ; ds w0 x2+a156 ; rl w0 x1+a520+a157 ; rs w0 x2+a157 ; j8: ; end <* check = 0 *> j9: ; end jl. j18. ; ; end <* ok *> ; j15: ; unintelligible: ; malfunction: ; --------------- al w0 2.0100000 ; begin lo w0 x2+a138 ; hs w0 x2+a138+1 ; message.state := message.state or answer; ; ; al w0 0 ; message.octet_count := 0; ; rs w0 x2+a152 ; ; jl. j18. ; end <* unintelligible, malfunction *> ; ; j18: ; common: ; ------- ; begin ; ------> 8000 special <------ rl w3 x1+a235 ; rl w0 x1+a10 ; device_address := main.device_address; al w1 2 ; se w0 q26 ; if main.kind <> ifp then am 2.11<1 ; answer_device(normal) do w1 x3+0 ; else rl. w1 i1. ; answer_device(ifp); ; ------> end 8000 special <------ zl w0 x2+a138+0 ; <* don't use com_area any more *> bs. w0 1 ; hs w0 x2+a138+0 ; message.count := message.count - 1; ; al w3 2.0000100 ; la w3 x2+a138 ; if message.count = 0 and sn w0 0 ; message.state = transfer_completed then sn w3 0 ; begin jl. j25. ; ; rl w3 x2+a141 ; if message.receiver <> 2 then sn w3 2 ; begin jl. j20. ; <* if message was sent to an area which is sh w3 0 ; removed during the operation a result 2 ac w3 x3 ; is inserted in the message *> se w3 (x3+a50) ; if receiver.main = receiver then jl. j19. ; begin <* receiver is a mainprocess *> rl w3 b21 ; driverproc := receiver.driverproc; zl w0 x3+a19 ; driverproc.buffer_claim := ba. w0 1 ; driverproc.buffer_claim + 1; hs w0 x3+a19 ; end; j19: ; se w2 (x1+a200) ; if message = main.prepare_dump_message then jl. j20. ; begin rl w2 x1+a201 ; rl w1 b21 ; jl w3 d124 ; remove_reserver(driverproc, main.dump_device); al w0 0 ; rl. w1 i1. ; rs w0 x1+a200 ; main.prepare_dump_message := 0; rs w0 x1+a201 ; main.dump_device := 0; ; end; ; end; j20: ; zl w0 x2+a138+1 ; if message.state.io then so w0 2.0000001 ; begin jl. j22. ; jl w3 d132 ; decrease_stopcount(message); rl. w1 i1. ; rl w2 x1+a501 ; ; dl w0 x2+a152 ; se w0 0 ; se w3 0 ; jl. j22. ; es. w0 1 ; if message.hw_transfered = 0 and wd w0 g48 ; message.bytecount <> 0 then ea. w0 1 ; mess.hw :=(((mess.bytes-1)/3)+1)*2 ls w0 1 ; rs w0 x2+a151 ; end; j22: ; ; rl. w0 i6. ; zl w0 x2+a138+1 ; sh w0 8.1777 ; if result=ok then jl. j23. ; goto result1 sz w0 -2048 ; if intervention then am 1 ; result:=4; am 2 ; else result:=3; j23: al w0 1 ; result1: result:=1; jl. w3 d15. ; deliver_answer(message); ; end; j25: ; jl. j30. ; end; ; i6: 0 ;-2: result i1: 0 ; 0: save main ; end; ; deliver interrupt to itc-main ; sets io result = 0 and continues with deliver interrupt c48: c.l53 b. f4 w. ; ****** test 41 ****** rs. w3 f1. ; al w1 x2-a241 ; rs. w1 f0. ; jl. w3 (f3.) ; 41 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a500 ; dump main.communication area al w1 x1+a517 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 47 ****** al w2 x1+a242 ; se w2 (x2) ; if in queue then jl w3 d5 ; remove from queue al w0 0 ; io result 0 al w3 c99 ; jl d121 ; got to deliver interrupt and goto reutrn from interrupt j30: rl. w1 i1. ; rl w0 x1+a78 ; so w0 2.010000 ; if not busy then jl c42 ; continue with check main queue jl c99 ; else goto return from interrupt; e. ▶EOF◀