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

⟦96b9fb85c⟧ TextFile

    Length: 121344 (0x1da00)
    Types: TextFile
    Names: »mondisc«

Derivation

└─⟦621cfb9a2⟧ Bits:30002817 RC8000 Dump tape fra HCØ.  Detaljer om "HC8000" projekt.
    └─⟦0364f57e3⟧ 
        └─⟦87223b8a0⟧ »kkrcmonfil« 
└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ.
    └─⟦b2ec5d50f⟧ 
        └─⟦87223b8a0⟧ »kkrcmonfil« 
            └─⟦this⟧ 

TextFile

\f


m.                mondisc - disc driver

b.i30 w.
i0=80 12 10, i1=14 00 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 = 10                ; 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  : bz  w0  x1+p14    ; action 7:
      al. w3     c4.    ;   startaddr:= 1st sense.channel pg;
      se  w0     0      ;   if initdisc.curr receiver <> 0
      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: al  w0     1      ; error: c. w1 = curr receiver;
      hs  w0  x1+p14    ;   initdisc.curr receiver:= 1;
     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
;                              action 2                      vacant
i35: 2.             1 1 1 1 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 , i36: 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 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.        j96.   ;
      jl.        j96.   ;
      jl.        j96.   ;   if tries <= 3 then goto start
      jl.        j55.   ;   else goto deliver error;

; 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

\f

▶EOF◀