|
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: 23040 (0x5a00) Types: TextFile Names: »tssicjob«
└─⟦a41ae585a⟧ Bits:30001842 SW-save af projekt 1000, Alarm-system └─⟦72244f0ef⟧ └─⟦this⟧ »tssicjob«
job hj 5 200 time 11 0 area 10 size 100000 ( source = copy 25.1 tssiclst = set 1 disc1 tssiclst = indent source mark lc listc = cross tssiclst o errors message pascal pascal80 alarmenv source o c lookup pass6code if ok.yes ( tssicbin = set 1 disc1 tssicbin = move pass6code scope user tssicbin ) tssiclst = copy listc errors scope user tssiclst convert errors finis ) \f process tsconnector( opsem : sempointer; (* operator sem *) var supsem, (* ts supervisor sem *) dcsem, (* to dc *) ncsem, (* to nc *) lamsem, (* to lam *) timeoutsem, (* to timeout *) listensem : !sempointer; (* buffer pool *) var mainsem, (* my mainsem *) outsem, (* transfer queue *) myfree, (* my free buffers *) lamoutsem, (* from lam *) timeoutanswer : !ts_pointer ); (* from timeout *) (******************************************************** * * function: this module establishes a connection between * two RC3502 machines in the demonstration * model * * semaphores: the module receives messages on mainsem, * and sends messages aimed at: * timeoutmodule on timeoutsem, * lamdriver on lamsem, * supervisor on supsem * dcmodule on dcsem * * programmed june 1980 by stb and wib * dec 1980 by hej * *********************************************************) (*-------------------------- configuration ----------------------------*) const version = "vers 3.18 /"; ts1port = 0; ts2port = 4; tsc_port = ts1port; (* or ts2port *) \f const tsbufleng= size_listen*2 -2; (* no of bytes in buffer from tss *) logleng= size_supp*2 -2; (* no of bytes in log-message *) lambufsize= 80; (* no of bytes in buffer to lamdriver *) con_lam_time= 20; (* lam driver timeout *) tick1= 5; (* timeout interval for ts with dc *) tick2= 6; (* timeout interval for ts *) no_of_lamlis= 3; no_of_mybuf= 5; (* buffers in my pool *) tablesize = 4; (* entries in route tables *) extra = 4; (* extra bytes in lambuffer, stx+bll+opc+etx *) opco = 9; (* index in data *) logcode = #h00; (* opcode 0.0 *) nb_code = #h10; (* log of refuse message *) refuse_code=#h12; (* refuse message *) newaddr_code = #hb1;(* opcode 11.1 *) reading = #hb2; (* opcode 11.2 *) updatevar= #hbe; (* opcode 11.14 *) nc_route = 13; \f type statetype= ( discon, idle, wack, wrep ); inputtype= ( out, data, ackn, nack, bell, enqu, nons, tmo, lto ); modulref = ( sup, ncs, dcs, net); tablerange = 1..tablesize; macrotable = array ( tablerange) of macroaddr; modultable = array ( tablerange) of modulref; tsbuftype= (* message to/from tss *) record bytes: integer; data: array (1..tsbufleng) of byte; end; logtype= record bytes: integer; data: array (1..logleng) of byte; end; lambuftype= (* message to/from lamdriver *) packed record stxt, bll, opc: byte; text: array (1..lambufsize-extra+1) of byte; end; note = record (* type 11.2 and 11.14 *) head: alarmlabel; data: array ( 1..8) of integer; end; flawshape = packed record (* mess 1.02 *) head : alarmlabel; data : alarmlabel end; createchtype= (* message format in createchannel operation *) record controlinfo, timeout: byte; end; actionrow= array (inputtype) of integer; actiontabletype= array (idle..wrep) of actionrow; \f const actiontable= actiontabletype( (* out data ackn nack bell enqu nons tmo lto *) (*idle*)actionrow( 1, 3, 0, 0, 12, 7, 0, 11, 0), (*wack*)actionrow( 2, 3, 4, 6, 6, 7, 8, 9, 0), (*wrep*)actionrow( 2, 3, 5, 6, 6, 7, 8, 10, 0)); (* operation codes in protocol between tsconnectors *) (* data1..ack2 must be consecutive values !! *) data1 = 17; (* ord(dc1) *) data2 = 18; (* ord(dc2) *) ack1 = 19; (* ord(dc3) *) ack2 = 20; (* ord(dc4) *) nakop = 21; (* ord(nak) *) enqop = 5; (* ord(enq) *) belop = 7; (* ord(bel) *) \f var (*pools*) mypool: pool (no_of_mybuf) of logtype; (* messagetype *) lampool: pool (2+no_of_lamlis) of lambuftype; updatepool: pool 1 of updates; (* updates *) timerpool: pool 1 of timers; (* for timeout *) (*references*) pending, myref, lamref, tmomes, msg: reference; z: zone; (*integers*) action, checklamlisten, (* how many listenbuffers to be checked after recreation of lamchannel caused by output or input status error *) i, sendcnt, retrcnt, (* statistics counters *) givupcnt, reccnt, nakcnt, formcnt, lamoutcnt, lamincnt, ttc, (* transmission error count pr message *) tec : integer := 0; (* transmis. error count *) testlevel : integer:= 0; (* controls testoutput *) mytick : integer:= tick2; (* controls timeout *) ttcmax : integer:= 17; (* max errors pr message *) (*booleans*) testboo : boolean; reccode, (* opc in received block *) blockno, (* last send blockno *) lastack (* last send ackno *) : byte; state: statetype; input: inputtype; (*------------------------ routing --------------------------------*) who, here: alarmnetaddr:= alarmnetaddr(macroaddr(0,0,0), netc_mic_addr); ix, top : tablerange:= 1; node : macrotable := macrotable(tablesize***macroaddr(0,0,0)); modul: modultable := modultable(tablesize*** net ); \f (*forward*) procedure testwrite (level: integer; a:alfa; i:integer); forward; \f (* wait, with return of dummy messages *) procedure tswait ( var msg: reference; var sp: sempointer ); begin wait ( msg, sp^); while msg^.u3 = dummy_route do begin return ( msg); wait ( msg, sp^) end; end; procedure book ( time: integer); begin timerbook ( tmomes, msg, time, netc_mic_addr, timeoutsem^, timeoutanswer.w^) end; procedure moretime ( time: integer); begin timerupdate ( tmomes, time, timeoutsem^, timeoutanswer.w^) end; \f procedure createchn (timeoutper: integer); (* creates lamchannel *) begin alloc ( lamref, lampool, lamoutsem.s^); repeat lamref^.u1:= create_it_ch; lamref^.u2:= tsc_port; lamref^.u3:= lam_route; lock lamref as crbuf: createchtype do begin crbuf.controlinfo:= ts_control; crbuf.timeout:= timeoutper; end; signal (lamref, lamsem^); tswait (lamref, lamoutsem.w); if lamref^.u2 <> 0 then (* error *) begin count ( lamoutcnt); testwrite ( 1, "createch u2:", lamref^.u2); end; until lamref^.u2= 0; release ( lamref); end; (* createchn *) \f procedure sendlam; begin msg^.u2:= tsc_port; signal ( msg, lamsem^) end; \f procedure route_local ( var msg : reference ); (* route message from other node or message not transmitted. *) var where : macroaddr; begin lock msg as head: alarmlabel do where:= head.rec.macro; node(top):= where; ix:= 1; while node(ix) <> where do ix:= ix+1; (*q testwrite ( 32, "local to ", ix); q*) msg^.u1:= 2; case modul(ix) of dcs: signal ( msg, dcsem^); ncs: signal ( msg, ncsem^); otherwise signal ( msg, supsem^) end end; \f <* procedure writeblock ( var msg: reference); (* writes message as a lambuffer *) var i, top : integer; begin testout ( z,"u2: ", msg^.u2); lock msg as lambuf: lambuftype do with lambuf do begin testout ( z," stx ", stxt); testout ( z," bll ", bll); testout ( z," opc ", opc); top:= bll; if top > lambufsize-3 then top:= lambufsize-3; for i:= 1 to top do testout ( z, " text ", text(i)); end; end; *> \f function decodeinput : inputtype; (* get buffer from mainsem; if ts-message to dc, nc, or sup then signal else decode inputtype *) var where : macroaddr; begin repeat tswait ( msg, mainsem.w); case msg^.u3 of tim_route: (* buffer from timeout *) decodeinput:= tmo; lam_route: (* buffer from lam_driver *) case msg^.u2 of 0: lock msg as lambuf: lambuftype do with lambuf do begin reccode:= opc; if (bll < extra) or (bll > lambufsize) then begin reccode:= ord(sub); count ( formcnt); testwrite ( 4, "blocklength ", bll); end else if text(bll-extra+1) <> ord(etx) then begin reccode:= ord(sub); count ( formcnt); testwrite ( 4, "format error", bll-extra+1); end; case reccode of data1, data2 : decodeinput:= data; ack1, ack2 : decodeinput:= ackn; nakop : decodeinput:= nack; belop : decodeinput:= bell; enqop : decodeinput:= enqu; otherwise decodeinput:= nons end (* case lambuf.opc *); end; 1,3: (* after recreate *) if checklamlisten > 0 then begin checklamlisten:= checklamlisten-1; decodeinput:= nons; sendlam end; 5: (* input timeout *) decodeinput:= lto; otherwise (* error *) begin count ( lamincnt); testwrite ( 2, "lamresultu2:", msg^.u2); testwrite ( 2, "lamresultu4:", msg^.u4); (*q if ( testlevel mod 4) >= 2 then writeblock ( msg); q*) decodeinput:= nons; end end (* case lammsg^.u2 *); \f otherwise (* from dc, nc or sup *) begin (* ts message *) if msg^.u4 = newaddr_code then (* change routetables *) lock msg as head: alarmlabel do begin if msg^.u3 = dc_route then begin mytick:= tick1; (* i have a dc *) head.rec:= head.send; head.result:= accepted; modul(top):= dcs end else if msg^.u3 = nc_route then modul(top):= ncs else begin modul(top):= sup; here.macro:= head.send.macro; end; ix:= 1; while modul(ix) <> modul(top) do ix:= ix+1; node(ix):= head.send.macro; if ix = top then top:= top+1; (*q testwrite ( 32,"change ", ix); q*) end; (* opcode 11.1 *) lock msg as head: alarmlabel do who:= head.rec; if who = here then begin (* msg for me *) if msg^.u4 = updatevar then (* 11.14 *) lock msg as buf: note do with buf do begin testlevel:= data(1); mytick:= data(2); ttcmax:= data(3); head.result:= accepted; head.rec:= head.send; head.send:= here; msg^.u4:= updatevar+1 end else if msg^.u4 = reading then (* 11.02 *) lock msg as buf: note do with buf do begin data(1):= sendcnt; sendcnt:= 0; data(2):= retrcnt; retrcnt:= 0; data(3):= givupcnt; givupcnt:= 0; data(4):= reccnt; reccnt:= 0; data(5):= nakcnt; nakcnt:= 0; data(6):= formcnt; formcnt:= 0; data(7):= lamoutcnt; lamoutcnt:= 0; data(8):= lamincnt; lamincnt:= 0; head.result:= accepted; head.rec:= head.send; head.send:= here; msg^.u4:= reading+1; end else if msg^.u4 = refuse_code then else begin (* unknown op-code *) lock msg as buf: flawshape do with buf do begin data:= head; data.op_code:= msg^.u4; head.rec:= head.send; head.send:= here; head.result:= unknown_opcode; end; msg^.u4:= refuse_code; end end; lock msg as head: alarmlabel do begin where:= head.rec.macro; head.op_code:= msg^.u4 end; modul(top):= net; node(top):= where; ix:= 1; while node(ix) <> where do ix:= ix+1; (*q testout ( z,"found in ", ix); q*) msg^.u3:= netc_route; if msg^.u4 = refuse_code then return ( msg) else case modul(ix) of sup: signal ( msg, supsem^); ncs: signal ( msg, ncsem^); dcs: signal ( msg, dcsem^); otherwise decodeinput:= out end end (* ts message *) end (* case u3 *) until not nil (msg) end; (* of decodeinput *) \f function getinput: inputtype; (* gets the next buffer to handle. The buffer is taken from either mainsem or outsem depending on the state and the semaphores *) begin if (state= idle) and open (outsem.w^) then begin tswait (msg, outsem.w); getinput:= out end else getinput:= decodeinput; <* if msg^.u3= lam_route then begin (* listenbuffer with answer from lam_driver *) if (checklamlisten>0) then (* lamchannel recreated caused by outputbuffer or listenbuffer - listenbuffers are to be checked while outputbuffer has been checked already *) begin checklamlisten:= checklamlisten-1; if (msg^.u2=1) or (msg^.u2=3) then begin (* listenbuffer returned by createchannel *) statuserror:= true; sendlam; end end (* checklamlisten *) else if (msg^.u2<> 0) and (msg^.u2<> 5) then (* status error in lamlistenbuffer *) begin count ( lamincnt); testwrite( 2, "lam status: ",msg^.u2); statuserror:= true; (* lamchannel recreated caused by listenbuffer - (* try again: *) sendlam; end (* status error in lamlistenbuffer *) end (* listenbuffer from lamdriver *) *> end (* getinput *); \f procedure trans (transcode: byte); (* gets and fills in lamoutputbuffer, sends it to lamdriver *) var errors: integer:= 0; begin tswait (lamref, lamoutsem.w); while (errors < 10) and ( lamref^.u2> 0) (* status error *) do begin case lamref^.u2 of 1,3: (* channel recreated by driver *) begin testwrite ( 1, "lamch create", lamref^.u2); checklamlisten:= no_of_lamlis; (* listenbuffers might have been returned upon recreation *) end; 4,5: testwrite ( 1, "lamresult: ",lamref^.u2) otherwise begin if lamoutcnt mod 10 = 0 then testwrite ( 1, "lamerrorout:", lamoutcnt); end; end (* case lamref^.u2 *); count ( lamoutcnt); (* try last output again: *) errors:= errors+1; lamref^.u2:= tsc_port; signal (lamref, lamsem^); tswait (lamref, lamoutsem.w) end (* while status error *); (* now compose lambuffer *) if ( transcode = data1 ) or ( transcode = data2 ) then (* copy message onto lambuffer *) lock lamref as lambuf: lambuftype do if (pending^.u4 = logcode) then (* logmessage to dc *) lock pending as mess: logtype do with lambuf do begin if (mess.bytes < label_size) or (mess.bytes > logleng) then begin testout(z,"no_of_bytes:",mess.bytes); testout(z,"u1: ",pending^.u1); testout(z,"u2: ",pending^.u2); testout(z,"u3: ",pending^.u3); testout(z,"u4: ",pending^.u4); for i:= 1 to 10 do testout(z," log ",mess.data(i)); end; if (mess.bytes < label_size) or ( mess.bytes > logleng) then mess.bytes:= logleng; bll:= mess.bytes+extra; opc:= transcode; for i:= 1 to bll-extra do text(i):= mess.data(i); text(bll-extra+1):= ord(etx); end (* logmessage to dc *) else (* ts message *) lock pending as mess: tsbuftype do with lambuf do begin if (mess.bytes < label_size) or (mess.bytes > tsbufleng) then begin testout(z,"no_of_bytes:",mess.bytes); testout(z,"u3: ",pending^.u3); for i:= 1 to 10 do testout(z," text ",mess.data(i)); end; if (mess.bytes < label_size) or (mess.bytes > tsbufleng ) then mess.bytes:= tsbufleng; bll:= mess.bytes + extra; opc:= transcode; for i:= 1 to (bll-extra) do text(i):= mess.data(i); if text(opco) <> pending^.u4 then testwrite ( 4,"opcode ", text(opco)); text(bll-extra+1):= ord(etx); end (* opcode=dataop *) else lock lamref as lambuf: lambuftype do with lambuf do begin bll:= extra; opc:= transcode; text(1):= ord(etx); end; (* now send lambuffer *) lamref^.u2:= tsc_port; (* if testlevel > 48 then writeblock ( lamref); *) signal (lamref, lamsem^); if not nil (msg) then case msg^.u3 of tim_route: ; lam_route: sendlam; dc_route: begin testout ( z, "skip msg ", msg^.u3); testout ( z, "opcode ", msg^.u4); return ( msg); end; otherwise return (msg); end; end; \f procedure accept_data; (* copies listenbuffer from lamdriver onto ts-buffer and signals it to dc or supervisor *) var reply: byte; begin (* copy lambuffer onto ts buffer *) lock msg as lambuf: lambuftype do if ( lambuf.text(opco)= logcode ) (* log-message *) then begin sensesem ( myref, myfree.w^); if not nil ( myref) then lock myref as mess: logtype do with lambuf do begin bll:= bll-extra; if bll < label_size then bll:= label_size else if bll > logleng then bll:= logleng; mess.bytes:= bll; for i:= 1 to bll do mess.data(i):= text(i); myref^.u4:= text(opco) (* op_code *); end end else begin sensesem ( myref, listensem^); if nil ( myref) then sensesem ( myref, myfree.w^); if not nil ( myref) then lock myref as mess: tsbuftype do with lambuf do begin bll:= bll - extra; if bll < label_size then bll:= label_size else if bll > tsbufleng then bll:= tsbufleng; mess.bytes:= bll; for i:= 1 to bll do mess.data(i):= text(i); myref^.u4:= text(opco) (*op_code*); end end; if nil ( myref) then (* no free buffer for the received data *) begin count ( nakcnt); reply:= nakop end else begin (* data is in myref, send to dc, nc, or sup *) reply:= reccode+2; lastack:= reply; myref^.u3:= netc_route; route_local ( myref); count ( reccnt); end; trans ( reply) end; (* of accept message *) \f procedure block_ok; begin return ( pending); moretime ( -1); tec:= tec + ttc; state:= idle end; procedure retransmit; begin trans ( blockno); moretime ( mytick); ttc:= ttc+1; count ( retrcnt); state:= wack end; \f procedure give_up ( var msg: reference); var code : byte; begin count ( givupcnt); lock msg as head : alarmlabel do code:= head.op_code; if ( code = nb_code) or ( code = refuse_code ) then return ( msg) else begin lock msg as buf : flawshape do with buf do begin data:= head; with head do begin no_of_by:= 2*label_size+2; rec:= send; send:= here; result:= no_connection end end; msg^.u3:= netc_route; msg^.u4:= refuse_code; (* 1.2 *) route_local ( msg) end end; \f procedure testwrite (level: integer; a:alfa; i:integer); begin if ( testlevel mod ( 2*level)) >= level then testout (z,a,i) end (* testwrite *); \f (**************************** * * * main program * * * ****************************) begin testopen (z, own.incname, opsem); testout(z,version,al_env_version); blockno:= data2; (* create channel *) createchn (con_lam_time); (* checklamlisten:= 0; *) (* initialise lamlistenbuffers *) for i:= 1 to no_of_lamlis do begin alloc (lamref, lampool, mainsem.s^); lamref^.u1:= read_it; (* input *) lamref^.u2:= tsc_port; lamref^.u3:= lam_route; signal (lamref, lamsem^); end; (* initialise lamoutputbuffer *) for i:= 1 to 1 do begin alloc (lamref, lampool, lamoutsem.s^); lamref^.u1:= write_it; (* output *) lamref^.u2:= 0; lamref^.u3:= lam_route; lock lamref as lambuf: lambuftype do lambuf.stxt:= ord(stx); return (lamref); end; (* initialise timeout *) alloc (msg, timerpool, mainsem.s^); alloc (tmomes, updatepool, timeoutanswer.s^); tmomes^.u3:= tim_route; book ( mytick); for i:= 1 to no_of_mybuf do begin (* initialise myoutputbuffer *) alloc (myref, mypool, myfree.s^); myref^.u1:= 2 (* write *); myref^.u3:= dc_route; return (myref); end; \f repeat (* until forever *) (*--------------------- connect loop ----------------------------*) state:= discon; lastack:= nakop; repeat case getinput of out: give_up ( msg); data: begin accept_data; state:= idle end; bell, enqu: begin trans ( lastack); state:= idle end; nack: begin sendlam; state:= idle end; tmo: begin book ( mytick); trans ( belop) end; otherwise sendlam end; until state=idle; testout ( z,"connected ", tsc_port); \f (*--------------------- main loop -----------------------------------*) repeat input:= getinput; action:= actiontable(state, input); (*-- ---------- case state of idle: testwrite ( 16, "idle ", action); wack: testwrite ( 16, "wack ", action); wrep: testwrite ( 16, "wrep ", action) end; -- ----------*) (*---------- .. case input of data: testwrite ( 16, " data ", ord(state)); out : testwrite ( 16, "out ", ord(state)); ackn: testwrite ( 8, "ackn ", ord(state)); nack: testwrite ( 8,"nack * ", ord(state)); bell: testwrite ( 8, "bell * ", ord(state)); enqu: testwrite ( 8, " enqu ", ord(state)); lto : if state <> idle then testwrite ( 8, "lto ", ord(state)); tmo : testwrite ( 8, " tmo ", ord(state)); nons: testwrite ( 4, "** nons ", ord(state)) end; (* if testlevel >= 4 then if input = nons then writeblock ( msg); .. (* ----------*) case action of 0: (*no action *) sendlam; 1: (* send data block *) begin blockno:= data1 + data2 - blockno; pending :=: msg; trans ( blockno); moretime ( mytick); ttc:= 0; (* 1st try *) count ( sendcnt); state:= wack end; 2: (* put block into queue *) signal ( msg, outsem.s^); 3: (*send ack to lam and data to tss or dc*) accept_data; 4: (* ack x received *) begin if reccode-2 = blockno then block_ok; sendlam end; 5: (* repeated ack received *) begin if reccode - 2 = blockno then (* ok *) begin block_ok; sendlam; end else retransmit; end; 6: (* retransmit data *) retransmit; 7: (* reply request *) trans ( lastack); 8: (* try enq again *) begin trans ( enqop); moretime ( mytick); ttc:= ttc+1; testwrite ( 8, "enq again ", ttc); state:= wrep; end; 9: (* timeout for ack for a block *) begin book ( mytick); trans ( enqop); ttc:= ttc+1; testwrite ( 8, "enq send ", ttc); state:= wrep; end; 10: (* timeout for enq *) begin book ( mytick); trans ( enqop); ttc:= ttc+1; testwrite ( 8, "enq timeout ", ttc); end; 11: (* a late timeout *) book ( -1); 12: (* bell received *) trans ( nakop) end (* case *); if ttc > ttcmax then (* give up *) begin give_up ( pending); tec:= tec+ttc; ttc:= 0; state:= idle; end; if tec >= 30000 then tec:= 100; if tec mod 100 = 10 then begin testout ( z, "transm error",tec); tec:= tec+1; end; until state = discon; testout ( z,"disconnected", tsc_port); testout ( z,"trans errors", tec); until false; end. ▶EOF◀