?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE CM : Manage 170 Resources' ??
MODULE cmm$manage_170_resources;


?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmd$null_equipment_number
*copyc cme$logical_configuration_mgr
*copyc cme$physical_configuration_mgr
*copyc cme$reserve_element
*copyc dse$error_codes
*copyc cmt$channel_ordinal
*copyc cmt$controller_location
*copyc cmt$controller_port_number
*copyc cmt$element_name
*copyc cmt$element_state
*copyc cmt$physical_channel
*copyc cmt$physical_equipment_number
*copyc cmt$pp_controller_loaded
*copyc cmt$request_block
*copyc oss$mainframe_paged_literal
?? POP ??
*copyc cmp$clear_channel_interlock
*copyc cmp$get_controller_type
*copyc cmp$get_logical_pp_index
*copyc cmp$pc_get_element
*copyc cmp$retrieve_logical_pp_index
*copyc dpp$put_critical_message
*copyc dsp$allocate_continuous_memory
*copyc dsp$fetch_controlware
*copyc dsp$load_pp
*copyc dsp$request_resources
*copyc i#call_monitor
*copyc i#move
*copyc i#ptr
*copyc i#real_memory_address
*copyc osp$append_status_integer
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$system_error
*copyc pmp$zero_out_table
?? EJECT ??
*copyc cmv$logical_pp_table_p
*copyc cmv$physical_configuration
*copyc cmv$system_device_pp
*copyc osv$mainframe_wired_cb_heap
*copyc osv$mainframe_wired_heap
*copyc osv$page_size
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??
  VAR
    cmv$controller_location: [XDCL] cmt$controller_location :=
          [REP (ORD (UPPERVALUE (cmt$controller_type)) + 1) OF [FALSE, NIL, NIL,0, FALSE, NIL, NIL, 0]];
?? OLDTITLE ??
?? NEWTITLE := 'cmp$acquire_deadstart_resources', EJECT ??

