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

⟦633bf5acf⟧ TextFile

    Length: 235008 (0x39600)
    Types: TextFile
    Names: »mdisc       «

Derivation

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

TextFile

\f


m.                mondisc - disc driver 17.0 beta
;--------------------------------------------------------------------------
;                      REVISION HISTORY 
;--------------------------------------------------------------------------
; DATE      TIME OR            DESCRIPTION
;           RELEASE
;--------------------------------------------------------------------------
;88.03.24 14.1A HSI  start of description
;                      regret csp-att mess when ifp is reset
;                      connect csp-terminals and -printers: set kind
;                      ifp-mess disconnect:  dont disconnect the mainprocess
;                      ifp-mess setmask: dont send operation to ifp
;                      ifp-mess copy: check that w1 is a legal address
;                      ifp-interrupt disconnect csp-terminal: send att-mess to user of remoter
;                      ifp-interrupt csp-attention: if terminal reserved then ignore
;
;                      ----- " -------- " --------: if att-receiver is unknown 
;                      then send 6<12+1 operation to adp
; 
;88.04.19  15.0  TSH   mainprocess driver/interrupt rewritten for RC9000.
;88.05.04  10.0  KAK   power interrupt at ifpmain cause return at once to
;                      driverproc's wait event
;88.05.16  13.21 kak   reset ifp/ida re-inserted with a few modification
;88.06.20  10.15 TSH   sspmain included
;88 06 24 20.06  hsi   max transfer in ifp devices set to 32000
;88 08 08  14.17 kak   sense operation to ifpmain  inserted
;88 08 16 14.43  hsi   timeout on main operations
;88 09 05 12.47  hsi   ifp mess: connect: start search for free linkproc
;                      from the highest devicenumber
;                      csp-term: set base on link when created.
;88 09 14 14.19  hsi   monitor must send a hard reset not a soft
;88 09 15 15.14        IFP/ADP: change default timeout to 60 sec.
;88 11 24 13.31  kak      -     timeout value inserted in sense message.mess_3
;89 01 30 07.51  kak   tape state inserted after answer create link
;89 03 08 09.33  kak   at interrupt received, the queue of waiting operation are checked
;                      before return to driverproc.wait_event
;                      if the interrupt is delivered from a IOC/LAN controller
;89 03 15 15.28 kak    decrease no_of_outstanding at commen end in driverprocs nterrupt procedure
;                      two new testpoint inserted in timeout and power interrup;89 03 17 11.20 kak    no_of_outstanding is set to one after reset, it will be decreased at commen end
;89 03 26 10 21 kak    when driverproc receive an attention message from a controller, it is checked that
;                      driverproc.bufferclaim > 5 before the message is sent to the receiver,
;                      otherwise only the answer to the controller is sent
;--------------------------------------------------------------------------
;                      START OF RELEASE 16.0
;89 04 11 13.38 hsi    unlink logical disk not allowed if part of logical vol.
;89 04 26 12.12  hsi   check name in createlink from lan (correction from 15.1)
;89 05 02 14.48 hsi    insert procfunc as user of new terminal link (15.1)
;--------------------------------------------------------------------------
;90 05 30 11.40 kak    START OF RELEASE 17.0
;90 05 30 11.40 kak    prepare dump excluded
;90 08 09 13.12 kak    the two attention events testbuffer full and error correction performed included as legal events
;90 10 12 1.14 kak     when excluding preparedump set timeout(ida/ifp) was excluded too this is corrected

b.i30 w.
i0=90 08 09 
i1=13 14 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.


; ---------------------------------------------------------------

;                 d i s c   d r i v e r   c o d e
;                            (dsc 801)
;
;                a r e a   p r o c e s s   c o d e

; ---------------------------------------------------------------

; this section contains the code executed by driverproc for pro-
; cessing messages to an area process or a disc driver.
;
; messages have the following format:
;
; sense          0<12 + mode         initialize 2<12
;                irrel                          no of heads
;                irrel                          disp. on odd cyl.
;                irrel                          disctype
;
; clean track    6<12 + mode         position   8<12 + mode
;                irrel                          irrel
;                irrel                          irrel
;                segment no                     segment no
;
; read           3<12 + mode         write      5<12 + mode
;                first address                  first address
;                last address                   last address
;                first segment no               first segment no
;
; get statistics 9<12 
;                first address
;                last address
;                irrel
;
; set regretted  10<12                continue  12<12   ; (used by testprograms) 
;                irrel                          irrel
;                irrel                          irrel
;                irrel                          irrel
; mode consists of a sum of one or more of following values:
;
; transput mode     0 transput of data
;                   1 transput of address marks
; error recovery    0 repeat at error
;                   2 do not repeat at error
; requeue           4 answer message after best repetitions
;                   0 requeue message after best repetitions
;                     and try later again
; read after write  0 no read after write
;                   8 read after write mode
;
; disctype 0 = dsm801, disctype 1 = dsm802 with variable offset.
;
; the answer to a message has the following format:
;
;                statusword
;                0 or number of bytes transferred
;                0 or number of chars transferred
;                i/o result, from start i/o
;                current status from controller
;                event status from controller
;                technical status from controller
;
; the following bits may be set in a statusword:
;
; bit  0 intervention, no disc driver at area process message
; bit  1 parity      , event status bit 1 or 4 (data-, hard err.)
; bit  2 sync.error  , event status bit 5 (position error)
; bit  3 data overrun, event status bit 3 (data overrun)
; bit  4 blocklength , buffer too small at get statistics
; bit  5 end medium  , 1st segm outside or curr stat b5 (seek err)
; bit 11 discerror   , requeue mode = 4 and repetitions < max
;
; the message may be sent to an area process, a logical disc
; driver (one physical disc may be split into more logical devi-
; ces) or to a physical disc driver. in either case the message is
; linked to the physical driver unless it concerns an area on a
; remote disc, in which case the code for processing such messages
; is entered.
;
; initialize, clean track, and write addr mark can only be sent to
; a reserved physical disc driver. get statistics can only be sent
; to a disc driver.
;
; segment numbers in message correspond to absolute segments
; when sent to a physical driver, to segmentno relative to start
; of logical disc when sent to a logical driver, and relative
; to areastart when sent to an area process.
;
; before linking the message to the physical disc driver it is
; reformatted and will contain sufficient information for exe-
; cuting the first part of the transfer corresponding to the
; largest number of consecutive segments starting at first seg-
; ment wanted. the buffer is updated at each portion of conse-
; cutive segments transferred until the entire number of segments
; have been transferred.
;
; when the message is linked to the physical driver it is not
; possible to see if it was sent to an area process or directly
; to a driver. however, when sent to a driver, all segments
; wanted can be processed in the first transfer, whereas an
; area process message may be processed in more transfers as
; the slices of an area need not be consecutive.
;
; the driver will automatically examine the number of heads on
; the disc, the displacement of sector zero on odd cylinders,
; and the disctype (dsm801-2) when the first message (after
; intervention) is received unless this first message is the
; initialize message.
\f



; pej 04.10.77    disc driver, contents

; c o n t e n t s
; ---------------------------------------------------------------

; definitions
; -----------
;
; constant definitions
; format of transformed message
; process description format
;
; main routines ( in sequential order)
; -------------
;
; message received by area process
; message received by disc driver
; link message to disc driver
; message not accepted
;
; process next message
; start device
;
; interrupt received
; successful transfer
; deliver answer routines
;
; error routine
;
; procedures (in alphabetical order)
; ----------
;
; check area process
; check message
; clean
; compound status
; copy statistics
; correct data
; initialize disc
; prepare consecutive segments
; setup channel program and start
; set errorkind
; set result and status
; transform first segment
; update buf
; update buf on error
; update on corrected error
; update retryinformation

b. j170, m10, p50, q70 ; disc driver and area process
\f



; pej 30.09.77    disc driver, constant definitions

; c o n s t a n t   d e f i n i t i o n s
; ---------------------------------------------------------------

; operation codes, control = even, transput = odd codes. if the
; codes are changed, also a table in proc setup channel program
; and start must be changed as well as error segment table
; updating in action 7a of error actions and proc. update buf.
q30 = 0                 ; sense
q31 = 2                 ; initialize
q32 = 3                 ; read
q33 = 5                 ; write
q34 = 6                 ; clean track
q35 = 8                 ; position
q36 = 9                 ; get statistics
q39 = 10                ; set regretted
q38 = 12                ; continue

; mode codes
q40 =     1             ; transput mode, = addr mark mode
q41 = 1 < 1             ; error recovery, = no repetition
q42 = 1 < 2             ; requeue, = do not reque
q43 = 1 < 3             ; read after write, = true

; segment units
q50 = 8                 ; no of bytes per addr mark
q51 = 12                ; -  -  chars -   -    -
q52 = 512               ; -  -  bytes -   data segment
q53 = 768               ; -  -  chars -   -    -

; process kinds
q60 = 84                ; subproc
q61 = 62                ; disc driver

; power restart parameters (time units: 0.1 msec)
q10 =  1 * 1000 * 10    ; time between sense in power rest. loop
q11 = 40 * 1000 * 10    ; maxtime to become ready at power rest.
q12 = q10               ; -       -  -      -     -  -     down
q13 = q11 / q10 + 1     ; no of times to sense at power restart
q14 = q12 / q10 + 1     ; no of times to sense at power down
q15 = 500               ; no of times to repeat at data overrun

; no of times to repeat at error
; repeats = 3           ; not defined as a constant due to imple-
                        ; mentation details. to change strategy,
                        ; correct proc update retryinformation
                        ; and action 8a and 10 in error routine.

; assembly options
q0  = (:a80>1a.1:)-1    ; disc driver included, 0=yes, -1=no
q1  = (:a82>1a.1:)-1    ; statistics included, 0=yes, -1=no
q2  = 10                ; no of entries in error segment table
\f


; pej 04.10.77    disc driver, format of transformed message

; f o r m a t   o f   t r a n s f o r m e d   m e s s a g e
; ---------------------------------------------------------------

; format of messagebuffer when linked to driver (after checking)
m0  = a145, m1 = m0+1   ; operation      , mode
m2  = m1+1,             ; first address
m3  = m2+2              ; last address
m4  = m3+2              ; first segment
m5  = m4+2, m6 = m5+1   ; no of segments , retryinformation
m7  = m6+1              ; next segment
m8  = m7+2, m9 = m8+1   ; segments wanted, remaining segments
m10 = m9+1              ; device
; operation  : not changed
; mode       : not changed
; firstaddr  : in curr transfer
; lastaddr   : not changed, used by start i/o for checking
; first segm : in curr transfer, rel. to start of disc
; no of segms: in curr transfer
; retryinf   : at read data, read addr mark:
;                 modeindex<8 + offsetindex<3 + tries
;                 modeindex  : index to modetable
;                 offsetindex: index to offset table
;                 tries      : no of tries at given modeindex
;                              and offset index
;              at read after write:
;                 writetries<3 + readtries
;                 writetries: no of times write has been tried
;                 readtries : no of times read has been tried
;                             after a write
;              at other operations:
;                 no of times the transfer has been tried
; next segm  : will be first segment in next transfer
; segms want : total no of segments wanted by sender
; rem segms  : no of segments remaining to be transferred
; device     : addr of disc driver containing sliceinformation
;              and physical segment no of first segment
\f


; pej 04.10.77    disc driver, proc descr format

; p r o c e s s   d e s c r i p t i o n   f o r m a t
; ---------------------------------------------------------------

; variables required for physical and logical disc.
    ; a250    ; driver descr addr
    ; a48     ; interval
    ; a49     ; -
    ; a10     ; kind
    ; a11     ; name
p2  = a50     ; mainproc, phys.=0, log.=addr of physical
    ; a52     ; reserver
    ; a53     ; users
    ; a54     ; next message
    ; a55     ; last message
    ; a56     ; regretted, often called interrupt address
    ; a70     ; not used
p0  = a71     ; chaintable
p1  = a72     ; slicelength
p3  = p1+2    ; first segment, phys.=0, log.= segm no of log. 0
p4  = p3+2    ; no of segments, phys.=on disc, log.=on log. disc

; disc characteristics (only required for physical disc).
p6  = p4+2    ; no of segments per track
p7  = p6+2    ; flags, used in address marks
p8  = p7+2    ; no of segments per cylinder (set by driver)
p10 = p8      ; cylinder, used during define disc
p9  = p8+2    ; displ. of sector 0 on odd cyl. (set by driver)
p11 = p9      ; head, used during define disc
p5  = p9+2    ; disctype, 0=dsm801, 1=dsm802 (var.offset)

; variables concerning state of disc (only physical disc).
p12 = p5+2    ;state, 0=after intervention, 1=defining disc,
              ;   2=ready
p13 = p12+2   ; transfer state, kind of transfer in progress
              ;   bit 0 = idle (initial state)
              ;       1 = define disc
              ;       2 = power restart
              ;       3 = sense
              ;       4 = position
              ;       5 = clean track
              ;       6 = read data
              ;       7 = read addr mark
              ;       8 = write data
              ;       9 = write addr mark
              ;      10 = read after write data
              ;      11 = read after write addr mark
p14 = p13+2   ; initdisc, 1=init at next start, 0=no
p15 = p14+1   ; retryinformation, used at driver initiated
              ;   transfers; see m6 of message buffer

; areas used by channelprograms (only physical disc).
p16 = p15+1   ; statusarea1, statusarea for first sense
              ; +0 : channel program counter
              ; +2 : remaining bytecount
              ; +4 : current status
              ; +6 : event status
              ; +8 : last read addr mark (4 words)
              ; +16: ecc, error correction information (2 words)
              ; +20: technical status
p18 = p16+22  ; statusarea2, statusarea for second sense, for-
              ;   matted as statusarea1
p22 = p18+8   ; addr mark, input area at define disc (4 words)
p36 = p18+16  ; actionkey, used in error actions
p37 = p18+18  ; actionindex, used in error actions
p38 = p18+20  ; write ok, used at read after write error
p20 = p18+22  ; seek parameter
              ; +0: cylinder<8 + head
              ; +2: sector<16 + flags
p21 = p20+4   ; setmode parameter, bit16-17:strobe,
              ;   bit18-19:offset, bit20-23:offset magnitude
              ;   (set to zero if strobe-offset not used)

; other variables (only physical disc).
p31 = p21+2   ; +0: curr status  (sum of all statusareas)
              ; +2: event status (-   -  -   -          )
p33 = p31+4   ; technical status (-   -  -   -          )
p34 = p33+2   ; compound status, formed from p31,p32,i/o result
p35 = p34+2   ; segment unit in curr transfer:
              ; +0: bytes per segment
              ; +2: chars per segment

; statistical information (only physical disc).
p40 = p35+4   ; no of transfers
p41 = p40+2   ; no of transfers not successful in first attempt
              ;   (intervention, power restart, power down,
              ;    write protect are not counted)
p42 = p41+2   ; no of errors corrected by ecc without repetition
p43 = p42+2   ; no of errors corrected within 3 retries
              ; strobe offset table, no of errors corrected by:
p44 = p43+2   ;   strobe 0 & offset n , strobe 0 & offset p
              ;                       , strobe l & offset 0
              ;   strobe l & offset n , strobe l & offset p
              ;                       , strobe e & offset 0
              ;   strobe e & offset n , strobe e & offset p
              ;   (e=early, l=late, p=positive, n=negative)
p45 = p44+10  ; no of errors corrected by offset magnitude  -,  1
              ;                                             2,  3
              ;                                             4,  5
              ;                                             .   .
              ;                                             .   .
              ;                                            14, 15
              ;   (first byte not used, magnitude 0 unexistent)
p47 = p45+16  ; counters for compound status bit  0, 1
              ;                                   2, 3
              ;                                   .  .
              ;                                   .  .
              ;                                  22,23
p48 = p47+24  ; counters for technic. status bit  0, 1
              ;                                   2, 3
              ;                                   .  .
              ;                                   .  .
              ;                                  22,23
p46 = p48+24  ; table of error segments, an entry contains
              ; +0: segment no. (physical)
              ; +2: no of reads ok   +3: no of reads with rep.
              ; +4: no of writes ok  +5: no of writes with rep.
p50=p46+q2*6-p40; size of statistics in bytes

; ***** please note that:
;       - declarations of p10 and p8 are equal.
;       - declarations of p11 and p9 are equal.
;       - p22, p36, p37, and p38 are declared inside p18.
;       conflicts in use will not occur as overlapping locations
;       are not used simultanously.
\f



; pej 21.09.77    area process, message received

; m e s s a g e   r e c e i v e d   b y   a r e a   p r o c e s s
; ---------------------------------------------------------------

m.                area process

; this routine is entered when driverproc receives a message for
; an area process. curr receiver (b19) = area process descr.

b. i10 w.               ; block containing area proc driver

; check if sender ok and if specified operation legal.
h5  : bz  w0  x2+m0     ; area process: c. w2 = curr buf;
      sn  w0     q33    ;   if operation.curr buf = output
      am         g15-g14;   then check reservation
      jl  w3     g14    ;   else check user;
      dl. w1     i0.    ;
      jl  w3     g16    ;   check operation(oper mask,mode mask);

; check the area process.
      jl. w3     j1.    ;   check area process;
      jl.        j37.   ;   if area segms < 0 then goto outside;
      jl.        j35.   ;   if no doc then goto doc not found;

; now curr receiver = disc driver (physical or logical). check
; if the disc is a remote disc or that disc driver included.
      rs  w1  x2+m7     ;   save area process addr in curr buf;
      rl  w0  x3+a10    ;
      la  w0     g50    ;
      se  w0     q60    ;   if kind.curr receiver = subproc then
      jl.        i10.   ;   begin c. remote disc;
      rs  w1  x3+a56    ;      interrupt addr.curr rec:= area proc;
      jl.       (2), h84;      goto subproc driver;
i10 :                   ;   end;
      c.        -q0-1   ;   if disc driver not included
      jl         g3     ;   then goto result 5; c. unknown;
      z.                ;
      c.         q0     ;

; check contents of the message
      rl  w0  x1+a61    ;   top:= no of segments.area proc;
      al  w1     q52    ;   bytes:= no of bytes in data segments;
      jl. w3     j2.    ;   check message(top,bytes);
      jl.        j37.   ;   if outside then goto outside;

; convert first segment into a segment no relative to discstart
; and prepare first portion of consecutive segments
      bz  w0  x2+m0     ;
      sn  w0     q30    ;   if operation.curr buf <> sense then
      jl.        j30.   ;   begin
      rl  w1  x2+m7     ;     area proc:= saved area proc;
      jl. w3     j3.    ;     transform first segm(area proc);
      bz  w0  x2+m0     ;
      se  w0     q35    ;     if operation.curr buf <> position
      jl. w3     j4.    ;     then prepare consec segms(curr rec);
                        ;   end;
      jl.        j30.   ;   goto link message;
      z.                ;

; legal mode combinations:
;          read after write
;              requeue
;                  error recovery
i1  = a0>(:        q41:)
i2  = a0>(:    q42    :)
i3  = a0>(:    q42+q41:)
i4  = a0>(:q43        :)
i5  = a0>(:q43    +q41:)
i6  = a0>(:q43+q42    :)
i7  = a0>(:q43+q42    :)

; oper and mode masks for area process message
      a0>q30+a0>q32+a0>q33+a0>q35
                        ; oper mask: sense, read, write, pos.
i0  : a0>0+i1+i2+i3+i4+i5+i6+i7
                        ; mode mask: no addr mark transput

e.                      ; end of area process driver
\f

; pej 21.09.77    disc driver, message received

; m e s s a g e   r e c e i v e d   b y   d i s c   d r i v e r
; ---------------------------------------------------------------

b. i50 w.               ; block including disc driver
h6  :                   ;
                        ;
      c.         q0     ;
m.                dsc 801

; this routine is entered when driverproc receives a message for
; a disc driver. curr receiver (b19) = (logical or physical) disc
; driver process description.

; check if sender ok and if specified operation legal
      bz  w0  x2+m0     ; disc driver: c. w2 = curr buf;
      sn  w0     q33    ;   if operation.curr buf = output
      jl.        j20.   ;
      se  w0     q31    ;   or operation.curr buf = initialize
      sn  w0     q34    ;   or operation.curr buf = clean track
j20 : am         g15-g14;   then check reservation
      jl  w3     g14    ;   else check user;
      dl. w1     i0.    ;   use oper/mode mask for phys. driver;
      am        (b19)   ;
      rl  w3     p2     ;
      sn  w3     0      ;   if mainproc.curr receiver <> 0 then
      jl.        j25.   ;   begin c. logical disc driver;
      rl. w0     i1.    ;     use oper mask for logical driver;
      bz  w3  x2+m0     ;     if operation.curr buf = output
      sn  w3     q33    ;     then use  mode mask for output;
      rl. w1     i2.    ;   end;
j25 : jl  w3     g16    ;   check operation(oper mask,mode mask);
; check if message is continnue.
; such a message should not be linked up to the physical driver.
; if regretted is set by the command "set regretted " the message 
; is answered ok and the physical disc is started in rutine process
; next message. otherwise the message is answered with result 3 and 
; and no action is performed.

      bz  w3  x2+m0     ; if operation.curr buf = continue then
      se  w3     q38    ; begin
      jl.        j28.   ; if regretted not set by "set regret"
      am        (b19)   ; ( regretted.curr receiver=3)
      rl  w1    +a56    ; then deliver result 3 else
      se  w1     3      ; deliver result 1 and continue with 
      jl         g5     ; process next message
      jl.        j101.  ; end 

; check contents of the message
j28 : bz  w0  x2+m1     ;
      al  w1     q52    ;   if transput mode.curr buf = 0
      sz  w0     q40    ;   then bytes:= bytes in data segments
      al  w1     q50    ;   else bytes:= bytes in addr marks;
      am        (b19)   ;
      rl  w0     p4     ;   top:= no of segments.curr receiver;
      jl. w3     j2.    ;   check message(top,bytes);
      jl.        j37.   ;   if outside then goto outside;
      jl.        j30.   ;   goto link message;

; legal mode combinations:
;          read after write
;              requeue
;                  error recovery
;                      transput of addr marks
i3  = a0>(:            q40:)
i4  = a0>(:        q41    :)
i5  = a0>(:        q41+q40:)
i6  = a0>(:    q42        :)
i7  = a0>(:    q42    +q40:)
i8  = a0>(:    q42+q41    :)
i9  = a0>(:    q42+q41+q40:)
i10 = a0>(:q43            :)
i11 = a0>(:q43        +q40:)
i12 = a0>(:q43    +q41    :)
i13 = a0>(:q43    +q41+q40:)
i14 = a0>(:q43+q42        :)
i15 = a0>(:q43+q42    +q40:)
i16 = a0>(:q43+q42+q41    :)
i17 = a0>(:q43+q42+q41+q40:)

; get statistics operation only allowed if statistics wanted
c. q1                   ;
i18 = a0>q36            ; statistics wanted
z.                      ;
c. -q1-1                ;
i18 = 0                 ; statistics not wanted
z.                      ;

; oper and mode masks for disc driver message

; op: sense  init.  read   write  clean  pos.   stat.  regr.   cont.
i1  : a0>q30       +a0>q32+a0>q33       +a0>q35+i18; logical
      a0>q30+a0>q31+a0>q32+a0>q33+a0>q34+a0>q35+i18+a0>q39+a0>q38; physical
    ; physical driver modes (all):
i0  : a0>0+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15+i16+i17
    ; logical driver modes at output (all except addrmarks):
i2  : a0>0   +i4   +i6   +i8   +i10    +i12    +i14    +i16
\f


\f

; pej 22.09.77    disc driver, link message

; l i n k   m e s s a g e   t o   d i s c   d r i v e r
; ---------------------------------------------------------------

; this routine is entered when a message received by an area
; process or a disc driver has been checked. the message is
; linked to the physical disc driver and curr receiver will
; be changed accordingly.
; 
; please note that the buffer is not claimed by the driver during
; the processing. the claiming takes place when the answer is re-
; turned, see procedure deliver result.

; change curr receiver into physical driver.
j30 : rl  w1     b19    ; link message: c. w2 = curr buf;
      rs  w1  x2+m10    ;   device.curr buf:= curr receiver;
      rl  w1  x1+p2     ;   if mainproc.curr receiver <> 0 then
      sn  w1     0      ;   begin c. curr rec = logical driver;
      jl.        j32.   ;     curr receiver:= mainproc.curr rec;
      rs  w1     b19    ;   end;

; link the message by calling procedure link operation which
; will continue in case the driver is idle or otherwise will
; jump to waitnext in driver proc.
j32 : jl  w3     g17    ;   link operation(curr buf);
      jl.        j50.   ;   goto process next message;
      z.                ;
\f

; pej 22.09.77    disc driver, message not accepted

; m e s s a g e   n o t   a c c e p t e d
; ---------------------------------------------------------------

; the routines are entered when a message received by an area
; process or a disc driver can not be accepted. the message
; is answered and continuation takes place at waitnext in driver
; proc.

j35 : rl  w0     g49    ; document not found:
      jl.        j41.   ;   status:= bit 0; c. intervention;

j37 : rl  w0     g62    ; outside:
                        ;   status:= bit 5; c. end medium;

j41 : rs  w0     g20    ;   status.i/o answer:= status; c. w0;
      ld  w1    -100    ;   bytes.i/o answer:=
      ds  w1     g22    ;   chars.i/o answer:= 0;
      jl         g7     ;   goto result 1; c. cont. at waitnext;
\f


; pej 20.09.77    disc driver, check area process

; procedure check area process
; ---------------------------------------------------------------
;
; the procedure performs:
; - checks if no of segments.curr receiver (= area proc) >= 0.
; - searches for document.curr receiver if device addr.curr
;   receiver = 0 and initializes device addr.curr receiver.
; - changes curr receiver to device addr.curr receiver .
;    (i.e. to disc driver).
;
; registers: call              exit
; w0                           destroyed
; w1                           area proc (= curr receiver at call)
; w2                           curr buf
; w3         link              curr receiver
;
; entry    : j1
;
; return   : link+0: no of segments.area proc < 0
;            link+2: document not found
;            link+4: normal return
b. i2 w.
j1  : rs. w3     i0.    ; check area proc: save link;
      rl  w1     b19    ;
      rl  w3  x1+a61    ;
      sh  w3    -1      ;   if no of segms.curr receiver < 0
      jl.       (i0.)   ;   then outside return; c. link;
      rl  w3  x1+a50    ;
      se  w3     0      ;   if device addr.curr receiver = 0 then
      jl.        i1.    ;   begin
      al  w2  x1+a62    ;     name:= document.curr receiver;
      dl  w1     d72    ;     base:= max interval;
      jl  w3     d71    ;     search name(name,entry,base);
      rl  w1     b19    ;
      sn  w3    (b7)    ;     if entry = nametable end
      jl.        i2.    ;     then goto doc not found return;
      rl  w3  x3+0      ;     device addr.curr receiver:=
      rs  w3  x1+a50    ;     core(entry);
i1  : rl  w2     b18    ;   end;
      rs  w3     b19    ;   curr receiver:=device addr.curr receiver;
      am.       (i0.)   ;
      jl         4      ;   normal return; c. link+4;
i2  : am.       (i0.)   ; doc not found return;
      jl         2      ;   goto link+2;

; variables
i0  : 0                 ; saved link
e.
      c.         q0     ;
\f

; pej 21.09.77    disc driver, check message

; procedure check message(top segment,bytes per segment)
; ---------------------------------------------------------------
; top segment      : highest allowed segment no + 1.
; bytes per segment: no of bytes to be transferred per segment.
;
; the procedure performs:
; - zeroizes retryinformation.curr buf.
; - checks that 0 <= first segment.curr buf < top segment (not
;   for sense, initialize, get statistics).
; - sets segms wanted.curr buf and remaining segms.curr buf
;   and no of segments.curr buf to:
;   (lastaddr.curr buf + 2 - firstaddr.curr buf)/bytes per segm.
;   (undefined for sense, initialize, get statistics).
;
; registers: call              exit
; w0         top segment       destroyed
; w1         bytes per segm.   unchanged
; w2         curr buf          unchanged
; w3         link              destroyed
;
; entry    : j2
;
; return   : link+0: first segment.curr buf outside limits
;            link+2: normal return
b. i2  w.
j2  : rs. w3     i0.    ; check message: save link;
      al  w3     0      ;
      hs  w3  x2+m6     ;   retryinformation.curr buf:= 0;
      rl  w3  x2+m4     ;
      sl  w3     0      ;   if first segment.curr buf >= 0
      sl  w3    (0)     ;   and first segm.curr buf < top segment
      jl.        i2.    ;   then
      rl  w3  x2+m3     ;   begin
      al  w3  x3+2      ;     segments wanted:=
      ws  w3  x2+m2     ;     (lastaddr.curr buf + 2
      al  w2     0      ;      - first addr.curr buf)
      wd  w3     2      ;     / bytes per segment;
      rl  w2     b18    ;     segments possible:=
      ws  w0  x2+m4     ;     top segment - first segm.curr buf;
      sh  w0  x3+0      ;
      rl  w3     0      ;     s:= min(segms wanted,segms poss.);
      hs  w3  x2+m5     ;     no of segments.curr buf:=
      hs  w3  x2+m8     ;     segments wanted.curr buf:=
      hs  w3  x2+m9     ;     remaining segments.curr buf:= s;
