?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Deadstart : System Messages Processor' ??
MODULE dsm$process_sys_msgs_helper;

{ PURPOSE:
{   This module contains procedures that assist the job template procedures involved
{   in the logging of DFT errors and the logging of system messages.  When the job
{   template procedures wish to contact the logging procedures that run in monitor
{   they call these procedures which are allowed to call monitor.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
*copyc dsp$fetch_boot_data
*copyc dsp$save_boot_data_pointer
*copyc i#current_sequence_position
*copyc pmp$zero_out_table
?? EJECT ??
*copyc dsv$boot_data_base_p
*copyc dsv$sys_msg_buffer_desc_p
*copyc dsv$sys_msg_buffer_initialized
*copyc dsv$sys_msg_buffer_ptrs
*copyc dsv$sys_msg_buffer_size
*copyc osv$boot_is_executing
*copyc osv$mainframe_wired_heap
?? TITLE := 'dsp$initialize_sys_msg_buffer', EJECT ??

{ PURPOSE:
{   This procedure initializes the circular system message buffer in mainframe wired.  If the boot is
{   executing it saves a pointer to the buffer in the SSR otherwise it moves any data that may have been
{   saved in the boot to the system core buffer.

  PROCEDURE [XDCL] dsp$initialize_sys_msg_buffer;

    VAR
      boot_sys_msg_data_p: ^SEQ ( * ),
      boot_sys_msg_desc_p: ^dst$sys_msg_buffer_desc,
      boot_sys_msg_header_p: ^dst$system_message_header,
      boot_sys_msg_seq_p: ^SEQ ( * ),
      buffer_sys_msg_data_p: ^SEQ ( * ),
      buffer_sys_msg_header_p: ^dst$system_message_header,
      rel_sys_msg_desc_p: [STATIC] REL (SEQ ( * )) ^dst$sys_msg_buffer_desc,
      rel_sys_msg_desc_seq_p: ^SEQ ( * );

    { Create the System Message buffer in mainframe wired.  Two pointers will be used with the System
    { Message buffer.  The 'add_data_seq_p' points to where data is added to the buffer and the
    { 'remove_data_seq_p' points to where data is removed from the buffer.  At the creation of the buffer
    { both pointers point to the beginning of the buffer.

    ALLOCATE dsv$sys_msg_buffer_ptrs.add_data_seq_p: [[REP dsv$sys_msg_buffer_size of cell]]
          IN osv$mainframe_wired_heap^;
    pmp$zero_out_table (dsv$sys_msg_buffer_ptrs.add_data_seq_p, dsv$sys_msg_buffer_size);
    dsv$sys_msg_buffer_ptrs.remove_data_seq_p := dsv$sys_msg_buffer_ptrs.add_data_seq_p;

    { The variable 'dsv$sys_msg_buffer_desc' is a record containing a 'description' of the System Message
    { buffer.  It contains three things:
    {   1)  It contains a pointer to the beginning of the buffer for the boot and for system core.
    {   2)  It contains the 'add' and 'remove' pointer positions.  This is needed for moving data from the
    {       boot to system core or for moving data in recovery.
    {   3)  It contains the size of the buffer.

    ALLOCATE dsv$sys_msg_buffer_desc_p IN osv$mainframe_wired_heap^;
    dsv$sys_msg_buffer_desc_p^.sys_msg_buffer_size := dsv$sys_msg_buffer_size;

    IF osv$boot_is_executing THEN

      { Save the pointer to the boot buffer so that in system core it can be retrieved and the data on
      { the boot buffer can be moved to the system core buffer.

      dsp$save_boot_data_pointer (dsc$system_messages, #SEQ (rel_sys_msg_desc_p));
      rel_sys_msg_desc_p := #REL (dsv$sys_msg_buffer_desc_p, dsv$boot_data_base_p^);
      dsv$sys_msg_buffer_desc_p^.boot_start_of_buffer_p :=
            #REL (dsv$sys_msg_buffer_ptrs.add_data_seq_p, dsv$boot_data_base_p^);

    ELSE

      { It is okay to access the System Message buffer pointers here instead of in a monitor routine because
      { the variable dsv$sys_msg_buffer_initialized is not yet set.  This variable must be set before the
      { monitor routines can access the buffer pointers.

      dsv$sys_msg_buffer_desc_p^.cm_start_of_buffer_p := dsv$sys_msg_buffer_ptrs.add_data_seq_p;

      { Fetch the pointer to the boot buffer.

      rel_sys_msg_desc_seq_p := #SEQ (rel_sys_msg_desc_p);
      dsp$fetch_boot_data (dsc$system_messages, rel_sys_msg_desc_seq_p);
      boot_sys_msg_desc_p := #PTR (rel_sys_msg_desc_p, dsv$boot_data_base_p^);
      boot_sys_msg_seq_p := #PTR (boot_sys_msg_desc_p^.boot_start_of_buffer_p, dsv$boot_data_base_p^);

      { Move the data from the boot buffer to the system core buffer.

      WHILE (i#current_sequence_position (boot_sys_msg_seq_p) < boot_sys_msg_desc_p^.add_data_ptr_offset) DO
        NEXT boot_sys_msg_header_p IN boot_sys_msg_seq_p;
        NEXT boot_sys_msg_data_p: [[REP boot_sys_msg_header_p^.message_size OF cell]] IN boot_sys_msg_seq_p;
        NEXT buffer_sys_msg_header_p IN dsv$sys_msg_buffer_ptrs.add_data_seq_p;
        NEXT buffer_sys_msg_data_p: [[REP boot_sys_msg_header_p^.message_size OF cell]] IN
              dsv$sys_msg_buffer_ptrs.add_data_seq_p;
        buffer_sys_msg_header_p^ := boot_sys_msg_header_p^;
        buffer_sys_msg_data_p^ := boot_sys_msg_data_p^;
      WHILEND;
    IFEND;

    { Save the current 'add' and 'remove' pointer positions.

    dsv$sys_msg_buffer_desc_p^.add_data_ptr_offset :=
          i#current_sequence_position (dsv$sys_msg_buffer_ptrs.add_data_seq_p);
    dsv$sys_msg_buffer_desc_p^.remove_data_ptr_offset :=
          i#current_sequence_position (dsv$sys_msg_buffer_ptrs.remove_data_seq_p);

    { This variable tells the monitor code that the System Message buffer is initialized and ready to be used.
    { After this variable is set to true only monitor code can access the System Message buffer.

    dsv$sys_msg_buffer_initialized := TRUE;

  PROCEND dsp$initialize_sys_msg_buffer;
MODEND dsm$process_sys_msgs_helper;
