|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 235008 (0x39600) Types: TextFile Names: »mdisc «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer └─⟦2ba378e4a⟧ └─⟦this⟧ »mdisc «
\f m. mondisc - disc driver 17.0 beta ;-------------------------------------------------------------------------- ; REVISION HISTORY ;-------------------------------------------------------------------------- ; DATE TIME OR DESCRIPTION ; RELEASE ;-------------------------------------------------------------------------- ;88.03.24 14.1A HSI start of description ; regret csp-att mess when ifp is reset ; connect csp-terminals and -printers: set kind ; ifp-mess disconnect: dont disconnect the mainprocess ; ifp-mess setmask: dont send operation to ifp ; ifp-mess copy: check that w1 is a legal address ; ifp-interrupt disconnect csp-terminal: send att-mess to user of remoter ; ifp-interrupt csp-attention: if terminal reserved then ignore ; ; ----- " -------- " --------: if att-receiver is unknown ; then send 6<12+1 operation to adp ; ;88.04.19 15.0 TSH mainprocess driver/interrupt rewritten for RC9000. ;88.05.04 10.0 KAK power interrupt at ifpmain cause return at once to ; driverproc's wait event ;88.05.16 13.21 kak reset ifp/ida re-inserted with a few modification ;88.06.20 10.15 TSH sspmain included ;88 06 24 20.06 hsi max transfer in ifp devices set to 32000 ;88 08 08 14.17 kak sense operation to ifpmain inserted ;88 08 16 14.43 hsi timeout on main operations ;88 09 05 12.47 hsi ifp mess: connect: start search for free linkproc ; from the highest devicenumber ; csp-term: set base on link when created. ;88 09 14 14.19 hsi monitor must send a hard reset not a soft ;88 09 15 15.14 IFP/ADP: change default timeout to 60 sec. ;88 11 24 13.31 kak - timeout value inserted in sense message.mess_3 ;89 01 30 07.51 kak tape state inserted after answer create link ;89 03 08 09.33 kak at interrupt received, the queue of waiting operation are checked ; before return to driverproc.wait_event ; if the interrupt is delivered from a IOC/LAN controller ;89 03 15 15.28 kak decrease no_of_outstanding at commen end in driverprocs nterrupt procedure ; two new testpoint inserted in timeout and power interrup;89 03 17 11.20 kak no_of_outstanding is set to one after reset, it will be decreased at commen end ;89 03 26 10 21 kak when driverproc receive an attention message from a controller, it is checked that ; driverproc.bufferclaim > 5 before the message is sent to the receiver, ; otherwise only the answer to the controller is sent ;-------------------------------------------------------------------------- ; START OF RELEASE 16.0 ;89 04 11 13.38 hsi unlink logical disk not allowed if part of logical vol. ;89 04 26 12.12 hsi check name in createlink from lan (correction from 15.1) ;89 05 02 14.48 hsi insert procfunc as user of new terminal link (15.1) ;-------------------------------------------------------------------------- ;90 05 30 11.40 kak START OF RELEASE 17.0 ;90 05 30 11.40 kak prepare dump excluded ;90 08 09 13.12 kak the two attention events testbuffer full and error correction performed included as legal events ;90 10 12 1.14 kak when excluding preparedump set timeout(ida/ifp) was excluded too this is corrected b.i30 w. i0=90 08 09 i1=13 14 00 ; ; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime; c.i0-a133 c.i0-a133-1, a133=i0, a134=i1, z. c.i1-a134-1, a134=i1, z. z. i10=i0, i20=i1 i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000 i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000 i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100 i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10 i2: <: date :> (:i15+48:)<16+(:i14+48:)<8+46 (:i13+48:)<16+(:i12+48:)<8+46 (:i11+48:)<16+(:i10+48:)<8+32 (:i25+48:)<16+(:i24+48:)<8+46 (:i23+48:)<16+(:i22+48:)<8+46 (:i21+48:)<16+(:i20+48:)<8+ 0 i3: al. w0 i2. ; write date: rs w0 x2+0 ; first free:=start(text); al w2 0 ; jl x3 ; return to slang(status ok); jl. i3. ; e. j. ; --------------------------------------------------------------- ; d i s c d r i v e r c o d e ; (dsc 801) ; ; a r e a p r o c e s s c o d e ; --------------------------------------------------------------- ; this section contains the code executed by driverproc for pro- ; cessing messages to an area process or a disc driver. ; ; messages have the following format: ; ; sense 0<12 + mode initialize 2<12 ; irrel no of heads ; irrel disp. on odd cyl. ; irrel disctype ; ; clean track 6<12 + mode position 8<12 + mode ; irrel irrel ; irrel irrel ; segment no segment no ; ; read 3<12 + mode write 5<12 + mode ; first address first address ; last address last address ; first segment no first segment no ; ; get statistics 9<12 ; first address ; last address ; irrel ; ; set regretted 10<12 continue 12<12 ; (used by testprograms) ; irrel irrel ; irrel irrel ; irrel irrel ; mode consists of a sum of one or more of following values: ; ; transput mode 0 transput of data ; 1 transput of address marks ; error recovery 0 repeat at error ; 2 do not repeat at error ; requeue 4 answer message after best repetitions ; 0 requeue message after best repetitions ; and try later again ; read after write 0 no read after write ; 8 read after write mode ; ; disctype 0 = dsm801, disctype 1 = dsm802 with variable offset. ; ; the answer to a message has the following format: ; ; statusword ; 0 or number of bytes transferred ; 0 or number of chars transferred ; i/o result, from start i/o ; current status from controller ; event status from controller ; technical status from controller ; ; the following bits may be set in a statusword: ; ; bit 0 intervention, no disc driver at area process message ; bit 1 parity , event status bit 1 or 4 (data-, hard err.) ; bit 2 sync.error , event status bit 5 (position error) ; bit 3 data overrun, event status bit 3 (data overrun) ; bit 4 blocklength , buffer too small at get statistics ; bit 5 end medium , 1st segm outside or curr stat b5 (seek err) ; bit 11 discerror , requeue mode = 4 and repetitions < max ; ; the message may be sent to an area process, a logical disc ; driver (one physical disc may be split into more logical devi- ; ces) or to a physical disc driver. in either case the message is ; linked to the physical driver unless it concerns an area on a ; remote disc, in which case the code for processing such messages ; is entered. ; ; initialize, clean track, and write addr mark can only be sent to ; a reserved physical disc driver. get statistics can only be sent ; to a disc driver. ; ; segment numbers in message correspond to absolute segments ; when sent to a physical driver, to segmentno relative to start ; of logical disc when sent to a logical driver, and relative ; to areastart when sent to an area process. ; ; before linking the message to the physical disc driver it is ; reformatted and will contain sufficient information for exe- ; cuting the first part of the transfer corresponding to the ; largest number of consecutive segments starting at first seg- ; ment wanted. the buffer is updated at each portion of conse- ; cutive segments transferred until the entire number of segments ; have been transferred. ; ; when the message is linked to the physical driver it is not ; possible to see if it was sent to an area process or directly ; to a driver. however, when sent to a driver, all segments ; wanted can be processed in the first transfer, whereas an ; area process message may be processed in more transfers as ; the slices of an area need not be consecutive. ; ; the driver will automatically examine the number of heads on ; the disc, the displacement of sector zero on odd cylinders, ; and the disctype (dsm801-2) when the first message (after ; intervention) is received unless this first message is the ; initialize message. \f ; pej 04.10.77 disc driver, contents ; c o n t e n t s ; --------------------------------------------------------------- ; definitions ; ----------- ; ; constant definitions ; format of transformed message ; process description format ; ; main routines ( in sequential order) ; ------------- ; ; message received by area process ; message received by disc driver ; link message to disc driver ; message not accepted ; ; process next message ; start device ; ; interrupt received ; successful transfer ; deliver answer routines ; ; error routine ; ; procedures (in alphabetical order) ; ---------- ; ; check area process ; check message ; clean ; compound status ; copy statistics ; correct data ; initialize disc ; prepare consecutive segments ; setup channel program and start ; set errorkind ; set result and status ; transform first segment ; update buf ; update buf on error ; update on corrected error ; update retryinformation b. j170, m10, p50, q70 ; disc driver and area process \f ; pej 30.09.77 disc driver, constant definitions ; c o n s t a n t d e f i n i t i o n s ; --------------------------------------------------------------- ; operation codes, control = even, transput = odd codes. if the ; codes are changed, also a table in proc setup channel program ; and start must be changed as well as error segment table ; updating in action 7a of error actions and proc. update buf. q30 = 0 ; sense q31 = 2 ; initialize q32 = 3 ; read q33 = 5 ; write q34 = 6 ; clean track q35 = 8 ; position q36 = 9 ; get statistics q39 = 10 ; set regretted q38 = 12 ; continue ; mode codes q40 = 1 ; transput mode, = addr mark mode q41 = 1 < 1 ; error recovery, = no repetition q42 = 1 < 2 ; requeue, = do not reque q43 = 1 < 3 ; read after write, = true ; segment units q50 = 8 ; no of bytes per addr mark q51 = 12 ; - - chars - - - q52 = 512 ; - - bytes - data segment q53 = 768 ; - - chars - - - ; process kinds q60 = 84 ; subproc q61 = 62 ; disc driver ; power restart parameters (time units: 0.1 msec) q10 = 1 * 1000 * 10 ; time between sense in power rest. loop q11 = 40 * 1000 * 10 ; maxtime to become ready at power rest. q12 = q10 ; - - - - - - down q13 = q11 / q10 + 1 ; no of times to sense at power restart q14 = q12 / q10 + 1 ; no of times to sense at power down q15 = 500 ; no of times to repeat at data overrun ; no of times to repeat at error ; repeats = 3 ; not defined as a constant due to imple- ; mentation details. to change strategy, ; correct proc update retryinformation ; and action 8a and 10 in error routine. ; assembly options q0 = (:a80>1a.1:)-1 ; disc driver included, 0=yes, -1=no q1 = (:a82>1a.1:)-1 ; statistics included, 0=yes, -1=no q2 = 10 ; no of entries in error segment table \f ; pej 04.10.77 disc driver, format of transformed message ; f o r m a t o f t r a n s f o r m e d m e s s a g e ; --------------------------------------------------------------- ; format of messagebuffer when linked to driver (after checking) m0 = a145, m1 = m0+1 ; operation , mode m2 = m1+1, ; first address m3 = m2+2 ; last address m4 = m3+2 ; first segment m5 = m4+2, m6 = m5+1 ; no of segments , retryinformation m7 = m6+1 ; next segment m8 = m7+2, m9 = m8+1 ; segments wanted, remaining segments m10 = m9+1 ; device ; operation : not changed ; mode : not changed ; firstaddr : in curr transfer ; lastaddr : not changed, used by start i/o for checking ; first segm : in curr transfer, rel. to start of disc ; no of segms: in curr transfer ; retryinf : at read data, read addr mark: ; modeindex<8 + offsetindex<3 + tries ; modeindex : index to modetable ; offsetindex: index to offset table ; tries : no of tries at given modeindex ; and offset index ; at read after write: ; writetries<3 + readtries ; writetries: no of times write has been tried ; readtries : no of times read has been tried ; after a write ; at other operations: ; no of times the transfer has been tried ; next segm : will be first segment in next transfer ; segms want : total no of segments wanted by sender ; rem segms : no of segments remaining to be transferred ; device : addr of disc driver containing sliceinformation ; and physical segment no of first segment \f ; pej 04.10.77 disc driver, proc descr format ; p r o c e s s d e s c r i p t i o n f o r m a t ; --------------------------------------------------------------- ; variables required for physical and logical disc. ; a250 ; driver descr addr ; a48 ; interval ; a49 ; - ; a10 ; kind ; a11 ; name p2 = a50 ; mainproc, phys.=0, log.=addr of physical ; a52 ; reserver ; a53 ; users ; a54 ; next message ; a55 ; last message ; a56 ; regretted, often called interrupt address ; a70 ; not used p0 = a71 ; chaintable p1 = a72 ; slicelength p3 = p1+2 ; first segment, phys.=0, log.= segm no of log. 0 p4 = p3+2 ; no of segments, phys.=on disc, log.=on log. disc ; disc characteristics (only required for physical disc). p6 = p4+2 ; no of segments per track p7 = p6+2 ; flags, used in address marks p8 = p7+2 ; no of segments per cylinder (set by driver) p10 = p8 ; cylinder, used during define disc p9 = p8+2 ; displ. of sector 0 on odd cyl. (set by driver) p11 = p9 ; head, used during define disc p5 = p9+2 ; disctype, 0=dsm801, 1=dsm802 (var.offset) ; variables concerning state of disc (only physical disc). p12 = p5+2 ;state, 0=after intervention, 1=defining disc, ; 2=ready p13 = p12+2 ; transfer state, kind of transfer in progress ; bit 0 = idle (initial state) ; 1 = define disc ; 2 = power restart ; 3 = sense ; 4 = position ; 5 = clean track ; 6 = read data ; 7 = read addr mark ; 8 = write data ; 9 = write addr mark ; 10 = read after write data ; 11 = read after write addr mark p14 = p13+2 ; initdisc, 1=init at next start, 0=no p15 = p14+1 ; retryinformation, used at driver initiated ; transfers; see m6 of message buffer ; areas used by channelprograms (only physical disc). p16 = p15+1 ; statusarea1, statusarea for first sense ; +0 : channel program counter ; +2 : remaining bytecount ; +4 : current status ; +6 : event status ; +8 : last read addr mark (4 words) ; +16: ecc, error correction information (2 words) ; +20: technical status p18 = p16+22 ; statusarea2, statusarea for second sense, for- ; matted as statusarea1 p22 = p18+8 ; addr mark, input area at define disc (4 words) p36 = p18+16 ; actionkey, used in error actions p37 = p18+18 ; actionindex, used in error actions p38 = p18+20 ; write ok, used at read after write error p20 = p18+22 ; seek parameter ; +0: cylinder<8 + head ; +2: sector<16 + flags p21 = p20+4 ; setmode parameter, bit16-17:strobe, ; bit18-19:offset, bit20-23:offset magnitude ; (set to zero if strobe-offset not used) ; other variables (only physical disc). p31 = p21+2 ; +0: curr status (sum of all statusareas) ; +2: event status (- - - - ) p33 = p31+4 ; technical status (- - - - ) p34 = p33+2 ; compound status, formed from p31,p32,i/o result p35 = p34+2 ; segment unit in curr transfer: ; +0: bytes per segment ; +2: chars per segment ; statistical information (only physical disc). p40 = p35+4 ; no of transfers p41 = p40+2 ; no of transfers not successful in first attempt ; (intervention, power restart, power down, ; write protect are not counted) p42 = p41+2 ; no of errors corrected by ecc without repetition p43 = p42+2 ; no of errors corrected within 3 retries ; strobe offset table, no of errors corrected by: p44 = p43+2 ; strobe 0 & offset n , strobe 0 & offset p ; , strobe l & offset 0 ; strobe l & offset n , strobe l & offset p ; , strobe e & offset 0 ; strobe e & offset n , strobe e & offset p ; (e=early, l=late, p=positive, n=negative) p45 = p44+10 ; no of errors corrected by offset magnitude -, 1 ; 2, 3 ; 4, 5 ; . . ; . . ; 14, 15 ; (first byte not used, magnitude 0 unexistent) p47 = p45+16 ; counters for compound status bit 0, 1 ; 2, 3 ; . . ; . . ; 22,23 p48 = p47+24 ; counters for technic. status bit 0, 1 ; 2, 3 ; . . ; . . ; 22,23 p46 = p48+24 ; table of error segments, an entry contains ; +0: segment no. (physical) ; +2: no of reads ok +3: no of reads with rep. ; +4: no of writes ok +5: no of writes with rep. p50=p46+q2*6-p40; size of statistics in bytes ; ***** please note that: ; - declarations of p10 and p8 are equal. ; - declarations of p11 and p9 are equal. ; - p22, p36, p37, and p38 are declared inside p18. ; conflicts in use will not occur as overlapping locations ; are not used simultanously. \f ; pej 21.09.77 area process, message received ; m e s s a g e r e c e i v e d b y a r e a p r o c e s s ; --------------------------------------------------------------- m. area process ; this routine is entered when driverproc receives a message for ; an area process. curr receiver (b19) = area process descr. b. i10 w. ; block containing area proc driver ; check if sender ok and if specified operation legal. h5 : bz w0 x2+m0 ; area process: c. w2 = curr buf; sn w0 q33 ; if operation.curr buf = output am g15-g14; then check reservation jl w3 g14 ; else check user; dl. w1 i0. ; jl w3 g16 ; check operation(oper mask,mode mask); ; check the area process. jl. w3 j1. ; check area process; jl. j37. ; if area segms < 0 then goto outside; jl. j35. ; if no doc then goto doc not found; ; now curr receiver = disc driver (physical or logical). check ; if the disc is a remote disc or that disc driver included. rs w1 x2+m7 ; save area process addr in curr buf; rl w0 x3+a10 ; la w0 g50 ; se w0 q60 ; if kind.curr receiver = subproc then jl. i10. ; begin c. remote disc; rs w1 x3+a56 ; interrupt addr.curr rec:= area proc; jl. (2), h84; goto subproc driver; i10 : ; end; c. -q0-1 ; if disc driver not included jl g3 ; then goto result 5; c. unknown; z. ; c. q0 ; ; check contents of the message rl w0 x1+a61 ; top:= no of segments.area proc; al w1 q52 ; bytes:= no of bytes in data segments; jl. w3 j2. ; check message(top,bytes); jl. j37. ; if outside then goto outside; ; convert first segment into a segment no relative to discstart ; and prepare first portion of consecutive segments bz w0 x2+m0 ; sn w0 q30 ; if operation.curr buf <> sense then jl. j30. ; begin rl w1 x2+m7 ; area proc:= saved area proc; jl. w3 j3. ; transform first segm(area proc); bz w0 x2+m0 ; se w0 q35 ; if operation.curr buf <> position jl. w3 j4. ; then prepare consec segms(curr rec); ; end; jl. j30. ; goto link message; z. ; ; legal mode combinations: ; read after write ; requeue ; error recovery i1 = a0>(: q41:) i2 = a0>(: q42 :) i3 = a0>(: q42+q41:) i4 = a0>(:q43 :) i5 = a0>(:q43 +q41:) i6 = a0>(:q43+q42 :) i7 = a0>(:q43+q42 :) ; oper and mode masks for area process message a0>q30+a0>q32+a0>q33+a0>q35 ; oper mask: sense, read, write, pos. i0 : a0>0+i1+i2+i3+i4+i5+i6+i7 ; mode mask: no addr mark transput e. ; end of area process driver \f ; pej 21.09.77 disc driver, message received ; m e s s a g e r e c e i v e d b y d i s c d r i v e r ; --------------------------------------------------------------- b. i50 w. ; block including disc driver h6 : ; ; c. q0 ; m. dsc 801 ; this routine is entered when driverproc receives a message for ; a disc driver. curr receiver (b19) = (logical or physical) disc ; driver process description. ; check if sender ok and if specified operation legal bz w0 x2+m0 ; disc driver: c. w2 = curr buf; sn w0 q33 ; if operation.curr buf = output jl. j20. ; se w0 q31 ; or operation.curr buf = initialize sn w0 q34 ; or operation.curr buf = clean track j20 : am g15-g14; then check reservation jl w3 g14 ; else check user; dl. w1 i0. ; use oper/mode mask for phys. driver; am (b19) ; rl w3 p2 ; sn w3 0 ; if mainproc.curr receiver <> 0 then jl. j25. ; begin c. logical disc driver; rl. w0 i1. ; use oper mask for logical driver; bz w3 x2+m0 ; if operation.curr buf = output sn w3 q33 ; then use mode mask for output; rl. w1 i2. ; end; j25 : jl w3 g16 ; check operation(oper mask,mode mask); ; check if message is continnue. ; such a message should not be linked up to the physical driver. ; if regretted is set by the command "set regretted " the message ; is answered ok and the physical disc is started in rutine process ; next message. otherwise the message is answered with result 3 and ; and no action is performed. bz w3 x2+m0 ; if operation.curr buf = continue then se w3 q38 ; begin jl. j28. ; if regretted not set by "set regret" am (b19) ; ( regretted.curr receiver=3) rl w1 +a56 ; then deliver result 3 else se w1 3 ; deliver result 1 and continue with jl g5 ; process next message jl. j101. ; end ; check contents of the message j28 : bz w0 x2+m1 ; al w1 q52 ; if transput mode.curr buf = 0 sz w0 q40 ; then bytes:= bytes in data segments al w1 q50 ; else bytes:= bytes in addr marks; am (b19) ; rl w0 p4 ; top:= no of segments.curr receiver; jl. w3 j2. ; check message(top,bytes); jl. j37. ; if outside then goto outside; jl. j30. ; goto link message; ; legal mode combinations: ; read after write ; requeue ; error recovery ; transput of addr marks i3 = a0>(: q40:) i4 = a0>(: q41 :) i5 = a0>(: q41+q40:) i6 = a0>(: q42 :) i7 = a0>(: q42 +q40:) i8 = a0>(: q42+q41 :) i9 = a0>(: q42+q41+q40:) i10 = a0>(:q43 :) i11 = a0>(:q43 +q40:) i12 = a0>(:q43 +q41 :) i13 = a0>(:q43 +q41+q40:) i14 = a0>(:q43+q42 :) i15 = a0>(:q43+q42 +q40:) i16 = a0>(:q43+q42+q41 :) i17 = a0>(:q43+q42+q41+q40:) ; get statistics operation only allowed if statistics wanted c. q1 ; i18 = a0>q36 ; statistics wanted z. ; c. -q1-1 ; i18 = 0 ; statistics not wanted z. ; ; oper and mode masks for disc driver message ; op: sense init. read write clean pos. stat. regr. cont. i1 : a0>q30 +a0>q32+a0>q33 +a0>q35+i18; logical a0>q30+a0>q31+a0>q32+a0>q33+a0>q34+a0>q35+i18+a0>q39+a0>q38; physical ; physical driver modes (all): i0 : a0>0+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15+i16+i17 ; logical driver modes at output (all except addrmarks): i2 : a0>0 +i4 +i6 +i8 +i10 +i12 +i14 +i16 \f \f ; pej 22.09.77 disc driver, link message ; l i n k m e s s a g e t o d i s c d r i v e r ; --------------------------------------------------------------- ; this routine is entered when a message received by an area ; process or a disc driver has been checked. the message is ; linked to the physical disc driver and curr receiver will ; be changed accordingly. ; ; please note that the buffer is not claimed by the driver during ; the processing. the claiming takes place when the answer is re- ; turned, see procedure deliver result. ; change curr receiver into physical driver. j30 : rl w1 b19 ; link message: c. w2 = curr buf; rs w1 x2+m10 ; device.curr buf:= curr receiver; rl w1 x1+p2 ; if mainproc.curr receiver <> 0 then sn w1 0 ; begin c. curr rec = logical driver; jl. j32. ; curr receiver:= mainproc.curr rec; rs w1 b19 ; end; ; link the message by calling procedure link operation which ; will continue in case the driver is idle or otherwise will ; jump to waitnext in driver proc. j32 : jl w3 g17 ; link operation(curr buf); jl. j50. ; goto process next message; z. ; \f ; pej 22.09.77 disc driver, message not accepted ; m e s s a g e n o t a c c e p t e d ; --------------------------------------------------------------- ; the routines are entered when a message received by an area ; process or a disc driver can not be accepted. the message ; is answered and continuation takes place at waitnext in driver ; proc. j35 : rl w0 g49 ; document not found: jl. j41. ; status:= bit 0; c. intervention; j37 : rl w0 g62 ; outside: ; status:= bit 5; c. end medium; j41 : rs w0 g20 ; status.i/o answer:= status; c. w0; ld w1 -100 ; bytes.i/o answer:= ds w1 g22 ; chars.i/o answer:= 0; jl g7 ; goto result 1; c. cont. at waitnext; \f ; pej 20.09.77 disc driver, check area process ; procedure check area process ; --------------------------------------------------------------- ; ; the procedure performs: ; - checks if no of segments.curr receiver (= area proc) >= 0. ; - searches for document.curr receiver if device addr.curr ; receiver = 0 and initializes device addr.curr receiver. ; - changes curr receiver to device addr.curr receiver . ; (i.e. to disc driver). ; ; registers: call exit ; w0 destroyed ; w1 area proc (= curr receiver at call) ; w2 curr buf ; w3 link curr receiver ; ; entry : j1 ; ; return : link+0: no of segments.area proc < 0 ; link+2: document not found ; link+4: normal return b. i2 w. j1 : rs. w3 i0. ; check area proc: save link; rl w1 b19 ; rl w3 x1+a61 ; sh w3 -1 ; if no of segms.curr receiver < 0 jl. (i0.) ; then outside return; c. link; rl w3 x1+a50 ; se w3 0 ; if device addr.curr receiver = 0 then jl. i1. ; begin al w2 x1+a62 ; name:= document.curr receiver; dl w1 d72 ; base:= max interval; jl w3 d71 ; search name(name,entry,base); rl w1 b19 ; sn w3 (b7) ; if entry = nametable end jl. i2. ; then goto doc not found return; rl w3 x3+0 ; device addr.curr receiver:= rs w3 x1+a50 ; core(entry); i1 : rl w2 b18 ; end; rs w3 b19 ; curr receiver:=device addr.curr receiver; am. (i0.) ; jl 4 ; normal return; c. link+4; i2 : am. (i0.) ; doc not found return; jl 2 ; goto link+2; ; variables i0 : 0 ; saved link e. c. q0 ; \f ; pej 21.09.77 disc driver, check message ; procedure check message(top segment,bytes per segment) ; --------------------------------------------------------------- ; top segment : highest allowed segment no + 1. ; bytes per segment: no of bytes to be transferred per segment. ; ; the procedure performs: ; - zeroizes retryinformation.curr buf. ; - checks that 0 <= first segment.curr buf < top segment (not ; for sense, initialize, get statistics). ; - sets segms wanted.curr buf and remaining segms.curr buf ; and no of segments.curr buf to: ; (lastaddr.curr buf + 2 - firstaddr.curr buf)/bytes per segm. ; (undefined for sense, initialize, get statistics). ; ; registers: call exit ; w0 top segment destroyed ; w1 bytes per segm. unchanged ; w2 curr buf unchanged ; w3 link destroyed ; ; entry : j2 ; ; return : link+0: first segment.curr buf outside limits ; link+2: normal return b. i2 w. j2 : rs. w3 i0. ; check message: save link; al w3 0 ; hs w3 x2+m6 ; retryinformation.curr buf:= 0; rl w3 x2+m4 ; sl w3 0 ; if first segment.curr buf >= 0 sl w3 (0) ; and first segm.curr buf < top segment jl. i2. ; then rl w3 x2+m3 ; begin al w3 x3+2 ; segments wanted:= ws w3 x2+m2 ; (lastaddr.curr buf + 2 al w2 0 ; - first addr.curr buf) wd w3 2 ; / bytes per segment; rl w2 b18 ; segments possible:= ws w0 x2+m4 ; top segment - first segm.curr buf; sh w0 x3+0 ; rl w3 0 ; s:= min(segms wanted,segms poss.); hs w3 x2+m5 ; no of segments.curr buf:= hs w3 x2+m8 ; segments wanted.curr buf:= hs w3 x2+m9 ; remaining segments.curr buf:= s; i1 : am. (i0.) ; normal: normal return; c. link+2; jl 2 ; end i2 : bz w3 x2+m0 ; else se w3 q39 ; if operation.curr = set regret or sn w3 q30 ; operation.curr buf = sense jl. i1. ; se w3 q31 ; or operation.curr buf = initialize sn w3 q36 ; or operation.curr buf = get statist. jl. i1. ; then goto normal jl. (i0.) ; else outside return; c. link+0; ; variables i0 : 0 ; e. \f ; pej 21.09.77 disc driver, transform first segment ; procedure transform first segment(area process) ; --------------------------------------------------------------- ; area process: addr of area proc which received curr buf. ; ; the procedure performs: ; - transforms first segment.buf from being a segment no relative ; to bs-area start into being a segment no relative to start ; of (physical or logical) disc. ; ; registers: call exit ; w0 destroyed ; w1 area process curr receiver ; w2 curr buf unchanged ; w3 link destroyed ; ; entry : j3 ; ; return : link+0 b. i0 w. j3 : rs. w3 i0. ; transform first segment: save link; al w3 0 ; rl w0 x2+m4 ; no of slices:= am (b19) ; first segment.curr buf wd w0 p1 ; / slicelength.curr receiver; rs w3 x2+m4 ; first segment.curr buf:= remainder; rl w2 x1+a60 ; index:= rl w1 b19 ; first slice.area proc wa w2 x1+p0 ; + chaintable.curr receiver; jl w3 d74 ; follow chain(noof slices,index,slice); ws w2 x1+p0 ; slice:= slice - chaintable.curr rec; al w0 x2+0 ; rl w2 b18 ; wm w0 x1+p1 ; first segment.curr buf:= wa w0 x2+m4 ; slice * slicelength.curr receiver rs w0 x2+m4 ; + first segment.curr buf; jl. (i0.) ; return; ; variables i0 : 0 ; saved link e. \f ; pej 21.09.77 disc driver, prepare consecutive segments ; procedure prepare consecutive segments(proc) ; --------------------------------------------------------------- ; proc: addr of disc proc descr containing sliceinformation. ; ; the procedure performs: ; - initializes no of segments.curr buf by the largest possible ; number of adjecent segments which can be transferred from ; first segment.curr buf and on. ; - sets next segment.curr buf to a value which may be used as ; first segment in the next call of this procedure. ; ; note: must only be called in connection with message origi- ; nating from an area process. ; ; registers: call exit ; w0 destroyed ; w1 proc unchanged ; w2 curr buf unchanged ; w3 link destroyed ; ; entry : j4 ; ; return : link+0 b. i3 w. j4 : rs. w3 i0. ; prepare consecutive segments: bz w3 x2+m9 ; save link; rs. w3 i1. ; remaining:= remaining segms.curr buf; rl w3 x2+m4 ; al w2 0 ; slice:= first segment.curr buf wd w3 x1+p1 ; / slicelength.proc wa w3 x1+p0 ; + chaintable.proc; ws w2 x1+p1 ; segments possible:= slicelength.proc ac w0 x2+0 ; - first segm.curr buf mod slicel.proc; i2 : bl w2 x3+0 ; while core(slice) = 1 sn w2 1 ; and segments possible < remaining do sl. w0 (i1.) ; begin jl. i3. ; slice:= slice + 1; al w3 x3+1 ; segments possible:= wa w0 x1+p1 ; segments possible+slicelength.proc; jl. i2. ; end; i3 : ba w3 x3+0 ; ws w3 x1+p0 ; next segment.curr buf:= wm w3 x1+p1 ; (slice + core(slice) - chaintab.proc) rl w2 b18 ; * slicelength.proc; rs w3 x2+m7 ; sl. w0 (i1.) ; if segments possible >= remaining rl. w0 i1. ; then segments possible:= remaining; hs w0 x2+m5 ; no of segms.curr buf:= segms possible; jl. (i0.) ; return; ; variables i0 : 0 ; saved link i1 : 0 ; remaining (from rem.segms.curr buf) e. \f ; pej 04.10.77 disc driver, proc copy statistics ; procedure copy statistics(result,words) ; --------------------------------------------------------------- ; result: see proc copy to buffer. ; words : no of words copied. ; ; the procedure performs: ; - copies the number of words specified in curr buf from ; statistics of curr receiver. ; - zeroizes the statistics area if copy ok. ; ; registers: call exit ; w0 result if result <> ok return ; w1 curr receiver destroyed ; w2 curr buf curr receiver if normal return ; w3 link words if normal return ; ; entry : j5 ; ; return : link+0: not enough room in buf for statistics ; link+2: result <> ok ; link+4: normal return c. q1 b. i8 w. j5 : al w0 2 ; copy statistics: wa w0 x2+m3 ; bytes:= 2 + lastaddr.curr buf ws w0 x2+m2 ; - firstaddr.curr buf; la w0 g50 ; make bytes even; sl w0 p50 ; if bytes < length of statistics jl. i2. ; jl x3+0 ; then no room return; i2 : al w3 x3+2 ; link:= link + 2; rs. w3 i0. ; save link; rs. w0 i1. ; save bytes; al w1 x1+p40 ; first:= addr of statistics.curr rec; rs. w1 i6. ; wa w1 0 ; al w1 x1-2 ; rs. w1 i7. ; al. w1 i5. ; jd 1<11+84 ; se w0 0 ; if result <> 0 jl. (i0.) ; then return; c. link + 2; rl w2 b19 ; al w1 x2+p40 ; i:= addr of statistics.curr rec; al w3 x1+p50 ; al w0 0 ; repeat i3 : rs w0 x1+0 ; curr receiver(i):= 0; al w1 x1+2 ; i:= i + 2 se w1 x3+0 ; jl. i3. ; until i = top of statistics; al w0 -1 ; entry:= 1st error segment.curr rec; al w3 x2+p46 ; repeat i4 : rs w0 x3+0 ; segment no.entry:= -1; al w3 x3+6 ; entry:= entry + 1 se w3 x2+p46+q2*6; jl. i4. ; until entry = top entry; rl. w3 i1. ; ls w3 -1 ; words:= bytes / 2; am. (i0.) ; jl 2 ; return; c. link + 4; ; variables i0 : 0 ; saved link i1 : 0 ; saved bytes i5: 2<1+1 ; function i6: 0 ; first i7: 0 ; last 0 ; relative e. z. \f ; pej 30.09.77 disc driver, initialize disc ; procedure initialize disc ; --------------------------------------------------------------- ; ; the procedure performs: ; - sets no of segments per cylinder and displacement of sector ; zero on odd cylinders and the disctype in the driver process ; description from information supplied in curr buf. ; - sets state.curr receiver to ready indicating that define disc ; should not be executed. ; - sets initdisc.curr receiver = 1. ; ; registers: call exit ; w0 destroyed ; w1 curr receiver unchanged ; w2 curr buf unchanged ; w3 link destroyed ; ; entry : j6 ; ; return : link+0 b. i0 w. j6 : rs. w3 i0. ; initialize disc: rl w0 x2+m2 ; wm w0 x1+p6 ; no of segments per cyl.curr rec:= rs w0 x1+p8 ; no of heads.curr buf rl w0 x2+m3 ; * no of segments per track.curr rec; rs w0 x1+p9 ; displacement.curr rec:= disp.curr buf; rl w0 x2+m4 ; disctype.curr receiver:= rs w0 x1+p5 ; disctype.curr buf; al w0 2 ; rs w0 x1+p12 ; state.curr receiver:= ready; al w0 1 ; hs w0 x1+p14 ; initdisc.curr receiver:= 1; jl. (i0.) ; return; ; variables i0 : 0 ; saved link e. \f ; pej 19.09.77 disc driver, setup channelprogram and start ; procedure setup channel program and start(kind,result); ; --------------------------------------------------------------- ; kind : 0 : setup channel pg according to curr buf. ; q39: define disc, setup read. (has no connection to ; q39+2: power rest., setup sense. the commands set regretted and continue ) ; result: result from procedure start i/o. ; ; the procedure performs: ; - sets up a channelprogram according to either the contents ; of curr buf, a channel program for reading addr mark at ; define disc or a channel program for sensing the disc at ; power restart. ; ; please note that if a channelprogram for reading or writing ; is set up according to curr buf, and no of segments.curr buf ; equals zero then firstaddr.curr buf is not used in the ; transfer command as procedure update buf on error may have ; incremented firstaddr.curr buf beyond lastaddr.curr buf. ; instead, to avoid result 3 from start i/o, the transfer ; command will contain a first address pointing into drivers ; process description. ; - calls procedure start i/o to start the transfer. the device ; is reset if initdisc.curr receiver <>0, and initdisc:= 0. ; - sets segment units.curr receiver at read or write to ; bytes-chars per segment. ; - zeroizes remaining bytes, curr status, event status, and ; technical status in the two statusareas. ; - zeroizes setmode param.curr receiver if setmode is not used ; (read, write, clean, position). ; - continues at waitnext in driver proc if the device is started ; or, if not, returns with a result (see proc start i/o). ; ; registers: call exit ; w0 result ; w1 kind channel pg start ; w2 0 or buf ; w3 link device address ; ; entry : j0 ; ; return : waitnext if ok ; link+0 if error b. c74, i110, l1, n10 w. \f ; pej 19.09.77 disc driver, setup channelprogram and start j0 : ; setup channel program and start: rs. w3 i0. ; save link; ; initialize according to most frequently used channel pg rl. w0 i4. ; command.mode.channel pg:= noop; rs. w0 c1. ; c. do not use strobe-offset; rl. w0 i5. ; command.first stop.channel pg:= stop; rs. w0 c5. ; c. not read after write; al. w0 c2. ; rs. w0 i1. ; startaddr:= first seek.channel pg; rl w2 b18 ; sn w1 0 ; if kind = 0 bz w1 x2+m0 ; then kind:= operation.curr buf; la w1 g50 ; wm w1 g48 ; i:= (kind >> 1) << 1 * 3; dl. w0 x1+l0. ; command.first transfer.channel pg:= rs. w3 c3. ; operation table(i); am (b19) ; transfer state.curr receiver:= rs w0 p13 ; operation table(i + 2); rl. w0 x1+l1. ; rs. w0 i2. ; actionaddr:= operation table(i + 4); ; enter next action with w1 = curr receiver, w2 = curr buf i20: rl w1 b19 ; central action: w1:= curr receiver; rl w2 b18 ; w2:= curr buf; am. (i2.) ; actionaddr:= actionaddr + 1; al w3 1 ; rs. w3 i2. ; ba w3 x3 ; jl x3 ; goto actiontable(actionaddr); ; actiontable h. ; 0 1 2 3 4 5 6 7 8 9 10 i101: n7., n9. ; sense i102: n0., n2., n5., n8., n10. ; read i103: n0., n2., n6., n8., n10. ; write i104: n0., n3., n8.,n9. ; clean i105: n0., n8.,n9. ; position i106: n1., n4., n8.,n9. ; define disc i107: n7., n9. ; power rest. w. \f ; pej 19.09.77 disc driver, setup channelprogram and start ; action 0, calculate seekinformation (read,write,clean,pos.). n0 : rl w0 x2+m4 ; action 0: am (x2+m10) ; s:= first segment.curr buf wa w0 p3 ; + first segment.device.curr buf; ld w3 -100 ; rs w3 x1+p21 ; setmode param.curr receiver:= 0; wd w0 x1+p8 ; cyl:= s / segments per cyl.curr rec; ; r:= s mod segments per cyl.curr rec; wd w3 x1+p6 ; head:= r / segms per track.curr rec; ; sect:= r mod segms per track.curr r; sz w0 2.1 ; if cyl odd wa w2 x1+p9 ; then sect:= sl w2 (x1+p6) ; (sect + displacement.curr receiver) ws w2 x1+p6 ; mod segments per track.curr receiver; i25: ls w0 8 ; insert seekinformation: wa w3 0 ; c. w0=cyl,w1=curr,w2=sect,w3=head; rs w3 x1+p20 ; seek param(0).curr receiver:= ls w2 16 ; cyl << 8 + head; wa w2 x1+p7 ; seek param(2).curr receiver:= rs w2 x1+p20+2 ; sect < 16 + flags.curr receiver; jl. i20. ; goto central action; ; action 1, calculate transfer - and seekinformation (define disc) n1 : al w3 p22 ; action 1: al w0 q51 ; first addr.1st transfer.channel pg:= ds. w0 c34. ; addr mark.curr receiver; rl w0 x1+p10 ; charcount.1st transfer.ch pg:=chars; rl w3 x1+p11 ; cyl:= define disc cyl.curr receiver; rl w2 x1+p6 ; head:= define disc head.curr rec; al w2 x2-1 ; sect:= segms per track.curr rec - 1; jl. i25. ; goto insert seekinformation; ; action 2, calculate transferinformation (read,write). n2 : dl. w0 i10. ; action 2: ds w0 x1+p35+2 ; segment units.curr receiver:= bz w0 x2+m1 ; chars-bytes per data segment; so w0 q40 ; if transput mode.curr buf = 1 then jl. i30. ; begin c. addr mark mode; rl. w0 c3. ; lo. w0 i8. ; command.1st transfer.channel pg:= rs. w0 c3. ; command.1st transfer.channel pg rl w0 x1+p13 ; +modif; ls w0 -1 ; transfer state.curr receiver:= rs w0 x1+p13 ; transfer state.curr receiver >> 1; dl. w0 i9. ; segment units.curr receiver:= ds w0 x1+p35+2 ; chars-bytes per addr mark; ; end; i30 : bz w0 x2+m5 ; wm w0 x1+p35+2 ; charcount.1st transfer.channel pg:= rs. w0 c34. ; chars * no of segments.curr buf; rl w1 x2+m2 ; firstaddr.1st transfer.channel pg:= rs. w1 c32. ; firstaddr.curr buf; se w0 0 ; if charcount.1st transfer.ch pg=0 then jl. i20. ; begin c. see procedure description; rl. w0 c3. ; lo. w0 i11. ; addrcode.1st transfer.channel pg:= rs. w0 c3. ; drivers process; al w0 p20 ; firstaddr.1st transfer.channel pg:= rs. w0 c32. ; rel of seek param; jl. i20. ; end; ; goto central action; ; action 3, insert dummy transfer information (clean track). n3 : dl. w1 c24. ; action 3: ds. w1 c34. ; parameters.1st transfer.channel pg:= ; parameters.1st seek.channel pg; ; c. because of checking in start i-o; jl. i20. ; goto central action; ; action 4, test if strobe-offset used (define disc). n4 : bz w3 x1+p15 ; action 4: ; retryinf:= retryinf.curr receiver; jl. i35. ; goto test mode; ; action 5, test if strobe-offset used (read). n5 : bz w3 x2+m6 ; action 5: retryinf:= retryinf.curr buf; ; test mode: c. ac3 = retryinf; i35 : sh w3 2.111 ; if retryinf(0:20) = 0 jl. i20. ; then goto central action; rl. w0 i6. ; rs. w0 c1. ; command.mode.channel pg:= setmode; ls w3 -3 ; rl. w2 i3. ; la w2 6 ; i:= modeindex.retryinf; ls w3 -5 ; i1:= offset index.retryinf; al w3 x3-1 ; bz. w0 x3+q20. ; ba. w0 x2+q21. ; setmode param.curr receiver:= rs w0 x1+p21 ; modetable(i-1)+ offsettable(i1); jl. i20. ; goto central action; ; action 6, test if read after write (write). n6 : bz w3 x2+m1 ; action 6: so w3 q43 ; if -, read after write.mode.curr buf jl. i20. ; then goto central action; rl w0 x1+p13 ; ls w0 -2 ; transfer state.curr receiver:= rs w0 x1+p13 ; transfer state.curr receiver >> 2; rl. w0 i4. ; rs. w0 c5. ; command.1st stop.channel pg:= noop; rl. w0 i7. ; command:= read with no transfer; sz w3 q40 ; if transput mode.curr buf = 1 rl. w0 i7. ;* then command:= command + modif; rs. w0 c7. ; command.2nd transfer.channel pg:= ; command; dl. w0 c34. ; parameters.2nd transfer.channel pg:= ds. w0 c74. ; parameters.1st transfer.channel pg; se w0 0 ; if charcount.2nd transfer.ch pg=0 then jl. j37. ; rl. w0 c7. ; addrcode.2nd transfer.channel pg:= lo. w0 i11. ; drivers process; rs. w0 c7. ; c. see action 2; i37 : bz w0 x2+m6 ; al w3 0 ; c. test if write is to be skipped; sz w0 2.111 ; if readtries.retryinf.curr buf <> 0 rs. w3 c34. ; then charcount.1st transfer.channel pg jl. i20. ; := 0; ; goto central action; ; action 7, determine startaddress (sense,power restart). n7 : zl w0 x2+m1 ; action 7: ls w0 -3 ; get mess.mode ea w0 x1+p14 ; al. w3 c4. ; startaddr:= 1st sense.channel pg; se w0 0 ; if initdisc.curr receiver <> 0 or mess.mode = 8 al. w3 c3. ; then startaddr := rs. w3 i1. ; 1st transfer.channel pg; c. init; jl. i20. ; goto central action; ; action 8, determine startaddr (read,write,clean,pos,define). n8 : bz w0 x1+p14 ; action 8: al. w3 c0. ; se w0 0 ; if initdisc.curr receiver <> 0 rs. w3 i1. ; then startaddr:= init.channel pg; jl. i20. ; goto central action; ; action 9, perform start with buf = 0 (all except read,write) n9 : al w2 0 ; action 9: buf:= 0; jl. i40. ; goto start; ; action 10, perform start with buf = curr buf: n10 : ; action 10: c. buf = curr buf; ; call start i/o to start the transfer. w1,w2 = curr rec.,buf. i40 : ld w0 -100 ; start: ds w0 x1+p16+4 ; zeroize rembytes, curr status, rs w0 x1+p16+6 ; event status, technical status rs w0 x1+p16+20 ; in statusarea1.curr receiver ds w0 x1+p18+4 ; and statusarea2.curr receiver; rs w0 x1+p18+6 ; rs w0 x1+p18+20 ; hs w0 x1+p14 ; initdisc.curr receiver:= 0; al w0 1<2+1 ; + std exit + start channel pg; rl w3 x1+a235 ; device addr:= device addr.curr rec; rl. w1 i1. ; jd 1<11+100; start i/o(func,startad,buf,devicead); jl. (i0.) ; return; ; pej 19.09.77 disc driver, setup channelprogram and start ; variables i0 : 0 ; saved link i1 : 0 ; start addr, in channel pg i2 : 0 ; action addr, index to actiontable i3 : 2.11111 ; for masking out offsetindex.retryinf i4 : 4095 ; channel pg command = noop i5 : 15<8 ; = stop i6 : 4<12+2<8+1 ; = setmode i7 : 4095 ;* = read, no transfer i8 : 1 ; modifier for addr mark (read,write) q50 ; bytes per addr mark i9 : q51 ; segment unit: +0: chars per addr mark q52 ; bytes per data segm i10 : q53 ; segment unit: +0: chars per data segm i11 : 4<12 ; addrcode = drivers process ; operation table. ; the table contains: +0: command for 1st transfer.channel pg ; +2: transfer state ; +4: action table base ; a row in the table is indexed by: (operation>1)<1*3 ; addrcode+command+modif, state, actionbase i100: 0<12 + 6<8 + 0,l0:1<20,l1:i101-1 ; + 0: sense 0<12 + 1<8 + 0 , 1<17 , i102-1 ; + 6: read 0<12 + 3<8 + 0 , 1<15 , i103-1 ; +12: write 4<12 + 3<8 + 3 , 1<18 , i104-1 ; +18: clean track 4095 , 1<19 , i105-1 ; +24: position 4<12 + 1<8 + 1 , 1<22 , i106-1 ; +30: define disc 0<12 + 6<8 + 0 , 1<21 , i107-1 ; +36: power restart ; 1 read ; 0 data ; 1 addr mark ; 3 write ; 0 data ; 1 addr mark ; 3 clean ; 6 init ; 0 data area in senders process ; 4 data area in drivers process descr \f ; pej 19.09.77 disc driver, channel program ; c h a n n e l p r o g r a m ; addrcode command params ; init after error c0 : 6<8 ; init irrel init 0 ; irrel 0 ; irrel ; normal starting point c2 : 4<12+ 2<8 ; 1st seek device seek c22 : p20 ; paramaddr c24 : 6 ; charcount c1 : 4<12+ 2<8+1 ; mode device setmode p21 ; paramaddr 3 ; charcount c3 : 0 ; 1st transfer c32 : 0 ; c34 : 0 ; c4 : 4<12+ 0<8 ; 1st sense device sense p16 ; statusarea1 33 ; max charcount ; stop unless read after write c5 : 15<8 ; 1st stop irrel stop 0 ; irrel 40000 ; timer, 0.1 ms ; checkread c6 : 4<12+ 2<8 ; 2nd seek device seek p20 ; paramaddr 6 ; charcount c7 : 0 ; 2nd transfer c72 : 0 ; c74 : 0 ; c8 : 4<12+ 0<8 ; 2nd sense device sense p18 ; statusarea2 33 ; max charcount ; stop c9 : 15<8 ; 2nd stop irrel stop 0 ; irrel 40000 ; timer, 0.1 ms e. \f ; pej 22.09.77 disc driver, process next message ; p r o c e s s n e x t m e s s a g e ; --------------------------------------------------------------- ; this routine is entered when the next message is to be proces- ; sed by the disc driver. the routine is entered either from link ; message routine (driver able to process a received message ; immediately) or when an answer to a processed message has been ; delivered and more messages are queued to the driver. curr buf ; contains addr of buffer to be processed. ; check if message is get statistics message ; process next message: j50 : al w0 0 ; c. w1 = curr receiver, w2 = curr buf; hs w0 x1+p15 ; retryinf.curr receiver:= 0; bz w0 x2+m0 ; c. q1 ; if statistics wanted se w0 q36 ; and operation.curr buf = get stat then jl. j52. ; begin jl. w3 j5. ; copy statistics(result,words); jl. j90. ; if no room then goto deliv. blockl; jl. j102. ; if -, ok then goto status/segms 0; jl. j94. ; goto deliver words wanted; z. ; end; ; check if message is initialize message j52 : se w0 q31 ; if operation.curr buf = init then jl. j53. ; begin jl. w3 j6. ; initialize disc; jl. j101. ; goto deliver size zero; ; end; ; check if message is set regretted j53 : se w0 q39 ; if operation.curr buf = set regretted then jl. j55. ; begin al w0 3 ; set regretted.curr receiver = 3 rs w0 x1+a56 ; deliver result 1 al w0 0 ; rs w0 g20 ; deliver status 0 jl g7 ; end \f ; pej 22.09.77 disc driver, start device ; s t a r t d e v i c e ; --------------------------------------------------------------- ; this routine is executed to start the device and is entered ; from process next message routine or when an operation is to ; be repeated. the disc is started according to the contents of ; curr buffer. ; ; if the disc is not yet defined (state.curr receiver <> ready) ; then a special transfer is activated to check number of heads ; and displacement of sector zero on odd cylinders. curr buf is ; left in the head of the queue and will be processed when the ; disc has been defined. regretted.curr receiver will be odd ; during define disc so as to avoid a start (this might happen if ; curr buf is regretted and the queue turns empty). ; ; continuation takes place at waitnext in driverproc. ; set up channel program for contents of curr buf j55 : rl w1 b19 ; start: rl w0 x1+p12 ; se w0 2 ; if state.curr receiver = ready then jl. j57. ; begin c. q1 ; if statistics wanted am (x1+p40) ; al w0 1 ; then no of transfers.curr rec:= rs w0 x1+p40 ; no of transfers.curr rec + 1; z. ; al w1 0 ; kind:= 0; c. use curr buf; jl. w3 j0. ; setup channel pg and start(kind); se w0 3 ; if result <> 3 jl. j101. ; then goto deliver size zero jl. j99. ; else goto deliver unintilligible; ; end; ; setup channel program for define disc j57 : se w0 0 ; if state.curr rec = after interv then jl. j59. ; begin rs w0 x1+p10 ; define disc cyl.curr receiver:= 0; rs w0 x1+p11 ; define disc head.curr receiver:= 0; hs w0 x1+p15 ; retryinformation.curr receiver:= 0; al w0 1 ; state.curr receiver:= defining disc; rs w0 x1+p12 ; regretted.curr receiver:= 1; rs w0 x1+a56 ; disctype.curr receiver:= 1; rs w0 x1+p5 ; initdisc.curr receiver:= 1; hs w0 x1+p14 ; end; j59 : al w1 q39 ; jl. w3 j0. ; setup channel pg and start(kind); \f ; pej 26.09.77 disc driver, interrupt received ; i n t e r r u p t r e c e i v e d ; --------------------------------------------------------------- ; ; this routine is entered when driver proc receives an interrupt ; operation for a disc driver. the i/o result stored in the ; device description indicates the event leading to generation of ; the interrupt operation: ; ; i/o result 0: normal termination, interrupt from device. ; 1: bus reject, busy , device not started. ; 2: bustimeout, discon, - - - ; 3: software timeout , software generated. ; 4: abnormal terminat., interrupt from device. ; 5: wait pg. terminat., - - - ; 6: power restart , software generated. ; form the compoundstatus from i/o result and all statuswords ; (curr status, event status) generated by the device. c34 : rl w3 b19 ; interrupt received: rl w0 x3+a230 ; if channel pg count.std status = 0 sn w0 0 ; then am p16+6-a233; curr-event:= curr-event.statusarea1 dl w1 x3+a233 ; else curr-event:=curr-event.stdstatus; lo w0 x3+p16+4 ; curr:= curr or curr.statusarea1; lo w1 x3+p16+6 ; event:= event or event.statusarea1; rl w2 x3+p16+20 ; tech:= techn status.statusarea1; lo w0 x3+p18+4 ; curr:= curr or curr.statusarea2; lo w1 x3+p18+6 ; event:= event or event.statusarea2; lo w2 x3+p18+20 ; tech:= tech or tech.statusarea2; ds w1 x3+p31+2 ; curr-event.curr rec:= curr-event; rs w2 x3+p33 ; technical status.curr rec:= tech; jl. w3 j8. ; compoundstatus(curr,event,compound); rs w0 x1+p34 ; compound status.curr rec:= compound; ; check if compound status is ok with respect to actual transfer. rl w3 x1+p13 ; ls w3 -1 ; i:= transfer state.curr rec >> 1; ns. w3 3 ; sh:= no of shifts to normalize i; ac w3 ; -sh ; ls w3 2 ; sh:= sh * 4; rl w2 b18 ; c. w1 = curr rec, w2 = curr buf; sz. w0 (x3+i20.) ; if compound and table(sh) <> 0 jl. j125. ; then goto error jl. (x3+i21.) ; else goto table(sh+2); ; table to determine if transfer was successful. an entry corre- ; sponds to a transfer state and contains: ; +0: mask which anded to compound status must give zero. ; +2: addr where to continue. ; mask addr transfer state i20 : -1 , i21 : j125 ; bit 0, idle (will always go to error) i23 , j85 ; 1, define disc i25 , j87 ; 2, power restart i23 , j75 ; 3, sense i23 , j75 ; 4, position i24 , j75 ; 5, clean track i23 , j77 ; 6, read data i23 , j77 ; 7, read addr mark i24 , j77 ; 8, write data i24 , j77 ; 9, write addr mark i24 , j77 ; 10, read after write data i24 , j77 ; 11, read after write addr mark ; masks, normal term (bit 19) not checked. must be 1. i23 = 8.77617757 ; input ok, bits not checked: 8,9,10 ; (write protect, high density, mode) i24 = 8.77737757 ; output ok, bits not checked: 9 ; (high density) i25 = 8.37617757 ; power ok, bits not checked: 0,8,9,10 ; (intervention, write protect, high ; density, mode) \f ; pej 26.09.77 disc driver, successful transfer ; s u c c e s s f u l t r a n s f e r ; --------------------------------------------------------------- ; these routines are entered when a transfer is regarded success- ; ful. w1 = curr receiver, w2 = curr buf. ; c o n t r o l s u c c e s s f u l j75 : rl w0 x1+a56 ; control ok: se w0 0 ; if regretted.curr receiver jl. j110. ; then goto examine queue; c. q1 ; if statistics wanted bz w0 x2+m6 ; se w0 0 ; and retryinf.curr buf <> 0 jl. w3 j17. ; then update on corrected error; z. ; jl. j101. ; goto deliver size zero; ; t r a n s p u t s u c c e s s f u l j77 : al w0 0 ; transput ok: sn w0 (x1+p16+2) ; if rembytes.statusarea1.curr rec <> 0 se w0 (x1+p18+2) ; or rembytes.statusarea2.curr rec <> 0 jl. j125. ; then goto error; al w3 1 ; rl w0 x1+p21 ; if setmode param.curr receiver <> 0 se w0 0 ; then initdisc.curr receiver:= 1; hs w3 x1+p14 ; c. force heads back to nominal pos; c. q1 ; if statistics wanted bz w0 x2+m6 ; se w0 0 ; and retryinf.curr buf <> 0 jl. w3 j16. ; then update on corrected error; z. ; bz w0 x2+m5 ; segments:= no of segments.curr buf; jl. w3 j11. ; update buf(segments,bytes); ; check if more segments are to be transferred at transput j80 : bz w0 x2+m9 ; sn w0 0 ; if remaining segms.curr buf = 0 jl. j103. ; then goto deliver wanted; al w0 0 ; c. jumps always at direct disc msg; hs w0 x2+m6 ; retryinformation.curr buf:= 0; rl w0 x2+m7 ; first segment.curr buf:= rs w0 x2+m4 ; next segment.curr buf; rl w1 x2+m10 ; proc:= device.curr buf; jl. w3 j4. ; prepare consecutive segms(proc); jl. j55. ; goto start; ; d e f i n e d i s c s u c c e s s f u l j85 : rl w0 x1+p16+2 ; define disc ok: se w0 0 ; if rembytes.statusarea1.curr rec <> 0 jl. j125. ; then goto error; rl w0 x1+p34 ; type:= ls w0 -14 ; hi dens.compound status.curr rec; la w0 g3 ; c. 0=dsm801, 1=dsm802; rs w0 x1+p5 ; disctype.curr receiver:= type; al w0 1 ; initdisc.curr receiver:= 1; hs w0 x1+p14 ; c. ensures nominal head position; wa w0 x1+p11 ; define disc head.curr receiver:= rs w0 x1+p11 ; define disc head.curr receiver + 1; al w3 8.377 ; c. test if last addr mark on cylind.; sz w3 (x1+p22+4) ; if nexthead.addrmark.curr rec <> 0 jl. j55. ; then goto start; wm w0 x1+p6 ; segments per cyl.curr receiver:= rs w0 x1+p8 ; define disc head.curr receiver rl w0 x1+p22+6 ; * segments per track.curr receiver; ls w0 -16 ; displacement.curr receiver:= rs w0 x1+p9 ; next sector.addrmark.curr receiver; al w0 2 ; c. sector 0 on odd cylinders; rs w0 x1+p12 ; state.curr receiver:= ready; jl. j110. ; goto examine queue; ; p o w e r r e s t a r t s u c c e s s f u l j87 : rl w0 x1+p12 ; power restart ok: sn w0 1 ; if state.curr rec = defining disc al w0 0 ; then state.curr rec:= after interven; rs w0 x1+p12 ; c. resume define disc from beginning; jl. j110. ; goto examine queue; \f ; pej 26.09.77 disc driver, deliver answer ; d e l i v e r a n s w e r r o u t i n e ; --------------------------------------------------------------- ; these routines are entered to deliver the answer to a processed ; message. upon delivering the answer it is examined if more ; messages are queued to the driver. if so, next message is pro- ; cessed, and if not, idle state is entered and a wait program ; is started. p35+0 and p35+2 contains bytes/chars per segment. ; result 1, status blocklength, bytes 0. j90 : dl. w1 i27. ; deliver blocklength: al w3 0 ; result:= 1; status:= bit4; jl. j106. ; segments:= 0; goto deliver; ; result 1, status discerror, bytes = what was transferred. j92 : dl. w1 i28. ; deliver discerror: result:= 1; rl w2 b18 ; status:= bit11; jl. j97. ; goto deliver transferred; ; result 1, status 0, words contained in ac3 j94 : al w0 2 ; deliver words wanted: c. w2=curr rec; al w1 3 ; bytes:= 2; chars:= 3; ds w1 x2+p35+2 ; c. w3 = words == segments; jl. j104. ; goto deliver ok; ; result 4, status 0, bytes=what was transferred j95 : al w0 4 ; deliver spurious: al w1 0 ; result:= 4; status:= 0; rl w2 b18 ; w2:= curr buf; jl. j97. ; goto deliver transferred; ; result, status corresp. to compound, bytes=what was transferred j96 : ; deliver error: jl. w3 j10. ; set result and status(result,status); j97 : bz w3 x2+m8 ; deliver transferred: c. w2 = curr buf; bs w3 x2+m9 ; segments:= segments wanted.curr buf bz w2 x2+m0 ; - remaining segments.curr buf; so w2 2.1 ; if operation.curr buf = control al w3 0 ; then segments:= 0; jl. j106. ; goto deliver; ; result 1, 2, 3, status 0, bytes 0. j99 : am 3-2 ; deliver unintelligible: j100: am 2-1 ; deliver rejected : j101: al w0 1 ; deliver size zero : j102: al w1 0 ; deliver status and segms zero: al w3 0 ; status:= 0; segments:= 0; jl. j106. ; goto deliver; ; result 1, status 0, bytes = what was wanted. j103: ; deliver wanted; c. w2 = curr buf; bz w3 x2+m8 ; segment:= segments wanted.curr buf; j104: dl. w1 i29. ; deliver ok: result:= 1; status:= 0; ; deliver the answer, w0=result, w1=status, w3=segments. j106: rs w1 g20 ; deliver: rl w1 b19 ; status.i/o answer:= status; rs w3 g21 ; wm w3 x1+p35 ; rx w3 g21 ; bytes.i/o answer:= segments * bytes; wm w3 x1+p35+2 ; rs w3 g22 ; chars.i/o answer:= segments * chars; rl w2 x1+a244 ; file.i/o answer:= i/o result.curr rec; rl w3 x1+p31 ; block.i/o answer:= ds w3 g24 ; curr status.curr receiver; rl w2 x1+p31+2 ; curr buf(18:19):= event stat.curr rec; rl w3 x1+p33 ; curr buf(20:21):= techn stat.curr rec; am (b18) ; ds w3 m8 ; rs w0 x1+p35 ; save result; ; w0= result; b18 =buffer rl w2 b18 ; w2:=buffer rl w1 x2+a141 ; w1:= receiver.buf sh w1 0 ; ac w1 x1 ; w1:= absolute value of receiver sh w1 6 ; jl. j107. ; rl w3 x1+a10 ; w3:= kind(rec); se w3 4 ; if area process then jl. j107. ; begin rl w3 g22 ; sn w0 1 ; if bytes<>0 then sn w3 0 ; begin jl. j107. ; bz w3 x2+8 ; if operation = write then se w3 q33 ; nooftiw:=nooftiw+1 am a412-a411 ; else al w3 x1+a411 ; nooftir:=nooftir+1; rl w2 x3 ; al w2 x2+1 ; rs w2 x3 ; j107: jl w3 g19 ; deliver result(result); ; clean the driver in case of abnormal result. rl w0 x1+p35 ; sl w0 4 ; if result > 3 jl. w3 j14. ; then clean(result); ; examine if more messages are queued. j110: al w0 0 ; examine queue: c. w1=curr receiver; rs w0 x1+a56 ; regretted.curr receiver:= 0; jl w3 g64 ; examine queue(queue empty); jl. j112. ; if not queue empty jl. j50. ; then goto process next message; ; queue is empty, start a wait program. continue at waitnext. j112: rl w0 g49 ; start wait: c. w1 = curr receiver; rs w0 x1+p13 ; transfer state.curr receiver:= idle; rl w3 x1+a235 ; dev:= device descr.curr rec; al w0 3<2+1 ; start control + std exit; ld w2 -100 ; buf:= 0; timeout:= eternal; jd 1<11+100 ; start i/o(func,timeout,buf,dev); \f ; pej 28.09.77 disc driver, error routine ; e r r o r r o u t i n e ; --------------------------------------------------------------- ; this routine is entered when an interrupt not corresponding to ; a successful transfer has been received. the treatment of the ; error takes place by running through a number of actions, each ; action being executed as a function of the kind of error and ; the transfer state of the driver. ; ; if possible, the transfer is repeated. if the routine is entered ; due to power restart (or disc power down = possible power break ; in progress) a loop is entered to check if power comes up again, ; leaving a possible message being currently processed in the head ; of the queue. ; determine the kind of error j125: ; error: c. w1 = curr receiver; jl w2 (b31) ; call errorlog jl. w3 j9. ; set errorkind(kind); wa w0 x1+p13 ; actionkey:= rs w0 x1+p36 ; errorkind + transfer state.curr rec; al w0 -4 ; rs w0 x1+p37 ; actionindex:= -4; ; determine if next action is to be executed j130: rl w1 b19 ; central action: w1:= curr receiver; j132: am (x1+p37) ; skip: al w3 4 ; rs w3 x1+p37 ; action index:= actionindex + 4; rl w0 x1+p36 ; la. w0 x3+i35. ; i:= table(actionindex) and actionkey; bz w2 1 ; sz w0 (g51) ; if i(0:11) = 0 sn w2 0 ; or i(12:23) = 0 jl. j132. ; then goto skip; rl w2 b18 ; goto table(actionindex + 2); jl. (x3+i36.) ; c. with w1 = curr rec, w2 = curr buf; b. n25, o16 w. ; block containing error actions ; table guiding the execution of actions. each entry contains: ; +0: transfer states < 12 + errorkinds ; the action is executed if the actionkey (see above) anded ; to this word gives nonzero in both bytes. ; +2: action address. ; --------------------------------------------------------------- ; ----transfer states---- --error kinds-- actions ; read ; write d a i p p t w d a o ; read aft. f n o o i r a d t ; i d p s p c d a d a d a o t t w w m t d h ; d e o e o l a d a d a d v e e e e p a r e ; l f w n s e t d t d t d e d r r r o r r ; e i e s a a r a r a r r v u o e e ; n r e n r o r d t t r r ; --------------------------------------------------------------- ; action 1 vacant i35: 2. 1 1 1 0 1 1 1 1 1 1 1 1 <12+2. 1 1 1 1 0 0 1 1 , i36: n2 2. 1 1 1 1 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 , n3 2. 1 1 <12+2. 1 1 1 1 1 1 1 1 1 1 , n4 2. 1 1 1 0 0 0 0 0 0 <12+2. 1 0 1 1 1 , n5 2. 1 1 1 1 1 1 1 1 1 <12+2. 1 0 1 1 1 , n6 2. 1 0 0 0 0 0 <12+2. 1 0 0 , n7 c. q1 2. 1 1 1 1 1 1 <12+2. 1 0 1 1 1 , o7 z. 2. 1 1 0 0 0 0 <12+2. 1 1 0 , n8 2. 1 1 0 0 0 0 <12+2. 1 0 0 0 0 , o8 2. 1 1 1 1 1 1 1 0 0 <12+2. 1 0 1 1 1 , n9 2. 1 1 <12+2. 1 0 1 1 1 , n10 2. 1 1 0 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 , n11 2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 0 , n12 2. 1 0 0 0 0 0 0 0 0 0 <12+2. 1 0 0 0 0 , n13 2. 1 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 , n14 2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 0 0 , n17 2. 1 0 0 1 1 1 1 <12+2. 1 0 0 0 , n16 2. 1 1 0 1 1 0 0 0 0 <12+2. 1 0 0 0 , o16 2. 1 0 0 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 , n17 2. 1 0 0 0 0 0 0 0 0 0 0 <12+2. 1 0 , n18 2. 1 0 0 0 0 0 0 0 0 0 0 <12+2. 1 1 1 1 1 1 1 1 1 1 , n19 2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 0 0 0 , n20 2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 0 0 0 0 0 0 0 0 0 , n21 2. 1 1 1 1 1 1 1 1 1 1 1 1 <12+2. 1 1 1 1 1 1 1 1 1 1 , n22 \f ; pej 28.09.77 disc driver, error routine ; action 2: set initdisc ; tr.state: all, except sense ; err.kind: all, except overrrun, write prot, and data err n2 : al w0 1 ; initdisc.curr receiver:= 1; hs w0 x1+p14 ; jl. j130. ; goto central action; ; action 3: update buf at error at read or simple write. ; tr.state: read data, read addr m, write data, write addr m ; err.kind: any n3 : al w2 x1+p16 ; area:= statusarea1.curr receiver; al. w3 j130. ; update buf on err(area,bytes,chars); jl. j12. ; goto central action; ; action 4: update buf at read after write error. ; tr.state: read after write data, read after write addr m. ; err.kind: any n4 : al w0 0 ; c. test if first transfer (write) ok; rs w0 x1+p38 ; write ok:= 0; c. see action 10; se w0 (x1+p16) ; if chan pg count.status1.curr rec = 0 se w0 (x1+p16+2) ; or rembytes.statusarea1.curr rec <> 0 jl. j130. ; then goto central action; c. not ok; dl w1 x1+p16+6 ; jl. w3 j8. ; compoundstatus(curr,event,compound); sz. w0 (i40.) ; if compound and output ok <> 0 jl. j130. ; then goto central action; c. not ok; rs w1 x1+p38 ; write ok:= <> 0; c. see action 10; al w2 x1+p18 ; area:= statusarea2.curr receiver; al. w3 j130. ; update buf on err(area,bytes,chars); jl. j12. ; goto central action; ; action 5: repeatable error, test if control message regretted. ; tr.state: sense, position, clean track ; err.kind: timeout, data error, addr mark error, other error n5 : al w0 0 ; sn w0 (x1+a56) ; if regretted.curr receiver = 0 jl. j130. ; then goto central action jl. j110. ; else goto examine queue; ; action 6: repeatable error, test if transfer may be repeated. ; tr.state: any, except idle, define disc, power restart ; err.kind: timeout, data error, addr mark error, other error n6 : ; c. q1 ; if statistics wanted then am (x1+p41) ; begin al w3 1 ; count:= not successful.curr rec + 1; bz w0 x2+m6 ; sn w0 0 ; if retryinf.curr buf = 0 then rs w3 x1+p41 ; not successful.curr rec:= count; z. ; end; bz w0 x2+m1 ; sz w0 q41 ; if -, error recovery.mode.curr buf jl. j96. ; then goto deliver error jl. j130. ; else goto central action; ; action 7: data error at read, try to repair by ecc. ; tr.state: read data ; err.kind: data error n7 : jl. w3 j15. ; correct data; jl. j130. ; if not corrected then goto cent act.; al w0 1 ; segments:= 1; rl w1 b19 ; c. one segment, the last, corrected; rl w2 b18 ; jl. w3 j11. ; update buf(segments,bytes); c. q1 ; if statistics wanted then am (x1+p42) ; begin al w3 1 ; count:= ecc corrected.curr rec + 1; bz w0 x2+m6 ; sn w0 0 ; if retryinf.curr buf = 0 rs w3 x1+p42 ; then ecc corrected.curr rec:= count se w0 0 ; jl. w3 j16. ; else update on corrected error; z. ; end; al w0 0 ; if setmode param.curr rec = 0 sn w0 (x1+p21) ; then initdisc.curr rec:= 0; hs w0 x1+p14 ; c. init not necessary; hs w0 x2+m6 ; retryinf.curr buf:= 0; bz w0 x2+m5 ; c. check if entire transfer now ok; sn w0 0 ; if no of segments.curr buf = 0 jl. j80. ; then goto check if more jl. j55. ; else goto start; ; action 7a, update table of error segments ; tr.state : read data, read addr m, write data, write addr m, ; read after write data, read after write addr m ; err.kind : timeout, data error, addr mark error, other error o7 : c. q1 ; if statistics wanted then bz w0 x2+m6 ; begin se w0 0 ; if retryinf.curr buf <> 0 jl. j130. ; then goto central action; rl w3 x2+m4 ; c. already registrated; am (x2+m10) ; segment:= first segment.curr buf wa w3 p3 ; + first segment.device.curr buf; al w2 x1+p46 ; entry:= 1st error segm.curr rec; j141: sl w2 x1+p46+q2*6; while entry <> top entry do jl. j130. ; begin sh w0 (x2+0) ; if segment no.entry < 0 sn w3 (x2+0) ; or segment no.entry = segment jl. j143. ; then goto found; increase entry; al w2 x2+6 ; end; jl. j141. ; goto central action; c. table full; j143: rs w3 x2+0 ; found: am (b18) ; segment no.entry:= segment; ba w2 m0 ; i:= operation.curr buf; bz w1 x2+0 ; al w1 x1+1 ; entry(i):= entry(i) + 1; hs w1 x2+0 ; jl. j130. ; end; z. ; goto central action; ; action 8, data error or addr m error at read, use strobe-offset ; tr.state: read data, read addr mark ; err.kind: data error, addr mark error n8 : al w1 x2+m6 ; retryinf:= retryinf.curr buf; jl. w3 j13. ; update retryinformation(retryinf); jl. j96. ; if no more tries goto deliver error; jl. j147. ; jl. j145. ; if next offset magnitude used then jl. j147. ; begin c. may buf be requeued; j145: rl w2 b18 ; bz w0 x2+m1 ; sz w0 q42 ; if requeue.curr buf = no requeue jl. j92. ; then goto deliver discerror; jl w3 d5 ; c. remove and link the buf to q end; am (b19) ; remove(curr buf); al w1 a54 ; jl w3 d6 ; link(mess queue.curr rec,curr buf); rl w1 b19 ; goto examine queue; jl. j110. ; end; j147: al w0 2.10 ; c. initdisc may be skipped if data rl w1 b19 ; error as the correct segment was la w0 x1+p36 ; read; sn w0 0 ; if actionkey and -, addr mark error hs w0 x1+p14 ; then initdisc.curr rec:= 0; jl. j55. ; goto start; ; action 8a: timeout at read, simulate address mark error if ; timeout is possibly caused by use of strobe - ; offset (synchronization chars out of reach). ; tr.state : read data, read addr m ; err.kind : timeout o8: bz w3 x2+m6 ; sh w3 2.111 ; if retryinf.curr buf <> strobe.offset jl. j130. ; used then goto central action; la. w3 i45. ; c. force next offset magnitude; wa. w3 i44. ; retryinf.curr buf:= last modeindex < 8 hs w3 x2+m6 ; +offset.retryinf.curr buf + maxtries; rl w3 x1+p36 ; c. simulate addr mark error; al w3 x3-2.10000; action key.cur rec:= al w3 x3+2.10 ; action key.curr rec rs w3 x1+p36 ; -timeout + addr m error; rl. w3 i43. ; compound status.curr rec:= rs w3 x1+p34 ; data err + hard err + abnorm term; jl. n8. ; goto action 8; ; action 9: error at control, read, simple write. repeat transfer ; tr.state: sense, position, clean track, ; read data, read addr m, write data, write addr m ; err.kind: timeout, data error, addr mark error, other error n9 : al w1 x2+m6 ; retryinf:= retryinf.curr buf; jl. w3 j13. ; update retryinformation(retryinf); jl. j98. ; jl. j98. ; jl. j98. ; if tries <= 3 then goto start jl. j55. ; else goto deliver error; j98: rl w1 b19 ; al w0 0 ; if more than 3 timeouts then rs w0 x1+p12 ; then execute initdisc before next operation jl. j96. ; (possible kitshift in progress) ; action 10: error at read after write, repeat transfer. ; tr.state : read after write data, read after write addr mark ; err.kind : timeout, data error, addr mark error, other error n10 : rl w0 x1+p38 ; c. see action 4 re. write ok; bz w3 x2+m6 ; r:= retryinformation.curr buf; c. w3; sn w0 0 ; if write ok then jl. j150. ; begin c. repeat 2nd transfer (read); al w3 x3+1 ; readtries.r:= readtries.r + 1; so w3 2.100 ; if readtries.r <= 3 then goto rep; jl. j151. ; end; j150: la. w3 i41. ; c. repeat 1st transfer (write); al w3 x3+2.1000 ; readtries.r:= 0; incr writetries.r; sz w3 2.100<3; if writetries.r > 3 jl. j96. ; then goto deliver error; j151: hs w3 x2+m6 ; rep: retryinformation.curr buf:= r; jl. j55. ; goto start; ; action 11: disc power down, enter power restart loop. ; tr.state : any, except power restart ; err.kind : power down n11 : am q14-q13; power down: n:= no of times to sense disc; ; action 12: power restart, enter power restart loop. ; tr.state : any ; err.kind : power restart n12 : al w3 q13 ; n:= no of times to sense disc; al w0 0 ; sn w0 (x1+p12) ; if state.curr rec = after intervent. jl. n15. ; then goto intervention; al w0 1 ; regretted.curr receiver:= 1; rs w0 x1+a56 ; c. to prevent start if buf arrives; jl. j154. ; goto power sense; ; action 13: sense disc in power restart loop. ; tr.state : power restart ; err.kind : timeout n13 : bz w3 x1+p15 ; n:= retryinformation.curr receiver; al w3 x3-1 ; n:= n - 1; sh w3 -1 ; if n < 0 then goto intervention; jl. n15. ; power sense: c. w3 = n; j154: hs w3 x1+p15 ; retryinformation.curr receiver:= n; al w1 q39+2 ; kind:= power restart; jl. w3 j0. ; setup channelprogram and start(kind); ; c. cont. at waitnext in driverproc; ; action 14: delay before next sense in power restart loop. ; tr.state : power restart ; err.kind : any n14 : rl w3 x1+a235 ; dev:= device descr.curr rec; al w0 2<2+1 ; function:= start wait, std exit; rl. w1 i42. ; timer:= time between sense in loop; al w2 0 ; buf:= 0; jd 1<11+100 ; start i/o(function,timer,buf,dev); ; c. cont. at waitnext in driverproc; ; action 15: intervention. ; tr.state : any ; err.kind : intervention n15 : al w0 5 ; intervention: result:= 5; c. unknown; jl. w3 j14. ; clean(result); jl (b20) ; goto waitnext; c. in driver proc; ; action 16: write protect at output. ; tr.state : clean track, all write states ; err.kind : write protect n16 : jl. j100. ; goto deliver rejected; ; action 16a: write protect at control, read. repeat transfer. ; tr.state : sense, position, read data, read a m ; err.kind : write protect o16 : al w1 x2+m6 ; retryinf:= retryinf.curr buf; jl. w3 j13. ; update retryinformation(retryinf); jl. j95. ; jl. j95. ; jl. j95. ; if tries <= 3 then goto start jl. j55. ; else goto deliver spurious; ; action 17: wait program terminated not because of intervention. ; tr.state : idle ; err.kind : any n17: jl. n11. ; goto power down; ; action 18: addr mark error at define disc, use stobe-offset. ; tr.state : define disc ; err.kind : addr mark error n18 : al w1 x1+p15 ; retryinf:= retryinf.curr receiver; jl. w3 j13. ; update retryinformation(retryinf); jl. j160. ; if no more tries possible then jl. j55. ; jl. j55. ; jl. j55. ; begin c. try next even cylinder j160: rl w1 b19 ; am (x1+p10) ; al w0 2 ; define disc cyl.curr rec:= rs w0 x1+p10 ; define disc cyl.curr rec + 2; al w0 0 ; define disc head.curr rec:= 0; rs w0 x1+p11 ; retryinformation.curr rec:= 0; hs w0 x1+p15 ; end; jl. j55. ; goto start; ; action 19: error at define disc. repeat transfer. ; tr.state : define disc ; err.kind : any n19 : al w1 x1+p15 ; retryinf:= retryinf.curr receiver; jl. w3 j13. ; jl. j162. ; jl. j162. ; jl. j162. ; jl. j55. ; if tries <= 3 then goto start; j162: al w0 4 ; result:= 4; c. malfunction; jl. w3 j14. ; clean(result); al w0 0 ; rs w0 x1+p12 ; state.curr rec:= after intervention; jl (b20) ; goto waitnext; c. in driverproc; ; action 20: repeat transfer in data overrun loop ; tr.state : any ; err.kind : after data overrun n20 : al w0 0 ; rs w0 x1+a56 ; regretted.curr receiver:= 0; bz w3 x1+p15 ; n:= retryinf.curr receiver; al w3 x3+1 ; n:= n+1; sl w3 q15 ; if n > max no of retries jl. j96. ; then goto deliver error hs w3 x1+p15 ; else begin jl. j55. ; retryinf.curr receiver:= n; ; goto start; ; end; ; action 21: start wait in data overrun loop ; tr.state : any ; err.kind : data overrun n21 : bz w0 x2+m1 ; sz w0 q41 ; if -,error recovery.mode.curr buf jl. j96. ; then goto deliver error; al w0 1 ; regretted.curr receiver:= 1; rs w0 x1+a56 ; c. to prevent start if buf arrives rl w3 x1+a235 ; dev:= device descr.curr receiver; al w1 x3 ; timer:= (dev >> 5) << 9; ls w1 -5 ; c. (controller io no)*512; ls w1 9 ; c. to ensure diff. waiting periods for diff. devices al w0 2<2+1 ; function:= start wait, std exit; al w2 0 ; buf:= 0; jd 1<11+100 ; start io(function,timer,buf,dev); ; action 22: final action, acts as a stopper. ; tr.state : any ; err.kind : any n22 : al w0 4 ; result:= 4; c. malfunction; jl. w3 j14. ; clean(result); jl. j112. ; goto start wait; e. ; end of block containing error actions \f ; pej 04.10.77 disc driver, variables ; m o d e t a b l e ; each entry contains strobe and offset information corre- ; sponding to bit 16-19 in a setmode parameter. modeindex in ; retryinformation - 1 is an index to the table. q23 = 3 ; first mode index in next round q24 = 8 ; last modeindex h. ; strobe offset q20 : 2.0100<4 ; +0: late 2.1000<4 ; +1: early 2.0001<4 ; +2: negative 2.0010<4 ; +3: positive 2.0101<4 ; +4: late negative 2.0110<4 ; +5: late positive 2.1001<4 ; +6: early negative 2.1010<4 ; +7: early positive -1 ; +8: top of table ; o f f s e t t a b l e ; each entry contains offset magnitude corresponding to bit 20-23 ; in a setmode parameter. offset index in retryinformation is ; an index to the table. q21 : 8,15,1,3,6,10,13,2,4,5,7,9,11,12,14 ; +0 - +14 -1 ; +15: top entry w. ; variables 1 ; -2: result (1) i27 : 8.02000000 ; blocklength error: +0: status (bit 4) 1 ; -2: result (1) i28 : 8.00010000 ; discerror: +0: status (bit 11) 1 ; -2: result (1) i29 : 0 ; ok: +0: status(0) i40 : i24 ; mask for zeroes in compound at output i41 : 2.11111000 ; mask for zeroizing readtries.retryinf i42 : q10 ; time between sense in power rest. loop i43: 1<22+1<19+1<8 ; compound status: data or hard err,abnorm term i44: q24<8+3 ; last modeindex<8+maxtries(retry inf) i45: 2.000011111000 ; mask for zeroize modeindex or tries (retryinf) \f ; pej 26.09.77 disc driver, compound status ; procedure compoundstatus(curr status,event status,compound) ; --------------------------------------------------------------- ; ; the procedure performs: ; - creates a compound status word from curr status and event ; status and i/o result from device descr, so that: ; ; bit 0 intervention event status bit 0 ; 1 data error - - - 1 ; 2 (unused, = 0) ; 3 data overrun - - - 3 ; 4 hard error - - - 4 ; 5 position error - - - 5 ; 6 power low curr - - 0 ; 7 local - - - 1 ; 8 write protect - - - 8 ; 9 high density - - - 9 ; 10 mode - - - 10 ; 11 seek error - - - 5 ; 12 (unused, = 0) ; 13 power restart i/o result 6 ; 14 wait pg. terminated - - 5 ; 15 abnormal termination - - 4 ; 16 software timeout - - 3 ; 17 bustimeout, disconn. - - 2 ; 18 bus reject, busy - - 1 ; 19 normal termination - - 0 ; 20 bus com, error event status bit 20 ; 21 interrupt error - - - 21 ; 22 bustimeout - - - 22 ; 23 bus parity error - - - 23 ; ; registers: call exit ; wo curr status compound status ; w1 event status curr receiver ; w2 destroyed ; w3 link unchanged ; ; entry : j8 ; ; return : link+0 b. i1 w. j8 : ; compound status: rl w2 0 ; i:= curr status >> 6; ls w2 -6 ; c. bit(6:7):= bit(0:1), bit11:= bit5; lo w2 0 ; i:= i or curr status; la. w2 i0. ; i:= i and bit 6,7,8,9,10,11; la. w1 i1. ; mask out unused event status bits; lo w1 4 ; compound:= event status or i; c. w1; al w0 2.10000; i:= bit 19; am (b19) ; rl w2 a244 ; sh:= i-o result.curr receiver; ls w0 x2+0 ; i:= i shift sh; c. w0; lo w0 2 ; compound:= compound or i; c. w0; rl w1 b19 ; jl x3+0 ; ; variables i0 : 8.00770000 ; bit 6,7,8,9,10,11 i1 : 8.67000017 ; bit 0,1,3,4,5,20,21,22,23 e. \f ; pej 27.09.77 disc driver, set errorkind ; procedure set errorkind(errorkind) ; -------------------------------------------------------------- ; errorkind: bit 14: data overrun ; 15: after data overrun ; 16: intervention ; 17: power restart ; 18: power down (disc power) ; 19: time out ; 20: write protect ; 21: data error ; 22: addr mark error ; 23: other error ; ; the procedure performs: ; - updates tables of compound status and technical statusbits ; if statistics wanted. ; - sets the errorkind as a function of bits in compound status ; and bits in statuswords stored by controller. ; ; registers: call exit ; w0 errorkind ; w1 curr receiver unchanged ; w2 compound status ; w3 link destroyed ; ; entry : j9 ; ; return : link+0 b. i30 w. j9 : rs. w3 i10. ; set errorkind: save link; c. q1 ; if statistics wanted then rl w0 x1+p34 ; begin rl w2 x1+p33 ; i:= 0; al w3 x1+p47 ; repeat i26 : sl w0 0 ; if compound(i).curr rec = 1 jl. i27. ; al w1 1 ; then ba w1 x3+0 ; compound table(i).curr rec:= hs w1 x3+0 ; compound table(i).curr rec + 1; i27 : sl w2 0 ; if technical(i).curr rec = 1 jl. i28. ; al w1 1 ; then ba w1 x3+p48-p47; technical table(i).curr rec:= hs w1 x3+p48-p47; technical table(i).curr rec + 1; i28 : al w3 x3+1 ; ls w0 1 ; ls w2 1 ; i:= i + 1 sn w0 0 ; until compound(i+1:23) = 0 and se w2 0 ; technical(i+1:23) = 0; jl. i26. ; rl w1 b19 ; z. ; end; rl w2 x1+p34 ; ac2:= compound status.curr rec; so. w2 (i6.) ; if data overrun then jl. i29. ; begin sz w2 8.200 ; if timeout jl. i15. ; then goto after data overrun jl. i14. ; else goto data overrun; i29 : ; end; rl w3 x1+p16+6 ; event:= event.statusarea 1.curr rec; sz. w2 (i0.) ; if compound and mask1 = 0 jl. i24. ; so. w3 (i1.) ; and dataerr.event and harderr.event jl. i24. ; then goto data error; jl. i21. ; i24 : rl w0 x1+a233 ; event:= event.std status.curr rec; sz. w2 (i2.) ; if compound and mask2 = 0 jl. i25. ; rl w3 x1+a230 ; se w3 0 ; and chan pg count.std status.curr rec bz w3 x3-6+1 ; <> 0 ls w3 -8 ; and latest command executed = read sn w3 1 ; so. w0 (i3.) ; and harderr.event and pos err.event jl. i25. ; jl. i22. ; then goto addr mark error; i25 : sz w2 8.2000 ; if power restart.compound jl. i17. ; then goto power restart; sz. w2 (i4.) ; if powlow.compound or discon.compound jl. i18. ; then goto power low; sz w2 8.200 ; if timeout.compound jl. i19. ; then goto timeout; sz. w2 (i5.) ; if interv.compound or local.compound jl. i13. ; then goto check power up; sz. w2 (i7.) ; if write protect.compound jl. i20. ; then goto write protect jl. i23. ; else goto other error; i13: ; check power up: rl w0 b75 ; if power up not yet serviced se w0 0 ; by clockdriver jl. i18. ; then goto power down jl. i16. ; else goto intervention; i14 : am 512-256; data overrun : set kind bit 14 i15 : am 256-128; aft. data ov. : 15 i16 : am 128-64 ; intervention : 16 i17 : am 64-32 ; power restart : 17 i18 : am 32-16 ; power down : 18 i19 : am 16-8 ; time out : 19 i20 : am 8-4 ; write protect : 20 i21 : am 4-2 ; data error : 21 i22 : am 2-1 ; addr mark error: 22 i23 : al w0 1 ; other error : 23; jl. (i10.) ; return; ; variables i0 : 8.45613757 ; mask1, data error, mask for zeroes i1 : 8.22000000 ; bit 1,4 i2 : 8.44613377 ; mask2, addr mark err, mask for zeroes i3 : 8.03000000 ; bit 4,5 i4 : 8.00400100 ; bit 6,17 i5 : 8.40200000 ; bit 0, 7 i6 : 8.04000000 ; bit 3, data overrun i7 : 8.00100000 ; bit 8 i10 : 0 ; saved link e. \f ; pej 27.09.77 disc driver, set result and status ; procedure set result and status(result,status). ; -------------------------------------------------------------- ; result: 4 if bit 16 in compound status (software timeout) ; - - 18 - - - (bus reject, busy) ; - - 20 - - - (communication error) ; - - 21 - - - (interrupt error) ; - - 22 - - - (bustimeout) ; - - 23 - - - (bus parity error) ; if no bits are set in status. ; 1 if bits are set in status. ; status: bit 1 (parity) if bit1,4 in compound (data,hard) ; bit 2 (sync.err) - - 5 - - (pos.error) ; bit 3 (data overr.) - - 3 - - (data overr.) ; bit 5 (end med.) - - 11 - - (seek error) ; ; the procedure performs: ; - calculates result and status from compound status. ; ; registers: call exit ; w0 result ; w1 status ; w2 curr buf ; w3 link unchanged ; ; entry : j10 ; ; return : link+0 b. i4 w. j10 : am (b19) ; set result and status: rl w2 p34 ; sz. w2 (i0.) ; if compound and result 4 mask am 4-1 ; then result:= 4 al w0 1 ; else result:= 1; al w1 0 ; status:= 0; sz. w2 (i1.) ; if compound and seek error mask al w1 x1+1<6 ; then status:= status + end medium; sz. w2 (i2.) ; if compound and data/hard error mask al w1 x1+1<10 ; then status:= status + parity; sz. w2 (i3.) ; if compound and data overrun mask al w1 x1+1<8 ; then status:= status + data overrun; sz. w2 (i4.) ; if compound and position error mask al w1 x1+1<9 ; then status:= status + sync.error; sn w1 0 ; if status = 0 al w0 4 ; then result:= 4; ls w1 12 ; rl w2 b18 ; w2:= curr buf; jl x3+0 ; return; ; variables i0 : 8.00000257 ; result 4 mask, bit 16,18,20,21,22,23 i1 : 8.00010000 ; seek error mask, bit 11 i2 : 8.22000000 ; data/hard err mask, bit 1,4 i3 : 8.04000000 ; data overrun mask, bit 3 i4 : 8.01000000 ; pos.error mask, bit 5 e. \f ; pej 26.09.77 disc driver, update buf ; procedure update buf(segments,bytes) ; --------------------------------------------------------------- ; segments: no of segments transferred. ; bytes : no of bytes transferred per segment. must at calltime ; be stored in p35.curr receiver. ; ; the procedure performs: ; - updates curr buf by segments: ; first segment and firstaddr are incremented. ; no of segments and remaining segments are decremented. ; - updates table of error segments (successful transfer) if sta- ; tistics wanted and a segment in the table lies in the ; interval given by first segment.curr buf and segments. ; ; registers: call exit ; w0 segments destroyed ; w1 curr receiver unchanged ; w2 curr buf unchanged ; w3 link destroyed ; ; entry : j11 ; ; return : link+0 b. i4 w. j11 : rs. w3 i0. ; update buf: save link; rl w3 x2+m4 ; wa w3 0 ; first segment.curr buf:= rs w3 x2+m4 ; first segment.curr buf + segments; c. q1 ; if statistics wanted then rs. w0 i2. ; begin am (x2+m10) ; wa w3 p3 ; top:= first segment.curr buf rs. w3 i1. ; + first segment.device.curr buf; ws w3 0 ; first:= top - segments; al w2 x1+p46-6 ; entry:= 1st error segment.curr rec; i3 : al w2 x2+6 ; while segment no.entry >= 0 and rl w0 x2+0 ; entry <> top entry do sl w0 0 ; begin sl w2 x1+p46+q2*6; if segmentno.entry >= first jl. i4. ; and segmentno.entry < top sl w0 (6) ; then goto found; sl. w0 (i1.) ; entry:= entry + 1; jl. i3. ; end; goto not found; am (b18) ; found: ba w2 m0 ; i:= operation.curr buf; bz w3 x2-1 ; al w3 x3+1 ; entry(i-1):= entry(i-1) + 1; hs w3 x2-1 ; i4 : rl w2 b18 ; not found: rl. w0 i2. ; z. ; end; bz w3 x2+m5 ; ws w3 0 ; no of segments.curr buf:= hs w3 x2+m5 ; no of segments.curr buf - segments; bz w3 x2+m9 ; ws w3 0 ; remaining segments.curr buf:= hs w3 x2+m9 ; rem segments.curr buf - segments; wm w0 x1+p35 ; b:= segments * bytes; wa w0 x2+m2 ; first addr.curr buf:= rs w0 x2+m2 ; first addr.curr buf + b; jl. (i0.) ; return; ; variables i0 : 0 ; saved link i1 : 0 ; saved top (segment) i2 : 0 ; saved param segments e. \f ; pej 28.09.77 disc driver, update buf on error ; procedure update buf on error(statusarea,bytes,chars) ; --------------------------------------------------------------- ; statusarea: addr of statusarea containing information about ; a read or write operation. ; bytes : see proc update buf. ; chars : no of chars transferred per segment. must at call- ; time be stored in p35+2.curr receiver. ; ; the procedure performs: ; - updates curr buf by calling proc update buf with segments ; according to transferred segments using remaining bytes in ; statusarea or, if statusarea undefined, then remaining bytes ; in std statusarea provided it relates to a read or write ; operation. ; please note that, due to a controller error (never to be ; corrected), remaining bytecount must be transformed as ; follows: ; if rem mod chars_per_segm <> 0 ; then rem:= rem - if data transfer then 65536 else 256 ; - leaves curr buf unchanged if neither statusarea nor std sta- ; tus area may be used. ; please note that if the error was of such a kind that the ; transfer specified in the channelprogram was completed ; (statusinformation etc. ok), but the channel program was ; not terminated normally (f.x. error during storing of std ; status), then this procedure may increment firstaddr.curr buf ; to a value equal to lastaddr.curr buf + 2. ; ; registers: call exit ; w0 destroyed ; w1 curr receiver unchanged ; w2 statusarea destroyed ; w3 link destroyed ; ; entry : j12 ; ; return : link+0 b. i5 w. j12 : rs. w3 i0. ; update buf on error: save link; rl w0 x2+2 ; rem:= rem bytecount.statusarea; rl w3 x2+0 ; se w3 0 ; if chan pg count.status area = 0 then jl. i1. ; begin c. statusarea undefined; rl w3 x1+a230 ; se w3 0 ; if chan pg count.stdstatus.curr rec bz w3 x3-6+1 ; <> 0 ls w3 -8 ; se w3 1 ; (and last command executed = read sn w3 3 ; or last command executed = write) jl. i2. ; then rem:= rembytes.stdstatus.curr jl. (i0.) ; else return; i2 : rl w0 x1+a231 ; i1 : rs. w0 i3. ; end; al w3 0 ; saved rem:= rem; wd w0 x1+p35+2 ; rem:= rem // chars; sn w3 0 ; if saved rem mod chars <> 0 then jl. i5. ; begin rl. w0 i3. ; rl w2 x1+p35+2 ; se w2 q53 ; rem:= saved rem - am 2 ; if chars = chars per data segm ws. w0 i4. ; then 65536 else 256; sh w0 -1 ; if rem < 0 jl. (i0.) ; then return; c. should be impossib; al w3 0 ; rem:= rem // chars; wd w0 4 ; end; i5 : ac w0 (0) ; rl w2 b18 ; segments:= ba w0 x2+m5 ; no of segments.curr buf - rem; rl. w3 i0. ; update buf(segments,bytes); jl. j11. ; c.return from there; ;variables i0 : 0 ; saved link i3 : 0 ; for saving rem i4 : 65536 ; constant for correcting rem, +0: data 256 ; +2: addr m e. \f ; pej 28.09.77 disc driver, update retryinformation ; procedure update retryinformation(retryinformation) ; --------------------------------------------------------------- ; retryinformation: addr of the byte containing retryinformation. ; bit 0- 3: modeindex ; bit 4- 8: offsetindex ; bit 9-11: tries ; ; the procedure performs: ; - increments tries. ; - increments modeindex if tries flows over and sets tries to 1. ; - increments offsetindex if modeindex flows over and sets mode- ; index to first value and tries to 1. not performed if ; variable offset impossible. ; ; registers: call exit ; w0 destroyed ; w1 retryinformation destroyed ; w2 destroyed ; w3 link unchanged ; ; entry : j13 ; ; return : link+0: no more tries possible ; link+2: next stobe-offset combination ; link+4: next offset magnitude ; link+6: tries <= 3 (mode/offset index unchanged) b. i4 w. j13 : rs. w1 i4. ; update retryinformation: bz w1 x1+0 ; r:= core(retryinformation) al w1 x1+1 ; tries.r:= tries.r + 1; hs. w1 (i4.) ; core(retryinformation):= r; so w1 2.100 ; if tries.r <= 3 jl x3+6 ; then return; c. link+6; la. w1 i0. ; tries.r:= 1; al w1 x1+i1 ; modeindex.r:= modeindex.r + 1; hs. w1 (i4.) ; core(retryinformation):= r; al w2 x1+0 ; ls w2 -8 ; bl. w0 x2+q20.-1 ; se w0 -1 ; if modetable(modeindex.r) <> -1 jl x3+2 ; then return; c. link+2; la. w1 i2. ; ls w1 -3 ; al w1 x1+1 ; i:= offsetindex + 1; bl. w0 x1+q21. ; am (b19) ; rl w2 p5 ; se w2 0 ; if disctype.curr receiver = 0 sn w0 -1 ; or offset table(i) = -1 jl x3+0 ; then return; c. link+0; ls w1 3 ; r:= modeindex for next round << 8 al w1 x1+i3 ; + i << 3 + 1; hs. w1 (i4.) ; core(retryinformation):= r; jl x3+4 ; return; c. link + 4; ; variables i0 : 2.111111111000 ; mask for zeroizing tries i1 = 2.000100000001 ; mask for incrementing modeindex, tries i2 : 2.000011111000 ; mask for zeroizing modeindex, tries i3 = q23<8+1 ; modeindex for next round << 8 + tries i4 : 0 ; saved param retryinformation e. \f ; pej 30.09.77 disc driver, clean ; procedure clean(result) ; --------------------------------------------------------------- ; result: result to be used as parameter to deliver result. ; ; the procedure performs: ; - returns all messages queued to the driver with above ; mentioned result. ; - zeroizes regretted.curr receiver. ; - sets transfer state.curr receiver idle. ; - if result = 5 (unknown) then state.curr receiver is set to ; after intervention, the name of curr receiver is zeroized ; and so is device address in all areaprocesses referring ; to curr receiver. the same is performed on eventual logical ; disc drivers referring to current receiver. ; ; registers: call exit ; w0 result destroyed ; w1 curr receiver ; w2 destroyed ; w3 link destroyed ; ; entry : j14 ; ; return : link+0 b. i7 w. j14 : ds. w0 i1. ; clean: save link, result; rl w1 b19 ; rl w2 g49 ; rs w2 x1+p13 ; transfer state.curr rec:= idle; al w2 0 ; rs w2 x1+a56 ; regretted.curr rec:= 0; rs w2 g20 ; status.i/o answer:= 0; rs w2 g21 ; bytes.i/o answer:= 0; rs w2 g22 ; chars.i/o answer:= 0; i2 : rl w2 x1+a54 ; while next message.curr rec <> sn w2 x1+a54 ; addr of next message.curr rec do jl. i3. ; begin rs w2 b18 ; curr buf:= next message.curr rec; jl w3 g19 ; deliver result(result); rl. w0 i1. ; jl. i2. ; end; i3 : se w0 5 ; if result <> 5 jl. (i0.) ; then return; al w0 0 ; rs w0 x1+p12 ; state.curr rec:= after intervention; rl w1 b4 ; proci:= addr of 1st device.nametable; i4 : rs. w1 i1. ; repeat rl w1 x1+0 ; proc:= nametable(proci); rl w3 x1+a10 ; rl w0 x1+p2 ; sn w0 (b19) ; if (mainproc.proc = curr receiver se w3 q61 ; and kind.proc = disc) sn w1 (b19) ; or proc = curr receiver then jl. i5. ; begin jl. i7. ; i5 : al w0 0 ; rs w0 x1+a11 ; name(0).proc:= 0; rs w0 x1+a52 ; reserver.proc:= 0; rl w3 b5 ; areai:= first areaproc.nametable; i6 : rl w2 x3+0 ; repeat area:= nametable(areai); sn w1 (x2+a50) ; if device addr.area:= proc rs w0 x2+a50 ; then device addr.area:= 0; al w3 x3+2 ; areai:= areai + 2 se w3 (b6) ; jl. i6. ; until areai = first internal; i7 : am. (i1.) ; end; al w1 2 ; proci:= proci + 2 se w1 (b5) ; jl. i4. ; until proci = first area proc; rl w1 b19 ; jl. (i0.) ; ; variables i0 : 0 ; saved link i1 : 0 ; saved result, proci in loop e. \f ; pej 04.10.77 disc driver, procedure correct data ; procedure correct data ; --------------------------------------------------------------- ; ; the procedure performs: ; - checks if the error correction information stored in status- ; area1 of curr receiver may be used for correcting the data ; segment pointed to by first addr.curr buf. ; - performs the correction by copying the bad word(s) ; from the buffer and back again after having corrected them. ; the copying is performed by calling a monitor procedure. ; two words are copied unless the errorburst starts in the ; base word or last word of the segment. ; ; registers: call exit ; w0 destroyed ; w1 curr receiver destroyed ; w2 curr buf if corrected ; w3 link destroyed ; ; entry : j15 ; ; return : link+0: data not corrected ; link+2: data corrected b. i25 w. j15 : rs. w3 i0. ; correct data: save link; al w2 x1+p16+16 ; addr:= ld w1 -100 ; addr of ecc inf.statusarea1.curr rec; ds. w1 i2. ; sum:= 0; jl. w3 i16. ; sum:= sum 21 ; + (21 - char0.addr) 452387 ; * 452387; jl. w3 i16. ; sum:= sum 88 ; + (88 - char1.addr) 72358 ; * 72358; jl. w3 i16. ; sum:= sum 12 ; + (12 - char2.addr) 315238 ; * 315238; al w2 x2+2 ; c. now eccinf(0) = 0; addr:= addr + 2; jl. w3 i16. ; sum:= sum 22 ; + (22 - char0.addr) 330902 ; * 330902; wd. w1 i3. ; c. now eccinf(2) = err pattern << 8; al w1 x1+1 ; bitdisp:= wm. w1 i3. ; (sum // 585442 + 1) * 585442 ws. w1 i2. ; - sum - 56 + 16; al w0 x1-56+16 ; c. is now base for error pattern; sl. w0 (i5.) ; if bitdisp outside segment jl. (i0.) ; then not corrected return; c. link+0; sh w0 0 ; if bitdisp <= 0 jl. i15. ; then goto corrected; rl w2 0 ; c. error entirely in checkcharacters; al w2 x2+11 ; al w1 0 ; bytedisp:= wd. w2 i6. ; (bitdisp + 11) / 12; c. w2; al w3 0 ; wd. w0 i8. ; al w3 x3-24 ; sh:= -24 + (bitdisp mod 24); sn w3 -24 ; if sh = - 24 al w3 0 ; then sh:= 0; rs. w3 i9. ; save sh; al w0 q52 ; ws w0 4 ; relative:= la w0 g50 ; even (segment size - bytedisp); c.w0; al. w1 i10. ; c. relative to firstaddr.curr buf; al. w3 i11. ; first:= first bad; last:= second bad; se w0 -2 ; if relative = -2 then jl. i17. ; begin c. only one word; al w0 0 ; relative:= 0; first:= last; al w1 x3+0 ; end; i17 : sn w0 q52-2 ; if relative = segmentsize - 2 al w3 x1+0 ; then last:= first; c. only 1 word; rl w2 b18 ; buf:= curr buf; rs. w1 i21. ; save first rl. w1 i25. ; store mode.call rs. w1 i20. ; ds. w0 i23. ; save relative,last al. w1 i20. ; w1:= parameter address jd 1<11+84; general copy(params,buf) se w0 0 ; if result <> 0 jl. (i0.) ; then not corrected return; c. link+0; am (b19) ; c. align the err pattern to error; rl w3 p16+18 ; w3:= eccinf(2).statusarea1.curr rec; al w0 0 ; w0:= 0; ld. w0 (i9.) ; w3w0:= w3w0 shift sh; lx. w3 i10. ; first bad:= first bad xor w3; lx. w0 i11. ; second bad:= second bad xor w0; ds. w0 i11. ; rl. w1 i24. ; change function in parameter list(from=curr,to=buf) rs. w1 i20. ; al. w1 i20. ; w1:= parameter address jd 1<11+84; general copy(params,buf) se w0 0 ; if result <> 0 jl. (i0.) ; then not corrected return; c. link+0; i15 : am. (i0.) ; corrected: jl 2 ; return; c. link + 2; ; routine for updating sum. the routine performs: ; sum:= sum + (k - (core(addr) shift (-16)) * m ; core(addr):= core(addr) shift 8 ; registers: call w2=addr, w3=link ; exit w0w1=sum (also stored in i1i2), w2,w3=unch ; call : jl. w3 i16. ; k link+0 ; m link+2 ; returnpoint link+4 i16 : rl w1 x2+0 ; update sum: al w0 0 ; w1:= core(addr); w0:= 0; ld w1 8 ; w0w1:= w0w1 shift 8; rs w1 x2+0 ; core(addr):= w1; sz w0 8.200 ; if char in w0 negative jl. (i0.) ; then not corrected return; rl w1 x3+0 ; ws w1 0 ; w1:= k - w0; wm w1 x3+2 ; w0w1:= w1 * m; aa. w1 i2. ; w0w1:= sum:= sum + w0w1; ds. w1 i2. ; jl x3+4 ; return; ; variables i0 : 0 ; saved link i1 : 0 ; double word for sum i2 : 0 ; - - i3 : 585442 ; constant used in calculations i6 : 12 ; - - - - i8 : 24 ; - - - - i5 : q53*8+16 ; largest bitdisplacement + 1 + 16 i9 : 0 ; saved sh (shifts to align err pattern) i10 : 0 ; to receive first bad word i11 : 0 ; - - 2nd - - ; parameters for general copy: i20 : 2<1+0 ; function(pair<1+mode),init: from=buf,to=curr i21 : 0 ; first i22 : 0 ; last i23 : 0 ; relative i24 : 2<1+1 ; function(from=curr,to=buf) i25 : 2<1+0 ; function(from=buf,to=curr) e. \f ; pej 17.11.77 disc driver, update on corrected error ; procedure update on corrected error ; --------------------------------------------------------------- ; ; the procedure performs: ; - updates statistics concerning an error which has been ; corrected either by incrementing the counter for errors ; corrected within 3 retries (setmode param.curr receiver = 0) ; or by incrementing a counter in the tables for errors ; corrected by strobe-offset. ; ; registers: call exit ; w0 destroyed ; w1 curr receiver unchanged ; w2 unchanged ; w3 link destroyed ; ; entry : j16 - used at transput ; j17 - used at control ; return : link + 0 c. q1 b. i3 w. j16 : rl w0 x1+p21 ; update on corrected transput error: se w0 0 ; if setmode param.curr rec = 0 then jl. i1. ; begin j17 : am (x1+p43) ; update on corrected control error: al w0 1 ; corrected in 3 tries.curr rec:= rs w0 x1+p43 ; corrected in 3 tries.curr rec + 1; jl x3+0 ; end else i1 : rs. w3 i0. ; begin c. strobe-offset used; ls w0 -4 ; i:= setmode param(16:19).curr rec; am (0) ; c. strobe and offset; bz w3 x1+p44-1 ; al w3 x3+1 ; strobe offset table(i-1).curr rec:= am (0) ; strobe offset table(i-1).curr rec+1; hs w3 x1+p44-1 ; c. i-1 as value 1 is counted in rl w0 x1+p21 ; byte o; sz w0 2.11<4 ; if setmode param(18:19).curr rec =0 jl. i2. ; then jl. (i0.) ; begin i2 : la. w0 i3. ; i:= setmode param(20:23).curr rec; am (0) ; c. offset magnitude; bz w3 x1+p45 ; al w3 x3+1 ; offset magn. table(i).curr rec:= am (0) ; offset magn. table(i).curr rec + 1; ; end; hs w3 x1+p45 ; end; jl. (i0.) ; return; ; variables i0 : 0 ; saved link i3 : 2.1111 ; for masking out offset magnitude e. z. \f ; pej 04.10.77 disc driver, end of code z.e. ; end disc driver block e. ; end area process-disc driver block b. p22, m50, n114 w. ; block including ioc and dlc main process. ; ------------------------------------------------------------------------- ; ; I O C M A I N P R O C E S S D R I V E R ; ; D L C M A I N P R O C E S S D R I V E R ; ; ------------------------------------------------------------------------- ; ; ; the main processes supports the following operations: ; ; IOC DLC ; -------------------------- ----------------------------- ; ; - dump (*) ; - prepare dump (*) ; - create link (*) - create link (*) ; - extract statistics - extract statistics ; - remove link (*) - remove link (*) ; - set mask - set mask ; - link logical disc ; - unlink logical disc ; - test (*) ; - initialize controller (*) - initialize controller (*) ; ; RC8000-IDA/IFP ; -------------------------- ; ; - input ; - output ; - position ; ; driverproc messages ; ----------------------------- ; - answer create link ; - answer remove link request ; - answer attention ; - stop normal communication (only rc8000) ; ; (*) the (possible re-formattet) message is transmitted to the controller ; ; ; execution of messages: ; ---------------------- ; ; when a message is received by the mainprocess, it is claimed ; (receiver is negated). ; only one message is executed by (the 1st part of) the driver at a ; time. when the message is executed in this part of the driver it is ; in no queue. if the message isn't going to be transmitted to the ; controller (those operation which are not marked '(*)' above) the ; answer to the message is returned before the next message is received ; (i.e. the message will never be in the event queue of the main ; process). ; if the message is going to be transfered to the controller (all ; operations marked '(*)') the message will be delivered to the 2ed ; part of the main driver, where it will be linked either to the ; waiting queue of the main process or to the event queue of the ; receiver. at this time the 1st part of the driver will never see ; the message/answer again (except for the create/remove link ; operations where it receives an interrupt-operation). ; the 1st part of the driver need not to worry about regret of messages ; as it will never receive a regretted message. the second part (setup ; part) of the driver will take a proper action on a regretted message ; if it is regretted while it is under execution (either in the rc8000 ; or in the controller). ; \f ; use of names: ; ------------- ; m main routines (one for each operation) ; ; n sub-routines ; ; p names of operations ; ; ; definition of operations ; p2 = 2 ; prepare dump p6 = 6 ; create link p9 = 9 ; extract statistics p10 = 10 ; remove link p12 = 12 ; set mask p14 = 14 ; dump p16 = 16 ; link logical disc p18 = 18 ; unlink logical disc p20 = 20 ; test p22 = 22 ; initialize controller p3 = 3 ; ida/ifp input p5 = 5 ; ida/ifp output p8 = 8 ; ida/ifp position ; ***** stepping stones ***** jl. (+2), d150 , d150 = k - 4 jl. (+2), d151 , d151 = k - 4 jl. (+2), d156 , d156 = k - 4 \f ; ; M E S S A G E R E C E I V E D B Y M A I N P R O C E S S . ; --------------------------------------------------------------- ; ; Control is transfered to this part when driverproc receives a ; message sent to an IOC or DLC main process. ; ; From driverproc the following messages can be received: ; stop normal communication - 4 ; answer attention - 3 ; answer remove link request - 2 ; answer create link - 1 ; remove link 10 ; ; At entry the registers contains: ; ; w0 - ; w1 sender ; w2 message ; w3 main process ; b. i10, j10 w. h20: ; message received h26: ; rs. w1 i1. ; begin rl w3 b21 ; zl w0 x3+a19 ; <* claim the buffer - driverproc will have claims bs. w0 1 ; enough as it received the message in wait event hs w0 x3+a19 ; and unclaimed it 'by hand' when it received it *> ac w3 (x2+a141) ; rs w3 x2+a141 ; ; sn w1 (b21) ; if message.sender = driverproc then jl. j3. ; goto branch; <* skip all checks *> ; rl w1 b19 ; <* select the proper operation/mode mask al w0 2.0111 ; depending on main state and main kind *> la w0 x1+a78 ; al w3 8 ; if main.connect_state = connected then sn w0 l38 ; index := connect_mask al w3 0 ; else index := free_mask; rl w0 x1+a10 ; se w0 q20 ; if main.kind = ifp_main then al w3 x3+4 ; index := index or ifp_mask al. w3 x3+i2. ; else index := index or ida_mask; dl w1 x3+0 ; jl w3 g16 ; check operation(operation mask, mode mask, message); ; rl. w1 i1. ; zl w3 x2+a150 ; if message.operation needs reservation then rl. w0 i3. ; ls w0 x3 ; check reserver(sender, message) sh w0 -1 ; else am g15-g14; check user(sender, message); jl w3 g14 ; ; zl w0 x2+a138+1 ; so w0 2.1 ; if message.state.io then jl. j3. ; begin jl w3 g34 ; if message.regretted or sz ; message.sender.state = stopped then jl. j2. ; begin rl w3 b20 ; no operation; jl g26 ; goto driverproc.wait event; ; end; ; j2: jl w3 g31 ; increase stopcount(message.sender); sn w0 p9 ; if message.operation <> extract statistics then jl. j3. ; begin ; rl w3 x2+a152 ; message.no of bytes := al w0 x3+2 ; (last address - first address + 2)/2 * 3; ws w0 x2+a151 ; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; ; rl w0 x2+a151 ; message.first address := wa w0 x1+a182 ; message.first address + sender.base; rs w0 x2+a151 ; <* physical address *> ; end; ; end; ; j3: el w3 x2+a150+0 ; branch: ls w3 +1 ; jl. (x3+i5.) ; goto case message.operation of ; m34 ; -4 : stop normal communication m33 ; -3 : answer attention m32 ; -2 : answer remove link request m31 ; -1 : answer create link i5: m0 ; 0 : sense -1 ; 1 : - m1 ; 2 : prepare dump / set tiomout (ida/ifp) m3 ; 3 : ida/ifp input m4 ; 4 : ida/ifp reset m5 ; 5 : ida/ifp output m6 ; 6 : create link -1 ; 7 : - m8 ; 8 : ida/ifp position m9 ; 9 : extract statistics m10 ; 10 : remove link -1 ; 11 : - m12 ; 12 : set mask -1 ; 13 : - m14 ; 14 : dump -1 ; 15 : - m16 ; 16 : link logical disc -1 ; 17 : - m18 ; 18 : unlink logical disc -1 ; 19 : - m20 ; 20 : test -1 ; 21 : - m22 ; 22 : initialize controller i1: 0 ; saved w1 (sender) ; ; format of the operation/mode mask table: ; -2 : ida/ioc, connected, operations ;i2: 0 : ida/ioc, connected, modes ; 2 : ifp/dlc, connected, operations ; 4 : ifp/dlc, connected, modes ; 6 : ida/ioc, not connected, operations ; 8 : ida/ioc, not connected, modes ; 10 : ifp/dlc, not connected, operations ; 12 : ifp/dlc, not connected, modes a0>3+a0>4+a0>5+a0>6+a0>8+a0>9+a0>10+a0>12+a0>16+a0>18+a0>22 i2: a0>0 + a0>1 + a0>2 + a0>3 + a0>4 + a0>5 a0>0+a0>2+a0>3+a0>4+a0>5 + a0>6 +a0>8 + a0>9 + a0>10 + a0>12 + a0>22 a0>0 + a0>1 + a0>2 + a0>3 + a0>4 + a0>5 + a0>6 a0>4+a0>5+a0>9+a0>12+a0>22 a0>0+a0>1+a0>2 a0>2+a0>3+a0>4+a0>5+a0>9+a0>12+a0>22 a0>0+a0>1+a0>2+a0>3+a0>4+a0>5+a0>6 ; the following operations needs reservation: i3: a0>4 e. ; end *** message received ***; \f ; sense ;---------------------------------------------------------------------------- ; message (sender format) message (when delivered to part 2) ; --------------------------- ---------------------------------- ; ; + 0: 0 < 12 + 0 0 < 12 + 0 ; + 6: timeout value (0.1 msec) ; ; ; at entry: ; ; w0 - ; w1 sender ; w2 message ; w3 - ; m0: ; sense: rl w1 b19 ; rl w3 x1+a87 ; rs w3 x2+a153 ; mess_3:=timeout value; al w0 0 ; force := no; jl. (n100.) ; start_controller(force); \f ; set timeout (ifp) ;---------------------------------------------------------------------------- ; ; The timevalue is set in the mainprocess. If the value exceeds 800 sec. ; timeout will be set to 800 sec. ; If timeout is set to 0, the timeout supervision is disabled. ; NOTE: the procedure is called from m2. ; The operation does not involve the ifp. ; ; message (sender format) ; +0 2<12 +0 ; +2 timeout value (in sec.) ; ; ; at entry: ; w0 - ; w1 sender ; w2 message ; w3 - b. i1 w. m1: rl w0 x2+a151 ; if mess.timeout < 0 then deliver result(3) sh w0 -1 ; jl g5 ; ; sl w0 800 ; if mess.timeout > 800 sec then al w0 800 ; main.timeout := 800 sec wm. w0 i1. ; rl w1 b19 ; rs w0 x1+a87 ; else main.timeout := mess.timeout al w0 0 ; rs w0 g20 ; deliver result(1) jl g7 ; i1: 10000 ; timeout in 0.1 msec e. \f c.-(:a399>23a.1:) m2=-1 z. c.(:a399>23a.1:)-1 ; prepare_dump (ioc) ; ----------------------------------------------------------------------------- ; ; the area specifed in the message is reserved for dump of the two specified ; core areas. ; the core areas will be changed if necessary to be a multiplum of the ; segment size by first decrementing (if possible) the first_address and then ; (if necessary) increment the last_address. ; the area process must be reserved by the sender when the message is received ; by the main process. ; ; message (sender format) message (when delivered to part 2) ; --------------------------- ---------------------------------- ; ; + 0: 2 < 12 + 0 2 < 12 + 0 ; + 2: first address (low core) first address (low core) ; + 4: last address (low core) 0 (no of bytes) ; + 6: first address (high core) first segment (disk: phys, area: 0) ; + 8: last address (high core) no of segments ; +10: dump_device 0 (next logical segment if area) ; +12: first segment (if dump dev=disk) first address (high core) ; +14: - no of segments (in high core) ; ; the format of the message when delivered to part 2 is close to the i/o ; format of a message to an area process. ; ; at entry: ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j20 w. m2: ; prepare dump/set timeout am b19 ; rl w0 +a10 ; if main.kind = ifp then goto set timeout se w0 q20 ; else jl. m1. ; ds. w2 i2. ; begin ; ------- check specified dump device ------- rl w1 x2+a155 ; rl w3 (b6) ; proc := message.dump_device; rl w0 (b4) ; sl w1 (0) ; if not proc within area or external then sl w1 x3 ; deliver_result(3); jl g5 ; ; rl w3 x1+a11 ; if proc.name = 0 or rl w0 x1+a10 ; proc.kind <> area and sn w3 0 ; proc.kind <> disk then jl g5 ; deliver_result(3); se w0 q4 ; sn w0 q6 ; sz ; jl g5 ; al w3 x1 ; p := proc; sz ; j1: rl w3 x3+a50 ; while p.kind <> ioc_main rl w0 x3+a10 ; begin se w0 q20 ; p := proc.main; jl. j1. ; end; ; se w3 (b19) ; if p <> this main then jl g5 ; deliver_result(3); ; rl w0 x1+a10 ; size := se w0 q4 ; if dump_device.kind = area then jl. j0. ; area.number_of_segments rl w0 x1+a61 ; else sz ; disk.number_of_segments; j0: rl w0 x1+a74 ; rs. w0 i4. ; ; rl w3 x3+a200 ; se w3 0 ; if this main.pending_prepare_dump <> 0 then jl g5 ; deliver_result(3); ; al w2 x1 ; rl. w1 i1. ; jl w3 d113 ; check_reserver(internal, proc); jl g6 ;+0: other: deliver_result(2); sz ;+2: internal: ok; jl g6 ;+4: none: deliver_result(2); ; ; -------- check addresses -------- al w0 2 ; rs. w0 i6. ; check high core addresses first ; rl w2 b18 ; j9: am. (i6.) ;check_addresses: dl w1 x2+a152 ; la w0 g50 ; first := message.first & -2; <* even *> la w1 g50 ; last := message.last & -2; <* even *> am. (i6.) ; message.first := first; rs w0 x2+a151 ; ; sl w0 0 ; if first > 8Mhw or sh w1 -1 ; last > 8Mhw or jl g5 ; last > core_size then sl w1 (b12) ; deliver_result(3); jl g5 ; ; al w1 x1+2 ; ws w1 0 ; dump_size := last - first + 2; sh w1 -1 ; if dump_size < 0 then jl g5 ; deliver_result(3); ; al w0 0 ; no_of_segm,rest := dump_size / 512; wd w1 b221 ; sn w0 0 ; if rest <> 0 then jl. j11. ; begin am. (i6.) ; rl w3 x2+a151 ; if message.first <> 0 then sn w3 0 ; begin jl. j10. ; ws w3 0 ; sh w3 0 ; first := message.first - rest; al w3 0 ; if first < 0 then first := 0; la w3 g50 ; first := first & -2; <* even *> am. (i6.) ; rs w3 x2+a151 ; message.first := first; jl. j9. ; goto check_addresses; ; end j10: ; else am. (i6.) ; begin rl w3 x2+a152 ; wa w3 0 ; last := message.last + rest & -2; <* even *> la w3 g50 ; am. (i6.) ; rs w3 x2+a152 ; jl. j9. ; goto check_addresses; ; end; ; end; j11: ; sl. w1 (i4.) ; if no_of_segm > size then rl. w1 i4. ; no_of_segm := size; am. (i6.) ; rs w1 x2+a152 ; message.no_of_segments := no_of_segm; rl. w0 i4. ; ws w0 2 ; size := size - no_of_segm; rs. w0 i4. ; ; al w0 0 ; if address_pair = last then rx. w0 i6. ; begin se w0 0 ; address_pair := first; jl. j9. ; goto check_addresses; ; end; rl w0 x2+a152 ; wa w0 x2+a154 ; if message.no_of_segments = 0 then sn w0 0 ; deliver_result(3); jl g5 ; ; dl w0 x2+a154 ; <* save high core addr in mess_6 - mess_7 *> ds w0 x2+a157 ; ds w0 b28 ; <* save high core addr in monitor for post mortem *> dl w0 x2+a152 ; ds w0 b27 ; <* save low core addr in monitor for post mortem *> ; rs w0 x2+a154 ; <* transform the format to resemble the al w0 0 ; area i/o format *> rs w0 x2+a152 ; rs w0 x2+a153 ; ; rl w3 b19 ; rs w2 x3+a200 ; main.pending_prepare_dump := message; al w1 0 ; main.dump_device := message.dump_device; rx w1 x2+a155 ; message.dump_device := 0; <* area: next logical segment *> rs w1 x3+a201 ; rl w0 x1+a10 ; if dump_device.kind = area then se w0 q4 ; begin jl. j12. ; al w2 x1 ; insert_reserver(driverproc, area); rl w1 b21 ; jl w3 d125 ; jl. j13. ; end j12: ; else rl w0 x2+a155 ; begin wa w0 x1+a73 ; message.first_segment := rs w0 x2+a153 ; message.first_logical_segment + ; disk.first_segment; j13: ; end; ; al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; i1: 0 ; save w1 i2: 0 ; save w2 i4: 0 ; size i6: 0 ; address pair: 0 a151 - a152 ; 2 a153 - a154 ; e. ; end; z. \f ; ; reset (ida & ifp) ; ------------------------------------------------------------------------- ; ; message (sender format) answer ; ----------------------- ------ ; + 0: 4<12 + mode 0 ; + 2: ifp_type (if soft_reset) ; ; the controller will be reset. for ida it will always be a hard reset ; (where the comm. area is not used); for ifp it will be a hard reset if ; mode <> 2 otherwise it will be a soft reset involving a reset operation ; to be sent to the controller - in this case an answer is returned when ; the ifp controller is ready. In this case cleanup is performed when the ; answer arrives. ; the process complex in rc8000 concerning this controller is cleaned up ; i.e. all pending messages are returned with result 4, and all physical ; disc, mt processes or gsd processes are removed. ; ; at entry: ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j10 w. m4: ; reset rl w1 b4 ; begin j0: rl w3 x1 ; for proc := first external, next until last external do rl w0 x3+a10 ; begin se w0 q6 ; jl. j1. ; if proc.kind = disc and rl w0 x3+a50 ; se w0 (b19) ; proc.main = this main and jl. j1. ; rl w0 x3+a70 ; proc.next logical disc <> 0 then se w0 0 ; jl g5 ; deliver result(3); ; j1: al w1 x1+2 ; se w1 (b5) ; jl. j0. ; end; ; rl w1 b19 ; al w0 2.100000 ; main.state := not_ok; lo w0 x1+a78 ; hs w0 x1+a78+1 ; rs w1 x1+a77 ; main.proc_id := main; <* just to initialize it *> ; al w0 0 ; ; rs w0 x1+a76 ; main.device_id := 0; <* - " - *> ; rl w0 x1+a10 ; if main.kind = ifp_main and am (b18) ; message.mode = soft_reset then zl w3 +a150+1 ; begin se w0 q20 ; se w3 2 ; jl. j2. ; al w0 2 ; force := strong; <* ignore state of main *> jl. (n100.) ; start_controller(force); ; <* never reached *> j2: ; end ; else rl w3 x1+a235 ; begin sn w0 q26 ; rs w3 b58 ; <* place ifp device addr in monitor table *> al w2 0 ; se w0 q26 ; if main.kind = ifpmain then am 2.01<1 ; reset(har_ifp_reset) do w2 x3+0 ; else reset(normal); la w3 b212 ; wa w3 b65 ; <* clear any pending interrupt from contrller *> rl w0 x3+a313 ; gp w0 b95 ; ; jl. w3 (n109.) ; cleanup; ; rl w1 b19 ; <* give the main process a few free al w0 3 ; buffers to play with *> ls w0 12 ; rs w0 x1+a78+0 ; proc.free_buffers := 3; proc.state:=free; al w0 0 ; status := 0; rs w0 x1+a86 ; rs w0 g20 ; al w2 x1+a242 ; se w2 (x2) ; if in timeout queue then jl w3 d5 ; remove (main, timeout_queue) jl g7 ; deliver_result(1); ; end; ; e. ; end; \f ; create link (ioc & dlc) ; ------------------------------------------------------------------------- ; ; if the specified rc8000 device number is -1 a free subprocess is ; selected (and the device no will be placed in word +6 of the message). ; the subprocess is (partly) initialized and the state of the subprocess ; is set to 'during connect'. ; the rest of the process is initialized when the maindriver receives ; a create link answer operation from the controller. ; ; IOC: message (sender/setup format) answer (*) ; ----------------------------- ---------- ; + 0: 6<12 + mode status ; + 2: control module/formatter RC8000 device number ; + 4: slave device/station no controller device index ; + 6: RC8000 device no/-1 (**) device kind ; + 8: device kind, device type device capacity ; ; ; mode: 0: include sender as user of connection ; 1: include users of main as users of connection ; ; device kind: ; 6: disk ; 18: tape ; ; device type: none is defined ; ; DLC: message (sender/setup format) answer ; ----------------------------- ---------- ; + 0: 6<12 + mode status ; + 2: device type (0-9) RC8000 device number ; + 4: controller index/255 ; + 6: RC8000 device no/-1 (**) ; + 8: name in controller ; +10: - " - ; +12: - " - ; +14: - " - ; ; mode: as for IOC ; ; device type: see device type table (i0:) ; ; (*) the answer is created by the controller. ; (**) RC8000 process address inserted instead of device no in part 1. ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j20 w. m6: ; create link rl w1 x2+a153 ; begin se w1 -1 ; jl. j3. ; if message.rc8000_device_no = -1 then ; begin rl w1 b5 ; for proc := last external, next until first external do al w1 x1-2 ; j1: rl w3 x1 ; begin rl w0 x3+a10 ; sn w0 q68 ; if proc.kind = free subprocess then jl. j4. ; goto out; ; end; j2: al w1 x1-2 ; sl w1 (b4) ; jl. j1. ; goto no_resources; jl. j20. ; end ; else j3: ls w1 +1 ; begin wa w1 b4 ; sl w1 (b4) ; if not message.rc8000_device_no within external then sl w1 (b5) ; deliver_result(3); jl g5 ; rl w3 x1 ; proc := nametable(rc8000 device no); rl w0 x3+a10 ; if proc.kind <> free subprocess then se w0 q68 ; goto no_resources; jl. j20. ; ; end; j4: am (b19) ;out: rl w0 +a10 ; <* w3: proc *> se w0 q20 ; if this main.kind = ioc_main then jl. j5. ; begin ; zl w0 x2+a154 ; kind := message.device_kind; se w0 q6 ; if kind <> disk and tape then sn w0 q18 ; deliver_result(3); sz ; jl g5 ; <* w0: kind *> jl. j7. ; end j5: ; else <* main = dlc *> rl w1 x2+a151 ; begin sl w1 1 ; if message.device_type < 1 or sl w1 10 ; message.device_type > 9 then jl g5 ; deliver_result(3); ; zl. w0 x1+i0. ; kind := device_kind_table(message.device_type); ; jl. j7. ; end; ; j7: ; rl w1 x2+a142 ; if message.regrettet then sh w1 0 ; deliver_result(dummy); jl g7 ; zl w1 x2+a150+1 ; if message.mode <> 0 or 1 then sz w1 -2 ; deliver_result(3); jl g5 ; ; ; <* init process *> rs w0 x3+a10 ; proc.kind := kind; ; dl w2 x2+a152 ; proc.module,facility := ds w2 x3+a68 ; message.module,facility; ld w2 -48 ; <* module,fac. irr. for dlc - don't matter *> ds w2 x3+a71 ; <* clear proc a70 - a87 *> ds w2 x3+a73 ; ds w2 x3+a75 ; ds w2 x3+a87 ; ; rl w2 b19 ; proc.main := this main; rs w2 x3+a50 ; al w1 2.000001; proc.state := during_connect; hs w1 x3+a78+1 ; rs w3 x3+a77 ; proc.proc_id := proc; am (b18) ; rs w3 +a153 ; message.8000_process := proc; ; al w2 x3 ; am (b18) ; if message.mode = 0 then zl w0 +a150+1 ; include_user(message.sender, proc) se w0 0 ; else jl. j10. ; include_all_users(main, proc); am (b18) ; rl w1 +a142 ; sh w1 0 ; ac w1 x1 ; jl w3 d126 ; al w0 0 ; force := no; jl. (n100.) ; j10: ; rl w1 b19 ; jl. w3 (n103.); al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; <* never reached *> ; j20: ; no_resources: al w0 8.1400 ; status := no_resources; rs w0 g20 ; jl g7 ; deliver_result(1); ; h. ; device_kind_table(0:9) i0: -1 ; 0 : - 8 ; 1 : terminal 28 ; 2 : IMC port handler 28 ; 3 : mailbox 28 ; 4 : 3270 input 28 ; 5 : 3270 output 28 ; 6 : lanstat (test device) 28 ; 7 : floppy 14 ; 8 : printer 18 ; 9 : streamer w. ; e. ; end; \f ; extract statistics (ioc & dlc) ; ------------------------------------------------------------------------- ; ; the statistical information collected in the main process is copied ; to the sender. ; ; message (sender format) answer ; ----------------------- ------ ; + 0: 9<12 + mode status ; + 2: first storage address no of halfwords ; + 4: last storage address no of characters ; ; mode: clear statistics<0: 0 = statistics remain unchanged ; 1 = statistics are cleared ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j10 w. m9: ; extract statistics rl w3 b19 ; begin al w0 x3+a216 ; param.first address := this main.statistics.first al w1 x3+a218 ; param.last address := this main.statistics.last ds. w1 i3. ; al. w1 i1. ; jd 1<11+84 ; general_copy(buffer, param); ; sn w0 0 ; if result = 3 then jl. j1. ; decrease stopcount and deliver result_3(message) se w0 2 ; else if result = 2 then jl. (n104.); begin jl w3 d132 ; decrease_stopcount(message); rl w3 b20 ; jl g26 ; goto_no_operation; ; end; j1: rs w1 g21 ; ls w1 -1 ; message.no_of_halfwords := halfwords; wm w1 g48 ; message.no_of_characters:= halfwords*2/3; rs w1 g22 ; al w0 0 ; rs w0 g20 ; message.status := 0; ; zl w1 x2+a150+1 ; if not clear_statistics then so w1 2.1 ; decrease stopcount and deliver result_1(message) jl. (n105.); else ld w1 -100 ; begin ds w1 x3+a216+2 ; clear all statistics in this mainprocess ds w1 x3+a218 ; jl. (n105.); decrease stopcount and deliver result_1(message); ; end; ; ; param: i1: 2<1 + 1 ; function := 1st address pair, core to buffer 0 ; first address i3: 0 ; last address 0 ; relative start ; e. ; end; \f ; ; remove link (ioc & dlc) ; ------------------------------------------------------------------------ ; ; removes the connection between a rc8000 external process representing an ; device and the corresponding device. ; ; message (sender format) answer (*) ; ----------------------- ---------- ; + 0: 10<12 + 0 0 ; + 2: rc8000 device number ; (+ 4: rc8000 proc addr when sent ; from driverproc) ; ; message (setup format) ; ---------------------- ; + 0: 10<12 + 0 ; + 2: rc8000 process address ; + 4: controller_index ; ; (*) the answer is created by the controller. ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j10 w. m10: ; remove link ; begin se w1 (b21) ; if sender = driverproc then jl. j0. ; begin rl w2 x2+a152 ; proc := message.mess_2; ; al w0 2.000111; if proc.state = free or la w0 x2+a78 ; proc.state = during disconnect then se w0 l36 ; deliver_result(3); sn w0 l39 ; <* a remove link message has been received jl g5 ; after driverproc sent this message *> jl. j2. ; goto proc_ok; j0: ; end; rl w3 x2+a151 ; ls w3 +1 ; wa w3 b4 ; sl w3 (b4) ; if not message.device number within external processes then sl w3 (b5) ; deliver result(3); jl g5 ; rl w2 x3 ; proc := nametable(message.device number); ; rl w3 x2+a50 ; sn w2 (b19) ; if proc = this main or jl g5 ; proc.main <> this main then se w3 (b19) ; deliver_result(3); jl g5 ; <* test of main will catch disconnect of logical ; disks and return result 3 *> al w0 2.000111; la w0 x2+a78 ; se w0 l36 ; if proc.state= free or sn w0 l39 ; proc.state= during disconnect jl g5 ; then deliver_result(3); rl w0 x2+a10 ; se w0 q6 ; if proc.kind = disk then jl. j1. ; begin rl w0 x2+a70 ; rl w3 b19 ; if proc.next_logical_disk <> 0 or se w0 0 ; proc = this main.dump_device then jl g5 ; deliver_result(3); sn w2 (x3+a201) ; jl g5 ; end; ; j1: jl w3 d76 ; test user and reserver(sender, proc); sz w3 2.1000 ; if other reserver or jl g6 ; (sender not user and other users) then so w3 2.0001 ; deliver_result(2); so w3 2.0100 ; sz ; jl g6 ; j2: ; proc_ok: rl w1 b18 ; rl w3 x2+a76 ; message.mess_1 := proc; ds w3 x1+a152 ; message.mess_2 := proc.controller_index; ; ac w0 2.000111+1; la w0 x2+a78 ; al w3 l39 ; lo w0 6 ; hs w0 x2+a78+1 ; proc.state := during disconnect; ; <* prevents create peripheral process *> rl w0 x2+a10 ; se w0 q8 ; if proc.kind = terminal then jl. j3. ; begin al w0 1<1 ; type := disconnected; rl w1 b19 ; jl. w3 (n112.) ; check_remoter(type, main, proc); rs w3 x2+a74 ; proc.att_receiver := internal_supervisor; se w3 0 ; if internal_supervisor then jl. w3 n114. ; send_remoter_att(type, main, proc); ; end; j3: ; jl. w3 n2. ; clear_process(proc); ; al w0 0 ; force := no; jl. (n100.) ; start controller(force); ; <* the rest of the process will be cleared when ; answer disconnect is received *> e. ; end; \f ; ; set mask (ioc & dlc) ; ------------------------------------------------------------------------ ; ; sets the test mask in the rc8000 driver. ; ; message (sender/setup format) answer ; ----------------------------- ---------- ; + 0: 12<12 + mode status ; + 2: rc8000 mask (point 0 - 23) ; + 4: rc8000 mask (point 24 - 47) ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; m12: ; set mask ; begin rl w3 b19 ; <* set mask for rc8000 device drivers *> dl w1 x2+a152 ; ds w1 x3+a75 ; al w0 0 ; answer.status := ok; rs w0 g20 ; jl g7 ; deliver_result(1); ; end; \f ; dump (ioc) ; ----------------------------------------------------------------------------- ; ; the previously sent 'prepare dump' operation will be executed. ; ; message (sender & setup format) ; ------------------------------- ; + 0: 14 < 12 + 0 ; + 2: 0 ; + 4: 0 ; ; ; at entry: ; ; w0: - ; w1: sender ; w2: message ; w3: - ; b. i10, j10 w. m14: ; dump rl w3 b19 ; begin rl w0 x3+a200 ; sn w0 0 ; if main.pending_prepare_dump = 0 then jl g5 ; deliver_result(3); rl w0 x2+a151 ; lo w0 x2+a152 ; se w0 0 ; if message.mess_1<>0 or message.mess_2<>0 then jl g5 ; deliver_result(3); al w0 1 ; force := weak; jl. (n100.) ; start_controller(force); ; e. ; end; \f ; ; link logical disk (ioc) ; ------------------------------------------------------------------------ ; ; creates a logical disc process and initialize it. if the specified ; device number of the logical disc is -1 a free subprocess is selec- ; ted. ; ; message (sender format) answer ; ----------------------- ------ ; + 0: 16<12 + mode status ; + 2: device no of logical disc/-1 device no of logical disc ; + 4: device no of physical disc device no of physical disc ; + 6: first segment first segment ; + 8: no of segments no of segments ; ; mode: 0: sender is included as user of logical disc. ; 1: all users of main are included as users of the logical disc. ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j15 w. m16: ; link logical disc zl w0 x2+a150+1 ; begin sz w0 -2 ; if not message.mode = 0 or 1 then jl g5 ; deliver result(3); rl w3 x2+a152 ; ls w3 +1 ; wa w3 b4 ; if not external processes then sl w3 (b4) ; sl w3 (b5) ; deliver result(3); jl g5 ; ; rl w3 x3 ; proc := nametable(devno); rl w0 x3+a10 ; if proc.kind <> disc or rl w2 x3+a50 ; proc.main <> this mainprocess then sn w0 q6 ; deliver result(3); se w2 (b19) ; jl g5 ; al w0 2.000111; la w0 x3+a78 ; if proc.state <> connected then se w0 l38 ; deliver result(3); jl g5 ; ; al w2 x3 ; jl w3 d113 ; check reserver(sender, proc); jl g6 ; +0: if other reserver then deliver result(2); jl. j0. ; +2: jl w3 d102 ; +4: if no reserver then check user(sender, proc); jl g6 ; +0: if not user then deliver result(2); ; +2: j0: al w3 x2 ; rs. w1 i1. ; rl w1 b18 ; logical := proc.first logical disc; rl w2 x3+a70 ; j1: sn w2 0 ; while logical <> 0 do jl. j4. ; begin ; rl w0 x2+a73 ; if logical.first segment < message.first segment then sl w0 (x1+a153) ; begin jl. j2. ; if logical.first segment+logical.no of segments >= wa w0 x2+a74 ; message.first segment then sh w0 (x1+a153) ; deliver result(3); jl. j3. ; jl g5 ; ; end else j2: rl w0 x1+a153 ; begin wa w0 x1+a154 ; if message.first segment+message.no of segments >= sh w0 (x2+a73) ; logical.first segment then sz ; deliver result(3); jl g5 ; ; end; j3: rl w2 x2+a70 ; logical := logical.next logical disc; jl. j1. ; end; ; j4: rl w2 x1+a153 ; if message.first segment < al w0 x2-1 ; proc.first segment or wa w0 x1+a154 ; message.first segment + message.no of segments > sl w2 (x3+a73) ; proc.no of segments or sl w0 (x3+a74) ; jl g5 ; sl w0 x2 ; message.no of segments <= 0 then sz ; jl g5 ; deliver result(3); ; rl w1 x1+a151 ; if message.logical devno = -1 then se w1 -1 ; begin jl. j7. ; rl w1 b4 ; for ext := first external, next until last external do j5: rl w2 x1 ; begin rl w0 x2+a10 ; se w0 q68 ; if ext.kind = free subprocess then jl. j6. ; begin rl w1 x2+a59 ; message.logical devno := ext.device_no; am (b18) ; rs w1 +a151 ; goto out; jl. j7. ; end; ; j6: al w1 x1+2 ; se w1 (b5) ; jl. j5. ; end; jl. j10. ; deliver status('no free subprocesses'); ;out: ; end; j7: ls w1 +1 ; wa w1 b4 ; sl w1 (b4) ; if not ext within external processes then sl w1 (b5) ; deliver result(3); jl g5 ; rl w2 x1 ; ext := nametable(logical devno); rl w0 x2+a10 ; if ext.kind <> free subprocess then se w0 q68 ; deliver status('no free subprocesses'); jl. j10. ; ; ld w1 -100 ; ext.chaintable := 0; ds w1 x2+a72 ; ext.slicelength := 0; al w1 x2+a81 ; al w0 x1 ; <* init process queues *> ds w1 x2+a81+2 ; al w1 x2+a54 ; al w0 x1 ; ds w1 x2+a55 ; ; rs w3 x2+a50 ; ext.main := physical disc; al w0 q6 ; ext.kind := disc kind; rs w0 x2+a10 ; al w0 2.1 ; hs w0 x2+a57 ; ext.type := logical type; am (b18) ; dl w1 +a154 ; ext.first segment := message.first segment; ds w1 x2+a74 ; ext.no of segments:= message.no of segments; dl w1 x3+a87 ; ext.max_transfer_size := physical_disk.max_transfer_size; ds w1 x2+a87 ; ext.max_buffer_size := physical_disk.max_buffer_size; rl w1 x3+a75 ; ext.bytes_pr_track := physical_disk.bytes_pr_track; rs w1 x2+a75 ; dl w1 x3+a77 ; ext.controller_index:=physical_disc.controller_index; ds w1 x2+a77 ; ext.rc8000process:= physical disc.rc8000process; dl w1 x3+a68 ; ext.cm := physical disc.cm; ds w1 x2+a68 ; ext.unit:= physical disc.unit; ; al w0 0 ; j8: sn w0 (x3+a70) ; while proc.next logical disc <> 0 do jl. j9. ; proc := proc.next logical disc; rl w3 x3+a70 ; jl. j8. ; ; j9: rs w2 x3+a70 ; proc.next logical disc := ext; rs w0 x2+a70 ; ext.next logical disc := 0; ; am (b18) ; zl w0 +a150+1 ; if message.mode = 0 then se w0 0 ; include user(message.sender, ext) jl. j11. ; else rl. w1 i1. ; include all users(physical disc, ext); jl w3 d126 ; jl. j12. ; j11: ; rl w1 x2+a50 ; jl. w3 (n103.) ; j12: ; al w0 l38 ; hs w0 x2+a78+1 ; ext.state := connected; ; rl w3 b18 ; al w0 0 ; rs w0 g20 ; status := ok; dl w1 x3+a152 ; rc8000 device no of logical disc ds w1 g22 ; rc8000 device no of physical disc dl w1 x3+a154 ; first segment ds w1 g24 ; no of segments jl g7 ; deliver result(1); ; ; j10: ; no_resources: al w0 8.1400 ; status := no_resources; rs w0 g20 ; jl g7 ; deliver result(1); ; i1: 0 ; saved sender ; e. ; end; \f ; ; unlink logical disc (ioc) ; ------------------------------------------------------------------------ ; ; removes the logical disc process in rc8000 and the connection to the ; physical disc process. ; ; message (sender format) answer ; ----------------------- ------ ; + 0: 18<12 + 0 0 ; + 2: rc8000 device number ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j10 w. m18: ; unlink logical disc rl w3 x2+a151 ; begin ls w3 +1 ; wa w3 b4 ; sl w3 (b4) ; if not message.device number within external processes then sl w3 (b5) ; deliver result(3); jl g5 ; ; rl w2 x3 ; proc := nametable(message.device number); rl w0 x2+a10 ; if proc.kind <> disc or zl w3 x2+a57 ; proc.type <> logical disc then sn w0 q6 ; deliver result(3); so w3 2.1 ; jl g5 ; sz w3 2.1100000; if proc.type = logical volume then jl g5 ; deliver result(3); ; rl w3 x2+a50 ; if proc.main.main <> this mainprocess or rl w3 x3+a50 ; proc.chaintable <> 0 then rl w0 x2+a71 ; deliver result(3); sn w0 0 ; se w3 (b19) ; jl g5 ; ; sn w2 (x3+a201) ; if mainprocess.dump_device = proc then jl g5 ; deliver_result(3); ; jl w3 d76 ; test user and reserver(sender, proc); sz w3 2.1000 ; if other reserver or jl g6 ; (sender not user and other users) then so w3 2.0001 ; deliver result(2); so w3 2.0100 ; sz ; jl g6 ; ; rl w1 x2+a50 ; p := proc.main; <* physical disc *> j1: sn w2 (x1+a70) ; while p.next logical disc <> proc do jl. j2. ; p := p.next logical disc; rl w1 x1+a70 ; jl. j1. ; ; j2: rl w0 x2+a70 ; p.next logical disc := proc.next logical disc; rs w0 x1+a70 ; al w0 0 ; proc.next logical disc := 0; rs w0 x2+a70 ; ; jl. w3 n2. ; clear_process(proc); ; jl. w3 n8. ; free_process(proc); ; al w0 0 ; status := 0; rs w0 g20 ; jl g7 ; deliver result(1); ; e. ; end; \f m20: ; test: al w0 0 ; force := no; jl. (n100.) ; start_controller(force); \f ; ; initialize controller ; ----------------------------------------------------------------------------- ; ; the mainprocess is connected to the supervisor process in the controller. ; credits for outstanding messages are exchanged between the two parties. ; ; message (sender/setup format) answer format ; + 0 22 < 12 + 0 0 ; + 2 controller credit monitor credit ; ; at entry ; w0 - ; w1 sender ; w2 message ; w3 - b. i10, j10 w. m22: ; initialize controller rl w1 b19 ; begin al w0 8.07 ; la w0 x1+a78+1 ; if main.state <> free then se w0 0 ; deliver_result(3); jl g5 ; ; am (b21) ; if driverproc.buffer_claim <= zl w0 +a19 ; message.controller_credit then sh w0 (x2+a151) ; deliver_result(3); jl g5 ; ; rl w0 x2+a142 ; if regretted(message) then sh w0 0 ; deliver_result(dummy); jl g7 ; ; al w0 2.000001; main.state := during_connect; lo w0 x1+a78 ; hs w0 x1+a78+1 ; <* give the main process a few free al w0 4 ; buffers to play with *> hs w0 x1+a78+0 ; proc.free_buffers := 4; ; rs w1 x1+a50 ; main.main := main; rs w1 x1+a77 ; main.proc_id := main; al w0 0 ; main.device_id := 0; rs w0 x1+a76 ; al w3 0 ; ds w0 x1+a216+2 ; <* clear statistics *> ds w0 x1+a218 ; ds w0 x1+a201 ; <* clear prepare dump variables *> ; rx w1 4 ; rl w1 x1+a142 ; jl w3 d126 ; include_user(message.sender, proc); ; al w0 1 ; force := weak; jl. (n100.) ; start_controller(force); ; e. ; end; \f ; ; answer create link (internal driverproc message) ; ----------------------------------------------------------------------------- ; ; sent from driverproc to mainprocess (driverproc) when 'answer create link' ; is sent to then controller. ; format of the message: see o20 in the interrupt procedure c36. ; ; at entry ; w0 - ; w1 (sender) ; w2 message ; w3 - ; b. i5, j5 w. i1: 0 ; reserver, result i2: 0 ; terminal_process m31: ; answer create link rl w0 x2+a151 ; begin rs. w0 i1. ; <* save reserved, result *> rl w0 x2+a153 ; rs. w0 i2. ; <* save terminal process *> ; al w0 0 ; force := no; am (b19) ; rl w1 +a59 ; jd 1<11+128 ; start_controller(force, this main.devno, message); se w0 0 ; if result <> ok then jl g4 ; deliver_result(4); ; hl. w0 i1.+0 ; hl. w1 i1.+1 ; if save_result <> ok or sn w1 1 ; save_reserved = 0 then se w0 1 ; goto driverproc.wait_event; jl (b20) ; ; ; al w0 1<0 ; type := connected; rl w1 b19 ; rl. w2 i2. ; jl. w3 n14. ; send_remoter_att(type, main, terminal); ; jl (b20) ; goto driverproc.wait_event; ; ; e. ; end; \f ; answer remove link request ; answer attention m32: m33: al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; stop normal communication m34: al w0 2 ; force := strong jl. (n100.); start_controller(force) \f ; ; input (ida ifp) only RC8000 ; ----------------------------------------------------------------------------- ; ; this operation must have been preceeded by a 'position' operation in which ; the input area was defined. ; ; message (sender format) answer (*) ; ----------------------- ---------- ; + 0: 3<12 + 0 status ; + 2: first storage address no of halfwords transfered ; + 4: last storage address no of chareacters transfered ; ; message (setup format) ; ---------------------- ; + 0: 3<12 + 0 ; + 2: first storage address ; + 4: no of bytes ; ; (*) the answer is created by the controller. ; ; at entry: ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i5, j5 w. m3: ; input ; begin al w3 0 ; message.no of bytes := rl w0 x2+a152 ; (message.no of bytes//768) * 768; wd w0 b222 ; wm w0 b222 ; < let no of bytes be a multiplum of the rs w0 x2+a152 ; segmentsize > al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; e. ; end; \f ; ; take autoload block (ida & ifp) only RC8000 ; ------------------------------------------------------------------------- ; ; the specified autoload block is transmitted to the controller. ; ; message (sender format) answer (*) ; ----------------------- ---------- ; + 0: 5<12 + 0 status ; + 2: first storage address number of halfwords transfered ; + 4: last storage address number of characters transfered ; ; message (setup format) ; ---------------------- ; + 0: 5<12 + 0 ; + 2: first storage address ; + 4: no of bytes ; ; (*) the answer is created by the controller. ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j10 w. m5: ; take autoload block ; begin al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; e. ; end; \f ; ; position (ida ifp) only RC8000 ; ----------------------------------------------------------------------------- ; ; this operation defines the (logical) filenumber from where the succeding ; input operations will receive data. ; ; message (sender/setup format) answer (*) ; ----------------------------- ---------- ; + 0: 8<12 + 0 status ; + 2: 0 ; + 4: 0 ; + 6: (logical) filenumber ; ; (*) the answer is created by the controller. ; ; at entry: ; ; w0 - ; w1 sender ; w2 message ; w3 - ; m8: ; position ; begin al w0 0 ; force := no; jl. (n100.) ; start_controller(force); ; end; \f ; ; M E S S A G E R E C E I V E D B Y S S P M A I N P R O C E S S . ; ---------------------------------------------------------------------- ; ; Control is transfered to this part when driverproc receives a ; message sent to the SSP main process. ; ; From driverproc the following messages can be received: ; answer attention - 3 ; ; The ioc/dlc code for the following operations are used by the ; ssp main-driver: ; - extract_statistics ( m9) ; - set_mask (m12) ; - initialize_controller (m22) ; ; At entry the registers contains: ; ; w0 - ; w1 sender ; w2 message ; w3 main process ; b. i10, j10 w. h24: ; message received rs. w1 i1. ; begin rl w3 b21 ; zl w0 x3+a19 ; <* claim the buffer - driverproc will have claims bs. w0 1 ; enough as it received the message in wait event hs w0 x3+a19 ; and unclaimed it 'by hand' when it received it *> ac w3 (x2+a141) ; rs w3 x2+a141 ; ; sn w1 (b21) ; if message.sender = driverproc then jl. j3. ; goto branch; <* skip all checks *> ; zl w0 x2+a150+0 ; if message.operation < 24 then sl w0 24 ; begin jl. j1. ; dl. w1 i2. ; check_operation(operation_mask, mode_mask, message); jl w3 g16 ; rl. w1 i1. ; jl w3 g14 ; check_user(sender, message); jl. j2. ; end j1: ; else <* no io operation with oper. code > 23 as *> se w0 24 ; begin <* check_operation must be called for those *> sn w0 25 ; if message.operation <> 24 and sz ; message.operation <> 26 then jl g5 ; deliver_result(3); rl. w1 i1. ; jl w3 g15 ; check_reserver(sender, message); j2: ; end; ; zl w0 x2+a138+1 ; so w0 2.1 ; if message.state.io then jl. j4. ; begin jl w3 g34 ; if message.regretted or sz ; message.sender.state = stopped then jl. j3. ; begin rl w3 b20 ; no operation; jl g26 ; goto driverproc.wait event; ; end; ; j3: jl w3 g31 ; increase stopcount(message.sender); ; rl w3 x2+a152 ; message.no of bytes := al w0 x3+2 ; (last address - first address + 2)/2 * 3; ws w0 x2+a151 ; ls w0 -1 ; wm w0 g48 ; rs w0 x2+a152 ; ; rl w0 x2+a151 ; message.first address := wa w0 x1+a182 ; message.first address + sender.base; rs w0 x2+a151 ; <* physical address *> ; end; ; j4: ; branch: zl w0 x2+a150+0 ; oper := message.operation; sn w0 5 ; if oper = operator_output then jl. m41. ; goto operator_output else sn w0 6 ; if oper = create_link then jl. m42. ; goto create_link else sn w0 9 ; if oper = extract_statistics then jl. m9. ; goto extract_statistics else sn w0 12 ; if oper = set_mask then jl. m12. ; goto set_mask else sn w0 22 ; if oper = initialize_controller then jl. m22. ; goto initialize_controller else sn w0 24 ; if oper = close_system then jl. m43. ; goto close_system else sn w0 26 ; if oper = reload_system then jl. m44. ; goto reload_system jl. m45. ; else goto answer_attention; ; ; i1: 0 ; save w1 (sender) ; ; ssp legal operation mask (only operations < 24) ; ssp legal mode mask (only operations < 24) a0>5 + a0>6 + a0>9 + a0>12 + a0>22 i2: a0>0 + a0>1 e. ; end *** message received ***; \f ; operator_output ; --------------------------------------------------------------------------- ; ; message: ; ; + 0: 5<12 + 0 ; + 2: first address ; + 4: last address (byte count when sent to controller) ; m41: ; operator_output: ; begin al w0 0 ; force := no; jl. n0. ; start_controller(force); ; end; ; close_system ; reload_system ; --------------------------------------------------------------------------- ; nothing to check - nothing to do here! m43: ; close_system: m44: ; reload_system: ; begin al w0 1 ; force := yes; <* just do it quickly *> jl. n0. ; start_controller)force); ; end; ; answer_attention ; ------------------------------------------------------------------------- ; nothing to check - nothing to do here! m45: ; answer_attention: ; begin al w0 0 ; force := no; jl. n0. ; start_controller(force); ; end; \f ; create link (SSP) ; ------------------------------------------------------------------------- ; ; if the specified rc8000 device number is -1 a free subprocess is ; selected (and the device no will be placed in word +6 of the message). ; the subprocess is (partly) initialized and the state of the subprocess ; is set to 'during connect'. ; the rest of the process is initialized when the maindriver receives ; a create link answer operation from the controller. ; ; message (sender/setup format) answer ; ----------------------------- ---------- ; + 0: 6<12 + mode status ; + 2: device type (1 or 7) RC8000 device number ; + 4: - ; + 6: RC8000 device no/-1 (**) ; ; mode: 0: include sender as user of link ; 1: include users of main as users of link ; ; device type: 1 : console ; 7 : floppy disk ; ; (**) RC8000 process address inserted instead of device no in part 1. ; ; at entry ; ; w0 - ; w1 sender ; w2 message ; w3 - ; b. i10, j20 w. m42: ; create link rl w1 x2+a153 ; begin se w1 -1 ; jl. j3. ; if message.rc8000_device_no = -1 then ; begin rl w1 b4 ; for proc := first external, next until last external do j1: rl w3 x1 ; begin rl w0 x3+a10 ; sn w0 q68 ; if proc.kind = free subprocess then jl. j4. ; goto out; ; end; j2: al w1 x1+2 ; se w1 (b5) ; jl. j1. ; goto no_resources; jl. j20. ; end ; else j3: ls w1 +1 ; begin wa w1 b4 ; sl w1 (b4) ; if not message.rc8000_device_no within external then sl w1 (b5) ; deliver_result(3); jl g5 ; rl w3 x1 ; proc := nametable(rc8000 device no); rl w0 x3+a10 ; if proc.kind <> free subprocess then se w0 q68 ; goto no_resources; jl. j20. ; ; end; j4: ; out: rl w1 x2+a151 ; se w1 1 ; if message.device_type <> 1 and sn w1 10 ; message.device_type <> 9 then sz ; deliver_result(3); jl g5 ; ; al w0 9 ; kind := if message.device_type = terminal then 9 se w1 1 ; else 28; al w0 28 ; ; rl w1 x2+a142 ; if message.regrettet then sh w1 0 ; deliver_result(dummy); jl g7 ; zl w1 x2+a150+1 ; if message.mode <> 0 or 1 then sz w1 -2 ; deliver_result(3); jl g5 ; ; ; <* init process *> rs w0 x3+a10 ; proc.kind := kind; ld w2 -48 ; ds w2 x3+a71 ; <* clear proc a70 - a87 *> ds w2 x3+a73 ; ds w2 x3+a75 ; ds w2 x3+a87 ; ; rl w2 b19 ; proc.main := this main; rs w2 x3+a50 ; al w1 2.000001; proc.state := during_connect; hs w1 x3+a78+1 ; rs w3 x3+a77 ; proc.proc_id := proc; am (b18) ; rs w3 +a153 ; message.8000_process := proc; ; al w2 x3 ; am (b18) ; if message.mode = 0 then zl w0 +a150+1 ; include_user(message.sender, proc) se w0 0 ; else jl. j10. ; include_all_users(main, proc); am (b18) ; rl w1 +a142 ; sh w1 0 ; ac w1 x1 ; jl w3 d126 ; al w0 0 ; force := no; jl. n0. ; j10: ; rl w1 b19 ; jl. w3 n3. ; al w0 0 ; force := no; jl. n0. ; start_controller(force); ; <* never reached *> ; j20: ; no_resources: al w0 8.1400 ; status := no_resources; rs w0 g20 ; jl g7 ; deliver_result(1); ; e. ; end; ; ***** stepping stones ***** n100: n0 ; n103: n3 ; n104: n4 ; n105: n5 ; n109: n9 ; n112: n12 ; n114: n14 jl. (+2), d156 , d156 = k - 4 \f ; I N T E R R U P T R E C E I V E D F R O M C O N T R O L L E R . ; --------------------------------------------------------------------- ; ; all interrupts except 'answer device operation' are delivered ; as interrupts to the mainprocess in question. ; when an interrupt is received the communication area from the controller ; to rc8000 has not been released yet. b. i10, j10, o121 w. c36: ; interrupt received rl w1 b19 ; begin rl w2 x1+a501 ; rs w2 b18 ; <* w1 = main, w2 = message (if any) *> rl w0 x1+a244 ; sn w0 3 ; if timeout_interrupt then goto timeout jl. o3. ; se w0 0 ; if NOT ok_interrupt then jl. o2. ; goto power_interrupt; ; else begin <*normal io result*> rl w3 b218 ; <* left 8 bits *> la w3 x1+a500 ; ls w3 -3-12 ; sl w3 13*2*2 ; if main.function >12 then jl -1 ; panic; jl. (x3+j0.) ; goto case main.function of ; ; <* w1: main, w2: message (if any) *> ; func, answ ; - - - - - - j0: -1 ; 0 0 : panic -1 ; 0 1 : panic -1 ; 1 0 : panic -1 ; 1 1 : panic, answer device operation, catched o20 ; 2 0 : create link o21 ; 2 1 : answer create link -1 ; 3 0 : panic o31 ; 3 1 : answer remove link o40 ; 4 0 : attention -1 ; 4 1 : panic -1 ; 5 0 : panic o1 ; 5 1 : answer regret: start controller -1 ; 6 0 : panic o1 ; 6 1 : answer reserve device: start controller -1 ; 7 0 : panic o1 ; 7 1 : answer release device: start controller o80 ; 8 0 : remove link request -1 ; 8 1 : panic -1 ; 9 0 : panic o91 ; 9 1 : answer initialize controller -1 ; 10 0 : panic -1 ; 10 1 : panic -1 ; 11 0 : panic o111 ; 11 1 : answer reset -1 ; 12 0 : panic o121 ; 12 1 : answer stop normal communication \f b. i10, j10 w. ; - - - data - - - i0: -1 < 12 + 0 ; mess_0: operation (= answer_create_link) i1: 0 ; +2: reserved, result i2: 0 ; +4: device_id i3: 0 ; +6: proc_id i4: 0, 0, 0, 0 ; +8-+14: name of reserver (if any) i8: 32000 ; max transfer size o20: ; create link ; -------------------- ; begin rl w0 x1+a502 ; rs. w0 i2. ; mess_2 := main.device_id; al w2 x1+a514 ; jl w3 d11 ; check_name,(driverproc,name_address); sz ; not found goto search free sub process jl. j0. ; found goto set result 9; rl w3 b5 ; proc := last_external; j1: al w3 x3-2 ; while proc.kind <> free and rl w2 x3 ; proc <> first_external rl w0 x2+a10 ; begin sn w0 q68 ; proc := nametable(prev); jl. j2. ; se w3 (b4) ; jl. j1. ; end; ; ; am 8-9 ; if proc = first_external j0: al w0 9 ; or name already exist then rs. w0 i1. ; begin jl. j9. ; result := no_resources/already exist; ; goto answer_controller; ; end; j2: ; al w0 1 ; rs. w0 i1. ; reserved := 0; result := ok; rs. w2 i3. ; mess_3 := proc; ld w0 -48 ; ds w0 x2+a71 ; <* clear proc a70 - a87 *> ds w0 x2+a73 ; ds w0 x2+a75 ; ds w0 x2+a87 ; al w3 x2+a81 ; <* init process queues *> al w0 x3 ; ds w0 x2+a81+2 ; al w3 x2+a54 ; al w0 x3 ; ds w0 x2+a54+2 ; rs w1 x2+a50 ; proc.main := this main; rl w1 (b6) ; jl w3 d126 ; insert_user(proc,proc_func); rl w1 x2+a50 ; al w0 l37 ; rs w0 x2+a78 ; proc.state := during_connect; al w0 q8 ; rs w0 x2+a10 ; proc.kind := terminal; rl w0 x1+a502 ; rs w0 x2+a76 ; proc.device_index := main.device_id; rs w2 x2+a77 ; proc.process_address := proc; rl. w3 i8.;x1+a513; rs w3 x2+a87 ; proc.buffer_size := main.mess_3; al w3 x3+1 ; rs w3 x2+a86 ; proc.max_transfer := buffer_size + 1; dl w0 x1+a514+2 ; ds w0 x2+a11+2 ; proc.name := main.mess_4 - mess_7; dl w0 x1+a514+6 ; ds w0 x2+a11+6 ; am (b21) ; proc.name_base := driverproc.base (i.e. max) dl w0 +a49 ; ds w0 x2+a49 ; al w0 1<0 ; type := connected; jl. w3 (n112.) ; check_remoter(type, main, proc); ; <* w3 retur: 0 or internal_supervisor *> sn w3 0 ; if internal_supervisor then jl. j4. ; begin al w2 x3 ; dl w0 x2+a11+2 ; ds. w0 i4.+2 ; mess_4 - mess_7 := internal_supervisor.name; dl w0 x2+a11+6 ; ds. w0 i4.+6 ; am. (i3.) ; rs w2 +a74 ; proc.att_receiver := internal_supervisor; al w2 1 ; mess_1.reserver := 1; hs. w2 i1.+0 ; end; j4: ; j9: ; answer_controller: al. w2 i0. ; jl. w3 n13. ; send_main_message(main, message); ; jl. o1. ; goto common_end; ; e. ; end <* ----- end create link ----- *> \f b. i10, j20 w. ; - - - data - - - i0: 32000 ; default ifp buffersize i2: 0 ; saved message i4: ; result : comment ; ccccccccddssssss........ ; c=connect_result, d=description, s=dev_status 2.000000000000010000000000 ; 8 : no resources 2.000000000000010100000000 ; 9 : link already exist 2.100000000000000100000000 ; 10 : ill kind (should not come ?) 2.001000000000000100000000 ; 11 : controller unknown 2.100000000000000100000000 ; 12 : device unknown 2.000100000000000100000000 ; 13 : controller fault 2.000100000000000100000000 ; 14 : device fault ; o21: ; answer create link ; -------------------- ; begin al w0 8.377 ; if main.result = ok then la w0 x1+a500 ; begin se w0 1 ; jl. j8. ; ; rl w3 x1+a503 ; proc := main.proc_id; rl w0 x3+a10 ; se w0 q6 ; if proc.kind = disk then jl. j2. ; begin ; rl w0 x1+a520+a154 ; proc.no_of_segments := rs w0 x3+a74 ; message.device_capacity := rs w0 x2+a154 ; main.mess_4; ; sn w0 0 ; if proc.no_of_segments > 0 then jl. j1. ; begin rs. w2 i2. ; al w2 x3 ; al w3 0 ; proc.segments_pr_track := rl w0 x1+a520+a156 ; main.mess_6 / bytes_pr_segment; wd w0 b222 ; rs w0 x2+a75 ; ; al w3 0 ; proc.buffer_size := rl w0 x1+a520+a155 ; main.mess_5 / bytes_pr_segment; wd w0 b222 ; rs w0 x2+a87 ; ; <* make max transfer a multiple al w3 0 ; of track size *> wd w0 x2+a75 ; proc.max_transfer := wm w0 x2+a75 ; proc.buffer_size / proc.segments_pr_track * ; proc.segments_pr_track; sn w0 0 ; if proc.max_transfer = 0 then rl w0 x2+a87 ; proc.max_transfer := proc.buffer_size; rs w0 x2+a86 ; <* in case where buffersize < tracksize *> ; al w3 x2 ; jl. j6. ; end j1: ; else ; begin ; <* drive has not been formated *> ; <* io requests will be rejected due to ; disk.no_of_segments *> ; end; jl. j6. ; end j2: ; else se w0 q18 ; if proc.kind = tape then jl. j3. ; begin ; rl w0 x1+a520+a155 ; proc.buffer_size := main.mess_5; rs w0 x3+a87 ; proc.max_transfer := main.mess_5 + 1; ba. w0 1 ; rs w0 x3+a86 ; ; rl w0 (b3) ; proc.remoter_process := rs w0 x3+a75 ; nametabel(1); ; al w0 3 ; proc.document_state := la w0 x1+a520+a157 ; rs w0 x3+a70 ; returned_state; jl. j6. ; end j3: ; else sn w0 q28 ; if proc.kind = gsd or jl. j4. ; proc.kind = printer or sn w0 q14 ; proc.kind = terminal or jl. j4. ; proc.kind = ssp terminal then sn w0 q8 ; jl. j4. ; se w0 q9 ; jl -1 ; begin j4: ; rl. w0 i0. ; proc.buffer_size := standard size rs w0 x3+a87 ; ba. w0 1 ; proc.max_transfer := standard size; rs w0 x3+a86 ; ; jl. j6. ; end ; else panic; j6: ; rl w0 x1+a502 ; proc.device_id := rs w0 x3+a76 ; main.device_id; ac w0 2.000111+1; la w0 x3+a78 ; al w2 l38 ; proc.state := lo w0 4 ; proc.state or connected; hs w0 x3+a78+1 ; ; <* prepare answer *> al w0 0 ; rs w0 g20 ; answer_0 := ok; <* status *> rl w0 x3+a59 ; rs w0 g21 ; answer_1 := proc.devno; rl w0 x1+a502 ; rs w0 g22 ; answer_2 := main.device_id; am (b18) ; rl w0 +a154 ; answer_3 := message.device_kind,device_modif; rs w0 g23 ; rl w0 x1+a514 ; answer_4 := main.mess_4; <*device capacity *> rs w0 g24 ; al. w3 o1. ; jl g18 ; deliver_result(1); ; goto common_end; ; end j8: ; else rl w2 x1+a503 ; begin jl. w3 n2. ; clear_process(main.proc_id); jl. w3 n8. ; free_process(main.proc_id); ; al. w3 o1. ; if main.result < 5 then sh w0 5 ; begin jl g19 ; deliver_result(main.result); ; goto common_end; ; end; rl w2 0 ; al w2 x2-8 ; ls w2 1 ; rl. w0 x2+i4. ; rs w0 g20 ; answer_0 := status_table(main.result); jl g18 ; deliver_result(1); ; goto common_end; ; end; e. ; end; \f b. i10, j10 w. ; o31: ; answer remove link ; -------------------- ; begin al w0 8.377 ; if main.result <> ok then la w0 x1+a500 ; panic; se w0 1 ; jl -1 ; ; rl w2 x1+a503 ; proc := main.proc_id; rl w0 x2+a10 ; sn w0 q8 ; if proc.kind = terminal then jl. w3 n7. ; remove_attention_buffer(proc); ; jl. w3 n8. ; free_process(proc); ; al w2 x2+a54 ; clear_queue(normal, proc.event_q); al w0 0 ; jl. w3 n1. ; ; rs w0 g20 ; answer_0 := 0; <* status *> jl w3 g18 ; deliver_result(1); ; jl. o1. ; goto common_end; ; e. ; end; \f b. i10, j25 w. ; - - - data - - - ; ------ message ------ i0: -3<12 + 0 ; + 0: operation (= answer attention) i1: 0 ; + 2: att_result, result i2: 0 ; + 4: device_id i3: 0 ; + 6: proc_id i5: 0 ; internal receiver of att_message i6: 0 ; remoter event_q i7: 0 ; remoter message ; o40: ; attention ; -------------------- ; begin ; <* prepare answer attention message *> dl w3 x1+a503 ; mess_2 := main.device_id; ds. w3 i3. ; mess_3 := main.proc_id; al w0 1 ; mess_1.att_result := ok; mess_1.result := ok; rs. w0 i1. ; <* initialized to ok; might be changed later on *> ; al w2 x3 ; proc := main.proc_id; rl w0 x2+a10 ; if proc.kind = disk then se w0 q6 ; begin jl. j5. ; ; al w0 8.377 ; la w0 x1+a511 ; event := main.mess_1; se w0 1 ; if event = intervention then jl. j4. ; begin ; al w0 l40 ; proc := proc.next_logical_disk; j2: rl w2 x2+a70 ; while proc <> 0 do sn w2 0 ; begin jl. j3. ; proc.state := intervention; hs w0 x2+a78+1 ; proc := proc.next_logical_disk; jl. j2. ; end; j3: jl. j20. ; j4: sl w0 1 ; end else sl w0 4 ; if envent <> test buffer full and event <> data correction performed then jl -1 ; panic jl. j20. ; end j5: ; else se w0 q18 ; if proc.kind = tape then jl. j15. ; begin ; al w0 8.377 ; la w0 x1+a511 ; event := main.mess_1; se w0 0 ; if event = online then jl. j10. ; begin ; al w0 l46 ; proc.document_state := rs w0 x2+a70 ; unidentified_document_mounted; al w0 0 ; proc.name := 0; rs w0 x2+a11 ; rs w0 x2+a52 ; proc.reserver := 0; ; rl w3 x2+a75 ; if proc.remoter<>0 then sn w3 0 ; begin jl. j9. ; al w1 x3+a54 ; message:=proc.remoter.eventq.first; rl w3 x1 ; rs. w1 i6. ; rs. w3 i7. ; j6: sn. w3 (i6.) ; while message<>none do jl. j9. ; begin rl w0 x3+a140 ; rs. w0 i7. ; if message.operation=wait for online and zl w0 x3+a150 ; ((message.mode=specific main and se w0 0 ; message.main=this main) or jl. j8. ; message.mode=all main) then zl w0 x3+a150+1 ; begin so w0 2.1 ; jl. j7. ; rl w0 x3+a151 ; se w0 (b19) ; jl. j8. ; j7: rs w3 b18 ; message.status:=0; al w0 0 ; message.mt-addr:=proc; rs w0 g20 ; rs w2 g21 ; jl w3 g18 ; deliver_result(1); j8: rl. w2 i2. ; end; rl. w3 i7. ; message:=message.next; jl. j6. ; end ; j9: ; end; jl. j11. ; end ; else j10: se w0 1 ; if event = offline then jl -1 ; begin al w0 l45 ; proc.document state := no document mounted; rs w0 x2+a70 ; al w0 0 ; proc.name := 0 ; rs w0 x2+a11 ; rs w0 x2+a52 ; proc.reserver := 0; ; end ; else panic; <* not defined *>; j11: ; jl. j20. ; end j15: ; else se w0 q8 ; if proc.kind = terminal or sn w0 q9 ; proc.kind = ssp terminal then sz ; jl. j21. ; begin ; rl w0 x2+a52 ; if terminal.reserver <> 0 then sn w0 0 ; begin jl. j16. ; rl w0 x2+a71 ; if terminal.attention_buffer_address <> 0 then se w0 0 ; goto skip_att_message; <* att already sent to jl. j19. ; reserving internal *> rl w2 x2+a74 ; att_receiver := terminal.att_receiver; jl. j18. ; end j16: ; else al w2 x1+a514 ; begin rl. w1 i3. ; dl w1 x1+a49 ; jl w3 d71 ; i := search_name(main.mess_4, terminal.name_base); rl w2 x3 ; att_receiver := name_table(i); rl w0 x2+a10 ; if i = name_table_end or se w3 (b7) ; att_receiver.kind <> internal and sz w0 -1-64 ; att_receiver.kind <> pseudo_process then sz ; begin jl. j18. ; al w0 1 ; mess_1.att_result := unknown; hs. w0 i1.+0 ; goto skip_att_message; jl. j19. ; ; end; ; end; j18: ; rs. w2 i5. ; <* save att_receiver *> rl. w1 i3. ; al w2 0 ; if terminal.attention_buffer <> 0 then rx w2 x1+a71 ; regret_message(terminal.attention_buffer); se w2 0 ; jl w3 d75 ; am (b21) ; zl w0 +a19 ; sh w0 5 ; if bufferclaim.driverproc < 6 then jl. j19. ; no message to receiver rl. w1 i5. ; rl w0 x1+a10 ; if att_receiver.kind = pseudo_process then se w0 0 ; att_receiver := att_receiver.main; rl w1 x1+a50 ; rl. w2 i3. ; jl w3 d126 ; insert_user(att_receiver, terminal); rl w1 b19 ; rl w0 x1+a511 ; rs w0 g21 ; att_mess_1 := main.event; <*returned messages *> ; ld w0 -48 ; <* clear att message *> rs w0 g20 ; ds w0 g23 ; al w1 g20 ; rl. w3 i5. ; jd 1<11+17 ; send_att_message(message, terminal, att_receiver); rl. w1 i3. ; rs w2 x1+a71 ; terminal.attention_buffer := message_buffer; ; j19: ; skip_att_message: ; jl. j20. ; end ; else panic; j21: se w0 q24 ; if proc_kind = ssp main then jl -1 ; begin rl w0 x1+a511 ; se w0 1 ; if event<>temperatur_too_high and sn w0 2 ; event<>power_warning then jl -1 ; panic; jl. j20. ; <* do nothing yet *> ; end; ; j20: ; rl w1 b19 ; al. w2 i0. ; jl. w3 n13. ; send_main_message(main, message); jl. o1. ; goto common_end; ; e. ; end; \f b. i10, j10 w. ; - - - data - - - ; --------- message --------- ; answer_remove_link_request remove_link i4: 0 ; + 0: -2 < 12 + 0 10 < 12 + 0 i5: 0 ; + 2: result proc.devno i6: 0 ; + 4: device_id proc address i7: 0 ; + 6: proc_id (address) ; o80: ; remove link request: ; -------------------- ; begin dl w3 x1+a503 ; mess_2 := main.device_id; ds. w3 i7. ; mess_3 := proc := main.proc_id; al w0 2.000111 ; la w0 x3+a78 ; sn w1 (x3+a50) ; mess_1 := <* result *> se w0 l38 ; if proc.main <> main or am 2 ; proc.state <> connected then al w0 1 ; 3 else 1; rs. w0 i5. ; al w0 -2 ; mess_0.operations := -2; hs. w0 i4.+0 ; <* answer remove link request *> ; al. w2 i4. ; jl. w3 n13. ; send_main_message(main, message); ; rl. w0 i5. ; if message.result = ok <* mess_1 *> se w0 1 ; begin jl. j1. ; ; rl w1 b19 ; <* main *> rl w3 x1+a503 ; mess_1 := proc.device_no; rl w2 x3+a59 ; mess_2 := proc; ds. w3 i6. ; al w0 10 ; mess_0.operation := remove_link; hs. w0 i4.+0 ; al. w2 i4. ; jl. w3 n13. ; send_main_message(main, message); ; end; j1: ; jl. o1. ; goto common_end; ; e. ; end <* ----- remove link request ----- *> ; ; b. i10, j10 w. o91: ; answer initialize controller; al w0 8.377 ; begin la w0 x1+a500 ; se w0 1 ; if main.result <> ok then jl -1 ; panic; rl w0 x1+a511 ; main.free_buffers:= hs w0 x1+a78+0 ; main.mess_1; rl w0 x1+a78 ; ea. w0 1 ; main.state:=connected; hs w0 x1+a78+1 ; <* a bit diry - is was in state during connect *> rl w0 x1+a502 ; main.supervisor_id:= rs w0 x1+a76 ; main.device_id; al w0 0 ; rs w0 g20 ; answer_0:=0; <* status *> jl w3 g18 ; deleiver_result(1); jl. o1. ; goto common end; e. ; end; \f b. i10, j10 w. i2: 0 ; saved message to answer o111: ; answer reset and answer stop o121: ; --------------------- al w0 8.377 ; begin la w0 x1+a500 ; se w0 1 ; if main.result <> ok then jl -1 ; panic; ; jl w3 d5 ; unlink(message); rs. w2 i2. ; <* unlink and save message to prevent it from ; being returned with result 4 *> jl. w3 n9. ; cleanup; rl w1 b19 ; al w0 3 ; main.free_buffers := 3; hs w0 x1+a78+0 ; <* give it a few buffers to play with *> al w0 0 ; main.controller_stat := ok and not busy; hs w0 x1+a78+1 ; main.connect_state := free; rs w0 g20 ; answer.status := 0; al w0 1 ; rs w0 x1+a86 ; main.no_of_outstanding := 1 <* it will be decreased at commen end *> al w2 x1+a242 ; se w2 (x2) ; if in timeout queue then jl w3 d5 ; unlink (main, timeout_queue) rl w0 x1+a511 ; rs w0 g21 ; answer.mess_1 := main.mess_1; rl. w0 i2. ; rs w0 b18 ; jl w3 g18 ; deliver_result(1); jl. o1. ; goto common_end; ; e. ; end; \f ; timeout_interrupt ; b. i4 w. ; <*** begin io result <> 0 ***> i1: -4<12 + 0 ; stop i2: 4<12 + 1 ; reset hard o3: c.l53 b. f4 w. ; ****** test 44 ****** rs. w3 f1. ; rs. w1 f0. ; jl. w3 (f3.) ; 44 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a86 ; dump main.communication area al w1 x1+a81+2 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 44 ****** al w0 0 ; clear interrupt rs w0 x1+a244 ; zl w0 x1+a78+1 ; if main.state = connected then se w0 l38 ; message := stop communication am i2-i1 ; else al. w2 i1. ; message := reset hard la w0 8.40 ; state := not ok hs w0 x1+a78+1 ; jl. w3 n13. ; jl. o0. ; return o2: ; power_interrupt: c.l53 b. f4 w. ; ****** test 43 ****** rs. w3 f1. ; rs. w1 f0. ; jl. w3 (f3.) ; 43 ; f0: 0 ; main f1: 0 ; jl. f2. ; al w0 x1+a86 ; dump main.communication area al w1 x1+a81+2 ; jl. w3 (f4.) ; jl. f2. ; f3: d150 ; f4: d151 ; f2: ; e.z. ; ****** end test 43 ****** al w3 0 ; rs w3 x1+a244 ; clear interrupt rs w3 x1+a78 ; main.free_buffers := 0; main.stat := free; rl w2 x1+a10 ; insert timeout depending of kind ws. w2 i3. ; rl. w0 x2+i0. ; main.timeout := default ds w0 x1+a87 ; main.no_of_outstanding := 0 jl. o0. ; return; i0: 0 ; default timeout: 20 ida 0 ; - - - - - - - : 22 not used 0 ; - - - - - - - : 24 (not invented yet) 600000 ; - - - - - - - : 26 ifp i3: 20 o1: ; common_end: ; -------------------- am (b19) ; rl w1 +a59 ; al w2 -1 ; jd 1<11+128 ; start_controller(this main.device_no, answer_device); rl w1 b19 ; rl w0 b218 ; la w0 x1+a500 ; ls w0 -15 ; jl. w3 d156. ; decrease no_of_outstanding(main,function); rl w2 x1+a81 ; element := main.waiting_q.first; sn w2 x1+a81 ; if element = none then jl. o0. ; return; al w0 0 ; force := sl w2 (b8+4) ; sl w2 (b8+6) ; if element <> message then no jl. i4. ; al w0 2.1000000 ; else message.state.force; la w0 x2+a138 ; ls w0 -6 i4: ; rl w1 x1+a59 ; jd 1<11+128 ; start_controller(this main.device_no, message); ; end; o0: jl (b20) ; goto driverproc.wait_event; e. ; end <*** io result <> 0 **> e. ; end <*** interrupt received ***> \f m. commen procedures ; ; ======================================================================== ; ; common procedures used by main processes ; ; ======================================================================== ; ; ; procedure start controller(force) ; ------------------------------------------------------------------------ ; ; the controller supervised by current receiver (b19) will be started ; with current message (b18). ; controll will be returned to 'wait event' in driverproc. ; the parameter force will be passed to the procedure test_ready_and_setup. ; ; call ; ; w0 force ; w1 - ; w2 - ; w3 - ; n0: ; procedure start controller; rl w1 b19 ; begin rl w1 x1+a59 ; rl w2 b18 ; start_controller(force, this main.devno, message); jd 1<11+128 ; ; se w0 0 ; if result <> ok then jl g4 ; deliver result(4) jl (b20) ; else goto wait event; ; end; \f ; ; procedure clear queue(io result,queue head); ; ------------------------------------------------------------------------ ; ; all messages in the specified queue are returned with result 4. ; for each message the receiver is tested. if the receiver is a monitor ; driven driver then the receiver is changed to the driverprocess of the ; mainprocess. this will make it possible for driverproc to send the answer. ; ; call return ; ; w0 io result io result ; w1 - unchanged ; w2 queue head queue head ; w3 link destroyed ; b. i10, j10 w. n1: ; procedure clear queue(io result, queue head); sn w2 (x2+0) ; begin jl x3 ; ds. w3 i3. ; ds. w1 i1. ; dl w1 b19 ; ds. w1 i5. ; ; while not queue head.empty do j1: rl w2 x2+0 ; begin rs w2 b18 ; cur buf := queue head.first; jl w3 g32 ; decrease stopcount(cur buf); rl w2 b18 ; ac w3 (x2+a141) ; rl w0 x3+a10 ; if message.receiver.kind <> main_kinds then se w0 q20 ; begin <* monitor driven driver *> sn w0 q26 ; message.receiver := driverproc; jl. j2. ; <* simulate that the message hasn't been claimed rl w1 b21 ; this will force 'deliver result' to decrease rs w1 x2+a141 ; bufferclaime of driverproc before sending the ; answer *> ; end; j2: rl. w0 i0. ; message.io result := io result; rs w0 g23 ; al w0 4 ; jl w3 g19 ; deliver result(4); rl. w2 i2. ; se w2 (x2+0) ; jl. j1. ; end; ; dl. w1 i5. ; ds w1 b19 ; dl. w1 i1. ; jl. (i3.) ; ; i0: 0 ; saved w0 i1: 0 ; saved w1 i2: 0 ; saved w2 i3: 0 ; saved w3 0 ; saved current buffer i5: 0 ; saved current receiver ; e. ; end; \f ; ; procedure clear process(proc); ; ------------------------------------------------------------------------ ; ; the specified process is cleared, i.e. name, users and reserver ; are zeroized. ; ; call return ; ; w0 - unchanged ; w1 - unchanged ; w2 proc proc ; w3 link link ; b. i10, j10 w. n2: ; procedure clear process(proc); ds. w1 i1. ; begin ld w1 -100 ; ds w1 x2+a11+2 ; proc.name := 0; rs w1 x2+a52 ; proc.reserver := 0; ; j0: am x1 ; users := 0; rs w0 x2+a402 ; al w1 x1+2 ; sh w1 a403-2 ; jl. j0. ; dl. w1 i1. ; jl x3 ; ; 0 ; saved w0 i1: 0 ; saved w1 ; e. ; end; ; \f ; ; procedure include all users(main, proc); ; ----------------------------------------------------------------------------- ; ; all users of the main process are included as users of the specified process. ; ; call return ; w0 - destroyed ; w1 main main ; w2 proc proc ; w3 link destroyed ; b. i10, j10 w. n3: ; include all users rs. w3 i3. ; begin al w3 a401 ; al w1 x1+a402 ; for i:=1 step 1 until no of words do al w2 x2+a402 ; proc.userbittable(i) := j1: rl w0 x1 ; main.userbittable(i); rs w0 x2 ; al w1 x1+2 ; al w2 x2+2 ; al w3 x3-1 ; se w3 0 ; jl. j1. ; al w1 x1-a48 ; al w2 x2-a48 ; jl. (i3.) ; ; i3: 0 ; saved return; e. ; end; \f ; ; procedure decrease stopcount and deliver result_3(message); ; procedure decrease stopcount and deliver result_1(message); ; ------------------------------------------------------------------------------ ; ; the stopcount of the sender of the message is decreased and the message is ; answered with result 3 or 1. ; ; call ; w0 - ; w1 - ; w2 message ; w3 - ; b. i5, j5 w. n4: ; decrease stopcount and deliver result 3: am 1 ; n5: al w0 0 ; decrease stopcount and deliver result 1: rs. w0 i0. ; begin jl w3 d132 ; decrease stopcount(message); rl. w0 i0. ; se w0 1 ; goto deliver result (3 or 1); am g7-g5 ; jl g5 ; ; i0: 0 ; e. ; end; \f ; procedure remove_attention_buffer(proc) ; ----------------------------------------------------------------------------- ; ; regretted message is called if an attention buffer exist ; ; call return ; w0 - unchanged ; w1 - unchanged ; w2 terminal unchanged ; w3 return address unchanged ; b. i5, j5 w. n7: ds. w3 i3. ; procedure remove_attention_buffer al w3 x2 ; begin al w2 0 ; rx w2 x3+a71 ; se w2 0 ; if proc.attention_buffer <> 0 then jl w3 d75 ; regretted_message(proc.attention_buffer); dl. w3 i3. ; jl x3 ; ; i2: 0 ; i3: 0 ; e. ; end; \f ; ; procedure free_process(proc); ; ----------------------------------------------------------------------------- ; ; the specified process is set free i.e. kind is set to free process and ; state is set to 'free'. ; ; call return ; ; w0 - unchanged ; w1 - unchanged ; w2 proc proc ; w3 link destroyed ; b. i5, j5 w. n8: ; free_process rs. w0 i0. ; begin al w0 q68 ; rs w0 x2+a10 ; proc.kind := free; ac w0 2.0111+1 ; la w0 x2+a78 ; lo. w0 i1. ; hs w0 x2+a78+1 ; proc.state := free; rl. w0 i0. ; jl x3 ; ; i0: 0 ; save w0 i1: l36 ; proc state free ; e. ; end; \f ; ; procedure cleanup ; ----------------------------------------------------------------------------- ; ; The process complex in rc8000 concerning the controller supervised by the ; mainprocess in b19, is cleaned up, i.e. all pending messages are returned ; with result 4 and all processes for devices on the controller are removed. ; ; call return ; w0 - destroyed ; w1 - destroyed ; w2 - destroyed ; w3 link destroyed b. i10, j10 w. n9: ; begin ; rs. w3 i3. ; rl w1 b4 ;for proc := first external, next until last external do j2: rl w2 x1 ; begin rl w0 x2+a10 ; rl w3 x2+a50 ; se w3 (b19) ; if proc.main = this main and jl. j3. ; proc.kind <> mainkind then se w0 q20 ; begin sn w0 q26 ; <* disc, mt or ifpgsd *> jl. j3. ; ; al w2 x2+a54 ; rl w0 x2+a10 ; if proc.kind = terminal then sn w0 q8 ; remove_attention_buffer(proc); jl. w3 n7. ; al w0 0 ; jl. w3 n1. ; clear_queue(normal, proc.event_queue); al w2 x2-a54 ; jl. w3 n2. ; clear_process(proc); jl. w3 n8. ; free_process(); jl. j4. ; end ; else j3: se w2 (b19) ; if proc = this main then jl. j4. ; begin al w0 0 ; al w2 x2+a54 ; jl. w3 n1. ; clear queue(normal,this main.event queue); al w2 x2-a54+a81; jl. w3 n1. ; clear queue(normal,this main.waiting queue); al w2 x2-a81 ; al w3 0 ; this main.statistics := 0; ds w0 x2+a216+2 ; ds w0 x2+a218 ; end; ; j4: al w1 x1+2 ; se w1 (b5) ; jl. j2. ; end; jl. (i3.) ; i3: 0 ; saved link ; e. ; end; \f ; procedure check_remoter(type, main, terminal) ; ----------------------------------------------------------------------------- ; ; the message queue of the remoter is searched for an terminal supervisor ; message (operation = 2). ; if such a message is found the terminal is reserved and the internal is ; returned. ; ; call return ; w0 att type undefined ; w1 main main ; w2 terminal terminal ; w3 link internal_supervisor (reserver) or 0 ; b. i10, j10 w. n12: ds. w3 i3. ; begin ds. w1 i1. ; al w0 0 ; rs. w0 i4. ; internal_supervisor := 0; rl w3 (b3) ; al w0 x3+a54 ; message:= remoter.eventq.first; rl w3 x3+a54 ; while message <> none do rs. w0 i6. ; begin j3: sn. w3 (i6.) ; jl. j6. ; rs. w3 i5. ; zl w0 x3+a150+0 ; if message.operation = wait for connect then se w0 2 ; begin jl. j5. ; zl w0 x3+a150+1 ; if (message.mode = all connections) or so w0 2.1 ; (message.mode = specific main and jl. j4. ; message.mainaddress = this main) then rl w0 x3+a151 ; begin se. w0 (i1.) ; jl. j5. ; j4: rl w1 x3+a142 ; sender:= message.sender; rl w0 x1+a10 ; if sender.kind<>internal then se w0 0 ; sender:=sender.main; <*pseudo proc*> rl w1 x1+a50 ; rl. w0 i0. ; se w0 1<0 ; if type = connected then jl. j6. ; begin rs. w1 i4. ; internal_supervisor := sender; jl w3 d125 ; include_reserver(sender, proc); ; end; ; end; ; end; j5: rl. w3 i5. ; rl w3 x3+a140 ; message:=message.next; jl. j3. ; end; j6: ; done: dl. w2 i2. ; <* restore and return *> rl. w0 i0. ; rl. w3 i4. ; <* return reserving process *> jl. (i3.) ; ; i0: 0 ; save w0 att_type i1: 0 ; w1 main i2: 0 ; w2 terminal i3: 0 ; w3 link i4: 0 ; internal_supervisor or 0 i5: 0 ; remoter message i6: 0 ; remoter queue e. ; end; \f ; procedure send_main_message(receiver, message); ; ---------------------------------------------------------------------------- ; ; send the specified message to the receiver. ; ; call return ; w0 - destroyed ; w1 receiver destroyed ; w2 message destroyed ; w3 link destroyed ; b. i5, j5 w. i3: 0 ; saved return i4: 0,0,0,0,0 ; namearea and nta n13: ; send_main_message rs. w3 i3. ; begin dl w0 x1+a11+2 ; namearea := receiver.name; ds. w0 i4.+2 ; dl w0 x1+a11+6 ; ds. w0 i4.+6 ; al. w3 i4. ; al w1 x2 ; jd 1<11+16; send message(message, receiver.name); jl. (i3.) ; e. ; end; \f ; procedure send_remoter_att(type, main, terminal) ; ----------------------------------------------------------------------------- ; ; an attention message is sent to the internal process which has reserved the ; terminal process. ; the attention message has the following format: ; ; sender: terminal or main ; receiver: sender of message to remoter ; + 0 0 (attention) ; + 2 state (1<0: terminal connected, 1<1: terminal disconnected) ; + 4 terminal address ; + 6- +12 terminal name ; ; if state = disconnected mainproc is inserted as sender of att message ; ; call return ; w0 att type att type ; w1 main main ; w2 terminal terminal ; w3 link undefined ; b. i10, j10 w. n14: ds. w3 i3. ; begin ds. w1 i1. ; al w3 0 ; att_mess.mess_0 := 0; ds w0 g21 ; att-mess.status := type; rs w2 g22 ; att-mess.terminal := terminal dl w0 x2+a11+2 ; att-mess.name := terminal.name ds w0 g23+2 ; dl w0 x2+a11+6 ; ds w0 g23+6 ; rl w3 x2+a74 ; receiver := terminal.att_receiver; rl. w2 i2. ; if type = disconnect then rl. w1 i0. ; sender := this main sn w1 1<1 ; else rl. w2 i1. ; sender := terminal; al w1 g20 ; jd 1<11+17; send_att_message(message, sender, receiver); am. (i2.) ; rs w2 +a71 ; terminal.att_buffer := buffer; rl. w0 i0. ; dl. w2 i2. ; <* restore and return *> jl. (i3.) ; ; i0: 0 ; save w0 att_type i1: 0 ; w1 main i2: 0 ; w2 terminal i3: 0 ; w3 link e. ; end; e. ; end of main driver