DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦2361cca42⟧ TextFile

    Length: 319488 (0x4e000)
    Types: TextFile
    Names: »mprocs      «

Derivation

└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
    └─⟦2ba378e4a⟧ 
        └─⟦this⟧ »mprocs      « 

TextFile

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