{ File: [20,50]GENSRVDEF.PAS       Last Edit: 9-AUG-1989 18:35:06 
}


{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Generic server program includes and definitions.  

  History:

    03-Aug-89.  Philip Hannay.  Created from GATESRV.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}


Const

  { directive status values }
  success = 1; 
  flag_was_set = 2;
  no_msg = -8;

  { event flag that will be used for waking up task in the event of
    message packet receipt }
  Packet_in_flag = f1;

  { event flag that will be used for QIOW output to device }
  Send_flag = f2;

  { event flag that will be used to signal that a read QIO has completed }
  QIO_done_flag = f3;

  { ACK timeout flag, when set, indicates ACK never arrived }
  ACK_TMO_flag = f4;

  { event flag that will be used for delays }
  Delay_flag = f5;


Type

  { for use by debug mode }
  Debug_type = (debug_read, debug_write);

  { Actions to take for message input/output.  We define possible generic 
   actions, and then use specific code to put these actions into a set.  
   The generic action of the program is then driven by the set. }

  Action_type = (ACT_WLB_send, ACT_RLB_raw, 
                 ACT_WLB_ACK_buffer, ACT_WLB_NAK_buffer,
                 ACT_message_with_ACK);





Var

  { installed task name }
  task_name: ch6;

  { device port variables }
  device_port: text;
  device_lun: integer;
  device_port_name: ch40;  { device port logical name }

  deb: text;  {debug file or port}
  mon: text;  {monitor file or port}

  Exit_requested: boolean;  {set true when program requested to exit}

  device_transaction_received: boolean; {set true when a device message contains
                                        a device transaction}
  message_packet_received: boolean; {set true when a message packet received}
  send_MSG: boolean; {set true when a message is ready to be sent}
  send_ACK: boolean; {set true when an ACK is ready to be sent}
  send_NAK: boolean; {set true when a NAK is ready to be sent}
  waiting_for_ACK: boolean; {set true when an ACK/NAK expected from device}
                      
  { Action sets for describing what to do for interfacing with
    the device - these are initialized in the device specific
    INITIALIZE_SPECIFIC procedure.  MSG_SEND_ACTION describes what
    to do when SEND_MSG is true, MSG_RECV_ACTION describes what
    to do with the message text when a message comes in (a read QIO completes),
    ACK_SEND_ACTION describes what to do when SEND_ACK is true,
    NAK_SEND_ACTION describes what to do when SEND_NAK is true,
    ACK_RECV_ACTION describes what to do when an expected ACK 
    (that is, in sequence when either an ACK or NAK would be normal) is
    received, NAK_RECV_ACTION describes what to do when an
    expected NAK (that is, in sequence when either an ACK or NAK would be 
    normal) is received, and TMO_RECV_ACTION describes what to do
    when a timeout occurs while expecting an ACK.  Note that an
    IOSTATUS of IE.TMO is considered a NAK, since the IO completed
    with error.  This is different from a timeout where no IO completes,
    but we get no response from the device.  NAK_RECV_ACTION handles the
    former case, and TMO_RECV_ACTION handles the latter case.}

  MSG_send_action, MSG_recv_action, ACK_send_action, NAK_send_action,
  ACK_recv_action, NAK_recv_action, TMO_recv_action: set of Action_type;

  monitor_on: boolean; {set true when monitor is requested}
  debug_on: boolean; {set true when debug detail is requested}

  New_message_packet: message_packet_type;  {current message packet received}
  New_packet_task: CH6;  {ASCII task name of packet sender}

  Notify_task: CH6; {ASCII task name for device significant event notification}

  { Messages may be queued internally, pending evaluation and processing.
    This internal queue is emptied before any new messages are brought in
    from the external message queue.  Normally, this internal queue is
    used to queue up device commands when a series of commands must be 
    issued. }
  Internal_msg_queue: packed array 
                         [1..max_internal_msg] of message_packet_type;
  Internal_msg_start_ptr: integer;
  Internal_msg_end_ptr: integer;

  Message_in_queue: boolean; {set true when message packets may be in queue}
  Device_message_in: boolean; {set true when device messages may be in }

  { raw device read buffers and status areas }
  Raw_buffer: array [1..max_qio] of 
                packed array [1..Max_tran_size] of char; 
  Raw_IOSB: array [1..max_qio] of IO_status_block;
  Raw_param_list: qio_param_list;

  { current completed or next completed pointer - points to the raw read QIO
    that has just completed, or is expected to complete next.  The raw QIOs
    are completed in a FIFO fashion, so CUR_QIO will advance in a loop. }
  Cur_qio: integer;

  { buffers and status areas for the device read under current consideration }
  Receive_buffer: transaction_rec;
  Receive_IOSB: IO_status_block;

  { ACK_BUFFER will contain a device specific ACK string all ready to go out }
  ACK_buffer: packed array [0..20] of char; {type0 string}

  { NAK_BUFFER will contain a device specific NAK string all ready to go out }
  NAK_buffer: packed array [0..20] of char; {type0 string}

  { SEND_BUFFER will contain the current message for the device either before
    sending (SEND_MSG is true) or after sending and awaiting ACK
    (WAITING_FOR_ACK is true).  While either of these booleans is true,
    the SEND_BUFFER is not available for use. }
  Send_buffer: packed array [0..Max_tran_size] of char; {type 0 string}
  Send_IOSB: IO_status_block;
  Send_param_list: qio_param_list;

  cum_ACKs: integer;  { cumulative ACKs received since last reporting period }
  cum_NAKs: integer;  { cumulative NAKs received since last reporting period }
  now_NAKs: integer;  { consecutive NAKs received }
  cum_SNAKs: integer; { cumulative NAKs sent since last reporting period }
  now_SNAKs: integer; { consecutive NAKs sent }
  cum_TMOs: integer;  { cumulative TMOs received since last reporting period }
  now_TMOs: integer;  { consecutive TMOs received }

{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}



{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
{~~~~~~~~~~~~~~~~  candidates for libraries   ~~~~~~~~~~~~~~~}


{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
PROCEDURE SRVERR ( error_number: integer;
                   aux_error_number: integer;
                   aux_msg: packed array [lo..hi: integer] of char
                );
{ Standard error/notice routine for server - primary error number plus 
  auxillary error number if any, along with a variable length text message.   
  Route to debug device if on, and always to program TI: (output).  Note
  that we tone down the printed message to say "Notice" as "Error" sounds
  too dramatic, and in some cases, are errors are "normal". }

{ Error/notice code -1 thru -49 are reserver for GENSRV use, while all
  other codes (normally -50 and below) can be used by the device 
  specific code.}

var
  i: integer;

Begin
{ always to TI: - output }
write(task_name,': Notice ',error_number:1,', Sub_notice ',
         aux_error_number:1,'  ');
swrite(output,aux_msg);
writeln;
{ And to debug device if on  - note that if debug device is same as
  TI:, the same message appears twice.  There is no easy way to avoid
  this, and its no big deal. }
if debug_on
  then begin
    write(deb,task_name,': Notice ',error_number:1,', Sub_notice ',
           aux_error_number:1,'  ');
    swrite(deb,aux_msg);
    writeln(deb);
    end;
end;

{~~~~~~~~~~~~~~~~  end candidates for libraries   ~~~~~~~~~~~~~~~}
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}


{ end GENSRVDEF.PAS   }