i1  : am.       (i0.)   ; normal: normal return; c. link+2;
      jl         2      ;   end
i2  : bz  w3  x2+m0     ;   else
     se  w3  q39       ; if operation.curr = set regret or
      sn  w3     q30    ;    operation.curr buf = sense
      jl.        i1.    ;
      se  w3     q31    ;   or operation.curr buf = initialize
      sn  w3     q36    ;   or operation.curr buf = get statist.
      jl.        i1.    ;   then goto normal
      jl.       (i0.)   ;   else outside return; c. link+0;

; variables
i0  : 0                 ;
e.
\f

; pej 21.09.77    disc driver, transform first segment

; procedure transform first segment(area process)
; ---------------------------------------------------------------
; area process: addr of area proc which received curr buf.
;
; the procedure performs:
; - transforms first segment.buf from being a segment no relative
;   to bs-area start into being a segment no relative to start
;   of (physical or logical) disc.
;
; registers: call              exit
; w0                           destroyed
; w1         area process      curr receiver
; w2         curr buf          unchanged
; w3         link              destroyed
;
; entry    : j3
;
; return   : link+0
b. i0 w.
j3  : rs. w3     i0.    ; transform first segment: save link;
      al  w3     0      ;
      rl  w0  x2+m4     ;   no of slices:=
      am        (b19)   ;   first segment.curr buf
      wd  w0     p1     ;   / slicelength.curr receiver;
      rs  w3  x2+m4     ;   first segment.curr buf:= remainder;
      rl  w2  x1+a60    ;   index:=
      rl  w1     b19    ;   first slice.area proc
      wa  w2  x1+p0     ;   + chaintable.curr receiver;
      jl  w3     d74    ;   follow chain(noof slices,index,slice);
      ws  w2  x1+p0     ;   slice:= slice - chaintable.curr rec;
      al  w0  x2+0      ;
      rl  w2     b18    ;
      wm  w0  x1+p1     ;   first segment.curr buf:=
      wa  w0  x2+m4     ;   slice * slicelength.curr receiver
      rs  w0  x2+m4     ;   + first segment.curr buf;
      jl.       (i0.)   ;   return;

; variables
i0  : 0                 ; saved link
e.
\f

; pej 21.09.77    disc driver, prepare consecutive segments

; procedure prepare consecutive segments(proc)
; ---------------------------------------------------------------
; proc: addr of disc proc descr containing sliceinformation.
;
; the procedure performs:
; - initializes no of segments.curr buf by the largest possible
;   number of adjecent segments which can be transferred from
;   first segment.curr buf and on.
; - sets next segment.curr buf to a value which may be used as
;   first segment in the next call of this procedure.
;
; note: must only be called in connection with message origi-
;       nating from an area process.
;
; registers: call               exit
; w0                            destroyed
; w1         proc               unchanged
; w2         curr buf           unchanged
; w3         link               destroyed
;
; entry    : j4
;
; return   : link+0
b. i3 w.
j4  : rs. w3     i0.    ; prepare consecutive segments:
      bz  w3  x2+m9     ;   save link;
      rs. w3     i1.    ;   remaining:= remaining segms.curr buf;
      rl  w3  x2+m4     ;
      al  w2     0      ;   slice:= first segment.curr buf
      wd  w3  x1+p1     ;           / slicelength.proc
      wa  w3  x1+p0     ;           + chaintable.proc;
      ws  w2  x1+p1     ;   segments possible:= slicelength.proc
      ac  w0  x2+0      ;   - first segm.curr buf mod slicel.proc;
i2  : bl  w2  x3+0      ;   while core(slice) = 1
      sn  w2     1      ;   and segments possible < remaining do
      sl. w0    (i1.)   ;   begin
      jl.        i3.    ;     slice:= slice + 1;
      al  w3  x3+1      ;     segments possible:=
      wa  w0  x1+p1     ;     segments possible+slicelength.proc;
      jl.        i2.    ;   end;
i3  : ba  w3  x3+0      ;
      ws  w3  x1+p0     ;   next segment.curr buf:=
      wm  w3  x1+p1     ;   (slice + core(slice) - chaintab.proc)
      rl  w2     b18    ;   * slicelength.proc;
      rs  w3  x2+m7     ;
      sl. w0    (i1.)   ;   if segments possible >= remaining
      rl. w0     i1.    ;   then segments possible:= remaining;
      hs  w0  x2+m5     ;   no of segms.curr buf:= segms possible;
      jl.       (i0.)   ;   return;

; variables
i0  : 0                 ; saved link
i1  : 0                 ; remaining (from rem.segms.curr buf)
e.
\f


; pej 04.10.77    disc driver, proc copy statistics

; procedure copy statistics(result,words)
; ---------------------------------------------------------------
; result: see proc copy to buffer.
; words : no of words copied.
;
; the procedure performs:
; - copies the number of words specified in curr buf from
;   statistics of curr receiver.
; - zeroizes the statistics area if copy ok.
;
; registers: call              exit
; w0                           result if result <> ok return
; w1         curr receiver     destroyed
; w2         curr buf          curr receiver if normal return
; w3         link              words if normal return
;
; entry    : j5
;
; return   : link+0: not enough room in buf for statistics
;            link+2: result <> ok
;            link+4: normal return
c. q1
b. i8 w.
j5  : al  w0     2      ; copy statistics:
      wa  w0  x2+m3     ;   bytes:= 2 + lastaddr.curr buf
      ws  w0  x2+m2     ;           - firstaddr.curr buf;
      la  w0     g50    ;   make bytes even;
      sl  w0     p50    ;   if bytes < length of statistics
      jl.        i2.    ;
      jl      x3+0      ;   then no room return;
i2  : al  w3  x3+2      ;   link:= link + 2;
      rs. w3     i0.    ;   save link;
      rs. w0     i1.    ;   save bytes;
      al  w1  x1+p40    ;   first:= addr of statistics.curr rec;
      rs. w1     i6.     ;
      wa  w1     0       ;
      al  w1  x1-2       ;
      rs. w1     i7.     ;
      al. w1     i5.     ;
      jd         1<11+84 ;
      se  w0     0      ;   if result <> 0
      jl.       (i0.)   ;   then return; c. link + 2;
      rl  w2     b19    ;
      al  w1  x2+p40    ;   i:= addr of statistics.curr rec;
      al  w3  x1+p50    ;
      al  w0     0      ;   repeat
i3  : rs  w0  x1+0      ;     curr receiver(i):= 0;
      al  w1  x1+2      ;     i:= i + 2
      se  w1  x3+0      ; 
      jl.        i3.    ;   until i = top of statistics;
      al  w0    -1      ;   entry:= 1st error segment.curr rec;
      al  w3  x2+p46    ;   repeat
i4  : rs  w0  x3+0      ;     segment no.entry:= -1;
      al  w3  x3+6      ;     entry:= entry + 1
      se  w3  x2+p46+q2*6;
      jl.        i4.    ;   until entry = top entry;
      rl. w3     i1.    ;
      ls  w3    -1      ;   words:= bytes / 2;
      am.       (i0.)   ;
      jl         2      ;   return; c. link + 4;

; variables
i0  : 0                 ; saved link
i1  : 0                 ; saved bytes

i5:   2<1+1              ; function
i6:   0                  ; first
i7:   0                  ; last
      0                  ; relative
e.
z.

\f


; pej 30.09.77    disc driver, initialize disc

; procedure initialize disc
; ---------------------------------------------------------------
;
; the procedure performs:
; - sets no of segments per cylinder and displacement of sector
;   zero on odd cylinders and the disctype in the driver process
;   description from information supplied in curr buf.
; - sets state.curr receiver to ready indicating that define disc
;   should not be executed.
; - sets initdisc.curr receiver = 1.
;
; registers: call              exit
; w0                           destroyed
; w1         curr receiver     unchanged
; w2         curr buf          unchanged
; w3         link              destroyed
;
; entry    : j6
;
; return   : link+0
b. i0 w.
j6  : rs. w3     i0.    ; initialize disc:
      rl  w0  x2+m2     ;
      wm  w0  x1+p6     ;   no of segments per cyl.curr rec:=
      rs  w0  x1+p8     ;   no of heads.curr buf
      rl  w0  x2+m3     ;   * no of segments per track.curr rec;
      rs  w0  x1+p9     ;   displacement.curr rec:= disp.curr buf;
      rl  w0  x2+m4     ;   disctype.curr receiver:=
      rs  w0  x1+p5     ;   disctype.curr buf;
      al  w0     2      ;
      rs  w0  x1+p12    ;   state.curr receiver:= ready;
      al  w0     1      ;
      hs  w0  x1+p14    ;   initdisc.curr receiver:= 1;
      jl.       (i0.)   ;   return;

; variables
i0  : 0                 ; saved link
e.
\f


; pej 19.09.77    disc driver, setup channelprogram and start

; procedure setup channel program and start(kind,result);
; ---------------------------------------------------------------
; kind  : 0 : setup channel pg according to curr buf.
;         q39: define disc, setup read.       (has no connection to
;         q39+2: power rest., setup sense.     the commands set regretted and continue )
; result: result from procedure start i/o.
;
; the procedure performs:
; - sets up a channelprogram according to either the contents
;   of curr buf, a channel program for reading addr mark at
;   define disc or a channel program for sensing the disc at
;   power restart.
;
;   please note that if a channelprogram for reading or writing
;   is set up according to curr buf, and no of segments.curr buf
;   equals zero then firstaddr.curr buf is not used in the
;   transfer command as procedure update buf on error may have
;   incremented firstaddr.curr buf beyond lastaddr.curr buf.
;   instead, to avoid result 3 from start i/o, the transfer
;   command will contain a first address pointing into drivers
;   process description.
; - calls procedure start i/o to start the transfer. the device
;   is reset if initdisc.curr receiver <>0, and initdisc:= 0.
; - sets segment units.curr receiver at read or write to
;   bytes-chars per segment.
; - zeroizes remaining bytes, curr status, event status, and
;   technical status in the two statusareas.
; - zeroizes setmode param.curr receiver if setmode is not used
;   (read, write, clean, position).
; - continues at waitnext in driver proc if the device is started
;   or, if not, returns with a result (see proc start i/o).
;
; registers: call              exit
; w0                           result
; w1         kind              channel pg start
; w2                           0 or buf
; w3         link              device address
;
; entry    : j0
; 
; return   : waitnext if ok
;            link+0 if error

b. c74, i110, l1, n10 w.
\f

; pej 19.09.77    disc driver, setup channelprogram and start

j0  :                   ; setup channel program and start:
      rs. w3     i0.    ;   save link;

; initialize according to most frequently used channel pg
      rl. w0     i4.    ;   command.mode.channel pg:= noop;
      rs. w0     c1.    ;   c. do not use strobe-offset;
      rl. w0     i5.    ;   command.first stop.channel pg:= stop;
      rs. w0     c5.    ;   c. not read after write;
      al. w0     c2.    ;
      rs. w0     i1.    ;   startaddr:= first seek.channel pg;
      rl  w2     b18    ;
      sn  w1     0      ;   if kind = 0
      bz  w1  x2+m0     ;   then kind:= operation.curr buf;
      la  w1     g50    ;
      wm  w1     g48    ;   i:= (kind >> 1) << 1 * 3;
      dl. w0  x1+l0.    ;   command.first transfer.channel pg:=
      rs. w3     c3.    ;   operation table(i);
      am        (b19)   ;   transfer state.curr receiver:=
      rs  w0     p13    ;   operation table(i + 2);
      rl. w0  x1+l1.    ;
      rs. w0     i2.    ;   actionaddr:= operation table(i + 4);

; enter next action with w1 = curr receiver, w2 = curr buf
i20:  rl  w1     b19    ; central action: w1:= curr receiver;
      rl  w2     b18    ;   w2:= curr buf;
      am.       (i2.)   ;   actionaddr:= actionaddr + 1;
      al  w3     1      ;
      rs. w3     i2.    ;
      ba  w3  x3        ;
      jl      x3        ;   goto actiontable(actionaddr);

; actiontable
h.  ;  0   1   2   3   4   5   6   7   8   9   10
i101:                             n7.,    n9.      ; sense
i102: n0.,    n2.,        n5.,        n8.,    n10. ; read
i103: n0.,    n2.,            n6.,    n8.,    n10. ; write
i104: n0.,        n3.,                n8.,n9.      ; clean
i105: n0.,                            n8.,n9.      ; position
i106:     n1.,        n4.,            n8.,n9.      ; define disc
i107:                             n7.,    n9.      ; power rest.
w.
\f

; pej 19.09.77    disc driver, setup channelprogram and start

; action 0, calculate seekinformation (read,write,clean,pos.).
n0  : rl  w0  x2+m4     ; action 0:
      am     (x2+m10)   ;   s:= first segment.curr buf
      wa  w0     p3     ;   + first segment.device.curr buf;
      ld  w3    -100    ;
      rs  w3  x1+p21    ;   setmode param.curr receiver:= 0;
      wd  w0  x1+p8     ;   cyl:= s / segments per cyl.curr rec;
                        ;   r:= s mod segments per cyl.curr rec;
      wd  w3  x1+p6     ;   head:= r / segms per track.curr rec;
                        ;   sect:= r mod segms per track.curr r;
      sz  w0     2.1    ;   if cyl odd
      wa  w2  x1+p9     ;   then sect:=
      sl  w2 (x1+p6)    ;   (sect + displacement.curr receiver)
      ws  w2  x1+p6     ;   mod segments per track.curr receiver;
i25:  ls  w0     8      ; insert seekinformation:
      wa  w3     0      ;   c. w0=cyl,w1=curr,w2=sect,w3=head;
      rs  w3  x1+p20    ;   seek param(0).curr receiver:=
      ls  w2     16     ;   cyl << 8 + head;
      wa  w2  x1+p7     ;   seek param(2).curr receiver:=
      rs  w2  x1+p20+2  ;   sect < 16 + flags.curr receiver;
      jl.        i20.   ;   goto central action;

; action 1, calculate transfer - and seekinformation (define disc)
n1  : al  w3     p22    ; action 1:
      al  w0     q51    ;   first addr.1st transfer.channel pg:=
      ds. w0     c34.   ;   addr mark.curr receiver;
      rl  w0  x1+p10    ;   charcount.1st transfer.ch pg:=chars;
      rl  w3  x1+p11    ;   cyl:= define disc cyl.curr receiver;
      rl  w2  x1+p6     ;   head:= define disc head.curr rec;
      al  w2  x2-1      ;   sect:= segms per track.curr rec - 1;
      jl.        i25.   ;   goto insert seekinformation;

; action 2, calculate transferinformation (read,write).
n2  : dl. w0     i10.   ; action 2:
      ds  w0  x1+p35+2  ;   segment units.curr receiver:=
      bz  w0  x2+m1     ;   chars-bytes per data segment;
      so  w0     q40    ;   if transput mode.curr buf = 1 then
      jl.        i30.   ;   begin c. addr mark mode;
      rl. w0     c3.    ;
      lo. w0     i8.    ;     command.1st transfer.channel pg:=
      rs. w0     c3.    ;     command.1st transfer.channel pg
      rl  w0  x1+p13    ;     +modif;
      ls  w0     -1     ;     transfer state.curr receiver:=
      rs  w0  x1+p13    ;     transfer state.curr receiver >> 1;
      dl. w0     i9.    ;     segment units.curr receiver:=
      ds  w0  x1+p35+2  ;     chars-bytes per addr mark;
                        ;   end;
i30 : bz  w0  x2+m5     ;
      wm  w0  x1+p35+2  ;   charcount.1st transfer.channel pg:=
      rs. w0     c34.   ;   chars * no of segments.curr buf;
      rl  w1  x2+m2     ;   firstaddr.1st transfer.channel pg:=
      rs. w1     c32.   ;   firstaddr.curr buf;
      se  w0     0      ;   if charcount.1st transfer.ch pg=0 then
      jl.        i20.   ;   begin c. see procedure description;
      rl. w0     c3.    ;
      lo. w0     i11.   ;     addrcode.1st transfer.channel pg:=
      rs. w0     c3.    ;     drivers process;
      al  w0     p20    ;     firstaddr.1st transfer.channel pg:=
      rs. w0     c32.   ;     rel of seek param;
      jl.        i20.   ;   end;
                        ;   goto central action;

; action 3, insert dummy transfer information (clean track).
n3  : dl. w1     c24.   ; action 3:
      ds. w1     c34.   ;   parameters.1st transfer.channel pg:=
                        ;   parameters.1st seek.channel pg;
                        ;   c. because of checking in start i-o;
      jl.        i20.   ;   goto central action;

; action 4, test if strobe-offset used (define disc).
n4  : bz  w3  x1+p15    ; action 4:
                        ;   retryinf:= retryinf.curr receiver;
      jl.        i35.   ;   goto test mode;

; action 5, test if strobe-offset used (read).
n5  : bz  w3  x2+m6     ; action 5: retryinf:= retryinf.curr buf;
                        ; test mode: c. ac3 = retryinf;
i35 : sh  w3     2.111  ;   if retryinf(0:20) = 0
      jl.        i20.   ;   then goto central action;
      rl. w0     i6.    ;
      rs. w0     c1.    ;   command.mode.channel pg:= setmode;
      ls  w3    -3      ;
      rl. w2     i3.    ;
      la  w2     6      ;   i:= modeindex.retryinf;
      ls  w3    -5      ;   i1:= offset index.retryinf;
      al  w3  x3-1      ;
      bz. w0  x3+q20.   ;
      ba. w0  x2+q21.   ;   setmode param.curr receiver:=
      rs  w0  x1+p21    ;   modetable(i-1)+ offsettable(i1);
      jl.        i20.   ;   goto central action;

; action 6, test if read after write (write).
n6  : bz  w3  x2+m1     ; action 6:
      so  w3     q43    ;   if -, read after write.mode.curr buf
      jl.        i20.   ;   then goto central action;
      rl  w0  x1+p13    ;
      ls  w0    -2      ;   transfer state.curr receiver:=
      rs  w0  x1+p13    ;   transfer state.curr receiver >> 2;
      rl. w0     i4.    ;
      rs. w0     c5.    ;   command.1st stop.channel pg:= noop;
      rl. w0     i7.    ;   command:= read with no transfer;
      sz  w3     q40    ;   if transput mode.curr buf = 1
      rl. w0     i7.    ;*  then command:= command + modif;
      rs. w0     c7.    ;   command.2nd transfer.channel pg:=
                        ;   command;
      dl. w0     c34.   ;   parameters.2nd transfer.channel pg:=
      ds. w0     c74.   ;   parameters.1st transfer.channel pg;
      se  w0     0      ;   if charcount.2nd transfer.ch pg=0 then
      jl.        j37.   ;
      rl. w0     c7.    ;   addrcode.2nd transfer.channel pg:=
      lo. w0     i11.   ;   drivers process;
      rs. w0     c7.    ;   c. see action 2;
i37 : bz  w0  x2+m6     ;
      al  w3     0      ;   c. test if write is to be skipped;
      sz  w0     2.111  ;   if readtries.retryinf.curr buf <> 0
      rs. w3     c34.   ;   then charcount.1st transfer.channel pg
      jl.        i20.   ;   := 0;
                        ;   goto central action;

; action 7, determine startaddress (sense,power restart).
n7  : zl  w0  x2+m1     ; action 7:
      ls  w0    -3      ;    get mess.mode
      ea  w0  x1+p14    ;
      al. w3     c4.    ;   startaddr:= 1st sense.channel pg;
      se  w0     0      ;   if initdisc.curr receiver <> 0 or mess.mode = 8
      al. w3     c3.    ;   then startaddr :=
      rs. w3     i1.    ;   1st transfer.channel pg; c. init;
      jl.        i20.   ;   goto central action;

; action 8, determine startaddr (read,write,clean,pos,define).
n8  : bz  w0  x1+p14    ; action 8:
      al. w3     c0.    ;
      se  w0     0      ;   if initdisc.curr receiver <> 0
      rs. w3     i1.    ;   then startaddr:= init.channel pg;
      jl.        i20.   ;   goto central action;

; action 9, perform start with buf = 0 (all except read,write)
n9  : al  w2     0      ; action 9: buf:= 0;
      jl.        i40.   ;   goto start;

; action 10, perform start with buf = curr buf:
n10 :                   ; action 10: c. buf = curr buf;

; call start i/o to start the transfer. w1,w2 = curr rec.,buf.
i40 : ld  w0    -100    ; start:
      ds  w0  x1+p16+4  ;   zeroize rembytes, curr status,
      rs  w0  x1+p16+6  ;     event status, technical status
      rs  w0  x1+p16+20 ;     in statusarea1.curr receiver
      ds  w0  x1+p18+4  ;     and statusarea2.curr receiver;
      rs  w0  x1+p18+6  ;
      rs  w0  x1+p18+20 ;
      hs  w0  x1+p14    ;   initdisc.curr receiver:= 0;
      al  w0     1<2+1  ;   + std exit + start channel pg;
      rl  w3  x1+a235   ;   device addr:= device addr.curr rec;
      rl. w1     i1.    ;
      jd         1<11+100;  start i/o(func,startad,buf,devicead);
      jl.       (i0.)   ;   return;

; pej 19.09.77    disc driver, setup channelprogram and start

; variables
i0  : 0                 ; saved link
i1  : 0                 ; start addr, in channel pg
i2  : 0                 ; action addr, index to actiontable
i3  : 2.11111           ; for masking out offsetindex.retryinf
i4  : 4095              ; channel pg command = noop
i5  : 15<8              ;                    = stop
i6  : 4<12+2<8+1        ;                    = setmode
i7  : 4095              ;*                   = read, no transfer
i8  : 1                 ; modifier for addr mark (read,write)
      q50               ;                   bytes per addr mark
i9  : q51               ; segment unit: +0: chars per addr mark
      q52               ;                   bytes per data segm
i10 : q53               ; segment unit: +0: chars per data segm
i11 : 4<12              ; addrcode = drivers process

; operation table.
; the table contains: +0: command for 1st transfer.channel pg
;                     +2: transfer state
;                     +4: action table base
; a row in the table is indexed by: (operation>1)<1*3
;   addrcode+command+modif, state, actionbase
i100: 0<12  +  6<8  +  0,l0:1<20,l1:i101-1   ; + 0: sense
      0<12  +  1<8  +  0  , 1<17 ,  i102-1   ; + 6: read
      0<12  +  3<8  +  0  , 1<15 ,  i103-1   ; +12: write
      4<12  +  3<8  +  3  , 1<18 ,  i104-1   ; +18: clean track
                   4095   , 1<19 ,  i105-1   ; +24: position
      4<12  +  1<8  +  1  , 1<22 ,  i106-1   ; +30: define disc
      0<12  +  6<8  +  0  , 1<21 ,  i107-1   ; +36: power restart
;              1 read
;                      0 data
;                      1 addr mark
;              3 write
;                      0 data
;                      1 addr mark
;                      3 clean
;              6 init
;     0 data area in senders process
;     4 data area in drivers process descr
\f

; pej 19.09.77    disc driver, channel program

; c h a n n e l   p r o g r a m

;                                 addrcode  command  params

; init after error
c0  :       6<8   ; init          irrel     init
      0           ;                                  irrel
      0           ;                                  irrel

; normal starting point
c2  : 4<12+ 2<8   ; 1st seek      device    seek
c22 : p20         ;                                  paramaddr
c24 : 6           ;                                  charcount
c1  : 4<12+ 2<8+1 ; mode          device    setmode
      p21         ;                                  paramaddr
      3           ;                                  charcount
c3  : 0           ; 1st transfer
c32 : 0           ;
c34 : 0           ;
c4  : 4<12+ 0<8   ; 1st sense     device    sense
      p16         ;                                  statusarea1
      33          ;                                  max charcount

; stop unless read after write
c5  :      15<8   ; 1st stop      irrel     stop
      0           ;                                  irrel
      40000       ;                                  timer, 0.1 ms

; checkread
c6  : 4<12+ 2<8   ; 2nd seek      device    seek
      p20         ;                                  paramaddr
      6           ;                                  charcount
c7  : 0           ; 2nd transfer
c72 : 0           ;
c74 : 0           ;
c8  : 4<12+ 0<8   ; 2nd sense     device    sense
      p18         ;                                  statusarea2
      33          ;                                  max charcount

; stop
c9  :      15<8   ; 2nd stop      irrel     stop
      0           ;                                  irrel
      40000       ;                                  timer, 0.1 ms

e.
\f


; pej 22.09.77    disc driver, process next message

; p r o c e s s   n e x t   m e s s a g e
; ---------------------------------------------------------------

; this routine is entered when the next message is to be proces-
; sed by the disc driver. the routine is entered either from link
; message routine (driver able to process a received message
; immediately) or when an answer to a processed message has been
; delivered and more messages are queued to the driver. curr buf
; contains addr of buffer to be processed.

; check if message is get statistics message
                        ; process next message:
j50 : al  w0     0      ;   c. w1 = curr receiver, w2 = curr buf;
      hs  w0  x1+p15    ;   retryinf.curr receiver:= 0;
      bz  w0  x2+m0     ;
      c.         q1     ;   if statistics wanted
      se  w0     q36    ;   and operation.curr buf = get stat then
      jl.        j52.   ;   begin
      jl. w3     j5.    ;     copy statistics(result,words);
      jl.        j90.   ;     if no room then goto deliv. blockl;
      jl.        j102.  ;     if -, ok then goto status/segms 0;
      jl.        j94.   ;     goto deliver words wanted;
      z.                ;   end;

; check if message is initialize message
j52 : se  w0     q31    ;   if operation.curr buf = init then
      jl.        j53.   ;   begin
      jl. w3     j6.    ;     initialize disc;
      jl.        j101.  ;     goto deliver size zero;
                        ;   end;


; check if message is set regretted
j53 : se  w0     q39    ;   if operation.curr buf = set regretted then
      jl.        j55.   ;   begin
      al  w0     3      ;     set regretted.curr receiver = 3
      rs  w0  x1+a56    ;     deliver result 1
      al  w0  0         ;
      rs  w0  g20       ; deliver status 0

      jl         g7     ;   end
\f

; pej 22.09.77    disc driver, start device

; s t a r t   d e v i c e
; ---------------------------------------------------------------

; this routine is executed to start the device and is entered
; from process next message routine or when an operation is to
; be repeated. the disc is started according to the contents of
; curr buffer.
;
; if the disc is not yet defined (state.curr receiver <> ready)
; then a special transfer is activated to check number of heads
; and displacement of sector zero on odd cylinders. curr buf is
; left in the head of the queue and will be processed when the
; disc has been defined. regretted.curr receiver will be odd
; during define disc so as to avoid a start (this might happen if
; curr buf is regretted and the queue turns empty).
;
; continuation takes place at waitnext in driverproc.

; set up channel program for contents of curr buf
j55 : rl  w1     b19    ; start:
      rl  w0  x1+p12    ;
      se  w0     2      ;   if state.curr receiver = ready then
      jl.        j57.   ;   begin
      c.         q1     ;     if statistics wanted
      am     (x1+p40)   ;
      al  w0     1      ;     then no of transfers.curr rec:=
      rs  w0  x1+p40    ;     no of transfers.curr rec + 1;
      z.                ;
      al  w1     0      ;     kind:= 0; c. use curr buf;
      jl. w3     j0.    ;     setup channel pg and start(kind);
      se  w0     3      ;     if result <> 3
      jl.        j101.  ;     then goto deliver size zero
      jl.        j99.   ;     else goto deliver unintilligible;
                        ;   end;

; setup channel program for define disc
j57 : se  w0     0      ;   if state.curr rec = after interv then
      jl.        j59.   ;   begin
      rs  w0  x1+p10    ;     define disc cyl.curr receiver:= 0;
      rs  w0  x1+p11    ;     define disc head.curr receiver:= 0;
      hs  w0  x1+p15    ;     retryinformation.curr receiver:= 0;
      al  w0     1      ;     state.curr receiver:= defining disc;
      rs  w0  x1+p12    ;     regretted.curr receiver:= 1;
      rs  w0  x1+a56    ;     disctype.curr receiver:= 1;
      rs  w0  x1+p5     ;     initdisc.curr receiver:= 1;
      hs  w0  x1+p14    ;   end;
