|
|
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◀