?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE CM : Physical Configuration manager' ??
MODULE cmm$physical_configuration_mgr;

{ PURPOSE:

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cme$logical_configuration_mgr
*copyc cme$physical_configuration_mgr
*copyc cmc$default_vsn
*copyc cmc$logical_conf_dev_file_name
*copyc cmc$logical_unit_constants
*copyc cmc$physical_conf_dev_file_name
*copyc cmt$controller_type
*copyc cmt$device_file_table
*copyc cmt$element_definition
*copyc cmt$element_name
*copyc cmt$physical_configuration
*copyc cmt$sci_dft_pp
*copyc cmt$state_information
*copyc cmt$unit_types
*copyc oss$mainframe_paged_literal
*copyc ost$signature_lock
?? POP ??
*copyc clp$convert_integer_to_string
*copyc cmp$convert_iou_name
*copyc cmp$get_channel_def
*copyc cmp$set_product_id_status
*copyc cmp$valid_channel_name
*copyc dmp$search_active_volume_table
*copyc dsp$read_channel_states
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
?? EJECT ??
*copyc cmv$controller_data
*copyc cmv$system_device_pp
*copyc dmv$active_volume_table
*copyc osv$mainframe_pageable_heap
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    cmv$parity_protected_units: [XDCL, READ, #GATE, oss$mainframe_paged_literal] cmt$unit_types :=
          $cmt$unit_types [
{           } cmc$ms5833_1p, cmc$ms5833_3p,
{           } cmc$ms5838_1p, cmc$ms5838_3p,
{           } cmc$ms47444_1p, cmc$ms47444_3p,
{           } cmc$ms5837_1p, cmc$ms5837_3p];

  VAR
    cmv$assignable_device: [XDCL, READ, #GATE, oss$mainframe_paged_literal] cmt$unit_types :=
          [cmc$mt679_5, cmc$mt679_6, cmc$mt679_7, cmc$mt679_2, cmc$mt679_3, cmc$mt679_4, cmc$mt677_2,
           cmc$mt677_3, cmc$mt677_4, cmc$mt667_2, cmc$mt667_2, cmc$mt667_3, cmc$mt667_4, cmc$mt669_2,
           cmc$mt669_3, cmc$mt669_4, cmc$mt698_3x, cmc$mt639_s0, cmc$mt639_1, cmc$mt5682_1x],
    cmv$configuration_activated : [XDCL, #GATE] boolean := FALSE,
    cmv$new_device_file: [XDCL, #GATE] cmt$device_file_record :=
          [cmc$physical_configuration_file, cmc$dfs_unknown, cmc$default_vsn, *, *],
    cmv$physical_configuration: [XDCL, #GATE] cmt$physical_configuration := NIL,
    cmv$save_pct_p: [XDCL] cmt$physical_configuration := NIL,
    cmv$save_state_table_p: [XDCL] ^ARRAY [1 .. *] OF cmt$state_information := NIL,
    cmv$sci_dft_pp: [XDCL, #GATE] cmt$sci_dft_pp :=
          [[0, dsc$cpt_nio, 0], FALSE, [0, dsc$cpt_nio, 0], FALSE, [0, dsc$cpt_nio, 0]],
    cmv$state_change_lock: [XDCL] ost$signature_lock,
    cmv$state_info_table: [XDCL, #GATE] ^ARRAY [1 .. *] OF cmt$state_information := NIL;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$build_pct', EJECT ??
*copy cmh$build_pct

  PROCEDURE [XDCL, #GATE] cmp$build_pct
    (    entry_count: integer;
         entries: ARRAY [1 .. * ] OF cmt$element_definition;
     VAR status: ost$status);

    VAR
      index: integer;

    status.normal := TRUE;
    cmv$save_pct_p := cmv$physical_configuration;
    ALLOCATE cmv$physical_configuration: [1 .. entry_count] IN osv$mainframe_pageable_heap^;
    IF cmv$physical_configuration = NIL THEN
      RETURN;
    IFEND;

    FOR index := 1 TO entry_count DO
      cmv$physical_configuration^ [index] := entries [index];
    FOREND;

  PROCEND cmp$build_pct;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$build_state_table', EJECT ??

{ PURPOSE:
{   This procedure builds a copy of the state information.

  PROCEDURE [XDCL, #GATE] cmp$build_state_table
    (    entry_count: integer;
         entries: ARRAY [ * ] OF cmt$state_information;
         use_mrt_state : boolean;
     VAR status: ost$status);

    VAR
      channel_definition: cmt$data_channel_definition,
      channel_identification: cmt$channel_descriptor,
      channel_protocol: dst$channel_protocol_type,
      channel_state_list: dst$entire_channel_state_list,
      iou_number: dst$iou_number,
      state_index: integer;

    status.normal := TRUE;

    cmv$save_state_table_p := cmv$state_info_table;

    IF use_mrt_state THEN
      dsp$read_channel_states (channel_state_list, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;
    ALLOCATE cmv$state_info_table: [1 .. entry_count] IN osv$mainframe_pageable_heap^;

    FOR state_index := 1 TO entry_count DO
      cmv$state_info_table^ [state_index].element_name := entries [state_index].element_name;
      cmv$state_info_table^ [state_index].status := entries [state_index].status;
      cmv$state_info_table^ [state_index].element_type := entries [state_index].element_type;
      IF cmv$state_info_table^ [state_index].element_type = cmc$data_channel_element THEN
        cmv$state_info_table^ [state_index].iou := entries [state_index].iou;
        cmp$convert_iou_name (cmv$state_info_table^[state_index].iou, iou_number, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        channel_identification.iou := cmv$state_info_table^ [state_index].iou;
        channel_identification.use_logical_identification := TRUE;
        channel_identification.name := cmv$state_info_table^ [state_index].element_name;
        cmp$get_channel_def (channel_identification, channel_definition, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF channel_definition.concurrent THEN
          channel_protocol := dsc$cpt_cio;
        ELSE
          channel_protocol := dsc$cpt_nio;
        IFEND;
        IF use_mrt_state THEN
          cmv$state_info_table^ [state_index].status.state :=
                channel_state_list [iou_number] [channel_protocol] [channel_definition.number];
        IFEND;
      ELSE
        cmv$state_info_table^ [state_index].product_id := entries [state_index].product_id;
        cmv$state_info_table^ [state_index].logical_unit := entries [state_index].logical_unit;
        cmv$state_info_table^ [state_index].application_info_size :=
              entries [state_index].application_info_size;
        cmv$state_info_table^ [state_index].site_info_size := entries [state_index].site_info_size;
        IF entries [state_index].application_info_p <> NIL THEN
          ALLOCATE cmv$state_info_table^ [state_index].application_info_p:
                [STRLENGTH(entries [state_index].application_info_p^)] IN osv$mainframe_pageable_heap^;
          cmv$state_info_table^ [state_index].application_info_p^ :=
                entries [state_index].application_info_p^;
        ELSE
          cmv$state_info_table^ [state_index].application_info_p := NIL;
        IFEND;
        IF entries [state_index].site_info_p <> NIL THEN
          ALLOCATE cmv$state_info_table^ [state_index].site_info_p:
                [STRLENGTH(entries [state_index].site_info_p^)] IN osv$mainframe_pageable_heap^;
          cmv$state_info_table^ [state_index].site_info_p^ := entries [state_index].site_info_p^;
        ELSE
          cmv$state_info_table^ [state_index].site_info_p := NIL;
        IFEND;
      IFEND;
    FOREND;

  PROCEND cmp$build_state_table;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$check_dual_pp_system_disk ', EJECT ??

{ PURPOSE:
{   This procedure returns whether or not the system disk PP has a partner pp.

  PROCEDURE [XDCL] cmp$check_dual_pp_system_disk
    (    pp: dst$iou_resource;
     VAR dual_pp: boolean;
     VAR partner_pp: dst$iou_resource);

    dual_pp := FALSE;

    IF (cmv$system_device_pp.primary_pp = pp) AND cmv$system_device_pp.dual_pp THEN
      dual_pp := TRUE;
      partner_pp := cmv$system_device_pp.partner_pp;
    IFEND;

  PROCEND cmp$check_dual_pp_system_disk;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$get_controller_type', EJECT ??

{ PURPOSE:
{   This procedure returns the internal controller type based on the product id.

  PROCEDURE [XDCL, #GATE] cmp$get_controller_type
    (    pid: cmt$product_identification;
     VAR controller_type: cmt$controller_type;
     VAR status: ost$status);

    VAR
      index: integer;

    status.normal := TRUE;

    FOR index := 1 TO UPPERBOUND (cmv$controller_data_ptr^) DO
      IF cmv$controller_data_ptr^ [index].product_id = pid THEN
        controller_type := cmv$controller_data_ptr^ [index].controller_type;
        RETURN;
      IFEND;
    FOREND;

    cmp$set_product_id_status (' ', pid, cme$pc_unknown_controller_type, status);

  PROCEND cmp$get_controller_type;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$get_element_name_via_lun ', EJECT ??
*copy cmh$get_element_name_via_lun

  PROCEDURE [XDCL, #GATE] cmp$get_element_name_via_lun
    (    logical_unit_number: iot$logical_unit;
     VAR element_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      mainframe_element_p: ^cmt$element_definition,
      temp_string: ost$string;

    cmp$pc_get_logical_unit (logical_unit_number, mainframe_element_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF mainframe_element_p <> NIL THEN
      element_name := mainframe_element_p^.element_name;
    ELSE
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_unit_not_found, '', status);
      clp$convert_integer_to_string (logical_unit_number, 10, FALSE, temp_string, ignore_status);
      osp$append_status_parameter (osc$status_parameter_delimiter,
            temp_string.value (1, temp_string.size), status);
    IFEND;

  PROCEND cmp$get_element_name_via_lun;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$get_logical_unit_number', EJECT ??
*copy cmh$get_logical_unit_number

  PROCEDURE [XDCL, #GATE] cmp$get_logical_unit_number
    (    element_name: cmt$element_name;
     VAR logical_unit_number: iot$logical_unit;
     VAR status: ost$status);

    VAR
      index: integer,
      mainframe_element_p: ^cmt$element_definition,
      unused_iou_name: cmt$element_name;

    logical_unit_number := 0;

    cmp$pc_get_element (element_name, unused_iou_name, mainframe_element_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Find a logical unit for element other than channel and controllers, since they do not get assigned
{ a logical unit.

    IF (mainframe_element_p^.element_type <> cmc$data_channel_element) AND
        (mainframe_element_p^.element_type <> cmc$controller_element) THEN
      IF cmv$state_info_table = NIL THEN
        osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_nil_lct, element_name, status);
        RETURN;
      IFEND;

      FOR index := LOWERBOUND (cmv$state_info_table^) TO UPPERBOUND (cmv$state_info_table^) DO
        IF element_name = cmv$state_info_table^ [index].element_name THEN
          logical_unit_number := cmv$state_info_table^ [index].logical_unit;
          RETURN;
        IFEND;
      FOREND;

      osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_not_logically_conf, element_name,
            status);
    ELSE
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_name_not_data_element,
            element_name, status);
    IFEND;

  PROCEND cmp$get_logical_unit_number;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$pc_get_element', EJECT ??
*copy cmh$pc_get_element

  PROCEDURE [XDCL, #GATE] cmp$pc_get_element
    (    element_name: cmt$element_name;
         iou_name: cmt$element_name;
     VAR mainframe_element_p: ^cmt$element_definition;
     VAR status: ost$status);

    VAR
      index: integer,
      text: string (64);

    status.normal := TRUE;

    IF cmv$physical_configuration = NIL THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_nil_pct, 'NIL PCT', status);
      RETURN;
    IFEND;

    FOR index := 1 TO UPPERBOUND (cmv$physical_configuration^) DO
      mainframe_element_p := ^cmv$physical_configuration^ [index];

      IF mainframe_element_p^.element_name = element_name THEN
        IF mainframe_element_p^.element_type = cmc$data_channel_element THEN
          IF iou_name = mainframe_element_p^.data_channel.iou THEN
            RETURN;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    FOREND;

    text := ' ';
    IF cmp$valid_channel_name(element_name) THEN
      text (1, 5) := iou_name (1, 5);
      text (6, *) := element_name;
    ELSE
      text (1, *) := element_name;
    IFEND;

    osp$set_status_abnormal (cmc$configuration_management_id, cme$lcm_element_not_found, text, status);

  PROCEND cmp$pc_get_element;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$pc_get_logical_unit', EJECT ??
*copy cmh$pc_get_logical_unit

  PROCEDURE [XDCL, #GATE] cmp$pc_get_logical_unit
    (    logical_unit_number: iot$logical_unit;
     VAR mainframe_element_p: ^cmt$element_definition;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      index: integer,
      temp_string: ost$string,
      unused_iou_name: cmt$element_name;

    status.normal := TRUE;

    FOR index := 1 TO UPPERBOUND (cmv$state_info_table^) DO
      IF (cmv$state_info_table^ [index].element_type <> cmc$data_channel_element) AND
            (cmv$state_info_table^ [index].logical_unit = logical_unit_number) THEN
        cmp$pc_get_element (cmv$state_info_table^ [index].element_name, unused_iou_name,
              mainframe_element_p, status);
        RETURN;
      IFEND;
    FOREND;

    osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_unit_not_found, '', status);
    clp$convert_integer_to_string (logical_unit_number, 10, FALSE, temp_string, ignore_status);
    osp$append_status_parameter (osc$status_parameter_delimiter,
          temp_string.value (1, temp_string.size), status);

  PROCEND cmp$pc_get_logical_unit;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$pc_get_next_channel', EJECT ??
*copy cmh$pc_get_next_channel

  PROCEDURE [XDCL, #GATE] cmp$pc_get_next_channel
    (    current_channel: integer;
     VAR mainframe_element_p: ^cmt$element_definition;
     VAR status: ost$status);

    VAR
      index: integer,
      channel_count: integer;

    status.normal := TRUE;

    IF cmv$physical_configuration = NIL THEN
      osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_nil_lct, 'NIL PCT', status);
      RETURN;
    IFEND;

    channel_count := current_channel;

    FOR index := 1 TO UPPERBOUND (cmv$physical_configuration^) DO
      mainframe_element_p := ^cmv$physical_configuration^ [index];
      IF mainframe_element_p^.element_type = cmc$data_channel_element THEN
        channel_count := channel_count - 1;
        IF channel_count < 0 THEN
          RETURN;
        IFEND;
      IFEND;
    FOREND;

    osp$set_status_abnormal (cmc$configuration_management_id, cme$pc_nil_lct, '', status);

  PROCEND cmp$pc_get_next_channel;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$search_active_volume_table', EJECT ??

  PROCEDURE [XDCL, #GATE] cmp$search_active_volume_table
    (    search_key: dmt$avt_search_key;
     VAR recorded_vsn: rmt$recorded_vsn;
     VAR avt_entry_not_found: boolean);

    VAR
      avt_index: dmt$active_volume_table_index;

    dmp$search_active_volume_table (search_key, avt_index, avt_entry_not_found);
    IF avt_entry_not_found THEN
      RETURN;
    IFEND;

    recorded_vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;

  PROCEND cmp$search_active_volume_table;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$update_dft_sci_location', EJECT ??

{ PURPOSE:
{   To initialize and update the values of SCI, DFT and secondary DFT pp number.

  PROCEDURE [XDCL] cmp$update_dft_sci_location
    (    dft_sci_location: cmt$sci_dft_pp);

    cmv$sci_dft_pp := dft_sci_location;

  PROCEND cmp$update_dft_sci_location;
?? OLDTITLE ??
MODEND cmm$physical_configuration_mgr;