j59 : al  w1     q39    ;
      jl. w3     j0.    ;   setup channel pg and start(kind);
\f

; pej 26.09.77    disc driver, interrupt received

; i n t e r r u p t   r e c e i v e d
; ---------------------------------------------------------------
;
; this routine is entered when driver proc receives an interrupt
; operation for a disc driver. the i/o result stored in the
; device description indicates the event leading to generation of
; the interrupt operation:
;
; i/o result 0: normal termination, interrupt from device.
;            1: bus reject, busy  , device not started.
;            2: bustimeout, discon, -      -   -
;            3: software timeout  , software generated.
;            4: abnormal terminat., interrupt from device.
;            5: wait pg. terminat., -         -    -
;            6: power restart     , software generated.

; form the compoundstatus from i/o result and all statuswords
; (curr status, event status) generated by the device.
c34 : rl  w3     b19    ; interrupt received:
      rl  w0  x3+a230   ;   if channel pg count.std status = 0
      sn  w0     0      ;   then
      am      p16+6-a233;   curr-event:= curr-event.statusarea1
      dl  w1  x3+a233   ;   else curr-event:=curr-event.stdstatus;
      lo  w0  x3+p16+4  ;   curr:= curr or curr.statusarea1;
      lo  w1  x3+p16+6  ;   event:= event or event.statusarea1;
      rl  w2  x3+p16+20 ;   tech:= techn status.statusarea1;
      lo  w0  x3+p18+4  ;   curr:= curr or curr.statusarea2;
      lo  w1  x3+p18+6  ;   event:= event or event.statusarea2;
      lo  w2  x3+p18+20 ;   tech:= tech or tech.statusarea2;
      ds  w1  x3+p31+2  ;   curr-event.curr rec:= curr-event;
      rs  w2  x3+p33    ;   technical status.curr rec:= tech;
      jl. w3     j8.    ;   compoundstatus(curr,event,compound);
      rs  w0  x1+p34    ;   compound status.curr rec:= compound;

; check if compound status is ok with respect to actual transfer.
      rl  w3  x1+p13    ;
      ls  w3    -1      ;   i:= transfer state.curr rec >> 1;
      ns. w3     3      ;   sh:= no of shifts to normalize i;
      ac  w3  ; -sh     ;
      ls  w3     2      ;   sh:= sh * 4;
      rl  w2     b18    ;   c. w1 = curr rec, w2 = curr buf;
      sz. w0 (x3+i20.)  ;   if compound and table(sh) <> 0
      jl.        j125.  ;   then goto error
      jl.    (x3+i21.)  ;   else goto table(sh+2);

; table to determine if transfer was successful. an entry corre-
; sponds to a transfer state and contains:
; +0: mask which anded to compound status must give zero.
; +2: addr where to continue.
;     mask        addr    transfer state
i20 :  -1 , i21 : j125  ; bit  0, idle (will always go to error)
      i23 ,       j85   ;      1, define disc
      i25 ,       j87   ;      2, power restart
      i23 ,       j75   ;      3, sense
      i23 ,       j75   ;      4, position
      i24 ,       j75   ;      5, clean track
      i23 ,       j77   ;      6, read data
      i23 ,       j77   ;      7, read addr mark
      i24 ,       j77   ;      8, write data
      i24 ,       j77   ;      9, write addr mark
      i24 ,       j77   ;     10, read after write data
      i24 ,       j77   ;     11, read after write addr mark

; masks, normal term (bit 19) not checked. must be 1.
i23 = 8.77617757        ; input ok, bits not checked: 8,9,10
                        ;  (write protect, high density, mode)
i24 = 8.77737757        ; output ok, bits not checked: 9
                        ;  (high density)
i25 = 8.37617757        ; power ok, bits not checked: 0,8,9,10
                        ;  (intervention, write protect, high
                        ;   density, mode)
\f

; pej 26.09.77    disc driver, successful transfer

; s u c c e s s f u l   t r a n s f e r
; ---------------------------------------------------------------

; these routines are entered when a transfer is regarded success-
; ful. w1 = curr receiver, w2 = curr buf.

; c o n t r o l   s u c c e s s f u l
j75 : rl  w0  x1+a56    ; control ok:
      se  w0     0      ;   if regretted.curr receiver
      jl.        j110.  ;   then goto examine queue;
      c.         q1     ;   if statistics wanted
      bz  w0  x2+m6     ;
      se  w0     0      ;   and retryinf.curr buf <> 0
      jl. w3     j17.   ;   then update on corrected error;
      z.                ;
      jl.        j101.  ;   goto deliver size zero;

; t r a n s p u t   s u c c e s s f u l
j77 : al  w0     0      ; transput ok:
      sn  w0 (x1+p16+2) ;   if rembytes.statusarea1.curr rec <> 0
      se  w0 (x1+p18+2) ;   or rembytes.statusarea2.curr rec <> 0
      jl.        j125.  ;   then goto error;
      al  w3     1      ;
      rl  w0  x1+p21    ;   if setmode param.curr receiver <> 0
      se  w0     0      ;   then initdisc.curr receiver:= 1;
      hs  w3  x1+p14    ;   c. force heads back to nominal pos;
      c.         q1     ;   if statistics wanted
      bz  w0  x2+m6     ;
      se  w0     0      ;   and retryinf.curr buf <> 0
      jl. w3     j16.   ;   then update on corrected error;
      z.                ;
      bz  w0  x2+m5     ;   segments:= no of segments.curr buf;
      jl. w3     j11.   ;   update buf(segments,bytes);

; check if more segments are to be transferred at transput
j80 : bz  w0  x2+m9     ;
      sn  w0     0      ;   if remaining segms.curr buf = 0
      jl.        j103.  ;   then goto deliver wanted;
      al  w0     0      ;   c. jumps always at direct disc msg;
      hs  w0  x2+m6     ;   retryinformation.curr buf:= 0;
      rl  w0  x2+m7     ;   first segment.curr buf:=
      rs  w0  x2+m4     ;   next segment.curr buf;
      rl  w1  x2+m10    ;   proc:= device.curr buf;
      jl. w3     j4.    ;   prepare consecutive segms(proc);
      jl.        j55.   ;   goto start;

; d e f i n e   d i s c   s u c c e s s f u l
j85 : rl  w0  x1+p16+2  ; define disc ok:
      se  w0     0      ;   if rembytes.statusarea1.curr rec <> 0
      jl.        j125.  ;   then goto error;
      rl  w0  x1+p34    ;   type:=
      ls  w0    -14     ;   hi dens.compound status.curr rec;
      la  w0     g3     ;   c. 0=dsm801, 1=dsm802;
      rs  w0  x1+p5     ;   disctype.curr receiver:= type;
      al  w0     1      ;   initdisc.curr receiver:= 1;
      hs  w0  x1+p14    ;   c. ensures nominal head position;
      wa  w0  x1+p11    ;   define disc head.curr receiver:=
      rs  w0  x1+p11    ;   define disc head.curr receiver + 1;
      al  w3     8.377  ;   c. test if last addr mark on cylind.;
      sz  w3 (x1+p22+4) ;   if nexthead.addrmark.curr rec <> 0
      jl.        j55.   ;   then goto start;
      wm  w0  x1+p6     ;   segments per cyl.curr receiver:=
      rs  w0  x1+p8     ;   define disc head.curr receiver
      rl  w0  x1+p22+6  ;   * segments per track.curr receiver;
      ls  w0    -16     ;   displacement.curr receiver:=
      rs  w0  x1+p9     ;   next sector.addrmark.curr receiver;
      al  w0     2      ;   c. sector 0 on odd cylinders;
      rs  w0  x1+p12    ;   state.curr receiver:= ready;
      jl.        j110.  ;   goto examine queue;

; p o w e r   r e s t a r t   s u c c e s s f u l
j87 : rl  w0  x1+p12    ; power restart ok:
      sn  w0     1      ;   if state.curr rec = defining disc
      al  w0     0      ;   then state.curr rec:= after interven;
      rs  w0  x1+p12    ;   c. resume define disc from beginning;
      jl.        j110.  ;   goto examine queue;
\f

; pej 26.09.77    disc driver, deliver answer

; d e l i v e r   a n s w e r   r o u t i n e
; ---------------------------------------------------------------

; these routines are entered to deliver the answer to a processed
; message. upon delivering the answer it is examined if more
; messages are queued to the driver. if so, next message is pro-
; cessed, and if not, idle state is entered and a wait program
; is started. p35+0 and p35+2 contains bytes/chars per segment.

; result 1, status blocklength, bytes 0.
j90 : dl. w1     i27.   ; deliver blocklength:
      al  w3     0      ;   result:= 1; status:= bit4;
      jl.        j106.  ;   segments:= 0; goto deliver;

; result 1, status discerror, bytes = what was transferred.
j92 : dl. w1     i28.   ; deliver discerror: result:= 1;
      rl  w2     b18    ;   status:= bit11;
      jl.        j97.   ;   goto deliver transferred;

; result 1, status 0, words contained in ac3
j94 : al  w0     2      ; deliver words wanted: c. w2=curr rec;
      al  w1     3      ;   bytes:= 2; chars:= 3;
      ds  w1  x2+p35+2  ;   c. w3 = words == segments;
      jl.        j104.  ;   goto deliver ok;

; result 4, status 0, bytes=what was transferred
j95 : al  w0     4      ; deliver spurious:
      al  w1     0      ;   result:= 4; status:= 0;
      rl  w2     b18    ;   w2:= curr buf;
      jl.        j97.   ;   goto deliver transferred;

; result, status corresp. to compound, bytes=what was transferred
j96 :                   ; deliver error:
      jl. w3     j10.   ;   set result and status(result,status);
j97 : bz  w3  x2+m8     ; deliver transferred: c. w2 = curr buf;
      bs  w3  x2+m9     ;   segments:= segments wanted.curr buf
      bz  w2  x2+m0     ;   - remaining segments.curr buf;
      so  w2     2.1    ;   if operation.curr buf = control
      al  w3     0      ;   then segments:= 0;
      jl.        j106.  ;   goto deliver;

; result 1, 2, 3, status 0, bytes 0.
j99 : am         3-2    ; deliver unintelligible:
j100: am         2-1    ; deliver rejected       :
j101: al  w0     1      ; deliver size zero      :
j102: al  w1     0      ; deliver status and segms zero:
      al  w3     0      ;   status:= 0; segments:= 0;
      jl.        j106.  ;   goto deliver;

; result 1, status 0, bytes = what was wanted.
j103:                   ; deliver wanted; c. w2 = curr buf;
      bz  w3  x2+m8     ;   segment:= segments wanted.curr buf;
j104: dl. w1     i29.   ; deliver ok: result:= 1; status:= 0;

; deliver the answer, w0=result, w1=status, w3=segments.
j106: rs  w1     g20    ; deliver:
      rl  w1     b19    ;   status.i/o answer:= status;
      rs  w3     g21    ;
      wm  w3  x1+p35    ;
      rx  w3     g21    ;   bytes.i/o answer:= segments * bytes;
      wm  w3  x1+p35+2  ;
      rs  w3     g22    ;   chars.i/o answer:= segments * chars;
      rl  w2  x1+a244   ;   file.i/o answer:= i/o result.curr rec;
      rl  w3  x1+p31    ;   block.i/o answer:=
      ds  w3     g24    ;   curr status.curr receiver;
      rl  w2  x1+p31+2  ;   curr buf(18:19):= event stat.curr rec;
      rl  w3  x1+p33    ;   curr buf(20:21):= techn stat.curr rec;
      am        (b18)   ;
      ds  w3     m8     ;
      rs  w0  x1+p35    ;   save result;
;  w0= result; b18 =buffer
      rl  w2  b18       ;  w2:=buffer
      rl  w1  x2+a141   ;  w1:= receiver.buf
      sh  w1  0         ; 
      ac  w1  x1        ;  w1:= absolute value of receiver
      sh  w1  6         ; 
      jl.     j107.     ; 
      rl  w3  x1+a10    ;  w3:= kind(rec);
      se  w3  4         ;  if area process then
      jl.     j107.     ;  begin
      rl  w3  g22       ; 
      sn  w0  1         ;  if bytes<>0 then
      sn  w3  0         ;  begin
      jl.     j107.     ; 
      bz  w3  x2+8      ;  if operation = write then
      se  w3  q33       ;    nooftiw:=nooftiw+1
      am      a412-a411 ;  else
      al  w3  x1+a411   ;    nooftir:=nooftir+1;
      rl  w2  x3        ; 
      al  w2  x2+1      ; 
      rs  w2  x3        ; 
j107: jl  w3     g19    ;   deliver result(result);

; clean the driver in case of abnormal result.
      rl  w0  x1+p35    ;
      sl  w0     4      ;   if result > 3
      jl. w3     j14.   ;   then clean(result);

; examine if more messages are queued.
j110: al  w0     0      ; examine queue: c. w1=curr receiver;
      rs  w0  x1+a56    ;   regretted.curr receiver:= 0;
      jl  w3     g64    ;   examine queue(queue empty);
      jl.        j112.  ;   if not queue empty
      jl.        j50.   ;   then goto process next message;

; queue is empty, start a wait program. continue at waitnext.
j112: rl  w0     g49    ; start wait: c. w1 = curr receiver;
      rs  w0  x1+p13    ;   transfer state.curr receiver:= idle;
      rl  w3  x1+a235   ;   dev:= device descr.curr rec;
      al  w0     3<2+1  ;   start control + std exit;
      ld  w2    -100    ;   buf:= 0; timeout:= eternal;
      jd      1<11+100  ;   start i/o(func,timeout,buf,dev);
\f


; pej 28.09.77    disc driver, error routine

; e r r o r   r o u t i n e
; ---------------------------------------------------------------

; this routine is entered when an interrupt not corresponding to
; a successful transfer has been received. the treatment of the
; error takes place by running through a number of actions, each
; action being executed as a function of the kind of error and
; the transfer state of the driver.
;
; if possible, the transfer is repeated. if the routine is entered
; due to power restart (or disc power down = possible power break
; in progress) a loop is entered to check if power comes up again,
; leaving a possible message being currently processed in the head
; of the queue.

; determine the kind of error
j125:                   ; error: c. w1 = curr receiver;
     jl  w2  (b31)        ; call errorlog
      jl. w3     j9.    ;   set errorkind(kind);
      wa  w0  x1+p13    ;   actionkey:=
      rs  w0  x1+p36    ;   errorkind + transfer state.curr rec;
      al  w0    -4      ;
      rs  w0  x1+p37    ;   actionindex:= -4;

; determine if next action is to be executed
j130: rl  w1     b19    ; central action: w1:= curr receiver;
j132: am     (x1+p37)   ; skip:
      al  w3     4      ;
      rs  w3  x1+p37    ;   action index:= actionindex + 4;
      rl  w0  x1+p36    ;
      la. w0  x3+i35.   ;   i:= table(actionindex) and actionkey;
      bz  w2     1      ; 
      sz  w0    (g51)   ;   if i(0:11) = 0
      sn  w2     0      ;   or i(12:23) = 0
      jl.        j132.  ;   then goto skip;
      rl  w2     b18    ;   goto table(actionindex + 2);
      jl.    (x3+i36.)  ;   c. with w1 = curr rec, w2 = curr buf;

b. n25, o16 w.               ; block containing error actions

; table guiding the execution of actions. each entry contains:
; +0: transfer states < 12 + errorkinds
;     the action is executed if the actionkey (see above) anded
;     to this word gives nonzero in both bytes.
; +2: action address.
; ---------------------------------------------------------------
;       ----transfer states----        --error kinds--       actions
;                   read
;                       write          d a i p p t w d a o
;                           read aft.    f n o o i r a d t
;       i d p s p c d a d a d a        o t t w w m   t d h
;       d e o e o l a d a d a d        v   e e e e p a r e
;       l f w n s e t d t d t d        e d r r r o r     r
;       e i e s   a a r a r a r        r   v     u o e e
;         n r e   n                    r o   r d t t r r
; ---------------------------------------------------------------
;                              action 1                      vacant
i35: 2. 1 1 1 0 1 1 1 1 1 1 1 1 <12+2.     1 1 1 1 0 0 1 1 , i36: n2
     2.             1 1 1 1 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n3
     2.                     1 1 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n4
     2.       1 1 1 0 0 0 0 0 0 <12+2.           1 0 1 1 1 ,      n5
     2.       1 1 1 1 1 1 1 1 1 <12+2.           1 0 1 1 1 ,      n6
     2.             1 0 0 0 0 0 <12+2.               1 0 0 ,      n7
c. q1
     2.             1 1 1 1 1 1 <12+2.           1 0 1 1 1 ,      o7
z.
     2.             1 1 0 0 0 0 <12+2.               1 1 0 ,      n8
     2.             1 1 0 0 0 0 <12+2.           1 0 0 0 0 ,      o8
     2.       1 1 1 1 1 1 1 0 0 <12+2.           1 0 1 1 1 ,      n9
     2.                     1 1 <12+2.           1 0 1 1 1 ,      n10
     2. 1 1 0 1 1 1 1 1 1 1 1 1 <12+2.         1 0 0 0 0 0 ,      n11
     2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2.       1 0 0 0 0 0 0 ,      n12
     2.     1 0 0 0 0 0 0 0 0 0 <12+2.           1 0 0 0 0 ,      n13
     2.     1 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n14
     2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2.     1 0 0 0 0 0 0 0 ,      n17
     2.           1 0 0 1 1 1 1 <12+2.             1 0 0 0 ,      n16
     2.       1 1 0 1 1 0 0 0 0 <12+2.             1 0 0 0 ,      o16
     2. 1 0 0 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n17
     2.   1 0 0 0 0 0 0 0 0 0 0 <12+2.                 1 0 ,      n18
     2.   1 0 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n19
     2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2.   1 0 0 0 0 0 0 0 0 ,      n20
     2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 0 0 0 0 ,      n21
     2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 1 1 1 1 1 1 1 1 1 ,      n22

\f

; pej 28.09.77    disc driver, error routine

; action 2: set initdisc
; tr.state: all, except sense
; err.kind: all, except overrrun, write prot, and data err
n2  : al  w0     1     ;   initdisc.curr receiver:= 1;
      hs  w0  x1+p14   ;
      jl.        j130. ;   goto central action;

; action 3: update buf at error at read or simple write.
; tr.state: read data, read addr m, write data, write addr m
; err.kind: any
n3  : al  w2  x1+p16    ;   area:= statusarea1.curr receiver;
      al. w3     j130.  ;   update buf on err(area,bytes,chars);
      jl.        j12.   ;   goto central action;

; action 4: update buf at read after write error.
; tr.state: read after write data, read after write addr m.
; err.kind: any
n4  : al  w0     0      ;   c. test if first transfer (write) ok;
      rs  w0  x1+p38    ;   write ok:= 0; c. see action 10;
      se  w0 (x1+p16)   ;   if chan pg count.status1.curr rec = 0
      se  w0 (x1+p16+2) ;   or rembytes.statusarea1.curr rec <> 0
      jl.        j130.  ;   then goto central action; c. not ok;
      dl  w1  x1+p16+6  ;
      jl. w3     j8.    ;   compoundstatus(curr,event,compound);
      sz. w0    (i40.)  ;   if compound and output ok <> 0
      jl.        j130.  ;   then goto central action; c. not ok;
      rs  w1  x1+p38    ;   write ok:= <> 0; c. see action 10;
      al  w2  x1+p18    ;   area:= statusarea2.curr receiver;
      al. w3     j130.  ;   update buf on err(area,bytes,chars);
      jl.        j12.   ;   goto central action;

; action 5: repeatable error, test if control message regretted.
; tr.state: sense, position, clean track
; err.kind: timeout, data error, addr mark error, other error
n5  : al  w0     0      ;
      sn  w0 (x1+a56)   ;   if regretted.curr receiver = 0
      jl.        j130.  ;   then goto central action
      jl.        j110.  ;   else goto examine queue;

; action 6: repeatable error, test if transfer may be repeated.
; tr.state: any, except idle, define disc, power restart
; err.kind: timeout, data error, addr mark error, other error
n6  :                   ;
      c.         q1     ;   if statistics wanted then
      am     (x1+p41)   ;   begin
      al  w3     1      ;     count:= not successful.curr rec + 1;
      bz  w0  x2+m6     ;
      sn  w0     0      ;     if retryinf.curr buf = 0 then
      rs  w3  x1+p41    ;     not successful.curr rec:= count;
      z.                ;   end;
      bz  w0  x2+m1     ;
      sz  w0     q41    ;   if -, error recovery.mode.curr buf
      jl.        j96.   ;   then goto deliver error
      jl.        j130.  ;   else goto central action;

; action 7: data error at read, try to repair by ecc.
; tr.state: read data
; err.kind: data error
n7  : jl. w3     j15.   ;   correct data;
      jl.        j130.  ;   if not corrected then goto cent act.;
      al  w0     1      ;   segments:= 1;
      rl  w1     b19    ;   c. one segment, the last, corrected;
      rl  w2     b18    ;
      jl. w3     j11.   ;   update buf(segments,bytes);
      c.         q1     ;   if statistics wanted then
      am     (x1+p42)   ;   begin
      al  w3     1      ;     count:= ecc corrected.curr rec + 1;
      bz  w0  x2+m6     ;
      sn  w0     0      ;     if retryinf.curr buf = 0
      rs  w3  x1+p42    ;     then ecc corrected.curr rec:= count
      se  w0     0      ;
      jl. w3     j16.   ;     else update on corrected error;
      z.                ;   end;
      al  w0     0      ;   if setmode param.curr rec = 0
      sn  w0 (x1+p21)   ;   then initdisc.curr rec:= 0;
      hs  w0  x1+p14    ;   c. init not necessary;
      hs  w0  x2+m6     ;   retryinf.curr buf:= 0;
      bz  w0  x2+m5     ;   c. check if entire transfer now ok;
      sn  w0     0      ;   if no of segments.curr buf = 0
      jl.        j80.   ;   then goto check if more
      jl.        j55.   ;   else goto start;

; action 7a, update table of error segments
; tr.state : read data, read addr m, write data, write addr m,
;            read after write data, read after write addr m
; err.kind : timeout, data error, addr mark error, other error
o7  : c.         q1     ;   if statistics wanted then
      bz  w0  x2+m6     ;   begin
      se  w0     0      ;     if retryinf.curr buf <> 0
      jl.        j130.  ;     then goto central action;
      rl  w3  x2+m4     ;     c. already registrated;
      am     (x2+m10)   ;     segment:= first segment.curr buf
      wa  w3     p3     ;     + first segment.device.curr buf;
      al  w2  x1+p46    ;     entry:= 1st error segm.curr rec;
j141: sl  w2  x1+p46+q2*6;    while entry <> top entry do
      jl.        j130.  ;     begin
      sh  w0 (x2+0)     ;       if segment no.entry < 0
      sn  w3 (x2+0)     ;       or segment no.entry = segment
      jl.        j143.  ;       then goto found; increase entry;
      al  w2  x2+6      ;     end;
      jl.        j141.  ;     goto central action; c. table full;
j143: rs   w3  x2+0     ; found:
      am         (b18)  ;     segment no.entry:= segment;
      ba  w2     m0     ;     i:= operation.curr buf;
      bz  w1  x2+0      ;
      al  w1  x1+1      ;     entry(i):= entry(i) + 1;
      hs  w1  x2+0      ;
      jl.        j130.  ;   end;
      z.                ;   goto central action;

; action 8, data error or addr m error at read, use strobe-offset
; tr.state: read data, read addr mark
; err.kind: data error, addr mark error
n8  : al  w1  x2+m6     ;   retryinf:= retryinf.curr buf;
      jl. w3     j13.   ;   update retryinformation(retryinf);
      jl.        j96.   ;   if no more tries goto deliver error;
      jl.        j147.  ;
      jl.        j145.  ;   if next offset magnitude used then
      jl.        j147.  ;   begin c. may buf be requeued;
j145: rl  w2     b18    ;
      bz  w0  x2+m1     ;
      sz  w0     q42    ;     if requeue.curr buf = no requeue
      jl.        j92.   ;     then goto deliver discerror;
      jl  w3     d5     ;     c. remove and link the buf to q end;
      am        (b19)   ;     remove(curr buf);
      al  w1     a54    ;
      jl  w3     d6     ;     link(mess queue.curr rec,curr buf);
      rl  w1     b19    ;     goto examine queue;
      jl.        j110.  ;   end;
j147: al  w0     2.10   ;   c. initdisc may be skipped if data
      rl  w1     b19    ;      error as the correct segment was
      la  w0  x1+p36    ;      read;
      sn  w0     0      ;   if actionkey and -, addr mark error
      hs  w0  x1+p14    ;   then initdisc.curr rec:= 0;
      jl.        j55.   ;   goto start;
; action 8a: timeout at read, simulate address mark error if
;            timeout is possibly caused by use of strobe -
;            offset (synchronization chars out of reach).
; tr.state : read data, read addr m
 
; err.kind : timeout
o8:   bz  w3  x2+m6     ;
      sh  w3  2.111     ; if retryinf.curr buf <> strobe.offset
      jl.     j130.     ; used then goto central action;
      la. w3  i45.      ; c. force next offset magnitude;
      wa. w3  i44.      ; retryinf.curr buf:= last modeindex < 8
      hs  w3  x2+m6     ; +offset.retryinf.curr buf + maxtries;
      rl  w3  x1+p36    ; c. simulate addr mark error;
      al  w3  x3-2.10000; action key.cur rec:=
      al  w3  x3+2.10   ; action key.curr rec
      rs  w3  x1+p36    ; -timeout + addr m error;
      rl. w3  i43.      ; compound status.curr rec:=
      rs  w3  x1+p34    ; data err + hard err + abnorm term;
      jl.     n8.       ; goto action 8;

; action 9: error at control, read, simple write. repeat transfer
; tr.state: sense, position, clean track,
;           read data, read addr m, write data, write addr m
; err.kind: timeout, data error, addr mark error, other error
n9  : al  w1  x2+m6     ;   retryinf:= retryinf.curr buf;
      jl. w3     j13.   ;   update retryinformation(retryinf);
      jl.        j98.   ;
      jl.        j98.   ;
      jl.        j98.   ;   if tries <= 3 then goto start
      jl.        j55.   ;   else goto deliver error;
j98:  rl  w1     b19    ;
      al  w0     0      ;   if more than 3 timeouts then
      rs  w0  x1+p12    ;   then execute initdisc before next operation
      jl.        j96.   ;   (possible kitshift in progress)

; action 10: error at read after write, repeat transfer.
; tr.state : read after write data, read after write addr mark
; err.kind : timeout, data error, addr mark error, other error
n10 : rl  w0  x1+p38    ;   c. see action 4 re. write ok;
      bz  w3  x2+m6     ;   r:= retryinformation.curr buf; c. w3;
      sn  w0     0      ;   if write ok then
      jl.        j150.  ;   begin c. repeat 2nd transfer (read);
      al  w3  x3+1      ;     readtries.r:= readtries.r + 1;
      so  w3     2.100  ;     if readtries.r <= 3 then goto rep;
      jl.        j151.  ;   end;
j150: la. w3     i41.   ;   c. repeat 1st transfer (write);
      al  w3  x3+2.1000 ;   readtries.r:= 0; incr writetries.r;
      sz  w3     2.100<3;   if writetries.r > 3
      jl.        j96.   ;   then goto deliver error;
j151: hs  w3  x2+m6     ; rep: retryinformation.curr buf:= r;
      jl.        j55.   ;   goto start;

; action 11: disc power down, enter power restart loop.
; tr.state : any, except power restart
; err.kind : power down
n11 : am         q14-q13; power down:   n:= no of times to sense disc;

; action 12: power restart, enter power restart loop.
; tr.state : any
; err.kind : power restart
n12 : al  w3     q13    ;   n:= no of times to sense disc;
      al  w0     0      ;
      sn  w0 (x1+p12)   ;   if state.curr rec = after intervent.
      jl.        n15.   ;   then goto intervention;
      al  w0     1      ;   regretted.curr receiver:= 1;
      rs  w0  x1+a56    ;   c. to prevent start if buf arrives;
      jl.        j154.  ;   goto power sense;