{ PURPOSE:
{   This procedure obtains resources and loads pps during system deadstart.  This routine is used to load the
{   system device and deadstart device drivers in the boot and system core before full configuration is
{   activated.

  PROCEDURE [XDCL] cmp$acquire_deadstart_resources
    (    channel: cmt$physical_channel;
         iou_number: dst$iou_number;
         equipment_number: 0 .. cmc$null_equipment_number;
         unit_number: 0 .. cmc$null_unit_number;
     VAR status: ost$status);

    VAR
      channel_type: dst$channel_protocol_type,
      partner_pp_index: iot$pp_number,
      partner_pp_table_rma: ost$real_memory_address,
      pp_index: iot$pp_number,
      resource_request: dst$resource_request;

    status.normal := TRUE;

    IF channel.concurrent THEN
      channel_type := dsc$cpt_cio;
    ELSE
      channel_type := dsc$cpt_nio;
    IFEND;

    cmp$retrieve_logical_pp_index (channel, iou_number, cmv$logical_pp_table_p, pp_index, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    partner_pp_index := cmv$logical_pp_table_p^ [pp_index].pp_info.logical_partner_pp_index;
    IF cmv$system_device_pp.dual_pp THEN
      IF cmv$logical_pp_table_p^ [pp_index].pp_info.pp_communication_buffer_p <> NIL THEN
        partner_pp_table_rma := cmv$logical_pp_table_p^ [pp_index].pp_info.pp_communication_buffer_p^.
              partner_pp;
      ELSE
        osp$set_status_condition (cme$no_pp_communication_buffer, status);
        osp$append_status_integer (osc$status_parameter_delimiter, pp_index, 16, true, status);
        RETURN; {----->
      IFEND;
    IFEND;

    resource_request.channel.iou_number := iou_number;
    resource_request.channel.channel_protocol := channel_type;
    resource_request.channel.number := channel.number;

    IF (equipment_number <> cmc$null_equipment_number) AND (unit_number <> cmc$null_unit_number) THEN
      resource_request.equipment_number := ORD (equipment_number);
      resource_request.unit_number := ORD (unit_number);
      cmp$request_resources (dsc$rrt_get_equipment, resource_request, status);
    ELSE
      cmp$request_resources (dsc$rrt_get_channel, resource_request, status);
    IFEND;
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF partner_pp_index > 0 THEN
      resource_request.options := $dst$resource_request_options [dsc$rro_partner_pp];
    ELSEIF channel_type = dsc$cpt_nio THEN
      resource_request.options := $dst$resource_request_options [dsc$rro_driver_pp];
    ELSE
      resource_request.options := $dst$resource_request_options [];
    IFEND;

    cmp$request_resources (dsc$rrt_get_pp, resource_request, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp := resource_request.primary_pp;
    cmv$logical_pp_table_p^ [pp_index].flags.resources_acquired := TRUE;
    cmv$system_device_pp.primary_pp := resource_request.primary_pp;
    cmv$system_device_pp.dual_pp := (partner_pp_index > 0);
    IF cmv$system_device_pp.dual_pp THEN
      cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp := resource_request.secondary_pp;
      cmv$logical_pp_table_p^ [partner_pp_index].flags.resources_acquired := TRUE;
      cmv$system_device_pp.partner_pp := resource_request.secondary_pp;
    IFEND;

    dsp$load_pp (dsc$load_pp_by_name, cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp, NIL,
          cmv$logical_pp_table_p^ [pp_index].pp_info.cip_driver_name,
          cmv$logical_pp_table_p^ [pp_index].pp_info.pp_interface_table_rma, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    cmv$logical_pp_table_p^ [pp_index].flags.pp_loaded := TRUE;

    IF cmv$system_device_pp.dual_pp THEN
      dsp$load_pp (dsc$load_pp_by_name, cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp, NIL,
            cmv$logical_pp_table_p^ [partner_pp_index].pp_info.cip_driver_name, partner_pp_table_rma, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      cmv$logical_pp_table_p^ [partner_pp_index].flags.pp_loaded := TRUE;
    IFEND;

  PROCEND cmp$acquire_deadstart_resources;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$assign_pp_r1', EJECT ??

{ PURPOSE:
{   This procedure sets up the monitor request block to indicate that a PP has been assigned in Monitor.

  PROCEDURE [XDCL] cmp$assign_pp_r1
    (    assigned: boolean;
         assigned_pp: iot$pp_number);

    VAR
      request_block: cmt$request_block;

    request_block.request_code := syc$rc_config_mgmt_request;
    request_block.kind := cmc$rbk_assign_pp;
    request_block.assigned := assigned;
    request_block.assigned_pp := assigned_pp;

    i#call_monitor (#LOC (request_block) , #SIZE (request_block));

  PROCEND cmp$assign_pp_r1;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$idle_pp_r1', EJECT ??

{ PURPOSE:
{   This procedure is the ring 1 interface to set up the monitor request block to soft idle a PP.

  PROCEDURE [XDCL, #GATE] cmp$idle_pp_r1
    (    channel_name: cmt$element_name;
         iou_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      channel_element_p: ^cmt$element_definition,
      done: boolean,
      ignore_status: ost$status,
      line: string (80),
      message_output: boolean,
      new_time: integer,
      old_time: integer,
      pp_index: iot$pp_number,
      request_block: cmt$request_block,
      wait_time: integer;

    status.normal := TRUE;
    done := FALSE;
    line := ' ';
    message_output := FALSE;

    cmp$pc_get_element (channel_name, iou_name, channel_element_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    cmp$get_logical_pp_index (channel_element_p^, pp_index, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Send the IDLE on first call to MONITOR.  Wait up to 12 minutes (units in microseconds).

   /send_request/
    BEGIN
      request_block.request_code := syc$rc_config_mgmt_request;
      request_block.kind := cmc$rbk_idle_pp;
      request_block.idled_pp := pp_index;
      request_block.send_idle := TRUE;
      wait_time := 12 * 60 * 1000000;
      old_time := #FREE_RUNNING_CLOCK (0);
      REPEAT
        i#call_monitor (#LOC (request_block) , #SIZE (request_block));
        IF NOT request_block.status.normal THEN
          osp$set_status_abnormal (cmc$configuration_management_id, cme$unable_to_idle,
                'PP did not respond to idle request.', status);
          EXIT /send_request/;
        IFEND;
        new_time := #FREE_RUNNING_CLOCK (0);
        done :=  (cmv$logical_pp_table_p^ [pp_index].pp_info.pp_interface_table_p^.idle_status) OR
              (new_time >= old_time + wait_time);
        IF NOT done AND (new_time > (old_time + 2000000)) THEN
          IF NOT message_output THEN
            line (1,26) := 'Waiting for PP to idle on ';
            line (28, 5) := channel_element_p^.data_channel.iou (1, 5);
            line (35, 5) := channel_name;
            dpp$put_critical_message (line, ignore_status);
            message_output := TRUE;
          IFEND;
        IFEND;

        { Only check PP response, the next time exchanging to MONITOR

        request_block.send_idle := FALSE;
      UNTIL done;

      IF NOT cmv$logical_pp_table_p^ [pp_index].pp_info.pp_interface_table_p^.idle_status THEN
        IF message_output THEN
          dpp$put_critical_message ('PP did not respond to idle request.', ignore_status);
          osp$set_status_abnormal (cmc$configuration_management_id, cme$unable_to_idle,
                'PP did not respond to idle request.', status);
        IFEND;
      ELSE
        IF message_output THEN
          dpp$put_critical_message ('PP responded to idle request.', ignore_status);
        IFEND;
      IFEND;
    END /send_request/;

    cmp$clear_channel_interlock (cmv$logical_pp_table_p^ [pp_index].pp_info.channel.iou_number,
          pp_index, ignore_status);
    IF NOT ignore_status.normal AND status.normal THEN
      status := ignore_status;
    IFEND;

  PROCEND cmp$idle_pp_r1;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$load_controller_module', EJECT ??

{ PURPOSE:
{   This procedure loads either controlware or a control module.  This procedure retrieves the necessary
{   controlware or control module from the CIP device and stores it in the mainframe wired heap.  It
{   creates the RMA list to the area in memory that contains the controller module so that the PP has access
{   to the area.

  PROCEDURE [XDCL] cmp$load_controller_module
    (    load_controller_type: (cmc$load_controlware, cmc$load_control_module);
     VAR logical_pp_table_p: ^cmt$logical_pp_table;
     VAR status : ost$status);

    TYPE
      unpacked_controller_data = PACKED RECORD
        fill: 0 .. 0f(16),
        byte: 0 .. 0ff(16),
      RECEND;

    VAR
      controller_buffer_p: ^SEQ ( * ),
      controller_length: integer,
      controller_name: string (4),
      controller_p: ^cell,
      controller_type: cmt$controller_type,
      max_rma_list_entries : integer,
      packed_controller_p: ^ARRAY [1 .. *] OF 0 .. 0ff(16),
      page_offset: ost$segment_offset,
      pp_number: iot$pp_number,
      rma: integer,
      rma_list_index: mmt$rma_list_index,
      rma_list_p: ^cmt$controller_rma_list,
      rma_list_seq_p: ^SEQ ( * ),
      rma_list_size: integer,
      rma_length : integer,
      table_index: integer,
      temp_controller_length : integer,
      temp_controller_seq_p: ^SEQ ( * ),
      unpacked_controller_length: integer,
      unpacked_controller_p: ^PACKED ARRAY [1 .. *] OF unpacked_controller_data,
      unpacked_index: integer;

    status.normal := TRUE;

    { Go through the physical configuration and figure out all the controllers that need controlware, then
    { get it from the CIP common disk area.

   /search_pct/
    FOR table_index := LOWERBOUND(cmv$physical_configuration^) TO UPPERBOUND
           (cmv$physical_configuration^) DO
      IF (cmv$physical_configuration^[table_index].element_type = cmc$controller_element)
         OR (cmv$physical_configuration^[table_index].element_type =
             cmc$channel_adapter_element) THEN
        cmp$get_controller_type (cmv$physical_configuration^[table_index].product_id,
               controller_type, status);
        IF NOT status.normal THEN
          { The controller is a foreign device.
          status.normal := TRUE;
          CYCLE /search_pct/;
        IFEND;
        IF load_controller_type = cmc$load_control_module THEN
          IF cmv$controller_location [controller_type].control_module_loaded THEN
            CYCLE /search_pct/;
          IFEND;
        ELSE
          IF cmv$controller_location [controller_type].controlware_loaded THEN
            CYCLE /search_pct/;
          IFEND;
        IFEND;

      { Find the four character controller name.

        IF load_controller_type = cmc$load_control_module THEN
          CASE controller_type OF
          = cmc$ms7255_1_1 =
            controller_name := 'H422';
          = cmc$ms7255_1_2 =
            controller_name := 'H424';
          ELSE
            CYCLE /search_pct/;
          CASEND;
        ELSE
          CASE controller_type OF
          = cmc$mt7021_3x, cmc$mt7021_4x, cmc$mt5698_xx, cmc$mscm3_ct =
            CYCLE /search_pct/;
          = cmc$ms7255_1_1, cmc$ms7255_1_2 =
            controller_name := 'A462';
          = cmc$ms7165_2x =
            controller_name := 'A464';
          = cmc$mt5680_xx =
            controller_name := 'B468';
          = cmc$mt7221_1,cmc$mt7221_2_s0 =
            controller_name := 'B465';
          = cmc$ms7155_1x, cmc$ms7155_1 =
            controller_name := 'A721';
          = cmc$ms7154_x =
            controller_name := 'A401';
          = cmc$ca2629_2 =
            controller_name := 'C418';
          = cmc$mt698_xx =
            controller_name := 'B467';
          ELSE
            CYCLE /search_pct/;
          CASEND;
        IFEND;

        { Fetch the controller module from the CIP device.  The controller module is stored on the mainframe
        { wired heap.  This area must be freed when the procedure has moved the controller module to its
        { permanent location.

        temp_controller_seq_p := NIL;
        dsp$fetch_controlware (controller_name, temp_controller_seq_p, status);
        IF NOT status.normal THEN
          IF temp_controller_seq_p <> NIL THEN
            FREE temp_controller_seq_p IN osv$mainframe_wired_heap^;
          IFEND;
          RETURN;
        IFEND;
        controller_length := #SIZE (temp_controller_seq_p^);

        { Check to see if the controller module must be packed.  Several types
        { of controller modules must be packed from eight bits of data stored in
        { twelve bit groups to a continuous stream of data.

        IF (controller_name = 'A721') OR (controller_name = 'A464') OR
              (controller_name = 'A462') OR (controller_name = 'A401') THEN
          ALLOCATE controller_buffer_p: [[REP controller_length OF cell]] IN osv$mainframe_wired_cb_heap^;
          RESET controller_buffer_p;
          pmp$zero_out_table (#LOC (controller_buffer_p^), controller_length);
          RESET temp_controller_seq_p;
          unpacked_controller_length := (controller_length * 8) DIV 12;
          NEXT unpacked_controller_p: [1 .. unpacked_controller_length] IN temp_controller_seq_p;
          NEXT packed_controller_p: [1 .. controller_length] IN controller_buffer_p;
          controller_length := 0;
          FOR unpacked_index := 1 TO unpacked_controller_length DO
            controller_length := controller_length + 1;
            packed_controller_p^ [controller_length] := unpacked_controller_p^ [unpacked_index].byte;
          FOREND;
          RESET controller_buffer_p;
          RESET temp_controller_seq_p;
          pmp$zero_out_table (#LOC (temp_controller_seq_p^), controller_length);
          i#move (controller_buffer_p, temp_controller_seq_p, controller_length);
          FREE controller_buffer_p IN osv$mainframe_wired_cb_heap^;
        IFEND;

        { Move the controller module into the permanent mainframe wired location.

        ALLOCATE controller_buffer_p: [[REP controller_length OF cell]] IN osv$mainframe_wired_cb_heap^;
        RESET controller_buffer_p;
        pmp$zero_out_table (#LOC (controller_buffer_p^), controller_length);
        RESET temp_controller_seq_p;
        i#move (temp_controller_seq_p, controller_buffer_p, controller_length);
        FREE temp_controller_seq_p IN osv$mainframe_wired_heap^;

        { Allocate space for the RMA list and find the RMAs for the list.
        { First figure out the size needed for the rma list.

        max_rma_list_entries := 1;
        controller_p := controller_buffer_p;
        page_offset := #OFFSET (controller_p) MOD osv$page_size;
        temp_controller_length := controller_length;
        WHILE temp_controller_length > 0 DO
          IF (page_offset + temp_controller_length) > osv$page_size THEN
            rma_length := (osv$page_size - page_offset);
          ELSE
            rma_length := temp_controller_length;
          IFEND;
          temp_controller_length := temp_controller_length - rma_length;
          page_offset := 0;
          controller_p := i#ptr (rma_length, controller_p);
          max_rma_list_entries := max_rma_list_entries + 1;
        WHILEND;
        rma_list_size := max_rma_list_entries * #SIZE (mmt$rma_list_entry);

        dsp$allocate_continuous_memory (osv$mainframe_wired_cb_heap, rma_list_size, rma_list_seq_p);
        RESET rma_list_seq_p;
        pmp$zero_out_table (#LOC (rma_list_seq_p^), rma_list_size);
        NEXT rma_list_p: [1 .. max_rma_list_entries] IN rma_list_seq_p;
        rma_list_index := LOWERBOUND (rma_list_p^);
        controller_p := controller_buffer_p;
        page_offset := #OFFSET (controller_p) MOD osv$page_size;
        WHILE controller_length > 0 DO
          IF rma_list_index > UPPERBOUND (rma_list_p^) THEN
            osp$system_error ('Controller rma list not big enough in cmm$manage_170_resources', NIL);
          IFEND;
          i#real_memory_address (controller_p, rma);
          rma_list_p^ [rma_list_index].rma := rma;
          IF (page_offset + controller_length) > osv$page_size THEN
            rma_list_p^ [rma_list_index].length := osv$page_size - page_offset;
          ELSE
            rma_list_p^ [rma_list_index].length := controller_length;
          IFEND;
          controller_length := controller_length - rma_list_p^ [rma_list_index].length;
          page_offset := 0;
          controller_p := i#ptr (rma_list_p^ [rma_list_index].length, controller_p);
          rma_list_index := rma_list_index + 1;
        WHILEND;
        IF load_controller_type = cmc$load_control_module THEN
          cmv$controller_location [controller_type].control_module_loaded := TRUE;
          cmv$controller_location [controller_type].control_module_location_p := controller_buffer_p;
          cmv$controller_location [controller_type].control_module_rma_list_p := rma_list_p;
          cmv$controller_location [controller_type].control_module_rma_list_size := rma_list_size;
        ELSE
          cmv$controller_location [controller_type].controlware_loaded := TRUE;
          cmv$controller_location [controller_type].controlware_location_p := controller_buffer_p;
          cmv$controller_location [controller_type].controlware_rma_list_p := rma_list_p;
          cmv$controller_location [controller_type].controlware_rma_list_size := rma_list_size;
        IFEND;
      IFEND;
    FOREND /search_pct/;

   /search_pp_table/
    FOR pp_number := LOWERBOUND (logical_pp_table_p^) TO UPPERBOUND (logical_pp_table_p^) DO

      { Check to see if the PP is configured.

      IF NOT logical_pp_table_p^ [pp_number].flags.configured THEN
        CYCLE /search_pp_table/;
      IFEND;

      { Check to see if the controller module has already been found for this PP.

      controller_type := logical_pp_table_p^ [pp_number].controller_info.controller_type;
      CASE controller_type OF
      = cmc$mt7021_3x, cmc$mt7021_4x, cmc$mscm3_ct =
        CYCLE /search_pp_table/;
      ELSE
        ;
      CASEND;
      IF load_controller_type = cmc$load_control_module THEN
        IF logical_pp_table_p^ [pp_number].controller_info.control_module_loaded THEN
          CYCLE /search_pp_table/;
        IFEND;
      ELSE
        IF logical_pp_table_p^ [pp_number].controller_info.controlware_loaded THEN
          CYCLE /search_pp_table/;
        IFEND;
      IFEND;

      { Check to see if this particular type of controller module already exists in memory.  If it is then
      { set up the area in memory that the PP observes.  The command code must be set last because it is what
      { the PP reacts on.

      IF load_controller_type = cmc$load_control_module THEN
        IF cmv$controller_location [controller_type].control_module_loaded THEN
          IF logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p = NIL THEN
            osp$set_status_condition (cme$no_pp_communication_buffer, status);
            osp$append_status_integer (osc$status_parameter_delimiter, pp_number, 16, true, status);
            RETURN; {----->
          IFEND;

          i#real_memory_address (#LOC (cmv$controller_location [controller_type].control_module_rma_list_p^),
                rma);
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.control_module_command.address :=
                rma;
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.control_module_command.length :=
                cmv$controller_location [controller_type].control_module_rma_list_size;
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.
                control_module_command.command_code := ioc$cc_load_control_module;
          logical_pp_table_p^ [pp_number].controller_info.control_module_loaded := TRUE;
          CYCLE /search_pp_table/;
        IFEND;
      ELSE
        IF cmv$controller_location [controller_type].controlware_loaded THEN
          IF logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p = NIL THEN
            osp$set_status_condition (cme$no_pp_communication_buffer, status);
            osp$append_status_integer (osc$status_parameter_delimiter, pp_number, 16, true, status);
            RETURN; {----->
          IFEND;

          i#real_memory_address (#LOC (cmv$controller_location [controller_type].controlware_rma_list_p^),
                rma);
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.controlware_command.address :=
                rma;
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.controlware_command.length :=
                cmv$controller_location [controller_type].controlware_rma_list_size;
          logical_pp_table_p^ [pp_number].pp_info.pp_communication_buffer_p^.
                controlware_command.command_code := ioc$cc_load_controlware;
          logical_pp_table_p^ [pp_number].controller_info.controlware_loaded := TRUE;
          CYCLE /search_pp_table/;
        IFEND;
      IFEND;

    FOREND /search_pp_table/;

  PROCEND cmp$load_controller_module;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$release_channel_resource', EJECT ??

{ PURPOSE:
{   This routine is used to release channel resources.  It is used both by CM external interface initiated
{   calls and by system calls such as Change_Element_State.

  PROCEDURE [XDCL, #GATE] cmp$release_channel_resource
    (    channel: cmt$physical_channel;
         iou_number: dst$iou_number;
     VAR status: ost$status);

    VAR
      resource_request: dst$resource_request;

    status.normal := TRUE;

    resource_request.channel.number := channel.number;
    IF channel.concurrent THEN
      resource_request.channel.channel_protocol := dsc$cpt_cio;
    ELSE
      resource_request.channel.channel_protocol := dsc$cpt_nio;
    IFEND;
    resource_request.channel.iou_number := iou_number;

    cmp$request_resources (dsc$rrt_return_channel, resource_request, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND cmp$release_channel_resource;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$release_equipment_resource', EJECT ??

{ PURPOSE:
{   This routine is used to release equipment resources.  It is used both by CM external interface initiated
{   calls and by system calls such as Change_Element_State.

  PROCEDURE [XDCL, #GATE] cmp$release_equipment_resource
    (    channel: cmt$physical_channel;
         iou_number: dst$iou_number;
         equipment_number: 0 .. cmc$null_equipment_number;
         unit_number: 0 .. cmc$null_unit_number);

    VAR
      ignore_status: ost$status,
      resource_request: dst$resource_request;

    resource_request.channel.number := channel.number;
    IF channel.concurrent THEN
      resource_request.channel.channel_protocol := dsc$cpt_cio;
    ELSE
      resource_request.channel.channel_protocol := dsc$cpt_nio;
    IFEND;
    resource_request.channel.iou_number := iou_number;
    resource_request.equipment_number := ORD (equipment_number);
    resource_request.unit_number := ORD (unit_number);

    cmp$request_resources (dsc$rrt_return_equipment, resource_request, ignore_status);

  PROCEND cmp$release_equipment_resource;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$release_pp_resource', EJECT ??

{ PURPOSE:
{   This routine is used to release a PP resource.  It is used both by CM external interface initiated calls
{   and by system calls such as Change_Element_State.

  PROCEDURE [XDCL, #GATE] cmp$release_pp_resource
    (    pp_number: dst$iou_resource;
     VAR status: ost$status);

    VAR
      resource_request: dst$resource_request;

    status.normal := TRUE;

    resource_request.channel.iou_number := pp_number.iou_number;
    resource_request.options := $dst$resource_request_options [];
    resource_request.primary_pp := pp_number;

    cmp$request_resources (dsc$rrt_return_pp, resource_request, status);

  PROCEND cmp$release_pp_resource;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$release_pp_by_channel', EJECT ??

{ PURPOSE:
{   This routine is used to a release PP resource.  It is used both by CM external interface initiated calls
{   and by system calls such as Change_Element_State.

  PROCEDURE [XDCL, #GATE] cmp$release_pp_by_channel
    (    channel: cmt$physical_channel;
         iou_number: dst$iou_number;
     VAR status: ost$status);

    VAR
      pp_index:  iot$pp_number;

    status.normal := TRUE;

    cmp$retrieve_logical_pp_index (channel, iou_number, cmv$logical_pp_table_p, pp_index, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    cmp$release_pp_by_index (pp_index, status);

  PROCEND cmp$release_pp_by_channel;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$release_pp_by_index', EJECT ??

{ PURPOSE:
{   This routine is used to a release PP resource.  It is used both by CM external interface initiated calls
{   and by system calls such as Change_Element_State.

  PROCEDURE [XDCL, #GATE] cmp$release_pp_by_index
    (    pp_index: iot$pp_number;
     VAR status: ost$status);

    VAR
      partner_pp_index:  iot$pp_number,
      resource_request: dst$resource_request;

    status.normal := TRUE;

    IF NOT cmv$logical_pp_table_p^ [pp_index].flags.resources_acquired THEN
      RETURN;
    IFEND;

    resource_request.channel.number := 0;
    resource_request.channel.channel_protocol :=
          cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp.channel_protocol;
    resource_request.channel.iou_number := cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp.iou_number;
    resource_request.options := $dst$resource_request_options [];
    resource_request.primary_pp := cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp;
    partner_pp_index := cmv$logical_pp_table_p^ [pp_index].pp_info.logical_partner_pp_index;
    IF (partner_pp_index > 0) AND cmv$logical_pp_table_p^ [partner_pp_index].flags.resources_acquired THEN
      resource_request.secondary_pp := cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp;
      resource_request.options := $dst$resource_request_options [dsc$rro_partner_pp];
    IFEND;

    cmp$request_resources (dsc$rrt_return_pp, resource_request, status);
    IF NOT status.normal THEN
       RETURN;
    IFEND;

    IF partner_pp_index > 0 THEN
      IF (cmv$system_device_pp.primary_pp = cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp) AND
            (cmv$system_device_pp.partner_pp =
            cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp) THEN
        cmv$system_device_pp.dual_pp := FALSE;
      IFEND;
    IFEND;

    cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp.iou_number := 0;
    cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp.channel_protocol := dsc$cpt_nio;
    cmv$logical_pp_table_p^ [pp_index].pp_info.physical_pp.number := 33(8);
    cmv$logical_pp_table_p^ [pp_index].flags.resources_acquired := FALSE;
    IF partner_pp_index > 0 THEN
      cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp.iou_number := 0;
      cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp.channel_protocol := dsc$cpt_nio;
      cmv$logical_pp_table_p^ [partner_pp_index].pp_info.physical_pp.number := 33(8);
      cmv$logical_pp_table_p^ [partner_pp_index].flags.resources_acquired := FALSE;
    IFEND;

    cmp$assign_pp_r1 (FALSE, pp_index);
    IF partner_pp_index > 0 THEN
      cmp$assign_pp_r1 (FALSE, partner_pp_index);
    IFEND;

  PROCEND cmp$release_pp_by_index;
?? OLDTITLE ??
?? NEWTITLE := 'cmp$request_resources', EJECT ??

{ PURPOSE:
{   This procedure makes a call to deadstart routines to request hardware resources.
{ DESIGN:
{   The parameter resource_request is both INPUT and OUTPUT.

  PROCEDURE [XDCL] cmp$request_resources
    (    request_type: dst$resource_request_types;
     VAR resource_request: dst$resource_request;
     VAR status: ost$status);

    IF (request_type = dsc$rrt_get_equipment) AND
         (resource_request.channel.channel_protocol = dsc$cpt_cio) THEN
      resource_request.resource_request_type := dsc$rrt_get_channel;
    ELSEIF (request_type = dsc$rrt_return_equipment) AND
         (resource_request.channel.channel_protocol = dsc$cpt_cio) THEN
      resource_request.resource_request_type := dsc$rrt_return_channel;
    ELSE
      resource_request.resource_request_type := request_type;
    IFEND;
    dsp$request_resources (resource_request, status);

  PROCEND cmp$request_resources;
?? OLDTITLE ??
MODEND cmm$manage_170_resources;
