|
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: 319488 (0x4e000) Types: TextFile Names: »mprocs «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer └─⟦2ba378e4a⟧ └─⟦this⟧ »mprocs «
\f m. monprocs - monitor procedures 17.0 beta ;-------------------------------------------------------------------------- ; REVISION HISTORY ;-------------------------------------------------------------------------- ; DATE TIME OR DESCRIPTION ; RELEASE ;-------------------------------------------------------------------------- ;88.03.24 14.1A HSI start of description ; remove double definition of l30-l46 ; insert csp-printer in driver and reserver table ; error in reserve table (no reserve check for kind >18 ; error causing overwriting of procfunc code ; new operation to csp-terminal: 6<12+1 : write 'unknown' ; ifp-operation answer disconnect set mess buf = 0 ;88.03.24 16.14 HSI new monitorcall: set number of processors ;88.04.11 13.07 HSI -- " -- " -- if number of processers > 1 ; then addr 66 = -1000 ;88.04.19 15.0 TSH Alle device drivers replaced by RC8500 device drivers, ; and the procedures d140 - d154 updated/added to ; reflect the new protocol. ; monitor procedures reserve/release process have been ; updated. ;88.04.24 14.27 HSI count max. number of processors in monitor call 34 ;88.05.24 07.50 kak change of cpa and address base included ;88.06.08 TSH update of drivers due to changed protocol ; update of monitor procedure start_controller (force ; parameter). ;88.06.20 10.15 TSH sspmain included ;88 07 05 10.57 HSI release process: if not reserved then no mess to ; controller ;88 07 31 10.07 kak new value of source in set_up (d153) ;88 08 08 15.23 kak sense operation to ifpmain inserted ;88 08 16 13.36 hsi insert timeout-check on operaions to main ;88 09 05 12.35 hsi d30: insert driverproc as receiver if link is removed ;88 09 11 15.31 REINSERT corrections to d155 and d156 (second time) ;88 09 21 13.42 regret (d154) increase number of outstanding operations ;88 09 25 12.15 hsi reserve/release: - - - " - - - " - - - " - - - " - - - ;88 09 26 08.59 hsi set no. of proc.: (e17) skip call if not mp ;88 11 25 12.53 kak error in generel copy corrected ;89 01 12 14.48 kak error in reset main correctet ;89 02 22 09.36 kak set w2 unchanged at return from d155 (increase no of outstanding) ; the correction just mentioned (890112) may then be cancelled ; test_ready_and_set_up :the condition before the call of clean_after_buserror corrected ;89 03 15 15.53 kak no lock unlock in driverproc ; driverproc is only locked the very first time it is started ;89 03 26 10.17 kak call of procfunc changed: area claim is checked before call of prepare bs ;89 04 07 14.35 HSI error in errorlog!. regret is answered with break 6 ;-------------------------------------------------------------------------- ;89 04 07 15.31 START OF RELEASE 16.0 ;89 04 07 15.31 hsi logical volumes: ;89 04 19 13.02 hsi (insert correction from 15.1: lock/unlock) ;89 04 27 14.53 hsi answer createlink with result <> 0: no linkproces in mess. ;89 05 01 14.57 hsi (correct check above) (r 15.1) ;89 05 25 14.14 kak call of deliver answer changed: result must not be set in receiver field, but kept in w0 ; count of outstanding message for area processes introducted: increased in deliver message ; and decreased in deliver answer ;89 11 21 15 17 kak new footprint included at break 6 (jl w3 c29) ;-------------------------------------------------------------------------- ;90 05 29 15.28 START OF RELEASE 17.0 ;90 05 29 15.29 kak errorlog prepared for errors from ioc and lan ;90 06 22 11.50 kak an error in errorlog corrected: add base before copy to ip addr ;90 07 05 09.52 kak contr. slave and main inserted in errorlog buffer ;90 08 30 10.00 kak an error in errorlog (move words) corrected ;90 09 06 14.39 kak the exam queue call in errorlog is replaced with a local procedure ;91 01 08 09.35 kak an error in errorlog corrected: status,ic,cause,sb was not dumped ;91 01 10 13.00 kak an error in errorlog corrected: wrong offset to g20 when called from driverproc ;91 01 16 11.59 hsi driverproc: if interrupt in queue then take it before mess. ;91 01 22 11.00 hsi allow reading from reserved processes if function bit 9 & 10 ; equals 01. (d141) ;91 02 13 10.26 kak je-jd removed from clock driver code ;91 05 02 09.06 kak check op=input when allowing reading from reserved processes b.i30 w. i0=91 05 02 i1=09 06 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. b. h30 w. \f ; list of monitor procedures: b16: ; start: e0 ; 0 : set interrupt e1 ; 2 : reset, priv e2 ; 4 : process description 5 : own 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 : test users , reserver, and writeprotection e15 ; 30 : set writeprotect e16 ; 32 : remove writeprotect e17 ; 34 : set number of processors 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 c29 ; 116 : not used 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 : set cpa e64 ; 128 : start controller e65 ; 130 : stop message c29 ; 132 :not used e67 ; 134 : emergency stop b17=k-b16 ; max monitor call number b80: 0, r.(:b17+2:) ; monitor call count table \f ; ********** driver block ************ ; ; ***** controller device driver entry table ***** b55: ; ; start of first part of device driver entry tabel ; -1 ; 0 ; undef. -1 ; 2 ; undef. h4 ; 4 ; area driver h6 ; 6 ; disc driver h8 ; 8 ; csp_terminal -1 ; 10 ; undef. -1 ; 12 ; undef. h14 ; 14 ; printer -1 ; 16 ; undef. h18 ; 18 ; magnetic tape driver -1 ; 20 ; undef. (ioc mainprocess: 1st part executed in driverproc) -1 ; 22 ; undef. -1 ; 24 ; undef. -1 ; 26 ; undef. (dlc mainprocess: 1st part executed in driverproc) h28 ; 28 ; ifp general sequential device (gsd) ; ; ***** controller device driver entry table: setup part ***** b56: ; start of second part of device driver entry table ; h1 ; 0 ; special (reserve/release process) -1 ; 2 ; undef. h5 ; 4 ; area driver setup h7 ; 6 ; disc driver setup h9 ; 8 ; csp_terminal -1 ; 10 ; undef. -1 ; 12 ; undef. h15 ; 14 ; printer -1 ; 16 ; undef. h19 ; 18 ; magnetic tape driver setup h21 ; 20 ; ioc mainprocess driver setup -1 ; 22 ; undef. -1 ; 24 ; undef. h27 ; 26 ; dlc mainprocess driver setup h29 ; 28 ; gsd driver setup ; ***** controller device driver: reservation requirements ***** b57: 0 ; 0 ; 0 ; ; 0 ; 2 ; 0 ; ; a0>5 + a0>18 ; 4 ; area: output + security erase 0 ; ; a0>5+a0>6+a0>10+a0>12+a0>16+a0>18+a0>21; 6 ; disc: output,format,power up,remove logical volume, power down ; security erase,write data and ecc a0>(:29-24:) ; ; write defect list 0 ; 8 ; 0 ; ; 0 ; 10 ; 0 ; ; 0 ; 12 ; 0 ; ; -1 ; 14 ; printer: reservation always needed -1 ; ; 0 ; 16 ; 0 ; ; -1 ; 18 ; tape: reservation always needed -1 ; ; 0 ; 20 ; 0 ; ; 0 ; 22 ; 0 ; ; 0 ; 24 ; 0 ; ; 0 ; 26 ; 0 ; ; -1 ; 28 ; gsd: reservation always needed -1 ; ; ; ***** definition of states for processes ***** ; l36 = 0 ; 0 = free l37 = 1 ; 1 = during connect l38 = 2 ; 2 = connected l39 = 3 ; 3 = during disconnect l40 = 4 ; 4 = intervention ; ***** definiton of states for magnetic tape ***** ; l45 = 1 ; no document mounted l46 = 2 ; unidentified document mounted l47 = 0 ; identified document mounted \f ; ************************************************************************* ; ; common procedures used by device drivers for devices connected through ; IOC/DLC controllers. ; ; ************************************************************************* ; ; procedure check operation(message); ; ----------------------------------- ; ; the user or reserver requirements of the receiver of the specified message ; is checked in accordance with the operation and the device kind of the ; receiver. ; ; note: the message must not be claimed. ; ; call return ; ; w0 - unchanged ; w1 - unchanged ; w2 message message ; w3 link destroyed ; ; return: link + 0: error, message.sender not user or reserver of ; message.receiver as required. ; link + 2: ok. ; b. i5, j5 w. d141: ; check operation (message); ds. w1 i1. ; begin ds. w3 i3. ; rl w1 x2+a142 ; rl w2 x2+a141 ; rl w3 x2+a10 ; w3:=kind se w3 q8 ; if not csp terminal then jl. j0. ; goto test user,reserver rl w1 (b6) ; else exclude proc func jl w3 d123 ; rl. w1 i2. ; w1:=saved w2 rl w1 x1+a142 ; w1:=receiver jl w3 d126 ; include intproc (maybe procfunc !) as user j0: jl w3 d113 ; check reserver(sender, receiver); jl. j4. ;+0: other reserver: check function mask; jl. j1. ;+2: internal: ok return; ;+4: no reserver: check requirements; rs. w1 i5. ; rl w3 x2+a10 ; reserve_mask := ls w3 1 ; if message.operation < 24 then am. (i2.) ; reservation(receiver.kind) zl w1 +a150 ; else sh w1 23 ; reservation(receiver.kind + 2); jl. j3. ; al w3 x3+2 ; al w1 x1-24 ; j3: rl. w0 x3+b57. ; if reserve_mask shift message.operation then ls w0 x1 ; sh w0 -1 ; error return; jl. j2. ; ; j5: rl. w1 i5. ; jl w3 d102 ; check user(sender, receiver); jl. j2. ;+0: not user: error return; ;+2: user: ok return; j1: dl. w3 i3. ; ok-return: al w3 x3+2 ; sz ; j2: dl. w3 i3. ; error-return: dl. w1 i1. ; jl x3 ; ; j4: ; reserved by another: check op=input and function bit 9,10: am. (i2.) ; zl w0 +a150 ; se w0 3 ; if op<>input then jl. j2. ; error return; zl w0 x1+a22 ; check function bit 9,10: so w0 2.100 ; if internal.function_mask(9) = 0 and so w0 2.010 ; internal.function_mask(10) = 1 then jl. j2. ; continue jl. j5. ; else error return. 0 ; save w0 i1: 0 ; save w1 i2: 0 ; save w2 i3: 0 ; save w3 i4: 24 ; first operation in word 2 of b57 i5: 0 ; saved sender e. ; end; \f ; procedure test_ready_and_setup(force, message/proc); ; ---------------------------------------------------- ; ; the state of the main-process for the proc or receiver specified in the ; message, is tested. if the state is 'ready' and the number of free ; buffers is above a certain low water mark the control is transfered ; to the setup procedure of the driver or the reserve/release setup-part. ; if the state of the main-process is 'communicating' or the number of ; free buffers is below the low water mark, the message/proc is linked ; to the waiting queue of the main process, and the control is transfered ; to the 'return from interrupt' procedure of the monitor. ; the linked message/proc will be transfered at a later time when a 'operation ; received' interrupt is received from the ioc/dlc controller and the ; number of free buffers is above the low water mark. ; if the state of the main-process is 'after error' then the specified ; message is answered with result 4 (receiver malfunction). ; ; the parameter 'force' will set the low water mark: ; = 0 : the low water mark will reserve 2 buffers ; <> 0 : the low water mark will be zero and no buffers is reserved. ; force should only be set in connection with regret and dump function/ ; operations. ; if force = 2 the driver will be started independent of main.state ; (only to be used in reset operation) ; note on message: ; at entry the message must have been claimed and it must not be in ; any queue. ; ; note on proc: ; at entry w2 must point at proc + a81 (done due to d149) ; ; call ; ; w0 force ; w1 - ; w2 message/proc + a81 ; w3 - ; b. i5, j10 w. d142: ; procedure test ready(force, message/proc); rs. w0 i4. ; begin sl w2 (b8+4) ; sl w2 (b8+6) ; if message then jl. j4. ; begin sn w0 0 ; jl. j0. ; al w0 2.1000000 ; if force then lo w0 x2+a138 ; begin hs w0 x2+a138+1 ; message.state := message.state or force; al w0 0 ; low_water := 0; sz ; end j0: al w0 2 ; low_water := 2; rs. w0 i0. ; <* reserve a few for regret and dump *> ; <* element := message; *> rl w1 x2+a141 ; sh w1 0 ; ac w1 x1 ; proc := message.receiver; rl w3 x1+a10 ; driver_kind := message.receiver.kind; ; jl. j1. ; end j4: ; else begin <* proc *> sn w0 0 ; low_water := am 2 ; if force then 0 al w0 0 ; else 2; rs. w0 i0. ; al w3 0 ; driver_kind := special; al w1 x2-a81 ; <* element := proc *> ; end; ; j1: rl w0 x1+a10 ; while proc.kind <> main_kind do se w0 q20 ; proc := proc.main; sn w0 q26 ; jl. j2. ; rl w1 x1+a50 ; jl. j1. ; ; j2: rl. w0 i4. ; sl w0 2 ; jl. j6. ; if force = strong or rl w0 x1+a78 ; sz w0 2.110000 ; (proc.state = ready and jl. j3. ; proc.free_buffers > low_water) then ls w0 -12 ; goto setup_procedure(driver_kind); sh. w0 (i0.) ; jl. j3. ; j6: jl. (x3+b56.) ; j3: ; else rl w0 x1+a78 ; if ok then sz w0 2.100000 ; jl. j5. ; begin ; rl w0 x1+a216 ; ***** statistics ***** ba. w0 1 ; increment no of times controller was not ready rs w0 x1+a216 ; ***** statistics ***** rl. w0 i0. ; se w0 0 ; if force = no and sn w2 (x2+a140) ; element.in_queue then sz ; return_from_interrupt jl c99 ; else ; begin jl w3 d5 ; unlink(element); al w1 x1+a81 ; <* if force then link in front of queue *> sn w0 0 ; head := if force then main.waiting_q.first rl w1 x1+a140 ; else main.waiting_q; jl w3 d6 ; link(head, element); jl c99 ; return_from_interrupt; ; end; j5: ; end else ; begin ; <* state = after error or after reset *> sl w2 (b8+4) ; sl w2 (b8+6) ; if element = message then sz ; jl. w3 d152. ; clean after buserror(message); jl c99 ; goto return from interrupt; ; end; ; i0: 0 ; low_water i4: 0 ; saved force; e. ; end; \f ; procedure prepare consecutive transfer(area, message, first logical segment); ; ----------------------------------------------------------------------------- ; ; the specified message is changed so it specifies an io transfer of ; as meny as possible consecutively placed segments. ; below is the used and changed fields of the message buffer specified: ; ; Note: message (w2) might be a pointer to a message-like structure ; in the communication area of the main process. ; ; + 0: ; + 2: ; (a152) + 4: no of bytes (set) ; (a153) + 6: first segment on physical disc (set) ; (a154) + 8: remaining segments (updated) ; +10: ; ; ; call return ; ; w0 first logical segment next logical segment ; w1 area process area process ; w2 message buffer message buffer ; w3 link remaining segments ; b. i10, j10 w. d143: ; procedure prepare consecutive transfer(area, message, first logical segment); ds. w3 i3. ; begin ds. w1 i1. ; rl w1 x1+a50 ; save area.logical disc; rs. w1 i8. ; ; al w3 0 ; wd w0 x1+a72 ; save first logical segment modulo slicelength; rs. w3 i5. ; ws w3 x1+a72 ; ac w3 x3 ; no_of_segm := sl w3 (x2+a154) ; if message.remaining segments < remaining in slice rl w3 x2+a154 ; then message.reamining segments rs. w3 i4. ; else remaining in slice; ; ; <* w0: logical slice no for slice which contains first segment *> rl. w3 i1. ; rl w2 x1+a71 ; wa w2 x3+a60 ; jl w3 d74 ; follow chain(no of slices, first slice); ; al w0 x2 ; message.first segment := ws w0 x1+a71 ; slice number * slice length + wm w0 x1+a72 ; wa w0 x1+a73 ; logical disc.first segment + wa. w0 i5. ; first logical segment modulo slicelength; rl. w3 i2. ; rs w0 x3+a153 ; ; <* optimize transfer according to track size *> al w3 0 ; segm_on_track := message.first_segment mod wd w0 x1+a75 ; disk.segments_pr_track; sn w3 0 ; if segm_on_track <> 0 then jl. j0. ; begin ac w3 x3 ; max_transfer := wa w3 x1+a75 ; disk.segments_pr_track - segm_on_track; sz ; end j0: rl w3 x1+a86 ; else max_transfer := disk.max_transfer; rs. w3 i7. ; rl. w3 i2. ; ; rl w0 x3+a154 ; remaining := message.remaining; rs. w0 i6. ; rl. w3 i4. ; possible := no of segments; <* remaining in slice ; or message.remaining *> j1: zl w0 x2+0 ; while (slice) = 1 and sn w0 1 ; sl. w3 (i6.) ; remaining > possible and jl. j2. ; sl. w3 (i7.) ; possible < max transfer do jl. j2. ; begin wa w3 x1+a72 ; possible := possible + slicelength; al w2 x2+1 ; slice := slice + 1; jl. j1. ; end; ; j2: sl. w3 (i6.) ; if possible > remaining then rl. w3 i6. ; possible := remaining; sn w0 0 ; if (slice) = 0 then rs. w3 i6. ; remaining := possible; sl. w3 (i7.) ; if possible > max transfer then rl. w3 i7. ; possible := max transfer; ; rl. w2 i2. ; al w1 x3 ; message.remaining segments := ws. w3 i6. ; remaining - possible; ac w3 x3 ; rs w3 x2+a154 ; ; rl. w0 i0. ; next logical segment := wa w0 2 ; first logical segment + possible; rs. w0 i0. ; ; wm w1 g48 ; message.no of bytes := ls w1 8 ; possible * 768; rs w1 x2+a152 ; ; dl. w1 i1. ; jl. (i3.) ; return; ; i0: 0 ; save w0: first logical segment i1: 0 ; save w1: area process i2: 0 ; save w2: message buffer i3: 0 ; save w3: link i4: 0 ; no of segments i5: 0 ; segment modulo slicelength i6: 0 ; remaining segments i7: 0 ; max transfer (rem. in track or disk.max_transfer) i8: 0 ; logical/physical disk ; e. ; end; \f ; procedure start_controller(main process); ; ---------------------------------------------------- ; ; the controller represented by the specified main process is started. ; ; call return ; ; w0 - - ; w1 main process main process ; w2 - unchanged ; w3 link link ; ; return: link + 0: rc8000 bus error, controller not started. ; link + 2: controller started. ; b. i10, j10 w. d144: ; procedure start_controller(main process); ; begin c.l53 b. f2 w. ; ***** test 46 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 46 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x1+a550 ; < dump rc8000 to comm area > al w1 x1+a567 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 46 ***** ds. w3 i3. ; rl w3 x1+a235 ; <w3: device address> rl w0 x1+a10 ; if main.kind <> ifpmain then al w2 1 ; start controller(device addr + 'start') se w0 q26 ; else am 2.10<1 ; start controller(device addr, ifp-start); do w2 x3+0 ; sx 2.111 ; if no exception then jl. j1. ; begin ; al w3 2.010000 ; mainproc.state := lo w3 x1+a78 ; mainproc.state or busy; hs w3 x1+a78+1 ; ls w3 -12 ; if not mainproc.geninfo.answer then al w3 x3-1 ; mainproc.free_buffers := hl w0 x1+a550+0 ; mainproc.free_buffers - 1; so w0 2.010000 ; hs w3 x1+a78+0 ; ; ***** statistics ***** dl w0 x1+a217 ; ba. w0 1 ; mainproc.no of operations := sx 2.001 ; mainproc.no of operations + 1; jl. j4. ; rs w0 x1+a217 ; jl. j3. ; j4: ba. w3 1 ; al w0 0 ; ds w0 x1+a217 ; j3: ; zl w0 x1+a78+1 ; if mainproc.state = in_chain then so w0 2.001000; mainproc.no of chained opr := jl. j2. ; mainproc.no of chained opr + 1; rl w0 x1+a218 ; se w0 -1 ; <* stop counting when counter is full *> ba. w0 1 ; rs w0 x1+a218 ; j2: ; ***** statistics end ***** dl. w3 i3. ; jl x3+2 ; ok_return; ; end else j1: al w0 2.100000; begin lo w0 x1+a78 ; mainproc.state := hs w0 x1+a78+1 ; mainproc.state or not_ok; dl. w3 i3. ; jl x3 ; error_return; ; end; ; i2: 0 ; saved w2 i3: 0 ; saved w3 e. ; end; \f ; ; procedure set_no_of_segments(message); ; ------------------------------------------ ; ; the largest no of segments which the core area, specified by first and last ; storage address, may contain is computed and placed in message word +8. ; ; call return ; ; w0 - unchanged ; w1 - unchanged ; w2 message message ; w3 link destroyed ; b. i1, j1 w. d145: ; procedure set_no_of_segments(message); rs. w3 i0. ; begin rl w3 x2+a152 ; message.no of segments := al w3 x3+2 ; (last address - first address + 2)//512; ws w3 x2+a151 ; ls w3 -9 ; rs w3 x2+a154 ; jl. (i0.) ; ; i0: 0 ; saved link e. ; end; \f ; procedure check_i-o_transfer(document size, message); ; ----------------------------------------------------- ; ; the i-o transfer specified by message.first segment and message.no of segments ; is compared to the specified document size. if the i-o transfer goes beyond ; the upper limit of the document, the size of the transfer (no of segments) ; is decreased to fit the limit of the document. ; ; call return ; ; w0 size of document size of document ; w1 - unchanged ; w2 message message ; w3 link destroyed ; b. i1, j1 w. d146: ; procedure check_i-o_transfer(size_of_doc, message); rs. w3 i0. ; begin rl w3 x2+a154 ; if message.first segment + wa w3 x2+a153 ; message.no of segments > ws w3 0 ; size of document then sh w3 0 ; jl. (i0.) ; message.no of segments := ac w3 x3 ; message.no of segments - wa w3 x2+a154 ; message.first segment - size of document; rs w3 x2+a154 ; jl. (i0.) ; ; i0: 0 ; saved link e. ; end; \f ; procedure deliver_status(status, message); ; ------------------------------------------ ; ; the specified status is placed in the message, the rest of the buffer is ; cleared and it is returned to the sender with ok-result. ; the control is transfered to the monitor procedure 'return_from_interrupt'. ; ; call ; ; w0 status ; w1 - ; w2 message ; w3 - ; b. i1, j1 w. d147: ; procedure deliver_status(status, message); rs w0 x2+a150 ; begin ld w0 -48 ; rs w0 x2+a151 ; clear answer; ds w0 x2+a151+4 ; ds w0 x2+a151+8 ; ds w0 x2+a151+12; al w0 1 ; message.status := status; al w3 c99 ; jl. d15. ; deliver answer(message,result); goto return_from_interrupt; ; e. ; end; \f ; procedure test_legal_operation(message, operation mask); ; -------------------------------------------------------- ; ; if the specified message contains an operation which is not specified in ; the operation mask as a valid operation, a result 3 is returned. ; if bit number I in the mask is one, operation number I is a valid ope- ; ration. ; ; call return ; ; w0 operation mask destroyed ; w1 - unchanged ; w2 message message ; w3 link destroyed ; b. i1, j1 w. d148: ; procedure test_legal_operation(message, operation mask) rs. w3 i0. ; begin zl w3 x2+a150 ; ls w0 x3 ; if opertion_mask.bit(message.operation)=1 then sh w0 -1 ; ok_return; jl. (i0.) ; ; al w0 3 ; message.result := 3; <* unintelligible *> al w3 c99 ; jl. d15. ; deliver answer(message,result); goto return_from_interrupt; ; i0: 0 ; e. ; end; \f ; procedure stop_message(queue process, main process, message); ; ----------------------------------------------------------------------- ; ; the specified message will be stopped depending on its 'state'. ; the state of the message is encoded in the state field of the message: ; bit 22: during transfer ; bit 21: transfer completed ; ; not transfered: 2.xxxx00x ; during transfer: 2.xxxx01x ; transfer completed: 2.xxxx10x ; ; not transfered: the message is returned to sender. the waiting queue of ; the mainprocess is examined: if empty the monitor is left, ; else test_ready_and_setup is called with the first element. ; ; during transfer: this state is only possible for messages which cause ; chained operations to be send to the controller. it will ; be in this state when a part of the chain has been ; send to the controller but before it is completed. ; no of bytes will be set to zero in the message. ; ; transfer completed: the message has been transfered to the controller ; (if the message caused a chained operation to be send, ; the chain has been completed). ; ; note: there might be a process linked to the waiting_queue of main ; it will be linked in proc+a81. ; ; call return ; ; w0 queue process destroyed ; w1 main process main process ; w2 message message ; w3 link destroyed ; ; return: ; link + 0: during transfer ; link + 2: transfer completed ; b. i10, j10 w. d149: ; stop_message(queue process, mainprocess, message) ds. w1 i1. ; begin ds. w3 i3. ; zl w0 x2+a138+1 ; if message.state = not transfered then sz w0 2.0000110 ; begin jl. j2. ; ; sz w0 2.0000001 ; if message.state.io then jl w3 d132 ; decrease_stopcount(message); al w0 0 ; rs w0 x2+a150 ; message.status := ok; rs w0 x2+a151 ; message.halfwords := message.bytes := 0; rs w0 x2+a152 ; rl. w2 i2. ; al w0 1 ; jl. w3 d15. ; deliver answer(message,result); ; dl. w1 i1. ; rl w2 x1+a81 ; element := mainprocess.waiting queue.first; sn w2 x1+a81 ; if element = none then jl c99 ; return_from_interrupt; ; al w0 0 ; force := sl w2 (b4) ; if element = message then sl w2 (b5) ; message.state.force al w0 2.1000000 ; else no; la w0 x2+a138 ; <* a bit dirty if element = proc ! *> jl. d142. ; test_ready_and_setup(force, element); ; end j2: ; else so w0 2.0000010 ; if message.state = during transfer then jl. j3. ; begin al w0 0 ; rs w0 x2+a152 ; message.no of bytes := 0; jl w3 d5 ; unlink(message); rl. w1 i0. ; al w1 x1+a54 ; jl w3 d6 ; link(queue process.event queue, message); rl. w1 i1. ; jl. (i3.) ; end j3: ; else jl w3 d5 ; begin <* message transfered completely *> rl. w1 i0. ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(queue process.event queue, message); rl. w1 i1. ; rl. w3 i3. ; jl x3+2 ; end; ; i0: 0 ; save w0 i1: 0 ; save w1 i2: 0 ; save w2 i3: 0 ; save w3 ; e. ; end; \f ; procedure clean_after_buserror(message); ; ---------------------------------------- ; ; called when an communication error with the controller is observed. ; the specified message will be returned with result 4 (receiver malfunction), ; stopcount of sender decreased (if necessary) and, if message was send to ; a main process, buffer claim of driverproc increased (it will be decreased ; when the message is answered). ; ; call return ; w0 - destroyed ; w1 - unchanged ; w2 message destroyed ; w3 link destroyed ; b. i5, j5 w. d152: ; procedure clean_after_buserror(message); ds. w2 i2. ; begin rs. w3 i3. ; jl w3 d5 ; unlink(message); zl w0 x2+a138+1 ; sz w0 2.0000001 ; if message.operation = io then jl w3 d132 ; decrease stopcount(message); rl. w2 i2. ; ac w1 (x2+a141) ; rl w0 x1+a10 ; if message.receiver.kind = main_kinds then se w0 q20 ; begin sn w0 q26 ; <* message was send to a mainprocess and sz ; claimed by driverproc *> jl. j1. ; rl w0 b218 ; la w0 x1+a550 ; w0 := function ls w0 -15 ; jl. w3 d156. ; decrease number of outstanding rl w1 b21 ; zl w3 x1+a19 ; driverproc.bufferclaim := al w3 x3+1 ; driverproc.bufferclaim + 1; hs w3 x1+a19 ; j1: ; end; al w0 4 ; jl. w3 d15. ; deliver answer(message,result); rl. w1 i1. ; jl. (i3.) ; return; ; i1: 0 ; saved w1 i2: 0 ; saved w2 i3: 0 ; saved w3 ; e. ; end; \f b. f12 w. ; block including log and test facilities for drivers. ; format of test record: (identical to the test record format of the fpa) ; ; + 0: type, length of record ; + 2: time1 ; + 4: time2 ; + 6: test information ; + 8: ... ; ; ; the call of the test facility is performed like this: ; ; b. f2 w. ; ; rs. w3 f1. ; save w3; ; rs. <w_> f0. ; save device process; ; jl. w3 d150. ; check condition(type, deviceproc, on/off); ; <type> ; type of testpoint ( 1 - 47 ) ; f0: <device proc> ; any device process (main, disc, mt, area or gsd) ; f1: <saved w3> ; saved w3 ; jl. f2. ;+6: test off: w0 - w2: unchanged, w3: saved w3 ; ;+8: test on: ; ... ; pack test information; ; al w0 <first>; first := test_area.first address; ; al w1 <last> ; last := test_area.last address; ; jl. w3 d151. ; create test record; ; f2: ; ; e. ; ; ; unlike the fpa test facilities it is not possible to stop the creation ; of test records after a specified number of records. ; ; working locations: ; ; saved w-registers: f0: 0 ; w0 f1: 0 ; w1 f2: 0 ; w2 f3: 0 ; w3 ; parameters: f7: 0 ; proc (main process) f9: 0 ; type, length \f ; ; check condition(type, device process, on/off); ; -------------------------------------------------- ; ; checks the type of the test point stored in link against the test mask ; of the mainprocess. ; if test is off then the procedure returns to link+6. ; test on implies that the test record is initiated, the registers are ; saved and return is made to link+8. ; ; call return ; w0 - unchanged ; w1 - unchanged ; w2 - unchanged ; w3 link saved w3 (off) ; b. i0, j2 w. d150: ; check condition ds. w1 f1. ; begin rs. w2 f2. ; rs. w3 i0. ; save all registers rl w0 x3+4 ; save saved w3; rs. w0 f3. ; rl w1 x3+2 ; proc := device; j1: rl w0 x1+a10 ; while proc.kind <> main process do se w0 q20 ; proc := proc.main; sn w0 q26 ; jl. j2. ; rl w1 x1+a50 ; jl. j1. ; ; j2: rs. w1 f7. ; rl w3 x3 ; <* type *> dl w1 x1+a75 ; mask := proc.mask; ld w1 x3 ; shift := type; sl w0 0 ; if mask shifted shift>=0 then jl. j0. ; goto exit2; hs. w3 f9. ; type := type of test point; dl. w1 f1. ; <* restore w0 - w3 *> dl. w3 f3. ; am. (i0.) ; jl +8 ; exit1: return to link+8; ; j0: dl. w1 f1. ; exit2: dl. w3 f3. ; <* restore w0 - w3 *> am. (i0.) ; jl +6 ; return to link+6; ; i0: 0 ; saved link; ; e. ; end; \f ; ; create test record ; ------------------ ; ; creates a test record with the format shown above. ; ; call return ; w0 first saved w0 ; w1 last saved w1 ; w2 - saved w2 ; w3 link saved w3 ; b. i6, j5 w. d151: ; create test record al w1 x1+2 ; begin ds. w1 i1. ; top := last + 2; ds. w3 i3. ; rl. w1 f7. ; proc := mainprocess; ; j0: rl. w2 i1. ; start: ws. w2 i0. ; record.length := al w2 x2+6 ; top - first + 6; hs. w2 f9.+1 ; wa w2 x1+a70 ; next_record.start := sh w2 (x1+a71) ; next_record.start + length; jl. j2. ; if next_record.start > test_buffer.top then ; goto insert; j1: rl w2 x1+a71 ; <* insert dummy end record *> ws w2 x1+a70 ; dummy_record.length := test_buffer.top - sl w2 1 ; next_record.start; rs w2 (x1+a70) ; if dummy_record.length>0 then dummy_record:=0,length; ; j5: al w0 0 ; rs w0 x1+a70 ; next_record.start := 0; dl w0 x1+a73 ; ds w0 x1+a71 ; jl. j0. ; goto start; ; j2: rx w2 x1+a70 ; insert: rl. w0 f9. ; rs w0 x2 ; <* type, length *> al w1 x2 ; <* save pointer *> jl w3 d7 ; update time; dl w0 b13+2 ; ds w0 x1+4 ; <* time *> al w2 x1+4+2 ; rl. w3 i0. ; j3: sl. w3 (i1.) ; transfer test information; jl. j4. ; rl w0 x3 ; rs w0 x2 ; al w2 x2+2 ; al w3 x3+2 ; jl. j3. ; ; j4: dl. w1 f1. ; restore w0 - w3 dl. w3 f3. ; jl. (i3.) ; return; ; i0: 0 ; first i1: 0 ; last i2: 0 ; i3: 0 ; link ; e. ; end; e. ; end block including test facilities ; ***** stepping stone ***** jl. (+2), d142, d142=k-4 \f ; procedure setup(param, main, message); ; -------------------------------------- ; ; the communication area of the specified main process is ; initialized according to the parameters. ; ; param (w0) has the following format: ; +0 : function code (to be stored in a550) ; +2 : source of data ; +4 : receiver of the function (process address) ; ; source of data can take the following values: ; 0 : from message pointed out by w2 ; 1 : from communication area i.e. don't initialize - ; already done (only possible in a chain) ; 2 : re-establish communication area from the save area ; (only possible after a 'broken' chain - broken by ; regret/dump functions). ; 3 : no message; initialize a550 - a553 only. ; 4 : as 0 but no increment of counter ; ; in case 0 - 2 the count field of message (a138 bit 0 -11) will be increased. ; ; call return ; w0 param - ; w1 main main ; w2 message message ; w3 link - ; b. i10, j10 w. d153: ; procedure setup rs. w1 i1. ; begin ds. w3 i3. ; rl w3 0 ; rl w0 x3+2 ; if param.source = message then se w0 0 ; begin sn w0 4 ; sz ; jl. j2. ; rs. w0 i4. ; save(source); rl w0 x3+0 ; main.function := param.function; rs w0 x1+a550 ; rs w2 x1+a551 ; main.message := message; rl w3 x3+4 ; rl w0 x3+a76 ; main.device_id := rs w0 x1+a552 ; receiver.device_id; rl w0 x3+a77 ; main.proc_id := rs w0 x1+a553 ; receiver.proc_id; zl w0 x2+a150 ; ls w0 +16 ; main.mess_0 := hl w0 x2+a150+1 ; message.operation shift 16 + rs w0 x1+a560 ; message.mode; ; dl w0 x2+a152 ; <* copy the rest of message *> ds w0 x1+a562 ; dl w0 x2+a154 ; ds w0 x1+a564 ; dl w0 x2+a156 ; ds w0 x1+a566 ; rl w0 x2+a157 ; rs w0 x1+a567 ; ; rl. w0 i4. ; sn w0 4 ; if source=no count then jl. j9. ; goto no increment; jl. j8. ; end j2: ; else se w0 1 ; if source = com_area then jl. j3. ; begin ; <* do nothing *> jl. j8. ; end j3: ; else se w0 2 ; if source = com_save then jl. j4. ; begin dl w0 x1+a580+2 ; <* re-establish the communication area ds w0 x1+a550+2 ; from the save area *> dl w0 x1+a580+6 ; ds w0 x1+a550+6 ; dl w0 x1+a580+10 ; ds w0 x1+a550+10 ; dl w0 x1+a580+14 ; ds w0 x1+a550+14 ; dl w0 x1+a580+18 ; ds w0 x1+a550+18 ; dl w0 x1+a580+22 ; ds w0 x1+a550+22 ; ; ac w0 2.0010000+1; la w0 x2+a138 ; message.state := hs w0 x2+a138+1 ; message.state and not com_save; jl. j8. ; end j4: ; else se w0 3 ; if source = no_message then jl -1 ; begin rl w0 x3+0 ; rs w0 x1+a550 ; main.function := param.function; rl w3 x3+4 ; rl w0 x3+a76 ; main.contorller_index := rs w0 x1+a552 ; param.receiver.controller_index; rl w0 x3+a77 ; main.rc8000_address := rs w0 x1+a553 ; param.receiver.rc8000_address; rs w2 x1+a551 ; main.message := message; <* might be dummy *> jl. j9. ; goto no_increment; ; end ; else panic; <* unknown source *> j8: ; zl w0 x2+a138+0 ; ba. w0 1 ; message.count := hs w0 x2+a138+0 ; message.count + 1; ; j9: ; no_increment: jl. (i3.) ; ; i1: 0 ; save w1 i2: 0 ; save w2 i3: 0 ; save w3 i4: 0 ; source e. ; end; \f ; procedure regret(receiver, main, message); ; ------------------------------------------ ; ; a regret function for the specified message is sent ; ; if the state of the communication area indicates that this ; regret interrupts a 'chain', the communication area is saved ; before the regret is sent. in this case this is marked in ; the state of the message which caused the chained operation ; (message.state bit 19). ; ; this procedure will not return but leaves the monitor. ; ; call ; w0 receiver of message ; w1 main ; w2 message ; w3 - ; b. i10, j10 w. ; <* data for regret *> ; i0: 5<17 ; param: function (always regret) 4 ; +2: source (always message,no count) 0 ; +4: receiver i6: 0 ; saved register (message) ; d154: ; procedure regret rs. w0 i0.+4 ; begin zl w0 x1+a78+1 ; param.receiver := receiver_of_message; so w0 2.001000 ; if main.com_state = in_chain then jl. j2. ; begin rl w3 x1+a551 ; al w0 2.0010000 ; main.message.state := lo w0 x3+a138 ; main.message.state or com_save; hs w0 x3+a138+1 ; ; ac w0 2.001000+1 ; main.com_state := la w0 x1+a78 ; main.com_state and not in_chain; hs w0 x1+a78+1 ; ; dl w0 x1+a550+2 ; <* save the communication area *> ds w0 x1+a580+2 ; dl w0 x1+a550+6 ; ds w0 x1+a580+6 ; dl w0 x1+a550+10 ; ds w0 x1+a580+10 ; dl w0 x1+a550+14 ; ds w0 x1+a580+14 ; dl w0 x1+a550+18 ; ds w0 x1+a580+18 ; dl w0 x1+a550+22 ; ds w0 x1+a580+22 ; ; end; j2: ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, message); jl. w3 d155. ; increase no_of_outstanding(main) jl. w3 d144. ; start_controller(main); jl. w3 d152. ;+0: clean_after_buserror(message); jl c99 ;+2: ok: return_from_interrupt; ; e. ; end <* regret *> \f ; procedure increase no_of_outstanding(main); ; ------------------------------------------ ; ; Increase the number of outstanding buffers for the specified mainprocess, ; when a message is sent. ; if timeout supervision is enabled (timeout <>0) and the answer bit in the ; function word is zero, the mainprocess is inserted in the timeout queue ; ; call return ; w0 - destroyed ; w1 main unchanged ; w2 - unchanged ; w3 - destroyed ; b. i3, j2 w. ; d155: c.l53 b. f4 w. ; ****** test 44 ****** rs. w3 f1. ; rs. w1 f0. ; jl. w3 (f3.) ; 44 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a86 ; dump main.communication area al w1 x1+a86 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 44 ****** rs. w3 i3. ; no_of_outstanding := +1 ds. w2 i2. ; rl w0 b227 ; la w0 x1+a550 ; if no answer bit then se w0 0 ; begin jl. j0. ; dl w0 x1 +a87 ; wa w3 b201 ; rs w3 x1+a86 ; sn w3 0 ; if no outstanding jl. j0. ; then return rs w0 x1+a244 ; al w2 x1+a242 ; if main.timeout <> 0 and al w1 b69 ; not in timeout queue then se w0 0 ; link(main, timeout_queue) se w2 (x2) ; sz ; jl w3 d6 ; j0: dl. w2 i2. ; end; jl. (i3.) ; i1: 0 ; saved w1 i2: 0 ; saved w2 i3: 0 ; - w3 e. \f ; procedure decrease no_of_outstanding(main); ; ------------------------------------------ ; ; Decreases the number of outstanding buffers for the specified mainprocess. ; if an answer is received the number of outstanding buffers is decreased. ; if timeout supervision is enabled and more messages is outstanding, ; the mainprocess is reinserted in the timeout queue with the total ; timeout value. ; ; call return ; w0 function unchanged ; w1 main unchanged ; w2 - unchanged ; w3 - unchanged ; b. i3, j2 w. ; d156: c.l53 b. f4 w. ; ****** test 44 ****** rs. w3 f1. ; rs. w1 f0. ; jl. w3 (f3.) ; 44 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a86 ; dump main.communication area al w1 x1+a86+2 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 44 ****** ds. w1 i1. ; ds. w3 i3. ; main.no_of_outstanding := -1 ls w0 -1 ; so w0 1 ; if answer bit and jl. j0. ; (function <> take operation or rl w2 x1+a503 ; receiver = main) then sn w0 3 ; sn w2 x1 ; sz ; jl. j0. ; begin al w2 x1+a242 ; if in timeout queue then se w2 (x2) ; unlink(main, timeout_queue) jl w3 d5 ; dl w0 x1 +a87 ; ws w3 b201 ; rs w3 x1+a86 ; sh w3 -1 jl -9 se w3 0 ; if main.timeout <> 0 and sn w0 0 ; main.no_of_outstanding <> 0 then jl. j0. ; rs w0 x1+a244 ; begin al w2 x1+a242 ; al w1 b69 ; link(main, timeout_queue) sn w2 (x2) ; end jl w3 d6 ; j0: dl. w3 i3. ; end; dl. w1 i1. ; jl x3 ; 0 ; -2: saved w0 i1: 0 ; 0: saved w1 0 ; -2: saved w2 i3: 0 ; 0: - w3 e. \f b. i24 w. i0: 0 ; saved w0 i1: 0 ; saved w1 i2: 0 ; saved w2 i3: 0 ; saved w3 i7: 0 ; cur process (sender of answer - if any) i8: 0 ; internal i23: 0 ; result ; 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: w0=result, w2=buf, w3=link ; exit: w0, w1=unchanged, w2, w3=undef ; return address: link d30: ; deliver answer - called from send answer ds. w1 i1. ; rs. w3 i3. ; save registers; rs. w0 i23. ; save result; rl w0 b1 ; rs. w0 i7. ; cur process := cur process in monitor; jl. i9. ; d15: ds. w1 i1. ; save registers; rs. w3 i3. ; rs. w0 i23. ; save result; i20: al w0 1 ; cur process := undefined; rs. w0 i7. ; <* not called from send answer *> i9: rl w3 x2+a141; sh w3 0 ; ac w3 x3 ; rl w0 x3+a10 ; se w0 q4 ; if proc = area then jl. i22. ; begin zl w1 x3+a57 ; al w1 x1-1 ; number of outstanding message:= hs w1 x3+a57 ; number of outstanding message-1; sn w0 0 ; if number of outstanding messages=0 and se w0 (x3+a11) ; area process removed then sz rs w1 x3+a50 ; clear main address; i22: ; end; rl. w0 i23. ; rs w0 x2+a141 ; insert result; dl w1 x2+a142 ; internal:=sender(buf); (w0 := receiver(buf)) sh w1 -1 ; if internal<0 then jl. i12. ; goto regretted; rl w3 x1+a10 ; se w3 q8 ; if kind = csp_terminal or sn w3 64 ; 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 b21 ; internal:=driverproc; (there is only one) rs. w1 i8. ; save(internal); rl w3 (b6) ; w3:=pda of 1. internal al w3 x3-1 ; sl w3 x1 ; if not internal then jl -100 ; 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); rl. w1 i7. ; se w1 (b1) ; if cur in monitor = sender of answer jl. i11. ; <*called from send answer*> rl. w3 i8. ; and rl w0 x3+a301 ; buf.sender.priority > cur process.priority sl w0 (x1+a301) ; then jl. i11. ; begin jl w3 d20 ; conditional reschedule(cur); ; end; 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. ; zl w0 x2+a150 ; la w0 b201 ; rs w0 x2+a138 ; message.state:=if even op then 0 else 1 rl w1 x2+a141 ; internal:=receiver(buf); rl w0 x1+a10 ; jl. w3 i21. ; test and count area process; 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); sn w1 0 ; if internal not defined then jl. i16. ; goto unknown; sh w1 0 ; if not receiver=internal then jl. i18. ; deliver special; 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 b1 ; if receiver.priority > sender.priority then rl. w3 i8. ; begin rl w0 x3+a301 ; sl w0 (x1+a301) ; jl. i17. ; jl w3 d20 ; conditional reschedule(sender); ; end; i17: 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; zl w0 x1-a15+a19; if internal.bufclaim = 0 then sn w0 0 ; 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 i23. ; result := 5; jl. i20. ; goto deliver answer; ; deliver special ; used for messages send to an external process representing devices on ; intelligent controllers (ida, ifp etc.). ; ; w0: kind of receiver ; w1: - ; w2: message buffer ; w3: - ; i18: zl w0 x2+a150 ; deliver special so w0 1 ; if message.operation=input-output then jl. i19. ; begin dl w0 x2+a152 ; <* make message.first,last even *>; la w3 g50 ; la w0 g50 ; rl w1 b1 ; sl w3 (x1+a17) ; if message.first < sender.low limit or sl w0 (x1+a18) ; message.last > sender.high limit then jl. i5. ; return result(3); sh w0 x3-2 ; if message.last<message.first then jl. i5. ; return result(3); wa w0 x1+a182 ; message.first:=physical_address(message.first); wa w3 x1+a182 ; message.last :=physical_address(message.last); ds w0 x2+a152 ; ; end; i19: jl. w3 d141. ; check operation(message); jl. i4. ;+0: error: return result(2); ;+2: ok: rl w1 x2+a141 ; claim(message); ac w0 x1 ; rs w0 x2+a141 ; ; rl w3 x1+a10 ; goto driver(receiver.kind); jl. (x3+b55.) ; ; i5: am 1 ; return result(3): i4: al w0 2 ; return result(2): rs. w0 i23. ; set result; jl. i20. ; goto deliver answer; ; ; test and count area process; ; reg call return ; w0 kind unchanged ; w1 receiver - ; w2 buff - ; w3 link undef ; i21: ; procedure test and count area process; se w0 q4 ; if proc = area then begin jl x3 ; begin rs. w3 i24. ; zl w3 x1+a57 ; al w3 x3+1 ; number of outstanding message:= hs w3 x1+a57 ; number of outstanding message+1; jl. (i24.); i24: 0 ; saved rerurn 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. \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, j0 w. e2: rl w0 x1+a176 ; if monitor call = 4 then se w0 4 ; begin jl. j0. ; 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; j0: rs w1 x1+a29 ; own process: jl c99 ; save w1 := own process description; i0: 0 ; end; e. ; procedure initialize process(name, result); ; - reserve - ( - , - ); ; call: return: ; save w0 result (=0, 1, 2, 3, 4) ; save w1 unchanged ; save w2 unchanged ; save w3 name unchanged b. i10, j21, h90 w. e3: ; initialize process: e4: ; reserve process: ; begin al w0 x2 ; save monitor function; jl w3 d101 ; check and search name; jl r3 ; +0: not found: goto result(3); rl w2 x3 ; +2: found: proc := name table(entry); am (x2+a10) ; jl. (2) ; goto case proc.kind of: ; ( h0 ; 0: internal h2 ; 2: clock h4 ; 4: area h6 ; 6: ida disc h8 ; 8: csp_terminal/sspconsole (9) r3 ; 10: r3 ; 12: h28 ; 14: csp-printer r3 ; 16: h18 ; 18: ida mag tape h20 ; 20: ida main r3 ; 22: r3 ; 24: h26 ; 26: ifp main h28 ; 28: ifp general sequential device 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: r2 ; 56: remoter, not allowed r3 ; 58: r3 ; 60: h62 ; 62: disc h64 ; 64: pseudo r3 ; 66: r3 ; 68: free ida/ifp subprocess r3 ; 70: r2 ; 72: rc8602 (sscir), not allowed r3 ; 74: rc8602 (isrpy), does not exist h76 ; 76: rc8601 (sscir) h78 ; 78: rc8601 (isrpy) h80 ; 80: fpa main r2 ; 82: fpa host, not allowed h84 ; 84: fpa subprocess h86 ; 86: fpa receiver h88 ; 88: fpa transmitter r2 ; 90: host, not allowed ; ); ; ; *** at entry: w0: monitor function ; w1: cur ; w2: proc h0: ; internal: h2: ; clock: h64: ; pseudo: ; begin se w0 8 ; if monitor function = initialize then jl r0 ; result(0) jl r2 ; else result(2); ; end; ; h4: ; area: rs. w0 i2. ; begin jl w3 d102 ; check user(cur, proc); jl r3 ; +0: not user: result(3); rl. w0 i2. ; +2: user: se w0 8 ; if monitor function = initialize then jl r0 ; result(0); ; jl. w3 j21. ; check reserver ok(cur, proc); jl w3 d114 ; check writeprotect(cur, proc); jl. j1. ; +0: none: goto check base; jl. j2. ; +2: internal: goto reserve proc; jl r4 ; +4: other: result(4); jl r4 ; +6: other+internal: result(4); ; j1: ; check base: dl w0 x2+a49 ; if proc.upperbase > cur.maxupper or al w3 x3+1 ; proc.lowerbase < cur.maxlower then sh w0 (x1+a44) ; result(2); sh w3 (x1+a44-2) ; jl r2 ; ; j2: ; reserve proc: jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; h6: ; ida disc: ; begin jl. w3 j20. ; check user and initialize(monitor function, cur, proc); jl. w3 j21. ; check reserve ok(cur, proc); rs. w2 i3. ; zl w0 x2+a57 ; if proc.type = physical disc then sz w0 2.1 ; begin jl. j4. ; j3: rl w2 x2+a70 ; proc := proc.next logical disc; sn w2 0 ; while proc <> 0 do jl. j5. ; begin jl w3 d113 ; check any reserver(cur, proc); jl r1 ; +0: other: result(1); jl. j3. ; +2: internal: jl. j3. ; +4: none: ; proc := proc.next logical disc; ; end; j4: ; end else sz w0 2.0100000 ; begin (*w0 state) jl r2 ; if part of logical volume then result(2) rl w2 x2+a50 ; jl w3 d113 ; check any reserver(cur, proc.main); jl r1 ; +0: other: result(1); am 0 ; +2: internal: ; +4: none: ; end; j5: rl. w2 i3. ; jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; ; h8: ; csp_terminal process: rs. w0 i2. ; begin jl w3 d126 ; include user(cur, proc); ; rl w0 x2+a10 ; if proc.kind=ssp_console then sn w0 q9 ; result(0); jl r0 ; <* just say jyes *> jl w3 d113 ; check any reserver(cur, proc); jl r1 ; +0: other: result(1); am 0 ; +2: internal: al w3 1 ; +4: none: hs w3 x2+a56+1 ; proc.external state := initialized; rl. w0 i2. ; se w0 8 ; if initialize then jl r0 ; result(0) ; else begin al w0 0 ; cur.save_w0 := 0; <* prepare ok result *> rs w0 x1+a28 ; jl. w3 j21. ; test reserver; jl w3 d125 ; reserve(int_proc,ext_proc); rs w1 x2+a74 ; proc.reserver_process := cur; ; <* force := no *> al w2 x2+a81 ; element := proc.process_queue; jl. d142. ; test_ready_and_setup(force, element); ; end; ; end; ; h20: ; ida main: h26: ; ifp main: ; begin jl. w3 j20. ; check user and initialize(monitor function, cur, proc); jl. w3 j21. ; check reserver ok(cur,proc); jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; ; h18: ; ida mag tape: h28: ; ifp gsd and csp-printer: h76: ; rc8601 (sscir): h78: ; rc8601 (isrpy): ; begin jl w3 d102 ; check user(cur, proc); jl r2 ; +0: not user: result(2); ; +2: user: jl. w3 j21. ; check reserver ok(cur, proc); jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; h62: ; disc: ; begin jl. w3 j20. ; check user and initialize(monitor function, cur, proc); jl. w3 j21. ; check reserver ok(cur, proc); rs. w2 i3. ; rl w2 x2+a50 ; proc := proc.main; sn w2 0 ; if proc <> none then jl. j7. ; begin <*logical disc*> jl w3 d113 ; check any reserver(cur, main); jl r1 ; +0: other: result(1); am 0 ; +2: internal: jl. j10. ; +4: none: ; end else j7: ; begin <*physical disc*> rl w2 b4 ; j8: rs. w2 i4. ; proc := first external; rl w2 x2+0 ; repeat begin rl w3 x2+a10 ; rl w0 x2+a50 ; if proc.kind = disc and sn w3 62 ; proc.main = main then se. w0 (i3.) ; begin jl. j9. ; jl w3 d113 ; check any reserver(cur, proc); jl r1 ; +0: other: result(1); am 0 ; +2: internal: ; +4: none: j9: am. (i4.) ; end; al w2 2 ; proc := next external; se w2 (b5) ; end jl. j8. ; until proc = first area; ; j10: ; end; rl. w2 i3. ; jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; ; h80: ; fpa main: ; begin jl. w3 j20. ; check user and initialize(monitor function, cur, proc); jl. w3 j21. ; check reserver ok(cur, proc); rs. w2 i3. ; rl w3 b4 ; main := first external; sz ; j11: al w3 x3+2 ; while main <> proc do se w2 (x3+0) ; main := next in nametable; jl. j11. ; ; rs. w3 i4. ; rl w2 x3+2 ; rec := nametable(main.devno + 1); jl w3 d113 ; check any reserver(cur, rec); jl r1 ; +0: other: result(1); am 0 ; +2: internal: rl. w2 i4. ; +4: none: rl w2 x2+4 ; trm := nametable(main.devno + 2); jl w3 d113 ; check any reserver(cur, trm); jl r1 ; +0: other: result(1); am 0 ; +2: internal: rl. w2 i3. ; +4: none: jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; ; h84: ; fpa subprocess: rs. w0 i2. ; begin rl w3 x2+a10 ; se w3 84 ; if proc.kind = temp then jl w3 d126 ; include user(cur, proc); jl w3 d102 ; check user(cur, proc); jl r2 ; +0: not user: result(2); ; +2: user: jl w3 d113 ; check any reserver(cur, proc); jl r1 ; +0: other: result(1); am 0 ; +2: internal: al w3 1 ; +4: none: hs w3 x2+a56+1 ; proc.external state := initialized; rl. w0 i2. ; zl w3 x2+a63 ; se w0 8 ; if not initialize or se w3 8 ; proc.subkind <> terminal then jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; ; h86: ; fpa receiver: h88: ; fpa transmitter: ; begin jl. w3 j20. ; check user and initialize(monitor function, cur, proc); jl. w3 j21. ; check reserver ok(cur, proc); rs. w2 i3. ; rl w2 x2+a50 ; main := proc.main; jl w3 d113 ; check any reserver(cur, main); jl r1 ; +0: other: result(1); am 0 ; +2: internal: rl. w2 i3. ; +4: none: jl w3 d125 ; reserve process(cur, proc); jl r0 ; result(0); ; end; ; i1: 0 ; return address i2: 0 ; monitor function i3: 0 ; save proc i4: 0 ; nt index ; ; ; procedure check user and initialize(func, cur, proc); ; call return ; w0 monitor func monitor func ; w1 cur cur ; w2 proc proc ; w3 link - ; ; return: if user and func = reserve : link ; if not user : result 2 ; if user and func = initialize : result 0 ; j20: ; begin ds. w0 i2. ; jl w3 d102 ; check user(cur, proc); jl r2 ; +0: not user: result(2); rl. w0 i2. ; +2: user: sn w0 6 ; if initialize then jl r0 ; result(0) jl. (i1.) ; else return to link; ; end; ; procedure check reserve ok(cur, proc); ; call return ; w0: - destroyed ; w1: cur cur ; w2: proc proc ; w3: link - ; ; return: other reserver : result 1 ; internal : result 0 ; none : link ; j21: ; begin rs. w3 i1. ; jl w3 d113 ; check any reserver(cur, proc); jl r1 ; +0: other: result(1); jl r0 ; +2: internal: result(0); jl. (i1.) ; +4: none: return to link; ; end; ; e. ; ; procedure release process (name); ; call: return: ; save w0 unchanged ; save w1 unchanged ; save w2 unchanged ; save w3 name unchanged b. i5 w. e5: jl w3 d101 ; check and search name; jl c99 ;+2 not found: goto interrupt return; rl w2 x3 ;+4 proc:=name table(entry); rl w3 x2+a10 ; if proc.kind <> internal and sz w3 -1-64 ; proc.kind <> pseudo then jl w3 d113 ; check reserver jl c99 ;+0 other reserver or proc =internal/pseudo: return sz ;+2 cur is reserver: continue jl c99 ;+4 no reserver : return rl w3 x2+a10 ; sz w3 -1-64 ; proc.kind <> pseudo then jl w3 d124 ; release process(cur, proc); rl w0 x2+a10 ; if proc.kind = csp terminal then se w0 q8 ; begin jl c99 ; al w0 0 ; proc.reserver_process := 0; rs w0 x2+a74 ; ; <* force := no *> al w2 x2+a81 ; element := proc.process_queue; jl. d142. ; test_ready_and_setup(force, element); ; end; e. ; end; ; 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); send att message (driver function); ; call: call: return: ; save w0 unchanged ; save w1 mess unchanged mess ; save w2 mess flag unchanged sender ; save w3 name unchanged receiver b. i15 w. ; send pseudo message: e62: rl w3 x1+a28 ; proc:= savew0(cur); rl w2 (b5) rl w0 (b6) sl w3 x2 sl w3 (0) jl c29 ; 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 ; rl w2 x1+a176 ; if cause = send att mess then sn w2 17 ; 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 i3. ; pseudo receiver point to here; 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+a142 ; sender(buf):=cur; al w0 5 ; al w3 c99 ; deliver answer(buf,result); jl. d15. ; goto interrupt return; ; test that save w2(cur) is an external proc description i3: rl w2 b4 ; rl w3 x1+a30 ; 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 ; sn w0 q8 ; if proc.kind = csp_terminal then rl w3 x3+a50 ; proc := proc.main; se w1 (x3+a250) ; if cur <> driverproc(proc) then jl c29 ; goto internal 3; rl w3 x1+a31 ; rl w0 x3+a10 ; w0:= receiver kind sz w0 -1-64 ; if kind<>internal and kind<>pseudo 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) := save w3(cur); al w0 0 ; flag := 0; rx w0 x1+a30 ; sender(buf) := proc; i.e. save w2(cur); ds w0 x2+6 ; jl. i9. ; 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. i8 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); ac w3 (x2+4) ; check state: sh w3 -1 ; if receiver(buf)>0 jl c29 ; goto internal 3; (i.e. not claimed); 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 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; 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 ; am (b1) ; rl w0 +a28 ; al w3 c99 ; deliver answer(buf,result); jl. d30. ; goto interrupt return; 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 b21 ; 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: ; examine next event: ; 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 or interrupt operation sl w2 (b8+4) ; if buf is not message buffer then sl w2 (b8+6) ; jl. i12. ; goto interrupt 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: ; se w0 0 ; if answer then jl c99 ; goto interrupt return; rl w3 x1+a30 ; <* get saved next mess addr zl w0 x1+a19 ; in case claims exceeded *> sn w0 0 ; if internal.bufclaims = 0 then jl. i9. ; goto examine next event; jl w3 d108 ; claim buffer(cur,buf); jl c99 ; goto interrupt return; 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); al w0 0 ; save w2:=0; (next buffer address) rs w0 x1+a30 ; 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 set writeprotect(name, result); ; procedure remove writeprotect(name, result); ; ; call return ; save w0: result (0, 1, 2, 3) ; save w1: ; save w2: ; save w3: name addr name addr b. i1, j1 w. e15: ; set writeprotect: e16: ; remove writeprotect: jl w3 d101 ; check and search name; jl r3 ;not found: goto result 3; ;found: rl w2 x3 ; rl w0 x2+ a10 ; if process <> area then se w0 4 ; goto result 3; jl r3 ; rl w0 x1+a176 ; if cur.cause = remove writeprotect then al w3 r0 ; begin se w0 30 ; remove writeprotect(cur, proc); jl d119 ; result(0); ; end; jl w3 d102 ; check user(cur, proc); jl r3 ;+0: not user: result(3); ;+2: user: jl w3 d113 ; check any reserver(cur, proc); jl r1 ;+0: other: result(1); jl. j1. ;+2: internal: goto writeprotect; ;+4: none: dl w0 x2+a49 ; al w3 x3+1 ; if proc.upperbase > cur.maxupper or sh w0 (x1+a44) ; proc.lowerbase < cur.maxlower then sh w3 (x1+a44-2) ; result(2); jl r2 ; ; j1: al w3 r0 ; jl d118 ; insert writeprotect(cur, proc); ; result(0); ; e. ; ; procedure regret message; ; call: return: ; save w0 unchanged ; save w1 unchanged ; save w2 buf unchanged ; save w3 unchanged e41: ; regret message al w3 c99 ; begin rl w2 x1+a30 ; if cur = procfunc then rl w0 (b6) ; begin sn w0 x1 ; jl d75 ; <* it's allowed for procfunc to regret all ; messages send from a process which is going ; to be removed *> ; regretted message(message); goto interrupt return; ; end; 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 ; zl w0 x2+a138+1 ; sn w3 (b1) ; if proc <> cur or sz w0 2.0000001; message.state.io then jl c29 ; goto internal 3; al w3 c99 ; regretted message(buf); jl d75 ; goto interrupt return; ; end; ; procedure set number of processors(count) ; call: return: ; save w0 result (0, 1, 2) ; save w1 count unchanged ; save w2 unchanged ; save w3 unchanged b. i3, j3 w. e17: rl w0 x1+a22 ; check function mask so w0 1<4 ; if function bit 7 <> 0 then jl r1 ; deliver result 1 b. h1 w. ; if mp then am (b9) ; h0=k jl. 0 ; begin jl. j1. ; goto mp activation c.(:h0+a8-k-1:) am 0, r.(: h0+a8+2-k :)>1 ; fill up z. e. ; end mp rl w0 x1+a29 ; if new number of processors <> 1 then sn w0 1 ; deliver result 2 jl r0 ; else deliver result 0 (ok) jl r2 ; <* end not mp *> j1: al w2 0 ; find max no of processors rl w3 (b59) ; for i:=1 step 1 until 4 do rs. w3 i2. ; begin al w3 x3+8 ; if pu_table(i)<>-1 then j0: rl w0 x3 ; max_no:=max_no+1; se. w0 (i3.) ; al w2 x2+1 ; al w3 x3-2 ; se. w3 (i2.) ; jl. j0. ; end; sh w2 (b82) ; if current no of processors > max then rs w2 b82 ; current max no := max; ; a cpu has'nt received the power up interrupt al w2 x2+1 ; rl w0 x1+a29 ; if process count < 1 sl w0 1 ; or process count > max processors then sl w0 x2 ; deliver result 2 jl r2 ; rl w2 b82 ; set new number of active processors rs w0 b82 ; delta := number_of_processors - count; ws w2 0 ; pu_table.no_of_free := rl w3 (b59) ; pu_table.no_of_free - delta; rl w0 x3 ; ws w0 4 ; rs w0 x3 ; rl. w0 i1. ; if active processors = 1 rl w2 b82 ; then current process :=-1000000 se w2 1 ; rs w0 b42 ; jl r0 ; return ok i1: -1000000 ; i2: 0 ; pu_table addr i3: -1 ; free pu entry 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. e51: ; prepare bs; zl w0 x1+a20 ; sh w0 0 ; if areaclaim.sender=0 then jl r1 ; result 1 jl. i14. ; else continue at check; 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; i14: ; 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); 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; sz w2 2.111 ; if device number not multiple of 8 (halfwords) then jl r4 ; goto result 4; 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 ; 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); 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; ; further checking is postponed until procfunc. jl. i3. ; goto link call; ; 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 w3 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); la w0 g50 ; <make addr in message even> la w1 g50 ; 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. i13. ; then goto result 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 ; use 'move-halfwords' instruction if implemented gg w1 b100 ; if cpu-kind= mp-cpu then sh w1 55 ; begin jl. i8. ; ; mh-instr: rx w2 6 ; move-halfwords(size, destination, source); mh w3 (0) ; rl w1 b1 ; goto result0; jl r0 ; end; ; programmed-move: 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 ;test users , reserver, and writeprotection ; ; call return ;save w0 result (=0 2 3 4) ;save w1 adr of internal ;save w2 user reserver writeprotection specification ;save w3 adr of external b. i2, j5 w. e14: rl w2 x1+a29 ; wa w2 x1+a182 ; if addr+base >= lower write limit and al w0 x2+6 ; addr+base+6 < upper write limit then sl w2 (x1+a183) ; nameaddr:= addr+base sl w0 (x1+a184) ; sz ; else jl. j2. ; if addr< cpa and ws w2 x1+a182 ; addr> 7 then al w0 x2+6 ; nameaddr:= addr sl w2 8 ; sl w0 (x1+a181) ; else jl c29 ; goto internal 3; j2: ; al w3 x1 ; internal := current process rl w0 x2 ; sn w0 0 ; jl. j1. ; ws w2 x1+a182 ; <* adjust for the base *> jl w3 d11 ; search name(internal) jl r3 ;+2 not found: result 3 rl w3 x3 ; internal := entry.nametable rl w0 x3+a10 ; if kind not internal then se w0 0 ; result 3 jl r3 ; j1: rs. w3 i1. ; save internal rl w2 x1+a31 ; wa w2 x1+a182 ; if addr+base>= lower writelimit and al w0 x2+6 ; addr+base+6< upper writelimit then sl w2 (x1+a183) ; nameaddr:= addr+base sl w0 (x1+a184) ; sz ; else jl. j3. ; if addr< cpa and addr> 7 then ws w2 x1+a182 ; nameaddr:= addr al w0 x2+6 ; sl w2 8 ; else sl w0 (x1+a181) ; goto internal 3; jl c29 ; j3: ; ws w2 x1+a182 ; <* adjust for the base *> jl w3 d11 ; search name(external) jl r4 ; +2 not found : result 4 rl w3 x3 ; external := entry.name table rl w0 x3+a10 ; if kind = internal or se w0 64 ; kind = pseudo proc then sn w0 0 ; jl r4 ; result := 4 al w2 x3 ; rl. w1 i1. ; test users , reserver, and writeprotection jl w3 d76 ; rl w1 b1 ; save w0(cur) := result ok al w0 0 ; save w2(cur) := user-reservr bits rs w0 x1+a28 ; rs w3 x1+a30 ; jl c99 ; return i1: 0 ; saved internal 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:= wa w0 x1+a182 ; cur.new start address + cur.base - ws w0 x3+a17 ; (child.first address + child.base); ws w0 x3+a182 ; 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(proc)+displ; wa w0 x2+a182 ; rs w0 x2+a182 ; rl w0 x2+a24 ; if proc.mode = 0 then sn w0 0 ; goto next; jl. j2. ; dl w1 x2+a184 ; current lower write limit(proc):= wa. w0 i1. ; current lower write limit(proc)+displ; wa. w1 i1. ; current upper write limit(proc):= ds w1 x2+a184 ; current upper write limit(proc)+displ; dl w1 x2+a306 ; update first and second process extension wa. w0 i1. ; wa. w0 i1. ; ds w1 x2+a306 ; 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 (= 1,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 ; la w0 g50 ; remove lsb c.(:a399>23a.1:)-1 sz w0 (g68) ; if displacement mod 8k<>0 then jl c29 ; goto internal 3 z. 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. ; sh w3 -1 ; if logical address < 0 or jl r1 ; wraps around top of core then sh w0 x3 ; goto result 1 jl r1 ; 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 cpa ; set the cparegister of an internal process. ; ; call return ; ; save w0 result (=0,2,3,4 ) ; save w1 cpa ; save w2 ; save w3 name adr(proc) ; b. i10, j10 w. e63: jl w3 d101 ; check and search name jl r3 ; not found: result 3 rl w3 x3 ; found : rs. w3 i1. ; save proc rl w0 x3+a10 ; if process not an internal process se w0 0 ; then goto result 3 jl r3 ; se w1 (x3+a34) ; if parent(proc) <> cur jl r3 ; then goto result 3 zl w0 x3+a13 ; if state(child) <> waiting for start by parent se w0 a99 ; then goto result 2 jl r2 ; rl w0 x1+a29 ; save cpa value c.(:a399>23a.1:)-1 sz w0 (g67) ; if new cpa mod 2k<>0 then jl c29 ; goto internal 3 z. rs. w0 i0. ; al w0 x3 ; if the process has any children rl w3 b6 ; then goto result 2 j1: rl w2 x3 ; sn w0 (x2+a34) ; jl r2 ; al w3 x3+2 ; se w3 (b7) ; jl. j1. ; rl. w0 i0. ; rl w3 0 ; rl w2 b8+6 ; sn w0 0 ; if cpa := 0 then al w3 x2+2 ; cpa := last word of last monitor table+2 am. (i1.) ; if cpa:= 1 then rl w2 +a171 ; sn w0 1 ; cpa:= initial cpa(child) al w3 x2 ; rl. w2 i1. ; la w3 g50 ; <*make cpa even*> sh w3 (x2+a171) ; check cpa: sh w3 7 ; if cpa > initial cpa(child) or jl r4 ; cpa < 7 then rs w3 x2+a181 ; goto result 4 else jl r0 ; goto result 0 ; end i0: 0 ; saved cpa i1: 0 ; saved proc e. ; 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 ; function>12 = 0 ; data= deviceno. < 1 (w3 > 2 ) ; function>12 < > 0 ; data = function > 12 ; 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 w3 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 w3 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 w3 c29 ; goto internal 3; rl w2 x1+a30 ; se w2 0 ; if save w2(cur) <> 0 then jl w3 d12 ; check message buf; zl w3 x1+a28+1 ; function select := save w0(cur); sl w3 0 ; if function select outside limits then sl w3 j0 ; jl w3 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; zl w3 x1+a28+1 ; 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 w0 x1+a225 ; if transfer code(device descr) <> 0 then se w0 0 ; jl w3 c29 ; goto internal 3; ; note: this check is repeated at i50, where it is needed for checking ; start of 'std wait program' 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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 w3 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) ; if function > 12 = 0 then zl w1 +a28 ; se w1 0 ; jl. i56. ; am (b1) ; bz w1 +a31+1 ; ls w1 -2 ; w1:=io-devno<1; i56: 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; ; monitor procedure start_controller(force, dev_no_of_main, message); ; ; if the controller which is superviced by the specified mainprocess is ; ready, the communication area for the controller is initialized and the ; controller is started. the message will be linked to the eventqueue of ; the mainprocess. ; if the mainprocess isn't ready the message is linked to the waiting queue ; of the mainprocess. ; at entry the message must be claimed ((and it must not be in any queues. ??)) ; ; if the message address is -1 the call will cause rc8000 to send an ; 'answer device' function to the controller. ; result=3 (rc8000 bus error) is only possible if 'answer device' is ; selected. ; ; call return ; ; save w0 force result (0: ok, 3: bus error, 4: unknown) ; save w1 devno of mainprocess devno of mainprocess ; save w2 message/-1 (answer dev.) message/-1 (answer dev.) ; save w3 - unchanged ; b. i1, j1 w. e64: ; start controller rl w3 x1+a29 ; begin ls w3 +1 ; wa w3 b4 ; sl w3 (b4) ; sl w3 (b5) ; if not mainproc within external processes then jl r4 ; result(4); ; rl w3 x3 ; if mainproc.driverprocess <> cur process then se w1 (x3+a250) ; goto internal(3); jl w3 c29 ; ; rl w2 x1+a30 ; sn w2 -1 ; if not answer device then jl. j0. ; begin jl w3 d12 ; check message buf(cur); al w0 0 ; rx w0 x1+a28 ; result := ok; force := save_w0; jl. (+2) ; goto test_ready_and_setup(force, message); d142 ; ; end else j0: ; begin rl w1 x3+a10 ; al w0 2 ; if mainproc.kind <> ifp then rl w2 x3+a235 ; start controller(mainproc.devno + 'answer device') se w1 26 ; else am 2.11<1 ; start controller(mainproc.devno, ifp-answer device); do w0 x2+0 ; rl w1 b1 ; <* restore cur process *> sx 2.111 ; if no exception then sz ; result(0) jl r0 ; else begin al w0 2.100000; mainproc.state := after error; lo w0 x3+a78 ; hs w0 x3+a78+1 ; jl r3 ; result(3); ; end; ; end; e. ; end; ; monitor procedure stop_io_message(message); ; ; it is only allowed procfunc to stop an io message send to an ida/ifp device. ; if the receiver of the message is an ida/ifp-process the message is marked ; stopped (if not already stopped). If the message isn't the first in the ; waiting queue of the corresponding main process, the driver of the ; receiver is started. ; ; call return ; saved w0 - - ; saved w1 - - ; saved w2 message message ; saved w3 - - ; b. j10 w. e65: ; stop_io_message rl w0 (b6) ; begin se w0 x1 ; if calling process <> procfunc then jl c29 ; goto internal 3; jl w3 d12 ; check message(cur); zl w0 x2+a138+1 ; so w0 2.0000001; if message.state.io then jl c99 ; return; ; rl w3 x2+a141 ; proc := message.receiver; sh w3 0 ; ac w3 x3 ; sh w3 5 ; if message.receiver < 6 then return; jl c99 ; <*message has been answered*> rl w0 x3+a10 ; kind := proc.kind; se w0 26 ; if kind<>ifp_main and sn w0 20 ; kind<>ida_main then jl. j2. ; begin j1: ; rl w3 x3+a50 ; while not (kind = idamain or rl w0 x3+a10 ; kind = ifpmain) do se w0 26 ; begin sn w0 20 ; proc := proc.main; sz ; kind := proc.kind; jl. j1. ; end; ; end; j2: al w1 2.1000 ; zl w0 x2+a138+1 ; if not message.state = stopped then sz w0 x1 ; begin jl c99 ; lo w0 2 ; message.state := stopped; hs w0 x2+a138+1 ; jl w3 d5 ; unlink(message); al w0 1 ; force := yes; jl. (+2) ; test_ready_and_setup(force, message); d142 ; ; end else return; e. ; end; ; procedure emergency stop ; stop cpu to save registers in emergency situations e67: jl -100 ; goto monitor fault ; 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 main *) unchanged ; *) only for lan/ioc device b. i17 , j22 w. g66: ds. w1 i0. ; save all registers ds. w3 i1. ; gg w3 b91 ; se w3 b49+12 ; if called from driverproc then am 1 ; called_from_dr:=true else al w0 0 ; called_from_dr:=false; rs. w0 i4. ; dl w1 b19 ; save current buffer , current receiver ds. w1 i3. ; rl w1 b30 ; set current receiver := errorlog rs w1 b19 ; jl. w3 j18. ; examine queue rl w2 b30 ; if mess in queue then 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 se w0 q6 ; if disc or sn w0 q8 ; terminal or jl. j6. ; se w0 q18 ; tape or sn w0 q20 ; iocmain or jl. j6. ; se w0 q26 ; lanmain or sn w0 q28 ; generel sekvential device jl. j6. ; then ioc/lan process error; 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 16 ; 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 34 ; size of record 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+42 ; fpa transmission error ls w0 12 ; hl w0 x1+44 ; save 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 ; ; j6: ; ioc/lan error: dl w0 x1+a11+2 ; ds w0 x2+4 ; move name.failed process dl w0 x1+a11+6 ; ds w0 x2+8 ; dl w0 x1+a68 ; slave and contr hs w3 0 ; rl. w1 i1. ; saved w3 is address of main ds w1 x2+14 ; move contr,slave,main dl w0 x1+a501 ; move function,mess buffer address from comm. area ds w0 x2+24 ; dl w0 x1+a503 ; device-id,proc-id ds w0 x2+28 ; al w1 x1+a510 ; al w2 x2+34 ; al w0 16 ; jl. w3 j9. ; move(comm_area.mess,addr.errorlog,16) al w3 50 ; save size; jl. j13. ; goto copy buf ; ; *** stepping stone *** jl. (2), d15, d15=k-4 ; ; help procedure move words. ; move the specified number if words as words. ; call return ; w0: no of halfwords destroyed (zero) ; w1: from adr unchanged ; w2: to adr unchanged ; w3: link unchanged ; ; j9: ds.w2 i13. ; ds. w0 i15. ; j10: rl w0 x1+0 ; rs w0 x2+0 ; al w1 x1+2 ; al w2 x2+2 ; 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 ; ; ; ; 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. ; al w2 x2+a70 ; rl. w1 i4. ; se w1 0 ; if called from monitor then jl. j12. ; begin rl w1 4 ; copy direct: setup parameters to procedure move doublewors rs. w3 i5. ; save buffer length rl. w2 i10. ; rl w3 x2+a142 ; sender sh w3 0 ; ac w3 x3 ; rl w2 x2+a151 ; first adr in messbuf wa w2 x3+a182 ; +sender.base wa. w2 i9. ; + no of hw already moved rl. w0 i5. ; record size jl. w3 j9. ; rl. w1 i5. ; goto update no of hw moved rl. w2 i10. ; jl. j14. ; end else ; begin <*use generel copy*> j12: wa w3 4 ; 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. ; end; j14: wa. w1 i9. ; (copy direct continues here. w1=no of hw moved rs. w1 i9. ; w2= mess buf adr) 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: rl. w1 i9. ; rl. w0 i4. ; se w0 0 ; if called_from_dr then al w2 g20-a150; addr:=driverproc answer area jl. w3 j22. ; send answer j17: al w0 -2 ; reset special watched receiver rs w0 b32 ; jl. w3 j18. ; if more messages in queue rl w0 x2+a153 ; then set next special watched receiver adr 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 ; ; ; ; procedure next buff ; scan the the errorlog bufferqueue to find a buffer from a internal proces ; if the buffer is regretted or the process is stopped then buffer is returned with result 1 and status 0 ; otherwise the procedure return to link + 0 for no buffer i queue or ; link + 2 a buffer in queue ; j18: rs. w3 i16. ; save link j19: rl w1 b30 ; rl w2 x1+a54 ; next buffer errorlog queue sn w2 x1+a54 ; if empty then jl. j15. ; return rs w2 b18 ; rl w1 x2+a142 ; sh w1 0 ; if regretted then jl. j20. ; goto prepare send answer else bz w0 x1+a13 ; so w0 a105 ; if -,(sender stopped) then jl. (i16.) ; return happy j20: al w1 0 ; prepare send answer: se. w1 (i4.) ; if called_from_pr then al w2 g20-a150; answer area:=driverproc.answer area else use the buffer jl. w3 j22. ; send answer(result,count,addr); jl. j19. ; goto test next; ; ; i16: 0 ; link (j18) i17: 0 ; link (j22) ; ; send answer ; reg call return ; w0 changed ; w1 hw count - ; w2 address - ; w3 link - ; j22: rs. w3 i17. ; save link rs w1 x2+a151 ; hw count ls w1 -1 ; wm w1 b203 ; rs w1 x2+a152 ; byte count al w1 0 ; rs w1 x2+a150 ; status al w0 1 ; result al. w3 d15. ; se. w1 (i4.) ; if called_from_dr then al w3 g19 ; then deliver result jl w3 x3 ; else deliver answer jl. (i17.) ; return ; 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 i4: 0 ; boolean called_from; i5: 0 ; record length (if called from monitor) 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 e. ; end of errorlog entry \f ; ****** stepping stones ****** ; jl. ( +2), d141 , d141 = k - 4 jl. ( +2), d142 , d142 = k - 4 jl. ( +2), d143 , d143 = k - 4 jl. ( +2), d144 , d144 = k - 4 jl. ( +2), d145 , d145 = k - 4 jl. ( +2), d146 , d146 = k - 4 jl. ( +2), d147 , d147 = k - 4 jl. ( +2), d148 , d148 = k - 4 jl. ( +2), d149 , d149 = k - 4 jl. ( +2), d150 , d150 = k - 4 jl. ( +2), d151 , d151 = k - 4 jl. ( +2), d152 , d152 = k - 4 jl. ( +2), d153 , d153 = k - 4 jl. ( +2), d154 , d154 = k - 4 jl. ( +2), d155 , d155 = k - 4 jl. ( +2), d156 , d156 = k - 4 ; ********************************************************************************** ; ; d e v i c e d r i v e r s ; ; this part contains drivers for devices connected through intelligent controllers. ; these device drivers are executed totaly in monitor mode. the drivers are called ; directly from the monitor procedure 'send message' when the receiver is an ; external process representing a device connected through an intelligent device ; controller. ; ; ; common comments: ; ---------------- ; ; structure of the drivers: ; all drivers contains two parts: one part which is entered from ; the monitor procedure 'send message' when an internal process ; sends a message to an external process representing a device ; connected through an "intelligent" controller. in this part the ; message may be changed slightly (depends on the operation), to ; facilitate the initialization of the "intelligent" controller ; communication area. ; in the second part of the driver the initialization of the ; communication area takes place. this part is called eigher from ; the first part of the driver (when the controller is ready to ; receive a new operation immediately) or from the 'operation recei- ; ved' interrupt procedure for the controller (only in the case where ; the controller was busy at the time the message was send, or when ; the message must be transfered as two or more chained operations ; in this case the message has been linked to the waiting queue of ; the mainprocess). ; ; chained operations: ; messages which involve data-transfer to or from an ioc disc, ; may be partitioned into two or more 'chained' operations. ; this will takes place when: ; ; 1) the data transfer concerns non-consecutively placed segments ; (messages to an area or 'prepare dump' operation to an ioc ; main process). ; ; 2) the specified transfer exceeds a certain amount of data ; (operations to disc or area or copy operation to an ; ida main process). ; ; whenever this partitioning takes place, the message will be placed ; in the waiting queue of the main process. this ensures that ; all the partitions of one chain is transfered indivisible (the 'dump' ; operation sent to an ioc main process or a regret function might ; interrupt the chain). when the last operation in the ; chain is transfered to the controller, the message is moved to the ; event queue of the receiver. ; ; message: ; when the specified message have been transfered to the controller ; it will be linked to the receiver of the message (except messages ; send to an area or a logical disc, where it will be linked to the ; physical disc on which the area/logical disc is located). ; if the controller is busy when the driver wants to transfer an ; operation (message), the message will be linked to the waiting ; queue of the main process of the controller. ; when the monitor receives an 'operation received' interrupt from ; the controller, it will check whether there is any messages in the ; waiting queue of the main process or not. if there are any, the ; driver for the receiver of the message will be started in the se- ; cond part of the driver. ; ; stopping of operations (also called regret): ; it is possible to regret any kinds of operations send to the ; controller if the operation was delivered to the controller as ; a 'device operation' function. ; it is only possible to receive a regretted message in the ; setup-part of the driver. ; a message can be in three states: ; - not transfered: the message has not been transfered to the ; controller (only possible when the message has been linked to ; the waiting queue). ; - during transfer: only possible for messages which are delivered ; as chained operations to the controller. it will be in this ; state when the first element in the chain has been delivered ; and until the last element is delivered. ; - transfer completed: the message has been transfered to the ; controller. ; ; if the message is in the 'not transfered' state the message is ; returned to the sender. a new message (if any) is selected from the ; waiting queue of the main process, and control is transfered ; to the driver of the receiver. ; ; if the message is in the 'during transfer' or 'transfer completed' ; state, the regret is sent as a 'regret message' function to the ; controller. ; ; if the message has been transfered to the controller when it is ; regretted, it will be removed from the event queue of the receiver ; and delivered to the driver in the normal way (the message is deli- ; vered to the setup part of the driver). ; ; ********************************************************************************** \f ; ; ----------------------------------------------------------------------------- ; ; special driver - setup part ; ; this driver is used for transmission of reserve_process and release_process ; requests. ; ; at entry the registers contains: ; ; w0 - ; w1 main ; w2 proc + a81 ; w3 - ; b. i5, j5 w. ; <* data for special driver *> ; ------ data ----- i0: 0 ; param: function 3 ; +2: source (always no message) 0 ; +4: receiver ; h1: ; special driver: setup c. l53 b. f2 w. ; ***** test 40 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 40 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x2-a81+a10 ; al w1 x2-a81+a52 ; dump proc.kind - proc.reserver jl. w3 d151. ; f2: ; e. z. ; ***** end test 40 ***** ; ; begin jl w3 d5 ; unlink(proc); al w2 x2-a81 ; ; rs. w2 i0.+4 ; param.receiver := proc; rl w0 x2+a52 ; se w0 0 ; if proc.reserver = 0 then jl. j1. ; begin al w0 7 ; func := release_device; jl. j2. ; end j1: ; else rl w2 x2+a74 ; begin dl w0 x2+a11+2 ; ds w0 x1+a565 ; main.mess_4 - mess_7 := dl w0 x2+a11+6 ; proc.att_receiver.name; ds w0 x1+a567 ; al w0 6 ; func := reserve_device; ; end; j2: ; ls w0 +17 ; param.function := func shift 17; rs. w0 i0.+0 ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, dummy); jl. w3 d155. ; increase no_of_outstanding(main); jl. w3 d144. ; start_controller(main); am 0 ;+0: error: ignore jl c99 ;+2: ok : goto return_from_interrupt; ; e. ; end \f ; ; ; ---------------------------------------------------------------------------- ; ; area driver, part 1 ; ( message received ) ; ; message send to an area located on a physical disc connected through an ; IOC device controller. ; ; control is transfered to this part of the area driver from the monitor ; procedure 'send message' through the intelligent device driver entry ; table, part 1. ; ; in this part of the driver the format of the messages will be changed ; slightly. when the messages is transfered to the second part of the ; area driver, they have the following formats: ; ; input or output security erase ; --------------- -------------- ; + 0: operation<12 + mode 18<12 + mode ; + 2: first storage address 0 ; + 4: 0 (number of bytes) number of bytes ; + 6: first (logical) segment first (logical) segment ; + 8: no of segments no of segments ; +10: next (logical) segment next (logical) segment ; ; sense or position ; ----------------- ; + 0: operation<12 + mode ; + 2: 0 ; + 4: 0 ; + 6: first (logical) segment (sense: 0) ; + 8: 0 ; +10: first (logical) segment (sense: 0) ; ; ; ; the operation sense acts like a position to the track on which the first ; segment of the area is stored. this will ensure that a valid 'detailed ; status' can be delivered in the answer. ; ; at entry the specified message must have been claimed and it may not be ; in any queues. the stop count of the sender must not have been increased. ; ; at entry the registers contains: ; ; w0: - ; w1: receiver (area process description address) ; w2: message buffer address ; w3: - ; b. i10, j10 w. h4: ; message received: c.l53 b. f2 w. ; ***** test 1 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 1 ; f0: 0 ; <area process> f1: 0 ; jl. f2. ; al w0 x2+a140 ; <dump message: -4 - +18> al w1 x2+a155 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 1 ***** ; rl. w0 i0. ; begin jl. w3 d148. ; test legal operation(message, operation mask); ; rl w3 x1+a50 ; if receiver.main.state <> connected then al w0 2.0111 ; la w0 x3+a78 ; goto intervention; se w0 l38 ; jl. j6. ; ; zl w0 x2+a150 ; sn w0 0 ; if message.operation <> sense then jl. j3. ; begin ; <*** input, output, position, security erase ***> j0: rl w3 x2+a153 ; if message.first_segment < 0 or sl w3 0 ; message.first_segment > area.size then sl w3 (x1+a61) ; goto end_of_area; jl. j5. ; ; al w3 0 ; if message.operation = position then sn w0 8 ; message.no_of_segments := 0; rs w3 x2+a154 ; ; sz w0 2.1 ; if message.operation=input or output then ; jl. w3 d145. ; set_no_of_segments(message); rl w0 x1+a61 ; jl. w3 d146. ; check i-o transfer(area.size, message); rl w0 x2+a138 ; so w0 2.001 ; if message.state=io then jl. j1. ; begin rl w0 x2+a154 ; sn w0 0 ; if message.number_of_segments=0 then jl. d147. ; deleiver_status('ok',message); rl w3 x2+a142 ; zl w0 x3+a12 ; message.sender.stop_count := ba. w0 1 ; message.sender.stop_count + 1; hs w0 x3+a12 ; j1: ; end; al w0 0 ; message.no of bytes := 0; rs w0 x2+a152 ; ; rl w0 x2+a153 ; message.next_logical_segment := rs w0 x2+a155 ; message.first_segment; zl w0 x2+a150 ; access_count := se w0 18 ; sz w0 2.00100 ; if output or security erase then am a411-a412 ; write_access al w1 x1+a412 ; else read_access; al w3 1 ; wa w3 x1 ; if not possition then se w0 8 ; access_count := rs w3 x1 ; access_count + 1; jl. j4. ; end ; else j3: ; begin <* sense, w0=0 *> rl w3 x1+a61 ; if area.size <= 0 then return_status('ok'); sh w3 0 ; jl. d147. ; ; al w3 0 ; message.first_address := last_address := ds w0 x2+a152 ; first_segment := remaining_segments := ds w0 x2+a154 ; next_logical_segment := 0; rs w0 x2+a155 ; ; jl. j4. ; end; ; j4: al w0 0 ; force := no; jl. d142. ; test_ready_and_setup(force, message); ; j5: ; end_of_area: rl w0 b229 ; jl. d147. ; deliver_status('end_of_area', message); ; j6: ; intervention: rl w0 g49 ; jl. d147. ; deliver status('intervention', message); ; ; area operation mask (legal operations): ; sense input output position security_erase i0: a0>0 + a0>3 + a0>5 + a0>8 + a0>18 ; e. ; end; \f ; ------------------------------------------------------------------------- ; ; area driver, part 2 ; (controller ready) ; ; this part of the area driver is called when the controller is ready ; to receive the message. ; in this part of the driver, the communication area of the controller ; is initialized in accordance with the specified message. ; if the message does not need to be delivered in more than one operation, ; (unchained), it is linked to the physical disc on which the area is ; located. ; if the message must be delivered in chained operations because the ; transfer contains non-consecutively placed segments, the message will ; be placed in front of the waiting queue of the main process (if not ; already there). this will ensure, that the chained operation will be ; delivered before any other operations are delivered to the controller ; (except for regret and dump operations!). ; ; when this part of the area driver transfer the message as an operation to ; the controller, the message has the following format: ; ; input or output security erase ; --------------- -------------- ; + 0: operation<12 + mode 18<12 + mode ; + 2: first storage address 0 ; + 4: no of bytes no of bytes ; + 6: first segment on physical disc first segment on physical disc ; + 8: remaining segments remaining segments ; +10: first logical segment first logical segment ; (in next transfer) (in next operation) ; ; sense or position ; ----------------- ; + 0: operation<12 + mode ; + 2: 0 ; + 4: 0 ; + 6: first segment on physical disc ; + 8: 0 ; +10: 0 ; ; ; at entry the specified message may either be linked to the waiting queue ; of the specified main process or it may be out of queue. ; ; at entry the registers contains: ; ; w0: - ; w1: main process ; w2: message ; w3: - ; b. i10, j10 w. ; <* data for area setup *> ; i0: 1<17 ; param + 0: function (always device operation) 0 ; + 2: source 0 ; + 4: ioc receiver (physical disk) i1: 0 ; main process i2: 0 ; saved message i3: 0 ; logical disc process i4: 0 ; area process ; h5: ; area driver: setup c.l53 b. f2 w. ; ***** test 2 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 2 ; f0: 0 ; <main process> f1: 0 ; jl. f2. ; al w0 x2+a138 ; <dump message: -4 - +18> al w1 x2+a155 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 2 ***** ; rs. w1 i1. ; begin rl w1 x2+a141 ; save main process ac w1 x1 ; rs. w1 i4. ; save area process rl w1 x1+a50 ; rs. w1 i3. ; save logical disc process zl w0 x1+a57 ; if logical_disk.type = physical then sz w0 2.00001 ; <* logical disk = physical disk *> ; rl w1 x1+a50 ; rs. w1 i0.+4 ; save physical disc process rs. w2 i2. ; save message ; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 2.0001000 ; goto stop_message; jl. j7. ; ; sz w0 2.0000110 ; if message.state = not_transfered then jl. j1. ; begin al w3 0 ; rs. w3 i0.+2 ; param.source := message; al w3 2.0000010 ; lo w3 x2+a138 ; message.state := message.state or hs w3 x2+a138+1 ; during_transfer; jl. j3. ; end j1: ; else so w0 2.0000010 ; if message.state = during_transfer then jl. j2. ; begin al w3 2 ; param.source := so w0 2.0010000 ; if message.state.com_save then al w3 1 ; com_save rs. w3 i0.+2 ; else com_area; jl. j3. ; end j2: ; else jl -1 ; panic; <* message.state = transfer_complete *> ; j3: al. w0 i0. ; rl. w1 i1. ; jl. w3 d153. ; setup(param, main, message); ; ; <* from now on use com area: com_mes *> ; zl w0 x1+a570+a150 ; if com_mes.operation = sense then ls w0 -4 ; begin se w0 0 ; jl. j0. ; al w0 8 ; com_mes.operation := position; ls w0 +4 ; <* rest of message was changen in part 1 *> hs w0 x1+a570+a150 ; ; end; j0: ; zl w0 x2+a138+1 ; so w0 2.0000001 ; if message.state.io then jl. j4. ; begin ; al w3 0 ; rl w0 x1+a570+a152 ; com_mes.first_address := ls w0 1 ; com_mes.first_address + wd w0 g48 ; com_mes.no_of_bytes * 2 / 3; wa w0 x1+a570+a151 ; rs w0 x1+a570+a151 ; ; end; j4: rl w0 x1+a570+a155 ; al w2 x1+a570 ; <* pseudo message addr in main.com: com_mes *> rl. w1 i4. ; prepare_consecutive_transfer(next_logical_segment, area, com_mes); jl. w3 d143. ; rl. w1 i1. ; rs w0 x1+a570+a155 ; com_mes.next_logical_segment := next_logical_segment; rl. w2 i2. ; ; se w3 0 ; if com_mes.remaining_segments = 0 then jl. j5. ; begin jl w3 d5 ; unlink(message); rl. w1 i0.+4 ; link(physical disc.event queue, message); al w1 x1+a54 ; jl w3 d6 ; ; rl. w1 i1. ; ac w0 2.001000+1 ; main.com_state := la w0 x1+a78 ; main.com_state and not in_chain; hs w0 x1+a78+1 ; ; ac w0 2.0000110+1; message.state := la w0 x2+a138 ; message.state and al w3 2.0000100 ; transfer_complete; lo w0 6 ; hs w0 x2+a138+1 ; jl. j6. ; end ; else j5: ; begin al w1 x1+a81 ; if not message.in_queue then sn w2 (x2+a140) ; link(main.waiting_q, message); jl w3 d6 ; ; rl. w1 i1. ; al w0 2.001000 ; main.com_state := lo w0 x1+a78 ; main.com_state or in_chain; hs w0 x1+a78+1 ; ; end; ; j6: ; c.l53 b. f2 w. ; ***** test 3 ***** rs. w3 f1. ; rl. w3 i1. ; rs. w3 f0. ; jl. w3 d150. ; 3 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message state> al w1 x2+a138 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 3 ***** ; jl. w3 d144. ; start controller(main); jl. w3 d152. ;+0: error: clean_after_buserror(message); jl c99 ;+2: ok, controller started - goto interrupt_return; ; ; ; j7: ; stop_message: rl. w1 i1. ; rl. w0 i0.+4 ; jl. w3 d149. ; stop_message(physical disc, main, message); am 0 ;+0: during transfer: ;+2: transfer completed: rl. w0 i0.+4 ; jl. d154. ; regret(physical disk, main, message); ; <* never reached *> ; e. ; end; \f ; ; ; ------------------------------------------------------------------------ ; ; disc driver, part 1 ; (message received) ; ; message send to a (logical or physical) disc which is connected through ; an ioc device controller. The logical disc may represent a logical volume. ; ; control is transfered to this part of the disc driver from the monitor ; procedure 'send message' through the intelligent device driver entry ; table, part 1. ; ; in this part of the disc driver the format of the message may be changed ; slightly. in case of a sense operation, the format will be changed to ; resemble the format of the position operation, where first segment will ; be segment number zero of the (physical or logical) disc. this will ; ensure that a valid 'detailed status' can be delivered in the answer. ; If the logical disc represents a logical volume an i/o message where ; first segment is outside the receiving logical disc will be transferred ; to the next logical disk in the logical volume with first segment in message ; decreased by the size of the logical disk. The receiver of the message will ; be changed to the new logical disk. ; when the message is transfered to the second part of the disc driver, ; the message has the following format: ; ; input or output security erase ; --------------- -------------- ; + 0: operation<12 + mode 18<12 + 0 ; + 2: first storage address 0 ; + 4: 0 0 ; + 6: first segment on physical disc first segment on physical disc ; + 8: no of segments no of segments ; ; sense or position extract stat + read/write defect list ; ----------------- ------------------------------------- ; + 0: operation<12 + 0 operation<12 + mode ; + 2: 0 first storage address ; + 4: 0 no of bytes ; + 6: segment no on physical disc ; + 8: 0 ; ; read or write data and ecc ; -------------------------- ; + 0: operation<12 + 0 ; + 2 first storage address ; + 4: 0 ; + 6: first segment on physical disc ; + 8: 2 (no of segments) ; note: transfers 774 bytes ; ; the operation 'format kit' will be transfered unchanged. ; ; at entry the message must have been claimed and it must not be in any ; queues. the stop count of the sender must not have been increased. ; ; at entry the registers contains: ; ; w0 - ; w1 receiver (disc process address) ; w2 message ; w3 - ; b. i10, j20 w. h6: ; message received j20: c.l53 b. f2 w. ; ***** test 6 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 6 ; f0: 0 ; < disc process > f1: 0 ; jl. f2. ; al w0 x2+a140 ; < dump message: +0 - +16 > al w1 x2+a154 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 6 ***** ; begin zl w0 x2+a150 ; sl w0 30 ; if message.operation > 29 then jl. j8. ; goto return_result_3; ; zl w0 x1+a57 ; if receiver.type = physical_disc and rl w3 x1+a70 ; receiver.next_log_disc <> 0 then so w0 2.00001 ; goto return_result_3; sn w3 0 ; sz ; jl. j8. ; ; zl w3 x2+a150 ; if receiver.state <> connected then al w0 2.0111 ; la w0 x1+a78 ; if message.operation <> power down or sn w0 l38 ; (message.operation = power down and jl. j0. ; receiver.state <> intervention) then sn w0 l40 ; goto intervention; se w3 12 ; jl. j10. ; j0: ; ; am x3 ; goto case message.operation of am x3 ; jl. (i0.) ; ; i0: j3 ; 0: sense j8 ; 1: - j8 ; 2: - j1 ; 3: input j8 ; 4: - j1 ; 5: output j4 ; 6: format kit j8 ; 7: - j1 ; 8: position j2 ; 9: extract statistics j4 ;10: power up spindel j8 ;11: - j4 ;12: power down spindel j8 ;13: - j14 ;14: define logical volume j8 ;15: - j16 ;16: remove logical volume j8 ;17: - j1 ;18: security erase j1 ;19: read data and ecc j8 ;20: - j1 ;21: write data and ecc j8 ;22: - j8 ;23: - j8 ;24: - j8 ;25: - j8 ;26: - j8 ; j2 ;27: read defect list <* ej rc8000 *> j8 ;28: - j8 ; j2 ;29: write defect list <* ej rc8000 *> ; j1: ; input: ; output: ; position: ; security erase: ; read and write data with ecc ; salvage data ; begin rl w0 x2+a153 ; if message.first_segment < 0 or sl w0 0 ; message.first_segment > disc.size then sl w0 (x1+a74) ; goto check_logical_volume; jl. j11. ; ; al w0 0 ; if message.operation = position then sn w3 8 ; message.no of segments := 0; rs w0 x2+a154 ; ; sz w3 2.1 ; if message.operation = input or output then jl. w3 d145. ; set_no_of_segments(message); rl w0 x1+a74 ; jl. w3 d146. ; check_i-o_transfer(disc.size, message); rl w0 x2+a138 ; so w0 2.001 ; if message.state=io then jl. j6. ; begin rl w0 x2+a154 ; sn w0 0 ; if message.number_of_segments=0 then jl. d147. ; deleiver_status('ok',message); rl w3 x2+a142 ; zl w0 x3+a12 ; message.sender.stop_count := ba. w0 1 ; message.sender.stop_count + 1; hs w0 x3+a12 ; ; end; j6: ; al w0 0 ; message.no_of_bytes := 0; rs w0 x2+a152 ; ; rl w0 x2+a153 ; message.first_segment := wa w0 x1+a73 ; message.first_segment + disc.first_segment; rs w0 x2+a153 ; jl. j5. ; end; ; j2: ; extract statistics: ; read/write defect list: zl w0 x1+a57 ; begin se w3 9 ; if message.operation = read/write_defect_list so w0 2.00001 ; and receiver.kind = locigal_disk then sz ; goto return_result_3; jl. j8. ; ; rl w3 x2+a152 ; al w0 x3+2 ; message.no_of_bytes := ws w0 x2+a151 ; (last_address - first_address + 2)/2*3 ; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; ; rl w3 x2+a142 ; message.sender.stop_count := zl w0 x3+a12 ; message.sender.stop_count + 1; ba. w0 1 ; hs w0 x3+a12 ; jl. j5. ; end; ; j3: ; sense: al w0 0 ; begin <* prepare a position operation *> rl w3 x1+a73 ; message.first_segment := disc.first_segment; ds w0 x2+a154 ; message.remaining_segments := 0; rs w0 x2+a151 ; message.first_storage_address := 0; rs w0 x2+a152 ; message.last_storage_address := 0; jl. j5. ; end; ; j4: ; format kit: ; power up spindel: ; power down spindel: zl w0 x1+a57 ; begin sz w0 2.00001 ; if receiver.type = logical_disc then jl. j8. ; goto return_result_3; jl. j5. ; end; ; j5: al w0 0 ; force := no; jl. d142. ; test_ready_and_setup(force, message); ; j7: am 2-3 ; return_result_2: j8: ; return_result_3: al w0 3 ; r=result al w3 c99 ; jl. d15. ; deliver_answer(message,result); goto return_from_interrupt; ; j9: ; end_medium: rl w0 b229 ; jl. d147. ; deliver_status('end_of_medium', message); ; j10: ; intervention: rl w0 g49 ; jl. d147. ; deliver_status('intervention', message); ; j11: ; check_logical_volume: rl w3 x1+a56 ; sl w0 0 ; if buf.first_segment <0 or sn w3 0 ; disk.successor =0 then jl. j9. ; goto end_medium ws w0 x1+a74 ; buf.first_segment:= rs w0 x2+a153 ; buf.first_segment-disk.size al w1 x3 ; ac w3 x3 ; receiver:= receiver.successor; rs w3 x2+a141 ; buf.receiver:=-disk.successor; jl. j20. ; goto message received j14: ; define logical volume: rl w3 x2+a142 ; if sender.function-bit(8) = 0 then zl w0 x3+a22 ; deliver_result_2; so w0 1<3 ; jl. j7. ; rl w0 x1+a56 ; <*check that the receiver is not already se w0 0 ; part of a logical volume *> jl. j8. ; if disk.successor = 0 then deliver_result_3; zl w0 x1+a57 ; <*check that receiver is a logical disc*> so w0 2.1 ; if receiver.state = physical_disk then jl. j8. ; deliver_result_3; rl w3 x2+a153 ; <*check successor*> ls w3 1 ; <*if mess-3 does not not hold a legal device no wa w3 b4 ; then answer unintelligble*> sl w3 (b4) ; sl w3 (b5) ; jl. j8. ; rl w3 x3 ; successor := process_description(buff.mess-3); sn w3 x1 ; if successor = receiver then deliver result(3); jl. j8. ; rl w0 x3+a10 ; <*check that successor is a logical disk*> se w0 q6 ; if successor.kind <> disk then deliver_result_3; jl. j8. ; zl w0 x3+a57 ; if successor.state <> logical_disk then se w0 2.0000001 ; deliver_result_3; jl. j8. ; ; <*everything is found to be ok*> lo. w0 i1. ; successor.state := part_of_logical_volume; hs w0 x3+a57 ; zl w0 x1+a57 ; <*if the receiver is a logical disk then so. w0 (i1.) ; it is the head of the logical volume*> lo. w0 i2. ; if receiver.state = logical_disk then hs w0 x1+a57 ; receiver.state := head_of_logical_volume rs w3 x1+a56 ; receiver.successor := successor; al w0 0 ; deliver_result_ok; jl. d147. ; ; remove logical volume: j16: rl w3 x2+a142 ; if sender.function_bit(8) = 0 then zl w0 x3+a22 ; deliver_result_2; so w0 1<3 ; jl. j7. ; zl w0 x1+a57 ; if receiver.state <> head_of_logical_volume so. w0 (i2.) ; then deliver_result_3; jl. j8. ; ; <*receiver ok*> lx. w0 i2. ; receiver.state = not(head_of_logical_volume) hs w0 x1+a57 ; al w3 0 ; <*run through logical volume and release rx w3 x1+a56 ; all logical disks*> sn w3 0 ; if successor = 0 then panic(16) jl -16 ; rs. w2 i3. ; rl. w2 i1. ; next:=disk.successor; al w0 0 ; j17: al w1 x3 ; while next <> 0 do rl w3 x1+a56 ; begin rs w0 x1+a56 ; disk.successor := 0; zl w2 x1+a57 ; lx. w2 i1. ; disk.state:=NOT(part_of_logical_volume); hs w2 x1+a57 ; end; se w3 0 ; jl. j17. ; rl. w2 i3. ; jl. d147. ; end ; i1: 2.0100000 ; bitmask: part_of_logical_volume i2: 2.1000000 ; bitmask: head_of_logical_volume i3: 0 ; saved message buffer e. ; end; \f ; ; ; ------------------------------------------------------------------------ ; ; disc driver, part 2 ; (controller ready) ; ; this part of the disc driver is called when the controller is ready ; to receive the message. ; in this part of the driver, the communication area of the controller ; is initialized in accordance with the specified message. ; ; if the message must be delivered in more than one operation to the con- ; troller (delivered as chained operations), the message buffer will be ; linked in front of the waiting queue of the main process (if not ; already there). this will only happen when the operation is input, output ; or security erase and the specified data transport exceeds a certain ; amount of data. ; in all other situations the message buffer will be linked to the physical ; disc. ; ; when this part of the disc driver deliver the message to the control- ; ler, the format of the message will be as follows: ; ; input or output security erase ; --------------- -------------- ; + 0: operation<12 + mode 18<12 + mode ; + 2: first storage address 0 ; + 4: no of bytes no of bytes ; + 6: first segment on physical disc first segment on physical disc ; + 8: remaining segments remaining segments ; ; read or write data and ecc ; -------------------------- ; + 0: operation<12 + 0 ; + 2: first address ; + 4: 2*768 (no of bytes) ; + 6: first segment on physical disc ; + 8: 0 (remaining segments) ; ; ; all other operation will be delivered unchanged to the controller ; (i.e. the format of the messages specified in the first part of the ; disc driver is not changed). ; ; at entry the specified message may either be in the waiting queue ; of the specified main process or it may be 'free'. ; ; at entry the registers contains: ; ; w0 - ; w1 main process ; w2 message ; w3 - ; b. i10, j25 w. ; <* data for disk setup *> i0: 1<17 ; param: function (always device operation) 0 ; +2: source 0 ; +4: receiver of operation (physical disk) i1: 0 ; main ; h7: ; disc driver: setup c.l53 b. f2 w. ; ***** test 7 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 7 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message: -4 - +16 > al w1 x2+a154 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 7 ***** ; rs. w1 i1. ; begin rl w3 x2+a141 ; ac w3 x3 ; physical disc := zl w0 x3+a57 ; if message.receiver.kind = physical disc then sz w0 2.00001 ; message.receiver rl w3 x3+a50 ; else message.receiver.main; rs. w3 i0.+4 ; ; zl w0 x2+a138+1 ; if message.state.regrettet then sz w0 2.0001000 ; goto stop_message; jl. j23. ; ; sz w0 2.0000110 ; if message.state = not_transfered then jl. j1. ; begin al w3 0 ; rs. w3 i0.+2 ; param.source := message; al w3 2.0000010 ; lo w3 x2+a138 ; message.state := hs w3 x2+a138+1 ; message.state or during_transfer; jl. j5. ; end j1: ; else so w0 2.0000010 ; if message.state = during_transfer then jl. j2. ; begin al w3 2 ; param.source := so w0 2.0010000 ; if message.state.com_save then al w3 1 ; com_save rs. w3 i0.+2 ; else com_area; jl. j5. ; end j2: ; else jl -1 ; panic; <* message.state = transfer_complete *> ; j5: ; al. w0 i0. ; setup(param, main, message); jl. w3 d153. ; ; <* from now on use com area: com_mes *> ; zl w3 x1+a570+a150 ; ls w3 -3 ; am x3 ; jl. ( j6.) ; goto case com_mes.operation of: j6: ; j15 ; 0: sense -1 ; 1: - -1 ; 2: - j10 ; 3: input -1 ; 4: - j10 ; 5: output j16 ; 6: format -1 ; 7: - j16 ; 8: position j16 ; 9: extract statistics j16 ; 10: power up spindel -1 ; 11: - j16 ; 12: power down spindel -1 ; 13: - -1 ; 14: - -1 ; 15: - -1 ; 16: - -1 ; 17: - j10 ; 18: security erase j10 ; 19: read data and ecc -1 ; 20: - j10 ; 21: write data and ecc -1 ; 22: - -1 ; 23: - -1 ; 24: - -1 ; 25: - -1 ; 26: - j16 ; 27: read defect list -1 ; 28: - j16 ; 29: write defect list ; j10: ; input: ; output: ; security erase: ; read/write data and ecc: zl w0 x2+a138+1 ; begin so w0 2.0000001 ; if message.state.io then jl. j11. ; begin al w3 0 ; rl w0 x1+a570+a152 ; com_mes.first_address := ls w0 1 ; com_mes.first_address + wd w0 g48 ; com_mes.no_of_bytes * 2 / 3; wa w0 x1+a570+a151 ; rs w0 x1+a570+a151 ; ; end; j11: ; rl w0 x1+a570+a152 ; al w3 0 ; com_mes.first_segment := wd w0 b222 ; com_mes.first_segment + wa w0 x1+a570+a153 ; com_mes.no_of_bytes / 768; rs w0 x1+a570+a153 ; ; rl. w2 i0.+4 ; rl w0 x1+a570+a153 ; segment_in_track := al w3 0 ; com_mes.first_segment modulo wd w0 x2+a75 ; disk.segments_pr_track; ; sh w3 0 ; if segment_in_track > 0 then jl. j12. ; begin ac w3 x3 ; rem_in_track := wa w3 x2+a75 ; disk.segments_pr_track - segment_in_track; sl w3 (x1+a570+a154) ; no_of_segments := rl w3 x1+a570+a154 ; min(rem_in_track, com_mes.remaining_segments); sz ; end j12: ; else rl w3 x1+a570+a154 ; no_of_segments := com_mes.remaining_segments; ; sl w3 (x2+a86) ; if no_of_segments > disk.max_transfer then rl w3 x2+a86 ; no_of_segments :=disk.max_transfer; ; ac w0 x3 ; com_mes.remaining_segments := wa w0 x1+a570+a154 ; com_mes.remaining_segments - no_of_segments; rs w0 x1+a570+a154 ; ; al w0 x3 ; com_mes.no_of_bytes := wm w0 b222 ; no_of_segments * 768; rs w0 x1+a570+a152 ; ; rl w2 x1+a551 ; message := main.message_buffer; ; rl w0 x1+a570+a154 ; if com_mes.remaining_segments = 0 then se w0 0 ; begin jl. j13. ; <* not chained (any more) *> ; jl w3 d5 ; unlink(message); rl. w1 i0.+4 ; al w1 x1+a54 ; link(physical_disk.event_q, message); jl w3 d6 ; ; rl. w1 i1. ; ac w0 2.001000+1 ; main.com_state := la w0 x1+a78 ; main.com_state and not in_chain; hs w0 x1+a78+1 ; ; ac w0 2.0000110+1 ; message.state := la w0 x2+a138 ; message.state and transfer_complete; al w3 2.0000100 ; lo w0 6 ; hs w0 x2+a138+1 ; jl. j14. ; end j13: ; else al w0 2.001000 ; begin <* chained *> lo w0 x1+a78 ; hs w0 x1+a78+1 ; main.com_state := main.com_state and in_chain; ; al w1 x1+a81 ; if not message in queue then sn w2 (x2+a140) ; link(main.wait_q, message); jl w3 d6 ; ; rl. w1 i1. ; ; end; j14: ; jl. j20. ; end <* input, output ..........*> ; ; j15: ; sense: al w0 8 ; begin ls w0 16 ; <* convert to position *> rs w0 x1+a570+a150 ; main.operation, mode := position, 0; ; jl. j16. ; goto position; ; end; ; j16: ; format: ; position (& sense): ; extract statistics: ; power ud/down spindel ; read/write defect list: ; begin jl w3 d5 ; rl. w1 i0.+4 ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(physical_disk.event_q, message); ; rl. w1 i1. ; ac w0 2.0000110+1 ; message.state := la w0 x2+a138 ; message.state and transfer_complete; al w3 2.0000100 ; lo w0 6 ; hs w0 x2+a138+1 ; jl. j20. ; end <* format, position .........*> ; ; j20: ; <* common part *> ; c.l53 b. f2 w. ; ***** test 8 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 8 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x2+a138 ; dump message.count, state; al w1 x2+a138 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 8 ***** ; jl. w3 d144. ; start_controller(main); jl. w3 d152. ;+0: error: clean_after_buserror(message); jl c99 ;+2: ok: return_from_interrupt; ; ; <* ----------- stop message ----------- *> j23: ; stop_message: rl. w0 i0.+4 ; begin jl. w3 d149. ; stop_message(physical_disk, main, message); am 0 ;+0: during_transfer: ;+2: transfer_complete: rl. w0 i0.+4 ; jl. d154. ; regret(physical_disk, main, message); ; <* never reached *> ; e. ; end <* disk driver part 2 *> \f ; ---------------------------------------------------------------------------- ; ; csp-terminal driver, part 1 ; ( message received ) ; ; message sent to a csp-terminal connected through an IFP/DLC device ; controller. ; ; control is transfered to this part of the csp-terminal driver from the monitor ; procedure 'send message' through the intelligent device driver entry ; table, part 1. ; ; in this part of the driver the format of the messages will be changed ; slightly. when the messages is transfered to the second part of the ; csp-terminal driver, they have the following formats: ; ; input or output lookup specification ; --------------- -------------------- ; + 0: operation<12 + mode 2<12 + 0 ; + 2: first storage address ; + 4: number of bytes ; + 6: proc flags ; + 8: name of sending process ; +10: - " - ; +12: - " - ; +14: - " - ; set specification sense ; ----------------- ----------------- ; + 0: 4<12 + 0 0<12 + 0 ; + 2: echo<11 + type ; + 4: 0 ; + 6: prompt<8 ; + 8: 0 ; +10: 0 ; +12: timer<8 ; +14: 0 ; ; at entry the specified message must have been claimed and it may not be ; in any queues. the stop count of the sender must not have been increased. ; ; at entry the registers contains: ; ; w0: - ; w1: receiver ; w2: message ; w3: - ; b. i10, j10 w. h8: ; message received: c.l53 b. f2 w. ; ***** test 25 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 25 ; f0: 0 ; <csp_terminal process> f1: 0 ; jl. f2. ; al w0 x2+a140 ; <dump message: +0 - +18> al w1 x2+a155 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 25 ***** ; ; begin rs. w1 i1. ; zl w0 x2+a138+1 ; if message.state.io then so w0 2.0000001 ; begin jl. j4. ; ; rl. w0 i0. ; jl. w3 d148. ; test_legal_operation(operatation_mask, message); rl w3 x2+a142 ; zl w0 x3+a12 ; increase_stopcount(message.sender); ba. w0 1 ; hs w0 x3+a12 ; ; rl w3 x2+a152 ; message.no_of_bytes:= al w0 x3+2 ; (last storage address - ws w0 x2+a151 ; first storage address + 2)/2*3; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; sl w0 (x1+a86) ; if message.no_of_bytes > terminal.max_transfer jl. j8. ; then got return_result_3; ; rl w3 x2+a142 ; <* move sender name to mess_4 - mess_7 *> dl w1 x3+a11+2 ; ds w1 x2+a154+2 ; dl w1 x3+a11+6 ; ds w1 x2+a154+6 ; rl. w1 i1. ; ; al w0 0 ; rx w3 x1+a75 ; message.proc_mask := se w3 (x1+a75) ; if last_user <> sender then al w0 2.10 ; changed_user rs w0 x2+a153 ; else same_user; ; end; j4: al w0 0 ; force := no; jl. d142. ; test_ready_and_setup(force, message); ; j8: ; return_result_3: al w0 3 ; message.result := 3; al w3 c99 ; deliver_answer(message,result); jl. d15. ; goto return_from_interrupt; ; csp_terminal operation mask (legal io operations): ; input output i0: a0>3 + a0>5 i1: 0 ; save receiver ; e. ; end; \f ; ------------------------------------------------------------------------- ; ; csp-terminal driver, part 2 ; (controller ready) ; ; this part of the csp-terminal driver is called when the controller is ; ready to receive the message. ; the communication area of the controller is initialized in accordance ; with the specified message. ; when this part of the csp-terminal driver is entered the message has ; the following format: ; ; ; input or output lookup specification ; --------------- --------------------- ; + 0: operation<12 + mode 2<12 + 0 ; + 2: first storage address ; + 4: number of bytes ; + 6: proc flags ; + 8: name of sending process ; +10: -- " -- ; +12: -- " -- ; +14: -- " -- ; ; set specification sense ; ----------------- ----------------- ; + 0: 4<12 + 0 0<12 + 0 ; + 2: echo<11 + type ; + 4: 0 ; + 6: prompt<8 ; + 8: 0 ; +10: 0 ; +12: timer<8 ; +14: 0 ; ; at entry the specified message may either be linked to the waiting queue ; of the specified main process or it may be out of queue. ; ; at entry the registers contains: ; ; w0: - ; w1: main ; w2: message ; w3: - ; b. i10, j10 w. ; <* data for terminal *> i0: 1 < 17 ; param: function (always device operation) 0 ; +2: source (always message) 0 ; +4: receiver of operation i1: 0 ; save main h9: ; csp_terminal driver: setup c.l53 b. f2 w. ; ***** test 26 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 26 ; f0: 0 ; <main process> f1: 0 ; jl. f2. ; al w0 x2+a140 ; <dump message: +0 - +18> al w1 x2+a155 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 26 ***** ; ; begin rl w3 x2+a141 ; ac w3 x3 ; rs. w3 i0.+4 ; save receiver; rs. w1 i1. ; save main; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 2.0001000 ; goto stop_message; jl. j2. ; ; sz w0 2.0010110 ; if message.state <> not_transfered or jl -1 ; message.state = com_copy then panic; al w3 2.0000100 ; lo w0 6 ; message.state := hs w0 x2+a138+1 ; message.state or transfer_completet; ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, message); ; jl w3 d5 ; unlink(message); rl. w1 i0.+4 ; al w1 x1+a54 ; jl w3 d6 ; link(message.receiver.event_queue, message); rl. w1 i1. ; ; j1: jl. w3 d144. ; start_controller(main); jl. w3 d152. ;+0: error: clean after buserror(message); jl c99 ;+2: ok: goto return from interrupt; ; ; ; j2: ; stop_message: al w0 x3 ; jl. w3 d149. ; stop_message(receiver, main, message); jl -1 ;+0: during transfer: not possible ;+2: transfer completed: rl. w0 i0.+4 ; jl. d154. ; regret(receiver, main, message); ; <* never reached *> ; e. ; end; \f ; ; ------------------------------------------------------------------------------ ; ; printer driver ; general sequential device driver ; part_1: message received ; ; Message send to a general sequential device/printer ; ; Control is transfered to this part of the driver from the monitor procedure ; 'send message' through the device driver entry table, part 1. ; ; In all operations which involve data transfer to or from the sending process' ; core area, the format of the message will be changed slightly in this part ; of the driver. When the message is transfered to the second part of the driver, ; the field 'last storage address' (message +4) will contain 'no of bytes'. ; ; i/o message ; ----------- ; + 0: operation < 12 + mode ; + 2: first storage address ; + 4: no of 8-bits bytes ; ; All other operations will be transfered unchanged. ; The legality of the specified operation and mode are not tested. ; ; At entry the message must have been claimed and it must not be in any queues. ; The stopcount of the sender must not have been increased. ; ; At entry the registers contains: ; ; w0 - ; w1 receiver ; w2 message ; w3 - ; b. i10, j10 w. h14: ; printer h28: ; general sequential device c.l53 b. f2 w. ; ***** test 24 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 24 ; f0: 0 ; receiver f1: 0 ; jl. f2. ; al w0 x2+a140 ; < dump message: 0 - +16 > al w1 x2+a154 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 24 ***** ; begin zl w3 x2+a138+1 ; if message.operation = i/o then so w3 2.0000001 ; begin jl. j1. ; ; rl w3 x2+a152 ; message.no of bytes := al w0 x3+2 ; (last address - first address + 2) / 2 * 3; ws w0 x2+a151 ; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; sl w0 (x1+a86) ; if message.no_of_bytes>receiver.max_transfer jl. j8. ; then goto return_result_3; ; rl w3 x2+a142 ; message.sender.stopcount := zl w0 x3+a12 ; message.sender.stopcount + 1; ba. w0 1 ; hs w0 x3+a12 ; ; jl. j2. ; end j1: ; else ; begin ; <other operations - do nothing> ; end; j2: ; al w0 0 ; force := no; jl. d142. ; test_ready_and_setup(force, message); ; j8: ; return_result_3: al w0 3 ; al w3 c99 ; deliver_answer(message,result); jl. d15. ; goto return_from_interrupt; e. ; end *** gsd/printer part_1 *** \f ; ; ; ------------------------------------------------------------------------ ; ; magnetic tape driver, part 1 ; (message received) ; ; message send to a magnetic tape which is mounted on a tape station con- ; nected through an ioc device controller. ; ; it is only possible to receive a message when the document state of the ; tape station is 'identified document mounted'. this is the only state ; in which the process has a name. ; ; control is transfered to this part of the magnetic tape driver from the ; monitor procedure 'send message' through the "intelligent" device driver ; entry table, part 1. ; ; in all operations which involve data transfer the format of the message ; will be changed slightly in this part of the driver. when the message is ; transfered to the second part of the magnetic tape driver the field ; 'last storage address' (message +4) will contain 'no of bytes': ; ; i/o messages ; ------------ ; + 0: operation<12 + mode ; + 2: first storage address ; + 4: no of bytes ; + 6: ; ; ; for all other operations, the message will be transfered unchanged. ; ; at entry the message must have been claimed and it must not be in any ; queues. the stop count of the sender must not have been increased. ; ; at entry the registers contains: ; ; w0 - ; w1 receiver (magnetic tape process description) ; w2 message ; w3 - ; b. i10, j10 w. h18: ; message received c.l53 b. f2 w. ; ***** test 11 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 11 ; f0: 0 ; < mag tape process > f1: 0 ; jl. f2. ; al w0 x2+a140 ; < dump message: +0 - +14 > al w1 x2+a153 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 11 ***** ; ; begin rl. w0 i2. ; jl. w3 d148. ; test legal operation(message, operation mask); ; zl w0 x2+a138+1 ; so w0 2.0000001 ; jl. j2. ; if message.state.io then ; begin <* input, output, extract statistics, extended sense *> rl w3 x2+a152 ; al w0 x3+2 ; message.no of bytes := ws w0 x2+a151 ; (last address - first address + 2)/2*3; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; zl w3 x2+a150 ; if message.operation = output then se w3 5 ; begin jl. j1. ; zl w3 x2+a150+1 ; message.no of bytes := ls w3 -4 ; message.no of bytes - message.mode.trail; la. w3 i0. ; ac w3 x3 ; wa w3 x2+a152 ; rs w3 x2+a152 ; end; j1: ; rl w3 x2+a152 ; if message.no of bytes < 3 or sl w3 3 ; message.no of bytes > receiver.max_transfer then sl w3 (x1+a86) ; return result('unintelligible'); jl. j4. ; rl w3 x2+a142 ; zl w0 x3+a12 ; increase stopcount(message.sender); ba. w0 1 ; hs w0 x3+a12 ; ; jl. j3. ; end j2: ; else ; begin ; <* other operations - do nothing *> ; end; ; j3: al w0 0 ; force := no; jl. d142. ; test_ready_and_setup(force, message); ; j4: ; return result: al w0 3 ; al w3 c99 ; jl. d15. ; deliver_answer(message,result); goto return_from_interrupt; ; ; i0: 2.111 ; mask for trail ; ; magnetic tape operation mask (legal operations): ; sense, input, output, erase, move, extract statistics, output file mark, ; check mode, security erase: i2: a0>0 + a0>3 + a0>5 + a0>6 + a0>8 + a0>9 + a0>10 + a0>14 + a0>18 e. ; end; \f ; ; ; ------------------------------------------------------------------------ ; ; printer driver ; ; magnetic tape driver ; ; general sequential device driver ; ; part_2: controller ready ; ; this part of the magnetic tape/gsd driver is called when the controller ; is ready to receive the message. ; in this part of the driver, the communication area of the controller ; is initialized in accordance with the specified message. ; ; the message will be linked to the event queue of the receiver. ; ; the message will be delivered unchanged to the controller. ; ; at entry the specified message may either be in the waiting queue of ; the specified main process or it may be 'free'. ; ; at entry the registers contains: ; ; w0 - ; w1 main process ; w2 message ; w3 - ; b. i10, j10 w. ; - - - data - - - ; i0: 1 < 17 ; param: function (always device operation) 0 ; +2: source (always message) 0 ; +4: receiver of operation ; i1: 0 ; save main; h15: ; printer driver: setup h19: ; magnetic tape driver: setup h29: ; general sequential device driver: setup c.l53 b. f2 w. ; ***** test 12 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 12 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message: -4 - +14 > al w1 x2+a153 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 12 ***** ; ; begin rl w3 x2+a141 ; ac w3 x3 ; rs. w3 i0.+4 ; save receiver; rs. w1 i1. ; save main; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 2.0001000 ; goto stop_message; jl. j2. ; ; sz w0 2.0010110 ; if message.state <> not_transfered or jl -1 ; message.state = com_copy then panic; al w3 2.0000100 ; lo w0 6 ; message.state := hs w0 x2+a138+1 ; message.state or transfer_completet; ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, message); ; jl w3 d5 ; unlink(message); rl. w1 i0.+4 ; al w1 x1+a54 ; jl w3 d6 ; link(message.receiver.event_queue, message); rl. w1 i1. ; ; c.l53 b. f2 w. ; ***** test 13 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 13 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message.count,state > al w1 x2+a138 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 13 ***** ; ; j1: jl. w3 d144. ; start_controller(main); jl. w3 d152. ;+0: error: clean after buserror(message); jl c99 ;+2: ok: goto return from interrupt; ; ; ; j2: ; stop_message: al w0 x3 ; jl. w3 d149. ; stop_message(receiver, main, message); jl -1 ;+0: during transfer: not possible ;+2: transfer completed: rl. w0 i0.+4 ; jl. d154. ; regret(receiver, main, message); ; <* never reached *> ; e. ; end; ; ****** stepping stones ****** ; jl. ( +2), d141 , d141 = k - 4 jl. ( +2), d142 , d142 = k - 4 jl. ( +2), d143 , d143 = k - 4 jl. ( +2), d144 , d144 = k - 4 jl. ( +2), d145 , d145 = k - 4 jl. ( +2), d146 , d146 = k - 4 jl. ( +2), d147 , d147 = k - 4 jl. ( +2), d148 , d148 = k - 4 jl. ( +2), d149 , d149 = k - 4 jl. ( +2), d150 , d150 = k - 4 jl. ( +2), d151 , d151 = k - 4 jl. ( +2), d152 , d152 = k - 4 jl. ( +2), d153 , d153 = k - 4 jl. ( +2), d154 , d154 = k - 4 jl. ( +2), d155 , d155 = k - 4 jl. ( +2), d156 , d156 = k - 4 \f ; ; ; ------------------------------------------------------------------------ ; ; ioc main process driver, part 2 ; ; dlc main process driver, part 2 ; ; (controller ready) ; ; this part of the ioc/dlc main process driver is called when the control- ; ler is ready to receive the message. ; the first part of the main process driver is implemented as a part ; of the common driver process (driverproc), and the control is transfered ; to this part of the driver through the monitor procedure 'start con- ; troller'. ; ; when this part of the driver is entered the format of the messages must ; be as follows: ; ; if the operation is 'create link' or 'remove link' the format must be: ; ; create link (IOC): create link (DLC): ; ------------------------- ------------------------- ; + 0: 6<12 + mode 6<12 + mode ; + 2: control module/formatter device type ; + 4: slave device/station no controller index/255 ; + 6: rc8000 process address (*) rc8000 process address (*) ; + 8: device kind, device type controller name ; +10: - " - ; +12: - " - ; +14: - " - ; ; remove link (IOC/DLC): ; ------------------------- ; + 0: 10<12 + 0 ; + 2: rc8000 process address (*) ; + 4: controller device index (*) ; ; if the operation are answer create link/remove link request/attention the ; format of the message must be (local message, sender is driverproc): ; ; answer attention ; answer create link answer remove link request ; ----------------------------- -------------------------- ; + 0: -1<12+0 att: -3<12 remove: -2<12 + 0 ; + 2: detailed_status, status (param_0) result (param_0) ; + 4: external process (param_1) subproc (param_1) ; + 6: controller device index (param_2) DLCindex (param_2) ;+8-+14: name of reserver (if detailed ; result = 1) ; ; ; if the operation is 'prepare dump' then the format must be: ; ; (entry part 2 format) (controller format) ; prepare dump: prepare dump: ; --------------------- -------------------- ; + 0: 2<12 + 0 2<16 + 0 ; + 2: first address (low core) first address ; + 4: 0 (no of bytes) (*) no of bytes ; + 6: first segm (area:log, disk:phys) segment ; + 8: no of segments (*) ; +10: 0 (area: next logical segment) ; +12: first address (high core) (*) ; +14: no of segments (in high core) (*) ; ; the fields marked '(*)' must be set in the first part of the main ; process driver (they are not (always) user defined). ; ; all other operations must be received unchanged. ; ; in case of a prepare dump operation it may in certain cases be delivered ; to the controller as two or more chained operations. this depends on the ; physical locations of the specified segments. ; ; at entry the message must have been claimed and the stopcount of the sender ; must have been increased if nessesary. ; ; at entry the registers contains: ; ; w0 - ; w1 main process ; w2 message ; w3 - ; b. i10, j15, o40 w. ; ========== DATA ========== ; i0: 0 ; param + 0: function 0 ; + 2: source 0 ; + 4: receiver (main) i1: 0 ; save w1: main i2: 0 ; save w2: message ; h. ; function, operation tabel: ;-------------------------- 12<5 ; -4 : stop normal communucation(rc8000 only) 4<5 + 1<4 ; -3 : answer attention 8<5 + 1<4 ; -2 : answer remove link request 2<5 + 1<4 ; -1 : answer create link i4: 10<5 ; 0 : sense 0 ; 1 : - 10<5 ; 2 : prepare dump 10<5 ; 3 : input RC8000 specific 11<5 ; 4 : soft reset rc8000 specific 10<5 ; 5 : output RC8000 specific 2<5 ; 6 : create link 0 ; 7 : - 10<5 ; 8 : position RC8000 specific 0 ; 9 : - (extract statistics - part 1 only) 3<5 ; 10 : remove link 0 ; 11 : - 0 ; 12 : - (set mask - part 1 only) 0 ; 13 : - 10<5 ; 14 : dump 0 ; 15 : - 0 ; 16 : - (link logical disk - part 1 only) 0 ; 17 : - 0 ; 18 : - (unlink logical disk - part 1 only) 0 ; 19 : - 10<5 ; 20 : test 0 ; 21 : - 9<5 ; 22 : initialize controller ; =========== end DATA ============ w. h21: ; ioc main process driver: setup h27: ; dlc main process driver: setup c.l53 b. f2 w. ; ***** test 16 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 16 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message: -4 - +22 > al w1 x2+a157 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 16 ***** ds. w2 i2. ; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 2.0001000 ; goto stop_message; jl. o27. ; ; sz w0 2.0000110 ; if message.state = not_transfered then jl. j1. ; begin al w3 0 ; rs. w3 i0.+2 ; param.source := message; rs. w1 i0.+4 ; param.receiver := main; ; <* might be changed later on dependent on oper*> el w3 x2+a150 ; zl. w0 x3+i4. ; param.function := hs. w0 i0.+0 ; function_table(message.operation); ; al w3 2.0000010 ; lo w3 x2+a138 ; message.state := message.state or hs w3 x2+a138+1 ; during_transfer ; ; jl. j2. ; end j1: ; else so w0 2.0000010 ; if message.state = during_transfer then jl. -1 ; begin ; al w3 2 ; param.source := so w0 2.0010000 ; if message.state.com_save then al w3 1 ; com_save rs. w3 i0.+2 ; else com_area; ; end ; else panic; <* message.state=transfer complete *> j2: ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, message); ; ; <* from now on use main.com_area: com_mes *> ; el w3 x1+a570+a150 ; as w3 -3 ; goto case com_mes.operation of: jl. (x3+j3.) ; ; o34 ; -4 : stop normal communication (rc8000 only) o33 ; -3 : answer attention o32 ; -2 : answer remove link request o31 ; -1 : answer create link j3: o0 ; 0 : sense -1 ; 1 : - o2 ; 2 : prepare dump o3 ; 3 : input: RC8000 specific o4 ; 4 : soft reset: rc8000 specific o5 ; 5 : output: RC8000 specific o6 ; 6 : create link -1 ; 7 : - o8 ; 8 : position: RC8000 specific -1 ; 9 : - (extract statistics) o10 ; 10 : remove link -1 ; 11 : - -1 ; 12 : - -1 ; 13 : - o14 ; 14 : dump -1 ; 15 : - -1 ; 16 : - (link logical disk) -1 ; 17 : - -1 ; 18 : - (unlink logical disk) -1 ; 19 : - o20 ; 20 : test -1 ; 21 : - o22 ; 22 : initialize controller ; ; ; o2: ; prepare dump: ; --------------- b. j5 w. ; begin rl w0 x1+a570+a154 ; se w0 0 ; if com_mes.no_of_segments = 0 then jl. j1. ; begin rs w0 x1+a570+a152 ; com_mes.no_of_bytes := 0; dl w0 x1+a570+a157 ; com_mes.first_addr := com_mes.save_first_addr; rs w3 x1+a570+a151 ; com_mes.no_of_segments := rs w0 x1+a570+a154 ; com_mes.save_no_of_segments; al w0 0 ; rs w0 x1+a570+a156 ; com_mes.save_first_addr := 0; rs w0 x1+a570+a157 ; com_mes.save_no_of_segments := 0; ; end; j1: ; al w3 0 ; rl w0 x1+a570+a152 ; com_mes.first_address := ls w0 +1 ; com_mes.first_address + com_mes.no_of_bytes * 2/3; wd w0 g48 ; wa w0 x1+a570+a151 ; rs w0 x1+a570+a151 ; ; rl w3 x1+a201 ; if main.dump_device.kind = area then rl w3 x3+a10 ; begin se w3 q4 ; jl. j2. ; rl w0 x1+a570+a155 ; al w2 x1+a570 ; <* address of message structure in main.com *> rl w1 x1+a201 ; jl. w3 d143. ; prepare_consecutive_transfer(nest_logical_segment, ; area, com_mes); rl. w1 i1. ; com_mes.next_logical_segment := rs w0 x1+a570+a155 ; next_logical_segment; jl. j3. ; end j2: ; else rl w0 x1+a570+a152 ; begin al w3 0 ; com_mes.first_segment := wd w0 b222 ; com_mes.first_segment + wa w0 x1+a570+a153 ; com_mes.no_of_bytes / 768; rs w0 x1+a570+a153 ; ; rl w2 x1+a201 ; no_of_segments := com_mes.remaining_segments; rl w3 x1+a570+a154 ; if no_of_segments > disk.max_transfer then sl w3 (x2+a86) ; no_of_segments := disk.max_transfer; rl w3 x2+a86 ; ; ac w0 x3 ; com_mes.remaining_segments := wa w0 x1+a570+a154 ; com_mes.remaining_segments - rs w0 x1+a570+a154 ; no_of_segments; al w0 x3 ; wm w0 b222 ; com_mes.no_of_bytes := rs w0 x1+a570+a152 ; no_of_segments * 768; ; rl w3 x1+a570+a154 ; ; end; j3: ; wa w3 x1+a570+a157 ; if com_mes.remaining_segments = 0 and se w3 0 ; com_mes.save_remaining_segments = 0 then jl. j4. ; begin rl. w2 i2. ; jl w3 d5 ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(main.event_q, message); ; rl. w1 i1. ; ac w0 2.0001000+1; main.com_state := la w0 x1+a78 ; main.com_state and not in_chain; hs w0 x1+a78+1 ; ac w0 2.0000110+1; la w0 x2+a138 ; message.state := al w3 2.0000100 ; message.state and transfer_complete; lo w0 6 ; hs w0 x2+a138+1 ; jl. j5. ; end j4: ; else al w1 x1+a81 ; begin rl. w2 i2. ; sn w2 (x2+a140) ; if not message.in_q then jl w3 d6 ; link(main.waiting_q, message); ; rl. w1 i1. ; al w0 2.001000 ; main.com_state := lo w0 x1+a78 ; main.com_state or in_chain; hs w0 x1+a78+1 ; ; end; j5: ; rl w3 x1+a201 ; dump_dev := rl w2 x3+a10 ; if main.dump_device.kind = disk then se w2 q6 ; main.dump_device rl w3 x3+a50 ; else ; main.dump_device.main; dl w0 x3+a77 ; main.device_id := dump_dev.device_id; ds w0 x1+a553 ; main.proc_id := dump_dev.proc_id; ; jl. o26. ; goto no message; <* message has been linked *> ; e. ; end; <* prepare dump *> o4: ; reset: ; --------------------------------------- b. j5 w. ; begin ; jl w3 d5 ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(main.event_q, message); ac w0 2.0000110+1 ; la w0 x2+a138 ; messge.state := al w3 2.0000100 ; message.state or transfer_complete; lo w0 6 ; hs w0 x2+a138+1 ; al w1 x1-a54 ; ; rl w0 x1+a10 ; if main.kind <> ifp_main then se w0 q26 ; panic; jl -1 ; ; jl. w3 d155. ; increase no_of_outstanding(main) al w0 3 ; rl w3 x1+a235 ; rs w3 b58 ; <* save device address in monitor table *> do w0 x3+0 ; reset_controller(soft); sx 2.111 ; if no exception then jl. j1. ; begin la w3 b212 ; <* clear bit 0 of device address *> wa w3 b65 ; <* clear any pending interrupt *> rl w0 x3+a313 ; gp w0 b95 ; ; <* forget about credit-counting *> jl c99 ; goto return_from_interrupt; ; end j1: ; else begin rl. w2 i2. ; jl. w3 d152. ; clear_after_buserror(message); jl c99 ; goto return_from_interrupt; ; end; e. ; end; ; o6: ; create link: ; --------------- b. j5 w. ; begin rl w0 x1+a570+a153 ; rs w0 x1+a553 ; main.proc_id := com_mes.proc_id; jl. o25. ; goto common_part; e. ; end; ; ; o10: ; remove_link: ; --------------- rl w0 x1+a570+a152 ; begin rs w0 x1+a552 ; main.controller_id := com_mes.controller_id; rl w0 x1+a570+a151 ; rs w0 x1+a553 ; main.proc_id := com_mes.proc_id; ; jl. o25. ; goto common_part; ; end; ; o14: ; dump ; --------------- b. i5, j5 w. ; begin ; zl w0 x1+a78+1 ; so w0 2.001000 ; if main.com_state = in_chain then jl. j1. ; begin rl w3 x1+a551 ; al w0 2.0010000 ; main.message.state := lo w0 x3+a138 ; main.message.state or com_save; hs w0 x3+a138+1 ; ; ac w0 2.001000+1; main.com_state := la w0 x1+a78 ; main.com_state and not in_chain; hs w0 x1+a78+1 ; ; dl w0 x1+a550+2 ; <* save the communication area *> ds w0 x1+a580+2 ; dl w0 x1+a550+6 ; ds w0 x1+a580+6 ; dl w0 x1+a550+10 ; ds w0 x1+a580+10 ; dl w0 x1+a550+14 ; ds w0 x1+a580+14 ; dl w0 x1+a550+18 ; ds w0 x1+a580+18 ; dl w0 x1+a550+22 ; ds w0 x1+a580+22 ; j1: ; end; jl. o25. ; goto common_part; e. ; end; ; ; o0: ; sense: o20: ; test: ; --------------- ; begin jl. o25. ; goto common_part; ; end; ; o22: ; initialize_controller: ; ---------------------- ; begin jl. o25. ; goto common_part; ; end; ; ; ============= messages from driverproc ============= ; o31: ; answer_create_link: ; ---------------------- rl w0 x1+a570+a151 ; begin sz w0 2.11111110; if result = 1 then jl. o33. ; rl w2 x1+a570+a153 ; begin zl w3 x2+a78+1 ; com_mes.proc_id.state := connected; al w3 x3+1 ; <* dirty! it was during connect *> hs w3 x2+a78+1 ; end; ; <* continue with the other answer setup *> ; o33: ; answer_attention: o32: ; answer_remove_link_request: ; --------------------------- ; begin dl w0 x1+a570+a153 ; main.controller_id := com_mes.controller_id; ds w0 x1+a553 ; main.proc_id := com_mes.proc_id; rl w0 x1+a570+a151 ; main.gen_info.result := com_mes.result; hs w0 x1+a550+1 ; ls w0 -12 ; <* place reserved/unknown results in right rs w0 x1+a570+a151 ; part of mess_1 *> al w2 0 ; message := main.m_b_a; rx w2 x1+a551 ; main.m_b_a := 0; ; rl w1 b21 ; <* increase bufferclaim of driverproc: al w0 1 ; it was decreased by two: in send_message and ba w0 x1+a19 ; in wait_event *> hs w0 x1+a19 ; jl w3 d109 ; remove_and_release_buffer(driverproc, message); ; jl. o26. ; goto no_message; ; end; ; ==================================================== ; ; ********** RC8000 specific ********** o3: ; input o5: ; output o8: ; position o34: ; stop normal communication ; jl. o25. ; goto common_part; ; ********** end RC8000 specific ********** o25: ; common_part: ; --------------------------------------- jl w3 d5 ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(main.event_q, message); ac w0 2.0000110+1 ; la w0 x2+a138 ; messge.state := al w3 2.0000100 ; message.state or transfer_complete; lo w0 6 ; hs w0 x2+a138+1 ; ; <* continue with no_message *> ; o26: ; no_message: ; --------------------------------------- rl. w1 i1. ; c.l53 b. f2 w. ; ***** test 17 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 17 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message state > al w1 x2+a138 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 17 ***** ; jl. w3 d155. ; increase no_of_outstanding(main) jl. w3 d144. ; start controller(main_proc); jl. w3 d152. ;+0: error: clean after buserror(message); jl c99 ;+2: ok - controller started; goto return from interrupt; ; ; o27: ; stop_message: ; ------------------ al w0 x1 ; begin jl. w3 d149. ; stop_message(main, main, message); am 0 ;+0: during transfer: ;+2: transfer complete: al w0 x1 ; jl. d154. ; regret(main, main, message); ; <* never reached *> ; e. ; end; ; \f c.-1 ; not used at RC8000 ; ; ------------------------------------------------------------------------ ; ; ssp main process driver, part 2 ; ; (controller ready) ; ; this part of the ssp main process driver is called when the controller ; is ready to receive the message. ; the first part of the main process driver is implemented as a part ; of the common driver process (driverproc), and the control is transfered ; to this part of the driver through the monitor procedure 'start con- ; troller' ; ; when this part of the driver is entered the format of the messages must ; be as follows: ; ; if the operation is 'create link' the format must be: ; ; create link (IOC): ; ------------------------- ; + 0: 6<12 + mode ; + 2: device type ; + 4: - ; + 6: rc8000 process address (*) ; ; if the operation is answer attention the format of the message must be ; (local message, sender is driverproc): ; ; answer attention ; ----------------------------- ; + 0: -3<12+0 ; + 2: result ; + 4: external process ; + 6: controller device index ; ; the fields marked '(*)' must be set in the first part of the main ; process driver (they are not (always) user defined). ; ; all other operations must be received unchanged. ; ; at entry the message must have been claimed and the stopcount of the sender ; must have been increased if nessesary. ; ; at entry the registers contains: ; ; w0 - ; w1 main process ; w2 message ; w3 - ; b. i10, j15, o40 w. ; ========== DATA ========== ; i0: 0 ; param + 0: function 0 ; + 2: source 0 ; + 4: receiver (main) i1: 0 ; save w1: main i2: 0 ; save w2: message ; h. ; function, operation tabel: ; - - - - - - - - - - - - - 4<5 + 1<4 ; -3 : answer attention 0 ; -2 : - 0 ; -1 : - i4: 0 ; 0 : - 0 ; 1 : - 0 ; 2 : - 0 ; 3 : - 0 ; 4 : - 13<5 ; 5 : operator_output 2<5 ; 6 : create link 0 ; 7 : - 0 ; 8 : - 0 ; 9 : - (extract statistics - part 1 only) 0 ; 10 : - 0 ; 11 : - 0 ; 12 : - (set mask - part 1 only) 0 ; 13 : - 0 ; 14 : - 0 ; 15 : - 0 ; 16 : - 0 ; 17 : - 0 ; 18 : - 0 ; 19 : - 0 ; 20 : - 0 ; 21 : - 9<5 ; 22 : initialize controller 0 ; 23 : - 14<5 ; 24 : close_system 0 ; 25 : - 15<5 ; 26 : reload_system ; =========== end DATA ============ w. h25: ; ssp main process driver: setup c.l53 b. f2 w. ; ***** test 16 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 16 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message: -4 - +22 > al w1 x2+a157 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 16 ***** ds. w2 i2. ; zl w0 x2+a138+1 ; if message.state = stopped then sz w0 2.0001000 ; goto stop_message; jl. o29. ; ; sz w0 2.0000110 ; if message.state = not_transfered then jl. j1. ; begin al w3 0 ; rs. w3 i0.+2 ; param.source := message; rs. w1 i0.+4 ; param.receiver := main; ; <* might be changed later on dependent on oper*> el w3 x2+a150 ; zl. w0 x3+i4. ; param.function := hs. w0 i0.+0 ; function_table(message.operation); ; al w3 2.0000010 ; lo w3 x2+a138 ; message.state := message.state or hs w3 x2+a138+1 ; during_transfer ; ; jl. j2. ; end j1: ; else jl. -1 ; panic; <* state = during_transfer/transver complete *> j2: ; al. w0 i0. ; jl. w3 d153. ; setup(param, main, message); ; ; <* from now on use main.com_area: com_mes *> ; el w3 x1+a570+a150 ; oper := com_mes.operation; as w3 -4 ; sn w3 6 ; if oper = create_link then jl. o6. ; goto create_link else sn w3 -3 ; if oper = answer_attention then jl. o33. ; goto answer_attention else jl. o27. ; goto common_end; ; ; o6: ; create link: ; --------------- b. j5 w. ; begin rl w0 x1+a570+a153 ; rs w0 x1+a553 ; main.proc_id := com_mes.proc_id; jl. o27. ; goto common_part; e. ; end; ; ; ; ; ============= messages from driverproc ============= ; ; o33: ; answer_attention: ; --------------------------- ; begin dl w0 x1+a570+a153 ; main.controller_id := com_mes.controller_id; ds w0 x1+a553 ; main.proc_id := com_mes.proc_id; rl w0 x1+a570+a151 ; main.gen_info.result := com_mes.result; hs w0 x1+a550+1 ; ls w0 -12 ; <* place reserved/unknown results in right rs w0 x1+a570+a151 ; part of mess_1 *> al w2 0 ; message := main.m_b_a; rx w2 x1+a551 ; main.m_b_a := 0; ; rl w1 b21 ; <* increase bufferclaim of driverproc: al w0 1 ; it was decreased by two: in send_message and ba w0 x1+a19 ; in wait_event *> hs w0 x1+a19 ; jl w3 d109 ; remove_and_release_buffer(driverproc, message); ; jl. o28. ; goto no_message; ; end; ; ==================================================== ; o27: ; common_part: ; --------------------------------------- jl w3 d5 ; unlink(message); al w1 x1+a54 ; jl w3 d6 ; link(main.event_q, message); ac w0 2.0000110+1 ; la w0 x2+a138 ; messge.state := al w3 2.0000100 ; message.state or transfer_complete; lo w0 6 ; hs w0 x2+a138+1 ; ; <* continue with no_message *> ; o28: ; no_message: ; --------------------------------------- rl. w1 i1. ; c.l53 b. f2 w. ; ***** test 17 ***** rs. w3 f1. ; rs. w1 f0. ; jl. w3 d150. ; 17 ; f0: 0 ; < main process > f1: 0 ; jl. f2. ; al w0 x2+a138 ; < dump message state > al w1 x2+a138 ; jl. w3 d151. ; f2: ; e.z. ; ***** end test 17 ***** ; jl. w3 d144. ; start controller(main_proc); jl. w3 d152. ;+0: error: clean after buserror(message); jl c99 ;+2: ok - controller started; goto return from interrupt; ; ; o29: ; stop_message: ; ------------------ al w0 x1 ; begin jl. w3 d149. ; stop_message(main, main, message); jl -1 ;+0: panic ;+2: transfer complete: al w0 x1 ; jl. d154. ; regret(main, main, message); ; <* never reached *> ; e. ; end; ;************** e n d o f d e v i c e d r i v e r s ***************** z. e. ; <* end of h - block *> \f 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 jd 1<11+134; emergency stop: ; in case of driverproc failure, stop all ; goto wait next; to preserve situation b. e10 w. b. i3 w. b77:jl w3 d80 ; lock monitor; b085:al w2 0 ; wait next: b084:jd 1<11+24; wait event; am (0) ; result: 0=message, 1=answer, jl. +2 ; 2=interrupt, 4=immediate message jl. e2. ;+2: message or answer: jl x2 ;+4: interrupt: goto service address; jl -123; go jump in water i0: 0 ; saved message buffer address ; message or answer: ; entry: w0=result from wait event, w2=buf e2: rl w1 b21 ; rl w3 x2+a140 ; next event; sn w3 x1+a15 ; if more in queue then jl. i2. ; begin rs. w3 i0. ; i3: sl w3 (b8+4) ; repeat <* scan of driverprocs queue for interrupt *> sl w3 (b8+6) ; if -,buffer then jl. b084. ; goto wait next; rl w3 x3+a140 ; next in queue; se w3 x1+a15 ; jl. i3. ; until end of queue; ; end; i2: rl w1 x2+6 ; sender := sender(buf); sh w1 0 ; if not regretted then jl. b084. ; 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 rl w0 x1+a10 ; la w0 g50 ; zl w3 x1+a63 ; sn w0 q8 ; if sender.kind = terminal then jl. i1. ; reset att buffer address sn w0 84 ; if kind(sender) <> subprocess se w3 8 ; or subkind(sender) <> terminal jl. b085. ; then ignore the answer; i1: al w0 0 ; reset att buffer adr sn w2 (x1+a71) ; if message = att message rs w0 x1+a71 ; jl. b085. ; goto wait next; ; message: ; entry: w1=sender, w2=buf e3: ; lock monitor; rl w3 b21 ; w3 := driverproc; 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: h8 ; 8: g2 ; 10: g2 ; 12: g2 ; 14: g2 ; 16: g2 ; 18: h20 ; 20: ida main process g2 ; 22: g2 ; 24: h26 ; 26: ifp main process 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 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 w0 -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 sn w3 0 ; if deviceadr = 0 then jl. j19. ; goto next entry; <*cpu-element*> rl w1 x3+a235-a230; device:= al w0 0 ; deviceaddr.proc.entry; jd 1<11+2 ; reset device(device,power); j19: ; next entry: 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 jl (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); jl. 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); zl w3 x2+a150 ; if message.operation=wait for mt-online then se w3 0 ; jl (b20) ; 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 proc.stat=2 and se w2 2 ; jl. j0. ; ((message.mode = wait specific main and am (b18) ; message.main = proc.main) or zl w2 +a150+1 ; message.mode = all main) then so w2 2.1 ; begin jl. j2. ; am (b18) ; message.status := 0; rl w2 +a151 ; message.mt-addr := proc; se w2 (x3+a50) ; jl. j0. ; j2: al w2 0 ; deliver result(1); ds w3 g21 ; goto exit; jl w3 g18 ; end; jl (b20) ; exit: return; e. \f ; errorlog process ; hsi 80.07.22 m. errorlog process b. i10, j10 w. i0=1<23 i0>19 j0: i0>0 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+a138 ; then answer unintelligble ls w1 -1 ; buf.state := buf.state -i/o-bit ls w1 +1 ; rs w1 x2+a138 ; (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. ;ations- ; 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: rl w0 x1+a182 ; if sender.base <> 0 then se w0 0 ; goto result3; jl g5 ; <*sender was relocated*> 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◀