; action 13: sense disc in power restart loop.
; tr.state : power restart
; err.kind : timeout
n13 : bz  w3  x1+p15    ;   n:= retryinformation.curr receiver;
      al  w3  x3-1      ;   n:= n - 1;
      sh  w3    -1      ;   if n < 0 then goto intervention;
      jl.        n15.   ; power sense: c. w3 = n;
j154: hs  w3  x1+p15    ;   retryinformation.curr receiver:= n;
      al  w1     q39+2  ;   kind:= power restart;
      jl. w3     j0.    ;   setup channelprogram and start(kind);
                        ;   c. cont. at waitnext in driverproc;

; action 14: delay before next sense in power restart loop.
; tr.state : power restart
; err.kind : any
n14 : rl  w3  x1+a235   ;   dev:= device descr.curr rec;
      al  w0     2<2+1  ;   function:= start wait, std exit;
      rl. w1     i42.   ;   timer:= time between sense in loop;
      al  w2     0      ;   buf:= 0;
      jd      1<11+100  ;   start i/o(function,timer,buf,dev);
                        ;   c. cont. at waitnext in driverproc;

; action 15: intervention.
; tr.state : any
; err.kind : intervention
n15 : al  w0     5      ; intervention: result:= 5; c. unknown;
      jl. w3     j14.   ;   clean(result);
      jl        (b20)   ;   goto waitnext; c. in driver proc;

; action 16: write protect at output.
; tr.state : clean track, all write states
; err.kind : write protect
n16 : jl.        j100.  ;   goto deliver rejected;

; action 16a: write protect at control, read. repeat transfer.
; tr.state  : sense, position, read data, read a m
; err.kind  : write protect
o16 : al  w1  x2+m6     ;   retryinf:= retryinf.curr buf;
      jl. w3     j13.   ;   update retryinformation(retryinf);
      jl.        j95.   ;
      jl.        j95.   ;
      jl.        j95.   ;   if tries <= 3 then goto start
      jl.        j55.   ;   else goto deliver spurious;

; action 17: wait program terminated not because of intervention.
; tr.state : idle
; err.kind : any
n17:  jl.     n11.      ; goto power down;

; action 18: addr mark error at define disc, use stobe-offset.
; tr.state : define disc
; err.kind : addr mark error
n18 : al  w1  x1+p15    ;   retryinf:= retryinf.curr receiver;
      jl. w3     j13.   ;   update retryinformation(retryinf);
      jl.        j160.  ;   if no more tries possible then
      jl.        j55.   ;
      jl.        j55.   ;
      jl.        j55.   ;   begin c. try next even cylinder
j160: rl  w1     b19    ;
      am     (x1+p10)   ;
      al  w0     2      ;     define disc cyl.curr rec:=
      rs  w0  x1+p10    ;     define disc cyl.curr rec + 2;
      al  w0     0      ;     define disc head.curr rec:= 0;
      rs  w0  x1+p11    ;     retryinformation.curr rec:= 0;
      hs  w0  x1+p15    ;   end;
      jl.        j55.   ;   goto start;

; action 19: error at define disc. repeat transfer.
; tr.state : define disc
; err.kind : any
n19 : al  w1  x1+p15    ;   retryinf:= retryinf.curr receiver;
      jl. w3     j13.   ;
      jl.        j162.  ;
      jl.        j162.  ;
      jl.        j162.  ;
      jl.        j55.   ;   if tries <= 3 then goto start;
j162: al  w0     4      ;   result:= 4; c. malfunction;
      jl. w3     j14.   ;   clean(result);
      al  w0     0      ;
      rs  w0  x1+p12    ;   state.curr rec:= after intervention;
      jl        (b20)   ;   goto waitnext; c. in driverproc;
  
; action 20: repeat transfer in data overrun loop
; tr.state : any
; err.kind : after data overrun
n20 : al  w0     0      ;   
      rs  w0  x1+a56    ;   regretted.curr receiver:= 0;
      bz  w3  x1+p15    ;   n:= retryinf.curr receiver;
      al  w3  x3+1      ;   n:= n+1;
      sl  w3     q15    ;   if n > max no of retries
      jl.        j96.   ;      then goto deliver error
      hs  w3  x1+p15    ;      else begin
      jl.        j55.   ;             retryinf.curr receiver:= n;
                        ;             goto start;
                        ;           end;
  
; action 21: start wait in data overrun loop
; tr.state : any
; err.kind : data overrun
n21 : bz  w0  x2+m1     ;
      sz  w0     q41    ;   if -,error recovery.mode.curr buf
      jl.        j96.   ;      then goto deliver error;
      al  w0     1      ;   regretted.curr receiver:= 1;
      rs  w0  x1+a56    ;   c. to prevent start if buf arrives
      rl  w3  x1+a235   ;   dev:= device descr.curr receiver;
      al  w1  x3        ;   timer:= (dev >> 5) << 9;
      ls  w1    -5      ;   c. (controller io no)*512;
      ls  w1     9      ;   c. to ensure diff. waiting periods for diff. devices
      al  w0     2<2+1  ;   function:= start wait, std exit;
      al  w2     0      ;   buf:= 0;
      jd      1<11+100  ;   start io(function,timer,buf,dev);

; action 22: final action, acts as a stopper.
; tr.state : any
; err.kind : any
n22 : al  w0     4      ;   result:= 4; c. malfunction;
      jl. w3     j14.   ;   clean(result);
      jl.        j112.  ;   goto start wait;

e.                      ; end of block containing error actions
\f


; pej 04.10.77    disc driver, variables

; m o d e   t a b l e
; each entry contains strobe and offset information corre-
; sponding to bit 16-19 in a setmode parameter. modeindex in
; retryinformation - 1 is an index to the table.
q23  = 3                ; first mode index in next round
q24 = 8                 ; last modeindex
h.                      ;     strobe  offset
q20 : 2.0100<4          ; +0: late
      2.1000<4          ; +1: early
      2.0001<4          ; +2:         negative
      2.0010<4          ; +3:         positive
      2.0101<4          ; +4: late    negative
      2.0110<4          ; +5: late    positive
      2.1001<4          ; +6: early   negative
      2.1010<4          ; +7: early   positive
      -1                ; +8: top of table

; o f f s e t   t a b l e
; each entry contains offset magnitude corresponding to bit 20-23
; in a setmode parameter. offset index in retryinformation is
; an index to the table.
q21 : 8,15,1,3,6,10,13,2,4,5,7,9,11,12,14 ; +0 - +14
      -1                                  ; +15: top entry
w.

; variables
      1                 ;                    -2: result (1)
i27 : 8.02000000        ; blocklength error: +0: status (bit 4)
      1                 ;            -2: result (1)
i28 : 8.00010000        ; discerror: +0: status (bit 11)
      1                 ;     -2: result (1)
i29 : 0                 ; ok: +0: status(0)
i40 : i24               ; mask for zeroes in compound at output
i41 : 2.11111000        ; mask for zeroizing readtries.retryinf
i42 : q10               ; time between sense in power rest. loop
i43:  1<22+1<19+1<8     ; compound status: data or hard err,abnorm term
i44:  q24<8+3           ; last modeindex<8+maxtries(retry inf)
i45:  2.000011111000    ; mask for zeroize modeindex or tries (retryinf)

\f



; pej 26.09.77    disc driver, compound status

; procedure compoundstatus(curr status,event status,compound)
; ---------------------------------------------------------------
;
; the procedure performs:
; - creates a compound status word from curr status and event
;   status and i/o result from device descr, so that:
;
;   bit  0   intervention            event status bit  0
;        1   data error              -     -      -    1
;        2   (unused, = 0)
;        3   data overrun            -     -      -    3
;        4   hard error              -     -      -    4
;        5   position error          -     -      -    5
;        6   power low               curr  -      -    0
;        7   local                   -     -      -    1
;        8   write protect           -     -      -    8
;        9   high density            -     -      -    9
;       10   mode                    -     -      -   10
;       11   seek error              -     -      -    5
;       12   (unused, = 0)
;       13   power restart           i/o result        6
;       14   wait pg. terminated     -   -             5
;       15   abnormal termination    -   -             4
;       16    software timeout       -   -             3
;       17    bustimeout, disconn.   -   -             2
;       18   bus reject, busy        -   -             1
;       19   normal termination      -   -             0
;       20   bus com, error          event status bit 20
;       21   interrupt error         -     -      -   21
;       22   bustimeout              -     -      -   22
;       23   bus parity error        -     -      -   23
;
; registers: call              exit
; wo         curr status       compound status
; w1         event status      curr receiver
; w2                           destroyed
; w3         link              unchanged
;
; entry    : j8
;
; return   : link+0
b. i1 w.
j8  :                   ; compound status:
      rl  w2     0      ;   i:= curr status >> 6;
      ls  w2    -6      ;   c. bit(6:7):= bit(0:1), bit11:= bit5;
      lo  w2     0      ;   i:= i or curr status;
      la. w2     i0.    ;   i:= i and bit 6,7,8,9,10,11;
      la. w1     i1.    ;   mask out unused event status bits;
      lo  w1     4      ;   compound:= event status or i; c. w1;
      al  w0     2.10000;   i:= bit 19;
      am        (b19)   ;
      rl  w2     a244   ;   sh:= i-o result.curr receiver;
      ls  w0  x2+0      ;   i:= i shift sh; c. w0;
      lo  w0     2      ;   compound:= compound or i; c. w0;
      rl  w1     b19    ;
      jl      x3+0      ;

; variables
i0  : 8.00770000        ; bit 6,7,8,9,10,11
i1  : 8.67000017        ; bit 0,1,3,4,5,20,21,22,23
e.
\f

; pej 27.09.77    disc driver, set errorkind

; procedure set errorkind(errorkind)
; --------------------------------------------------------------
; errorkind: bit 14: data overrun
;                15: after data overrun
;                16: intervention
;                17: power restart
;                18: power down (disc power)
;                19: time out
;                20: write protect
;                21: data error
;                22: addr mark error
;                23: other error
;
; the procedure performs:
; - updates tables of compound status and technical statusbits
;   if statistics wanted.
; - sets the errorkind as a function of bits in compound status
;   and bits in statuswords stored by controller.
;
; registers: call              exit
; w0                           errorkind
; w1         curr receiver     unchanged
; w2                           compound status
; w3         link              destroyed
;
; entry    : j9
;
; return   : link+0

b. i30 w.
j9  : rs. w3     i10.   ; set errorkind: save link;
      c.         q1     ;   if statistics wanted then
      rl  w0  x1+p34    ;   begin
      rl  w2  x1+p33    ;     i:= 0;
      al  w3  x1+p47    ;     repeat
i26 : sl  w0     0      ;       if compound(i).curr rec = 1
      jl.        i27.   ;
      al  w1     1      ;       then
      ba  w1  x3+0      ;       compound table(i).curr rec:=
      hs  w1  x3+0      ;       compound table(i).curr rec + 1;
i27 : sl  w2     0      ;       if technical(i).curr rec = 1
      jl.        i28.   ;
      al  w1     1      ;       then
      ba  w1  x3+p48-p47;       technical table(i).curr rec:=
      hs  w1  x3+p48-p47;       technical table(i).curr rec + 1;
i28 : al  w3  x3+1      ;
      ls  w0     1      ;
      ls  w2     1      ;       i:= i + 1
      sn  w0     0      ;     until compound(i+1:23) = 0 and
      se  w2     0      ;           technical(i+1:23) = 0;
      jl.        i26.   ;
      rl  w1     b19    ;
      z.                ;   end;
      rl  w2  x1+p34    ;   ac2:= compound status.curr rec;
      so. w2    (i6.)   ;   if data overrun then
      jl.        i29.   ;   begin
      sz  w2     8.200  ;     if timeout
      jl.        i15.   ;        then goto after data overrun
      jl.        i14.   ;        else goto data overrun;
i29 :                   ;   end;
      rl  w3  x1+p16+6  ;   event:= event.statusarea 1.curr rec;
      sz. w2    (i0.)   ;   if compound and mask1 = 0
      jl.        i24.   ;
      so. w3    (i1.)   ;   and dataerr.event and harderr.event
      jl.        i24.   ;   then goto data error;
      jl.        i21.   ;
i24 : rl  w0  x1+a233   ;   event:= event.std status.curr rec;
      sz. w2    (i2.)   ;   if compound and mask2 = 0
      jl.        i25.   ;
      rl  w3  x1+a230   ;
      se  w3     0      ;   and chan pg count.std status.curr rec
      bz  w3  x3-6+1    ;       <> 0
      ls  w3    -8      ;   and latest command executed = read
      sn  w3     1      ;
      so. w0    (i3.)   ;   and harderr.event and pos err.event
      jl.        i25.   ;
      jl.        i22.   ;   then goto addr mark error;
i25 : sz  w2     8.2000 ;   if power restart.compound
      jl.        i17.   ;   then goto power restart;
      sz. w2    (i4.)   ;   if powlow.compound or discon.compound
      jl.        i18.   ;   then goto power low;
      sz  w2     8.200  ;   if timeout.compound
      jl.        i19.   ;   then goto timeout;
      sz. w2    (i5.)   ;   if interv.compound or local.compound
      jl.        i13.   ;   then goto check power up;
      sz. w2    (i7.)   ;   if write protect.compound
      jl.        i20.   ;   then goto write protect
      jl.        i23.   ;   else goto other error;
i13:                    ; check power up:
      rl  w0     b75    ;   if power up not yet serviced
      se  w0     0      ;   by clockdriver
      jl.        i18.   ;   then goto power down
      jl.        i16.   ;   else goto intervention;
i14 : am         512-256; data overrun   : set kind bit 14
i15 : am         256-128; aft. data ov.  :              15
i16 : am         128-64 ; intervention   :              16
i17 : am          64-32 ; power restart  :              17
i18 : am          32-16 ; power down     :              18
i19 : am          16-8  ; time out       :              19
i20 : am           8-4  ; write protect  :              20
i21 : am           4-2  ; data error     :              21
i22 : am           2-1  ; addr mark error:              22
i23 : al  w0       1    ; other error    :              23;
      jl.       (i10.)  ;   return;

; variables
i0  : 8.45613757        ; mask1, data error, mask for zeroes
i1  : 8.22000000        ; bit 1,4
i2  : 8.44613377        ; mask2, addr mark err, mask for zeroes
i3  : 8.03000000        ; bit 4,5
i4  : 8.00400100        ; bit 6,17
i5  : 8.40200000        ; bit 0, 7
i6  : 8.04000000        ; bit 3, data overrun
i7  : 8.00100000        ; bit 8
i10 : 0                 ; saved link
e.
\f


; pej 27.09.77    disc driver, set result and status

; procedure set result and status(result,status).
; --------------------------------------------------------------
; result: 4 if bit 16 in compound status (software timeout)
;           -  -   18 -  -        -      (bus reject, busy)
;           -  -   20 -  -        -      (communication error)
;           -  -   21 -  -        -      (interrupt error)
;           -  -   22 -  -        -      (bustimeout)
;           -  -   23 -  -        -      (bus parity error)
;           if no bits are set in status.
;         1 if bits are set in status.
; status: bit 1 (parity)      if bit1,4 in compound (data,hard)
;         bit 2 (sync.err)    -  -    5 -  -        (pos.error)
;         bit 3 (data overr.) -  -    3 -  -        (data overr.)
;         bit 5 (end med.)    -  -   11 -  -        (seek error)
;
; the procedure performs:
; - calculates result and status from compound status.
;
; registers: call              exit
; w0                           result
; w1                           status
; w2                           curr buf
; w3         link              unchanged
;
; entry    : j10
;
; return   : link+0
b. i4 w.
j10 : am        (b19)   ; set result and status:
      rl  w2     p34    ;
      sz. w2    (i0.)   ;   if compound and result 4 mask
      am         4-1    ;   then result:= 4
      al  w0     1      ;   else result:= 1;
      al  w1     0      ;   status:= 0;
      sz. w2    (i1.)   ;   if compound and seek error mask
      al  w1  x1+1<6    ;   then status:= status + end medium;
      sz. w2    (i2.)   ;   if compound and data/hard error mask
      al  w1  x1+1<10   ;   then status:= status + parity;
      sz. w2    (i3.)   ;   if compound and data overrun mask
      al  w1  x1+1<8    ;   then status:= status + data overrun;
      sz. w2    (i4.)   ;   if compound and position error mask
      al  w1  x1+1<9    ;   then status:= status + sync.error;
      sn  w1     0      ;   if status = 0
      al  w0     4      ;   then result:= 4;
      ls  w1     12     ;
      rl  w2     b18    ;   w2:= curr buf;
      jl      x3+0      ;   return;

; variables
i0  : 8.00000257        ; result 4 mask, bit 16,18,20,21,22,23

i1  : 8.00010000        ; seek error mask, bit 11
i2  : 8.22000000        ; data/hard err mask, bit 1,4
i3  : 8.04000000        ; data overrun mask, bit 3
i4  : 8.01000000        ; pos.error mask, bit 5
e.
\f


; pej 26.09.77    disc driver, update buf

; procedure update buf(segments,bytes)
; ---------------------------------------------------------------
; segments: no of segments transferred.
; bytes   : no of bytes transferred per segment. must at calltime
;           be stored in p35.curr receiver.
;
; the procedure performs:
; - updates curr buf by segments:
;   first segment and firstaddr are incremented.
;   no of segments and remaining segments are decremented.
; - updates table of error segments (successful transfer) if sta-
;   tistics wanted and a segment in the table lies in the
;   interval given by first segment.curr buf and segments.
;
; registers: call              exit
; w0         segments          destroyed
; w1         curr receiver     unchanged
; w2         curr buf          unchanged
; w3         link              destroyed
;
; entry    : j11
;
; return   : link+0
b. i4 w.
j11 : rs. w3     i0.    ; update buf: save link;
      rl  w3  x2+m4     ;
      wa  w3     0      ;   first segment.curr buf:=
      rs  w3  x2+m4     ;   first segment.curr buf + segments;
      c.         q1     ;   if statistics wanted then
      rs. w0     i2.    ;   begin
      am     (x2+m10)   ;
      wa  w3     p3     ;     top:= first segment.curr buf
      rs. w3     i1.    ;     + first segment.device.curr buf;
      ws  w3     0      ;     first:= top - segments;
      al  w2  x1+p46-6  ;     entry:= 1st error segment.curr rec;
i3  : al  w2  x2+6      ;     while segment no.entry >= 0 and
      rl  w0  x2+0      ;           entry <> top entry do
      sl  w0     0      ;     begin
      sl  w2  x1+p46+q2*6;      if segmentno.entry >= first
      jl.        i4.    ;       and segmentno.entry < top
      sl  w0    (6)     ;       then goto found;
      sl. w0    (i1.)   ;       entry:= entry + 1;
      jl.        i3.    ;     end; goto not found;
      am        (b18)   ; found:
      ba  w2     m0     ;     i:= operation.curr buf;
      bz  w3  x2-1      ;
      al  w3  x3+1      ;     entry(i-1):= entry(i-1) + 1;
      hs  w3  x2-1      ;
i4  : rl  w2     b18    ; not found:
      rl. w0     i2.    ;
      z.                ;   end;
      bz  w3  x2+m5     ;
      ws  w3     0      ;   no of segments.curr buf:=
      hs  w3  x2+m5     ;   no of segments.curr buf - segments;
      bz  w3  x2+m9     ;
      ws  w3     0      ;   remaining segments.curr buf:=
      hs  w3  x2+m9     ;   rem segments.curr buf - segments;
      wm  w0  x1+p35    ;   b:= segments * bytes;
      wa  w0  x2+m2     ;   first addr.curr buf:=
      rs  w0  x2+m2     ;   first addr.curr buf + b;
      jl.       (i0.)   ;   return;

; variables
i0  : 0                 ; saved link
i1  : 0                 ; saved top (segment)
i2  : 0                 ; saved param segments
e.
\f


; pej 28.09.77    disc driver, update buf on error

; procedure update buf on error(statusarea,bytes,chars)
; ---------------------------------------------------------------
; statusarea: addr of statusarea containing information about
;             a read or write operation.
; bytes     : see proc update buf.
; chars     : no of chars transferred per segment. must at call-
;             time be stored in p35+2.curr receiver.
;
; the procedure performs:
; - updates curr buf by calling proc update buf with segments
;   according to transferred segments using remaining bytes in
;   statusarea or, if statusarea undefined, then remaining bytes
;   in std statusarea provided it relates to a read or write
;   operation.
;   please note that, due to a controller error (never to be
;   corrected), remaining bytecount must be transformed as
;   follows:
;     if rem mod chars_per_segm <> 0
;     then rem:= rem - if data transfer then 65536 else 256
; - leaves curr buf unchanged if neither statusarea nor std sta-
;   tus area may be used.
; please note that if the error was of such a kind that the
; transfer specified in the channelprogram was completed
; (statusinformation etc. ok), but the channel program was
; not terminated normally (f.x. error during storing of std
; status), then this procedure may increment firstaddr.curr buf
; to a value equal to lastaddr.curr buf + 2.
;
; registers: call              exit
; w0                           destroyed
; w1         curr receiver     unchanged
; w2         statusarea        destroyed
; w3         link              destroyed
;
; entry    : j12
;
; return   : link+0
b. i5 w.
j12 : rs. w3     i0.    ; update buf on error: save link;
      rl  w0  x2+2      ;   rem:= rem bytecount.statusarea;
      rl  w3  x2+0      ;
      se  w3     0      ;   if chan pg count.status area = 0 then
      jl.        i1.    ;   begin c. statusarea undefined;
      rl  w3  x1+a230   ;
      se  w3     0      ;     if chan pg count.stdstatus.curr rec
      bz  w3  x3-6+1    ;        <> 0
      ls  w3    -8      ;
      se  w3     1      ;     (and last command executed = read
      sn  w3     3      ;      or last command executed = write)
      jl.        i2.    ;     then rem:= rembytes.stdstatus.curr
      jl.       (i0.)   ;     else return;
i2  : rl  w0  x1+a231   ;
i1  : rs. w0     i3.    ;   end;
      al  w3     0      ;   saved rem:= rem;
      wd  w0  x1+p35+2  ;   rem:= rem // chars;
      sn  w3     0      ;   if saved rem mod chars <> 0 then
      jl.        i5.    ;   begin
      rl. w0     i3.    ;
      rl  w2  x1+p35+2  ;
      se  w2     q53    ;     rem:= saved rem -
      am         2      ;     if chars = chars per data segm
      ws. w0     i4.    ;     then 65536 else 256;
      sh  w0    -1      ;     if rem < 0
      jl.       (i0.)   ;     then return; c. should be impossib;
      al  w3     0      ;     rem:= rem // chars;
      wd  w0     4      ;   end;
i5  : ac  w0    (0)     ;
      rl  w2     b18    ;   segments:=
      ba  w0  x2+m5     ;   no of segments.curr buf - rem;
      rl. w3     i0.    ;   update buf(segments,bytes);
      jl.        j11.   ;   c.return from there;

;variables
i0  : 0                 ; saved link
i3  : 0                 ; for saving rem
i4  : 65536             ; constant for correcting rem, +0: data
      256               ;                              +2: addr m
e.
\f


; pej 28.09.77    disc driver, update retryinformation

; procedure update retryinformation(retryinformation)
; ---------------------------------------------------------------
; retryinformation: addr of the byte containing retryinformation.
;                   bit 0- 3: modeindex
;                   bit 4- 8: offsetindex
;                   bit 9-11: tries
;
; the procedure performs:
; - increments tries.
; - increments modeindex if tries flows over and sets tries to 1.
; - increments offsetindex if modeindex flows over and sets mode-
;   index to first value and tries to 1. not performed if
;   variable offset impossible.
;
; registers: call              exit
; w0                           destroyed
; w1         retryinformation  destroyed
; w2                           destroyed
; w3         link              unchanged
;
; entry    : j13
;
; return   : link+0: no more tries possible
;            link+2: next stobe-offset combination
;            link+4: next offset magnitude
;            link+6: tries <= 3 (mode/offset index unchanged)
b. i4 w.
j13 : rs. w1     i4.    ; update retryinformation:
      bz  w1  x1+0      ;   r:= core(retryinformation)
      al  w1  x1+1      ;   tries.r:= tries.r + 1;
      hs. w1    (i4.)   ;   core(retryinformation):= r;
      so  w1     2.100  ;   if tries.r <= 3
      jl      x3+6      ;   then return; c. link+6;
      la. w1     i0.    ;   tries.r:= 1;
      al  w1  x1+i1     ;   modeindex.r:= modeindex.r + 1;
      hs. w1    (i4.)   ;   core(retryinformation):= r;
      al  w2  x1+0      ;
      ls  w2    -8      ;
      bl. w0  x2+q20.-1 ;
      se  w0    -1      ;   if modetable(modeindex.r) <> -1
      jl      x3+2      ;   then return; c. link+2;
      la. w1     i2.    ;
      ls  w1    -3      ;
      al  w1  x1+1      ;   i:= offsetindex + 1;
      bl. w0  x1+q21.   ;
      am        (b19)   ;
      rl  w2     p5     ;
      se  w2     0      ;   if disctype.curr receiver = 0
      sn  w0    -1      ;   or offset table(i) = -1
      jl      x3+0      ;   then return; c. link+0;
      ls  w1     3      ;   r:= modeindex for next round << 8
      al  w1  x1+i3     ;       + i << 3 + 1;
      hs. w1    (i4.)   ;   core(retryinformation):= r;
      jl      x3+4      ;   return; c. link + 4;

; variables
i0  : 2.111111111000    ; mask for zeroizing tries
i1  = 2.000100000001    ; mask for incrementing modeindex, tries
i2  : 2.000011111000    ; mask for zeroizing modeindex, tries
i3  = q23<8+1           ; modeindex for next round << 8 + tries
i4  : 0                 ; saved param retryinformation
e.
\f


; pej 30.09.77    disc driver, clean

; procedure clean(result)
; ---------------------------------------------------------------
; result: result to be used as parameter to deliver result.
;
; the procedure performs:
; - returns all messages queued to the driver with above
;   mentioned result.
; - zeroizes regretted.curr receiver.
; - sets transfer state.curr receiver idle.
; - if result = 5 (unknown) then state.curr receiver is set to
;   after intervention, the name of curr receiver is zeroized
;   and so is device address in all areaprocesses referring
;   to curr receiver. the same is performed on eventual logical
;   disc drivers referring to current receiver.
;
; registers: call               exit
; w0         result             destroyed
; w1                            curr receiver
; w2                            destroyed
; w3         link               destroyed
;
; entry    : j14
;
; return   : link+0
b. i7 w.
j14 : ds. w0     i1.    ; clean: save link, result;
      rl  w1     b19    ;
      rl  w2     g49    ;
      rs  w2  x1+p13    ;   transfer state.curr rec:= idle;
      al  w2     0      ;
      rs  w2  x1+a56    ;   regretted.curr rec:= 0;
      rs  w2     g20    ;   status.i/o answer:= 0;
      rs  w2     g21    ;   bytes.i/o answer:= 0;
      rs  w2     g22    ;   chars.i/o answer:= 0;
i2  : rl  w2  x1+a54    ;   while next message.curr rec <>
      sn  w2  x1+a54    ;         addr of next message.curr rec do
      jl.        i3.    ;   begin
      rs  w2     b18    ;     curr buf:= next message.curr rec;
      jl  w3     g19    ;     deliver result(result);
      rl. w0     i1.    ;
      jl.        i2.    ;   end;
i3  : se  w0     5      ;   if result <> 5
      jl.       (i0.)   ;   then return;
      al  w0     0      ;
      rs  w0  x1+p12    ;   state.curr rec:= after intervention;
      rl  w1     b4     ;   proci:= addr of 1st device.nametable;
i4  : rs. w1     i1.    ;   repeat
      rl  w1  x1+0      ;     proc:= nametable(proci);
      rl  w3  x1+a10    ;
      rl  w0  x1+p2     ;
      sn  w0    (b19)   ;     if (mainproc.proc = curr receiver
      se  w3     q61    ;          and kind.proc = disc)
      sn  w1    (b19)   ;      or proc = curr receiver then
      jl.        i5.    ;      begin
      jl.        i7.    ;
i5  : al  w0     0      ;
      rs  w0  x1+a11    ;        name(0).proc:= 0;
      rs  w0  x1+a52    ;        reserver.proc:= 0;
      rl  w3     b5     ;        areai:= first areaproc.nametable;
i6  : rl  w2  x3+0      ;        repeat area:= nametable(areai);
      sn  w1 (x2+a50)   ;          if device addr.area:= proc
      rs  w0  x2+a50    ;          then device addr.area:= 0;
      al  w3  x3+2      ;          areai:= areai + 2
      se  w3    (b6)    ;
      jl.        i6.    ;        until areai = first internal;
