?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE CM : Miscellaneous Interfaces' ??
MODULE cmm$miscellaneous_interfaces;

{ PURPOSE:
{   This module contains interfaces that return information about elements in a configuration and
{   perform state changes.

  CONST
    one_second = 1000 {milliseconds};

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cme$job_template_deadstart
*copyc cme$logical_configuration_mgr
*copyc cme$reserve_element
*copyc cml$element_state_change
*copyc cmt$connection
*copyc cmt$element_definition
*copyc cmt$element_descriptor
*copyc cmt$element_reservation
*copyc cmt$lcu_lock_control
*copyc ofe$error_codes
*copyc dme$tape_errors
*copyc dmt$error_condition_codes
*copyc dst$iou_resource
*copyc dst$log_ele_state_change
*copyc ost$caller_identifier
*copyc rmt$device_class

{Begin Debug code
*copyc osc$processor_defined_registers
*copyc ost$execution_control_block
*copyc pmp$binary_to_ascii
*copyc pmp$log_ascii
*copyc clp$trimmed_string_size
{End Debug code
?? POP ??
*copyc avp$capabilities_active_any
*copyc cmp$change_connection_status_r1
*copyc cmp$change_state_info_table
*copyc cmp$change_state_r1
*copyc cmp$clear_ppit
*copyc cmp$convert_channel_type
*copyc cmp$convert_iou_name
*copyc cmp$convert_iou_number
*copyc cmp$dedicated_maint_active
*copyc cmp$determine_redundant_channel
*copyc cmp$determine_tape_element
*copyc cmp$disable_unit
*copyc cmp$enable_unit
*copyc cmp$find_state_change_request
*copyc cmp$get_connected_elements
*copyc cmp$get_connection_status
*copyc cmp$get_controller_type
*copyc cmp$get_element_definition
*copyc cmp$get_element_name
*copyc cmp$get_element_state
*copyc cmp$get_logical_pp_index
*copyc cmp$get_logical_unit_number
*copyc cmp$get_logical_unit_state
*copyc cmp$get_pp_table_rma
*copyc cmp$get_unit_type
*copyc cmp$get_volumes_active
*copyc cmp$idle_pp_r1
*copyc cmp$lcu_lock_set_by_job
*copyc cmp$locate_disabled_connection
*copyc cmp$lock_lun_entry
*copyc cmp$lock_set_by_task
*copyc cmp$manage_lock_r3
*copyc cmp$manage_lcu_lock
*copyc cmp$pc_get_element
*copyc cmp$pc_get_logical_unit
*copyc cmp$queue_state_change
*copyc cmp$reacquire_resources
*copyc cmp$release_channel_resource
*copyc cmp$release_equipment_resource
*copyc cmp$release_pp_by_channel
*copyc cmp$resume_pp_r1
*copyc cmp$retrieve_logical_pp_index
*copyc cmp$search_peripheral_table
*copyc cmp$search_redundant_path
*copyc cmp$support_redundant_channel
*copyc cmp$switch_tape_channel
*copyc cmp$unlock_lun_entry
*copyc cmp$update_connection_states_r1
*copyc cmp$update_logical_unit_table
*copyc cmp$update_pcu_state_info
*copyc cmp$zero_out_uit_rma
*copyc dmp$update_stt
*copyc dpp$put_critical_message
*copyc dsp$log_system_message
*copyc iop$update_usage_allocation
*copyc nap$change_network_device_state
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$begin_system_activity
*copyc osp$end_system_activity
*copyc osp$generate_error_message
*copyc osp$generate_log_message
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc pmp$get_job_names
*copyc pmp$get_mainframe_id
*copyc pmp$wait
?? EJECT ??
*copyc cmv$logical_pp_table_p
*copyc cmv$logical_unit_table
*copyc cmv$peripheral_element_table
*copyc cmv$physical_configuration
*copyc osv$170_os_type
*copyc osv$task_private_heap

  VAR
    cmv$display_config_debug_msg: [XREF] boolean;

?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  TYPE
    cmt$max_channels_per_storage =  0 .. cmc$max_ports_per_data_storage * cmc$max_ports_per_controller - 1,

    pps_acquired_info = RECORD
      CASE acquired: boolean OF
      = TRUE =
        iou: dst$iou_number,
        channel: cmt$physical_channel,
        pp_table_rma: ost$real_memory_address,
        driver_name: pmt$program_name,
        controller_type: cmt$controller_type,
        logical_pp: ARRAY [1 .. 2] OF iot$pp_number,
      = FALSE =
      CASEND,
    RECEND,

    pps_released_info = RECORD
      CASE released: boolean OF
      = TRUE =
        iou: dst$iou_number,
        channel: cmt$physical_channel,
        channel_name: cmt$element_name,
        logical_pp: ARRAY [1 .. 2] OF iot$pp_number,
      = FALSE =
      CASEND,
    RECEND;

?? NEWTITLE := 'P$PROCESS_STATE_CHANGE', EJECT ??

  PROCEDURE p$process_state_change
    (    tape_element: boolean;
         system_caller: boolean;
         outstanding_request: boolean;
         element_descriptor: cmt$element_descriptor;
         system_critical_element: boolean;
         current_element_state: cmt$element_state;
         new_element_state: cmt$element_state;
         caller_ring: ost$ring;
     VAR lock_control: cmt$lcu_lock_control;
     VAR status: ost$status);

    TYPE
      release_information = record
        acquired: boolean,
        pen: cmt$physical_equipment_number,
        pun: cmt$physical_unit_number,
        lun: iot$logical_unit,
        state: cmt$element_state,
        current_state: cmt$element_state,
        new_state: cmt$element_state,
      recend;

    VAR
      actual_new_state: cmt$element_state,
      acquire_redundant_pp: boolean,
      alternate_access_type: cmt$element_type,
      alternate_path_active: boolean,
      channel_released: boolean,
      channel_state: cmt$element_state,
      channel: cmt$element_definition,
      channel_type: string (11),
      cm_unit_type: cmt$unit_type,
      controller_state: cmt$element_state,
      controller_type: cmt$controller_type,
      critical_msg: string (64),
      ct_element_p: ^cmt$element_definition,
      current_state: cmt$element_state,
      disabled_connection_exists: boolean,
      driver_name: pmt$program_name,
      element: cmt$element_descriptor,
      element_definition: cmt$element_definition,
      equipment_number: cmt$physical_equipment_number,
      foreign_equipment: boolean,
      found: boolean,
      index: integer,
      ignore_status: ost$status,
      io_unit_type: iot$unit_type,
      iou_number: dst$iou_number,
      iou_name: cmt$element_name,
      lock_type: cmt$lcu_lock_type,
      logical_pp: iot$pp_number,
      log_data_ptr: ^SEQ ( * ),
      logging_data: dst$log_ele_state_change,
      logical_unit_state: cmt$element_state,
      logical_unit_number: iot$logical_unit,
      mainframe_id: pmt$mainframe_id,
      mass_storage_element: boolean,
      msg_size: 0 .. 0ff(16),
      need_to_idle_pp: boolean,
      name_list_p: ^array [ * ] of cmt$element_name,
      new_state: cmt$element_state,
      number_of_entries: integer,
      number_of_down_controllers: integer,
      number_of_on_controllers: integer,
      number_of_path: integer,
      number_of_units: integer,
      pen: cmt$physical_equipment_number,
      peripheral_driver_name: pmt$program_name,
      physical_channel: cmt$physical_channel,
      physical_id: cmt$physical_identification,
      port: integer,
      pp_idled: boolean,
      pp_not_active: boolean,
      pp_table_rma: ost$real_memory_address,
      process_channel: boolean,
      process_pp: boolean,
      pun: cmt$physical_unit_number,
      released_units: ^array [1 .. * ] of release_information,
      redundant_path_pp_list: array [cmt$physical_equipment_number] of iot$pp_number,
      redundant_channel_list: ^array [ * ] of cmt$physical_address,
      redundant_pp_table_rma_list: array [cmt$physical_equipment_number] of ost$real_memory_address,
      redundant_path_available: boolean,
      redundant_path_useable: boolean,
      save_status: ost$status,
      state: cmt$element_state,
      state_change_request: cmt$state_change_request,
      state_to_check: cmt$element_state,
      system_supplied_name: jmt$system_supplied_name,
      unit_class: cmt$unit_class,
      unit_element_p: ^cmt$element_definition,
      update_controller_address: boolean,
      user_supplied_name: jmt$user_supplied_name;

{Debug code begin
    VAR
      xcb_p: ^ost$execution_control_block,
      gtid: ost$global_task_id;
{Debug code end

?? NEWTITLE := '      clean_up', EJECT ??

    PROCEDURE clean_up
      (    msg: string ( * <= 31));

      VAR
        cleanup_status: ost$status,
        current_state: cmt$element_state,
        i: integer,
        iou_number: dst$iou_number,
        internal_state: cmt$element_state,
        lock_obtained: boolean,
        new_state: cmt$element_state;

?? NEWTITLE := 'p$log_bad_status', EJECT ??

      PROCEDURE p$log_bad_status
        (    msg: string ( * <= 31);
             status: ost$status);

        VAR
          debug_msg: string (132),
          debug_msg_size: integer;

        IF cmv$display_config_debug_msg THEN
          debug_msg := 'PROCESS_STATE_CHANGE.CLEANUP - ';
          debug_msg (32, * ) := msg;
          debug_msg_size := clp$trimmed_string_size (debug_msg);
          pmp$log_ascii (debug_msg (1, debug_msg_size), $pmt$ascii_logset [pmc$job_log, pmc$system_log],
                pmc$msg_origin_system, cleanup_status);
          osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status, cleanup_status);
        IFEND;

      PROCEND p$log_bad_status;
?? OLDTITLE ??
?? NEWTITLE := 'p$log_lock_problem', EJECT ??

      PROCEDURE p$log_lock_problem
        (    msg: string ( * <= 31));

        IF cmv$display_config_debug_msg THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unable_to_access_lut, msg,
                cleanup_status);
          osp$append_status_integer (osc$status_parameter_delimiter, released_units^ [i].lun, 16, TRUE,
                cleanup_status);
          p$log_bad_status ('', cleanup_status);
        IFEND;

      PROCEND p$log_lock_problem;
?? OLDTITLE ??
?? EJECT ??

      p$log_bad_status (msg, status);

      cmp$convert_iou_name (channel.data_channel.iou, iou_number, cleanup_status);
      FOR i := 1 TO number_of_units DO
        IF released_units^ [i].acquired THEN
          new_state := released_units^ [i].new_state;
          current_state := released_units^ [i].current_state;
          cmp$get_logical_unit_state (released_units^ [i].lun, cmv$logical_unit_table, internal_state);

{LUN Locked
          cmp$lock_lun_entry (released_units^ [i].lun, lock_obtained);
          IF NOT lock_obtained THEN
            p$log_lock_problem ('set');
            RETURN; {----->
          IFEND;

{  OFF
          IF (current_state = cmc$off) THEN
            cmp$disable_unit (released_units^ [i].lun);
            IF (controller_type <> cmc$mt5698_xx) AND NOT (((controller_type = cmc$mt698_xx) OR
                  (controller_type = cmc$mt5680_xx)) AND (osv$170_os_type = osc$ot7_dual_state_nos_be)) THEN

              cmp$release_equipment_resource (physical_channel, iou_number, released_units^ [i].pen,
                    released_units^ [i].pun);
            IFEND;

{  ON/DOWN
          ELSEIF (current_state = cmc$on) OR (current_state = cmc$down) THEN
            IF (controller_type <> cmc$mt5698_xx) AND NOT ((controller_type = cmc$mt698_xx) AND
                  (osv$170_os_type = osc$ot7_dual_state_nos_be)) AND (controller_type <> cmc$mt5680_xx) THEN
              cmp$reacquire_resources (dsc$rrt_get_equipment, physical_channel, iou_number,
                    released_units^ [i].pen, released_units^ [i].pun, driver_name, pp_table_rma,
                    controller_type, FALSE, cleanup_status);

              IF NOT cleanup_status.normal THEN
                p$log_bad_status ('cmp$reacquire_resources', cleanup_status);
                cmp$unlock_lun_entry (released_units^ [i].lun, lock_obtained);
                IF NOT lock_obtained THEN
                  p$log_lock_problem ('clear');
                IFEND;
                RETURN; {----->
              IFEND;
            IFEND;

            IF (current_state = cmc$down) THEN
              cmp$disable_unit (released_units^ [i].lun);
            ELSEIF (current_state = cmc$on) THEN
              cmp$enable_unit (released_units^ [i].lun);
            IFEND;
          IFEND;

          IF (controller_type = cmc$mt5698_xx) OR (controller_type = cmc$mt5680_xx) THEN
            cmp$zero_out_uit_rma (released_units^ [i].lun, channel, current_state, cleanup_status);
            IF NOT cleanup_status.normal THEN
              p$log_bad_status ('cmp$zero_out_uit_rma', cleanup_status);
            IFEND;
          IFEND;

          cmp$update_logical_unit_table (released_units^ [i].lun, current_state, cleanup_status);
          IF NOT cleanup_status.normal THEN
            p$log_bad_status ('cmp$update_logical_unit_table', cleanup_status);
            cmp$unlock_lun_entry (released_units^ [i].lun, lock_obtained);
            IF NOT lock_obtained THEN
              p$log_lock_problem ('clear');
            IFEND;
            RETURN; {----->
          IFEND;

{Unlock LUN
          cmp$unlock_lun_entry (released_units^ [i].lun, lock_obtained);
          IF NOT lock_obtained THEN
            p$log_lock_problem ('clear');
            RETURN; {----->
          IFEND;

          REPEAT
            dmp$update_stt (released_units^ [i].lun, internal_state, current_state, cleanup_status);
            IF NOT cleanup_status.normal AND (cleanup_status.condition = dme$unable_to_lock_tape_table) THEN
              pmp$wait (one_second, one_second);
            IFEND;
          UNTIL cleanup_status.normal OR (cleanup_status.condition <> dme$unable_to_lock_tape_table);
          IF NOT cleanup_status.normal THEN
            p$log_bad_status ('dmp$update_stt', cleanup_status);
            RETURN; {----->
          IFEND;
        IFEND;
      FOREND;

      IF redundant_path_available AND acquire_redundant_pp THEN
        FOR i := 0 TO number_of_path DO
          cmp$release_pp_by_channel (redundant_channel_list^ [i].channel, redundant_channel_list^ [i].iou,
                cleanup_status);
          IF NOT cleanup_status.normal THEN
            p$log_bad_status ('cmp$release_pp_by_channel', cleanup_status);
          IFEND;
        FOREND;
      IFEND;

      IF pp_idled THEN
        cmp$resume_pp_r1 (channel.element_name, channel.data_channel.iou, cleanup_status);
        IF NOT cleanup_status.normal THEN
          p$log_bad_status ('cmp$resume_pp_r1', cleanup_status);
        IFEND;
        pp_idled := FALSE;
      IFEND;

    PROCEND clean_up;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;
    save_status.normal := TRUE;
    new_state := new_element_state;
    current_state := current_element_state;

    pmp$get_job_names (user_supplied_name, system_supplied_name, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    { If passed in physical address, convert to element name to search in peripheral table.

    IF (element_descriptor.element_type <> cmc$data_channel_element)
{ } AND (NOT element_descriptor.peripheral_descriptor.use_logical_identification) THEN
      physical_id.hardware_address := element_descriptor.peripheral_descriptor.hardware_address;
      physical_id.product_identification.product_number := '     ';
      physical_id.product_identification.underscore := ' ';
      physical_id.product_identification.model_number := '   ';
      physical_id.serial_number := '   ';
      cmp$get_element_name (physical_id, element, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    ELSE
      element := element_descriptor;
    IFEND;

    PUSH redundant_channel_list: [LOWERVALUE (cmt$physical_equipment_number) ..
          UPPERVALUE (cmt$physical_equipment_number)];

{Debug code begin
    xcb_p := #ADDRESS (1, osc$segnum_job_fixed_heap, #READ_REGISTER (osc$pr_base_constant));
    gtid := xcb_p^.global_task_id;

    IF cmv$display_config_debug_msg THEN
      critical_msg := 'Enter P$PROCESS_STATE_CHANGE: ';
      critical_msg (33, 19) := system_supplied_name;
      pmp$binary_to_ascii (gtid.index, critical_msg (53, 4), 16, 4);
      critical_msg (57) := ':';
      pmp$binary_to_ascii (gtid.seqno, critical_msg (58, 3), 16, 3);
      pmp$log_ascii (critical_msg, $pmt$ascii_logset [pmc$job_log, pmc$system_log], pmc$msg_origin_system,
            ignore_status);
      ignore_status.normal := TRUE;
    IFEND;
{Debug code end

  /main_program/
    begin
      mass_storage_element := FALSE;
      foreign_equipment := FALSE;
      pp_idled := FALSE;
      redundant_path_available := FALSE;
      redundant_path_useable := FALSE;
      acquire_redundant_pp := FALSE;
      need_to_idle_pp := FALSE;

      cmp$get_element_definition (element, element_definition, status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

{ Validate legal state change.
      IF new_state = current_state THEN
        disabled_connection_exists := FALSE;
        IF new_state = cmc$on THEN
          cmp$locate_disabled_connection (element_definition, disabled_connection_exists, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;
        IFEND;
        IF NOT disabled_connection_exists THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$request_state_is_crnt_state, ' ',
                status);
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

{ Validate element type.
      IF element.element_type <> element_definition.element_type THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$incorrect_element_type,
              element_definition.element_name, status);
        EXIT /main_program/; {----->
      IFEND;

      cmp$retrieve_element_info (element_definition, driver_name, controller_type, status);
      IF NOT status.normal THEN
        IF status.condition = cme$pc_unknown_controller_type THEN
          foreign_equipment := TRUE;
          status.normal := TRUE;
        ELSE
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

    /acquire_release_resource/
      BEGIN
        IF tape_element THEN
          lock_type := cmc$removable_media_operation;
        ELSE
          lock_type := cmc$configuration_administrator;
        IFEND;

        cmp$manage_lock_r3 (lock_type, cmc$llo_set_lock, lock_control, status);

{ Queue request if system call and unable to obtain lock.
        IF NOT status.normal THEN
          IF system_caller THEN
            state_change_request.pending := TRUE;
            state_change_request.new_state := new_state;

            { Lock already set by another job or task, queue the request and status should be
            { normal for system caller.

            cmp$queue_state_change (element, state_change_request, status);

            { Attempt to acquire lock one more time. If successful then process the state change.
            { This is done to make sure that the request will be done if it was missed by the
            { QUIT command.

            cmp$manage_lock_r3 (lock_type, cmc$llo_set_lock, lock_control, ignore_status);
            IF NOT ignore_status.normal THEN
              EXIT /main_program/; {----->
            IFEND;
          ELSE { Manual state change case, return abnormal status to user.
            EXIT /main_program/; {----->
          IFEND;
        IFEND;

        IF foreign_equipment THEN

          { Check if element is already reserved by any job .
          { Only update state table, foreign subsystem is responsible for scheduling IOU resources

          check_for_element_reservation (element, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;
          EXIT /acquire_release_resource/; {----->
        IFEND;

        { Figure out the state that need to be used in deciding whether or not
        { a tape unit should be processed.

        IF new_state = cmc$on THEN
          state_to_check := current_state;
        ELSE
          state_to_check := new_state;
        IFEND;

        CASE element_definition.element_type OF
        = cmc$data_channel_element =
          channel := element_definition; { Channel is initialized for clean up purpose.
          physical_channel.number := element_definition.data_channel.number;
          physical_channel.concurrent := element_definition.data_channel.concurrent;
          physical_channel.port := element_definition.data_channel.port;
          cmp$convert_iou_name (element_definition.data_channel.iou, iou_number, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

{ Element is an ICA or a MTI/MDI/EXPRESSLINK channel. }
          IF (controller_type = cmc$ca2629_2) OR (controller_type = cmc$mti2620_21x) OR
                (controller_type = cmc$expresslink) OR (controller_type = cmc$mdi2621_21x) THEN

            FOR pen := LOWERVALUE (cmt$physical_equipment_number)
                  TO UPPERVALUE (cmt$physical_equipment_number) DO
              IF element_definition.data_channel.connection.equipment [pen].configured THEN

                { Check states of ICA/MTI/MDI/EXPRESSLINK channel and device before call NAM/VE. }

                cmp$get_element_state (element_definition.data_channel.connection.equipment [pen].
                      element_name, iou_name, state, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;

                IF current_state = cmc$on THEN
                  IF state = cmc$on THEN
                    nap$change_network_device_state (element_definition.data_channel.connection.
                          equipment [pen].element_name, new_state, current_state, status);
                    IF NOT status.normal THEN
                      osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status,
                            ignore_status);
                      EXIT /main_program/; {----->
                    IFEND;
                  IFEND;
                ELSE
                  IF state = cmc$on THEN
                    IF new_state = cmc$on THEN
                      cmp$change_state_info_table (element_definition.element_name,
                            element_definition.data_channel.iou, new_state, status);
                      IF NOT status.normal THEN
                        EXIT /main_program/; {----->
                      IFEND;
                      nap$change_network_device_state (element_definition.data_channel.connection.
                            equipment [pen].element_name, new_state, current_state, status);
                      IF NOT status.normal THEN
                        osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status,
                              ignore_status);
                        ignore_status.normal := TRUE;
                        cmp$change_state_info_table (element_definition.element_name,
                              element_definition.data_channel.iou, current_state, ignore_status);
                        EXIT /main_program/; {----->
                      IFEND;
                    IFEND;
                  IFEND;
                IFEND;
                EXIT /acquire_release_resource/; {----->
              IFEND;

              { Check to see if channel is already reserved.

              check_for_element_reservation (element, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
              IF (controller_type = cmc$lcn380_170) OR (controller_type = cmc$fs740_200) THEN

                { Need to call DFP$ interface for file server element

                EXIT /acquire_release_resource/; {----->
              IFEND;
            FOREND;

{ Element is a TAPE channel.
          ELSEIF (controller_type = cmc$mt7021_3x) OR (controller_type = cmc$mt7021_4x) OR
                (controller_type = cmc$mt698_xx) OR (controller_type = cmc$mt5698_xx) OR
                (controller_type = cmc$mt7221_2_s0) OR (controller_type = cmc$mt7221_1) OR
                (controller_type = cmc$mt5680_xx) THEN

            { Check to see if DOWN or OFF the primary channel in a redundant configuration.
            { If so attempt to get a PP for the redundant channel if it is not already active.

            IF (cmp$support_redundant_channel (controller_type)) THEN
              cmp$search_redundant_path (element_definition, iou_number, physical_channel, new_state,
                    redundant_path_available, update_controller_address, number_of_path,
                    redundant_channel_list^, redundant_path_pp_list, peripheral_driver_name,
                    redundant_pp_table_rma_list);
              IF redundant_path_available THEN
                FOR index := 0 TO number_of_path DO
                  determine_if_pp_not_active (redundant_channel_list^ [index].channel.number,
                        redundant_channel_list^ [index].channel.port,
                        redundant_channel_list^ [index].channel.concurrent,
                        redundant_channel_list^ [index].iou, pp_not_active);
                  IF pp_not_active AND (new_state <> cmc$on) THEN
                    cmp$reacquire_resources (dsc$rrt_get_pp, redundant_channel_list^ [index].channel,
                          redundant_channel_list^ [index].iou, cmc$null_equipment_number,
                          cmc$null_unit_number, peripheral_driver_name, redundant_pp_table_rma_list [index],
                          controller_type, TRUE, status);
                    redundant_path_useable := status.normal;
                    IF NOT acquire_redundant_pp THEN
                      acquire_redundant_pp := status.normal;
                    IFEND;
                  ELSE
                    redundant_path_useable := TRUE;
                  IFEND;
                FOREND;
              IFEND;
            IFEND;

            count_all_units (element_definition, number_of_units);
            IF number_of_units > 0 THEN
              PUSH released_units: [1 .. number_of_units];
              FOR pun := 1 TO number_of_units DO
                released_units^ [pun].acquired := FALSE;
              FOREND;
            IFEND;
            number_of_units := 0;
            number_of_on_controllers := 0;
            number_of_down_controllers := 0;
            PUSH name_list_p: [1 .. 2 * (UPPERVALUE (cmt$physical_equipment_number) + 1)];

            { Get a list of all element names connected to the given channel

            cmp$get_connected_elements (element_definition, name_list_p, number_of_entries, status);
            IF NOT status.normal THEN
              EXIT /main_program/; {----->
            IFEND;

          /for_loop3/
            FOR index := 1 TO number_of_entries DO
              cmp$pc_get_element (name_list_p^ [index], iou_name, ct_element_p, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
              cmp$get_element_state (ct_element_p^.element_name, iou_name, controller_state, ignore_status);
              IF controller_state = cmc$on THEN
                number_of_on_controllers := number_of_on_controllers + 1;
              ELSEIF controller_state = cmc$down THEN
                number_of_down_controllers := number_of_down_controllers + 1;
              IFEND;
              IF (controller_state <> state_to_check) THEN

              /pun_loop/
                FOR pun := LOWERVALUE (cmt$physical_unit_number) TO UPPERVALUE (cmt$physical_unit_number) DO

                  {  NOTE : LOGICAL_UNIT_STATE : denotes the internal state of a tape unit. This
                  {        state reflects the state of the upline elements connected to this
                  {        unit. For example, the state  of a unit may be ON but since the
                  {        channel is DOWN, the internal state is also DOWN.
                  {        ACTUAL_NEW_STATE : denotes the new state of a tape unit. This new state
                  {        is not necessarely the new state of the element being processed, since
                  {        the state of all upline elements must be considered. For example,
                  {        changing the state of a CHANNEL to ON will not result in changing the
                  {        internal state of the unit to ON if the controller connected to that
                  {        channel is DOWN.
                  {        RELEASED_UNITS : This is the variable used to stored all the units
                  {        that have been processed without error. This variable is scanned to
                  {        undo the operation should any errors occur.

                  IF ct_element_p^.controller.connection.unit [pun].configured THEN
                    number_of_units := number_of_units + 1;
                    cmp$get_element_state (ct_element_p^.controller.connection.unit [pun].element_name,
                          iou_name, state, status);
                    IF NOT status.normal THEN
                      EXIT /main_program/; {----->
                    IFEND;
                    cmp$pc_get_element (ct_element_p^.controller.connection.unit [pun].element_name, iou_name,
                          unit_element_p, status);
                    IF NOT status.normal THEN
                      EXIT /main_program/; {----->
                    IFEND;

                    cmp$check_alternate_path (unit_element_p^, ct_element_p^, element_definition.data_channel,
                          alternate_path_active, alternate_access_type, status);
                    IF NOT status.normal THEN
                      EXIT /main_program/; {----->
                    IFEND;
                    IF (NOT alternate_path_active) THEN

                      cmp$get_logical_unit_number (ct_element_p^.controller.connection.unit [pun].
                            element_name, logical_unit_number, status);
                      IF NOT status.normal THEN
                        EXIT /main_program/; {----->
                      IFEND;

                      { Process all units in the ON state.
                      { Must take into account the state of the controller or unit and use it to update the
                      { state of the unit in the logical unit table.

                      IF (new_state = cmc$on) THEN
                        IF controller_state = cmc$on THEN
                          actual_new_state := state; { Use state of the unit. }
                        ELSE
                          actual_new_state := controller_state;
                        IFEND;
                      ELSE
                        actual_new_state := new_state;
                      IFEND;
                      cmp$get_logical_unit_state (logical_unit_number, cmv$logical_unit_table,
                            logical_unit_state);
                      IF (state <> state_to_check) AND (state <> cmc$off) THEN
                        cmp$change_tape_unit_state (unit_element_p^, current_state, actual_new_state,
                              element_definition, ct_element_p^.controller.physical_equipment_number,
                              controller_type, driver_name, FALSE, logical_unit_number, logical_unit_state,
                              channel_released, status);
                        IF NOT status.normal THEN
                          IF number_of_units > 0 THEN
                            clean_up ('cmp$change_tape_unit_state - 1');
                            EXIT /main_program/; {----->
                          IFEND;
                        IFEND;
                        released_units^ [number_of_units].acquired := TRUE;
                        released_units^ [number_of_units].pen := ct_element_p^.controller.
                              physical_equipment_number;
                        released_units^ [number_of_units].pun := pun;
                        released_units^ [number_of_units].lun := logical_unit_number;
                        released_units^ [number_of_units].state := state;
                        released_units^ [number_of_units].current_state := logical_unit_state;
                        released_units^ [number_of_units].new_state := actual_new_state;
                      IFEND;
                      IF ((controller_type = cmc$mt5698_xx) OR (controller_type = cmc$mt5680_xx)) AND
                            (NOT redundant_path_available) AND (NOT redundant_path_useable) THEN
                        cmp$zero_out_uit_rma (logical_unit_number, element_definition, new_state, status);
                        IF NOT status.normal THEN
                          clean_up ('cmp$zero_out_uit_rma - 1');
                          EXIT /main_program/; {----->
                        IFEND;
                      IFEND;
                    IFEND;
                  IFEND;
                FOREND /pun_loop/;
              IFEND;
            FOREND /for_loop3/;

            IF NOT channel_released THEN
              process_channel := (number_of_on_controllers > 0) OR (number_of_down_controllers > 0);
            ELSE
              process_channel := FALSE;
            IFEND;
            process_pp := number_of_on_controllers > 0;
            process_iou_resources (element_definition, controller_type, process_channel, process_pp,
                  current_state, new_state, driver_name, status);
            IF NOT status.normal THEN
              clean_up ('process_iou_resources - 1');
              EXIT /main_program/; {----->
            IFEND;

            IF redundant_path_available AND redundant_path_useable THEN

              { If the current channel is redundant then turning it on will only cause a state
              { change, there is no need to switch if the primary channel is active.
              { This include 5698 and 5680 tape subsystem where there are redundant channel
              { configured on the controller.

              determine_if_pp_not_active (element_definition.data_channel.number,
                    element_definition.data_channel.port, element_definition.data_channel.concurrent,
                    iou_number, pp_not_active);
              IF NOT pp_not_active OR (new_state <> cmc$on) THEN
                cmp$switch_tape_channel (element_definition, FALSE {ignore_controller_state} , number_of_path,
                      redundant_channel_list^, new_state, redundant_path_pp_list, status);
              IFEND;
            IFEND;

{ Element is a DISK channel.
          ELSEIF (controller_type = cmc$ms5831_x)   OR (controller_type = cmc$msntdc_1) OR
                 (controller_type = cmc$msntdc_2)   OR
                 (controller_type = cmc$ms7154_x)   OR (controller_type = cmc$ms7155_1) OR
                 (controller_type = cmc$ms7155_1x)  OR (controller_type = cmc$ms7165_2x) OR
                 (controller_type = cmc$mscm3_ct)   OR (controller_type = cmc$mshydra_ct) OR
                 (controller_type = cmc$ms7255_1_1) OR (controller_type = cmc$ms7255_1_2) THEN

            mass_storage_element := TRUE;
            cmp$get_logical_pp_index (element_definition, logical_pp, ignore_status);

            IF ignore_status.normal THEN { Not a redundant path, PPIT built at deadstart. }
              cmp$change_disk_element_state (element_definition, controller_type, system_critical_element,
                    logical_pp, physical_channel, iou_number, new_state, logical_unit_number, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
            IFEND;
          ELSEIF controller_type = cmc$mp65354_11 THEN
            cmp$change_ext_cpu_state (element_definition, current_state, new_state, controller_type, status);
            IF NOT status.normal THEN
              EXIT /main_program/; {----->
            IFEND;
          IFEND;

        = cmc$communications_element, cmc$channel_adapter_element =
          cmp$process_netw_element_state (element_definition, element, current_state, new_state, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;
          EXIT /acquire_release_resource/; {----->

        = cmc$controller_element =
          check_for_element_reservation (element, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

          find_connected_channel (element_definition, channel, equipment_number, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

          physical_channel.number := channel.data_channel.number;
          physical_channel.concurrent := channel.data_channel.concurrent;
          physical_channel.port := channel.data_channel.port;
          cmp$convert_iou_name (channel.data_channel.iou, iou_number, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;


          IF (controller_type = cmc$mt7021_3x) OR (controller_type = cmc$mt7021_4x) OR
                (controller_type = cmc$mt698_xx) OR (controller_type = cmc$mt5698_xx) OR
                (controller_type = cmc$mt7221_2_s0) OR (controller_type = cmc$mt7221_1) OR
                (controller_type = cmc$mt5680_xx) THEN

            { See notes on channel_element case.

            { Check to see if DOWN or OFF the primary controller in a redundant configuration.
            { If so attempt to get a PP for the redundant channel if it is not already active.

            IF (cmp$support_redundant_channel (controller_type)) THEN
              cmp$search_redundant_path (element_definition, iou_number, physical_channel, new_state,
                    redundant_path_available, update_controller_address, number_of_path,
                    redundant_channel_list^, redundant_path_pp_list, peripheral_driver_name,
                    redundant_pp_table_rma_list);
              IF redundant_path_available THEN
                FOR index := 0 TO number_of_path DO
                  determine_if_pp_not_active (redundant_channel_list^ [index].channel.number,
                        redundant_channel_list^ [index].channel.port,
                        redundant_channel_list^ [index].channel.concurrent,
                        redundant_channel_list^ [index].iou, pp_not_active);
                  IF pp_not_active AND (new_state <> cmc$on) THEN
                    cmp$reacquire_resources (dsc$rrt_get_pp, redundant_channel_list^ [index].channel,
                          redundant_channel_list^ [index].iou, cmc$null_equipment_number,
                          cmc$null_unit_number, peripheral_driver_name, redundant_pp_table_rma_list [index],
                          controller_type, TRUE, status);
                    redundant_path_useable := status.normal;
                    IF NOT acquire_redundant_pp THEN
                      acquire_redundant_pp := status.normal;
                    IFEND;
                  ELSE
                    redundant_path_useable := TRUE;
                  IFEND;
                FOREND;
              IFEND;
            IFEND;
            count_all_units (element_definition, number_of_units);

            cmp$get_element_state (channel.element_name, channel.data_channel.iou, channel_state, status);
            IF NOT status.normal THEN
              EXIT /main_program/; {----->
            IFEND;

            IF number_of_units > 0 THEN
              PUSH released_units: [1 .. number_of_units];
              FOR pun := 1 TO number_of_units DO
                released_units^ [pun].acquired := FALSE;
              FOREND;
            IFEND;

            number_of_units := 0;

          /pun_loop2/
            FOR pun := LOWERVALUE (cmt$physical_unit_number) TO UPPERVALUE (cmt$physical_unit_number) DO
              IF element_definition.controller.connection.unit [pun].configured THEN
                number_of_units := number_of_units + 1;
                cmp$get_element_state (element_definition.controller.connection.unit [pun].element_name,
                      iou_name, state, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;
                cmp$pc_get_element (element_definition.controller.connection.unit [pun].element_name,
                      iou_name, unit_element_p, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;
                cmp$check_alternate_path (unit_element_p^, element_definition, channel.data_channel,
                      alternate_path_active, alternate_access_type, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;
                cmp$get_logical_unit_number (element_definition.controller.connection.unit [pun].element_name,
                      logical_unit_number, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;

                IF (NOT alternate_path_active) OR (alternate_access_type = cmc$data_channel_element) THEN

                  { Set flag to idle PP so IPI tape subsystem knows about the new units whose UIT RMA has
                  { been un-nil.

                  determine_if_pp_not_active (channel.data_channel.number, channel.data_channel.port,
                        channel.data_channel.concurrent, iou_number, pp_not_active);
                  IF ((controller_type = cmc$mt5698_xx) OR (controller_type = cmc$mt5680_xx)) AND
                        (new_state = cmc$on) AND NOT pp_not_active THEN
                    need_to_idle_pp := TRUE;
                  IFEND;

                  { Take into account the current state of the channel or unit, when changing
                  { the state of the unit to ON, since the channel may be OFF/DOWN.

                  IF new_state = cmc$on THEN
                    IF channel_state = cmc$on THEN
                      actual_new_state := state; { State of unit }
                    ELSE
                      actual_new_state := channel_state;
                    IFEND;
                  ELSE
                    actual_new_state := new_state;
                  IFEND;
                  cmp$get_logical_unit_state (logical_unit_number, cmv$logical_unit_table,
                        logical_unit_state);

                  IF (state <> state_to_check) AND (state <> cmc$off) THEN
                    cmp$change_tape_unit_state (unit_element_p^, current_state, actual_new_state, channel,
                          equipment_number, controller_type, driver_name, FALSE, logical_unit_number,
                          logical_unit_state, channel_released, status);
                    IF NOT status.normal THEN
                      IF number_of_units > 0 THEN
                        clean_up ('cmp$change_tape_unit_state - 2');
                        EXIT /main_program/; {----->
                      IFEND;
                    IFEND;
                    released_units^ [number_of_units].acquired := TRUE;
                    released_units^ [number_of_units].pen := equipment_number;
                    released_units^ [number_of_units].pun := pun;
                    released_units^ [number_of_units].lun := logical_unit_number;
                    released_units^ [number_of_units].state := state;
                    released_units^ [number_of_units].current_state := logical_unit_state;
                    released_units^ [number_of_units].new_state := actual_new_state;
                  IFEND;

                  { If units are OFF or DOWN and IPI tape subsytem, turning ON the controller should un-nil
                  { UIT RMA
                  { only and leave unit status as disabled in the Unit Interface Table.

                  IF ((controller_type = cmc$mt5698_xx) OR (controller_type = cmc$mt5680_xx)) AND
                        (NOT redundant_path_available) AND (NOT redundant_path_useable) THEN
                    cmp$zero_out_uit_rma (logical_unit_number, channel, new_state, status);
                    IF NOT status.normal THEN
                      clean_up ('cmp$zero_out_uit_rma - 2');
                      EXIT /main_program/; {----->
                    IFEND;
                  IFEND;
                IFEND;
              IFEND;
            FOREND /pun_loop2/;

            process_iou_resources (element_definition, controller_type, process_channel, process_pp,
                  current_state, new_state, driver_name, status);
            IF NOT status.normal THEN
              clean_up ('process_iou_resources - 2');
              EXIT /main_program/; {----->
            IFEND;

            IF redundant_path_available AND redundant_path_useable AND (controller_type = cmc$mt5680_xx) THEN

              { If the current controller is redundant then turning it on will only cause a state
              { change, there is no need to switch if the primary controller is active.

              determine_if_pp_not_active (channel.data_channel.number, channel.data_channel.port,
                    channel.data_channel.concurrent, iou_number, pp_not_active);
              IF NOT pp_not_active OR (new_state <> cmc$on) THEN
                cmp$switch_tape_channel (channel, TRUE {ignore_controller_state} , number_of_path,
                      redundant_channel_list^, new_state, redundant_path_pp_list, status); { STATUS ignored.
                need_to_idle_pp := FALSE; { Reset this flag since PP already IDLE and RESUME at this point.
              IFEND;
            IFEND;

            { Because IPI tape controllers can be configured daisy chain, needs to
            { Idle and Resume the PP to let it know about new units.

            IF need_to_idle_pp THEN
              cmp$idle_pp_r1 (channel.element_name, channel.data_channel.iou, status);
              IF NOT status.normal THEN
                clean_up ('cmp$idle_pp_r1');
                EXIT /main_program/; {----->
              IFEND;
              pp_idled := TRUE;
            IFEND;

            IF pp_idled THEN
              cmp$resume_pp_r1 (channel.element_name, channel.data_channel.iou, status);
              IF NOT status.normal THEN
                clean_up ('cmp$resume_pp_r1');
                EXIT /main_program/; {----->
              IFEND;
            IFEND;

        { Element is disk controller.
          ELSEIF (controller_type = cmc$ms5831_x)   OR (controller_type = cmc$msntdc_1) OR
                 (controller_type = cmc$msntdc_2)   OR
                 (controller_type = cmc$ms7154_x)   OR (controller_type = cmc$ms7155_1) OR
                 (controller_type = cmc$ms7155_1x)  OR (controller_type = cmc$ms7165_2x) OR
                 (controller_type = cmc$mscm3_ct)   OR (controller_type = cmc$mshydra_ct) OR
                 (controller_type = cmc$ms7255_1_1) OR (controller_type = cmc$ms7255_1_2) THEN

            mass_storage_element := TRUE;
            cmp$get_logical_pp_index (channel, logical_pp, ignore_status);

            IF ignore_status.normal THEN { PPIT built at deadstart. }
              cmp$change_disk_element_state (element_definition, controller_type, system_critical_element,
                    logical_pp, physical_channel, iou_number, new_state, logical_unit_number, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
            IFEND;
          IFEND;

        = cmc$storage_device_element =
          check_for_element_reservation (element, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

          find_connected_channel (element_definition, channel, equipment_number, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

          physical_channel.number := channel.data_channel.number;
          physical_channel.concurrent := channel.data_channel.concurrent;
          physical_channel.port := channel.data_channel.port;
          cmp$convert_iou_name (channel.data_channel.iou, iou_number, status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;

          cmp$get_element_state (channel.element_name, channel.data_channel.iou, channel_state,
                ignore_status);
          cmp$get_element_state (channel.data_channel.connection.equipment [equipment_number].element_name,
                channel.data_channel.iou, controller_state, ignore_status);

          cmp$get_unit_type (element_definition.product_id, cm_unit_type, io_unit_type, unit_class, found);
          IF found THEN
            IF unit_class = cmc$magnetic_tape_unit THEN
              cmp$get_logical_unit_number (element_definition.element_name, logical_unit_number, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;

              cmp$get_logical_unit_state (logical_unit_number, cmv$logical_unit_table, logical_unit_state);

              { Only Return/acquire equipment and update internal logical state if both channel and
              { controller are currently ON.

              IF ((channel_state = cmc$on) AND (controller_state = cmc$on)) OR
                    ((new_state <> cmc$on) AND (logical_unit_state <> cmc$off)) THEN
                cmp$change_tape_unit_state (element_definition, current_state, new_state, channel,
                      equipment_number, controller_type, driver_name, system_caller, logical_unit_number,
                      logical_unit_state, channel_released, status);
                IF NOT status.normal THEN
                  EXIT /main_program/; {----->
                IFEND;
              ELSEIF (current_state = cmc$off) AND ((channel_state <> cmc$on) OR (controller_state <> cmc$on))
                    THEN

                {
                { Get the unit only if needed, i.e if the path to the unit is not already OFF/DOWN.
                {
                IF (logical_unit_state <> cmc$on) THEN

                  {
                  {   Get the unit and update the stt and logical unit state to be the channel
                  {   or controller state.
                  {
                  IF channel_state <> cmc$on THEN
                    state := channel_state;
                  ELSEIF controller_state <> cmc$on THEN
                    state := controller_state;
                  ELSE
                    state := cmc$down;
                  IFEND;
                  cmp$change_tape_unit_state (element_definition, current_state, {new state} state, channel,
                        equipment_number, controller_type, driver_name, system_caller, logical_unit_number,
                        logical_unit_state, channel_released, status);
                  IF NOT status.normal THEN
                    EXIT /main_program/; {----->
                  IFEND;
                IFEND;
              IFEND;
            ELSEIF unit_class = cmc$mass_storage_unit THEN
              cmp$get_logical_pp_index (channel, logical_pp, ignore_status);
              mass_storage_element := TRUE;

              cmp$change_disk_element_state (element_definition, controller_type, system_critical_element,
                    logical_pp, physical_channel, iou_number, new_state, logical_unit_number, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
            IFEND;
          IFEND;

        = cmc$external_processor_element =
          FOR pen := LOWERVALUE (cmt$physical_equipment_number)
                TO UPPERVALUE (cmt$physical_equipment_number) DO
            IF element_definition.external_processor.connection.io_port [pen].configured THEN
              cmp$pc_get_element (element_definition.external_processor.connection.io_port [pen].element_name,
                    element_definition.external_processor.connection.io_port [pen].iou, ct_element_p, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
              cmp$change_ext_cpu_state (ct_element_p^, current_state, new_state, controller_type, status);
              IF NOT status.normal THEN
                EXIT /main_program/; {----->
              IFEND;
            IFEND;
          FOREND;

        ELSE
          ;
        CASEND;
      END /acquire_release_resource/;

{ Update state table and state info device file. }
      IF element_definition.element_type = cmc$data_channel_element THEN
        iou_name := element_definition.data_channel.iou;
      IFEND;

      cmp$change_state_info_table (element_definition.element_name, iou_name, new_state, status);
      IF NOT status.normal THEN
        osp$set_status_condition (cme$jtd_state_not_retained, save_status);
        status.normal := TRUE;
      IFEND;

      IF element_definition.element_type <> cmc$data_channel_element THEN
        cmp$update_pcu_state_info (element_definition.element_name, new_state, status);
        IF NOT status.normal THEN
          osp$set_status_condition (cme$jtd_state_not_retained, save_status);
          status.normal := TRUE;
        IFEND;
      IFEND;

{ IF maintenance  job then call Device Management to activate all volumes
      IF (caller_ring <= 6) AND (NOT system_caller) AND (new_state = cmc$on) AND mass_storage_element THEN
        cmp$get_volumes_active (ignore_status);
      IFEND;

{ Call interface to update all connection status for elements that are affected by this state change.
      pmp$get_mainframe_id (mainframe_id, ignore_status);
      cmp$change_connection_status_r1 (element_definition, mainframe_id, save_status);

      IF element_definition.element_type = cmc$data_channel_element THEN
        critical_msg (1, 6) := element_definition.data_channel.iou;
        msg_size := 6;
        critical_msg (7, * ) := element_definition.element_name;
        logging_data.element_name (1, 4) := element_definition.data_channel.iou (1, 4);
        logging_data.element_name (5) := '/';
        logging_data.element_name (6, * ) := element_definition.element_name;
        logging_data.serial_number := 'N/A';
        cmp$convert_channel_type (element_definition.data_channel.kind, channel_type);
        logging_data.product_id.product_number := ' ';
        logging_data.product_id.product_number (1, 3) := channel_type (1, 3);
        logging_data.product_id.underscore := ' ';
        logging_data.product_id.model_number := ' ';
      ELSE
        logging_data.element_name := element_definition.element_name;
        logging_data.product_id := element_definition.product_id;
        logging_data.serial_number := element_definition.serial_number;
        msg_size := 0;
        critical_msg (1, * ) := element_definition.element_name;
      IFEND;

      REPEAT
        msg_size := msg_size + 1;
      UNTIL critical_msg (msg_size, 1) = ' ';

      logging_data.old_state := current_state;
      logging_data.new_state := new_state;
      IF system_caller THEN
        logging_data.initiator := 'fail';
      ELSEIF avp$capabilities_active_any ($avt$conditional_capabilities
            [avc$cc_configuration_admin, avc$cc_removable_media_operator, avc$cc_system_operator]) THEN
        logging_data.initiator := 'op';
      ELSEIF (caller_ring <= 6) THEN
        logging_data.initiator := 'ce';
      IFEND;
      log_data_ptr := #SEQ (logging_data);
      dsp$log_system_message (cml$element_state_change, log_data_ptr, status);

      { Put message to the critical window of the NOS/VE System Console. }

      critical_msg (msg_size, 19) := ' STATE CHANGED FROM';
      msg_size := msg_size + 19;

      CASE current_state OF
      = cmc$on =
        critical_msg (msg_size, 5) := ' ON  ';
      = cmc$off =
        critical_msg (msg_size, 5) := ' OFF ';
      = cmc$down =
        critical_msg (msg_size, 5) := ' DOWN';
      ELSE
      CASEND;
      msg_size := msg_size + 5;

      critical_msg (msg_size, 3) := ' TO';
      msg_size := msg_size + 3;

      CASE new_state OF
      = cmc$on =
        critical_msg (msg_size, 6) := ' ON   ';
      = cmc$off =
        critical_msg (msg_size, 6) := ' OFF  ';
      = cmc$down =
        critical_msg (msg_size, 6) := ' DOWN ';
      ELSE
      CASEND;
      msg_size := msg_size + 6;

      dpp$put_critical_message (critical_msg, ignore_status);
      IF system_caller THEN
        critical_msg (1, 64) := 'Initiated by NOS/VE due to element failure.                     ';
        IF outstanding_request THEN
          critical_msg (45, 16) := '(Queued Request)';
        IFEND;
        dpp$put_critical_message (critical_msg, ignore_status);
      ELSE
        IF (caller_ring <= 6) THEN
          critical_msg (1, 31) := 'Initiated by job (ring <= 6): ';
        ELSE
          critical_msg (1, 31) := 'Initiated by job : ';
        IFEND;
        critical_msg (32, 19) := system_supplied_name;
        critical_msg (51, 14) := '              ';
        dpp$put_critical_message (critical_msg, ignore_status);
      IFEND;
    END /main_program/;

    IF NOT save_status.normal THEN
      status := save_status;
    IFEND;

{Debug code begin
    IF cmv$display_config_debug_msg THEN
      critical_msg := 'Exit P$PROCESS_STATE_CHANGE: ';
      critical_msg (33, 19) := system_supplied_name;
      pmp$binary_to_ascii (gtid.index, critical_msg (53, 4), 10, 4);
      critical_msg (57) := ':';
      pmp$binary_to_ascii (gtid.seqno, critical_msg (58, 3), 10, 3);
      pmp$log_ascii (critical_msg, $pmt$ascii_logset [pmc$job_log, pmc$system_log], pmc$msg_origin_system,
            ignore_status);
    IFEND;
{Debug code end

  PROCEND p$process_state_change;
?? TITLE := ' cmp$active_path',EJECT ??

 { PURPOSE : This procedure retrieve information necessary to acquire PP
 {   for active disk channels.

  PROCEDURE cmp$active_path (
        element : cmt$element_definition;
        controller_type : cmt$controller_type;
    VAR pp_acquired : ARRAY [cmt$max_channels_per_storage] OF pps_acquired_info;
    VAR status : ost$status);


      VAR
        ch : integer,
        ch_element : ^cmt$element_definition,
        channel_state : cmt$element_state,
        ch_port : integer,
        eq_element : ^cmt$element_definition,
        equipment_state : cmt$element_state,
        ignore_status : ost$status,
        ignore_unit_state : boolean,
        iou_name : cmt$element_name,
        iou_number : dst$iou_number,
        mainframe_id : pmt$mainframe_id,
        minus_one : integer,
        pen : cmt$physical_equipment_number,
        physical_channel : cmt$physical_channel,
        port : integer,
        pp : integer,
        pp_not_active: boolean,
        pp_table_rma : ost$real_memory_address,
        pun : cmt$physical_unit_number,
        redundant : boolean,
        unit_state : cmt$element_state,
        unit_element : ^cmt$element_definition;

      status.normal := TRUE;

      FOR port := LOWERVALUE (cmt$max_channels_per_storage) TO
                    UPPERVALUE (cmt$max_channels_per_storage) DO
        pp_acquired [port].acquired := FALSE;
        pp_acquired [port].pp_table_rma := 0;
        pp_acquired [port].driver_name := ' ';
        FOR pp := 1 TO 2 DO
          pp_acquired [port].logical_pp [pp] := 0;
        FOREND;
      FOREND;
      pmp$get_mainframe_id (mainframe_id, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      CASE element.element_type OF
      = cmc$data_channel_element =

        cmp$convert_iou_name (element.data_channel.iou, iou_number, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        /pen_loop_1/
        FOR pen := LOWERVALUE (cmt$physical_equipment_number) TO
                     UPPERVALUE (cmt$physical_equipment_number) DO
          IF element.data_channel.connection.equipment [pen].configured THEN
            cmp$get_element_state (element.data_channel.connection.equipment [pen].element_name, iou_name,
                  equipment_state, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;

            IF equipment_state = cmc$on THEN
              cmp$pc_get_element (element.data_channel.connection.
                equipment [pen].element_name, iou_name, eq_element, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;

              IF eq_element ^.element_type = cmc$storage_device_element THEN { Hydra }

                cmp$get_pp_table_rma (element, pp_table_rma, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;

                determine_if_pp_not_active (element.data_channel.number, element.data_channel.port,
                      element.data_channel.concurrent, iou_number, pp_acquired [0].acquired);
                IF pp_acquired [0].acquired THEN
                  pp_acquired [0].iou := iou_number;
                  pp_acquired [0].channel.number := element.data_channel.number;
                  pp_acquired [0].channel.concurrent := element.data_channel.concurrent;
                  pp_acquired [0].channel.port := element.data_channel.port;
                  pp_acquired [0].pp_table_rma := pp_table_rma;
                  pp_acquired [0].driver_name := 'E9S887';
                  pp_acquired [0].controller_type := cmc$mshydra_ct;

                  cmp$get_logical_pp_index (element, pp_acquired [0].logical_pp [1], status);
                  IF NOT status.normal THEN
                    RETURN;
                  IFEND;
                IFEND;

                EXIT /pen_loop_1/;

              ELSEIF eq_element ^.element_type = cmc$controller_element THEN
                FOR pun := LOWERVALUE (cmt$physical_unit_number) TO
                             UPPERVALUE (cmt$physical_unit_number) DO
                  IF eq_element ^.controller.connection.unit [pun].configured THEN
                    cmp$get_element_state (eq_element ^.controller.
                      connection.unit [pun].element_name, iou_name, unit_state, status);
                    IF NOT status.normal THEN
                      RETURN;
                    IFEND;

                    IF unit_state = cmc$on THEN
                      physical_channel.number := element.data_channel.number;
                      physical_channel.concurrent := element.data_channel.concurrent;
                      physical_channel.port := element.data_channel.port;
                      IF cmp$support_redundant_channel (controller_type) THEN
                        cmp$determine_redundant_channel (physical_channel, iou_number,
                            {ignore_state=}TRUE, redundant, ignore_status);
                        IF redundant THEN
                          CYCLE /pen_loop_1/;
                        IFEND;
                      IFEND;
                      cmp$get_pp_table_rma (element, pp_table_rma, status);
                      IF NOT status.normal THEN
                        RETURN;
                      IFEND;

                      determine_if_pp_not_active (element.data_channel.number, element.data_channel.port,
                            element.data_channel.concurrent, iou_number, pp_not_active);
                      IF pp_not_active THEN
                        pp_acquired [0].acquired := TRUE;
                        pp_acquired [0].iou := iou_number;
                        pp_acquired [0].channel.number := element.data_channel.number;
                        pp_acquired [0].channel.concurrent := element.data_channel.concurrent;
                        pp_acquired [0].channel.port := element.data_channel.port;
                        pp_acquired [0].pp_table_rma := pp_table_rma;
                        pp_acquired [0].controller_type := controller_type;
                        pp_acquired [0].driver_name := eq_element ^.controller.
                             peripheral_driver_name;
                        cmp$get_logical_pp_index (element, pp_acquired [0].logical_pp [1], status);
                        IF NOT status.normal THEN
                          RETURN;
                        IFEND;

                        IF cmv$logical_pp_table_p^ [pp_acquired [0].logical_pp [1]].
                              pp_info.logical_partner_pp_index > 0 THEN
                          pp_acquired [0].logical_pp [2] :=
                                cmv$logical_pp_table_p^ [pp_acquired [0].logical_pp [1]].
                                pp_info.logical_partner_pp_index;
                        IFEND
                      IFEND;
                      EXIT /pen_loop_1/;
                    IFEND;
                  IFEND;
                FOREND;
              IFEND;
            IFEND;
          IFEND;
        FOREND /pen_loop_1/;

      = cmc$controller_element =
        ignore_unit_state := (controller_type = cmc$mt5698_xx) OR (controller_type = cmc$mt5680_xx) OR
             (controller_type = cmc$mt7021_3x) OR (controller_type = cmc$mt7021_4x)
             OR (controller_type = cmc$mt7221_2_s0) OR (controller_type = cmc$mt7221_1)
             OR (controller_type = cmc$mt698_xx);
        channel_state := cmc$down;
        /channel_loop_1/
        FOR port := LOWERVALUE (cmt$controller_port_number) TO
                      UPPERVALUE (cmt$controller_port_number) DO
          IF (element.controller.connection.port [port].configured) AND
                (element.controller.connection.port [port].mainframe_ownership = mainframe_id) THEN
            cmp$get_element_state (element.controller.connection.port [port].element_name,
                  element.controller.connection.port [port].iou, channel_state, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
            IF channel_state = cmc$on THEN
              EXIT /channel_loop_1/;
            IFEND;
          IFEND;
        FOREND /channel_loop_1/;

        unit_state := cmc$down;
        /pun_loop_1/
        FOR pun := LOWERVALUE (cmt$physical_unit_number) TO
                     UPPERVALUE (cmt$physical_unit_number) DO
          IF element.controller.connection.unit [pun].configured THEN
            cmp$get_element_state (element.controller.
              connection.unit [pun].element_name, iou_name, unit_state, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
            IF unit_state = cmc$on THEN
              EXIT /pun_loop_1/;
            IFEND;
          IFEND;
        FOREND /pun_loop_1/;

        IF (channel_state = cmc$on) AND ((unit_state = cmc$on) OR (ignore_unit_state)) THEN

          /channel_loop_2/
          FOR port := LOWERVALUE (cmt$controller_port_number) TO
                        UPPERVALUE (cmt$controller_port_number) DO

            { Duplicate code (cmp$get_element_state) for the first ON channel.

            IF (element.controller.connection.port [port].configured) AND
                  (element.controller.connection.port [port].mainframe_ownership = mainframe_id) THEN
              cmp$get_element_state (element.controller.
                connection.port [port].element_name, element.controller.connection.port
                  [port].iou, channel_state, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;

              IF channel_state = cmc$on THEN
                cmp$pc_get_element (element.controller.connection.
                  port [port].element_name, element.controller.connection.port[port].iou,
                        ch_element, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;
                cmp$convert_iou_name (ch_element^.data_channel.iou, iou_number, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;
                physical_channel.number := ch_element^.data_channel.number;
                physical_channel.concurrent := ch_element^.data_channel.concurrent;
                physical_channel.port := ch_element^.data_channel.port;
                IF cmp$support_redundant_channel (controller_type) THEN
                  cmp$determine_redundant_channel (physical_channel, iou_number,
                      {ignore_state=}TRUE, redundant, ignore_status);
                  IF redundant THEN
                    CYCLE /channel_loop_2/;
                  IFEND;
                IFEND;
                cmp$get_pp_table_rma (ch_element^, pp_table_rma, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;

                IF port > LOWERVALUE (cmt$controller_port_number) THEN
                  FOR minus_one := LOWERVALUE (cmt$controller_port_number) TO port - 1 DO
                    IF pp_acquired [minus_one].acquired THEN
                      IF pp_acquired [minus_one].pp_table_rma = pp_table_rma THEN

                        { Do not acquire PP for CCH#(A or B) again.

                        CYCLE /channel_loop_2/; { Find the next channel.}

                      IFEND;
                    IFEND;
                  FOREND;
                IFEND;

                determine_if_pp_not_active (ch_element^.data_channel.number, ch_element^.data_channel.port,
                      ch_element^.data_channel.concurrent, iou_number, pp_acquired [port].acquired);
                IF pp_acquired [port].acquired THEN
                  pp_acquired [port].iou := iou_number;
                  pp_acquired [port].channel.number := ch_element ^.data_channel.number;
                  pp_acquired [port].channel.concurrent := ch_element ^.data_channel.concurrent;
                  pp_acquired [port].channel.port := ch_element ^.data_channel.port;
                  pp_acquired [port].pp_table_rma := pp_table_rma;
                  pp_acquired [port].controller_type := controller_type;

                  pp_acquired [port].driver_name := element.controller.
                       peripheral_driver_name;
                  cmp$get_logical_pp_index (ch_element^, pp_acquired [port].logical_pp [1], status);
                  IF NOT status.normal THEN
                    RETURN;
                  IFEND;

                  IF cmv$logical_pp_table_p^ [pp_acquired [port].logical_pp [1]].
                        pp_info.logical_partner_pp_index > 0 THEN
                    pp_acquired [port].logical_pp [2] :=
                          cmv$logical_pp_table_p^ [pp_acquired [port].logical_pp [1]].
                          pp_info.logical_partner_pp_index;
                  IFEND
                IFEND;
              IFEND;
            IFEND;
          FOREND /channel_loop_2/;
        IFEND;

      = cmc$storage_device_element =

        channel_state := cmc$down;
        equipment_state := cmc$down;
        ch := -1;

        /port_loop_2/
        FOR port := LOWERVALUE (cmt$data_storage_port_number) TO
                     UPPERVALUE (cmt$data_storage_port_number) DO
          IF element.storage_device.connection.port [port].configured THEN
            IF element.storage_device.connection.
                port [port].upline_connection_type = cmc$data_channel_element THEN { Hydra }
              IF element.storage_device.connection.port [port].mainframe_ownership = mainframe_id THEN
                cmp$get_element_state (element.storage_device.
                  connection.port [port].element_name, element.storage_device.connection.
                       port [port].iou, channel_state, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;

                IF channel_state = cmc$on THEN
                  cmp$pc_get_element (element.storage_device.connection.
                    port [port].element_name, element.storage_device.connection.port
                          [port].iou, ch_element, status);
                  IF NOT status.normal THEN
                    RETURN;
                  IFEND;

                  cmp$get_pp_table_rma (ch_element^, pp_table_rma, ignore_status);
                  IF NOT ignore_status.normal THEN { PPIT not build at deadstart. }
                    CYCLE /port_loop_2/; { Find the next channel. }
                  IFEND;

                  IF port > LOWERVALUE (cmt$data_storage_port_number) THEN
                    FOR minus_one := LOWERVALUE (cmt$data_storage_port_number) TO port - 1 DO
                      IF pp_acquired [minus_one].acquired THEN
                        IF pp_acquired [minus_one].pp_table_rma = pp_table_rma THEN

                          { Do not acquire PP for CCH#(A or B) again.

                          CYCLE /port_loop_2/; { Find the next channel.}
                        IFEND;
                      IFEND;
                    FOREND;
                  IFEND;
                  cmp$convert_iou_name (ch_element^.data_channel.iou, iou_number, status);
                  IF NOT status.normal THEN
                    RETURN;
                  IFEND;

                  determine_if_pp_not_active (ch_element^.data_channel.number, ch_element^.data_channel.port,
                        ch_element^.data_channel.concurrent, iou_number, pp_acquired [port].acquired);
                  IF pp_acquired [port].acquired THEN
                    pp_acquired [port].iou := iou_number;
                    pp_acquired [port].channel.number := ch_element ^.data_channel.number;
                    pp_acquired [port].channel.concurrent := ch_element ^.data_channel.concurrent;
                    pp_acquired [port].channel.port := ch_element ^.data_channel.port;
                    pp_acquired [port].pp_table_rma := pp_table_rma;
                    pp_acquired [port].driver_name := 'E9S887';
                    pp_acquired [port].controller_type := cmc$mshydra_ct;

                    cmp$get_logical_pp_index (ch_element^, pp_acquired [port].logical_pp [1], status);
                    IF NOT status.normal THEN
                      RETURN;
                    IFEND;
                  IFEND;
                IFEND;
              IFEND;
            ELSEIF element.storage_device.connection.
                port [port].upline_connection_type = cmc$controller_element THEN
              cmp$get_element_state (element.storage_device.
                connection.port [port].element_name, iou_name, equipment_state, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;

              IF equipment_state = cmc$on THEN
                cmp$pc_get_element (element.storage_device.
                  connection.port [port].element_name, iou_name, eq_element, status);
                IF NOT status.normal THEN
                  RETURN;
                IFEND;

                /channel_loop_3/
                FOR ch_port := LOWERVALUE (cmt$controller_port_number) TO
                                 UPPERVALUE (cmt$controller_port_number) DO
                  IF (eq_element ^.controller.connection.port [ch_port].configured) AND
                         (eq_element^ .controller.connection.port [ch_port].mainframe_ownership
                          = mainframe_id) THEN
                    cmp$get_element_state (eq_element ^.controller.
                      connection.port [ch_port].element_name,
                        eq_element^.controller.connection.port [ch_port].iou, channel_state,
                           status);
                    IF NOT status.normal THEN
                      RETURN;
                    IFEND;
                    IF channel_state = cmc$on THEN
                      cmp$pc_get_element (eq_element ^.controller.connection.
                        port [ch_port].element_name, eq_element^.controller.connection.port
                            [ch_port].iou,ch_element, status);
                      IF NOT status.normal THEN
                        RETURN;
                      IFEND;

                      cmp$convert_iou_name (ch_element^.data_channel.iou, iou_number, status);
                      IF NOT status.normal THEN
                        RETURN;
                      IFEND;
                      physical_channel.number := ch_element^.data_channel.number;
                      physical_channel.concurrent := ch_element^.data_channel.concurrent;
                      physical_channel.port := ch_element^.data_channel.port;
                      cmp$determine_redundant_channel (physical_channel, iou_number,
                          {ignore_state=}TRUE, redundant, ignore_status);
                      IF cmp$support_redundant_channel (controller_type) THEN
                        IF redundant THEN
                          CYCLE /channel_loop_3/;
                        IFEND;
                      IFEND;
                      cmp$get_pp_table_rma (ch_element^, pp_table_rma, status);
                      IF NOT status.normal THEN
                        RETURN;
                      IFEND;

                      IF ch > LOWERVALUE (cmt$max_channels_per_storage) THEN
                        FOR minus_one := LOWERVALUE (cmt$max_channels_per_storage) TO ch - 1 DO
                          IF pp_acquired [minus_one].acquired THEN
                            IF pp_acquired [minus_one].pp_table_rma = pp_table_rma THEN

                              { Do not acquire PP for CCH#(A or B) again.

                              CYCLE /channel_loop_3/; { Find the next channel.}

                            IFEND;
                          IFEND;
                        FOREND;
                      IFEND;

                      determine_if_pp_not_active (ch_element^.data_channel.number,
                            ch_element^.data_channel.port, ch_element^.data_channel.concurrent,
                            iou_number, pp_not_active);
                      IF pp_not_active THEN
                        ch := ch + 1;
                        pp_acquired [ch].acquired := TRUE;
                        pp_acquired [ch].iou := iou_number;
                        pp_acquired [ch].channel.number := ch_element ^.data_channel.number;
                        pp_acquired [ch].channel.concurrent := ch_element ^.data_channel.concurrent;
                        pp_acquired [ch].channel.port := ch_element ^.data_channel.port;
                        pp_acquired [ch].pp_table_rma := pp_table_rma;
                        pp_acquired [ch].controller_type := controller_type;
                        pp_acquired [ch].driver_name := eq_element ^.
                            controller.peripheral_driver_name;
                        cmp$get_logical_pp_index (ch_element^, pp_acquired [ch].logical_pp [1], status);
                        IF NOT status.normal THEN
                          RETURN;
                        IFEND;

                        IF cmv$logical_pp_table_p^ [pp_acquired [ch].logical_pp [1]].
                              pp_info.logical_partner_pp_index > 0 THEN
                          pp_acquired [ch].logical_pp [2] :=
                                cmv$logical_pp_table_p^ [pp_acquired [ch].logical_pp [1]].
                                pp_info.logical_partner_pp_index;
                        IFEND
                      IFEND;
                    IFEND;
                  IFEND;
                FOREND /channel_loop_3/;
              IFEND;
            IFEND;
          IFEND;
        FOREND /port_loop_2/;

      ELSE
        ;
      CASEND;

    PROCEND cmp$active_path;

?? TITLE := '  cmp$change_ext_cpu_state', EJECT ??

  PROCEDURE cmp$change_ext_cpu_state
    (    channel_definition: cmt$element_definition;
         current_state: cmt$element_state;
         new_state: cmt$element_state;
         controller_type: cmt$controller_type;
     VAR status: ost$status);

    VAR
      driver_name: pmt$program_name,
      element_def: ^cmt$element_definition,
      iou_name: cmt$element_name,
      iou_number: dst$iou_number,
      logical_unit_number: iot$logical_unit,
      lock_obtained: boolean,
      pen: cmt$physical_equipment_number,
      physical_channel: cmt$physical_channel,
      pp_table_rma: ost$real_memory_address,
      pp_not_active: boolean,
      resources_released: boolean;

    status.normal := TRUE;
    resources_released := FALSE;

  /main_program/
    BEGIN
      IF channel_definition.element_type <> cmc$data_channel_element THEN
        EXIT /main_program/;
      ELSE
        FOR pen := LOWERVALUE (cmt$physical_equipment_number)
              TO UPPERVALUE (cmt$physical_equipment_number) DO
          IF channel_definition.data_channel.connection.equipment [pen].configured THEN
            cmp$pc_get_element (channel_definition.data_channel.connection.equipment [pen].element_name,
                  iou_name, element_def, status);
            IF NOT status.normal THEN
              EXIT /main_program/;
            IFEND;
            driver_name := element_def^.external_processor.peripheral_driver_name;
            cmp$get_logical_unit_number (element_def^.element_name, logical_unit_number, status);
            IF NOT status.normal THEN
              EXIT /main_program/;
            IFEND;

            IF NOT resources_released THEN
              cmp$get_pp_table_rma (channel_definition, pp_table_rma, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              cmp$convert_iou_name (channel_definition.data_channel.iou, iou_number, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              physical_channel.number := channel_definition.data_channel.number;
              physical_channel.concurrent := channel_definition.data_channel.concurrent;
              physical_channel.port := channel_definition.data_channel.port;

              IF ((new_state = cmc$off) AND (current_state = cmc$on)) OR
                    ((new_state = cmc$down) AND (current_state = cmc$on)) THEN
                determine_if_pp_not_active (channel_definition.data_channel.number,
                      channel_definition.data_channel.port, channel_definition.data_channel.concurrent,
                      iou_number, pp_not_active);
                IF NOT pp_not_active THEN
                  cmp$idle_pp_r1 (channel_definition.element_name, channel_definition.data_channel.iou,
                        status);
                  IF NOT status.normal THEN
                    EXIT /main_program/;
                  IFEND;

                  cmp$release_pp_by_channel (physical_channel, iou_number, status);
                  IF NOT status.normal THEN
                    EXIT /main_program/;
                  IFEND;
                IFEND;
                IF new_state = cmc$off THEN
                  cmp$release_channel_resource (physical_channel, iou_number, status);
                  IF NOT status.normal THEN
                    EXIT /main_program/;
                  IFEND;
                IFEND;
              ELSEIF (new_state = cmc$down) AND (current_state = cmc$off) THEN
                cmp$clear_ppit (channel_definition.element_name, channel_definition.data_channel.iou,
                      status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;

                cmp$reacquire_resources (dsc$rrt_get_channel, physical_channel, iou_number,
                      cmc$null_equipment_number, cmc$null_unit_number, driver_name, pp_table_rma,
                      controller_type, FALSE, status);
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;

              ELSEIF (new_state = cmc$on) THEN
                IF current_state = cmc$off THEN
                  cmp$reacquire_resources (dsc$rrt_get_channel, physical_channel, iou_number,
                        cmc$null_equipment_number, cmc$null_unit_number, driver_name, pp_table_rma,
                        controller_type, TRUE, status);
                ELSEIF current_state = cmc$down THEN
                  cmp$reacquire_resources (dsc$rrt_get_pp, physical_channel, iou_number,
                        cmc$null_equipment_number, cmc$null_unit_number, driver_name, pp_table_rma,
                        controller_type, TRUE, status);
                IFEND;
                IF NOT status.normal THEN
                  EXIT /main_program/;
                IFEND;
              IFEND;
              resources_released := TRUE;
            IFEND; { NOT resources_released }
            cmp$lock_lun_entry (logical_unit_number, lock_obtained);

            IF NOT lock_obtained THEN
              osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unable_to_access_lut, 'set',
                    status);
              osp$append_status_integer (osc$status_parameter_delimiter, logical_unit_number, 16, TRUE,
                    status);
              EXIT /main_program/;
            IFEND;

            IF new_state = cmc$on THEN
              cmp$disable_unit (logical_unit_number);
            ELSE
              cmp$enable_unit (logical_unit_number);
            IFEND;

            cmp$update_logical_unit_table (logical_unit_number, new_state, status);
            IF NOT status.normal THEN
              EXIT /main_program/;
            IFEND;

            cmp$unlock_lun_entry (logical_unit_number, lock_obtained);
            IF NOT lock_obtained THEN
              osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unable_to_access_lut, 'clear',
                    status);
              osp$append_status_integer (osc$status_parameter_delimiter, logical_unit_number, 16, TRUE,
                    status);
              EXIT /main_program/;
            IFEND;
          IFEND;
        FOREND;
      IFEND;
    END /main_program/;

  PROCEND cmp$change_ext_cpu_state;

?? TITLE := '  cmp$check_alternate_path ', EJECT ??

  PROCEDURE cmp$check_alternate_path (element : cmt$element_definition;
          upline_element : cmt$element_definition;
          data_channel : cmt$data_channel_definition;
      VAR alternate_path_active : BOOLEAN;
      VAR alternate_access_type: cmt$element_type;
      VAR status : ost$status);

      VAR
        channel_element_p : ^cmt$element_definition,
        controller_state: cmt$element_state,
        ct_element_p : ^cmt$element_definition,
        iou_number : dst$iou_number,
        i : cmt$data_storage_port_number,
        iou_name : cmt$element_name,
        mainframe_id : pmt$mainframe_id,
        pp_not_active: boolean,
        upline_index : cmt$controller_port_number;

{  PURPOSE : This procedure figures out whether an element of type
{      cmc$storage_device_element has an alternate active path.
{

       status.normal := TRUE;
       alternate_path_active := FALSE;
       ct_element_p := NIL;
       pmp$get_mainframe_id (mainframe_id, status);
       IF NOT status.normal THEN
         RETURN;
       IFEND;
       IF element.element_type = cmc$storage_device_element THEN
         FOR i := LOWERVALUE(cmt$data_storage_port_number) TO UPPERVALUE
                     (cmt$data_storage_port_number) DO
           IF element.storage_device.connection.port [i].configured THEN
             IF element.storage_device.connection.port [i].upline_connection_type =
                          cmc$controller_element THEN
               cmp$get_element_state (element.storage_device.connection.port [i].
                      element_name, iou_name, controller_state, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;

               IF (element.storage_device.connection.port [i].element_name <>
                      upline_element.element_name) AND (controller_state = cmc$on) THEN

                 cmp$pc_get_element (element.storage_device.connection.port [i].
                        element_name, iou_name, ct_element_p, status);
                 IF NOT status.normal THEN
                   RETURN;
                 IFEND;

    { Found another controller connected to this unit. Now get the
    { state of all element on the upline connection of the controller.

                 FOR upline_index := LOWERVALUE(cmt$controller_port_number) TO UPPERVALUE
                           (cmt$controller_port_number) DO
                   IF ct_element_p^.controller.connection.port [upline_index].configured THEN
                     IF (ct_element_p^.controller.connection.port [upline_index].
                               upline_connection_type = cmc$data_channel_element) AND
                               (ct_element_p^.controller.connection.port [upline_index].
                               mainframe_ownership = mainframe_id) THEN
                       cmp$pc_get_element (ct_element_p^.controller.connection.port [upline_index].
                             element_name, ct_element_p^.controller.connection.port [upline_index].
                                   iou, channel_element_p, status);
                       IF NOT status.normal THEN
                         RETURN;
                       IFEND;
                       cmp$convert_iou_name (ct_element_p^.controller.connection.port [upline_index].
                                   iou, iou_number, status);
                       IF NOT status.normal THEN
                         RETURN;
                       IFEND;
                       determine_if_pp_not_active (channel_element_p^.data_channel.number,
                             channel_element_p^.data_channel.port, channel_element_p^.data_channel.concurrent,
                             iou_number, pp_not_active);
                       IF NOT pp_not_active THEN
                         alternate_path_active := TRUE;
                         alternate_access_type := cmc$controller_element;
                         RETURN;
                       IFEND;
                     IFEND;
                   IFEND;
                 FOREND;
               IFEND;
             IFEND;  { Upline connection is a controller }
          IFEND; { Upline connection is configured }
        FOREND; { Loop Through upline connection of unit }

        IF (ct_element_p = NIL) AND (upline_element.element_type = cmc$controller_element) THEN
          ct_element_p := ^upline_element;
        ELSE
          RETURN;
        IFEND;

 { If control gets here, there is no dual controller acces. See if there
 { is dual channel access.

        FOR upline_index := LOWERVALUE(cmt$controller_port_number) TO UPPERVALUE
                    (cmt$controller_port_number) DO
           IF ct_element_p^.controller.connection.port [upline_index].configured THEN
             IF (ct_element_p^.controller.connection.port [upline_index].
                       upline_connection_type = cmc$data_channel_element) AND
                       (ct_element_p^.controller.connection.port [upline_index].
                       mainframe_ownership = mainframe_id) THEN
               cmp$pc_get_element (ct_element_p^.controller.connection.port [upline_index].
                     element_name, ct_element_p^.controller.connection.port [upline_index].
                           iou, channel_element_p, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;
               IF (channel_element_p^ .data_channel.number <> data_channel.number) OR
                      (channel_element_p^ .data_channel.concurrent <> data_channel.concurrent)
                      OR (channel_element_p^ .data_channel.iou <> data_channel.iou) THEN
                 cmp$convert_iou_name (ct_element_p^.controller.connection.port [upline_index].
                           iou, iou_number, status);
                 IF NOT status.normal THEN
                   RETURN;
                 IFEND;
                 determine_if_pp_not_active (channel_element_p^.data_channel.number,
                       channel_element_p^.data_channel.port, channel_element_p^.data_channel.concurrent,
                       iou_number, pp_not_active);
                 IF NOT pp_not_active THEN
                   alternate_path_active := TRUE;
                   alternate_access_type := cmc$data_channel_element;
                   RETURN;
                 IFEND;
               IFEND;
             IFEND;
           IFEND;
         FOREND;
       IFEND; { Element is a storage device element }

  PROCEND cmp$check_alternate_path;

?? TITLE := '  cmp$change_disk_element_state', EJECT ??

  PROCEDURE cmp$change_disk_element_state (
       element_definition : cmt$element_definition;
       controller_type : cmt$controller_type;
       system_critical_element : boolean;
       logical_pp : iot$pp_number;
       channel_number : cmt$physical_channel;
       iou_number: dst$iou_number;
       new_state : cmt$element_state;
   VAR logical_unit_number : iot$logical_unit;
   VAR status : ost$status);

   VAR
     ct_element_p : ^cmt$element_definition,
     equipment_number : cmt$physical_equipment_number,
     ignore_status : ost$status,
     iou_name : cmt$element_name,
     path_active : boolean,
     pen : cmt$physical_equipment_number,
     physical_channel : cmt$physical_channel,
     port : integer,
     pp_acquired : ^ARRAY [ * ] OF pps_acquired_info,
     pp_not_active: boolean,
     pp_released : ^ARRAY [ * ] OF pps_released_info,
     pun : cmt$physical_unit_number,
     sd_element_p : ^cmt$element_definition,
     state : cmt$element_state;

{ PURPOSE : This procedure change the state of MASS storage devices.

     status.normal := TRUE;
     equipment_number := 0;
     PUSH pp_acquired: [LOWERVALUE (cmt$max_channels_per_storage) .. UPPERVALUE
             (cmt$max_channels_per_storage)];
     PUSH pp_released: [LOWERVALUE (cmt$controller_port_number) .. UPPERVALUE
             (cmt$controller_port_number)];

   /main_program/
     BEGIN
       IF element_definition.element_type = cmc$storage_device_element THEN
         cmp$get_logical_unit_number (
            element_definition.element_name, logical_unit_number, status);
         IF NOT status.normal THEN
           EXIT /main_program/;
         IFEND;
         equipment_number := cmv$logical_pp_table_p^ [logical_pp].pp_info.pp_interface_table_p^.
               unit_descriptors[logical_unit_number].physical_path.controller_number;
       ELSEIF element_definition.element_type = cmc$controller_element THEN
         equipment_number := element_definition.controller.physical_equipment_number;
       IFEND;
       IF new_state = cmc$on THEN

{ Acquire and deadstart PP(s) for channel(s) if at least
{ one path to the unit has all its elements in the ON state

         cmp$active_path (element_definition, controller_type, pp_acquired^, status);
         IF NOT status.normal THEN
           EXIT /main_program/;
         IFEND;

         FOR port := LOWERVALUE (cmt$max_channels_per_storage) TO
                       UPPERVALUE (cmt$max_channels_per_storage) DO
           IF pp_acquired^ [port].acquired THEN
             cmp$reacquire_resources (dsc$rrt_get_pp, pp_acquired^ [port].channel,
               pp_acquired^ [port].iou, cmc$null_equipment_number, cmc$null_unit_number,
                 pp_acquired^ [port].driver_name, pp_acquired^ [port].pp_table_rma,
                   pp_acquired^ [port].controller_type, TRUE, status);
             IF NOT status.normal THEN
               EXIT /main_program/;
             IFEND;

           IFEND;
         FOREND;
       IFEND;

{ Call monitor to propose disabling/enabling of units

       cmp$change_state_r1 (element_definition.element_name,
             element_definition.element_type, controller_type, system_critical_element,
             new_state, iou_number, logical_pp,
             channel_number, equipment_number, logical_unit_number, status);
       IF NOT status.normal THEN
         IF new_state = cmc$on THEN

 { Undo - Release above acquired PP(s)

           FOR port := LOWERVALUE (cmt$max_channels_per_storage) TO
                         UPPERVALUE (cmt$max_channels_per_storage) DO
             IF pp_acquired^ [port].acquired THEN
               cmp$release_pp_by_channel (pp_acquired^ [port].channel, pp_acquired^ [port].iou,
                     ignore_status);
             IFEND;
           FOREND;

         IFEND;
         EXIT /main_program/;
       IFEND;


       IF (new_state = cmc$off) OR (new_state = cmc$down) THEN
         IF element_definition.element_type = cmc$controller_element THEN

   { Release PP(s) for channel if no more controllers are ON

           cmp$unactive_path (element_definition, pp_released^, status);
           IF NOT status.normal THEN
             EXIT /main_program/;
           IFEND;
           FOR port := LOWERVALUE (cmt$controller_port_number) TO
                         UPPERVALUE (cmt$controller_port_number) DO
             IF pp_released^ [port].released THEN
               cmp$release_pp_by_channel (pp_released^ [port].channel, pp_released^ [port].iou, status);
               IF NOT status.normal THEN
                 EXIT /main_program/;
               IFEND;
               cmp$convert_iou_number (pp_released^ [port].iou, iou_name, status);
               IF NOT status.normal THEN
                 EXIT /main_program/;
               IFEND;
               cmp$clear_ppit (pp_released^ [port].channel_name, iou_name, status);
               IF NOT status.normal THEN
                 EXIT /main_program/;
               IFEND;
             IFEND;
           FOREND;
         ELSEIF element_definition.element_type = cmc$data_channel_element THEN

   { Release PP for channel

           determine_if_pp_not_active (element_definition.data_channel.number,
                 element_definition.data_channel.port, element_definition.data_channel.concurrent,
                 iou_number, pp_not_active);
           IF NOT pp_not_active THEN
             physical_channel.number := element_definition.data_channel.number;
             physical_channel.concurrent := element_definition.data_channel.concurrent;
             physical_channel.port := element_definition.data_channel.port;

             cmp$release_pp_by_channel (physical_channel, iou_number, status);
             IF NOT status.normal THEN
               EXIT /main_program/;
             IFEND;

             cmp$clear_ppit (element_definition.element_name, element_definition.data_channel.iou,
                  status);
           IFEND;
         IFEND;
       IFEND;
     END /main_program/;

{ Need to ensure we have all the necessary statistics allocated. I do this here until I figure out
{ how to properly handle the redundant/alternate access situation when one controller is down during
{ Deadstart.

     IF status.normal AND (new_state = cmc$on) THEN
       iop$update_usage_allocation (status);
     IFEND;

   PROCEND cmp$change_disk_element_state;

?? TITLE := '  cmp$change_tape_unit_state ', EJECT ??

  PROCEDURE cmp$change_tape_unit_state
    (    element_definition: cmt$element_definition;
         current_state: cmt$element_state;
         new_state: cmt$element_state;
         channel: cmt$element_definition;
         equipment_number: cmt$physical_equipment_number;
         controller_type: cmt$controller_type;
         driver_name: pmt$program_name;
         system_call: boolean;
         logical_unit_number: iot$logical_unit;
         logical_unit_state: cmt$element_state;
     VAR channel_released: boolean;
     VAR status: ost$status);

    VAR
      iou_number: dst$iou_number,
      lock_obtained: boolean,
      lock_set: boolean,
      lut_state: cmt$element_state,
      physical_channel: cmt$physical_channel,
      pp_table_rma: ost$real_memory_address,
      unit_number: cmt$physical_unit_number;

{ PURPOSE: This procedure update the logical unit table and the
{   system tape table . It assumes the given element is a tape unit.

    status.normal := TRUE;
    lock_set := FALSE;
    channel_released := FALSE;
  /main_program/
    BEGIN

      cmp$convert_iou_name (channel.data_channel.iou, iou_number, status);
      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;

      unit_number := element_definition.storage_device.physical_unit_number;

      cmp$lock_lun_entry (logical_unit_number, lock_obtained);
      IF NOT lock_obtained THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unable_to_access_lut, 'set',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, logical_unit_number, 16, TRUE, status);
        EXIT /main_program/;
      IFEND;
      lock_set := TRUE;

      IF (new_state = cmc$off) OR (new_state = cmc$down) THEN
        IF cmv$logical_unit_table^ [logical_unit_number].status.assigned THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unit_already_assigned,
                element_definition.element_name, status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                cmv$logical_unit_table^ [logical_unit_number].status.assigned_jsn, status);
          EXIT /main_program/;
        IFEND;
      IFEND;

 { Update logical unit table and system tape table }

      physical_channel.number := channel.data_channel.number;
      physical_channel.concurrent := channel.data_channel.concurrent;
      physical_channel.port := channel.data_channel.port;
      IF (((new_state = cmc$off) OR (new_state = cmc$down)) AND (current_state=cmc$on)) OR
             ((new_state = cmc$off) AND (current_state = cmc$down)) THEN
        cmp$disable_unit (logical_unit_number);
        IF (new_state = cmc$off) AND (logical_unit_state <> cmc$off) THEN
          IF (controller_type <> cmc$mt5698_xx) AND NOT(((controller_type = cmc$mt698_xx)
             OR (controller_type = cmc$mt5680_xx)) AND
               (osv$170_os_type = osc$ot7_dual_state_nos_be)) THEN

            cmp$release_equipment_resource (physical_channel, iou_number, equipment_number, unit_number);
            IF physical_channel.concurrent THEN
              channel_released := TRUE;
            IFEND;
          IFEND;
        IFEND;

      ELSEIF (((new_state = cmc$on) OR (new_state=cmc$down)) AND (current_state = cmc$off)) THEN
        IF (controller_type <> cmc$mt5698_xx) AND NOT((controller_type = cmc$mt698_xx) AND
               (osv$170_os_type = osc$ot7_dual_state_nos_be)) AND
               (controller_type <> cmc$mt5680_xx) THEN
          cmp$reacquire_resources (dsc$rrt_get_equipment, physical_channel,
             iou_number, equipment_number, unit_number,
             driver_name, pp_table_rma, controller_type, FALSE, status);
          IF NOT status.normal THEN
            EXIT /main_program/;
          IFEND;
        IFEND;
        IF new_state = cmc$on THEN
          cmp$enable_unit (logical_unit_number);
        IFEND;
      ELSEIF (new_state = cmc$on) AND (current_state = cmc$down) THEN
        cmp$enable_unit (logical_unit_number);
      IFEND;

      cmp$update_logical_unit_table (logical_unit_number, new_state, status);
      IF NOT status.normal THEN
        EXIT /main_program/;
      IFEND;
      REPEAT
        dmp$update_stt (logical_unit_number, logical_unit_state, new_state, status);
        IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
          pmp$wait (one_second, one_second);
        IFEND;
      UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
    END /main_program/;
    IF lock_set THEN
      cmp$unlock_lun_entry (logical_unit_number, lock_obtained);
      IF (lock_obtained = FALSE) AND (status.normal) THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_unable_to_access_lut, 'clear',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, logical_unit_number, 16, TRUE, status);
      IFEND;
    IFEND;

  PROCEND cmp$change_tape_unit_state;

?? TITLE := '  cmp$check_lcu_lock_set', EJECT ??

{ PURPOSE:
{   This procedure checks the LCU lock.

  PROCEDURE [XDCL, #GATE] cmp$check_lcu_lock_set (
     VAR status: ost$status);

    VAR
      lock_set: boolean,
      job_name: jmt$system_supplied_name;

    status.normal := TRUE;
    cmp$lcu_lock_set_by_job (job_name, lock_set);
    IF lock_set THEN
      osp$set_status_abnormal (cmc$configuration_management_id,
           cme$lcu_still_active, job_name, status);
    IFEND;

  PROCEND cmp$check_lcu_lock_set;

?? TITLE := '  cmp$process_outstanding_sc_req', EJECT ??

{ PURPOSE:
{   This procedure looks for outstanding state change requests
{   and processes them.

  PROCEDURE [XDCL, #GATE] cmp$process_outstanding_sc_req
    (VAR lock_control: cmt$lcu_lock_control;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      current_state: cmt$element_state,
      element: cmt$element_descriptor,
      local_status: ost$status,
      lock_type: cmt$lcu_lock_type,
      new_state: cmt$element_state,
      outstanding_request: boolean,
      tape_subsystem: boolean;

    #CALLER_ID (caller_id);
    status.normal := TRUE;
    IF NOT (avp$capabilities_active_any ($avt$conditional_capabilities
          [avc$cc_configuration_admin, avc$cc_removable_media_operator, avc$cc_system_operator]) OR
          (caller_id.ring <= 6)) THEN
      osp$set_status_abnormal ('OF', ofe$sou_not_active,
            'configuration_administration, removable_media_operation or system_operation', status);
      RETURN; {----->
    IFEND;

    REPEAT
      cmp$find_state_change_request (outstanding_request, element, new_state, current_state);
      IF outstanding_request THEN
        cmp$determine_tape_element (element, tape_subsystem);
        IF tape_subsystem THEN
          lock_type := cmc$removable_media_operation;
        ELSE
          lock_type := cmc$configuration_administrator;
        IFEND;

        cmp$manage_lock_r3 (lock_type, cmc$llo_set_lock, lock_control, status);
        IF status.normal THEN
          p$process_state_change (tape_subsystem, {system_call=} TRUE, outstanding_request, element, FALSE,
                current_state, new_state, caller_id.ring, lock_control, status);
          IF NOT status.normal THEN
            osp$generate_error_message (status, local_status);
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status, local_status);
          IFEND;

          IF lock_control.controls [lock_type].lock_set_by_this_instance THEN
            cmp$manage_lock_r3 (lock_type, cmc$llo_clear_lock, lock_control, status);
            IF NOT status.normal THEN
              osp$generate_error_message (status, local_status);
              osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status,
                    local_status);
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    UNTIL (NOT outstanding_request) OR (NOT status.normal);

{NOTE: We may lose outstanding requests when we did not get the lock!

  PROCEND cmp$process_outstanding_sc_req;
?? OLDTITLE ??
?? NEWTITLE := 'CMP$PROCESS_STATE_CHANGE', EJECT ??

  PROCEDURE [XDCL, #GATE] cmp$process_state_change
    (    tape_element: boolean;
         system_caller: boolean;
         element_descriptor: cmt$element_descriptor;
         system_critical_element: boolean;
         current_element_state: cmt$element_state;
         new_element_state: cmt$element_state;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      current_state: cmt$element_state,
      element: cmt$element_descriptor,
      lock_control: cmt$lcu_lock_control,
      new_state: cmt$element_state,
      outstanding_request: boolean,
      system_call: boolean,
      tape_subsystem: boolean;

?? NEWTITLE := 'P$CLEAR_LCU_LOCKS', EJECT ??

    PROCEDURE p$clear_lcu_locks
      (VAR lock_control: cmt$lcu_lock_control);

      VAR
        local_status: ost$status;

      IF lock_control.controls [cmc$configuration_administrator].lock_set_by_this_instance THEN
        cmp$manage_lock_r3 (cmc$configuration_administrator, cmc$llo_clear_lock, lock_control, local_status);
      IFEND;

      IF lock_control.controls [cmc$removable_media_operation].lock_set_by_this_instance THEN
        cmp$manage_lock_r3 (cmc$removable_media_operation, cmc$llo_clear_lock, lock_control, local_status);
      IFEND;

    PROCEND p$clear_lcu_locks;
?? OLDTITLE ??
?? EJECT ??
    #CALLER_ID (caller_id);
    status.normal := TRUE;

    IF NOT (avp$capabilities_active_any ($avt$conditional_capabilities
          [avc$cc_configuration_admin, avc$cc_removable_media_operator, avc$cc_system_operator]) OR
          (caller_id.ring <= 6)) THEN
      osp$set_status_abnormal ('OF', ofe$sou_not_active,
            'configuration_administration, removable_media_operation or system_operation', status);
      RETURN; {----->
    IFEND;

    new_state := new_element_state;
    current_state := current_element_state;
    tape_subsystem := tape_element;
    outstanding_request := FALSE;
    element := element_descriptor;
    system_call := system_caller;

    lock_control.system_activity_set := FALSE;
    lock_control.controls [cmc$configuration_administrator].lock_set := FALSE;
    lock_control.controls [cmc$configuration_administrator].lock_set_by_this_instance := FALSE;
    lock_control.controls [cmc$removable_media_operation].lock_set := FALSE;
    lock_control.controls [cmc$removable_media_operation].lock_set_by_this_instance := FALSE;


  /main_program/
    REPEAT
      p$process_state_change (tape_subsystem, system_call, outstanding_request, element,
            system_critical_element {wrong for outstanding requests!} , current_state, new_state,
            caller_id.ring, lock_control, status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      p$clear_lcu_locks (lock_control);

      cmp$find_state_change_request (outstanding_request, element, new_state, current_state);
      IF outstanding_request THEN
        system_call := TRUE;
        cmp$determine_tape_element (element, tape_subsystem);
      IFEND;
    UNTIL (outstanding_request = FALSE); {/main_program/

    p$clear_lcu_locks (lock_control);

  PROCEND cmp$process_state_change;
?? OLDTITLE ??
?? NEWTITLE := 'CMP$LCU_PROCESS_STATE_CHANGE', EJECT ??

  PROCEDURE [XDCL, #GATE] cmp$lcu_process_state_change
    (    tape_element: boolean;
         system_caller: boolean;
         element_descriptor: cmt$element_descriptor;
         system_critical_element: boolean;
         current_element_state: cmt$element_state;
         new_element_state: cmt$element_state;
     VAR lock_control: cmt$lcu_lock_control;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier;

    #CALLER_ID (caller_id);
    status.normal := TRUE;
    p$process_state_change (tape_element, system_caller, FALSE {= no outstanding request} ,
          element_descriptor, system_critical_element, current_element_state, new_element_state,
          caller_id.ring, lock_control, status);

  PROCEND cmp$lcu_process_state_change;
?? TITLE := '  cmp$process_netw_element_state ', EJECT ??

  PROCEDURE cmp$process_netw_element_state (element_definition : cmt$element_definition;
         element_descriptor : cmt$element_descriptor;
         current_state : cmt$element_state;
         new_state : cmt$element_state;
     VAR status : ost$status);

     VAR
       state : cmt$element_state,
       mainframe_id: pmt$mainframe_id,
       iou_name : cmt$element_name,
       ignore_status : ost$status,
       peripheral_index : integer,
       element_reservation : cmt$element_reservation,
       comm_port : cmt$communications_port_number;

{ PURPOSE: This procedure change the state of communications and
{   channel adapter elements.

     status.normal := TRUE;
   /main_program/
     BEGIN
       pmp$get_mainframe_id (mainframe_id, status);
       IF NOT status.normal THEN
         EXIT /main_program/;
       IFEND;

       IF element_definition.element_type = cmc$communications_element THEN
         IF (element_definition.product_id.product_number = ' $2620') OR
             (element_definition.product_id.product_number = ' $4000') OR
             (element_definition.product_id.product_number = ' $2621') THEN

           { Check states of MDI/MTI/EXPRESSLINK channel and device before call NAM/VE. }

           /communications_loop/
           FOR comm_port := LOWERVALUE (cmt$communications_port_number) TO
                              UPPERVALUE (cmt$communications_port_number) DO
             IF (element_definition.communications_element.connection.port [comm_port].configured) AND
                 (element_definition.communications_element.connection.port [comm_port].mainframe_ownership
                  = mainframe_id) THEN
               cmp$get_element_state (element_definition.
                 communications_element.connection.port [comm_port].element_name,
                 element_definition.communications_element.connection.port [comm_port].iou,
                 state, status);
               IF NOT status.normal THEN
                 EXIT /main_program/;
               IFEND;
               EXIT /communications_loop/;
             IFEND;
           FOREND /communications_loop/;

           IF current_state = cmc$on THEN
             IF state = cmc$on THEN
               nap$change_network_device_state (
                 element_definition.element_name, new_state, current_state, status);
               IF NOT status.normal THEN
                 osp$generate_log_message (
                   $pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
                 EXIT /main_program/;
               IFEND;
             IFEND;
           ELSE
             IF state = cmc$on THEN
               IF new_state = cmc$on THEN

                 { Turn ON MDI/MTI/EXPRESSLINK for NAM/VE to reserve it. }

                 cmp$change_state_info_table (element_definition.element_name,iou_name, new_state, status);
                 IF NOT status.normal THEN
                   EXIT /main_program/;
                 IFEND;

                 nap$change_network_device_state (
                   element_definition.element_name, new_state, current_state, status);
                 IF NOT status.normal THEN
                   osp$generate_log_message (
                     $pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
                   ignore_status.normal := TRUE;
                   cmp$change_state_info_table (
                     element_definition.element_name, iou_name, current_state, ignore_status);
                   EXIT /main_program/;
                 IFEND;
               IFEND;
             IFEND;
           IFEND;

         ELSE

           { For communication elements other than MDI/MTI/EXPRESSLINK. }
           { For File Server element, will need to call dfp$ interface

           check_for_element_reservation (element_descriptor, status);
           IF NOT status.normal THEN
             EXIT /main_program/;
           IFEND;
         IFEND;

       ELSEIF element_definition.element_type = cmc$channel_adapter_element THEN
         IF element_definition.product_id.product_number = ' $2629' THEN

           { Check states of ICA channel and ICA before call NAM/VE. }

           IF element_definition.channel_adapter.connection.channel.configured THEN
             cmp$get_element_state (element_definition.
               channel_adapter.connection.channel.element_name,
               element_definition.channel_adapter.connection.channel.iou, state,
                 status);
             IF NOT status.normal THEN
               EXIT /main_program/;
             IFEND;
           IFEND;

           IF current_state = cmc$on THEN
             IF state = cmc$on THEN
               nap$change_network_device_state (
                 element_definition.element_name, new_state, current_state, status);
               IF NOT status.normal THEN
                 osp$generate_log_message (
                   $pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
                 EXIT /main_program/;
               IFEND;
             IFEND;
           ELSE
             IF state = cmc$on THEN
               IF new_state = cmc$on THEN
                 { Turn ON ICA for NAM/VE to reserve it. }

                 cmp$change_state_info_table (element_definition.element_name, iou_name,new_state, status);
                 IF NOT status.normal THEN
                   EXIT /main_program/;
                 IFEND;

                 nap$change_network_device_state (
                   element_definition.element_name, new_state, current_state, status);
                 IF NOT status.normal THEN
                   osp$generate_log_message (
                     $pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
                   ignore_status.normal := TRUE;
                   cmp$change_state_info_table (
                     element_definition.element_name, iou_name, current_state, ignore_status);
                   EXIT /main_program/;
                 IFEND;
               IFEND;
             IFEND;
           IFEND;
         IFEND;
       IFEND;
    END /main_program/;

  PROCEND cmp$process_netw_element_state;

?? TITLE := ' cmp$return_desc_data_by_lun_lpn', EJECT ??

  PROCEDURE [XDCL, #GATE] cmp$return_desc_data_by_lun_lpn (
      logical_unit_number : iot$logical_unit;
      logical_pp_number : iot$pp_number;
    VAR iou_number : dst$iou_number;
    VAR descriptor_data: ost$string;
    VAR physical_pp_number: 0 .. 31);

    PROCEDURE [INLINE] append_string_data (string_data: string ( * <= 31));
      descriptor_data.value (index, * ) := string_data;
      WHILE (descriptor_data.value (index, 1) <> ' ') DO
        index := index + 1;
      WHILEND;
    PROCEND append_string_data;

    VAR
      compn : cmt$communications_port_number,
      concurrent: boolean,
      pp_string: string (10),
      length,
      index : integer,
      status : ost$status,
      mainframe_element,
      channel_element : ^cmt$element_definition,
      mainframe_id : pmt$mainframe_id,
      mainframe_name,
      iou_name,
      channel_name,
      element_name : cmt$element_name;
{
{ PURPOSE:  This routine return a string containing physical pp number,
{    channel, iou, mainframe and element name given the logical unit
{    number and the logical pp number.
{
{ NOTE: This routine is mainly called by NAM/VE, RHFAM and any of the
{    users of cmp$reserve_element, cmp$execute_pp_program.
{

    PUSH mainframe_element;
    PUSH channel_element;
    descriptor_data.value := ' ';
    descriptor_data.size := 0;
    cmp$pc_get_logical_unit (logical_unit_number, mainframe_element, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    element_name := mainframe_element ^.element_name;
    pmp$get_mainframe_id (mainframe_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    CASE mainframe_element ^.element_type OF
    = cmc$channel_adapter_element =
      IF (mainframe_element^.channel_adapter.connection.channel.configured) AND
         (mainframe_element^.channel_adapter.connection.channel.mainframe_ownership =
               mainframe_id) THEN
        channel_name := mainframe_element ^.channel_adapter.connection.channel.element_name;
        mainframe_name := mainframe_element ^.channel_adapter.connection.channel.mainframe_ownership;
        iou_name := mainframe_element^ .channel_adapter.connection.channel.iou;
        cmp$pc_get_element (channel_name,iou_name, channel_element, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        cmp$convert_iou_name (iou_name, iou_number, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        physical_pp_number := cmv$logical_pp_table_p^ [logical_pp_number].pp_info.physical_pp.number;
        pp_string := '      ';
        STRINGREP (pp_string, length, physical_pp_number);
        index := 1;
        append_string_data (mainframe_name);
        append_string_data ('. ');
        append_string_data (iou_name);
        IF cmv$logical_pp_table_p^ [logical_pp_number].pp_info.physical_pp.channel_protocol = dsc$cpt_nio THEN
          append_string_data ('.PP ');
        ELSE { cio pp
          append_string_data ('.CPP ');
        IFEND;
        append_string_data (pp_string (2, * ));
        append_string_data ('. ');
        append_string_data (channel_name);
        append_string_data ('. ');
        append_string_data (element_name);
        descriptor_data.size := index - 1;
      IFEND;

    = cmc$communications_element =
      /communications_loop/
      FOR compn := LOWERVALUE (compn) TO UPPERVALUE (compn) DO
        IF (mainframe_element ^.communications_element.connection.port [compn].configured) AND
           (mainframe_element^.communications_element.connection.port[compn].mainframe_ownership =
               mainframe_id) THEN
          channel_name :=
            mainframe_element ^.communications_element.connection.port [compn].element_name;
          mainframe_name :=
            mainframe_element ^.communications_element.connection.port [compn].mainframe_ownership;
          iou_name := mainframe_element^ .communications_element.connection.port [compn].iou;
          cmp$pc_get_element (channel_name,iou_name, channel_element, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          cmp$convert_iou_name (iou_name, iou_number, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

{ Ensure channel is the one that is currently being used by this logical PP.

          IF cmv$logical_pp_table_p^ [logical_pp_number].flags.reservd_by_other_has_ch_present THEN
            concurrent := (cmv$logical_pp_table_p^ [logical_pp_number].pp_info.channel.channel_protocol =
                  dsc$cpt_cio);
            IF NOT ((channel_element^.data_channel.number =
                  cmv$logical_pp_table_p^ [logical_pp_number].pp_info.channel.number) AND
                  (channel_element^.data_channel.concurrent = concurrent) AND
                  (iou_number =
                  cmv$logical_pp_table_p^ [logical_pp_number].pp_info.channel.iou_number)) THEN
              CYCLE /communications_loop/;
            IFEND;
          IFEND;

          physical_pp_number := cmv$logical_pp_table_p^ [logical_pp_number].pp_info.physical_pp.number;
          pp_string := '      ';
          STRINGREP (pp_string, length, physical_pp_number);
          index := 1;
          append_string_data (mainframe_name);
          append_string_data ('. ');
          append_string_data (iou_name);
          IF cmv$logical_pp_table_p^ [logical_pp_number].pp_info.physical_pp.channel_protocol =
                dsc$cpt_nio THEN
            append_string_data ('.PP ');
          ELSE { cio pp
            append_string_data ('.CPP ');
          IFEND;
          append_string_data (pp_string (2, * ));
          append_string_data ('. ');
          append_string_data (channel_name);
          append_string_data ('. ');
          append_string_data (element_name);
          descriptor_data.size := index - 1;
          EXIT /communications_loop/;
        IFEND;
      FOREND /communications_loop/;
    ELSE
      ;
    CASEND;
  PROCEND cmp$return_desc_data_by_lun_lpn;
?? TITLE := '  cmp$return_logical_pp_number ', EJECT ??

{ PURPOSE:
{   This procedure returns the logical pp number associated with a channel. It provides a ring 11 user to
{   retrieve this information by calling a ring 1 routine.

  PROCEDURE [XDCL, #GATE] cmp$return_logical_pp_number
    (    channel: cmt$element_name;
         iou: cmt$element_name;
     VAR logical_pp: iot$pp_number;
     VAR status: ost$status);

   VAR
     channel_p : ^cmt$element_definition;

   status.normal := TRUE;
   cmp$pc_get_element (channel, iou, channel_p, status);
   IF NOT status.normal THEN
     RETURN;
   IFEND;

   cmp$get_logical_pp_index (channel_p^, logical_pp, status);

  PROCEND cmp$return_logical_pp_number;
?? TITLE := ' cmp$retrieve_element_info',EJECT ??

   { PURPOSE: This procedure retrieve information about the controller
   {   and peripheral driver name of an element.

  PROCEDURE cmp$retrieve_element_info
    (    element_definition: cmt$element_definition;
     VAR driver_name: pmt$program_name;
     VAR controller_type: cmt$controller_type;
     VAR status: ost$status);

      VAR
        data_storage_index : cmt$data_storage_port_number,
        element_def: ^cmt$element_definition,
        iou_name : cmt$element_name,
        ignore_status : ost$status,
        mainframe_id : pmt$mainframe_id,
        mf_element : ^cmt$element_definition,
        pen : cmt$physical_equipment_number,
        port : cmt$controller_port_number,
        pun : cmt$physical_equipment_number,
        unit_element: ^cmt$element_definition;


        status.normal := TRUE;
        pmp$get_mainframe_id (mainframe_id, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      /main_program/
         BEGIN

      { Validate element type and get full physical path. }

        CASE element_definition.element_type OF

        = cmc$data_channel_element =

 { ignore_status is used if PPIT is not built at deadstart }

        /for_loop1/
          FOR pen := LOWERVALUE (cmt$physical_equipment_number) TO UPPERVALUE
                       (cmt$physical_equipment_number) DO
            IF (element_definition.data_channel.connection.equipment [pen].configured) THEN
              cmp$pc_get_element (element_definition.data_channel.connection.equipment
                    [pen].element_name, iou_name, mf_element, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;
              EXIT /for_loop1/;
            IFEND;
          FOREND /for_loop1/;

          IF mf_element^.element_type = cmc$external_processor_element THEN
            driver_name := mf_element^.external_processor.peripheral_driver_name;
          ELSEIF mf_element^.element_type = cmc$controller_element THEN
            driver_name := mf_element^.controller.peripheral_driver_name;
          ELSEIF mf_element^.element_type = cmc$storage_device_element THEN
            IF mf_element ^.product_id.product_number = '  $887' THEN
              controller_type := cmc$mshydra_ct;
              EXIT /main_program/;
            IFEND;
          ELSEIF mf_element^.element_type = cmc$communications_element THEN
            driver_name := mf_element^.communications_element.peripheral_driver_name;
          ELSEIF mf_element^.element_type = cmc$channel_adapter_element THEN
            driver_name := mf_element^.channel_adapter.peripheral_driver_name;
          IFEND;
          cmp$get_controller_type (mf_element^.product_id, controller_type, status);
          IF NOT status.normal THEN
            EXIT /main_program/;
          IFEND;

        = cmc$channel_adapter_element, cmc$communications_element =
              ;
        = cmc$controller_element =
          driver_name := element_definition.controller.peripheral_driver_name;
          cmp$get_controller_type (element_definition.product_id, controller_type, status);
          IF NOT status.normal THEN
            EXIT /main_program/;
          IFEND;

        = cmc$storage_device_element =
          FOR data_storage_index := LOWERVALUE (cmt$data_storage_port_number) TO
                UPPERVALUE (cmt$data_storage_port_number) DO
            IF element_definition.storage_device.connection.port [data_storage_index].configured THEN
              IF element_definition.storage_device.connection.port [data_storage_index].
                   upline_connection_type = cmc$data_channel_element THEN
                iou_name := element_definition.storage_device.connection.port [data_storage_index]
                       .iou;
              IFEND;
              cmp$pc_get_element (element_definition.storage_device.connection.port
                [data_storage_index].element_name, iou_name, mf_element, status);
              IF NOT status.normal THEN
                EXIT /main_program/;
              IFEND;

              IF element_definition.product_id.product_number = '  $887' THEN
                driver_name := 'E9S887';
                controller_type := cmc$mshydra_ct;
                EXIT /main_program/;
              IFEND;

              driver_name := mf_element^.controller.peripheral_driver_name;
              cmp$get_controller_type (mf_element^.product_id,
                         controller_type, status);
              EXIT /main_program/;
            IFEND;
          FOREND;
        = cmc$external_processor_element =
          cmp$get_controller_type (element_definition.product_id, controller_type,
              status);
          IF NOT status.normal THEN
            EXIT /main_program/;
          IFEND;
          driver_name := element_definition.external_processor.peripheral_driver_name;
        ELSE
          osp$set_status_abnormal (cmc$configuration_management_id, cme$jtd_invalid_state_change,
               'State change unsupported for this type of element.', status);
          EXIT /main_program/;

        CASEND;

      END /main_program/;


  PROCEND cmp$retrieve_element_info;
?? TITLE := 'determine_if_pp_not_active', EJECT ??

{ PURPOSE:
{   This procedure determines whether or not a PP is currently assigned to a given channel.

  PROCEDURE determine_if_pp_not_active
    (    number: ost$physical_channel_number;
         port: cmt$channel_port;
         concurrent: boolean;
         iou_number: dst$iou_number;
     VAR pp_not_active: boolean);

    VAR
      channel: cmt$physical_channel,
      local_status: ost$status,
      logical_pp_index: iot$pp_number,
      partner_pp_index: iot$pp_number;

    pp_not_active := FALSE;
    channel.number := number;
    channel.port := port;
    channel.concurrent := concurrent;
    cmp$retrieve_logical_pp_index (channel, iou_number, cmv$logical_pp_table_p, logical_pp_index,
          local_status);
    IF local_status.normal THEN
      partner_pp_index := cmv$logical_pp_table_p^ [logical_pp_index].pp_info.logical_partner_pp_index;
      IF partner_pp_index > 0 THEN
        pp_not_active := NOT cmv$logical_pp_table_p^ [logical_pp_index].flags.resources_acquired AND
              NOT cmv$logical_pp_table_p^ [partner_pp_index].flags.resources_acquired;
      ELSE
        pp_not_active := NOT cmv$logical_pp_table_p^ [logical_pp_index].flags.resources_acquired;
      IFEND;
    IFEND;

  PROCEND determine_if_pp_not_active;
?? TITLE := ' cmp$unactive_path',EJECT ??

 { PURPOSE : This procedure retrieve information necessary to release PP
 {   for active disk channels.

  PROCEDURE cmp$unactive_path (
        element_definition : cmt$element_definition;
    VAR pp_released : ARRAY [cmt$controller_port_number] OF pps_released_info;
    VAR status : ost$status);

      VAR
        channel_definition : ^cmt$element_definition,
        channel_name: cmt$element_name,
        channel_state : cmt$element_state,
        controller_type : cmt$controller_type,
        count: 0 .. 3,
        equipment_state : cmt$element_state,
        found: boolean,
        ignore_status : ost$status,
        iou_name : cmt$element_name,
        iou_number : dst$iou_number,
        logical_pp : iot$pp_number,
        loop_count : 0 .. 2,
        mainframe_id : pmt$mainframe_id,
        minus_one : integer,
        physical_channel : cmt$physical_channel,
        pp : integer,
        pen : integer,
        port : integer,
        port_used: char,
        redundant : boolean,
        string_index : 0 .. osc$max_name_size,
        temp_channel_p: ^cmt$element_definition;

      status.normal := TRUE;

      FOR port := LOWERVALUE (cmt$controller_port_number) TO
                    UPPERVALUE (cmt$controller_port_number) DO
        pp_released [port].released := FALSE;
        FOR pp := 1 TO 2 DO
          pp_released [port].logical_pp [pp] := 0;
        FOREND;
      FOREND;
      pmp$get_mainframe_id (mainframe_id, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      CASE element_definition.element_type OF
      = cmc$controller_element =
        cmp$get_controller_type (element_definition.product_id, controller_type, ignore_status);
        /channel_loop/
        FOR port := LOWERVALUE (cmt$controller_port_number) TO
                      UPPERVALUE (cmt$controller_port_number) DO
          IF (element_definition.controller.connection.port [port].configured) AND
                 (element_definition.controller.connection.port [port].mainframe_ownership
                  = mainframe_id) THEN
            cmp$get_element_state (element_definition.
              controller.connection.port [port].element_name,
                   element_definition.controller.connection.port [port].iou, channel_state, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;

            IF channel_state = cmc$on THEN
              cmp$pc_get_element (element_definition.controller.
                connection.port [port].element_name, element_definition.controller.
                 connection.port [port].iou, channel_definition, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;

              IF (channel_definition^.data_channel.concurrent) AND
                       (channel_definition^.data_channel.port <> cmc$unspecified_port) THEN
                loop_count := 2;
              ELSE
                loop_count := 1;
              IFEND;

              { Check if no controllers are ON. Take into account CIO channel with port.

              iou_name := channel_definition^.data_channel.iou;
              count := 0;
              REPEAT

                FOR pen := LOWERVALUE (cmt$physical_equipment_number) TO
                             UPPERVALUE (cmt$physical_equipment_number) DO
                  IF channel_definition ^.data_channel.connection.equipment [pen].configured THEN

                  { State of controller not updated in cmv$state_table_info yet.

                    IF channel_definition ^.data_channel.connection.
                          equipment [pen].element_name <> element_definition.element_name THEN
                      cmp$get_element_state (channel_definition ^.data_channel.
                          connection.equipment [pen].element_name, iou_name, equipment_state, status);
                      IF NOT status.normal THEN
                        RETURN;
                      IFEND;
                      IF equipment_state = cmc$on THEN
                        CYCLE /channel_loop/;
                      IFEND;
                    IFEND;
                  IFEND;
                FOREND;

 { If a CIO channel port is configured, make sure the other channel port is not configured
 { to other controllers.

                count := count + 1;
                IF (loop_count > 1) AND (count <> loop_count) THEN
                  channel_name := channel_definition^.element_name;
                  IF channel_definition^.data_channel.port = cmc$port_a THEN
                    port_used := 'B';
                  ELSEIF channel_definition^.data_channel.port = cmc$port_b THEN
                    port_used := 'A';
                  IFEND;
                  string_index := 0;
                  found := FALSE;
                  WHILE (NOT found) AND (string_index <= osc$max_name_size) DO
                    string_index := string_index + 1;
                    found := (channel_name (string_index, 1) = 'A') OR
                                  (channel_name (string_index, 1) = 'B');
                  WHILEND;
                  channel_name (string_index, 1) := port_used;
                  cmp$pc_get_element (channel_name, iou_name, temp_channel_p, ignore_status);
                  IF NOT ignore_status.normal THEN
                    count := count + 1;
                  ELSE
                    channel_definition := temp_channel_p;
                  IFEND;
                IFEND;
              UNTIL (count = loop_count);
              cmp$convert_iou_name (channel_definition^.data_channel.iou, iou_number, status);
              IF NOT status.normal THEN
                RETURN;
              IFEND;
              physical_channel.number := channel_definition^.data_channel.number;
              physical_channel.concurrent := channel_definition^.data_channel.concurrent;
              physical_channel.port := channel_definition^.data_channel.port;

 { Do not count PP and Channel in the case of multiple controller daisy chained
 { to one channel.

              IF (cmp$support_redundant_channel (controller_type)) AND (controller_type
                    <> cmc$mt5680_xx) THEN
                cmp$determine_redundant_channel (physical_channel, iou_number,
                   {ignore_state=}TRUE, redundant, ignore_status);
                IF redundant THEN
                  CYCLE /channel_loop/;
                IFEND;
              IFEND;
              cmp$get_logical_pp_index (channel_definition ^, logical_pp, status);

              IF status.normal THEN
                IF port > LOWERVALUE (cmt$controller_port_number) THEN
                  FOR minus_one := LOWERVALUE (cmt$controller_port_number) TO port - 1 DO
                    IF pp_released [minus_one].released THEN

                      IF logical_pp = pp_released [minus_one].logical_pp [1] THEN

                        { Do not release PP for CCH#(A or B) again.

                        CYCLE /channel_loop/;

                      IFEND;
                    IFEND;
                  FOREND;
                IFEND;
                pp_released [port].released := TRUE;
                pp_released [port].iou := iou_number;
                pp_released [port].channel.number := channel_definition ^.data_channel.number;
                pp_released [port].channel.concurrent := channel_definition ^.data_channel.concurrent;
                pp_released [port].channel.port := channel_definition ^.data_channel.port;
                pp_released [port].channel_name := channel_definition ^.element_name;
                pp_released [port].logical_pp [1] := logical_pp;
                IF cmv$logical_pp_table_p^ [pp_released [port].logical_pp [1]].
                      pp_info.logical_partner_pp_index > 0 THEN
                  pp_released [port].logical_pp [2] :=
                        cmv$logical_pp_table_p^ [pp_released [port].logical_pp [1]].
                        pp_info.logical_partner_pp_index;
                IFEND;
              ELSE
                RETURN;
              IFEND;
            IFEND;
          IFEND;
        FOREND /channel_loop/;

      ELSE
        ;
      CASEND;

    PROCEND cmp$unactive_path;

?? TITLE := '  check_for_element_reservation', EJECT ??

  PROCEDURE [INLINE] check_for_element_reservation
    (    element_descriptor: cmt$element_descriptor;
     VAR status: ost$status);

    VAR
      element_reservation: cmt$element_reservation,
      peripheral_index: integer;

    status.normal := TRUE;

    cmp$search_peripheral_table (element_descriptor, element_reservation, FALSE, peripheral_index, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (cmv$peripheral_element_table.pointer^ [peripheral_index].entry_interlock) THEN
      IF element_descriptor.element_type = cmc$data_channel_element THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$element_already_reserved,
              element_descriptor.channel_descriptor.name, status);
      ELSE
        osp$set_status_abnormal (cmc$configuration_management_id, cme$element_already_reserved,
              element_descriptor.peripheral_descriptor.element_name, status);
      IFEND;
      osp$append_status_parameter (osc$status_parameter_delimiter, cmv$peripheral_element_table.
            pointer^ [peripheral_index].reserved_job, status);
      RETURN;
    IFEND;
    IF cmp$dedicated_maint_active (peripheral_index) THEN
      IF element_descriptor.element_type = cmc$data_channel_element THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$element_already_reserved,
              element_descriptor.channel_descriptor.name, status);
      ELSE
        osp$set_status_abnormal (cmc$configuration_management_id, cme$element_already_reserved,
              element_descriptor.peripheral_descriptor.element_name, status);
      IFEND;
      osp$append_status_parameter (osc$status_parameter_delimiter, cmv$peripheral_element_table.
            pointer^ [peripheral_index].maintenance_activity.dedicated_accessor.job_identification, status);
      RETURN;
    IFEND;
  PROCEND check_for_element_reservation;

?? TITLE := '  count_all_units', EJECT ??

{ PURPOSE : This procedure goes through all the downline connections
{   of a channel or controller and counts the total number of units
{   configured.

  PROCEDURE count_all_units
    (    element_definition: cmt$element_definition;
     VAR number_of_units: integer);

    VAR
      controller_element_p: ^cmt$element_definition,
      ignore_status: ost$status,
      index: integer,
      iou_name: cmt$element_name,
      name_list_p: ^array [ * ] of cmt$element_name,
      number_of_entries: integer,
      pun: cmt$physical_unit_number;

    number_of_units := 0;
    IF element_definition.element_type = cmc$data_channel_element THEN
      PUSH name_list_p: [1 .. 2 * (UPPERVALUE (cmt$physical_equipment_number) + 1)];
      cmp$get_connected_elements (element_definition, name_list_p, number_of_entries, ignore_status);

      FOR index := 1 TO number_of_entries DO
        cmp$pc_get_element (name_list_p^ [index], iou_name, controller_element_p, ignore_status);
        IF ignore_status.normal THEN
          IF controller_element_p^.element_type = cmc$controller_element THEN
            FOR pun := LOWERVALUE (cmt$physical_unit_number) TO UPPERVALUE (cmt$physical_unit_number) DO
              IF controller_element_p^.controller.connection.unit [pun].configured THEN
                number_of_units := number_of_units + 1;
              IFEND;
            FOREND;
          ELSEIF controller_element_p^.element_type = cmc$storage_device_element THEN
            number_of_units := number_of_units + 1;
          IFEND;
        IFEND;
      FOREND;
    ELSEIF element_definition.element_type = cmc$controller_element THEN
      FOR pun := LOWERVALUE (cmt$physical_unit_number) TO UPPERVALUE (cmt$physical_unit_number) DO
        IF element_definition.controller.connection.unit [pun].configured THEN
          number_of_units := number_of_units + 1;
        IFEND;
      FOREND;
    IFEND;

  PROCEND count_all_units;

?? TITLE := '    find_connected_channel', EJECT ??

{ PURPOSE : This procedure will return the active channel and controller
{   for the specified element.  The element is assumed to be either a
{   controller or a mass storage device.  If no active path to the element
{   is found the first channel in the ON state will be returned and if no
{   connected channels are in the ON state the primary channel and primary
{   controller are returned.
{

  PROCEDURE find_connected_channel
    (    element_definition: cmt$element_definition;
     VAR channel: cmt$element_definition;
     VAR controller_equipment_number: cmt$physical_equipment_number;
     VAR status: ost$status);

    VAR
      active_channel_found: boolean,
      channel_controller_status: cmt$connection_status,
      channel_element_p: ^cmt$element_definition,
      channel_element_state: cmt$element_state,
      controller_element_p: ^cmt$element_definition,
      controller_unit_status: cmt$connection_status,
      data_storage_index: cmt$data_storage_port_number,
      element_descriptor: cmt$element_descriptor,
      mainframe_id: pmt$mainframe_id,
      port: cmt$controller_port_number,
      primary_channel_found: boolean,
      primary_controller_found: boolean,
      unused_iou: cmt$element_name;

    status.normal := TRUE;
    active_channel_found := FALSE;
    primary_channel_found := FALSE;
    primary_controller_found := FALSE;

    pmp$get_mainframe_id (mainframe_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    CASE element_definition.element_type OF
    = cmc$controller_element =
      controller_equipment_number := element_definition.controller.physical_equipment_number;

    /channel_loop_1/
      FOR port := LOWERVALUE (cmt$controller_port_number) TO UPPERVALUE (cmt$controller_port_number) DO
        IF NOT element_definition.controller.connection.port [port].configured THEN
          CYCLE /channel_loop_1/;
        IFEND;

        IF element_definition.controller.connection.port [port].mainframe_ownership <> mainframe_id THEN
          CYCLE /channel_loop_1/;
        IFEND;

        cmp$pc_get_element (element_definition.controller.connection.port [port].element_name,
              element_definition.controller.connection.port [port].iou, channel_element_p, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF NOT primary_channel_found THEN
          primary_channel_found := TRUE;
          channel := channel_element_p^;
        IFEND;

        cmp$get_element_state (channel_element_p^.element_name, channel_element_p^.data_channel.iou,
              channel_element_state, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF NOT active_channel_found AND (channel_element_state = cmc$on) THEN
          active_channel_found := TRUE;
          channel := channel_element_p^;
        IFEND;

        element_descriptor.element_type := cmc$data_channel_element;
        element_descriptor.channel_descriptor.use_logical_identification := TRUE;
        element_descriptor.channel_descriptor.name := element_definition.controller.connection.port [port].
              element_name;
        element_descriptor.channel_descriptor.iou := element_definition.controller.connection.port [port].iou;

        cmp$get_connection_status (element_descriptor, element_definition.element_name,
              channel_controller_status, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF channel_controller_status = cmc$active THEN
          channel := channel_element_p^;
          RETURN;
        IFEND;

      FOREND /channel_loop_1/;

    = cmc$storage_device_element =

    /controller_loop/
      FOR data_storage_index := LOWERVALUE (cmt$data_storage_port_number)
            TO UPPERVALUE (cmt$data_storage_port_number) DO
        IF NOT element_definition.storage_device.connection.port [data_storage_index].configured THEN
          CYCLE /controller_loop/;
        IFEND;

        IF element_definition.storage_device.connection.port [data_storage_index].upline_connection_type =
              cmc$controller_element THEN

          cmp$pc_get_element (element_definition.storage_device.connection.port [data_storage_index].
                element_name, unused_iou, controller_element_p, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          IF NOT primary_controller_found THEN
            primary_controller_found := TRUE;
            controller_equipment_number := controller_element_p^.controller.physical_equipment_number;
          IFEND;

          element_descriptor.element_type := cmc$controller_element;
          element_descriptor.peripheral_descriptor.use_logical_identification := TRUE;
          element_descriptor.peripheral_descriptor.element_name := controller_element_p^.element_name;

          cmp$get_connection_status (element_descriptor, element_definition.element_name,
                controller_unit_status, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

        /channel_loop_2/
          FOR port := LOWERVALUE (cmt$controller_port_number) TO UPPERVALUE (cmt$controller_port_number) DO
            IF NOT controller_element_p^.controller.connection.port [port].configured THEN
              CYCLE /channel_loop_2/;
            IFEND;

            IF controller_element_p^.controller.connection.port [port].mainframe_ownership <>
                  mainframe_id THEN
              CYCLE /channel_loop_2/;
            IFEND;

            cmp$pc_get_element (controller_element_p^.controller.connection.port [port].element_name,
                  controller_element_p^.controller.connection.port [port].iou, channel_element_p, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;

            IF NOT primary_channel_found THEN
              primary_channel_found := TRUE;
              channel := channel_element_p^;
            IFEND;

            element_descriptor.element_type := cmc$data_channel_element;
            element_descriptor.channel_descriptor.use_logical_identification := TRUE;
            element_descriptor.channel_descriptor.name := controller_element_p^.controller.connection.port
                  [port].element_name;
            element_descriptor.channel_descriptor.iou := controller_element_p^.controller.connection.port
                  [port].iou;

            cmp$get_connection_status (element_descriptor, controller_element_p^.element_name,
                  channel_controller_status, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;

            IF (NOT active_channel_found) AND (channel_controller_status = cmc$active) THEN
              active_channel_found := TRUE;
              channel := channel_element_p^;
              controller_equipment_number := controller_element_p^.controller.physical_equipment_number;
            IFEND;

            IF (channel_controller_status = cmc$active) AND (controller_unit_status = cmc$active) THEN
              channel := channel_element_p^;
              controller_equipment_number := controller_element_p^.controller.physical_equipment_number;
              RETURN;
            IFEND;
          FOREND /channel_loop_2/;

        ELSE
          {
          {Process hydra mass storage device.
          {
          controller_equipment_number := element_definition.storage_device.physical_unit_number;
          IF element_definition.storage_device.connection.port [data_storage_index].mainframe_ownership <>
                mainframe_id THEN
            CYCLE /controller_loop/;
          IFEND;

          cmp$pc_get_element (element_definition.storage_device.connection.port [data_storage_index].
                element_name, element_definition.storage_device.connection.port [data_storage_index].iou,
                channel_element_p, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          IF NOT primary_channel_found THEN
            primary_channel_found := TRUE;
            channel := channel_element_p^;
          IFEND;

          cmp$get_element_state (channel_element_p^.element_name, channel_element_p^.data_channel.iou,
                channel_element_state, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          IF NOT active_channel_found AND (channel_element_state = cmc$on) THEN
            active_channel_found := TRUE;
            channel := channel_element_p^;
          IFEND;

          element_descriptor.element_type := cmc$data_channel_element;
          element_descriptor.channel_descriptor.use_logical_identification := TRUE;
          element_descriptor.channel_descriptor.name := element_definition.storage_device.connection.
                port [data_storage_index].element_name;
          element_descriptor.channel_descriptor.iou := element_definition.storage_device.connection.
                port [data_storage_index].iou;

          cmp$get_connection_status (element_descriptor, element_definition.element_name,
                channel_controller_status, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF channel_controller_status <> cmc$active THEN
            CYCLE /controller_loop/;
          IFEND;

          channel := channel_element_p^;
          RETURN;
        IFEND;
      FOREND /controller_loop/;
    ELSE
    CASEND;
  PROCEND find_connected_channel;

?? TITLE := '  process_iou_resources', EJECT ??

 { PURPOSE : This procedure acquires/release channel and PP resources.

  PROCEDURE process_iou_resources (element_definition : cmt$element_definition;
         controller_type : cmt$controller_type;
         process_channel : boolean;
         process_pp : boolean;
         current_state : cmt$element_state;
         new_state : cmt$element_state;
         driver_name : pmt$program_name;
     VAR status : ost$status);

     VAR
       channel : cmt$element_definition,
       equipment_number : cmt$physical_equipment_number,
       ignore_status : ost$status,
       iou_name : cmt$element_name,
       iou_number : dst$iou_number,
       physical_channel : cmt$physical_channel,
       port : integer,
       pp_not_active: boolean,
       pp_acquired : ARRAY [cmt$max_channels_per_storage] OF pps_acquired_info,
       pp_released : ARRAY [cmt$controller_port_number] OF pps_released_info,
       pp_table_rma : ost$real_memory_address,
       redundant: boolean;

     status.normal := TRUE;
     IF element_definition.element_type = cmc$data_channel_element THEN
       cmp$convert_iou_name (element_definition.data_channel.iou, iou_number, status);
       IF NOT status.normal THEN
         RETURN;
       IFEND;
       physical_channel.number := element_definition.data_channel.number;
       physical_channel.concurrent := element_definition.data_channel.concurrent;
       physical_channel.port := element_definition.data_channel.port;

       IF new_state = cmc$on THEN

         IF current_state = cmc$off THEN
           IF process_channel THEN
             cmp$reacquire_resources (dsc$rrt_get_channel, physical_channel,
                 iou_number, cmc$null_equipment_number, cmc$null_unit_number, driver_name,
                 pp_table_rma, controller_type, FALSE, status);
             IF NOT status.normal THEN
               RETURN;
             IFEND;
           IFEND;
         IFEND;
         IF process_pp THEN
           redundant := FALSE;
           IF cmp$support_redundant_channel (controller_type) THEN
              cmp$determine_redundant_channel (physical_channel, iou_number,
                  {ignore_state=}TRUE, redundant, ignore_status);
           IFEND;
           IF NOT redundant THEN
             cmp$get_pp_table_rma (element_definition, pp_table_rma, status);
             IF NOT status.normal THEN
               RETURN;
             IFEND;
             cmp$reacquire_resources (dsc$rrt_get_pp, physical_channel,
                   iou_number, cmc$null_equipment_number, cmc$null_unit_number,
                   driver_name, pp_table_rma, controller_type, TRUE, status);
             IF NOT status.normal THEN
               RETURN;
             IFEND;
           IFEND;
         IFEND;
       ELSEIF (new_state = cmc$down) AND (current_state = cmc$off) THEN

 { Acquire the channel only.

         cmp$reacquire_resources (dsc$rrt_get_channel, physical_channel,
             iou_number, cmc$null_equipment_number, cmc$null_unit_number, driver_name,
             pp_table_rma, controller_type, FALSE, status);
         IF NOT status.normal THEN
           RETURN;
         IFEND;

       ELSE { New state is DOWN or OFF and current state is ON }

 { Soft idle the pp first. The status will be ignored since PP will
 { be hardware idled upon being released.

         determine_if_pp_not_active (element_definition.data_channel.number,
               element_definition.data_channel.port, element_definition.data_channel.concurrent,
               iou_number, pp_not_active);
         IF NOT pp_not_active THEN
           cmp$idle_pp_r1 (element_definition.element_name, element_definition.data_channel.iou, status);
           cmp$release_pp_by_channel (physical_channel, iou_number, status);
           IF NOT status.normal THEN
             RETURN;
           IFEND;
           cmp$clear_ppit (element_definition.element_name, element_definition.
                 data_channel.iou, ignore_status);
         IFEND;
         IF (new_state = cmc$off) AND process_channel THEN
           cmp$release_channel_resource (physical_channel, iou_number, status);
           IF NOT status.normal THEN
             RETURN;
           IFEND;
         IFEND;
       IFEND;

     ELSEIF element_definition.element_type = cmc$controller_element THEN
       IF new_state = cmc$on THEN
         cmp$active_path (element_definition, controller_type, pp_acquired, status);
         IF NOT status.normal THEN
           RETURN;
         IFEND;
         FOR port := LOWERVALUE (cmt$max_channels_per_storage) TO
                       UPPERVALUE (cmt$max_channels_per_storage) DO
           IF pp_acquired [port].acquired THEN
             IF current_state = cmc$off THEN
               cmp$reacquire_resources (dsc$rrt_get_channel, pp_acquired [port].channel,
                       pp_acquired [port].iou, cmc$null_equipment_number, cmc$null_unit_number,
                       driver_name, pp_table_rma, controller_type, FALSE, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;
             IFEND;
             cmp$reacquire_resources (dsc$rrt_get_pp, pp_acquired [port].channel,
               pp_acquired [port].iou, cmc$null_equipment_number, cmc$null_unit_number,
                 pp_acquired [port].driver_name, pp_acquired [port].pp_table_rma,
                   pp_acquired [port].controller_type, TRUE, status);
             IF NOT status.normal THEN
               RETURN;
             IFEND;
           IFEND;
         FOREND;
       ELSEIF (new_state = cmc$down) AND (current_state = cmc$off) THEN

 { Acquire all Channels.

         cmp$active_path (element_definition, controller_type, pp_acquired, status);
         IF NOT status.normal THEN
           RETURN;
         IFEND;
         FOR port := LOWERVALUE (cmt$max_channels_per_storage) TO
                       UPPERVALUE (cmt$max_channels_per_storage) DO
           IF pp_acquired [port].acquired THEN
             IF (current_state = cmc$off) THEN
               cmp$reacquire_resources (dsc$rrt_get_channel, pp_acquired [port].channel,
                       pp_acquired [port].iou, cmc$null_equipment_number, cmc$null_unit_number,
                       driver_name, pp_table_rma, controller_type, FALSE, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;
             IFEND;
           IFEND;
         FOREND;
       ELSE { New state is DOWN or OFF }
         cmp$unactive_path (element_definition, pp_released, status);
         IF NOT status.normal THEN
           RETURN;
         IFEND;
         FOR port := LOWERVALUE (cmt$controller_port_number) TO
                    UPPERVALUE (cmt$controller_port_number) DO
           IF pp_released [port].released THEN
             cmp$convert_iou_number (pp_released [port].iou, iou_name, ignore_status);
             determine_if_pp_not_active (pp_released [port].channel.number,
                   pp_released [port].channel.port, pp_released [port].channel.concurrent,
                   pp_released [port].iou, pp_not_active);
             IF NOT pp_not_active THEN
               cmp$idle_pp_r1 (pp_released [port].channel_name, iou_name, ignore_status);
               cmp$release_pp_by_channel (pp_released [port].channel, pp_released [port].iou, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;
             IFEND;
             IF (new_state = cmc$off) THEN
               cmp$release_channel_resource (pp_released [port].channel, pp_released [port].iou, status);
               IF NOT status.normal THEN
                 RETURN;
               IFEND;
             IFEND;
             cmp$clear_ppit (pp_released [port].channel_name, iou_name, status);
             IF NOT status.normal THEN
               RETURN;
             IFEND;
           IFEND;
         FOREND;
       IFEND;
     IFEND;

  PROCEND process_iou_resources;
?? OLDTITLE , OLDTITLE ??
MODEND cmm$miscellaneous_interfaces
