|
DataMuseum.dkPresents historical artifacts from the history of: RC3500 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC3500 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 48384 (0xbd00) Types: TextFileVerbose Names: »tsvacjob«
└─⟦a41ae585a⟧ Bits:30001842 SW-save af projekt 1000, Alarm-system └─⟦72244f0ef⟧ └─⟦this⟧ »tsvacjob«
job srs 9 200 time 11 0 area 10 size 100000 (source=copy 25.1 tsvaclst=set 1 disc1 tsvaclst= indent source mark lc listc= cross tsvaclst o errors head 1 message tsvac program pascal80 spacing.3000 codesize.3000 alarmenvc source o c lookup pass6code if ok.yes (tsvacbin=set 1 disc1 tsvacbin= move pass6code scope user tsvacbin ) tsvaclst= copy listc errors scope user tsvaclst convert errors finis ) \f (* vc(at)-connector alarmsystem *) (**** short decription of process ***** PROCESS vcatc ( param ); declarations; procedures; functions; BEGIN start of lam-driver; alloc of buffers; initialiser variables; REPEAT read buffer to mess_ref; rute , func , types := depend of u3 and u4; *** classify buffer *** CASE rute of CASE types of : buftype:= END END action:= acttable ( vcatc_state , buftype ); *** make action *** CASE action of 1 : 2 : 8 : lamspeak; 16 : END *** send buffer *** CASE buftype of END UNTIL FALSE END. ***) \f process vcatc( opsem : sempointer; var messem , (*input to connector*) queuesem : !ts_pointer; (*queue of unprocessed messages*) var vchsem , (*output to vc-handler*) lamsem , (*message to lam-driver*) timeoutsem , (*for booking and update*) com_pool : !sempointer; var dc_address : macroaddr; (*macro addresse own dc*) micadr : integer; (*micro adr for this vc(at)*) canno : byte); (*cannel number to lamdriver*) \f const version = "vers 3.07 /"; max_lbuf_needed = 5; (*------ consts used by LAMSPEAK ------*) max_info_bytes = 2; type mask_unknown = record fix : alarmlabel; data: alarmlabel; end; mask_service = record fix : alarmlabel; data: integer; end; mask_poll = record fix : alarmlabel; error_count : integer; poll_rate : integer; end; mask_vcm = record fix : alarmlabel; data : alarmnetaddr; end; mask_atvcdc = record fix : alarmlabel; at : alarmnetaddr; vc : alarmnetaddr; dc : alarmnetaddr; end; mask_atadr = record fix : alarmlabel; entry: at_addr_e; end; mask_atts = record fix : alarmlabel; entry: at_ts_e; end; mask_test = record fix : alarmlabel; data : array(1..5) of integer; end; ch_format = packed record cntl_inf : byte; time_inf : byte; end; state_type = (not_ready, (* initially table *) passive, (* waiting start poll *) active, (* polling state *) lam_talk, (* lamspeak active *) lam_need_buf, (* lamspeak waiting listenbuf *) vcatc_need_buf, (* vcatc waiting listenbuf *) wait_shorttime, (* waiting shorttime from vcath *) stop_poll); (* send stop poll mess *) buf_type = (unknown, (*unknown buffer*) alarm , (*alarmbuffer*) listen , (*listen buffer*) table , (*buffer for update tables*) report , (*buffer to vc(at)*) service, (*buffer to vc(at)-connector*) testat , (*testbuffer to vc(at)*) operate, (*vc,dc operations*) clock , (*poll pulse*) ltime , (*longtime timeout*) stime , (*shorttime timeout*) lam , (*answer from lam-driver*) used , (*current buffer on inner semaphore*) empty , (*empty buffer to return*) permiss); (* dc to vc ask buffer *) input_type = (from_sem , from_listen_ref, nothing ); (*------------- Types only used by the LAMSPEAK procedure ---------*) to_telegram_type = packed record to_data : 0..255; (* 8 bits *) to_opcode : 0.. 3; (* 2 bits *) to_serial_no : 0.. 1; (* 1 bit *) to_check : 0.. 31 (* 5 bits *) end; lbuf_kind_type = (log, norm); lbuf_record = record kind : lbuf_kind_type; noob : integer; reci : alarmnetaddr; opco : byte; upda : 0..15; resu : 0..15; dta1 : byte; dta2 : byte; addr : alarmnetaddr end; oknok_type = (ok , nok); (* state of transmitter line *) \f var test : boolean := true; buftype : buf_type; (* type of current buffer *) vcatc_state : state_type; old_state : state_type; input : input_type; line : oknok_type; (* transmitter line state *) lamspeak_state : (nottele, lettertovc, polling, letterfromvc, testi); (* no of record's in tables *) noatadr, noatts , novcm , novce : integer := 0; (*tables*) atadrtable: array(1..vc_addr_l) of at_addr_e;(*atadrcode <=> netadr*) attstable : array(1..at_ts_l ) of at_ts_e; (*ts addresse for at*) vcmtable : array(1..vcmat_l ) of vcmat_e; (*vc addresse for potentiel guard transfer*) vcetable : array(1..vce_l ) of vce_e; (*vc addresse with guardtransfer to this connector*) rute : byte; func, types : func_grp; found : boolean; (* auxiliary *) action, (* auxiliary *) intg_aux, (* auxiliary *) next : integer; (* auxiliary *) adr_code: byte; own_dc , cur_vcm , zero_addr, work : alarmnetaddr; listen_ref, (* unused listenbufs *) bookup_ref, (*booking or update timeout module*) clock_ref, (*unused clockbuffer*) timeout_ref, (*unused timeoutbuffer*) tolam_ref, (* unused lambuffer *) fromlam_ref, (* buffer from lamdriver *) mess_ref : reference; (* current buffer *) timeout_answer: semaphore; (* immediately answer from timeout modul *) lam_pool : pool 1 of integer; (* rettes til integer *) tim_pool : pool no_vcc_tim of timers; (* rettes til timers *) book_pool : pool no_vcc_upd of updates; (* rettes til updates *) (* counters *) pack_counter, (* no of mess to vch *) trans_ok , (* succession of ok telegram *) no_of_queue, (* no of bufs in queue *) line_error_count, (* total number of transmiterror *) no_of_listen, (* no of bufs on listensem *) no_of_returned, (* no of received returned bufs *) no_of_released, (* no of needless bufs released *) no_of_unknown : integer:= 0; (* no of unknown messages received *) index,object: integer; (*param to book and update*) (* limits *) serve_limit : integer := service_lim; stoppoll_limit : integer := stop_poll_lim; max_succ_errors : integer := max_succ_lin_err; fix_incr_on_err : integer := trans_err_rate; poll_delay : integer := poll_delay_time; zout : zone; (* testoutput from modul *) (*--------- Vars only used by the LAMSPEAK procedure ----------*) speak_action : integer := 8; (* as p_ack in polling state *) keep_the_telegram : to_telegram_type; area_to_lam , area_from_lam : array (1..3) of byte; lbuf_info : array (1..max_lbuf_needed) of lbuf_record; keep_the_opcode : byte; teletxt : alfa; at_table_addr : alarmnetaddr; atts_table_index : integer; serial_no , succ_line_errors, area_pointer , lbuf_needed : integer := 0; below_serve_limit , below_stoppoll_limit, lamtest, boo : boolean := true; \f type row = array(buf_type) of integer; col = array(state_type) of row; const acttable = col ( (* u s o p *) (* n l r e t p e *) (* k a i t e r e e c l s e r *) (* n l s a p v s r l t t u m m *) (* o a t b o i t a o i i l s p i *) (* w r e l r c a t c m m a e t s *) (* n m n e t e t e k e e m d y s *) (*not_ready *)row( 1, 2, 4, 5, 2, 2, 2, 2, 6, 6, 6, 6, 0,18, 2), (*passive *)row( 1, 3, 4, 5, 3, 7, 3,15, 6, 6, 6, 6, 0,18, 3), (*active *)row( 1, 8, 4, 5, 8, 7, 8,15, 8, 6, 6, 6, 0,18, 8), (*lam_talk *)row( 1, 9, 4, 9, 9, 7, 9,15,10,11,12, 8, 0,18, 9), (*lam_need_buf *)row( 1, 9, 8, 9, 9, 7, 9,15,19,11,12,17, 0,18, 9), (*vcatc_need_buf*)row( 1, 9,13, 9, 9, 7, 9, 9,10, 6,14,17, 0,18, 9), (*wait_shorttime*)row( 1, 9,16, 9, 9, 9, 9, 9,10, 6,14,17, 0,18, 9), (*stop_poll *)row( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); \f procedure save_listen_buf; forward; procedure update(ticks: integer); (* update the booked timeoutbuffer *) begin bookup_ref^.u1:= update_req; bookup_ref^.u4:= #hc4; lock bookup_ref as buf: updates do begin buf.index := index; buf.count := ticks; buf.object:= object end; signal(bookup_ref,timeoutsem^); wait (bookup_ref,timeout_answer); (*q if test then testout(zout,"update ",ticks*10+bookup_ref^.u2); q*) end; procedure book(ticks: integer); (* booking of one modultimeout *) begin if not nil( timeout_ref ) then begin bookup_ref^.u1:= book_req; bookup_ref^.u4:= #hc3; lock bookup_ref as buf: updates do begin buf.count:= ticks; buf.object:= ticks end; lock timeout_ref as buf: timers do buf.object:= ticks; push(timeout_ref,bookup_ref); signal(bookup_ref,timeoutsem^); wait(bookup_ref,timeout_answer); (*q if test then testout(zout,"book ",ticks*10+bookup_ref^.u2); q*) lock bookup_ref as buf: updates do begin index := buf.index; object:= buf.object end end end; \f function get_adr_code(atadr: alarmnetaddr; var code: byte): boolean; var found: boolean; begin next:= 1; found:= false; while (not found) and (next<=noatadr) do if atadr=atadrtable(next).at_addr then begin found:= true; code := atadrtable(next).addr_code end else next:= next+1; get_adr_code:= found; end; function get_net_addr(var atadr: alarmnetaddr; code: byte): boolean; var found: boolean; begin next:= 1; found:= false; while (not found) and (next<=noatadr) do if code = atadrtable(next).addr_code then begin found:= true; atadr:= atadrtable(next).at_addr end else next:= next+1; get_net_addr:= found; end; \f function get_atts_index(tsadr: macroaddr; var index: integer): boolean; var found: boolean; begin next := 1; found:= false; while (not found) and (next<=noatts) do if tsadr = attstable(next).ts_addr then begin found:= true; index:= attstable(next).index end else next:= next+1; get_atts_index:= found; end; \f procedure unknown_buf(error: byte); (* returning of one unknown buffer *) begin buftype:= unknown; mess_ref^.u4:= #h10; lock mess_ref as buf: mask_unknown do with buf do begin data:= fix; fix.rec := own_dc; fix.send.micro:= micadr; fix.no_of_by := 2*label_size+2; fix.result := error end; no_of_unknown:= (no_of_unknown mod max_int) + 1 end; procedure return_buf( error: byte ); (* returned buffer to sender with error *) begin lock mess_ref as buf: alarmlabel do with buf do if send.micro < at_addr_limit then begin (* receipt with error *) buftype:= unknown; mess_ref^.u4:= mess_ref^.u4 + 1; rec := send; send.micro := micadr; result := error end; if buftype <> unknown then unknown_buf( error); end; \f procedure send_to_vch; begin case mess_ref^.u4 div 16 of 4,8 : pack_counter:= (pack_counter+1) mod max_int; otherwise end; signal(mess_ref,vchsem^); end; procedure restart_clock; begin signal(mess_ref,timeoutsem^); if no_of_listen<2 then begin sensesem(mess_ref,com_pool^); if not nil (mess_ref) then save_listen_buf; buftype:= clock; end end; \f function get_listen_buf: boolean; (* serving out one listenbuf from listen_ref *) begin if no_of_listen>0 then begin pop(mess_ref,listen_ref); mess_ref^.u2:= 1; mess_ref^.u3:= netc_route; mess_ref^.u4:= #hc5; buftype:= listen; no_of_listen:= no_of_listen - 1; (*q if test then testout(zout," no of li : ",no_of_listen); q*) get_listen_buf:= true; end else get_listen_buf:= false end; procedure save_listen_buf; (* save listenbuf from mess_ref to listen_ref *) begin push(mess_ref,listen_ref); buftype:= used; no_of_listen:= no_of_listen + 1; (*q if test then testout(zout," no of li : ", no_of_listen); q*) end; \f procedure lamspeak; (*************************************************************** * * * Function: Lamspeak is responsible for the communication * * with VC(AT) via lamdriver, that is the protocol * * for telegram communication is administrated by * * lamspeak. * * The VC(AT)-Conn is in state LAM_TALK. Lamspeak * * can change vcatc_state to either ACTIVE or * * LAM_NEED_BUF, else vcatc_state is unchanged * * LAM_TALK. * * * * Externals: * * * * Parameters: None. * * * Semaphores: None. * * * Programmed june 1980 by SRS * * ***************************************************************) \f const p_ack = 0; data = 1; opr = 2; status = 3; d_ack = 4; t_ack = 5; nak = 6; free = 7; type from_telegram_type = packed record from_data : 0..255; (* 8 bits *) from_opcode : 0.. 7; (* 3 bits *) from_check : 0.. 31 (* 5 bits *) end; mask_norm_lbuf = packed record fix_label : alarmlabel; norm_inf : byte end; mask_log_lbuf = packed record fix_label : alarmlabel; log_addr : alarmnetaddr; log_opc : byte; log_alarm : byte end; var slave_opcode : integer; slave_data : byte; numb_of_bytes : integer := label_size; lam_timeout : boolean := false; boo : boolean := true; \f procedure calltest(var r : reference); begin (*x lock r as telegram : to_telegram_type do begin if serial_no=0 then case telegram.to_opcode of 0: teletxt := " * POLL 0 "; 1: teletxt := " * DATA 0 "; 2: teletxt := " * TESTI 0 "; 3: teletxt := " * OPR 0 " end else case telegram.to_opcode of 0: teletxt := " * POLL 1 "; 1: teletxt := " * DATA 1 "; 2: teletxt := " * TESTI 1 "; 3: teletxt := " * OPR 1 " end; testout(zout, teletxt, telegram.to_data); end; x*) end; \f procedure build_same_telegram( var r: reference ); begin r^.u2 := canno; lock r as telegram : to_telegram_type do telegram := keep_the_telegram; if lamtest then calltest( r ); end (* of procedure build_same_telegram *); procedure build_serial_changed_telegram( var r: reference ); begin (* build the same telegram, but change serial_no *) r^.u2 := canno; serial_no := 1 - serial_no; lock r as telegram: to_telegram_type do begin telegram := keep_the_telegram; telegram.to_serial_no := serial_no end (* of lock statement *); boo := check5( r, generate); lock r as telegram: to_telegram_type do keep_the_telegram := telegram; end (* of procedure build_serial_changed_telegram *); \f procedure build_a_poll_telegram( var r: reference ); begin r^.u2 := canno; lock r as telegram : to_telegram_type do begin (*----------------------------------- build up the buffer *) serial_no := 1 - serial_no; with telegram do begin (*------------------------------ build the telegram *) to_opcode := 0; to_serial_no:= serial_no; to_data := 0; if serial_no = 0 then to_check := 10 (* as bits 01010 *) else to_check := 19; (* as bits 10011 *) end; (*---------------------------------- keep the telegram *) keep_the_telegram := telegram; end (* of lock statement *); if lamtest then calltest( r ); end (* of procedure build_a_poll_telegram *); \f procedure build_a_letter_telegram( var r: reference ); begin serial_no := 1 - serial_no; r^.u2 := canno; lock r as telegram : to_telegram_type do begin (* build up the buffer *) with telegram do begin if area_pointer = 1 then to_opcode := 3 (* OPR master opcode *) else to_opcode := 1; (* DATA master opcode *) to_serial_no := serial_no; to_data := area_to_lam( area_pointer ); end; end (* of lock statement *); if lamtest then calltest( r ); boo := check5( r, generate ); (* complete the telegram *) (*---------------------------- keep the telegram *) lock r as telegram : to_telegram_type do keep_the_telegram := telegram; end (* of procedure build_a_letter_telegram *); \f procedure build_line_dep_telegram( var r : reference; line_was: oknok_type ); (* Maybe the serial number at VC(AT) has been changed * * of some unknown reason. Line_was = nok indicates * * that the serial_no must be changed. *) begin if line_was = ok then build_same_telegram( r ) else (* line was not ok *) build_serial_changed_telegram( r); end (* of procedure build_line_dep_telegram *); \f procedure build_an_lbuf( var r : reference; x : lbuf_record ); begin r^.u4 := x.opco; case x.kind of norm: lock r as buf : mask_norm_lbuf do begin with buf.fix_label do begin no_of_by := x.noob; rec := x.reci; op_code := x.opco; update := x.upda; result := x.resu end; buf.norm_inf := x.dta1; end; log: lock r as buf : mask_log_lbuf do begin with buf.fix_label do begin no_of_by := x.noob; rec := x.reci; op_code := x.opco; update := x.upda; result := x.resu end; buf.log_addr := x.addr; buf.log_opc := x.dta1; buf.log_alarm := x.dta2; end end (* of case on x.kind *); end (* of procedure build_an_lbuf *); \f procedure demand_lbuf( d_kind : lbuf_kind_type; d_noob : integer; d_reci : alarmnetaddr; d_opco : byte; d_upda : 0..15; d_resu : 0..15; d_dta1 : byte; d_dta2 : byte; d_addr : alarmnetaddr ); begin lbuf_needed := lbuf_needed + 1; with lbuf_info( lbuf_needed ) do begin kind := d_kind; noob := label_size + d_noob; reci := d_reci; opco := d_opco; upda := d_upda; resu := d_resu; dta1 := d_dta1; dta2 := d_dta2; addr := d_addr end; end (* of procedure demand_lbuf *); \f procedure fault_at_line; begin if succ_line_errors <> max_int then succ_line_errors := succ_line_errors + 1; if succ_line_errors = max_succ_errors then begin (*------ line alarm *) if lam_timeout then (* timeout *) demand_lbuf( norm, 1, own_dc, #h31, 0, 0, at_tim_excess, 0, own_dc) else (* not timeout *) demand_lbuf( norm, 1, own_dc, #h31, 0, 0, call, 0, own_dc ); lam_timeout := false; end; if line_error_count <= (max_int - fix_incr_on_err) then line_error_count := line_error_count + fix_incr_on_err else line_error_count := max_int; if (line_error_count >= serve_limit) and below_serve_limit then begin (*------service alarm *) (* high counter *) demand_lbuf( norm, 1, own_dc, #h34, 0, 0, call, 0, own_dc ); below_serve_limit := false; end; if (line_error_count >= stoppoll_limit) and below_stoppoll_limit then begin (*------ stoppoll alarm *) (* high counter *) demand_lbuf( norm, 1, own_dc, #h35, 0, 0, call, 0, own_dc ); below_stoppoll_limit := false; end; line := nok; end (* of fault_at_line *); \f procedure ok_at_line; begin line_error_count := line_error_count - 1; if line_error_count < 0 then line_error_count := 0; (* Must not be negative *) if (line_error_count < serve_limit) and not(below_serve_limit) then begin (*------ recall service alarm *) (* low counter *) demand_lbuf( norm, 1, own_dc, #h34, 0, 0, recall, 0, own_dc ); below_serve_limit := true; end; if (line_error_count < stoppoll_limit) and not(below_stoppoll_limit) then begin (*------ recall stoppoll alarm *) (* low counter *) demand_lbuf( norm, 1, own_dc, #h35, 0, 0, recall, 0, own_dc ); below_stoppoll_limit := true; end; if succ_line_errors >= max_succ_errors then begin (*------recall line alarm *) demand_lbuf( norm, 1, own_dc, #h31, 0, 0, recall, 0, own_dc ); end; succ_line_errors := 0; line := ok; (*q if test then begin testout(zout,"line state: ",ord(line)); testout(zout,"succ lineerr",succ_line_errors); testout(zout,"lineerrcount",line_error_count); end; q*) end (* of ok_at_line *); \f procedure to_lam_driver; (*********************************************************** * The buftype is alarm, report or testat. * * Send a letter to VC(AT). A letter is always 3 telegrams * * The reference to the message buffer is mess_ref and this * * buffer will be released, ie buftype = empty. * * The reference to the unused lam buffer is tolam_ref. * * The letter is stored in the area_to_lam array * ************************************************************) begin keep_the_opcode := func * 16 + types; case buftype of testat : (* Send TESTI telegram by order of own DC *) begin (* opcode 8,0 or 8,2 *) serial_no := 1 - serial_no; tolam_ref^.u2 := canno; (*----------------------- build the telegram of TESTI *) lock tolam_ref as telegram : to_telegram_type do begin with telegram do begin to_opcode := 2; to_serial_no := serial_no; if keep_the_opcode = #h80 then to_data := 0 else to_data := 1; end; end (* of lock statement *); if lamtest then calltest( tolam_ref ); (*----------------------- complete the telegram *) boo := check5( tolam_ref, generate ); (*----------------------- keep the telegram *) lock tolam_ref as telegram : to_telegram_type do keep_the_telegram := telegram; lamspeak_state := testi; signal( tolam_ref, lamsem^ ); end (* of testat *); alarm, report : (* Send a letter by order of an AT-CONNECTOR *) begin area_pointer := 1; area_to_lam( 1 ) := keep_the_opcode; area_to_lam( 2 ) := adr_code; (* a lookup in the AT-addr_table * * is made outside lamspeak *) lock mess_ref as buf : mask_norm_lbuf do begin numb_of_bytes := buf.fix_label.no_of_by; if numb_of_bytes = label_size then area_to_lam( 3 ) := 0 else (* nbbbbb numb_of_bytes must be label_size + 1 here *) area_to_lam( 3 ) := buf.norm_inf; if (keep_the_opcode=#h41) or (keep_the_opcode=#h85) then case buf.fix_label.result of 0: area_to_lam(1) := keep_the_opcode (* accepted *) otherwise area_to_lam(1) := keep_the_opcode+1 (* rejected *) end (* of case *); end (* of lock statement *); build_a_letter_telegram( tolam_ref ); lamspeak_state := lettertovc; signal( tolam_ref, lamsem^ ); end; (* of alarm, report *) permiss : (* send a letter by order of own dc, opcode 6.4 *) begin area_pointer := 1; area_to_lam(1) := keep_the_opcode; lock mess_ref as buf: mask_vcm do begin area_to_lam(2) := adr_code; area_to_lam(3) := buf.fix.update; (* 0: says start at, 1: stop at *) end; (* of lock statement *) build_a_letter_telegram( tolam_ref ); lamspeak_state := lettertovc; signal( tolam_ref, lamsem^ ); end (* of permiss *) end (* of case *); end (* of to_lam_driver *); \f procedure from_lam_driver; var hlp, i: integer; begin case lamspeak_state of lettertovc : (* master telegram is opr or data ================*) case slave_opcode of p_ack, data , opr : (* non expected answer on opr or data *) speak_action := 1; status: speak_action := 14; d_ack: case area_pointer of 1: (* non expected answer on opr *) speak_action := 1; 2: (* data sended for the first time *) speak_action := 3 otherwise (* data sended for the third time *) speak_action := 4 end (* of case on area_pointer *); t_ack: case area_pointer of 1: (* expected answer on opr *) speak_action := 3 otherwise (* non expected answer on data *) speak_action := 1 end (* of case on area_pointer *); nak , free: speak_action := 2; end (* of case in lettertovc *); letterfromvc: (* master telegram is poll =====================*) case slave_opcode of p_ack: speak_action := 5; data : case area_pointer of 1: speak_action := 1; 2: speak_action := 6; 3: speak_action := 7 end (* of case *); opr , d_ack, t_ack: (* non expected answer on poll *) speak_action := 1; status: speak_action := 14; nak , free : speak_action := 2; end (* of case in letterfromvc *); polling: (* master telegram is poll ===========================*) case slave_opcode of p_ack: speak_action := 8; data , d_ack, t_ack: (* non expected answer on poll *) speak_action := 9; opr : speak_action := 10; status: speak_action := 14; nak , free : speak_action := 11; end (* of case in polling *); testi : (* master telegram is testi =============================*) case slave_opcode of p_ack , data , opr , d_ack : (* non expected answer on testi *) speak_action := 1; status: speak_action := 14; t_ack : speak_action := 12; nak , free : speak_action := 2; end (* of case in testi *) end (* of case on lamspeak_state *); case speak_action of (* the treatment of: "speak_actions" =======*) 1: (* non expected answers *) begin build_line_dep_telegram( tolam_ref, line ); fault_at_line; signal( tolam_ref, lamsem^ ) end; 2: (* nak and free answers only *) begin fault_at_line; build_same_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ) end; 3: (* letter not finished *) begin ok_at_line; area_pointer := area_pointer + 1; build_a_letter_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ) end; 4: (* letter finished, make receipt *) begin ok_at_line; area_pointer := 1; case area_to_lam(1) of #h30, #h31, #h32 : (* make receipt of delivered alarm *) begin boo := get_net_addr( at_table_addr, area_to_lam(2) ); demand_lbuf( log, 6, own_dc, #h2, 0, 0, area_to_lam(1), area_to_lam(3), at_table_addr ) end otherwise (* nothing *) end (* of case *); (* make master poll to handle response from vc *) build_a_poll_telegram( tolam_ref ); lamspeak_state := polling; signal( tolam_ref, lamsem^ ) end; 5: (* poll answers leading to poll sending *) begin ok_at_line; build_a_poll_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ) end; 6: begin area_from_lam(area_pointer) := slave_data; area_pointer := area_pointer + 1; ok_at_line; build_a_poll_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ) end; 7: (* three gathered telegrams, make lbuf *) begin area_from_lam(area_pointer) := slave_data; ok_at_line; area_pointer := 1; lamspeak_state := nottele; (* send the letter via lbuf *) hlp := area_from_lam(1); case get_net_addr( at_table_addr, area_from_lam(2)) of true : begin if (hlp = #h40) or (hlp = #h84) then (* "styr" or "test" *) demand_lbuf( norm, 1, at_table_addr, hlp, 0, 0, area_from_lam(3), 0, own_dc ) else if (0 < hlp) and (hlp < 5) then (* "start at", "stop at" "-start at" -*) begin case hlp of 1, 3: i := 0; (* permission was "start at" *) 2, 4: i := 1 (* permission was "stop at" *) end (* of case *); demand_lbuf( log, 4, own_dc, #h65, i, area_from_lam(3), 0, 0, at_table_addr ); end else begin (* refuse command *) area_to_lam(1) := #h10; area_to_lam(2) := area_from_lam(2); area_to_lam(3) := area_from_lam(3); lamspeak_state := lettertovc; build_a_letter_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ); end; end; false: begin if (hlp = #h40) or (hlp = #h84) then area_to_lam(1) := hlp + 3 else if (0<hlp) and (hlp<5) then area_to_lam(1) := #h65 else area_to_lam(1) := #h10; area_to_lam(2) := area_from_lam(2); area_to_lam(3) := area_from_lam(3); lamspeak_state := lettertovc; build_a_letter_telegram( tolam_ref ); signal( tolam_ref, lamsem^ ); end (* of false *) end (* of case on check *); end (* of action 7 *); 8: (* a single poll caused by a clockpulse *) begin ok_at_line; buftype := used; lamspeak_state := nottele end (* of action 8 *); 9: (* non expected answers caused by a single poll *) begin fault_at_line; buftype := used; lamspeak_state := nottele end (* of action 9 *); 10: (* first telegram of a letter is comming *) begin ok_at_line;; area_from_lam(1) := slave_data; area_pointer := 2; build_a_poll_telegram( tolam_ref ); lamspeak_state := letterfromvc; signal ( tolam_ref, lamsem^ ) end (* of action 10 *); 11: (* nak and free answers in polling state only *) begin fault_at_line; buftype := used; lamspeak_state := nottele end; 12: (* usable answers on master testi *) begin ok_at_line; demand_lbuf( norm, 1, own_dc, keep_the_opcode+1, 0, accepted, slave_data, 0, own_dc ); (*------ 8.1 or 8.3 demanded *) buftype := used; lamspeak_state := nottele; end (* of action 12 *); 13: (* empty *); 14: (* status answers *) begin demand_lbuf( norm, 1, own_dc, #h32, 0, 0, slave_data, 0, own_dc ); ok_at_line; build_serial_changed_telegram( tolam_ref); signal( tolam_ref, lamsem^ ) end (* of action 14 *); end (* of case on speak_action *); end (* of from_lam_driver procedure *); \f begin (******************************************* **** the body of the lamspeak procedure **** ********************************************) (*q if test then testout(zout,"speak st in ",ord(lamspeak_state)); q*) case buftype of clock : (* <--------<< *) (* ------ No nessage buffer is involved. * * ------ The lam buffer is idle at tolam_ref. *) begin build_a_poll_telegram( tolam_ref ); lamspeak_state := polling; signal( tolam_ref, lamsem^ ); end; permiss, alarm, (* <--------<< *) report, testat: (* the message buffer is involved at mess_ref. * * return this buffer, ie buftype := empty. * * The lam buffer is idle at tolam_ref. *) begin to_lam_driver; buftype := empty; end; lam : (* The message buffer is a lam buffer, that is * * the lam buffer is not idle. * * Transfer the reference, ie tolam_ref :=: mess_ref. *) begin tolam_ref :=: mess_ref; lock tolam_ref as telegram : from_telegram_type do begin (*----- get all the information needed *) slave_opcode := telegram.from_opcode; slave_data := telegram.from_data; end; (*x if lamtest then begin case slave_opcode of 0: teletxt := " P-ACK "; 1: teletxt := " DATA "; 2: teletxt := " OPR "; 3: teletxt := " STATUS "; 4: teletxt := " D-ACK "; 5: teletxt := " T-ACK "; 6: teletxt := " NAK "; 7: teletxt := " FREE " end; testout(zout, teletxt, slave_data); end; x*) if check5( tolam_ref, check ) = false then begin slave_opcode := free; if lamtest then testout(zout,"CHEHK5FAULT ",slave_opcode); end; if tolam_ref^.u2 <> 0 then begin slave_opcode := free; if tolam_ref^.u2 = 5 then begin lam_timeout := true; (*x if lamtest then testout(zout,"LAMTIMEOUT ",slave_opcode); x*) end; (*x if lamtest then testout(zout,"LAMFAULT ",tolam_ref^.u2); x*) end; from_lam_driver; end; listen : (* <--------<< *) (* The listen buffer is refered to by mess_ref. *) begin (*---- Nb ---- if lbuf_needed < 1 the program fault *) build_an_lbuf( mess_ref, lbuf_info( lbuf_needed ) ); lbuf_needed := lbuf_needed - 1; buftype := listen; end otherwise (*-------- Nb --- program fault *); end (* of case on buftype *); if lamspeak_state = nottele then vcatc_state := active; if lbuf_needed > 0 then begin (*q if test then testout(zout,"lbuf needed:",lbuf_needed); q*) vcatc_state := lam_need_buf; if no_of_listen > 0 then input := from_listen_ref; (* There is a lbuf *) end; (*q if test then testout(zout,"speak st out",ord(lamspeak_state)); q*) end (* of lamspeak procedure *); \f begin (***** main program *****) (* initier module *) testopen(zout,own.incname,opsem); testout(zout, version, al_env_version); testout (zout, "chann/addr ", canno*1000+micadr); alloc(mess_ref,lam_pool,messem.s^); with mess_ref^ do begin u1:= create_at_ch; u2:= canno; u3:= lam_route end; lock mess_ref as buf : ch_format do with buf do begin cntl_inf:= at_control; time_inf:= con_lam_time end; signal(mess_ref,lamsem^); (* initier timeout buffers *) alloc(bookup_ref,book_pool,timeout_answer); bookup_ref^.u3:= tim_route1; alloc(clock_ref,tim_pool,messem.s^); with clock_ref^ do begin u1:= delay_req; u3:= tim_route; u4:= #hc1 end; lock clock_ref as buf: timers do buf.object:= poll_delay; alloc(timeout_ref,tim_pool,messem.s^); with timeout_ref^ do begin u1:= book_req; u3:= tim_route1; u4:= #hc2 end; \f line := ok; input := from_sem; vcatc_state := not_ready; (* <--------<< *) old_state := not_ready; lamspeak_state := nottele; zero_addr := alarmnetaddr(macroaddr(0,0,0),0); cur_vcm := zero_addr; own_dc.macro := dc_address; own_dc.micro := 0; \f repeat (* read one new buffer *) (*q if test then begin testout(zout," input : ",ord(input)); testout(zout," vcatc st : ",ord(vcatc_state)); end; q*) buftype:= used; case input of from_sem : case vcatc_state of not_ready..active : if not nil(fromlam_ref) then mess_ref :=: fromlam_ref else if no_of_queue>0 then begin wait(mess_ref,queuesem.w^); no_of_queue:= no_of_queue - 1 end else wait(mess_ref,messem.w^); lam_talk : if not nil(fromlam_ref) then mess_ref :=: fromlam_ref else wait(mess_ref,messem.w^); otherwise wait(mess_ref,messem.w^) end; from_listen_ref : begin found:= get_listen_buf; input:= from_sem end; nothing : input:= from_sem otherwise end; (* classify buffer *) rute := mess_ref^.u3; func := mess_ref^.u4 div 16; types:= mess_ref^.u4 mod 16; (*q if test then begin testout(zout," route : ",rute); testout(zout," functype : ",func*100+types); end; q*) case rute of dummy_route : (*this buffer must bee returned*) buftype:= empty; tim_route : (* delay from timeoutmodule *) case types of 1 : buftype:= clock otherwise unknown_buf(unknown_opcode) end; tim_route1 : (* timeout answer and longtimeout *) case types of 2 : lock mess_ref as buf : timers do if buf.object = vcc_vch_ltime then buftype:= ltime else if buf.object = vcc_vch_stime then buftype:= stime else unknown_buf(rejected) otherwise unknown_buf(unknown_opcode) end; netc_route : (*buffer from vch*) case func of 3 : case types of 0,1,2 : buftype:= alarm (* at --> vcat *) otherwise unknown_buf(unknown_opcode) end; 4 : case types of 1 : buftype:= report (* at --> vcat *) otherwise unknown_buf(unknown_opcode) end; 6 : case types of 2 : return_buf( accepted); (* dc --> dc *) 4 : buftype := permiss (* dc --> vc *) otherwise unknown_buf( unknown_opcode ) end; 8 : case types of 0,2 : buftype:= testat; (* dc --> vcat *) 5 : buftype:= report (* at --> vcat *) otherwise unknown_buf(unknown_opcode) end; 9 : case types of 0 : buftype:= operate otherwise unknown_buf(unknown_opcode) end; 10 : case types of 2,4 : buftype:= table otherwise unknown_buf(unknown_opcode) end; 11 : case types of 2,4,6,8,10,12,14 : buftype:= service otherwise unknown_buf(unknown_opcode) end; 12 : case types of 5 : buftype:= listen otherwise unknown_buf(unknown_opcode) end otherwise unknown_buf(unknown_opcode) end; lam_route : (* buffer from lamdriver *) buftype:= lam otherwise unknown_buf(unknown_route) end; \f (* make action *) action:= acttable(vcatc_state,buftype); (*q if test then begin testout(zout," buftype : ",ord(buftype)); testout(zout," action : ",action); end; q*) case action of 1 : (* no action, has been taken *); 2 : (* not ready *) return_buf(module_not_ready); 3 : (* passive , alarm/report/testat received *) if cur_vcm <> zero_addr then (* send to current vcm *) lock mess_ref as buf: alarmlabel do buf.rec:= cur_vcm else return_buf(module_passive); 4 : (* save listenbuf *) save_listen_buf; 5 : (* update table *) begin case types of 2 : (* at_addr *) lock mess_ref as buf : mask_atadr do with buf do if fix.update = remove_code then begin (* delete *) if get_adr_code(entry.at_addr,adr_code) then begin (* found *) atadrtable(next):= atadrtable(noatadr); noatadr:= noatadr - 1; fix.result:= accepted; end else begin (* not found *) fix.result:= not_found; end; end else if fix.update = insert_code then begin (* insert *) if noatadr < at_addr_l then begin (* ok *) noatadr:= noatadr + 1; (*q if test then testout(zout," noatadr : ",noatadr); q*) atadrtable(noatadr):= entry; fix.result:= accepted; end else begin (* no room *) fix.result:= no_room; end; end else fix.result:= update_error; 4 : (* at-ts *) lock mess_ref as buf: mask_atts do with buf do if fix.update = remove_code then begin (* delete *) if get_atts_index(entry.ts_addr,intg_aux) then begin (* found *) attstable(next):= attstable(noatts); noatts:= noatts-1; fix.result:= accepted; end else begin (* not found *) fix.result:= not_found; end end else if fix.update = insert_code then begin (* insert *) if noatts < at_ts_l then begin (* ok *) noatts:= noatts+1; attstable(noatts):= entry; fix.result:= accepted; end else begin (* no room *) fix.result:= no_room; end; end else fix.result:= update_error; otherwise (* nothing *) end; end; 6 : (* save received buffer *) begin case buftype of clock : begin clock_ref:=: mess_ref; while get_listen_buf do return(mess_ref) end; ltime, stime : timeout_ref :=: mess_ref; lam : begin mess_ref^.u1:= write_read_at; tolam_ref :=: mess_ref; if vcatc_state=not_ready then begin (* book(vcc_vch_ltime); *) vcatc_state:= passive (* <--------<< *) end end otherwise (* nothing *) end; buftype:= used end; 7 : (* service on variable limit and counters *) begin lock mess_ref as buf: alarmlabel do buf.result:= accepted; case types of 2 : (* read line error count *) lock mess_ref as buf: mask_service do with buf do begin fix.no_of_by:= label_size + 2; case fix.update of read_code : data:= line_error_count; insert_code: line_error_count:= data otherwise fix.result:= update_error end end; 4 : (* read pack counter *) lock mess_ref as buf: mask_service do with buf do begin fix.no_of_by:= label_size + 2; case fix.update of read_code : data:= pack_counter otherwise fix.result:= update_error end end; 6 : (* update service limit *) lock mess_ref as buf: mask_service do with buf do begin fix.no_of_by:= label_size + 2; case fix.update of read_code : data:= serve_limit; insert_code : serve_limit:= data otherwise fix.result:= update_error end end; 8 : (* read current vcm *) lock mess_ref as buf: mask_vcm do with buf do begin fix.no_of_by:= label_size + 4; case fix.update of read_code : data:= cur_vcm otherwise fix.result:= update_error end end; 10 : (* update stoppoll limit *) lock mess_ref as buf: mask_service do with buf do begin fix.no_of_by:= label_size + 2; case fix.update of read_code : data:= stoppoll_limit; insert_code : stoppoll_limit:= data otherwise fix.result:= update_error end end; 12 : (* update max succ errors *) lock mess_ref as buf: mask_service do with buf do begin fix.no_of_by:= label_size + 2; case fix.update of read_code : data:= max_succ_errors; insert_code : max_succ_errors:= data otherwise fix.result:= update_error end end; 14 : (* intern tests *) lock mess_ref as buf: mask_test do with buf do case fix.update of 0 : (* test off *) test:= false; 1 : (* test on *) test:= true; 2 : (* lamtest off *) lamtest := false; 3 : (* lamtest on *) lamtest := true; 4 : (* get variable *) begin fix.no_of_by:= label_size + 10; data(1):= no_of_listen; data(2):= no_of_returned; data(3):= no_of_released; data(4):= no_of_unknown; data(5):= no_of_queue; end; 5 : (* get states *) begin fix.no_of_by:= label_size + 10; data(1):= ord(vcatc_state); data(2):= ord(old_state); data(3):= ord(lamspeak_state); data(4):= ord(input); data(5):= poll_delay mod 256; end; otherwise fix.result:= update_error; end; otherwise (* nothing *) end end; 8 : (* call lamspeak *) begin found:= true; case buftype of report, alarm : lock mess_ref as buf: alarmlabel do begin found:= get_adr_code(buf.send,adr_code); if found then buf.op_code:= adr_code end; permiss: lock mess_ref as buf: mask_vcm do begin found:= get_adr_code(buf.data,adr_code); if found then buf.fix.op_code:= adr_code else buf.fix.result:= not_found end; clock : restart_clock; otherwise (* nothing *) end; if found then begin vcatc_state:= lam_talk; (* <--------<< *) lamspeak end else if buftype<>permiss then unknown_buf(sender_error) end; 9 : (* save mess_ref *) begin signal(mess_ref,queuesem.s^); no_of_queue:= no_of_queue + 1; buftype:= used end; 10 : (* restart clock *) restart_clock; 11 : (* long timeout *) begin timeout_ref :=: mess_ref; buftype:= used; old_state:= vcatc_state; if get_listen_buf then begin (* listenbuf found *) mess_ref^.u2:= 0; (* empty databuffer *) book(vcc_vch_stime); vcatc_state:= wait_shorttime; (* <--------<< *) end else begin (* listenbuf not found *) vcatc_state:= vcatc_need_buf; (* <--------<< *) end end; 12 : (* book longtime *) begin timeout_ref :=: mess_ref; book(vcc_vch_ltime) end; 13 : (* listenbuf ready to vcatc *) begin mess_ref^.u2:= 0; (* empty databuffer *) book(vcc_vch_stime); vcatc_state:= wait_shorttime (* <--------<< *) end; 14 : (* modul error *) (* temporary solution *) begin timeout_ref :=: mess_ref; testout(zout,"timeout vch ",ord(vcatc_state)); vcatc_state := passive; book(vcc_vch_ltime) end; 15 : (* dc or vc operations *) case types of 0 : (* order to start or stop polling *) lock mess_ref as buf: mask_poll do with buf do case fix.update of stop_code : (* stop poll *) if vcatc_state <> passive then begin area_pointer := 1; lamspeak_state := nottele; (* lamspeak is initialized *) vcatc_state:= passive; (* <--------<< *) fix.result:= accepted; end else fix.result:= rejected; start_code : (* start poll *) if (vcatc_state=passive) and (not nil(tolam_ref)) and (not nil(clock_ref)) then begin vcatc_state:= active; (* <--------<< *) poll_delay:= poll_rate; lock clock_ref as cbuf: timers do cbuf.object:= poll_delay; signal(clock_ref,timeoutsem^); (* start clock timeout *) fix.result:= accepted; line_error_count:= error_count; end else fix.result:= rejected; otherwise fix.result:= update_error; end; 2 : (* at-vc control *) begin lock mess_ref as buf: mask_atvcdc do with buf do begin buftype:= alarm; if fix.send = at then begin fix.send:= fix.rec; fix.rec := dc; fix.result:= accepted; end else if fix.send = dc then begin fix.send:= fix.rec; fix.rec := at; fix.result:= accepted; end else buftype := unknown; end; if buftype = unknown then unknown_buf( sender_error); end otherwise (* nothing *) end; 16 : (* one listenbuf arrived before shorttimeout *) begin save_listen_buf; input:= from_listen_ref; vcatc_state:= old_state (* <--------<< *) end; 17 : (* lambuf arrived before lamspeak ready *) fromlam_ref :=: mess_ref; 18 : (* return buffer to pool *) begin return(mess_ref); no_of_returned:= (no_of_returned mod max_int) + 1; buftype:= used; end; 19 : (* lam need buf *) begin restart_clock; if no_of_listen>0 then input:= from_listen_ref else if no_of_queue>5 then begin wait(mess_ref,queuesem.w^); no_of_queue:= no_of_queue - 1; unknown_buf(pool_empty) end end otherwise unknown_buf(rejected) end (* case *); \f (* send buffer *) (*q if test then testout(zout,"buftype out:",ord(buftype)); q*) case buftype of operate, table , service, permiss: begin (* receipt in current buffer , back to sender *) mess_ref^.u3:= vca_route; mess_ref^.u4:= mess_ref^.u4 + 1; lock mess_ref as buf: alarmlabel do begin buf.rec:= buf.send; buf.send.micro:= micadr; end; send_to_vch end; unknown: begin (* send buffer to own dc or sender *) mess_ref^.u3:= vca_route; send_to_vch end; listen: begin (* new listenbuffer are used *) mess_ref^.u3:= vca_route1; (* request listenbuffer *) lock mess_ref as buf: alarmlabel do buf.send.micro:= micadr; send_to_vch end; report, testat, alarm: begin (* send to other receiver *) mess_ref^.u3:= vca_route; send_to_vch end; empty: begin (* buffer is empty, release to pool *) mess_ref^.u2:= 0; mess_ref^.u3:= vca_route; if no_of_listen<2 then save_listen_buf else return(mess_ref) end otherwise (* nothing *) end (* send buffer *); if input <> nothing then if not nil(mess_ref) then begin (* needless buffer , possible program error *) (*q if test then testout(zout,"released : ",mess_ref^.u4); q*) no_of_released:= (no_of_released mod max_int) + 1; return(mess_ref); end; until false; end. «eof»