i7  : am.       (i1.)   ;      end;
      al  w1     2      ;      proci:= proci + 2
      se  w1    (b5)    ;
      jl.        i4.    ;   until proci = first area proc;
      rl  w1     b19    ;
      jl.       (i0.)   ;

; variables
i0  : 0                 ; saved link
i1  : 0                 ; saved result, proci in loop
e.
\f


; pej 04.10.77    disc driver, procedure correct data

; procedure correct data
; ---------------------------------------------------------------
;
; the procedure performs:
; - checks if the error correction information stored in status-
;   area1 of curr receiver may be used for correcting the data 
;   segment pointed to by first addr.curr buf.
; - performs the correction by copying the bad word(s)
;   from the buffer and back again after having corrected them.
;   the copying is performed by calling a monitor procedure.
;   two words are copied unless the errorburst starts in the
;   base word or last word of the segment.
;
; registers: call              exit
; w0                           destroyed
; w1         curr receiver     destroyed
; w2                           curr buf if corrected
; w3         link              destroyed
;
; entry    : j15
;
; return   : link+0: data not corrected
;            link+2: data corrected
b. i25 w.
j15 : rs. w3     i0.    ; correct data: save link;
      al  w2  x1+p16+16 ;   addr:=
      ld  w1    -100    ;   addr of ecc inf.statusarea1.curr rec;
      ds. w1     i2.    ;   sum:= 0;
      jl. w3     i16.   ;   sum:= sum
      21                ;         + (21 - char0.addr)
      452387            ;         * 452387;
      jl. w3     i16.   ;   sum:= sum
      88                ;         + (88 - char1.addr)
      72358             ;         * 72358;
      jl. w3     i16.   ;   sum:= sum
      12                ;         + (12 - char2.addr)
      315238            ;         * 315238;
      al  w2  x2+2      ;   c. now eccinf(0) = 0; addr:= addr + 2;
      jl. w3     i16.   ;   sum:= sum
      22                ;         + (22 - char0.addr)
      330902            ;         * 330902;
      wd. w1     i3.    ;   c. now eccinf(2) = err pattern << 8;
      al  w1  x1+1      ;   bitdisp:=
      wm. w1     i3.    ;   (sum // 585442 + 1) * 585442
      ws. w1     i2.    ;   - sum - 56 + 16;
      al  w0  x1-56+16  ;   c. is now base for error pattern;
      sl. w0    (i5.)   ;   if bitdisp outside segment
      jl.       (i0.)   ;   then not corrected return; c. link+0;
      sh  w0     0      ;   if bitdisp <= 0
      jl.        i15.   ;   then goto corrected;
      rl  w2     0      ;   c. error entirely in checkcharacters;
      al  w2  x2+11     ;
      al  w1     0      ;   bytedisp:=
      wd. w2     i6.    ;   (bitdisp + 11) / 12; c. w2;
      al  w3     0      ;
      wd. w0     i8.    ;
      al  w3  x3-24     ;   sh:= -24 + (bitdisp mod 24);
      sn  w3    -24     ;   if sh = - 24
      al  w3     0      ;   then sh:= 0;
      rs. w3     i9.    ;   save sh;
      al  w0     q52    ;
      ws  w0     4      ;   relative:=
      la  w0     g50    ;   even (segment size - bytedisp); c.w0;
      al. w1     i10.   ;   c. relative to firstaddr.curr buf;
      al. w3     i11.   ;   first:= first bad; last:= second bad;
      se  w0    -2      ;   if relative = -2 then
      jl.        i17.   ;   begin c. only one word;
      al  w0     0      ;     relative:= 0; first:= last;
      al  w1  x3+0      ;   end;
i17 : sn  w0     q52-2  ;   if relative = segmentsize - 2
      al  w3  x1+0      ;   then last:= first; c. only 1 word;
      rl  w2     b18    ;   buf:= curr buf;
      rs. w1     i21.   ;   save first
      rl. w1     i25.   ;   store mode.call
      rs. w1     i20.   ;

      ds. w0     i23.   ;   save relative,last
      al. w1     i20.   ;   w1:= parameter address
      jd         1<11+84;   general copy(params,buf)
      se  w0     0      ;   if result <> 0
      jl.       (i0.)   ;   then not corrected return; c. link+0;
      am        (b19)   ;   c. align the err pattern to error;
      rl  w3     p16+18 ;   w3:= eccinf(2).statusarea1.curr rec;
      al  w0     0      ;   w0:= 0;
      ld. w0    (i9.)   ;   w3w0:= w3w0 shift sh;
      lx. w3     i10.   ;   first bad:= first bad xor w3;
      lx. w0     i11.   ;   second bad:= second bad xor w0;
      ds. w0     i11.   ;
      rl. w1     i24.   ;   change function in parameter list(from=curr,to=buf)
      rs. w1     i20.   ;
      al. w1     i20.   ;   w1:= parameter address
      jd         1<11+84;   general copy(params,buf)
      se  w0     0      ;   if result <> 0
      jl.       (i0.)   ;   then not corrected return; c. link+0;
i15 : am.       (i0.)   ; corrected:
      jl         2      ;   return; c. link + 2;

; routine for updating sum. the routine performs:
;   sum:= sum + (k - (core(addr) shift (-16)) * m
;   core(addr):= core(addr) shift 8
; registers: call w2=addr, w3=link
;            exit w0w1=sum (also stored in i1i2), w2,w3=unch
; call     : jl. w3  i16.
;            k             link+0
;            m             link+2
;            returnpoint   link+4
i16 : rl  w1  x2+0      ; update sum:
      al  w0     0      ;   w1:= core(addr); w0:= 0;
      ld  w1     8      ;   w0w1:= w0w1 shift 8;
      rs  w1  x2+0      ;   core(addr):= w1;
      sz  w0     8.200  ;   if char in w0 negative
      jl.       (i0.)   ;   then not corrected return;
      rl  w1  x3+0      ;
      ws  w1     0      ;   w1:= k - w0;
      wm  w1  x3+2      ;   w0w1:= w1 * m;
      aa. w1     i2.    ;   w0w1:= sum:= sum + w0w1;
      ds. w1     i2.    ;
      jl      x3+4      ;   return;

; variables
i0  : 0                 ; saved link
i1  : 0                 ; double word for sum
i2  : 0                 ; -      -
i3  : 585442            ; constant used in calculations
i6  : 12                ; -        -    -  -
i8  : 24                ; -        -    -  -
i5  : q53*8+16          ; largest bitdisplacement + 1 + 16
i9  : 0                 ; saved sh (shifts to align err pattern)
i10 : 0                 ; to receive first bad word
i11 : 0                 ; -  -       2nd   -   -
  
; parameters for general copy:
i20 : 2<1+0             ; function(pair<1+mode),init: from=buf,to=curr
i21 : 0                 ; first
i22 : 0                 ; last
i23 : 0                 ; relative
  
i24 : 2<1+1             ; function(from=curr,to=buf)
i25 : 2<1+0             ; function(from=buf,to=curr)
e.
\f


; pej 17.11.77    disc driver, update on corrected error

; procedure update on corrected error
; ---------------------------------------------------------------
;
; the procedure performs:
; - updates statistics concerning an error which has been
;   corrected either by incrementing the counter for errors
;   corrected within 3 retries (setmode param.curr receiver = 0)
;   or by incrementing a counter in the tables for errors
;   corrected by strobe-offset.
;
; registers: call              exit
; w0                           destroyed
; w1         curr receiver     unchanged
; w2                           unchanged
; w3         link              destroyed
;
; entry    : j16  -  used at transput
;            j17  -  used at control
; return   : link + 0
c. q1
b. i3 w.
j16 : rl  w0  x1+p21    ; update on corrected transput error:
      se  w0     0      ;   if setmode param.curr rec = 0 then
      jl.        i1.    ;   begin
j17 : am     (x1+p43)   ; update on corrected control error:
      al  w0     1      ;     corrected in 3 tries.curr rec:=
      rs  w0  x1+p43    ;     corrected in 3 tries.curr rec + 1;
      jl      x3+0      ;   end else
i1  : rs. w3     i0.    ;   begin c. strobe-offset used;
      ls  w0    -4      ;     i:= setmode param(16:19).curr rec;
      am        (0)     ;     c. strobe and offset;
      bz  w3  x1+p44-1  ;
      al  w3  x3+1      ;     strobe offset table(i-1).curr rec:=
      am        (0)     ;     strobe offset table(i-1).curr rec+1;
      hs  w3  x1+p44-1  ;     c. i-1 as value 1 is counted in
      rl  w0  x1+p21    ;        byte o;
      sz  w0     2.11<4 ;     if setmode param(18:19).curr rec =0
      jl.        i2.    ;     then
      jl.       (i0.)   ;     begin
i2  : la. w0     i3.    ;     i:= setmode param(20:23).curr rec;
      am        (0)     ;     c. offset magnitude;
      bz  w3  x1+p45    ;
      al  w3  x3+1      ;     offset magn. table(i).curr rec:=
      am        (0)     ;     offset magn. table(i).curr rec + 1;
                        ;     end;
      hs  w3  x1+p45    ;   end;
      jl.       (i0.)   ;   return;

; variables
i0  : 0                 ; saved link
i3  : 2.1111            ; for masking out offset magnitude
e.
z.

\f


; pej 04.10.77    disc driver, end of code

z.e.                    ; end disc driver block

e.                      ; end area process-disc driver block

b. p22, m50, n114 w.  ; block including ioc and dlc main process.

; -------------------------------------------------------------------------
; 
;              I O C   M A I N   P R O C E S S   D R I V E R
;
;              D L C   M A I N   P R O C E S S   D R I V E R
;
; -------------------------------------------------------------------------
;
;
; the main processes supports the following operations:
;
;     IOC                            DLC
;   --------------------------     -----------------------------
;
;   - dump (*)
;   - prepare dump (*)
;   - create link (*)              - create link (*)
;   - extract statistics           - extract statistics
;   - remove link (*)              - remove link (*)
;   - set mask                     - set mask    
;   - link logical disc
;   - unlink logical disc
;   - test (*)
;   - initialize controller (*)    - initialize controller (*)
;
;     RC8000-IDA/IFP
;   -------------------------- 
;
;   - input
;   - output
;   - position
;
;                                    driverproc messages
;                                  -----------------------------
;                                  - answer create link
;                                  - answer remove link request
;                                  - answer attention          
;                                  - stop normal communication (only rc8000)
;
; (*)  the (possible re-formattet) message is transmitted to the controller
;
;
; execution of messages:
; ----------------------
;
; when a message is received by the mainprocess, it is claimed
; (receiver is negated).
; only one message is executed by (the 1st part of) the driver at a
; time. when the message is executed in this part of the driver it is
; in no queue. if the message isn't going to be transmitted to the
; controller (those operation which are not marked '(*)' above) the
; answer to the message is returned before the next message is received
; (i.e. the message will never be in the event queue of the main
; process).
; if the message is going to be transfered to the controller (all 
; operations marked '(*)') the message will be delivered to the 2ed
; part of the main driver, where it will be linked either to the
; waiting queue of the main process or to the event queue of the
; receiver. at this time the 1st part of the driver will never see
; the message/answer again (except for the create/remove link
; operations where it receives an interrupt-operation).
; the 1st part of the driver need not to worry about regret of messages
; as it will never receive a regretted message. the second part (setup
; part) of the driver will take a proper action on a regretted message
; if it is regretted while it is under execution (either in the rc8000
; or in the controller).
;
\f


; use of names:
; -------------
;        m  main routines (one for each operation)
;
;        n  sub-routines
;
;        p  names of operations
;
;

; definition of operations
;
 p2 =  2     ; prepare dump
 p6 =  6     ; create link
 p9 =  9     ; extract statistics
p10 = 10     ; remove link
p12 = 12     ; set mask
p14 = 14     ; dump
p16 = 16     ; link logical disc
p18 = 18     ; unlink logical disc
p20 = 20     ; test
p22 = 22     ; initialize controller
 p3 =  3     ; ida/ifp input
 p5 =  5     ; ida/ifp output
 p8 =  8     ; ida/ifp position


; ***** stepping stones *****

jl.  (+2),  d150 ,  d150 = k - 4
jl.  (+2),  d151 ,  d151 = k - 4
jl.  (+2),  d156 ,  d156 = k - 4

\f



; 
; M E S S A G E   R E C E I V E D   B Y   M A I N P R O C E S S .
; ---------------------------------------------------------------
;
; Control is transfered to this part when driverproc receives a 
; message sent to an IOC or DLC main process.
; 
; From driverproc the following messages can be received:
;      stop normal communication    - 4
;      answer attention             - 3
;      answer remove link request   - 2
;      answer create link           - 1
;      remove link                   10
;
; At entry the registers contains:
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  main process
;

b. i10, j10  w.

h20:                   ; message received
h26:                   ;
     rs. w1     i1.    ; begin
     rl  w3     b21    ;
     zl  w0  x3+a19    ;   <* claim the buffer - driverproc will have claims
     bs. w0     1      ;      enough as it received the message in wait event
     hs  w0  x3+a19    ;      and unclaimed it 'by hand' when it received it *>
     ac  w3 (x2+a141)  ;
     rs  w3  x2+a141   ;
                       ;
     sn  w1    (b21)   ;   if message.sender = driverproc then    
     jl.        j3.    ;      goto branch;    <* skip all checks *>
                       ;
     rl  w1     b19    ;   <* select the proper operation/mode mask 
     al  w0     2.0111 ;      depending on main state and main kind *>
     la  w0  x1+a78    ;
     al  w3     8      ;   if main.connect_state = connected then
     sn  w0     l38    ;        index := connect_mask
     al  w3     0      ;   else index := free_mask;
     rl  w0  x1+a10    ;
     se  w0     q20    ;   if main.kind = ifp_main then
     al  w3  x3+4      ;        index := index or ifp_mask
     al. w3  x3+i2.    ;   else index := index or ida_mask;
     dl  w1  x3+0      ;
     jl  w3     g16    ;   check operation(operation mask, mode mask, message);
                       ;
     rl. w1     i1.    ;
     zl  w3  x2+a150   ;   if message.operation needs reservation then
     rl. w0     i3.    ;
     ls  w0  x3        ;      check reserver(sender, message)
     sh  w0    -1      ;   else
     am         g15-g14;      check user(sender, message);
     jl  w3     g14    ;
                       ;
     zl  w0  x2+a138+1 ;
     so  w0     2.1    ;   if message.state.io then
     jl.        j3.    ;   begin
     jl  w3     g34    ;     if message.regretted or
     sz                ;        message.sender.state = stopped then
     jl.        j2.    ;     begin
     rl  w3     b20    ;       no operation;
     jl         g26    ;       goto driverproc.wait event;
                       ;     end;
                       ;
j2:  jl  w3     g31    ;     increase stopcount(message.sender);
     sn  w0     p9     ;     if message.operation <> extract statistics then
     jl.        j3.    ;     begin
                       ;
     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   ;
                       ;
     rl  w0  x2+a151   ;       message.first address := 
     wa  w0  x1+a182   ;       message.first address + sender.base;
     rs  w0  x2+a151   ;       <* physical address *>
                       ;     end;
                       ;   end;
                       ;
j3:  el  w3  x2+a150+0 ; branch:
     ls  w3    +1      ;
     jl.    (x3+i5.)   ;   goto case message.operation of
                       ;
              m34      ; -4 : stop normal communication
              m33      ; -3 : answer attention
              m32      ; -2 : answer remove link request
              m31      ; -1 : answer create link
i5:            m0      ;  0 : sense
               -1      ;  1 : -
               m1      ;  2 : prepare dump / set tiomout (ida/ifp)
               m3      ;  3 : ida/ifp input
               m4      ;  4 : ida/ifp reset
               m5      ;  5 : ida/ifp output
               m6      ;  6 : create link
               -1      ;  7 : -
               m8      ;  8 : ida/ifp position
               m9      ;  9 : extract statistics
              m10      ; 10 : remove link
               -1      ; 11 : -
              m12      ; 12 : set mask
               -1      ; 13 : -
              m14      ; 14 : dump
               -1      ; 15 : -
              m16      ; 16 : link logical disc
               -1      ; 17 : -
              m18      ; 18 : unlink logical disc
               -1      ; 19 : -
              m20      ; 20 : test
               -1      ; 21 : -
              m22      ; 22 : initialize controller


i1: 0                  ; saved w1 (sender)
                       ;
    ; format of the operation/mode mask table:
    ;   -2 : ida/ioc, connected, operations
    ;i2: 0 : ida/ioc, connected, modes
    ;    2 : ifp/dlc, connected, operations
    ;    4 : ifp/dlc, connected, modes
    ;    6 : ida/ioc, not connected, operations
    ;    8 : ida/ioc, not connected, modes
    ;   10 : ifp/dlc, not connected, operations
    ;   12 : ifp/dlc, not connected, modes

    a0>3+a0>4+a0>5+a0>6+a0>8+a0>9+a0>10+a0>12+a0>16+a0>18+a0>22
i2: a0>0 + a0>1 + a0>2 + a0>3 + a0>4 + a0>5
    a0>0+a0>2+a0>3+a0>4+a0>5 + a0>6 +a0>8 + a0>9 + a0>10 + a0>12 + a0>22
    a0>0 + a0>1 + a0>2 + a0>3 + a0>4 + a0>5 + a0>6
    a0>4+a0>5+a0>9+a0>12+a0>22
    a0>0+a0>1+a0>2
    a0>2+a0>3+a0>4+a0>5+a0>9+a0>12+a0>22
    a0>0+a0>1+a0>2+a0>3+a0>4+a0>5+a0>6
    
                       ; the following operations needs reservation:
i3: a0>4

e.                     ; end   *** message received ***;
\f

;    sense
;----------------------------------------------------------------------------
;        message (sender format)           message (when delivered to part 2)
;        ---------------------------       ----------------------------------
;
;  + 0:  0 < 12 + 0                        0 < 12 + 0
;  + 6:                                    timeout value (0.1 msec)
;
;
; at entry:
;
;  w0   -
;  w1   sender
;  w2   message
;  w3   -
;

m0:                    ; sense:
     rl  w1     b19    ;
     rl  w3  x1+a87    ;
     rs  w3  x2+a153   ;   mess_3:=timeout value;
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);
\f

;    set timeout (ifp)
;----------------------------------------------------------------------------
;
; The timevalue is set in the mainprocess. If the value exceeds 800 sec.
; timeout will be set to 800 sec.
; If timeout is set to 0, the timeout supervision is disabled.
; NOTE: the procedure is called from m2.
; The operation does not involve the ifp.
;
;    message (sender format)
; +0 2<12 +0
; +2 timeout value (in sec.)
;
;
; at entry:
; w0     -                                                              
; w1     sender
; w2     message
; w3     -

b. i1 w.
m1:  rl  w0  x2+a151     ; if mess.timeout < 0 then deliver result(3)
     sh  w0     -1       ;
     jl         g5       ;                                              ;
     sl  w0     800      ; if mess.timeout > 800 sec then
     al  w0     800      ;   main.timeout := 800 sec
     wm. w0     i1.      ;
     rl  w1     b19      ;
     rs  w0  x1+a87      ; else main.timeout := mess.timeout
     al  w0     0        ;
     rs  w0     g20      ; deliver result(1)
     jl         g7       ;

i1:  10000               ; timeout in 0.1 msec
e.
\f


c.-(:a399>23a.1:)
m2=-1
z.

c.(:a399>23a.1:)-1
; prepare_dump (ioc)
; -----------------------------------------------------------------------------
; 
; the area specifed in the message is reserved for dump of the two specified
; core areas. 
; the core areas will be changed if necessary to be a multiplum of the 
; segment size by first decrementing (if possible) the first_address and then
; (if necessary) increment the last_address.
; the area process must be reserved by the sender when the message is received
; by the main process.
;
;        message (sender format)           message (when delivered to part 2)
;        ---------------------------       ----------------------------------
;
;  + 0:  2 < 12 + 0                        2 < 12 + 0
;  + 2:  first address (low core)          first address (low core)
;  + 4:  last  address (low core)          0 (no of bytes)
;  + 6:  first address (high core)         first segment (disk: phys, area: 0)
;  + 8:  last  address (high core)         no of segments
;  +10:  dump_device                       0 (next logical segment if area)
;  +12:  first segment (if dump dev=disk)  first address (high core)
;  +14:  -                                 no of segments (in high core)
;
; the format of the message when delivered to part 2 is close to the i/o
; format of a message to an area process.
;
; at entry:
;
;  w0   -
;  w1   sender
;  w2   message
;  w3   -
;

b.   i10,  j20    w.

m2:                      ; prepare dump/set timeout
     am         b19      ;
     rl  w0    +a10      ; if main.kind = ifp then goto set timeout
     se  w0     q20      ; else
     jl.        m1.      ;
     ds. w2     i2.      ; begin
                         ;   ------- check specified dump device -------
     rl  w1  x2+a155     ;
     rl  w3    (b6)      ;   proc := message.dump_device;
     rl  w0    (b4)      ;
     sl  w1    (0)       ;   if not proc within area or external then
     sl  w1  x3          ;      deliver_result(3);
     jl         g5       ;
                         ;
     rl  w3  x1+a11      ;   if proc.name = 0 or
     rl  w0  x1+a10      ;      proc.kind <> area and
     sn  w3     0        ;      proc.kind <> disk then
     jl         g5       ;      deliver_result(3);
     se  w0     q4       ;
     sn  w0     q6       ;
     sz                  ;
     jl         g5       ;
     al  w3  x1          ;   p := proc;
     sz                  ; 
j1:  rl  w3  x3+a50      ;   while p.kind <> ioc_main
     rl  w0  x3+a10      ;   begin
     se  w0     q20      ;     p := proc.main;
     jl.        j1.      ;   end;
                         ;
     se  w3    (b19)     ;   if p <> this main then
     jl         g5       ;      deliver_result(3);
                         ;
     rl  w0  x1+a10      ;   size :=
     se  w0     q4       ;   if dump_device.kind = area then
     jl.        j0.      ;      area.number_of_segments
     rl  w0  x1+a61      ;   else
     sz                  ;      disk.number_of_segments;
j0:  rl  w0  x1+a74      ;
     rs. w0     i4.      ;
                         ;
     rl  w3  x3+a200     ;
     se  w3     0        ;   if this main.pending_prepare_dump <> 0 then
     jl         g5       ;      deliver_result(3);
                         ;
     al  w2  x1          ;
     rl. w1     i1.      ;
     jl  w3     d113     ;   check_reserver(internal, proc);
     jl         g6       ;+0: other: deliver_result(2);
     sz                  ;+2: internal: ok;
     jl         g6       ;+4: none: deliver_result(2);
                         ;
                         ; -------- check addresses --------
     al  w0     2        ;
     rs. w0     i6.      ;   check high core addresses first
                         ;
     rl  w2     b18      ;
j9:  am.       (i6.)     ;check_addresses:
     dl  w1  x2+a152     ;
     la  w0     g50      ;   first := message.first & -2; <* even *>
     la  w1     g50      ;   last  := message.last  & -2; <* even *>
     am.       (i6.)     ;   message.first := first; 
     rs  w0  x2+a151     ;
                         ;
     sl  w0     0        ;   if first > 8Mhw or
     sh  w1     -1       ;      last  > 8Mhw or
     jl         g5       ;      last  > core_size then
     sl  w1    (b12)     ;      deliver_result(3);
     jl         g5       ; 
                         ;
     al  w1  x1+2        ;
     ws  w1     0        ;   dump_size := last - first + 2;
     sh  w1    -1        ;   if dump_size < 0 then
     jl         g5       ;      deliver_result(3);
                         ;
     al  w0     0        ;   no_of_segm,rest := dump_size / 512;
     wd  w1     b221     ;
     sn  w0     0        ;   if rest <> 0 then
     jl.        j11.     ;   begin
     am.       (i6.)     ;
     rl  w3  x2+a151     ;     if message.first <> 0 then
     sn  w3     0        ;     begin
     jl.        j10.     ;
     ws  w3     0        ;
     sh  w3     0        ;       first := message.first - rest;
     al  w3     0        ;       if first < 0 then first := 0;
     la  w3     g50      ;       first := first & -2; <* even *>
     am.       (i6.)     ;
     rs  w3  x2+a151     ;       message.first := first;
     jl.        j9.      ;       goto check_addresses;
                         ;     end
j10:                     ;     else
     am.       (i6.)     ;     begin
     rl  w3  x2+a152     ;
     wa  w3     0        ;       last := message.last + rest & -2; <* even *>
     la  w3     g50      ;
     am.       (i6.)     ;
     rs  w3  x2+a152     ;
     jl.        j9.      ;       goto check_addresses;
                         ;     end;
                         ;   end;
j11:                     ;
     sl. w1    (i4.)     ;   if no_of_segm > size then
     rl. w1     i4.      ;      no_of_segm := size;
     am.       (i6.)     ;
     rs  w1  x2+a152     ;   message.no_of_segments := no_of_segm;
     rl. w0     i4.      ;
     ws  w0     2        ;   size := size - no_of_segm;
     rs. w0     i4.      ;
                         ;
     al  w0     0        ;   if address_pair = last then
     rx. w0     i6.      ;   begin
     se  w0     0        ;     address_pair := first;
     jl.        j9.      ;     goto check_addresses;
                         ;   end;
     rl  w0  x2+a152     ;
     wa  w0  x2+a154     ;   if message.no_of_segments = 0 then
     sn  w0     0        ;      deliver_result(3);
     jl         g5       ;
                         ;
     dl  w0  x2+a154     ;   <* save high core addr in mess_6 - mess_7 *>
     ds  w0  x2+a157     ;
     ds  w0     b28      ;   <* save high core addr in monitor for post mortem *>
     dl  w0  x2+a152     ;
     ds  w0     b27      ;   <* save low core addr in monitor for post mortem *>
                         ;
     rs  w0  x2+a154     ;   <* transform the format to resemble the 
     al  w0     0        ;      area i/o format *>
     rs  w0  x2+a152     ;
     rs  w0  x2+a153     ;
                         ;
     rl  w3     b19      ;
     rs  w2  x3+a200     ;   main.pending_prepare_dump := message;
     al  w1     0        ;   main.dump_device := message.dump_device;
     rx  w1  x2+a155     ;   message.dump_device := 0; <* area: next logical segment *>
     rs  w1  x3+a201     ;
     rl  w0  x1+a10      ;   if dump_device.kind = area then
     se  w0     q4       ;   begin
     jl.        j12.     ;
     al  w2  x1          ;     insert_reserver(driverproc, area);
     rl  w1     b21      ;
     jl  w3     d125     ;  
     jl.        j13.     ;   end
j12:                     ;   else
     rl  w0  x2+a155     ;   begin
     wa  w0  x1+a73      ;     message.first_segment :=
     rs  w0  x2+a153     ;     message.first_logical_segment + 
                         ;     disk.first_segment;
j13:                     ;   end;
                         ;
     al  w0     0        ;   force := no;
     jl.       (n100.)   ;   start_controller(force);
                         ;
i1:  0                   ; save w1
i2:  0                   ; save w2
i4:  0                   ; size
i6:  0                   ; address pair: 0  a151 - a152
                         ;               2  a153 - a154
                         ;
e.                       ; end;
z.
\f

;
; reset (ida & ifp) 
; -------------------------------------------------------------------------
;
;        message (sender format)        answer
;        -----------------------        ------
;   + 0: 4<12 + mode                    0
;   + 2:                                ifp_type (if soft_reset)
;
; the controller will be reset. for ida it will always be a hard reset 
; (where the comm. area is not used); for ifp it will be a hard reset if
; mode <> 2 otherwise it will be a soft reset involving a reset operation 
; to be sent to the controller - in this case an answer is returned when
; the ifp controller is ready. In this case cleanup is performed when the
; answer arrives.
; the process complex in rc8000 concerning this controller is cleaned up
; i.e. all pending messages are returned with result 4, and all physical
; disc, mt processes or gsd processes are removed.
;
; at entry:
;
; w0 -
; w1 sender
; w2 message
; w3 -
;

b.  i10, j10  w.

m4:                    ; reset
     rl  w1     b4     ; begin
j0:  rl  w3  x1        ;   for proc := first external, next until last external do
     rl  w0  x3+a10    ;   begin
     se  w0     q6     ;   
     jl.        j1.    ;     if proc.kind = disc and
     rl  w0  x3+a50    ;
     se  w0    (b19)   ;        proc.main = this main and
     jl.        j1.    ;
     rl  w0  x3+a70    ;        proc.next logical disc <> 0 then
     se  w0     0      ;
     jl         g5     ;        deliver result(3);
                       ;
j1:  al  w1  x1+2      ;
     se  w1    (b5)    ;
     jl.        j0.    ;   end;
                       ;
     rl  w1     b19    ;
     al  w0   2.100000 ;   main.state := not_ok;
     lo  w0  x1+a78    ;
     hs  w0  x1+a78+1  ;
     rs  w1  x1+a77    ;   main.proc_id := main; <* just to initialize it *>
;    al  w0     0      ;
;    rs  w0  x1+a76    ;   main.device_id := 0;  <*          - " -        *>
                       ;
     rl  w0  x1+a10    ;   if main.kind = ifp_main and
     am        (b18)   ;      message.mode = soft_reset then
     zl  w3    +a150+1 ;   begin
     se  w0     q20    ;
     se  w3     2      ;
     jl.        j2.    ;
     al  w0     2      ;     force := strong; <* ignore state of main *>
     jl.       (n100.) ;     start_controller(force); 
                       ;     <* never reached *>
j2:                    ;   end
                       ;   else
     rl  w3  x1+a235   ;   begin
     sn  w0     q26    ;
     rs  w3     b58    ;     <* place ifp device addr in monitor table *>
     al  w2     0      ;
     se  w0     q26    ;     if  main.kind = ifpmain then
     am       2.01<1   ;         reset(har_ifp_reset) 
     do  w2  x3+0      ;     else reset(normal);
     la  w3  b212      ;
     wa  w3     b65    ;     <* clear any pending interrupt from contrller *>
     rl  w0  x3+a313   ;
     gp  w0     b95    ;
                       ;
     jl. w3    (n109.) ;     cleanup;
                       ;
     rl  w1     b19    ;     <* give the main process a few free
     al  w0     3      ;     buffers to play with *>
     ls  w0     12     ;
     rs  w0  x1+a78+0  ;     proc.free_buffers := 3; proc.state:=free;
     al  w0     0      ;     status := 0;
     rs  w0 x1+a86     ;
     rs  w0     g20    ;
     al  w2  x1+a242   ;
     se  w2     (x2)   ;     if in timeout queue then
     jl  w3     d5     ;       remove (main, timeout_queue)
     jl         g7     ;     deliver_result(1);
                       ;   end;
                       ;
e.                     ; end;
\f



; create link (ioc & dlc)
; -------------------------------------------------------------------------
; 
; if the specified rc8000 device number is -1 a free subprocess is
; selected (and the device no will be placed in word +6 of the message).
; the subprocess is (partly) initialized and the state of the subprocess
; is set to 'during connect'.
; the rest of the process is initialized when the maindriver receives
; a create link answer operation from the controller.
;
; IOC:  message (sender/setup format)    answer (*)
;       -----------------------------    ----------
;  + 0: 6<12 + mode                      status
;  + 2: control module/formatter         RC8000 device number
;  + 4: slave device/station no          controller device index
;  + 6: RC8000 device no/-1 (**)         device kind
;  + 8: device kind, device type         device capacity
;
;
; mode: 0: include sender as user of connection
;       1: include users of main as users of connection
;
; device kind: 
;              6: disk
;             18: tape
;
; device type: none is defined
;
; DLC:  message (sender/setup format)    answer
;       -----------------------------    ----------
;  + 0: 6<12 + mode                      status
;  + 2: device type (0-9)                RC8000 device number
;  + 4: controller index/255
;  + 6: RC8000 device no/-1 (**)
;  + 8: name in controller
;  +10:       - " -
;  +12:       - " -
;  +14:       - " -
;
; mode: as for IOC
;
; device type: see device type table (i0:)
;
; (*) the answer is created by the controller.
; (**) RC8000 process address inserted instead of device no in part 1.
;
; at entry 
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j20  w.

m6:                    ; create link   
     rl  w1  x2+a153   ; begin
     se  w1    -1      ; 
     jl.        j3.    ;   if message.rc8000_device_no = -1 then
                       ;   begin
     rl  w1     b5     ;     for proc := last external, next until first external do
     al  w1  x1-2      ;
j1:  rl  w3  x1        ;     begin
     rl  w0  x3+a10    ;
     sn  w0     q68    ;       if proc.kind = free subprocess then
     jl.        j4.    ;         goto out;
                       ;     end;       
j2:  al  w1  x1-2      ;
     sl  w1    (b4)    ;
     jl.        j1.    ;     goto no_resources; 
     jl.        j20.   ;   end
                       ;   else
j3:  ls  w1    +1      ;   begin
     wa  w1     b4     ;
     sl  w1    (b4)    ;     if not message.rc8000_device_no within external then
     sl  w1    (b5)    ;        deliver_result(3);
     jl         g5     ;
     rl  w3  x1        ;     proc := nametable(rc8000 device no);
     rl  w0  x3+a10    ;     if proc.kind <> free subprocess then
     se  w0     q68    ;        goto no_resources;
     jl.        j20.   ;
                       ;   end;
j4:  am        (b19)   ;out:
     rl  w0    +a10    ;   <* w3: proc *>
     se  w0     q20    ;   if this main.kind = ioc_main then
     jl.        j5.    ;   begin
                       ;
     zl  w0  x2+a154   ;     kind := message.device_kind;
     se  w0     q6     ;     if kind <> disk and tape then
     sn  w0     q18    ;        deliver_result(3);
     sz                ;
     jl         g5     ;       <* w0: kind *>
     jl.        j7.    ;   end
j5:                    ;   else <* main = dlc *>
     rl  w1  x2+a151   ;   begin
     sl  w1     1      ;     if message.device_type < 1 or
     sl  w1     10     ;        message.device_type > 9 then
     jl         g5     ;        deliver_result(3);
                       ;
     zl. w0  x1+i0.    ;     kind := device_kind_table(message.device_type);
;    jl.        j7.    ;   end;
                       ;
j7:                    ;
     rl  w1  x2+a142   ;   if message.regrettet then
     sh  w1     0      ;     deliver_result(dummy);
     jl         g7     ;
     zl  w1  x2+a150+1 ;   if message.mode <> 0 or 1 then
     sz  w1    -2      ;      deliver_result(3);
     jl         g5     ;
                       ;
                       ;   <*  init process  *>
     rs  w0  x3+a10    ;   proc.kind := kind;
                       ;
     dl  w2  x2+a152   ;   proc.module,facility :=
     ds  w2  x3+a68    ;   message.module,facility;
     ld  w2    -48     ;   <* module,fac. irr. for dlc - don't matter *>
     ds  w2  x3+a71    ;   <* clear proc a70 - a87 *>
     ds  w2  x3+a73    ;
     ds  w2  x3+a75    ;
     ds  w2  x3+a87    ;
                       ;
     rl  w2     b19    ;   proc.main := this main;
     rs  w2  x3+a50    ;
     al  w1    2.000001;   proc.state := during_connect;
     hs  w1  x3+a78+1  ;
     rs  w3  x3+a77    ;   proc.proc_id := proc;
     am        (b18)   ;
     rs  w3    +a153   ;   message.8000_process := proc;
                       ;
     al  w2  x3        ;
     am        (b18)   ;   if message.mode = 0 then
     zl  w0    +a150+1 ;      include_user(message.sender, proc)
     se  w0     0      ;   else
     jl.        j10.   ;      include_all_users(main, proc);
     am        (b18)   ;
     rl  w1    +a142   ;
     sh  w1     0      ;
     ac  w1  x1        ;
     jl  w3     d126   ;
     al  w0     0      ;   force := no;
     jl.       (n100.) ;
j10:                   ;
     rl  w1     b19    ;
     jl. w3     (n103.);
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);
                       ;   <* never reached *>
                       ;
