{
{ This module contains some procedure used by camac_in and must be 
{ included in camac_in after the declaration of the general variables 
{			Version 0.1 
{			Author       G.Sanzani 14/5/87 Bologna
{ 
{			F Ronga sept 1989
{			added some instructions
{}
procedure skip_blank (	stringa    : varying_string (80);
		 	var first_part : varying_string (80);
        		var rest_part  : varying_string (80);
                        var end_string : [optional] boolean);
{
{ This procedure is called by the fill_camac_list and other procedures.
{ It divides a string (stringa) in two parts :
{ a) the first one (first_part) contains a part of the original string 
{    until a blank
{ b) the second one contains(rest_part)  the part of the string from the 
{    character after the blank to the end of the string.
{  Is not possible to give as 'stringa' and 'first_part' the same variable
{  Is possible to give as 'stringa' and 'rest_part' the same variable
{}
var
	posblank  : integer;
        poschar   : integer
begin
        if present(end_string) then end_string:=FALSE;
	poschar := find_member (stringa,['A'..'Z','a'..'z','$',
   {search the first char}    '0','1','2','3','4','5','6','7','8','9']);
        stringa := substr (stringa,poschar);
	posblank := find_member ( stringa,[' ']);
        if (posblank=0) then 
         begin
          first_part := stringa {end string};
          if present(end_string) then end_string:=TRUE;
         end
         else 
         begin
	  first_part := substr( stringa,1,posblank-1);
          rest_part := substr(stringa,posblank+1);
          poschar := find_member (stringa,['A'..'Z','a'..'z','$',
		                '0','1','2','3','4','5','6','7','8','9']);
          rest_part := substr (rest_part,poschar);
         end;
end;
{}

{----------------------------------------------------------------------}

procedure skip_comma   ( stringa    : varying_string (80);
		 	var first_part : varying_string (80);
        		var rest_part  : varying_string (80);
                        var end_string : [optional] boolean);
{
{
{ This procedure is called by the fill_camac_list and other procedures.
{ It divides a string (stringa) in two parts :
{ a) the first one (first_part) contains a part of the original string 
{    until a comma
{ b) the second one contains(rest_part)  the part of the string from the 
{    character after the comma to the end of the string.
{  An optional variable (end_string) is set true when  no comma is found
{  inside the string. Is useful for decoding a string the contains
{  many variable s separatede by commas to signal the end of the string.
{  Is not possible to give as 'stringa' and 'first_part' the same variable
{  Is possible to give as 'stringa' and 'rest_part' the same variable
{}
var
	poscomma  : integer;
        poschar : integer;
begin
        if present(end_string) then end_string:=FALSE;
	poschar := find_member (stringa,['A'..'Z','a'..'z','$',
		                '0','1','2','3','4','5','6','7','8','9']);
        stringa := substr (stringa,poschar);
	poscomma := find_member ( stringa,[',']);
        if (poscomma=0) then {no comma found,i have reached the end ?}
         begin
          if present(end_string) then end_string:=TRUE;
          first_part := substr( stringa,poschar);
         end
        else
         begin
	  first_part := substr( stringa,poschar,poscomma-1);
          rest_part := substr(stringa,poscomma+1);
	  poschar := find_member (stringa,['A'..'Z','a'..'z','$',
	 	                '0','1','2','3','4','5','6','7','8','9']);
          rest_part := substr (rest_part,poschar);
        end; 
end;

{-----------------------------------------------------------------}

procedure fill_nil;

{ This procedure is called by the main process of the job Camac_in when it
{ starts to clear all the pointer used by the acquisition process
{}
var
	i,ii:integer;
begin

        for i:=1 to 255 do begin
         for ii:=1 to 255 do begin
          select_matrix[i,ii]:=nil;
         end;   
         trigger_array[i] :=nil;
         pointer_array[i] :=nil;
        end;
        pointer_for_init:=nil;
end;

{------------------------------------------------------------------}
procedure interrupt_enable(irq_num : integer);

{ This procedure unmask the 8210 ext int
{}

var 	csrreg: ces8210_csr;
	camadd : camac_addr;

begin	
	camadd.full:=0;
	camadd.b:=int_branch;
	camadd.c:=0;
	camadd.n:=29;
	camadd.a:=0;
	camadd.f:=4;

{ IFR register}
	eln$camac_short_write(camadd,0); {clear pending int}

	camadd.f:=0;
{ CSR Register}
	eln$camac_short_read(camadd,csrreg.full); {read csr}

	if (irq_num=2) then
	    csrreg.ext_int_2:=0
	else
	    csrreg.ext_int_4:=0;
    	
	eln$camac_short_write(camadd,csrreg.full); {clear ext int mask}
	
end;
	
{------------------------------------------------------------------}
procedure interrupt_disable(irq_num :integer);

{ This procedure mask the 8210 ext int
{}

var 	csrreg: ces8210_csr;
	camadd : camac_addr;

begin	
	camadd.full:=0;
	camadd.b:=int_branch;
	camadd.c:=0;
	camadd.n:=29;
	camadd.a:=0;
	camadd.f:=0;

{ CSR Register}
	eln$camac_short_read(camadd,csrreg.full); {read csr}

	if (irq_num=2) then
	    csrreg.ext_int_2:=1
	else
	    csrreg.ext_int_4:=1;
    	
	eln$camac_short_write(camadd,csrreg.full); {set ext int mask}

	camadd.f:=4;
{ IFR register}
	eln$camac_short_write(camadd,0); {clear pending int}
end;

{------------------------------------------------------------------}


procedure freememory (point_to_mem:^camac_list);

{ This procedure frees the memory allocated for the camac_list and is
{ called each time the camac_list is loaded (by mean of the command
{ init). In input requires the pointer to the first element of a list.
{ It executes the statement 'dispose' until a nil pointer is reached.
{}

var
	nextfree_point,free_point : ^camac_list ;
begin
	free_point := point_to_mem;
	while (free_point<>nil) do begin
         nextfree_point:=free_point^.next_elem;
	 dispose(free_point);
         free_point := nextfree_point;
	end;
end;
{-----------------------------------------------------------------------}

procedure fill_list(b:camac_B;c:camac_C;n:camac_N;a:camac_A;f:camac_F;
		    length24:boolean;q_oper:boolean;cam_data:word24);

{ This procedure fills a block of the camac_list.
{  It requires in input the camac b,c,n,a,f and data in word24 (integer
{ with max value = 2**(24-1)
{ This procedure,also,allocates the memory space for another block of 
{ the list (new(p)) and loads  the pointer to the new block in a 
{ word of the old one.
{}
begin
{}
	  p^.cam_add.full:=0;

          p^.cam_add.b:=b;
          p^.cam_add.c:=c;
	  p^.cam_add.n:=n;
	  p^.cam_add.a:=a;
	  p^.cam_add.f:=f;       {load address}

	  if (length24 = FALSE)  then
		p^.cam_add.opl:=1;

{ Set Q test option }
          p^.qtest:=q_oper;
	  
          csr_add.b:=b;
	  p^.stat_add::integer := base_ptr::integer+csr_Add::integer; 
{ Add map offset}

	  p^.mem_add::integer:=base_ptr::integer+p^.cam_add.full;
	
          p^.data_to_write.full:=cam_data;
	  previus := p;
	  new (p); 			{space for a new element }
	  previus^.next_elem := p;     {load the pointer to the new block}
end;                                   {in the previus one} 

{------------------------------------------------------------------}

procedure decode_bcnaf (input_str : varying_string(80);
	  	          var B:camac_B;
	  	          var C:camac_C;
	  	          var N:camac_N;
	  	          var A:camac_A;
	  	          var F:camac_F;
		          var cam_data  :word24;
                          var rpt : [optional] word16);
{ This procedure decode a string of the camac_list and gives the camac
{ b,c,n,a,f . Data is always given in word24 (two words). Only one is used
{ for 16 bits operations.
{}
var
	end_str:boolean;
        local_str : varying_string(80);
	idigit : array [1..6] of integer ;
	ilen,ipot,j,k : integer ;
        chnum : string(1); 
{}
begin
             cam_data:=0;{la pongo sempre a zero}
	     if present(rpt) then 
			rpt:=0;	
             skip_comma (input_str,local_str,input_str);
             B:=convert(camac_B,local_str);
             skip_comma (input_str,local_str,input_str);
	     C:=convert(camac_C,local_str);
             skip_comma (input_str,local_str,input_str);
	     N := convert (camac_N,local_str);{converto la station}
             skip_comma (input_str,local_str,input_str);
             A :=convert (camac_A,local_str);{converto il subadd.}
             skip_comma (input_str,local_str,input_str,end_str);
	     F :=convert (camac_F,local_str);{converto la function}
             if not end_str then 
              begin
               skip_comma (input_str,local_str,input_str,end_str);
	       if substr(local_str,1,1)='$'  then  {hexadecimal input}
                begin
	         ilen := length(local_str) ;
                 ilen:=ilen-1;
	         local_str:=substr(local_str,2,ilen);
  	         for k := 1 to 6 do
	          begin
	           idigit[k] := 0
	          end ;
	         for k := 1 to ilen do
	          begin
	           chnum := substr(local_str,k,1) ;
	           j := ilen+1-k ;
	           idigit [j] := ord(chnum)-48 ;
	           if idigit[j] >16 then idigit[j] := idigit[j]-7 ;
	          end ;
	          ipot := 1 ;  
	          cam_data := idigit [1] ;
	          for j := 2 to 6 do
	          begin
	           cam_data := cam_data + (ipot*16)*idigit[j] ;
	           ipot := ipot*16 ;
	          end ;
                end
               else  cam_data:=convert(word24,local_str);
             end ;
             if not end_str then
              begin
               if present(rpt) then
                begin
                 skip_comma (input_str,local_str,input_str);
                 rpt:=convert(word16,local_str);
                end;
               end;
end;


{------------------------------------------------------------------}

procedure hextoint(var local_str : varying_string(80);
		   var int_data : integer);

{ Conversion hex to integer
  input : hex string starting with '$' char 
  output : integer 
}

var	idigit : array [1..8] of integer ;
	ilen,ipot,j,k : integer ;
        chnum : string(1); 

begin
	         ilen := length(local_str) ;
                 ilen:=ilen-1;
	         local_str:=substr(local_str,2,ilen);
  	         for k := 1 to 8 do
	          begin
	           idigit[k] := 0
	          end ;
	         for k := 1 to ilen do
	          begin
	           chnum := substr(local_str,k,1) ;
	           j := ilen+1-k ;
	           idigit [j] := ord(chnum)-48 ;
	           if idigit[j] >16 then idigit[j] := idigit[j]-7 ;
	          end ;
	          ipot := 1 ;  
	          int_data := idigit [1] ;
	          for j := 2 to 8 do
	          begin
	           int_data := int_data + (ipot*16)*idigit[j] ;
	           ipot := ipot*16 ;
	          end ;
end ;


{------------------------------------------------------------------}
procedure decode_vic_comm (input_str : varying_string(80);
	  	           var B  : camac_B;
	  	           var C  : camac_C;
		           var page : integer;
                           var vme_off : integer;
                           var nwords : integer);

{ This procedure decode a string of the camac_list for vic operation 
{}
var
	end_str:boolean;
        local_str : varying_string(80);
	idigit : array [1..6] of integer ;
	ilen,ipot,j,k : integer ;
        chnum : string(1); 
	ext_vme_add :integer;
{}
begin
             skip_comma (input_str,local_str,input_str);
             B:=convert(camac_B,local_str);
             skip_comma (input_str,local_str,input_str);
	     C:=convert(camac_C,local_str);
             skip_comma (input_str,local_str,input_str,end_str);
	     hextoint(local_str,ext_vme_add);
             page := ext_vme_add DIV %x100000;	     
             vme_off := ext_vme_add MOD %x100000;	     
             if not end_str then
	       begin
                 skip_comma (input_str,local_str,input_str);
  		 if substr(local_str,1,1)='$'  then  {hexadecimal input}
	             hextoint(local_str,nwords)
                 else
                     nwords:=convert(integer,local_str);
               end
	    else nwords:=1;
end;

{------------------------------------------------------------------}

procedure decode_i1i2 (input_str : varying_string(80);
	  	          var B:integer2;
	  	          var C:integer2);
{ This procedure decode a string of the camac_list and gives two integers
{ adapted from decode_bcna by F Ronga
{}
var
        local_str : varying_string(80);
{}
begin
             skip_comma (input_str,local_str,input_str);
             B:=convert(camac_B,local_str);
             skip_comma (input_str,local_str,input_str);
	     C:=convert(camac_C,local_str);
end;

{------------------------------------------------------------------}

procedure decode_i1i2i3 (input_str : varying_string(80);
	  	          var B:integer;
	  	          var C:integer;
                          var D:integer);
{ This procedure decodes a string of the camac_list and gives three integers
{ adapted from decode_i1i2 by E Kearns
{}
var
        local_str : varying_string(80);
{}
begin
             skip_comma (input_str,local_str,input_str);
             B:=convert(integer,local_str);
             skip_comma (input_str,local_str,input_str);
	     C:=convert(integer,local_str);
             skip_comma (input_str,local_str,input_str);
	     D:=convert(integer,local_str);
end;

{------------------------------------------------------------------}

procedure decode_i1i2i3i4 (input_str : varying_string(80);
	  	          var B:integer;
	  	          var C:integer;
                          var D:integer;
                          var E:integer);
{ This procedure decodes a string of the camac_list and gives three integers
{ adapted from decode_i1i2i3 by E Kearns
{}
var
        local_str : varying_string(80);
{}
begin
             skip_comma (input_str,local_str,input_str);
             B:=convert(integer,local_str);
             skip_comma (input_str,local_str,input_str);
	     C:=convert(integer,local_str);
             skip_comma (input_str,local_str,input_str);
	     D:=convert(integer,local_str);
             skip_comma (input_str,local_str,input_str);
	     E:=convert(integer,local_str);
end;

{------------------------------------------------------------------}

procedure fill_amc_list (qmode:word24;
                         long_operation : boolean;                              
 			var iover:[optional]byte);
{}
{ This procedure fills some blocks of camac_list ,as many as it's need,
{ for executing an amc operation.
{ It also loads the amc reset operation in the comunication region with
{ the isr for the lam clear.
{ It requires in input a variable giving the mode of operation of the amc,
{ a boolean variable set if 24bits operation it's need, and a byte variable,
{ used as a flag and read from the camac_list, that gives the mode of 
{ operation when in qscan (see manual).
{}
var
	br : camac_B;
	cr : camac_C;
	sn : camac_N;
	na : camac_A;
        fu : camac_F;
	long_data,num_word : word24;

begin
{ load amc reset operation in the comunication region with the isr}
	     decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
	     num_word:=long_data;
{F Ronga nov 1993 temporaneo per problema ultima parola in qstop}
	     if qmode=%X0002 then num_word := num_word+1;
{--- Load CAMP ---------------------------------------------------------}
             p^.mode_operation:=2;
             long_data:=(cr*512)+(sn*16)+na;
             fill_list(br,0,29,1,4,FALSE,FALSE,long_data);

	     if (qmode=%x0006) then	{QSCAN mode}
	     begin
	      	p^.mode_operation:=2;
       	      	long_data:=dma_end_n*16; {set QSCAN end address}
             	fill_list(br,0,29,1,5,FALSE,FALSE,long_data);
	     end;
		
{--- Load VMEGEN -------------------------------------------------------}
             p^.mode_operation:=2;
	     long_data:=%x3E;  {Address modifiers}
             fill_list(br,0,29,1,7,FALSE,FALSE,long_data);

{--- Load WCNT -------------------------------------------------------}
             p^.mode_operation:=3;
             fill_list(br,0,29,1,6,TRUE,FALSE,num_word);

{--- Load CSR1 -------------------------------------------------------}
             p^.mode_operation:=2;
	     long_data:=qmode;

	     if (long_operation) then long_data:=long_data+1;{tras 24}

	     long_data:=long_data+(fu*8); { load F }
	     long_data:=long_data+(1*256); {IRQ 5}
	     long_data:=long_data+(1*1024); {Arbitration}
	     long_data:=long_data+(1*32768); {Arm DMA}

             p^.mode_operation:=2;
             fill_list(br,0,29,1,0,FALSE,FALSE,long_data);



{----------------------- Interrupt management ---------------------}


{--- Reset chip ------------------------------------------------------}
		
	     long_data:=0;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,TRUE,FALSE,long_data);

{--- Set mode bits to comon vector ------------------------------------}
		
	     long_data:=%x82;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,TRUE,FALSE,long_data);


{--- Unmask all IRR bits ----------------------------------------------}
		
	     long_data:=%x20;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,TRUE,FALSE,long_data);

{--- Byte count --------------------------------------------------------}
		
	     long_data:=%xe0;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,TRUE,FALSE,long_data);

{--- Int.Vector --------------------------------------------------------}

		
	     long_data:=%x40;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,FALSE,FALSE,long_data);
	
{--- Arm Int    --------------------------------------------------------}

		
	     long_data:=%xA1;
	     p^.mode_operation:=2;
	     fill_list(br,0,29,1,8,TRUE,FALSE,long_data);
	

{--- Set for ADRP -------------------------------------------------------}
	     p^.mode_operation:=7;
	     if (long_operation) then
		p^.spare:=0   {mark 24 bit transfer} 
	     else 
		p^.spare:=1;   {mark 16 bit transfer}
	     fill_list(br,0,29,1,3,TRUE,FALSE,long_data);

{--- Load CSR2 -------------------------------------------------------}

	     long_data:=%x80;        {start DMA}
             p^.mode_operation:=7;
	     p^.spare:=qmode;
	     fill_list(br,0,29,1,1,FALSE,FALSE,long_data);
end;               
{}

{-------------------------------------------------------------------}

procedure fill_camac_list (filename : varying_string (80));

{}
{	This procedure open the file (filename ) in the vax/vms 
{	tha contains the camac list and reads and decodes the records.
{	For each record one or blocks like the following is filled:
{
{	1 word : 	cam_add  (camac_add) address the operation to execute
{	2 word :	mode_operation (byte) Kind of operation 
{	3 word :	data_to_write (packed record) Data for write operation
{			or used for other parameters
{	4 word :	next_equip (^camac_list) If filled points to the start
{			of the next equipment.
{	5 word :	next_elem (^camac_list) Points to the next element
{			of the list.
{
{	The pointer to the first element of an equipment list is contained in
{	the pointer_array. When the command trig n followed by the list
{       of the equipment (eqp) is received the list of equipment are
{	copied in an unique list (one for trigger).
{	The pointer to the first element of a trigger list is contained
{	in the trigger_array.
{       In case of select register is used a matrix of ^camac_list 
{	(select_matrix) that gives the pointer to the first element
{	of the selected part of an equipment.
{	I.e. select_matrix[1,5] means the in the selecct register 1
{	the bit 5 is set so is executed the associated list.
{	The following numbers gives what operation must be executed
{	(loaded in the mode_operation element of a camac list block
{
{ short_read 		      	0
{ long_read			1
{ short_write			2
{ long_write			3	
{ short_test 			4   
{ long_test			5   	
{ mark end equipment		6   
{ start dma transfer    	7
{  (loading MAR)	
{ short read of a module	8
{ long read of a module  	9
{ read select register   	10
{ read select block      	11
{ start equipment        	12 
{ execute user procedure	13
{ test acc lam			14
{ wait for q response		15
{ short write of a module 
{ (with the same a)             16
{ long write of a module 
{ (with the same a)             17
{ short write of a module 
{ (with different a)            18
{ long write of a module  
{ (with different a)            19
{ load data file                20
{ load unf. data file           21
{
{ added by F Ronga sept 1989
{ short read ignore q           22
{ long  read ignore q           23
{ short read of a module no q   24
{ long read of a module no q    25
{ Q read (last operation)       26
{ Q read for a new operation    27
{ short read stop q=0           28
{ long read stop q=0            29
{ short read qignore            30
{ long read qignore             31
{ short read sqstop             34
{ long read  sqstop             35
{    						
{ The test function (t) executes write operation or read without loading
{ data in memory. 
{}
type
	file_record = varying_string (80);
	list_command_type = (INIT,TRIG,RDTRIG,EQUIP,LAMCLR,LOAD,USER_PROCEDURE,
                             EOE,C,EOI,EOT,F,T,SET16,SET24,QIGNORE,
			     QREPEAT,QSCAN,DMAEND,QSTOP,
			     SELREG,SECT,SELECT,EOS,WAIT_Q,WR_SAME_A,
			     WR_DIFF_A,LOADF,LOOP,ENDL,
			     SETQ,SETNOQ,QREAD,EVSCA,TRMVAX,FQIGNORE,
			     FQSTOP,DEF_SETVETO,VME_RD_EX,VME_RD_ST,VME_WR_EX,
                             WFD_READOUT,WFD_MAP,WFD_PATREG,WFD_THRESH,
                             WFD_RDMEM,WFD_RDTIM,WRITEHEX,
			     SQSTOP,VME_WR_ST,VME16,VME32,DEF_RESVETO);
var 
	fill_camac_stato,i,ii,record_num : integer;
	list_file: file of file_record;
        ifil:file of integer;
        list_command : file_record;
        conv_list_command : list_command_type;
        fill_command:varying_string(80);
	status: integer;
	eof_found : boolean;
        long_operation:boolean;
	vme_long_operation:boolean;
	q_operation:boolean:=true;
        trig_num : byte; 
        equip_num,sect_num,select_num : byte;
        stop_dma,iover:byte;
        repet:word16;
        pointer_to_copy,remember_pointer,start_equip_pointer : ^camac_list;
	br : camac_B;
	cr : camac_C;
	sn : camac_N;
	na,num_add : camac_A;
        fu : camac_F;
	long_data,num_word:word24;
	nwords: integer;
	i1,i2 : integer2;
        tmpint, iwin, ilim, ism, ichan, iend, iinp, ival : integer;
        wfd_sm_base_addr, wfd_ch_base_addr : integer;
        pgd_add : ^VIC_pgd;

{---------------------- VIC variable declaration -------------------}


	vme_b : camac_B;
	vme_c : camac_C;
	vme_add : integer;
	vme_page : integer;
	pgd : VIC_pgd;
	map_found : boolean ;
	pg_add : ^integer;
	found_pgd : VIC_pgd;
	virtual_base_add : ^word32;
	istat, entry : integer;
	pgdnum,pgindex:integer;
	vme_data : integer;
{-------------- Surdo:}
        ipg,iipg : integer;
{-----------------------------}

function fill_exception of type exception_handler;
{exception if an error occurs}
var
	list_error_string: varying_string(255);
begin
          eln$get_status_text (signal_args.name,[],list_error_string);
          writeln (list_error_string) ;
          if ( signal_args.name=error_on_list) then begin
                   writeln ('Received : ',list_command);
                   writeln (' Received ',fill_command,' while in status ',
                   fill_camac_stato:3,' record num. ',record_num);
          end;
          if ( signal_args.name=BCoffline) then begin
                   writeln ('Received : ',list_command);
                   writeln (' Branch or Crate OFFLINE ');
          end;
	   list_error:=true;
           fill_exception:=true;
           if (fill_camac_stato>1) then p^.next_elem:=nil;  
           goto end_proc
end;	
{}

procedure pr_qstop;
begin
 	        fill_amc_list(%x0002,long_operation){qstop oper}
end;

procedure pr_dmaend;
begin
	     dma_end_n := convert(camac_N,scratch_string);{conversion of the crate num.}
end

procedure pr_qscan;
begin
 	      fill_amc_list(%x0006,long_operation,iover);{qscan oper}
end;

procedure pr_qrepeat;
begin
 	     fill_amc_list(%x0004,long_operation);
end;

procedure pr_qignore;
begin
             fill_amc_list(%x0000,long_operation);
end;

procedure pr_user_procedure;
begin
	         p^.data_to_write.low 
                                 := convert(word16,scratch_string);{proc. number}
	      	 p^.mode_operation :=13;
	      	 previus:=p;
	      	 new(p); {space for the next element}
	     	 previus^.next_elem:=p;
end;

procedure pr_vme_ex;

var i:integer;

begin
              
	      pgd.crate:=vme_c;
	      pgd.amcode:= VIC_EX_CODE;
              pgd.addr:= vme_page;
	      pgd.ok := 1;
              pgd.swap:=0;
	      map_found:=FALSE;
	      for i:=1 to npg_mapped[vme_b] do
               begin
{ page descr add = virtual base address+ MMU address + page address}

		pgdnum:=%x1000+vme_b*%x10+(i-1);

		pgd_add::integer := vic_base_add[vme_b]::integer+%x20000+
					pgdnum*4;		
		found_pgd:=pgd_add^;
       found_pgd.dont_care := 0;   {! Error/Status byte reset ! A.SURDO !!!!}
		if(found_pgd.full=pgd.full) then
		 begin
			map_found:=TRUE;		
			virtual_base_add:=
                                  saved_virt_base_add[(vme_b-1)*%x10+i];
                 end;            
	       end;
	      if(not(map_found)) then
               begin 

		pgdnum:=%x1000+vme_b*%x10+(npg_mapped[vme_b]);

		pgd_add::integer := vic_base_add[vme_b]::integer+%x20000+
					pgdnum*4;		

		pgd_add^:=pgd;
                kav$out_map(status:=istat,
			   entry:=entry,
			   page_count:=16,
                           bus_address:=vme_b*%x1000000 
					+npg_mapped[vme_b]*%x100000,
			   virtual_address:=virtual_base_add,
		           am_code:=kav$k_user_32,
                           map_functions := kav$m_vme+kav$m_mode_3_swap);

                 if not odd(istat) then                               
                        begin                                         
                          lock_mutex(write_mutex);                    
                          writeln(' VIC map  error during camaclist',
					hex(istat));      
                          unlock_mutex(write_mutex);                  
                       end;                                           

		pgindex:=(vme_b-1)*%x10+(npg_mapped[vme_b]+1);
		saved_virt_base_add[pgindex]:=virtual_base_add;            
                npg_mapped[vme_b]:=npg_mapped[vme_b]+1;

{ Modified to allow access to variables by ELN_VMS_SERVER.    A.Surdo }
                lock_area(save_vic_data,vic_data_p^.lock_vic);
                 vic_data_p^.npg_maps[vme_b] := npg_mapped[vme_b];
                 vic_data_p^.vic_adds[pgindex] := virtual_base_add;
                unlock_area(save_vic_data,vic_data_p^.lock_vic);

	       end;
end;


procedure pr_vme_st;

var i:integer;

begin

	      vme_b:=1;
	      pgd.crate:=vme_c;
	      pgd.amcode:= VIC_ST_CODE;
              pgd.addr:= vme_page;
	      pgd.ok := 1;
              pgd.swap:=0;
	      map_found:=FALSE;
	      for i:=1 to npg_mapped_st do
               begin
{ page descr add = virtual base address+ MMU address + page address}

		pgdnum:=%x1FF0+%xB+(i-1);

		pgd_add::integer := vic_base_add[vme_b]::integer+%x20000+
					pgdnum*4;		
		found_pgd:=pgd_add^;
       found_pgd.dont_care := 0;   {! Error/Status byte reset ! A.SURDO !!!!}
		if(found_pgd.full=pgd.full) then
		 begin
			map_found:=TRUE;		
			virtual_base_add:=
                                  saved_virt_base_add_st[i];
                 end;            
	       end;
	      if(not(map_found)) then
               begin 

		pgdnum:=%x1FF0+vme_b*%xB+npg_mapped_st;

		pgd_add::integer := vic_base_add[vme_b]::integer+%x20000+
					pgdnum*4;		

		pgd_add^:=pgd;
                kav$out_map(status:=istat,
			   entry:=entry,
			   page_count:=16,
                           bus_address:=%xB00000 
					+npg_mapped_st*%x100000,
			   virtual_address:=virtual_base_add,
		           am_code:=kav$k_user_24,
                           map_functions := kav$m_vme+kav$m_mode_2_swap);

                 if not odd(istat) then                               
                        begin                                         
                          lock_mutex(write_mutex);                    
                          writeln(' VIC standard map  error during camaclist',
					hex(istat));      
                          unlock_mutex(write_mutex);                  
                       end;                                           

		pgindex:=npg_mapped_st+1;
		saved_virt_base_add_st[pgindex]:=virtual_base_add;            
                if(npg_mapped_st <= 5) then
			npg_mapped_st:=npg_mapped_st+1;

{ Modified to allow access to variables by ELN_VMS_SERVER.    A.Surdo }
                lock_area(save_vic_data,vic_data_p^.lock_vic);
                 vic_data_p^.npg_map_st := npg_mapped_st;
                 vic_data_p^.vic_add_st[npg_mapped_st] := virtual_base_add;
                unlock_area(save_vic_data,vic_data_p^.lock_vic);

	       end;
end;


procedure pr_vme_st_master;

var i:integer;

begin

	      if ((vme_page <5 ) or (vme_page >7)) then 
	       begin
                lock_mutex(write_mutex);                    
                writeln(' VIC master map  error: ADDRESS NOT AVAILABLE');
                unlock_mutex(write_mutex);                  
               end
	      else
               begin		
	        if (master_virt_base_add_st[vme_page-4]::integer<>0) then
                 begin
		  virtual_base_add:= master_virt_base_add_st[vme_page-4];
                 end
		else
                 begin
                  kav$out_map(status:=istat,
			   entry:=entry,
			   page_count:=16,
                           bus_address:=vme_page*%x100000,
			   virtual_address:=virtual_base_add,
		           am_code:=kav$k_user_24,
                           map_functions := kav$m_vme+kav$m_mode_2_swap);

                  if not odd(istat) then                               
                        begin                                         
                          lock_mutex(write_mutex);                    
                          writeln(' VIC master standard map  error during camaclist',
					hex(istat));      
                          unlock_mutex(write_mutex);                  
                       end;                                           

		  master_virt_base_add_st[vme_page-4]:=virtual_base_add;            

{ Modified to allow access to variables by ELN_VMS_SERVER.    A.Surdo }
                  lock_area(save_vic_data,vic_data_p^.lock_vic);
                   vic_data_p^.mast_adds[vme_page-4] := virtual_base_add;
                  unlock_area(save_vic_data,vic_data_p^.lock_vic);

 	        end;
	     end;
end;

{------- Start of fill_camac_list body --------------------------------}

begin
        establish(fill_exception);
	
{----------------------------------------------------- Surdo }
      lock_area(save_vic_data,vic_data_p^.lock_vic);
       for i := 1 to 3 do begin
         npg_mapped[i] := vic_data_p^.npg_maps[i];
         for ipg := 1 to npg_mapped[i] do begin
           iipg:=(i-1)*%x10 + ipg;
           saved_virt_base_add[iipg] := vic_data_p^.vic_adds[iipg];
         end;
       end;
       npg_mapped_st := vic_data_p^.npg_map_st;
       for ipg := 1 to npg_mapped_st do
         saved_virt_base_add_st[ipg] := vic_data_p^.vic_add_st[ipg];
       for i := 1 to 3 do
         master_virt_base_add_st[i] := vic_data_p^.mast_adds[i];
      unlock_area(save_vic_data,vic_data_p^.lock_vic);

{------------------------------------------------------------}

	fill_camac_stato:=1; {procedure status}
        long_operation:= FALSE;
        vme_long_operation:= FALSE;
	q_operation:=true;
	eof_found:=FALSE;
        for i:=1 to 255 do begin {dispose of memory}
         for ii:=1 to 255 do begin
          freememory (select_matrix[i,ii]);
          select_matrix[i,ii] :=nil;
         end; 
         freememory (trigger_array[i]);
         trigger_array[i] :=nil;
         freememory (pointer_array[i]);
         pointer_array[i] :=nil;
        end;
        freememory (pointer_for_init);
        pointer_for_init:=nil ;
	previus := nil;
	select_num:=0;
        record_num:=0;
	veto_present := FALSE;

	
{}

	open(list_file,
	     file_name := filename,
	     history := history$readonly);
	reset(list_file);
       writeln (' ');
       writeln ('...Reading List : ',filename);
	repeat
	 if not eof(list_file) then 
          begin
	   read(list_file,list_command);
           record_num:=record_num+1; 
{A.S.(22/6/94)           writeln ('Received : ',list_command); }
	   skip_blank (list_command,fill_command,scratch_string);
           conv_list_command := convert (list_command_type,fill_command);
           case fill_camac_stato of          

{-------------------------------------------------------------------}
1:  	  begin 
           case conv_list_command of
{}           


RDTRIG:     begin
             	decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);

       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
    		trigger_add.b := br;
		trigger_add.c := cr;
		trigger_add.n := sn;
		trigger_add.a := na;
		trigger_add.f := fu;
	    
 	    end;

DEF_SETVETO:   begin
             	decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);

       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
    		setveto.veto_add.b := br;
		setveto.veto_add.c := cr;
		setveto.veto_add.n := sn;
		setveto.veto_add.a := na;
		setveto.veto_add.f := fu;
                if (fu = 16) then
		begin
			setveto.data.full:=long_data;  
			setveto.testop:=FALSE;
		end
		else
			setveto.testop:=TRUE;

		veto_present := TRUE;
	      end;

DEF_RESVETO: begin
             	decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
    		resveto.veto_add.b := br;
		resveto.veto_add.c := cr;
		resveto.veto_add.n := sn;
		resveto.veto_add.a := na;
		resveto.veto_add.f := fu;
                if (fu = 16) then
		begin
			resveto.data.full:=long_data;  
			resveto.testop:=FALSE;
		end
		else
			resveto.testop:=TRUE;

		veto_present := TRUE;
 	   end;

EVSCA:     begin  {define register for event number (if any)}
	     ev_da_scala := true;
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
    	     event_add.b := br;
	     event_add.c := cr;
	     event_add.n := sn;
             event_add.a := na;
	     event_add.f := fu;
            end;

TRMVAX:     begin {define trigger list (if any)};
            decode_i1i2(scratch_string,i1,i2);
	    TR_LIST[i1].full := i2;	    
            end;

C:          begin
             {only comments}
            end; 

EQUIP:	    begin
	     equip_num := convert(byte,scratch_string);{equip. num}
	     new (p); {apro una nuova tabella di indirizzi camac}
	     p^.data_to_write.low:=equip_num;
	     p^.mode_operation:=12; 
	     pointer_array [equip_num]:=p; {load the pointer in the array}
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;
             fill_camac_stato:=2;
	    end;

INIT:       begin
	     new (p); {new camac_list block}
	     pointer_for_init:=p; {memorize for init execution}
	     p^.data_to_write.low:=999; {init equip number}
	     p^.mode_operation:=99;
	     p^.next_equip:=NIL;
	     previus:=p;
	     new(p);
	     previus^.next_elem:=p;
	     fill_camac_stato:=3;
	    end;

TRIG:	    begin
	     trig_num := convert (byte,scratch_string);{trigger num.}
	     new(p);  {new block}
             trigger_array[trig_num]:=p; { load the pointer to the list}
             fill_camac_stato:=4; 
            end;
            
            otherwise raise_exception (error_on_list);
            end; {of case stato 1}
           end; {of stato 1}

{--------------------------------------------------------------------------}

2:	  begin
	   case conv_list_command of

T:	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (long_operation) then p^.mode_operation:=5 
	       else p^.mode_operation:=4;
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;

F:  	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (fu>15) and (fu<24) then {write function}
              begin 
	       if (long_operation) then p^.mode_operation:=3
                  else p^.mode_operation:=2;                       
              end
	     else {read function}
              begin
                if (long_data<>0) then {is a serie of operations}
                 begin
     	             if (long_operation)  then
			p^.mode_operation:=9
                     else 
		        p^.mode_operation:=8; 
                 end
                else  {is NOT a serie of operations}
                 begin
     	             if (long_operation)  then
			p^.mode_operation:=1
                     else 
		        p^.mode_operation:=0; 
                 end;  
	      end;
            fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;

SET16:      long_operation:= FALSE;

SET24:	    long_operation:= TRUE; 

VME16:      vme_long_operation := FALSE;

VME32:      vme_long_operation := TRUE;

SETQ:	    q_operation := true;

SETNOQ:	    q_operation := false;

QREAD:     begin
	    p^.mode_operation :=26;
            fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
	    end;


FQSTOP:	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (fu>15) and (fu<24) then {write function}
	     else 
              begin
     	             if (long_operation) then
				p^.mode_operation:=29 
			else
				p^.mode_operation:=28; 
		                fill_list(br,cr,sn,na,fu,long_operation,
					     q_operation,long_data);
                end
            end;

SQSTOP:	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (fu>15) and (fu<24) then {write function}
	     else 
              begin
     	             if (long_operation) then
				p^.mode_operation:=35
			else
				p^.mode_operation:=34; 
		                fill_list(br,cr,sn,na,fu,long_operation,
					     q_operation,long_data);
                end
            end;

QIGNORE:    pr_qignore;

QREPEAT:    pr_qrepeat;

DMAEND:	    begin	
             pr_dmaend;
             fill_camac_stato:=5;
             end;

QSTOP:	    begin
             pr_qstop;
            end;

EOE:        begin
	     p^.mode_operation :=6;{end equipment}
             p^.next_elem:=NIL;
             fill_camac_stato := 1;
	     long_operation := FALSE;
	     vme_long_operation := FALSE;
	     q_operation := TRUE;
            end; 

C:          begin
             {only comments}
            end; 

SELREG:     begin
             if (long_operation) then p^.mode_operation:=10
              else p^.mode_operation:=10;{only short max 16 bits}
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);{new(p) is  in fill_list}

{}
             select_num:=select_num+1; {increment consecutive num} 
	     p^.data_to_write.low:=select_num; {load consecutive num.in list}
             p^.mode_operation:=11;
	     remember_pointer:=p;
             new(p);{creo lo spazio per il prossimo blocco della lista}
             remember_pointer^.next_elem:=p;{carico il point al nuovo blocco}   
             fill_camac_stato:=8;   
            end;

SECT:	     begin
              p^.mode_operation:=11;{end list of select}
              p^.next_elem:=nil;
	      sect_num := convert (byte,scratch_string);{new list}
              new(p);{creo lo spazio per il primo elemento della lista sect}
              select_matrix[select_num,sect_num]:=p;
             end;

USER_PROCEDURE: begin
                 pr_user_procedure;
	       end;

EOS:	     begin
              p^.mode_operation:=11;
	      p^.next_elem:=nil;
              p:=remember_pointer^.next_elem; {restore della lista}
             end;     	
WAIT_Q:     begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data,repet);
          if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if repet=0 then  {max wait time}
                p^.spare:=2  {wait default to 20ms}
              else
                p^.spare:=repet;
             p^.mode_operation:=15;
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;
                                                   
                                                                        
LOOP:       begin                                                       
             p^.mode_operation:=32;                                     
             p^.spare := convert(integer,scratch_string);{num of loop}  
             previus:=p;                                                
             new (p); {apro una nuova tabella di indirizzi camac}       
             previus^.next_elem:=p;                                     
            end;                                                        
                                                                        
ENDL:       begin                                                       
             p^.mode_operation:=33;                                     
             previus:=p;                                                
             new (p); {apro una nuova tabella di indirizzi camac}       
             previus^.next_elem:=p;                                     
            end;                                                        

FQIGNORE:     begin                                                      
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);      
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (fu>15) and (fu<24) then {write function}                
             else                                                        
              begin                                                      
                     if (long_operation) then                            
                                p^.mode_operation:=31                    
                        else                                             
                                p^.mode_operation:=30;                   
                                fill_list(br,cr,sn,na,fu,
					long_operation,FALSE,long_data);     
                end                                                      
            end;                                                         
                                                                         
VME_RD_EX: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					nwords);
	      pr_vme_ex;
              
{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=50; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=51; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.spare:=nwords;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	


VME_RD_ST: begin

	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
 					nwords);
	      if (vme_b = 0) then
                 pr_vme_st_master
              else
                 pr_vme_st;	     

{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=50; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=51; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.spare:=nwords;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	

VME_WR_EX: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					vme_data);
	      pr_vme_ex;
              
{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=52; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=53; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.data_to_write.full:=vme_data;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	


VME_WR_ST: begin

	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
 					vme_data);
	      if (vme_b = 0) then
                 pr_vme_st_master
              else
                 pr_vme_st;	     

{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=52; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=53; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.data_to_write.full:=vme_data;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;
	    end;	

WRITEHEX:  begin
              hextoint(scratch_string,tmpint);
              p^.data_to_write.full := tmpint;
              p^.mode_operation := 57;
	      previus:=p;
              new(p);
	      previus^.next_elem:=p;
           end;

WFD_PATREG:
           begin
              decode_i1i2i3(scratch_string,
                            tmpint,
                            p^.cam_add.full,
                            p^.data_to_write.full);
              p^.l_mem_add := address(wfd_spr[tmpint]);
              p^.mode_operation := 58;
	      previus:=p;
              new(p);
	      previus^.next_elem:=p;
           end;

WFD_RDMEM: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					nwords);
	      pr_vme_ex;
              if (vme_long_operation) then
	         begin
                    p^.mode_operation:=54; 
	     	    p^.l_mem_add::integer:= virtual_base_add::integer+
		                            vme_add::integer;
	         end
              else
	         begin
	     	    p^.mode_operation:=54; 
	     	    p^.mem_add::integer:= virtual_base_add::integer+
		                          vme_add::integer;
	         end;
              p^.spare:=nwords;
	      previus:=p;
              new(p);
	      previus^.next_elem:=p;
	   end;	

WFD_READOUT:  
            { Example usage: WFD_READOUT 1,0,200000,5000               }
            { -------------------------------------------------------- }
            { The first argument is the supermodule number, which is   }
            { used to index the software pattern register array in     }
            { the CADRIVER readout code. The second argument is a mode }
            { select which is currently unused and undefined and       }
            { should always be set to zero. The third argument is the  }
            { default time window in 5 ns units. This initializes the  }
            { pattern register that stores the time window. It is      }
            { expected that in normal running, this register will be   }
            { dynamically filled by the STOP master if we use variable }
            { length delays. The fourth argument contains the limit    }
            { on the amount of data to readout, in bytes.              }
            { -------------------------------------------------------- }
            { ETK 16-Mar-1995                                          }
            begin
              decode_i1i2i3i4(scratch_string,ism,tmpint,iwin,ilim);
              p^.mode_operation:=56;
              p^.spare := ism;              {  <-  supermodule number  }
              wfd_spr[12+ism] := iwin;      {  <-  default time-window }
              p^.data_to_write.full := ilim;
              previus:=p;
              new(p);
              previus^.next_elem:=p;
	    end;	

WFD_RDTIM: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					nwords);
	      pr_vme_ex;
	      if (vme_long_operation) then
	       	 begin
	     	    p^.mode_operation:=55; 
	     	    p^.l_mem_add::integer:= virtual_base_add::integer+
		                            vme_add::integer;
                 end
              else
	         begin
	     	    p^.mode_operation:=55; 
	     	    p^.mem_add::integer:= virtual_base_add::integer+
		                          vme_add::integer;
                 end;
              p^.spare:=nwords;
	      previus:=p;
              new(p);
	      previus^.next_elem:=p;
           end;

            otherwise raise_exception (error_on_list);
           end; {of case stato 2} 
           end; {of stato 2}


{-------------------------------------------------------------------------}

3:	  begin
case conv_list_command of

T:	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (long_operation) then p^.mode_operation:=5 
	       else p^.mode_operation:=4;
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;
            
F:	    begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             if (fu>15) and (fu<24) then
             begin 
	      if (long_operation) then p^.mode_operation:=3
                 else p^.mode_operation:=2;                       
              end
	     else 
              begin
	      if (long_operation) then p^.mode_operation:=5
                 else p^.mode_operation:=4;{in initi solo funzioni di test}
	      end;
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;

LOADF:      begin
             ind_file:=ind_file+1;
             write_file[ind_file]:=scratch_string;
             if (long_operation) then p^.spare:=1
                 else p^.spare:=0;{set long or short transfer}
	     p^.mode_operation :=20;
	     p^.data_to_write.low:=ind_file; {give the index for find the file}
             open(ifil,history:=history$readonly,
                   file_name := write_file[p^.data_to_write.low]);
             close(ifil);
	     previus:=p;
	     new(p); {space for the next element}
	     previus^.next_elem:=p;
	    end;

LOAD:      begin
             if (long_operation) then raise_exception (error_on_list);    
             ind_file:=ind_file+1;
             write_file[ind_file]:=scratch_string;
	     p^.mode_operation :=21;
	     p^.data_to_write.low:=ind_file; {give the index for find the file}
             open(ifil,history:=history$old,
                   file_name := write_file[p^.data_to_write.low],
	           record_type:=record$variable);
             close (ifil); {test if file is present}
	     previus:=p;
	     new(p); {space for the next element}
	     previus^.next_elem:=p;
	    end;

WR_SAME_A:  begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data,repet);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             p^.mode_operation:=16;
             p^.spare:=repet;{how many times?}
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;

WR_DIFF_A:  begin
             decode_bcnaf(scratch_string,br,cr,sn,na,fu,long_data,repet);
       if (not(table_br_cr[br][cr])) then raise_exception (BCoffline);
             p^.mode_operation:=18;
             p^.spare:=repet;{how many times?}
             fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
            end;

SET16:      long_operation:= FALSE;

SET24:	    long_operation:= TRUE; 

SETQ:	    q_operation := true;

SETNOQ:	    q_operation := false;


USER_PROCEDURE: begin
                 pr_user_procedure;
	     	end;

QIGNORE:    pr_qignore;

QREPEAT:    pr_qrepeat;

DMAEND:	    begin	
             pr_dmaend;
             fill_camac_stato:=9;
             end;

QSTOP:	    begin
             pr_qstop;
            end;

EOI:	    begin
             dispose (p);
             previus^.next_elem:=nil;
	     long_operation := FALSE;
	     vme_long_operation := FALSE;
	     q_operation := TRUE;
             fill_camac_stato:=1 ;
  	    end;

C:          begin
             {solo commenti}
            end; 


QREAD:     begin
	    p^.mode_operation :=26;
            fill_list(br,cr,sn,na,fu,long_operation,q_operation,long_data);
	    end;

                                                                        
LOOP:       begin                                                       
             p^.mode_operation:=30;                                     
             p^.spare := convert(integer,scratch_string);{num of loop}  
             previus:=p;                                                
             new (p); {apro una nuova tabella di indirizzi camac}       
             previus^.next_elem:=p;                                     
            end;                                                        
                                                                        
ENDL:       begin                                                       
             p^.mode_operation:=31;                                     
             previus:=p;                                                
             new (p); {apro una nuova tabella di indirizzi camac}       
             previus^.next_elem:=p;                                     
            end;                                                        
                                                                        
{.........................................................................}
{ Commands added in the INIT section on request of A.Sanzgiri for WFD tests...
{                                                         A.Surdo, 28/3/'94.
{}

VME16:      vme_long_operation := FALSE;

VME32:      vme_long_operation := TRUE;

VME_RD_EX: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					nwords);
	      pr_vme_ex;
              
{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=50; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=51; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.spare:=nwords;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	

VME_RD_ST: begin

	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
 					nwords);
	      if (vme_b = 0) then
                 pr_vme_st_master
              else
                 pr_vme_st;	     

{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=50; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=51; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.spare:=nwords;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	

VME_WR_EX: begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					vme_data);
	      pr_vme_ex;
              
{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=52; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=53; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.data_to_write.full:=vme_data;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	      
	    end;	


VME_WR_ST: begin

	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
 					vme_data);
	      if (vme_b = 0) then
                 pr_vme_st_master
              else
                 pr_vme_st;	     

{ Now fill camac_list block}
	     if (vme_long_operation) then
	     	begin
	     		p^.mode_operation:=52; 
	     		p^.l_mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
	    	end
	     else
		begin
	     		p^.mode_operation:=53; 
	     		p^.mem_add::integer:= virtual_base_add::integer+
		      			vme_add::integer;
		end;
	     p^.data_to_write.full:=vme_data;
	     previus:=p;
             new(p);
	     previus^.next_elem:=p;

	    end;	
{.........................................................................}

WFD_PATREG:
           begin
              decode_i1i2i3(scratch_string,
                            tmpint,
                            p^.cam_add.full,
                            p^.data_to_write.full);
              p^.l_mem_add := address(wfd_spr[tmpint]);
              p^.mode_operation := 58;
	      previus:=p;
              new(p);
	      previus^.next_elem:=p;
           end;

WFD_THRESH: begin
               decode_i1i2i3i4(scratch_string,
                               ism,ichan,iinp,ival);
               iend  := ichan MOD 2;
               ichan := ichan DIV 2;
               p^.spare := iinp;
               p^.cam_add.full := 1000*ism + 10*ichan + iend;
               p^.data_to_write.full := ival;
               p^.mode_operation := 59;
	       previus:=p;
               new(p);
	       previus^.next_elem:=p;
            end;

WFD_MAP:    begin
	      decode_vic_comm(scratch_string,vme_b,vme_c,vme_page,vme_add,
					tmpint);
              
              wfd_sm_base_addr := vme_page * %x100000 + vme_add;
              for ichan := 0 to 23 do
                 begin
                 for iend := 0 to 1 do
                    begin
                       wfd_ch_base_addr := wfd_sm_base_addr +
                                           (ichan*2+iend) * %x10000;
                       vme_page := wfd_ch_base_addr DIV %x100000;
                       vme_add  := wfd_ch_base_addr MOD %x100000;
                       pr_vme_ex;
                       wfd_chan_addr[tmpint,ichan,iend].virtual := 
                          virtual_base_add::integer+vme_add::integer;
                       wfd_chan_addr[tmpint,ichan,iend].actual :=
                          wfd_ch_base_addr;
                    end;
                 end;
	    end;	

WRITEHEX:   begin
               hextoint(scratch_string,tmpint);
               p^.data_to_write.full := tmpint;
               p^.mode_operation := 57;
	       previus:=p;
               new(p);
	       previus^.next_elem:=p;
            end;

            otherwise raise_exception (error_on_list);
           end; {of case stato 3}  
          end; {of stato 3}
{---------------------------------------------------------------------------}
4:	begin
	  case conv_list_command of
{}
EQUIP:     begin
  	    skip_blank (scratch_string,user_string,scratch_string);
	    equip_num := convert (byte,user_string);
	    pointer_to_copy := pointer_array[equip_num];{punta alla lista}
	    start_equip_pointer:=p;{save pointer to the first}
	    while (pointer_to_copy<>NIL) do begin
 	     p^:=pointer_to_copy^ ;{ricopio l'elemento di lista}
	     previus:=p; {salvo il puntatore}
             new(p);
	     previus^.next_elem :=p; {puntatore nella lista precedente}
	     pointer_to_copy:=pointer_to_copy^.next_elem;
            end;
	    start_equip_pointer^.next_equip:=p;
           end;

EOT:	   begin
            dispose (p);
	    start_equip_pointer^.next_equip:=NIL;
            previus^.next_elem:=NIL;
            fill_camac_stato:=1 ;
  	   end;

C:          begin
             {solo commenti}
           end; 

           otherwise raise_exception (error_on_list);
           end; {of case stato 4}
          end; {of stato 4}
{-------------------------------------------------------------------------}
5:	  begin
	   case conv_list_command of
{}
QSCAN:	     begin
              pr_qscan;
	      fill_camac_stato:=2;
             end;
             otherwise raise_exception (error_on_list);
            end; {of case stato 5}
           end; {of stato 5}
		

{-------------------------------------------------------------------------}
7: 	   begin
           {error status wait for end of file}
           end; {of case stato 7}
{-------------------------------------------------------------------------}
8:	  begin
	   case conv_list_command of
{}
SECT:	     begin
	      sect_num := convert (byte,scratch_string);
              new(p);{creo lo spazio per il primo elemento della lista sect}
              select_matrix[select_num,sect_num]:=p;
              fill_camac_stato:=2;
             end;

             otherwise raise_exception (error_on_list);
            end; {of case stato 8}
           end; {of stato 8}

{-------------------------------------------------------------------------}
9:	  begin
	   case conv_list_command of
{}
QSCAN:	     begin
              pr_qscan;
	      fill_camac_stato:=3;
             end;
             otherwise raise_exception (error_on_list);
            end; {of case stato 9}
           end; {of stato 9}
		
{--------------------------------------------------------------------------}


          end; {of case sugli stati}
         end{dell'if sull eof}
	else {ho trovato l'eof}
	  begin
	   eof_found:=true;
	   fill_camac_stato:=1;
           writeln ('Ready ... ');
           writeln (' ');
	  end;	
	until eof_found;
end_proc: close (list_file);
end;