j20:                   ; no_resources:
     al  w0   8.1400   ;   status := no_resources;
     rs  w0     g20    ;
     jl         g7     ;   deliver_result(1);
                       ;
h.                     ; device_kind_table(0:9)
i0:            -1      ; 0 : -
      8                ; 1 : terminal
     28                ; 2 : IMC port handler
     28                ; 3 : mailbox
     28                ; 4 : 3270 input
     28                ; 5 : 3270 output
     28                ; 6 : lanstat (test device)
     28                ; 7 : floppy
     14                ; 8 : printer
     18                ; 9 : streamer
w.                     ;
e.                     ; end;

\f


; extract statistics (ioc & dlc)
; -------------------------------------------------------------------------
;
; the statistical information collected in the main process is copied
; to the sender.
;
;       message (sender format)         answer
;       -----------------------         ------
;  + 0: 9<12 + mode                     status
;  + 2: first storage address           no of halfwords
;  + 4: last storage address            no of characters
;
;  mode: clear statistics<0: 0 = statistics remain unchanged
;                            1 = statistics are cleared
;
;  at entry
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j10  w.

m9:                    ; extract statistics
     rl  w3     b19    ; begin
     al  w0  x3+a216   ;   param.first address := this main.statistics.first
     al  w1  x3+a218   ;   param.last address  := this main.statistics.last
     ds. w1     i3.    ;
     al. w1     i1.    ;
     jd      1<11+84   ;   general_copy(buffer, param);
                       ;
     sn  w0     0      ;   if result = 3 then
     jl.        j1.    ;      decrease stopcount and deliver result_3(message)
     se  w0     2      ;   else if result = 2 then 
     jl.        (n104.);   begin
     jl  w3     d132   ;     decrease_stopcount(message);
     rl  w3     b20    ;
     jl         g26    ;     goto_no_operation;
                       ;   end;
j1:  rs  w1     g21    ;
     ls  w1    -1      ;   message.no_of_halfwords := halfwords;
     wm  w1     g48    ;   message.no_of_characters:= halfwords*2/3;
     rs  w1     g22    ;
     al  w0     0      ;
     rs  w0     g20    ;   message.status := 0;
                       ;
     zl  w1  x2+a150+1 ;   if not clear_statistics then
     so  w1     2.1    ;      decrease stopcount and deliver result_1(message)
     jl.        (n105.);   else
     ld  w1    -100    ;   begin
     ds  w1  x3+a216+2 ;     clear all statistics in this mainprocess
     ds  w1  x3+a218   ;
     jl.        (n105.);     decrease stopcount and deliver result_1(message);
                       ;   end;
                       ;
                       ; param:
i1:  2<1 + 1           ; function := 1st address pair, core to buffer
     0                 ; first address
i3:  0                 ; last address
     0                 ; relative start
                       ;
e.                     ; end;
\f


;
; remove link (ioc & dlc)
; ------------------------------------------------------------------------
;
; removes the connection between a rc8000 external process representing an
; device and the corresponding device.
;
;       message (sender format)         answer (*)
;       -----------------------         ----------
;  + 0: 10<12 + 0                       0
;  + 2: rc8000 device number         
; (+ 4: rc8000 proc addr when sent
;              from driverproc)
;
;       message (setup format)
;       ----------------------
;  + 0: 10<12 + 0
;  + 2: rc8000 process address
;  + 4: controller_index
;
; (*) the answer is created by the controller.
;
; at entry 
; 
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j10  w.

m10:                    ; remove link
                        ; begin
     se  w1    (b21)    ;   if sender = driverproc then
     jl.        j0.     ;   begin
     rl  w2  x2+a152    ;     proc := message.mess_2;
                        ;
     al  w0     2.000111;     if proc.state = free or
     la  w0  x2+a78     ;        proc.state = during disconnect then
     se  w0     l36     ;        deliver_result(3);
     sn  w0     l39     ;        <* a remove link message has been received
     jl         g5      ;           after driverproc sent this message *>
     jl.        j2.     ;     goto proc_ok;
j0:                     ;   end;
     rl  w3  x2+a151    ; 
     ls  w3    +1       ;
     wa  w3     b4      ;
     sl  w3    (b4)     ;   if not message.device number within external processes then
     sl  w3    (b5)     ;      deliver result(3);
     jl         g5      ;
     rl  w2  x3         ;   proc := nametable(message.device number);
                        ;
     rl  w3  x2+a50     ;
     sn  w2    (b19)    ;   if proc = this main or
     jl         g5      ;      proc.main <> this main then
     se  w3    (b19)    ;      deliver_result(3);
     jl         g5      ;   <* test of main will catch disconnect of logical
                        ;      disks and return result 3 *>
     al  w0     2.000111;
     la  w0  x2+a78     ;
     se  w0     l36     ;   if proc.state= free or
     sn  w0     l39     ;      proc.state= during disconnect 
     jl         g5      ;   then deliver_result(3);
     rl  w0  x2+a10     ;
     se  w0     q6      ;   if proc.kind = disk then
     jl.        j1.     ;   begin
     rl  w0  x2+a70     ;
     rl  w3     b19     ;     if proc.next_logical_disk <> 0 or
     se  w0     0       ;        proc = this main.dump_device then
     jl         g5      ;        deliver_result(3);
     sn  w2 (x3+a201)   ; 
     jl         g5      ;   end;
                        ;
j1:  jl  w3     d76     ;   test user and reserver(sender, proc);
     sz  w3     2.1000  ;   if other reserver or
     jl         g6      ;     (sender not user and other users) then
     so  w3     2.0001  ;   deliver_result(2);
     so  w3     2.0100  ;
     sz                 ;
     jl         g6      ;
j2:                     ; proc_ok:
     rl  w1     b18     ;
     rl  w3  x2+a76     ;   message.mess_1 := proc;
     ds  w3  x1+a152    ;   message.mess_2 := proc.controller_index;
                        ;
     ac  w0     2.000111+1;
     la  w0  x2+a78     ;
     al  w3     l39     ;
     lo  w0     6       ;
     hs  w0  x2+a78+1   ;   proc.state := during disconnect;
                        ;   <* prevents create peripheral process *>
     rl  w0  x2+a10     ;   
     se  w0     q8      ;   if proc.kind = terminal then
     jl.        j3.     ;   begin
     al  w0     1<1     ;     type := disconnected;
     rl  w1     b19     ;
     jl. w3     (n112.) ;     check_remoter(type, main, proc);
     rs  w3  x2+a74     ;     proc.att_receiver := internal_supervisor;
     se  w3     0       ;     if internal_supervisor then
     jl. w3     n114.   ;        send_remoter_att(type, main, proc);
                        ;   end;
j3:                     ;
     jl. w3     n2.     ;   clear_process(proc);
                        ;
     al  w0     0       ;   force := no;
     jl.       (n100.)  ;   start controller(force);
                        ;   <* the rest of the process will be cleared when
                        ;      answer disconnect is received *>
e.                      ; end;
\f


;
; set mask (ioc & dlc)
; ------------------------------------------------------------------------
; 
; sets the test mask in the rc8000 driver.
;
;       message (sender/setup format)     answer
;       -----------------------------     ----------
;  + 0: 12<12 + mode                      status
;  + 2: rc8000 mask (point  0 - 23) 
;  + 4: rc8000 mask (point 24 - 47)
;
; at entry 
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

m12:                   ; set mask
                       ; begin
     rl  w3     b19    ;   <* set mask for rc8000 device drivers *>
     dl  w1  x2+a152   ;
     ds  w1  x3+a75    ;
     al  w0     0      ;   answer.status := ok;
     rs  w0     g20    ;
     jl         g7     ;   deliver_result(1);
                       ; end;
\f


; dump (ioc)
; -----------------------------------------------------------------------------
;
; the previously sent 'prepare dump' operation will be executed.
;
;         message (sender & setup format)
;         -------------------------------
;   + 0: 14 < 12 + 0
;   + 2:  0
;   + 4:  0
;
;
; at entry:
;
;    w0:  -
;    w1:  sender
;    w2:  message
;    w3:  -
;

b.  i10,  j10   w.

m14:                      ; dump
     rl  w3     b19       ; begin
     rl  w0  x3+a200      ;
     sn  w0     0         ;   if main.pending_prepare_dump = 0 then
     jl         g5        ;      deliver_result(3);
     rl  w0  x2+a151      ;
     lo  w0  x2+a152      ;
     se  w0     0         ;   if message.mess_1<>0 or message.mess_2<>0 then
     jl         g5        ;      deliver_result(3);
     al  w0     1         ;   force := weak;
     jl.       (n100.)    ;   start_controller(force);
                          ;
e.                        ; end;

\f


;
; link logical disk (ioc)
; ------------------------------------------------------------------------
; 
; creates a logical disc process and initialize it. if the specified 
; device number of the logical disc is -1 a free subprocess is selec-
; ted.
;
;       message (sender format)               answer
;       -----------------------               ------
;  + 0: 16<12 + mode                          status
;  + 2: device no of logical disc/-1          device no of logical disc
;  + 4: device no of physical disc            device no of physical disc
;  + 6: first segment                         first segment
;  + 8: no of segments                        no of segments
;
;  mode: 0: sender is included as user of logical disc.
;        1: all users of main are included as users of the logical disc.
;
; at entry
; 
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j15  w.

m16:                    ; link logical disc
     zl  w0  x2+a150+1  ; begin
     sz  w0    -2       ;   if not message.mode = 0 or 1 then
     jl         g5      ;      deliver result(3);
     rl  w3  x2+a152    ;
     ls  w3    +1       ;
     wa  w3     b4      ;      if not external processes then
     sl  w3    (b4)     ;
     sl  w3    (b5)     ;      deliver result(3);
     jl         g5      ;
                        ;
     rl  w3  x3         ;   proc := nametable(devno);
     rl  w0  x3+a10     ;   if proc.kind <> disc or
     rl  w2  x3+a50     ;      proc.main <> this mainprocess then
     sn  w0     q6      ;      deliver result(3);
     se  w2    (b19)    ;
     jl         g5      ;
     al  w0     2.000111;
     la  w0  x3+a78     ;   if proc.state <> connected then
     se  w0     l38     ;      deliver result(3);
     jl         g5      ;
                        ;
     al  w2  x3         ;   
     jl  w3     d113    ;   check reserver(sender, proc);
     jl         g6      ;   +0: if other reserver then deliver result(2);
     jl.        j0.     ;   +2: 
     jl  w3     d102    ;   +4: if no reserver then check user(sender, proc);
     jl         g6      ;   +0: if not user then deliver result(2);
                        ;   +2:
j0:  al  w3  x2         ;
     rs. w1     i1.     ;
     rl  w1     b18     ;   logical := proc.first logical disc;
     rl  w2  x3+a70     ;
j1:  sn  w2     0       ;   while logical <> 0 do
     jl.        j4.     ;   begin
                        ;
     rl  w0  x2+a73     ;     if logical.first segment < message.first segment then
     sl  w0 (x1+a153)   ;     begin
     jl.        j2.     ;       if logical.first segment+logical.no of segments >=
     wa  w0  x2+a74     ;          message.first segment then
     sh  w0 (x1+a153)   ;          deliver result(3);
     jl.        j3.     ;
     jl         g5      ;
                        ;     end else
j2:  rl  w0  x1+a153    ;     begin
     wa  w0  x1+a154    ;       if message.first segment+message.no of segments >=
     sh  w0 (x2+a73)    ;          logical.first segment then
     sz                 ;          deliver result(3);
     jl         g5      ;
                        ;     end;
j3:  rl  w2  x2+a70     ;     logical := logical.next logical disc;
     jl.        j1.     ;   end;
                        ;
j4:  rl  w2  x1+a153    ;   if message.first segment <
     al  w0  x2-1       ;      proc.first segment or
     wa  w0  x1+a154    ;      message.first segment + message.no of segments >
     sl  w2 (x3+a73)    ;      proc.no of segments or
     sl  w0 (x3+a74)    ;      
     jl         g5      ;
     sl  w0  x2         ;      message.no of segments <= 0 then
     sz                 ;
     jl         g5      ;      deliver result(3);
                        ;
     rl  w1  x1+a151    ;   if message.logical devno = -1 then
     se  w1    -1       ;   begin
     jl.        j7.     ;
     rl  w1     b4      ;     for ext := first external, next until last external do
j5:  rl  w2  x1         ;     begin
     rl  w0  x2+a10     ;
     se  w0     q68     ;       if ext.kind = free subprocess then
     jl.        j6.     ;       begin
     rl  w1  x2+a59     ;         message.logical devno := ext.device_no;
     am        (b18)    ;
     rs  w1    +a151    ;         goto out;
     jl.        j7.     ;       end;
                        ;
j6:  al  w1  x1+2       ;
     se  w1    (b5)     ;
     jl.        j5.     ;     end;
     jl.        j10.    ;     deliver status('no free subprocesses');
                        ;out:
                        ;   end;
j7:  ls  w1    +1       ;
     wa  w1     b4      ;
     sl  w1    (b4)     ;   if not ext within external processes then
     sl  w1    (b5)     ;   deliver result(3);
     jl         g5      ;
     rl  w2  x1         ;   ext := nametable(logical devno);
     rl  w0  x2+a10     ;   if ext.kind <> free subprocess then
     se  w0     q68     ;      deliver status('no free subprocesses');
     jl.        j10.    ;
                        ;
     ld  w1    -100     ;   ext.chaintable := 0;
     ds  w1  x2+a72     ;   ext.slicelength := 0;
     al  w1  x2+a81     ;
     al  w0  x1         ;   <* init process queues *>
     ds  w1  x2+a81+2   ;
     al  w1  x2+a54     ;
     al  w0  x1         ;
     ds  w1  x2+a55     ;
                        ;
     rs  w3  x2+a50     ;   ext.main := physical disc;
     al  w0     q6      ;   ext.kind := disc kind;
     rs  w0  x2+a10     ;
     al  w0     2.1     ;
     hs  w0  x2+a57     ;   ext.type := logical type;
     am        (b18)    ;
     dl  w1    +a154    ;   ext.first segment := message.first segment;
     ds  w1  x2+a74     ;   ext.no of segments:= message.no of segments;
     dl  w1  x3+a87     ;   ext.max_transfer_size := physical_disk.max_transfer_size;
     ds  w1  x2+a87     ;   ext.max_buffer_size := physical_disk.max_buffer_size;
     rl  w1  x3+a75     ;   ext.bytes_pr_track := physical_disk.bytes_pr_track;
     rs  w1  x2+a75     ;
     dl  w1  x3+a77     ;   ext.controller_index:=physical_disc.controller_index;
     ds  w1  x2+a77     ;   ext.rc8000process:= physical disc.rc8000process;
     dl  w1  x3+a68     ;   ext.cm  := physical disc.cm;
     ds  w1  x2+a68     ;   ext.unit:= physical disc.unit;
                        ;
     al  w0     0       ;
j8:  sn  w0 (x3+a70)    ;   while proc.next logical disc <> 0 do
     jl.        j9.     ;   proc := proc.next logical disc;
     rl  w3  x3+a70     ;
     jl.        j8.     ;
                        ;
j9:  rs  w2  x3+a70     ;   proc.next logical disc := ext;
     rs  w0  x2+a70     ;   ext.next logical disc := 0;
                        ;
     am        (b18)    ;
     zl  w0    +a150+1  ;   if message.mode = 0 then
     se  w0     0       ;      include user(message.sender, ext)
     jl.        j11.    ;   else
     rl. w1     i1.     ;      include all users(physical disc, ext);
     jl  w3     d126    ;
     jl.        j12.    ;
j11:                    ;
     rl  w1  x2+a50     ;
     jl. w3     (n103.) ;
j12:                    ;
     al  w0     l38     ;
     hs  w0  x2+a78+1   ;   ext.state := connected;
                        ;
     rl  w3     b18     ;
     al  w0     0       ;
     rs  w0     g20     ;   status := ok;
     dl  w1  x3+a152    ;   rc8000 device no of logical disc
     ds  w1     g22     ;   rc8000 device no of physical disc
     dl  w1  x3+a154    ;   first segment
     ds  w1     g24     ;   no of segments
     jl         g7      ;   deliver result(1);
                        ;
                        ;
j10:                    ; no_resources: 
     al  w0   8.1400    ;   status := no_resources; 
     rs  w0     g20     ;
     jl         g7      ;   deliver result(1);
                        ;
i1:  0                  ; saved sender
                        ;
e.                      ; end;
\f


;
; unlink logical disc (ioc)
; ------------------------------------------------------------------------
;
; removes the logical disc process in rc8000 and the connection to the 
; physical disc process.
;
;       message (sender format)            answer
;       -----------------------            ------
;  + 0: 18<12 + 0                          0
;  + 2: rc8000 device number               
;
; at entry
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j10  w.

m18:                   ; unlink logical disc
     rl  w3  x2+a151   ; begin
     ls  w3    +1      ;
     wa  w3     b4     ;
     sl  w3    (b4)    ;   if not message.device number within external processes then
     sl  w3    (b5)    ;      deliver result(3);
     jl         g5     ;
                       ;
     rl  w2  x3        ;   proc := nametable(message.device number);
     rl  w0  x2+a10    ;   if proc.kind <> disc or
     zl  w3  x2+a57    ;      proc.type <> logical disc then
     sn  w0     q6     ;      deliver result(3);
     so  w3     2.1    ;
     jl         g5     ;
     sz  w3     2.1100000;    if proc.type = logical volume then 
     jl         g5     ;      deliver result(3);
                       ;
     rl  w3  x2+a50    ;   if proc.main.main <> this mainprocess or
     rl  w3  x3+a50    ;      proc.chaintable <> 0 then
     rl  w0  x2+a71    ;      deliver result(3);
     sn  w0     0      ;
     se  w3    (b19)   ;
     jl         g5     ;
                       ;
     sn  w2 (x3+a201)  ;   if mainprocess.dump_device = proc then
     jl         g5     ;      deliver_result(3);
                       ;
     jl  w3     d76    ;   test user and reserver(sender, proc);
     sz  w3     2.1000 ;   if other reserver or
     jl         g6     ;      (sender not user and other users) then
     so  w3     2.0001 ;      deliver result(2);
     so  w3     2.0100 ;
     sz                ;
     jl         g6     ;
                       ;
     rl  w1  x2+a50    ;   p := proc.main; <* physical disc *>
j1:  sn  w2 (x1+a70)   ;   while p.next logical disc <> proc do
     jl.        j2.    ;     p := p.next logical disc;
     rl  w1  x1+a70    ;
     jl.        j1.    ;
                       ;
j2:  rl  w0  x2+a70    ;   p.next logical disc := proc.next logical disc;
     rs  w0  x1+a70    ;
     al  w0     0      ;   proc.next logical disc := 0;
     rs  w0  x2+a70    ;
                       ;
     jl. w3     n2.    ;   clear_process(proc);
                       ;
     jl. w3     n8.    ;   free_process(proc);
                       ;
     al  w0     0      ;   status := 0;
     rs  w0     g20    ;
     jl         g7     ;   deliver result(1);
                       ;
e.                     ; end;
\f


m20:                   ; test:
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);


\f


;
; initialize controller
; -----------------------------------------------------------------------------
;
; the mainprocess is connected to the supervisor process in the controller.
; credits for outstanding messages are exchanged between the two parties.
;
;      message (sender/setup format)     answer format
; + 0  22 < 12 + 0                       0
; + 2  controller credit                 monitor credit
;
; at entry
; w0   -
; w1   sender
; w2   message
; w3   -

b.  i10,  j10  w.

m22:                    ; initialize controller
     rl  w1     b19     ; begin
     al  w0     8.07    ;
     la  w0  x1+a78+1   ;   if main.state <> free then
     se  w0     0       ;      deliver_result(3);
     jl         g5      ;
                        ;
     am        (b21)    ;   if driverproc.buffer_claim <=
     zl  w0    +a19     ;      message.controller_credit then
     sh  w0 (x2+a151)   ;      deliver_result(3);
     jl         g5      ;
                        ;
     rl  w0  x2+a142    ;   if regretted(message) then
     sh  w0     0       ;      deliver_result(dummy);
     jl         g7      ;
                        ;
     al  w0     2.000001;   main.state := during_connect;
     lo  w0  x1+a78     ;
     hs  w0  x1+a78+1   ;   <* give the main process a few free
     al  w0     4       ;      buffers to play with *>
     hs  w0  x1+a78+0   ;   proc.free_buffers := 4;
                        ;
     rs  w1  x1+a50     ;   main.main := main;
     rs  w1  x1+a77     ;   main.proc_id := main;
     al  w0     0       ;   main.device_id := 0;
     rs  w0  x1+a76     ;
     al  w3     0       ;
     ds  w0  x1+a216+2  ;   <* clear statistics *>
     ds  w0  x1+a218    ;
     ds  w0  x1+a201    ;   <* clear prepare dump variables *>
                        ;
     rx  w1     4       ;
     rl  w1  x1+a142    ;
     jl  w3     d126    ;   include_user(message.sender, proc);
                        ;
     al  w0     1       ;   force := weak;
     jl.       (n100.)  ;   start_controller(force);
                        ;
e.                      ; end;
\f


;
; answer create link (internal driverproc message)
; -----------------------------------------------------------------------------
;
; sent from driverproc to mainprocess (driverproc) when 'answer create link'
; is sent to then controller.
; format of the message: see o20 in the interrupt procedure c36.
;
;    at entry
;   w0  -
;   w1  (sender)
;   w2  message
;   w3  -
;

b.  i5,  j5  w.

i1:  0                    ; reserver, result
i2:  0                    ; terminal_process

m31:                      ; answer create link
     rl  w0  x2+a151      ; begin
     rs. w0     i1.       ;   <* save reserved, result *>
     rl  w0  x2+a153      ;
     rs. w0     i2.       ;   <* save terminal process *>
                          ;
     al  w0     0         ;   force := no;
     am        (b19)      ;
     rl  w1    +a59       ;
     jd         1<11+128  ;   start_controller(force, this main.devno, message);
     se  w0     0         ;   if result <> ok then 
     jl         g4        ;      deliver_result(4);
                          ;
     hl. w0     i1.+0     ;   
     hl. w1     i1.+1     ;   if save_result <> ok or
     sn  w1     1         ;      save_reserved = 0 then
     se  w0     1         ;      goto driverproc.wait_event;
     jl        (b20)      ;
                          ;
;    al  w0     1<0       ;   type := connected;
     rl  w1     b19       ;
     rl. w2     i2.       ;
     jl. w3     n14.      ;   send_remoter_att(type, main, terminal);
                          ;
     jl        (b20)      ;   goto driverproc.wait_event;
                          ;
                          ;
e.                        ; end;

\f



; answer remove link request
; answer attention

m32:
m33:
     al  w0     0      ; force := no;
     jl.       (n100.) ; start_controller(force);

; stop normal communication

m34: al  w0     2      ; force := strong
     jl.        (n100.); start_controller(force)





\f


;
; input (ida ifp) only RC8000
; -----------------------------------------------------------------------------
;
; this operation must have been preceeded by a 'position' operation in which
; the input area was defined.
;
;        message (sender format)       answer (*)
;        -----------------------       ----------
;   + 0: 3<12 + 0                      status
;   + 2: first storage address         no of halfwords transfered
;   + 4: last storage address          no of chareacters transfered
;
;        message (setup format)
;        ----------------------
;   + 0: 3<12 + 0
;   + 2: first storage address
;   + 4: no of bytes
;
; (*) the answer is created by the controller.
;
; at entry:
;
; w0  -
; w1  sender
; w2  message
; w3  -
;

b.  i5, j5  w.

m3:                    ; input 
                       ; begin
     al  w3     0      ;   message.no of bytes := 
     rl  w0  x2+a152   ;  (message.no of bytes//768) * 768;
     wd  w0     b222   ;
     wm  w0     b222   ;   < let no of bytes be a multiplum of the
     rs  w0  x2+a152   ;     segmentsize >
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);
                       ;
e.                     ; end;

\f


;
; take autoload block (ida & ifp) only RC8000
; -------------------------------------------------------------------------
;
; the specified autoload block is transmitted to the controller.
;
;       message (sender format)        answer (*)
;       -----------------------        ----------
;  + 0: 5<12 + 0                       status
;  + 2: first storage address          number of halfwords transfered
;  + 4: last storage address           number of characters transfered
;
;       message (setup format)
;       ----------------------
;  + 0: 5<12 + 0
;  + 2: first storage address
;  + 4: no of bytes
;
; (*) the answer is created by the controller.
;
; at entry
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b. i10, j10  w.

m5:                    ; take autoload block
                       ; begin
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);
                       ;
e.                     ; end;
\f


;
; position (ida ifp) only RC8000
; -----------------------------------------------------------------------------
; 
; this operation defines the (logical) filenumber from where the succeding
; input operations will receive data.
;
;       message (sender/setup format)     answer (*)
;       -----------------------------     ----------
;  + 0: 8<12 + 0                          status
;  + 2: 0
;  + 4: 0
;  + 6: (logical) filenumber
;
; (*) the answer is created by the controller.
;
; at entry:
; 
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

m8:                    ; position
                       ; begin
     al  w0     0      ;   force := no;
     jl.       (n100.) ;   start_controller(force);
                       ; end;
\f

; 
; M E S S A G E   R E C E I V E D   B Y   S S P  M A I N P R O C E S S .
; ----------------------------------------------------------------------
;
; Control is transfered to this part when driverproc receives a 
; message sent to the SSP main process.
; 
; From driverproc the following messages can be received:
;      answer attention             - 3
;
; The ioc/dlc code for the following operations are used by the
; ssp main-driver:
;      - extract_statistics    ( m9)
;      - set_mask              (m12)
;      - initialize_controller (m22)
;
; At entry the registers contains:
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  main process
;

b. i10, j10  w.

h24:                   ; message received
     rs. w1     i1.    ; begin
     rl  w3     b21    ;
     zl  w0  x3+a19    ;   <* claim the buffer - driverproc will have claims
     bs. w0     1      ;      enough as it received the message in wait event
     hs  w0  x3+a19    ;      and unclaimed it 'by hand' when it received it *>
     ac  w3 (x2+a141)  ;
     rs  w3  x2+a141   ;
                       ;
     sn  w1    (b21)   ;   if message.sender = driverproc then    
     jl.        j3.    ;      goto branch;    <* skip all checks *>
                       ;
     zl  w0  x2+a150+0 ;   if message.operation < 24 then
     sl  w0     24     ;   begin
     jl.        j1.    ;
     dl. w1     i2.    ;     check_operation(operation_mask, mode_mask, message);
     jl  w3     g16    ;
     rl. w1     i1.    ;
     jl  w3     g14    ;     check_user(sender, message);
     jl.        j2.    ;   end
j1:                    ;   else   <* no io operation with oper. code > 23 as  *>
     se  w0     24     ;   begin  <* check_operation must be called for those *>
     sn  w0     25     ;     if message.operation <> 24 and
     sz                ;        message.operation <> 26 then
     jl         g5     ;        deliver_result(3);
     rl. w1     i1.    ;
     jl  w3     g15    ;     check_reserver(sender, message);
j2:                    ;   end;
                       ;
     zl  w0  x2+a138+1 ;
     so  w0     2.1    ;   if message.state.io then
     jl.        j4.    ;   begin
     jl  w3     g34    ;     if message.regretted or
     sz                ;        message.sender.state = stopped then
     jl.        j3.    ;     begin
     rl  w3     b20    ;       no operation;
     jl         g26    ;       goto driverproc.wait event;
                       ;     end;
                       ;
j3:  jl  w3     g31    ;     increase stopcount(message.sender);
                       ;
     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   ;
                       ;
     rl  w0  x2+a151   ;     message.first address := 
     wa  w0  x1+a182   ;     message.first address + sender.base;
     rs  w0  x2+a151   ;     <* physical address *>
                       ;   end;
                       ;
j4:                    ; branch:
     zl  w0  x2+a150+0 ;   oper := message.operation;
     sn  w0     5      ;   if oper = operator_output then
     jl.        m41.   ;      goto   operator_output else
     sn  w0     6      ;   if oper = create_link then
     jl.        m42.   ;      goto   create_link else
     sn  w0     9      ;   if oper = extract_statistics then
     jl.        m9.    ;      goto   extract_statistics else
     sn  w0     12     ;   if oper = set_mask then
     jl.        m12.   ;      goto   set_mask else
     sn  w0     22     ;   if oper = initialize_controller then
     jl.        m22.   ;      goto   initialize_controller else
     sn  w0     24     ;   if oper = close_system then
     jl.        m43.   ;      goto   close_system else
     sn  w0     26     ;   if oper = reload_system then
     jl.        m44.   ;      goto   reload_system
     jl.        m45.   ;   else goto answer_attention;
                       ;
                       ;
i1:  0                 ; save w1 (sender)
                       ;
                       ; ssp legal operation mask (only operations < 24)
                       ; ssp legal mode mask      (only operations < 24)

    a0>5 + a0>6 + a0>9 + a0>12 + a0>22
i2: a0>0 + a0>1

e.                     ; end   *** message received ***;
\f


; operator_output
; ---------------------------------------------------------------------------
;
;   message:
;
;  + 0: 5<12 + 0
;  + 2: first address
;  + 4: last address (byte count when sent to controller)
;

m41:                   ; operator_output:
                       ; begin
     al  w0     0      ;   force := no;
     jl.        n0.    ;   start_controller(force);
                       ; end;

; close_system
; reload_system
; ---------------------------------------------------------------------------
; nothing to check - nothing to do here!

m43:                   ; close_system:
m44:                   ; reload_system:
                       ; begin
     al  w0     1      ;   force := yes;  <* just do it quickly *>
     jl.        n0.    ;   start_controller)force);
                       ; end;

; answer_attention
; -------------------------------------------------------------------------
; nothing to check - nothing to do here!

m45:                   ; answer_attention:
                       ; begin
     al  w0     0      ;   force := no;
     jl.        n0.    ;   start_controller(force);
                       ; end;
\f


; create link (SSP)
; -------------------------------------------------------------------------
; 
; if the specified rc8000 device number is -1 a free subprocess is
; selected (and the device no will be placed in word +6 of the message).
; the subprocess is (partly) initialized and the state of the subprocess
; is set to 'during connect'.
; the rest of the process is initialized when the maindriver receives
; a create link answer operation from the controller.
;
;       message (sender/setup format)    answer
;       -----------------------------    ----------
;  + 0: 6<12 + mode                      status
;  + 2: device type (1 or 7)             RC8000 device number
;  + 4: -
;  + 6: RC8000 device no/-1 (**)
;
; mode: 0: include sender as user of link
;       1: include users of main as users of link
;
; device type: 1 : console
;              7 : floppy disk
;
; (**) RC8000 process address inserted instead of device no in part 1.
;
; at entry 
;
;  w0  -
;  w1  sender
;  w2  message
;  w3  -
;

b.  i10, j20  w.

m42:                   ; create link   
     rl  w1  x2+a153   ; begin
     se  w1    -1      ; 
     jl.        j3.    ;   if message.rc8000_device_no = -1 then
                       ;   begin
     rl  w1     b4     ;     for proc := first external, next until last external do
j1:  rl  w3  x1        ;     begin
     rl  w0  x3+a10    ;
     sn  w0     q68    ;       if proc.kind = free subprocess then
     jl.        j4.    ;         goto out;
                       ;     end;       
j2:  al  w1  x1+2      ;
     se  w1    (b5)    ;
     jl.        j1.    ;     goto no_resources; 
     jl.        j20.   ;   end
                       ;   else
j3:  ls  w1    +1      ;   begin
     wa  w1     b4     ;
     sl  w1    (b4)    ;     if not message.rc8000_device_no within external then
     sl  w1    (b5)    ;        deliver_result(3);
     jl         g5     ;
     rl  w3  x1        ;     proc := nametable(rc8000 device no);
     rl  w0  x3+a10    ;     if proc.kind <> free subprocess then
     se  w0     q68    ;        goto no_resources;
     jl.        j20.   ;
                       ;   end;
j4:                    ; out:
     rl  w1  x2+a151   ;
     se  w1     1      ;   if message.device_type <> 1 and
     sn  w1     10     ;      message.device_type <> 9 then
     sz                ;      deliver_result(3);
     jl         g5     ;
                       ;
     al  w0     9      ;   kind := if message.device_type = terminal then 9
     se  w1     1      ;           else 28;
     al  w0     28     ;
                       ;
     rl  w1  x2+a142   ;   if message.regrettet then
     sh  w1     0      ;     deliver_result(dummy);
     jl         g7     ;
     zl  w1  x2+a150+1 ;   if message.mode <> 0 or 1 then
     sz  w1    -2      ;      deliver_result(3);
     jl         g5     ;
                       ;
                       ;   <*  init process  *>
     rs  w0  x3+a10    ;   proc.kind := kind;
     ld  w2    -48     ;
     ds  w2  x3+a71    ;   <* clear proc a70 - a87 *>
     ds  w2  x3+a73    ;
     ds  w2  x3+a75    ;
     ds  w2  x3+a87    ;
                       ;
     rl  w2     b19    ;   proc.main := this main;
     rs  w2  x3+a50    ;
     al  w1    2.000001;   proc.state := during_connect;
     hs  w1  x3+a78+1  ;
     rs  w3  x3+a77    ;   proc.proc_id := proc;
     am        (b18)   ;
     rs  w3    +a153   ;   message.8000_process := proc;
                       ;
     al  w2  x3        ;
     am        (b18)   ;   if message.mode = 0 then
     zl  w0    +a150+1 ;      include_user(message.sender, proc)
     se  w0     0      ;   else
     jl.        j10.   ;      include_all_users(main, proc);
     am        (b18)   ;
     rl  w1    +a142   ;
     sh  w1     0      ;
     ac  w1  x1        ;
     jl  w3     d126   ;
     al  w0     0      ;   force := no;
     jl.        n0.    ;
j10:                   ;
     rl  w1     b19    ;
     jl. w3     n3.    ;
     al  w0     0      ;   force := no;
     jl.        n0.    ;   start_controller(force);
                       ;   <* never reached *>
                       ;
j20:                   ; no_resources:
     al  w0   8.1400   ;   status := no_resources;
     rs  w0     g20    ;
     jl         g7     ;   deliver_result(1);
                       ;
e.                     ; end;
; ***** stepping stones *****

n100: n0               ;
n103: n3               ;
n104: n4               ;
n105: n5               ;
n109: n9               ;
n112: n12              ;
n114: n14
jl.  (+2),  d156 ,  d156 = k - 4

\f


; I N T E R R U P T   R E C E I V E D   F R O M   C O N T R O L L E R .
; ---------------------------------------------------------------------
;
; all interrupts except 'answer device operation' are delivered
; as interrupts to the mainprocess in question.
; when an interrupt is received the communication area from the controller
; to rc8000 has not been released yet.

b. i10, j10, o121 w.


c36:                      ; interrupt received
     rl  w1     b19       ; begin
     rl  w2  x1+a501      ;
     rs  w2     b18       ;   <*  w1 = main,   w2 = message (if any) *>
     rl  w0  x1+a244      ;
     sn  w0     3         ;   if timeout_interrupt then goto timeout
     jl.        o3.       ;   
     se  w0     0         ;   if NOT ok_interrupt then
     jl.        o2.       ;      goto power_interrupt;
                          ;  else begin <*normal io result*>
     rl  w3     b218      ;   <* left 8 bits *>
     la  w3  x1+a500      ;
     ls  w3    -3-12      ;
     sl  w3    13*2*2     ;   if main.function >12 then
     jl        -1         ;      panic;
     jl.    (x3+j0.)      ;   goto case main.function of
                          ;
                          ;   <* w1: main, w2: message (if any) *>
                          ; func, answ
                          ; - - - - - -
j0:            -1         ;   0    0  : panic
               -1         ;   0    1  : panic
               -1         ;   1    0  : panic 
               -1         ;   1    1  : panic, answer device operation, catched
     o20                  ;   2    0  : create link
     o21                  ;   2    1  : answer create link
               -1         ;   3    0  : panic
     o31                  ;   3    1  : answer remove link
     o40                  ;   4    0  : attention
               -1         ;   4    1  : panic
               -1         ;   5    0  : panic
      o1                  ;   5    1  : answer regret: start controller
               -1         ;   6    0  : panic
      o1                  ;   6    1  : answer reserve device: start controller
               -1         ;   7    0  : panic
      o1                  ;   7    1  : answer release device: start controller
     o80                  ;   8    0  : remove link request
               -1         ;   8    1  : panic
               -1         ;   9    0  : panic
     o91                  ;   9    1  : answer initialize controller
               -1         ;  10    0  : panic
               -1         ;  10    1  : panic
               -1         ;  11    0  : panic
     o111                 ;  11    1  : answer reset
               -1         ;  12    0  : panic
     o121                 ;  12    1  : answer stop normal communication
\f


b.  i10,  j10   w.        ; - - - data - - - 

i0:  -1 < 12 + 0          ; mess_0: operation (= answer_create_link)
i1:  0                    ;     +2: reserved, result 
i2:  0                    ;     +4: device_id
i3:  0                    ;     +6: proc_id
i4:  0, 0, 0, 0           ; +8-+14: name of reserver (if any)

i8:  32000                ; max transfer size

o20:                      ; create link
                          ; --------------------
                          ; begin
     rl  w0  x1+a502      ;
     rs. w0     i2.       ;   mess_2 := main.device_id;    
     al  w2  x1+a514      ;
     jl  w3     d11       ;   check_name,(driverproc,name_address);
     sz                   ; not found goto search free sub process
     jl.        j0.       ; found goto set result 9;
     rl  w3     b5        ;   proc := last_external;
j1:  al  w3  x3-2         ;   while proc.kind <> free and
     rl  w2  x3           ;         proc <> first_external 
     rl  w0  x2+a10       ;   begin
     sn  w0     q68       ;     proc := nametable(prev);
     jl.        j2.       ;
     se  w3    (b4)       ;
     jl.        j1.       ;   end;
                          ;
                          ;
     am         8-9       ;   if proc = first_external 
j0:  al  w0     9         ;      or name already exist then
     rs. w0     i1.       ;   begin
     jl.        j9.       ;     result := no_resources/already exist;
                          ;     goto answer_controller;
                          ;   end;
j2:                       ;
     al  w0     1         ;
     rs. w0     i1.       ;   reserved := 0; result := ok;
     rs. w2     i3.       ;   mess_3 := proc;
     ld  w0    -48        ;
     ds  w0  x2+a71       ;   <* clear proc a70 - a87 *>
     ds  w0  x2+a73       ;
     ds  w0  x2+a75       ;
     ds  w0  x2+a87       ;
     al  w3  x2+a81       ;   <* init process queues *>
     al  w0  x3           ;
     ds  w0  x2+a81+2     ;
     al  w3  x2+a54       ;
     al  w0  x3           ;
     ds  w0  x2+a54+2     ;
     rs  w1  x2+a50       ;   proc.main := this main;
     rl  w1     (b6)      ;
     jl  w3     d126      ;   insert_user(proc,proc_func);
     rl  w1  x2+a50       ;
     al  w0     l37       ;
     rs  w0  x2+a78       ;   proc.state := during_connect;
     al  w0     q8        ;
     rs  w0  x2+a10       ;   proc.kind := terminal;
     rl  w0  x1+a502      ;
     rs  w0  x2+a76       ;   proc.device_index := main.device_id;
     rs  w2  x2+a77       ;   proc.process_address := proc;
     rl. w3     i8.;x1+a513;
     rs  w3  x2+a87       ;   proc.buffer_size := main.mess_3;
     al  w3  x3+1         ;
     rs  w3  x2+a86       ;   proc.max_transfer := buffer_size + 1;
     dl  w0  x1+a514+2    ;
     ds  w0  x2+a11+2     ;   proc.name := main.mess_4 - mess_7;
     dl  w0  x1+a514+6    ;
     ds  w0  x2+a11+6     ;
     am         (b21)     ;   proc.name_base := driverproc.base (i.e. max)
     dl  w0     +a49      ;
     ds  w0  x2+a49       ;
     al  w0     1<0       ;   type := connected;
     jl. w3     (n112.)   ;   check_remoter(type, main, proc);
                          ;   <* w3 retur: 0 or internal_supervisor *>
     sn  w3     0         ;   if internal_supervisor then
     jl.        j4.       ;   begin
     al  w2  x3           ;
     dl  w0  x2+a11+2     ;
     ds. w0     i4.+2     ;     mess_4 - mess_7 := internal_supervisor.name;
     dl  w0  x2+a11+6     ;
     ds. w0     i4.+6     ;
     am.       (i3.)      ;
     rs  w2    +a74       ;     proc.att_receiver := internal_supervisor;
     al  w2     1         ;     mess_1.reserver := 1;
     hs. w2     i1.+0     ;   end;
j4:                       ;
j9:                       ; answer_controller:
     al. w2     i0.       ;
     jl. w3     n13.      ;   send_main_message(main, message);
                          ;
     jl.        o1.       ;   goto common_end;
                          ;
e.                        ; end <* ----- end create link ----- *>
\f


b.   i10, j20   w.              ; - - - data - - - 
i0:  32000                     ; default ifp buffersize
i2:  0                         ; saved message
i4:                            ; result : comment
;    ccccccccddssssss........  ; c=connect_result, d=description, s=dev_status
   2.000000000000010000000000  ;    8   : no resources
   2.000000000000010100000000  ;    9   : link already exist
   2.100000000000000100000000  ;   10   : ill kind (should not come ?)
   2.001000000000000100000000  ;   11   : controller unknown
   2.100000000000000100000000  ;   12   : device unknown
   2.000100000000000100000000  ;   13   : controller fault
   2.000100000000000100000000  ;   14   : device fault

                          ;
o21:                      ; answer create link
                          ; --------------------
                          ; begin
     al  w0     8.377     ;   if main.result = ok then
     la  w0  x1+a500      ;   begin
     se  w0     1         ;
     jl.        j8.       ;
                          ;
     rl  w3  x1+a503      ;     proc := main.proc_id;
     rl  w0  x3+a10       ;
     se  w0     q6        ;     if proc.kind = disk then 
     jl.        j2.       ;     begin
                          ;
     rl  w0  x1+a520+a154 ;       proc.no_of_segments :=
     rs  w0  x3+a74       ;       message.device_capacity :=
     rs  w0  x2+a154      ;       main.mess_4;
                          ;
     sn  w0     0         ;       if proc.no_of_segments > 0 then
     jl.        j1.       ;       begin
     rs. w2     i2.       ;
     al  w2  x3           ; 
     al  w3     0         ;         proc.segments_pr_track :=
     rl  w0  x1+a520+a156 ;         main.mess_6 / bytes_pr_segment;
     wd  w0     b222      ;
     rs  w0  x2+a75       ;
                          ;
     al  w3     0         ;         proc.buffer_size :=
     rl  w0  x1+a520+a155 ;         main.mess_5 / bytes_pr_segment;
     wd  w0     b222      ;
     rs  w0  x2+a87       ;
                          ;         <* make max transfer a multiple
     al  w3     0         ;            of track size *>
     wd  w0  x2+a75       ;         proc.max_transfer :=
     wm  w0  x2+a75       ;         proc.buffer_size / proc.segments_pr_track *
                          ;                            proc.segments_pr_track;
     sn  w0     0         ;         if proc.max_transfer = 0 then
     rl  w0  x2+a87       ;         proc.max_transfer := proc.buffer_size;
     rs  w0  x2+a86       ;         <* in case where buffersize < tracksize *>
                          ;
     al  w3  x2           ;
     jl.        j6.       ;       end
j1:                       ;       else
                          ;       begin
                          ;         <* drive has not been formated *>
                          ;         <* io requests will be rejected due to  
                          ;            disk.no_of_segments *>
                          ;       end;
     jl.        j6.       ;     end
j2:                       ;     else
     se  w0     q18       ;     if proc.kind = tape then
     jl.        j3.       ;     begin
                          ;
     rl  w0  x1+a520+a155 ;       proc.buffer_size := main.mess_5;
     rs  w0  x3+a87       ;       proc.max_transfer := main.mess_5 + 1;
     ba. w0     1         ;
     rs  w0  x3+a86       ;
                          ;
     rl  w0    (b3)       ;       proc.remoter_process :=
     rs  w0  x3+a75       ;       nametabel(1);
                          ;
     al  w0     3         ;       proc.document_state :=
     la  w0  x1+a520+a157 ;
     rs  w0  x3+a70       ;       returned_state;
     jl.        j6.       ;     end
j3:                       ;     else
     sn  w0     q28       ;     if proc.kind = gsd or
     jl.        j4.       ;        proc.kind = printer or
     sn  w0     q14       ;        proc.kind = terminal or
     jl.        j4.       ;        proc.kind = ssp terminal then
     sn  w0     q8        ;
     jl.        j4.       ;
     se  w0     q9        ;
     jl        -1         ;     begin
j4:                       ;
     rl. w0     i0.       ;       proc.buffer_size := standard size 
     rs  w0  x3+a87       ;
     ba. w0     1         ;       proc.max_transfer := standard size;
     rs  w0  x3+a86       ;
;    jl.        j6.       ;     end
                          ;     else panic;
j6:                       ;
     rl  w0  x1+a502      ;     proc.device_id := 
     rs  w0  x3+a76       ;     main.device_id;
     ac  w0     2.000111+1;
     la  w0  x3+a78       ;
     al  w2     l38       ;     proc.state := 
     lo  w0     4         ;     proc.state or connected;
     hs  w0  x3+a78+1     ;
                          ;     <* prepare answer *>
     al  w0     0         ;
     rs  w0     g20       ;     answer_0 := ok; <* status *>
     rl  w0  x3+a59       ;
     rs  w0     g21       ;     answer_1 := proc.devno;
     rl  w0  x1+a502      ; 
     rs  w0     g22       ;     answer_2 := main.device_id;
     am        (b18)      ;
     rl  w0    +a154      ;     answer_3 := message.device_kind,device_modif;
     rs  w0     g23       ;
     rl  w0  x1+a514      ;     answer_4 := main.mess_4; <*device capacity *>
     rs  w0     g24       ;
     al. w3     o1.       ;
     jl         g18       ;     deliver_result(1);
                          ;     goto common_end;
                          ;   end
j8:                       ;   else
     rl  w2  x1+a503      ;   begin
     jl. w3     n2.       ;     clear_process(main.proc_id);
     jl. w3     n8.       ;     free_process(main.proc_id);
                          ;
     al. w3     o1.       ;     if main.result < 5 then
     sh  w0     5         ;     begin
     jl         g19       ;       deliver_result(main.result);
                          ;       goto common_end;
                          ;     end;
     rl  w2     0         ;
     al  w2  x2-8         ;
     ls  w2     1         ;
     rl. w0  x2+i4.       ;
     rs  w0     g20       ;     answer_0 := status_table(main.result);
     jl         g18       ;     deliver_result(1);
                          ;     goto common_end;
                          ;   end;
e.                        ; end;
\f


b.   i10,  j10   w.       ; 

o31:                      ; answer remove link
                          ; --------------------
                          ; begin
     al  w0     8.377     ;   if main.result <> ok then
     la  w0  x1+a500      ;      panic;
     se  w0     1         ;
     jl        -1         ;
                          ;
     rl  w2  x1+a503      ;   proc := main.proc_id;
     rl  w0  x2+a10       ;
     sn  w0     q8        ;   if proc.kind = terminal then
     jl. w3     n7.       ;      remove_attention_buffer(proc);
                          ;
     jl. w3     n8.       ;   free_process(proc);
                          ;
     al  w2  x2+a54       ;   clear_queue(normal, proc.event_q);
     al  w0     0         ;
     jl. w3     n1.       ;
                          ;
     rs  w0     g20       ;   answer_0 := 0; <* status *>
     jl  w3     g18       ;   deliver_result(1);
                          ;
     jl.        o1.       ;   goto common_end;
                          ;
e.                        ; end;

\f


b.   i10,  j25  w.        ; - - - data - - -

                          ; ------ message ------
i0:  -3<12 + 0            ; + 0: operation (= answer attention)
i1:  0                    ; + 2: att_result, result
i2:  0                    ; + 4: device_id
i3:  0                    ; + 6: proc_id
i5:  0                    ; internal receiver of att_message
i6:  0                    ; remoter event_q
i7:  0                    ; remoter message
                          ;
o40:                      ; attention
                          ; --------------------
                          ; begin
                          ;   <* prepare answer attention message *>
     dl  w3  x1+a503      ;   mess_2 := main.device_id;
     ds. w3     i3.       ;   mess_3 := main.proc_id;
     al  w0     1         ;   mess_1.att_result := ok; mess_1.result := ok;
     rs. w0     i1.       ;   <* initialized to ok; might be changed later on *>
                          ;
     al  w2  x3           ;   proc := main.proc_id;
     rl  w0  x2+a10       ;   if proc.kind = disk then
     se  w0     q6        ;   begin
     jl.        j5.       ;
                          ;
     al  w0     8.377     ;
     la  w0  x1+a511      ;     event := main.mess_1;
     se  w0     1         ;     if event = intervention then
     jl.       j4.        ;     begin
                          ;
     al  w0     l40       ;       proc := proc.next_logical_disk;
j2:  rl  w2  x2+a70       ;       while proc <> 0 do
     sn  w2     0         ;       begin
     jl.        j3.       ;         proc.state := intervention;
     hs  w0  x2+a78+1     ;         proc := proc.next_logical_disk;
     jl.        j2.       ;       end;
j3:  jl.        j20.      ;
j4:  sl  w0     1         ;     end else 
     sl  w0     4         ;     if envent <> test buffer full and event <> data correction performed then
     jl         -1        ;     panic
     jl.        j20.      ;   end
j5:                       ;   else
     se  w0     q18       ;   if proc.kind = tape then
     jl.        j15.      ;   begin
                          ;
     al  w0     8.377     ;
     la  w0  x1+a511      ;     event := main.mess_1;
     se  w0     0         ;     if event = online then
     jl.        j10.      ;     begin
                          ;
     al  w0     l46       ;       proc.document_state :=
     rs  w0  x2+a70       ;            unidentified_document_mounted;
     al  w0     0         ;       proc.name := 0;
     rs  w0  x2+a11       ;
     rs  w0  x2+a52       ;       proc.reserver := 0;
                          ;
     rl  w3  x2+a75       ;       if proc.remoter<>0 then
     sn  w3     0         ;       begin
     jl.        j9.       ;
     al  w1  x3+a54       ;         message:=proc.remoter.eventq.first;
     rl  w3  x1           ;
     rs. w1     i6.       ;
     rs. w3     i7.       ;
j6:  sn. w3    (i6.)      ;         while message<>none do
     jl.        j9.       ;         begin
     rl  w0  x3+a140      ; 
     rs. w0     i7.       ;           if message.operation=wait for online and
     zl  w0  x3+a150      ;            ((message.mode=specific main and
     se  w0     0         ;              message.main=this main) or
     jl.        j8.       ;              message.mode=all main) then
     zl  w0  x3+a150+1    ;           begin
     so  w0     2.1       ;
     jl.        j7.       ;
     rl  w0  x3+a151      ;
     se  w0    (b19)      ;
     jl.        j8.       ;
j7:  rs  w3     b18       ;             message.status:=0;
     al  w0     0         ;             message.mt-addr:=proc;
     rs  w0     g20       ;
     rs  w2     g21       ;
     jl  w3     g18       ;             deliver_result(1);
j8:  rl. w2     i2.       ;           end;
     rl. w3     i7.       ;           message:=message.next;
     jl.        j6.       ;         end ;
j9:                       ;       end;
     jl.        j11.      ;     end 
                          ;     else
j10: se  w0     1         ;     if event = offline then
     jl        -1         ;     begin
     al  w0     l45       ;       proc.document state := no document mounted;
     rs  w0  x2+a70       ;
     al  w0     0         ;       proc.name := 0  ;
     rs  w0  x2+a11       ;
     rs  w0  x2+a52       ;       proc.reserver := 0;
                          ;     end
                          ;     else panic; <* not defined *>;
j11:                      ;
     jl.        j20.      ;   end
j15:                      ;   else
     se  w0     q8        ;   if proc.kind = terminal or
     sn  w0     q9        ;      proc.kind = ssp terminal then
     sz                   ;
     jl.        j21.      ;   begin
                          ;
     rl  w0  x2+a52       ;     if terminal.reserver <> 0 then
     sn  w0     0         ;     begin
     jl.        j16.      ;
     rl  w0  x2+a71       ;       if terminal.attention_buffer_address <> 0 then
     se  w0     0         ;       goto skip_att_message; <* att already sent to
     jl.        j19.      ;                               reserving internal *>
     rl  w2  x2+a74       ;       att_receiver := terminal.att_receiver;
     jl.        j18.      ;     end
j16:                      ;     else
     al  w2  x1+a514      ;     begin
     rl. w1     i3.       ;
     dl  w1  x1+a49       ;   
     jl  w3     d71       ;       i := search_name(main.mess_4, terminal.name_base);
     rl  w2  x3           ;       att_receiver := name_table(i);
     rl  w0  x2+a10       ;       if i = name_table_end or
     se  w3    (b7)       ;          att_receiver.kind <> internal and
     sz  w0    -1-64      ;          att_receiver.kind <> pseudo_process then
     sz                   ;       begin
     jl.        j18.      ;  
     al  w0     1         ;         mess_1.att_result := unknown;
     hs. w0     i1.+0     ;         goto skip_att_message;
     jl.        j19.      ;
                          ;       end;
                          ;     end;
j18:                      ;
     rs. w2     i5.       ;     <* save att_receiver *>
     rl. w1     i3.       ;
     al  w2     0         ;     if terminal.attention_buffer <> 0 then
     rx  w2  x1+a71       ;     regret_message(terminal.attention_buffer);
     se  w2     0         ;
     jl  w3     d75       ; 
     am         (b21)     ;
     zl  w0     +a19      ;
     sh  w0     5         ;     if bufferclaim.driverproc < 6 then
     jl.        j19.      ;       no message to receiver
     rl. w1     i5.       ;
     rl  w0  x1+a10       ;     if att_receiver.kind = pseudo_process then
     se  w0     0         ;     att_receiver := att_receiver.main;
     rl  w1  x1+a50       ;
     rl. w2     i3.       ; 
     jl  w3     d126      ;     insert_user(att_receiver, terminal);
     rl  w1     b19       ;
     rl  w0  x1+a511      ;  
     rs  w0     g21       ;     att_mess_1 := main.event; <*returned messages *>
                          ;
     ld  w0    -48        ;     <* clear att message *>
     rs  w0     g20       ;
     ds  w0     g23       ;
     al  w1     g20       ;
     rl. w3     i5.       ;   
     jd      1<11+17      ;     send_att_message(message, terminal, att_receiver);
     rl. w1     i3.       ;
     rs  w2  x1+a71       ;     terminal.attention_buffer := message_buffer;
                          ;
j19:                      ; skip_att_message:
                          ;
     jl.        j20.      ;   end
                          ;   else panic;

j21: se  w0     q24       ;   if proc_kind = ssp main then
     jl         -1        ;   begin
     rl  w0  x1+a511      ;
     se  w0     1         ;     if event<>temperatur_too_high and
     sn  w0     2         ;        event<>power_warning then
     jl         -1        ;     panic;
     jl.        j20.      ;     <* do nothing yet *>
                          ;   end;
                          ;
j20:                      ;
     rl  w1     b19       ;
     al. w2     i0.       ;
     jl. w3     n13.      ;   send_main_message(main, message);
     jl.        o1.       ;   goto common_end;
                          ;
e.                        ; end;

\f


b.  i10, j10    w.        ; - - - data - - - 
                          ;             --------- message ---------
                          ;       answer_remove_link_request   remove_link
i4:  0                    ; + 0:  -2 < 12 + 0                  10 < 12 + 0
i5:  0                    ; + 2:  result                       proc.devno
i6:  0                    ; + 4:  device_id                    proc address
i7:  0                    ; + 6:  proc_id (address)
                          ;
o80:                      ; remove link request:
                          ; --------------------
                          ; begin
     dl  w3  x1+a503      ;   mess_2 := main.device_id;
     ds. w3     i7.       ;   mess_3 := proc := main.proc_id; 
     al  w0     2.000111  ;
     la  w0  x3+a78       ;
     sn  w1 (x3+a50)      ;   mess_1 := <* result *>
     se  w0     l38       ;   if proc.main <> main or
     am         2         ;      proc.state <> connected then
     al  w0     1         ;   3 else 1;
     rs. w0     i5.       ;
     al  w0    -2         ;   mess_0.operations := -2;
     hs. w0     i4.+0     ;   <* answer remove link request *>
                          ;
     al. w2     i4.       ;
     jl. w3     n13.      ;   send_main_message(main, message);
                          ;
     rl. w0     i5.       ;   if message.result = ok <* mess_1 *>
     se  w0     1         ;   begin
     jl.        j1.       ;
                          ;
     rl  w1     b19       ;     <* main *>
     rl  w3  x1+a503      ;     mess_1 := proc.device_no;
     rl  w2  x3+a59       ;     mess_2 := proc;
     ds. w3     i6.       ;
     al  w0     10        ;     mess_0.operation := remove_link;
     hs. w0     i4.+0     ;
     al. w2     i4.       ;
     jl. w3     n13.      ;     send_main_message(main, message);
                          ;   end;
j1:                       ;
     jl.        o1.       ;   goto common_end;
                          ;
e.                        ; end <* ----- remove link request ----- *>
;
;
b. i10, j10 w.
o91:                      ; answer initialize controller;
     al  w0     8.377     ; begin
     la  w0  x1+a500      ;
     se  w0     1         ;   if main.result <> ok then
     jl         -1        ;     panic;
     rl  w0  x1+a511      ;   main.free_buffers:=
     hs  w0  x1+a78+0     ;   main.mess_1;
     rl  w0  x1+a78       ;
     ea. w0     1         ;   main.state:=connected;
     hs  w0  x1+a78+1     ;   <* a bit diry - is was in state during connect *>
     rl  w0  x1+a502      ;   main.supervisor_id:=
     rs  w0  x1+a76       ;   main.device_id;
     al  w0     0         ;
     rs  w0     g20       ;   answer_0:=0; <* status *>
     jl  w3     g18       ;   deleiver_result(1);
     jl.        o1.       ;   goto common end;
e.                        ; end;
\f

b.  i10,  j10  w.

i2:  0                    ; saved message to answer

o111:                     ; answer reset and answer stop
o121:                     ; ---------------------
     al  w0     8.377     ; begin
     la  w0  x1+a500      ;
     se  w0     1         ;   if main.result <> ok then
     jl        -1         ;      panic;
                          ;
     jl  w3     d5        ;   unlink(message);
     rs. w2     i2.       ;   <* unlink and save message to prevent it from
                          ;      being returned with result 4 *>
     jl. w3     n9.       ;   cleanup;
     rl  w1     b19       ;
     al  w0     3         ;   main.free_buffers := 3;
     hs  w0  x1+a78+0     ;   <* give it a few buffers to play with *>
     al  w0     0         ;   main.controller_stat := ok and not busy;
     hs  w0  x1+a78+1     ;   main.connect_state := free;
     rs  w0     g20       ;   answer.status := 0;
     al  w0     1         ;
     rs  w0  x1+a86       ;   main.no_of_outstanding := 1  <* it will be decreased at commen end *>
     al  w2  x1+a242      ;   
     se  w2     (x2)      ;   if in timeout queue then
     jl  w3     d5        ;     unlink (main, timeout_queue)
     rl  w0  x1+a511      ;
     rs  w0     g21       ;   answer.mess_1 := main.mess_1;
     rl. w0     i2.       ;
     rs  w0     b18       ;
     jl  w3     g18       ;   deliver_result(1);
     jl.        o1.       ;   goto common_end;
                          ; 
e.                        ; end;
\f


; timeout_interrupt      ;
b. i4 w.                 ;  <*** begin io result <> 0 ***>

i1:  -4<12 + 0           ; stop
i2:   4<12 + 1           ; reset hard                                    

o3:
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+a81+2     ;
     jl. w3    (f4.)      ;
     jl.        f2.       ;
f3:  d150                 ;
f4:  d151                 ;
f2:                       ;
e.z.                      ; ****** end test 44 ******
     al  w0     0        ; clear interrupt
     rs  w0  x1+a244     ;
     zl  w0  x1+a78+1    ; if main.state = connected then
     se  w0     l38      ; message := stop communication
     am      i2-i1       ;  else
     al. w2     i1.      ; message := reset hard
     la  w0     8.40     ; state := not ok
     hs  w0  x1+a78+1    ;
     jl. w3     n13.     ;
     jl.        o0.      ; return


o2:                       ; power_interrupt:
c.l53  b.  f4  w.         ; ****** test 43 ******
     rs. w3     f1.       ;
     rs. w1     f0.       ;
     jl. w3    (f3.)      ;
     43                   ;
f0:  0                    ; main
f1:  0                    ;
     jl.        f2.       ;
     al  w0  x1+a86       ; dump main.communication area
     al  w1  x1+a81+2     ;
     jl. w3    (f4.)      ;
     jl.        f2.       ;
f3:  d150                 ;
f4:  d151                 ;
f2:                       ;
e.z.                      ; ****** end test 43 ******
     al  w3    0          ; 
     rs  w3  x1+a244      ; clear interrupt
     rs  w3  x1+a78       ; main.free_buffers := 0; main.stat := free;
     rl  w2  x1+a10       ; insert timeout depending of kind
     ws. w2     i3.       ;
     rl. w0  x2+i0.       ; main.timeout := default 
     ds  w0  x1+a87       ; main.no_of_outstanding := 0
     jl.       o0.        ; return;

i0: 0                     ; default timeout: 20 ida 
    0                     ;  - - - - - - - : 22 not used
    0                     ;  - - - - - - - : 24 (not invented yet)
    600000                ;  - - - - - - - : 26 ifp
i3: 20


o1:                       ; common_end:
                          ; --------------------

     am        (b19)      ;
     rl  w1    +a59       ;
     al  w2    -1         ;
     jd        1<11+128   ;   start_controller(this main.device_no, answer_device);

     rl  w1     b19       ;
     rl  w0     b218      ;
     la  w0  x1+a500      ;
     ls  w0     -15       ;
     jl. w3     d156.     ;   decrease no_of_outstanding(main,function);

     rl  w2  x1+a81       ;   element := main.waiting_q.first;
     sn  w2  x1+a81       ;   if element = none then
     jl.        o0.       ;      return;
     al  w0     0         ;   force :=
     sl  w2     (b8+4)    ;
     sl  w2     (b8+6)    ;   if element <> message then no
     jl.        i4.       ;
     al  w0     2.1000000 ;   else message.state.force;
     la  w0  x2+a138      ;
     ls  w0     -6
i4:                       ;
     rl  w1     x1+a59    ;
     jd         1<11+128  ;   start_controller(this main.device_no, message);
                          ; end;
o0:  jl         (b20)     ;   goto driverproc.wait_event;

e.                        ;   end <*** io result <> 0 **>
e.                        ; end <*** interrupt received ***>




\f

m.                   commen procedures

;
; ========================================================================
;
;             common procedures used by main processes
;
; ========================================================================
;


; 
; procedure start controller(force)
; ------------------------------------------------------------------------
;
; the controller supervised by current receiver (b19) will be started
; with current message (b18).
; controll will be returned to 'wait event' in driverproc.
; the parameter force will be passed to the procedure test_ready_and_setup.
;
;        call
;
;   w0   force
;   w1   -
;   w2   -
;   w3   -
;

n0:                    ; procedure start controller;
     rl  w1     b19    ; begin
     rl  w1  x1+a59    ;   
     rl  w2     b18    ;   start_controller(force, this main.devno, message);
     jd      1<11+128  ;
                       ;
     se  w0     0      ;   if result <> ok then 
     jl         g4     ;   deliver result(4)
     jl        (b20)   ;   else goto wait event;
                       ; end;

\f


;
; procedure clear queue(io result,queue head);
; ------------------------------------------------------------------------
;
; all messages in the specified queue are returned with result 4.
; for each message the receiver is tested. if the receiver is a monitor
; driven driver then the receiver is changed to the driverprocess of the
; mainprocess. this will make it possible for driverproc to send the answer.
;
;     call            return
;
; w0  io result       io result
; w1  -               unchanged
; w2  queue head      queue head
; w3  link            destroyed
;

b.  i10, j10  w.

n1:                   ; procedure clear queue(io result, queue head); 
     sn  w2 (x2+0)    ; begin
     jl      x3       ;
     ds. w3     i3.   ;
     ds. w1     i1.   ;
     dl  w1     b19   ;
     ds. w1     i5.   ;
                      ;   while not queue head.empty do
j1:  rl  w2  x2+0     ;   begin
     rs  w2     b18   ;     cur buf := queue head.first;
     jl  w3     g32   ;     decrease stopcount(cur buf);
     rl  w2     b18   ;
     ac  w3 (x2+a141) ;
     rl  w0  x3+a10   ;     if message.receiver.kind <> main_kinds then
     se  w0     q20   ;     begin <* monitor driven driver *>
     sn  w0     q26   ;       message.receiver := driverproc;
     jl.        j2.   ;       <* simulate that the message hasn't been claimed
     rl  w1     b21   ;          this will force 'deliver result' to decrease
     rs  w1  x2+a141  ;          bufferclaime of driverproc before sending the
                      ;          answer *>
                      ;     end;
j2:  rl. w0     i0.   ;     message.io result := io result;
     rs  w0     g23   ;
     al  w0     4     ;
     jl  w3     g19   ;     deliver result(4);
     rl. w2     i2.   ;
     se  w2 (x2+0)    ;
     jl.        j1.   ;   end;
                      ;
     dl. w1     i5.   ;
     ds  w1     b19   ;
     dl. w1     i1.   ;
     jl.       (i3.)  ;
                      ;
i0:  0                ;  saved w0
i1:  0                ;  saved w1
i2:  0                ;  saved w2
i3:  0                ;  saved w3
     0                ;  saved current buffer
i5:  0                ;  saved current receiver
                      ;
e.                    ; end;
\f


;
; procedure clear process(proc);
; ------------------------------------------------------------------------
;
; the specified process is cleared, i.e. name, users and reserver
; are zeroized.
;
;     call              return
;
; w0  -                 unchanged
; w1  -                 unchanged
; w2  proc              proc
; w3  link              link
;

b.  i10, j10  w.

n2:                    ; procedure clear process(proc);
     ds. w1     i1.    ; begin
     ld  w1    -100    ;
     ds  w1  x2+a11+2  ;   proc.name := 0;
     rs  w1  x2+a52    ;   proc.reserver := 0;
                       ;
j0:  am      x1        ;   users := 0;
     rs  w0  x2+a402   ;
     al  w1  x1+2      ;
     sh  w1     a403-2 ;
     jl.        j0.    ;
     dl. w1     i1.    ;
     jl      x3        ;
                       ;
     0                 ;  saved w0
i1:  0                 ;  saved w1
                       ;
e.                     ; end;
                       ;
\f


;
; procedure include all users(main, proc);
; -----------------------------------------------------------------------------
;
; all users of the main process are included as users of the specified process.
;
;       call            return
;  w0   -               destroyed
;  w1   main            main
;  w2   proc            proc
;  w3   link            destroyed
;

b.  i10,  j10  w.

n3:                    ; include all users
     rs. w3     i3.    ; begin
     al  w3     a401   ;
     al  w1  x1+a402   ;   for i:=1 step 1 until no of words do
     al  w2  x2+a402   ;   proc.userbittable(i) :=
j1:  rl  w0  x1        ;   main.userbittable(i);
     rs  w0  x2        ;
     al  w1  x1+2      ;
     al  w2  x2+2      ;
     al  w3  x3-1      ;
     se  w3     0      ;
     jl.        j1.    ;
     al  w1  x1-a48    ;
     al  w2  x2-a48    ;
     jl.       (i3.)   ;
                       ;
i3:  0                 ;   saved return;
e.                     ; end;
\f


;
; procedure decrease stopcount and deliver result_3(message);
; procedure decrease stopcount and deliver result_1(message);
; ------------------------------------------------------------------------------
;
; the stopcount of the sender of the message is decreased and the message is
; answered with result 3 or 1.
;
;         call 
;  w0     -
;  w1     -
;  w2     message
;  w3     -
;

b.  i5, j5  w.

n4:                    ; decrease stopcount and deliver result 3:
     am         1      ;
n5:  al  w0     0      ; decrease stopcount and deliver result 1:
     rs. w0     i0.    ; begin
     jl  w3     d132   ;   decrease stopcount(message);
     rl. w0     i0.    ;
     se  w0     1      ;   goto deliver result (3 or 1);
     am         g7-g5  ;
     jl         g5     ;
                       ;
i0:  0                 ;
e.                     ; end;
\f


; procedure remove_attention_buffer(proc)
; -----------------------------------------------------------------------------
;
; regretted message is called if an attention buffer exist
;
;         call             return
;  w0      -               unchanged
;  w1      -               unchanged
;  w2     terminal         unchanged
;  w3     return address   unchanged
;

b.   i5,  j5   w.

n7:  ds. w3     i3.    ; procedure remove_attention_buffer
     al  w3  x2        ; begin
     al  w2     0      ;
     rx  w2  x3+a71    ;
     se  w2     0      ;   if proc.attention_buffer <> 0 then 
     jl  w3     d75    ;      regretted_message(proc.attention_buffer);
     dl. w3     i3.    ;
     jl      x3        ;  
                       ;
i2:  0                 ;
i3:  0                 ;
e.                     ; end;
\f


;
; procedure free_process(proc);
; -----------------------------------------------------------------------------
;
; the specified process is set free i.e. kind is set to free process and
; state is set to 'free'.
;
;      call            return
;
; w0   -               unchanged
; w1   -               unchanged
; w2   proc            proc
; w3   link            destroyed
;

b.  i5,  j5  w.

n8:                      ; free_process
     rs. w0     i0.      ; begin
     al  w0     q68      ;
     rs  w0  x2+a10      ;   proc.kind := free;
     ac  w0     2.0111+1 ;
     la  w0  x2+a78      ; 
     lo. w0     i1.      ;
     hs  w0  x2+a78+1    ;   proc.state := free;
     rl. w0     i0.      ;
     jl      x3          ; 
                         ;
i0:  0                   ; save w0
i1:  l36                 ; proc state free
                         ;
e.                       ; end;
\f


;
; procedure cleanup
; -----------------------------------------------------------------------------
;
; The process complex in rc8000 concerning the controller supervised by the
; mainprocess in b19, is cleaned up, i.e. all pending messages are returned
; with result 4 and all processes for devices on the controller are removed.
;
;         call           return
;  w0     -              destroyed
;  w1     -              destroyed
;  w2     -              destroyed
;  w3     link           destroyed

b.  i10,  j10  w.

n9:                    ; begin
                       ;
     rs. w3     i3.    ;
     rl  w1     b4     ;for proc := first external, next until last external do
j2:  rl  w2  x1        ;   begin
     rl  w0  x2+a10    ;
     rl  w3  x2+a50    ;
     se  w3    (b19)   ;     if proc.main = this main and 
     jl.        j3.    ;        proc.kind <> mainkind then
     se  w0     q20    ;     begin
     sn  w0     q26    ;       <* disc, mt or ifpgsd *>
     jl.        j3.    ;
                       ;
     al  w2  x2+a54    ;
     rl  w0  x2+a10    ;       if proc.kind = terminal then
     sn  w0     q8     ;          remove_attention_buffer(proc);
     jl. w3     n7.    ;
     al  w0     0      ;
     jl. w3     n1.    ;       clear_queue(normal, proc.event_queue);
     al  w2  x2-a54    ;
     jl. w3     n2.    ;       clear_process(proc);
     jl. w3     n8.    ;       free_process();
     jl.        j4.    ;     end 
                       ;     else
j3:  se  w2    (b19)   ;     if proc = this main then
     jl.        j4.    ;     begin
     al  w0     0      ;
     al  w2  x2+a54    ;
     jl. w3     n1.    ;       clear queue(normal,this main.event queue); 
     al  w2  x2-a54+a81;
     jl. w3     n1.    ;       clear queue(normal,this main.waiting queue); 
     al  w2  x2-a81    ;
     al  w3     0      ;       this main.statistics := 0;
     ds  w0  x2+a216+2 ;
     ds  w0  x2+a218   ;     end;
                       ;
j4:  al  w1  x1+2      ;
     se  w1    (b5)    ;
     jl.        j2.    ;   end;
     jl.       (i3.)   ;
i3:  0                 ; saved link
                       ;
e.                     ; end;

\f


; procedure check_remoter(type, main, terminal)
; -----------------------------------------------------------------------------
;
; the message queue of the remoter is searched for an terminal supervisor
; message (operation = 2).
; if such a message is found the terminal is reserved and the internal is 
; returned.
;
;          call           return
; w0       att type       undefined
; w1       main           main
; w2       terminal       terminal
; w3       link           internal_supervisor (reserver) or 0
;

b.  i10,  j10   w.

n12: ds. w3     i3.    ; begin
     ds. w1     i1.    ;
     al  w0     0      ;
     rs. w0     i4.    ;   internal_supervisor := 0;
     rl  w3    (b3)    ;   
     al  w0  x3+a54    ;   message:= remoter.eventq.first;
     rl  w3  x3+a54    ;   while message <> none do
     rs. w0     i6.    ;   begin
j3:  sn. w3    (i6.)   ;   
     jl.        j6.    ;
     rs. w3     i5.    ;
     zl  w0  x3+a150+0 ;     if message.operation = wait for connect then
     se  w0     2      ;     begin
     jl.        j5.    ;
     zl  w0  x3+a150+1 ;       if (message.mode = all connections) or
     so  w0     2.1    ;          (message.mode = specific main and
     jl.        j4.    ;           message.mainaddress = this main) then
     rl  w0  x3+a151   ;       begin
     se. w0    (i1.)   ;
     jl.        j5.    ;
j4:  rl  w1  x3+a142   ;         sender:= message.sender;
     rl  w0  x1+a10    ;         if sender.kind<>internal then
     se  w0     0      ;         sender:=sender.main; <*pseudo proc*>
     rl  w1  x1+a50    ;
     rl. w0     i0.    ;              
     se  w0     1<0    ;         if type = connected then
     jl.        j6.    ;         begin
     rs. w1     i4.    ;           internal_supervisor := sender;
     jl  w3     d125   ;           include_reserver(sender, proc);
                       ;         end;
                       ;       end;
                       ;     end;
j5:  rl. w3     i5.    ;
     rl  w3  x3+a140   ;     message:=message.next;
     jl.        j3.    ;   end;
j6:                    ; done:
     dl. w2     i2.    ;   <* restore and return *>
     rl. w0     i0.    ;
     rl. w3     i4.    ;   <* return reserving process *>
     jl.       (i3.)   ;
                       ;
i0:  0                 ; save w0  att_type
i1:  0                 ;      w1  main
i2:  0                 ;      w2  terminal
i3:  0                 ;      w3  link
i4:  0                 ; internal_supervisor or 0
i5:  0                 ; remoter message
i6:  0                 ; remoter queue
e.                     ; end;

\f


; procedure send_main_message(receiver, message);
; ----------------------------------------------------------------------------
;
; send the specified message to the receiver.
;
;    call        return
; w0 -           destroyed
; w1 receiver    destroyed
; w2 message     destroyed
; w3 link        destroyed
;

b.  i5, j5  w.

i3:  0                 ; saved return
i4:  0,0,0,0,0         ; namearea and nta

n13:                   ; send_main_message
     rs. w3     i3.    ; begin
     dl  w0  x1+a11+2  ;   namearea := receiver.name;
     ds. w0     i4.+2  ;
     dl  w0  x1+a11+6  ;
     ds. w0     i4.+6  ;
     al. w3     i4.    ;
     al  w1  x2        ;   
     jd         1<11+16;   send message(message, receiver.name);
     jl.       (i3.)   ; 
e.                     ; end;
\f


; procedure send_remoter_att(type, main, terminal)
; -----------------------------------------------------------------------------
;
; an attention message is sent to the internal process which has reserved the
; terminal process.
; the attention message has the following format:
;
;    sender:     terminal or main
;    receiver:   sender of message to remoter
;    + 0         0       (attention)
;    + 2         state   (1<0: terminal connected, 1<1: terminal disconnected)
;    + 4         terminal address
;    + 6- +12    terminal name  
;
; if state = disconnected mainproc is inserted as sender of att message
;
;          call           return
; w0       att type       att type
; w1       main           main
; w2       terminal       terminal
; w3       link           undefined
;

b.  i10,  j10   w.

n14: ds. w3     i3.    ; begin
     ds. w1     i1.    ;
     al  w3     0      ;   att_mess.mess_0 := 0;
     ds  w0     g21    ;   att-mess.status := type;
     rs  w2     g22    ;   att-mess.terminal := terminal 
     dl  w0  x2+a11+2  ;   att-mess.name := terminal.name
     ds  w0     g23+2  ;         
     dl  w0  x2+a11+6  ;
     ds  w0     g23+6  ;
     rl  w3  x2+a74    ;   receiver := terminal.att_receiver;
     rl. w2     i2.    ;   if type = disconnect then 
     rl. w1     i0.    ;      sender := this main
     sn  w1     1<1    ;   else
     rl. w2     i1.    ;      sender := terminal;
     al  w1     g20    ;
     jd         1<11+17;   send_att_message(message, sender, receiver);
     am.       (i2.)   ;
     rs  w2    +a71    ;   terminal.att_buffer := buffer;
     rl. w0     i0.    ;
     dl. w2     i2.    ;   <* restore and return *>
     jl.       (i3.)   ;
                       ;
i0:  0                 ; save w0  att_type
i1:  0                 ;      w1  main
i2:  0                 ;      w2  terminal
i3:  0                 ;      w3  link
e.                     ; end;

e.                     ; end of main driver