MODULE iom$allocate_usage_counters;
?? RIGHT := 110 ??

{PURPOSE:
{  Allocate structure for path & unit statistics. Also update the structure when new pathes
{  are enabled.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmc$logical_unit_constants
*copyc cmt$controller_type
*copyc cmt$logical_pp_table
*copyc cmt$physical_equipment_number
*copyc iot$disk_type_table
*copyc iot$disk_usage
*copyc iot$logical_unit
*copyc iot$pp_interface_table
*copyc iot$pp_table
*copyc iot$unit_interface_table
?? POP ??
*copyc cmp$get_element_name_via_lun
*copyc dpp$put_critical_message
*copyc pmp$zero_out_table
*copyc cmv$logical_pp_table_p
*copyc cmv$logical_unit_table
*copyc iov$disk_pp_usage_p
*copyc iov$disk_type_table
*copyc iov$disk_unit_usage_p
*copyc osv$mainframe_wired_heap
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] IOP$UPDATE_USAGE_ALLOCATION', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$update_usage_allocation
    (VAR status: ost$status);

    VAR
      bytes_per_mau: iot$bytes_per_mau,
      channel: cmt$physical_channel,
      controller_type: cmt$controller_type,
      disk_channel: boolean,
      element_name: cmt$element_name,
      equipment: cmt$physical_equipment_number,
      i: integer,
      iou_number: dst$iou_number,
      pico_channel: boolean,
      port_index: 0 .. 1,
      pp: integer,
      pp_count: integer,
      pp_usage_p: ^iot$disk_pp_usage,
      size: integer,
      str: string (80),
      unit: iot$logical_unit,
      unit_count: integer,
      unit_type: iot$unit_type,
      unit_usage_p: ^iot$disk_unit_usage;

    status.normal := TRUE;
    IF (cmv$logical_pp_table_p = NIL) OR (cmv$logical_unit_table = NIL) OR (iov$disk_unit_usage_p = NIL) OR
          (iov$disk_pp_usage_p = NIL) THEN
      dpp$put_critical_message (' Statistics not yet established.', status);
      RETURN; {----->
    IFEND;

    pp_count := UPPERBOUND (cmv$logical_pp_table_p^);
    IF pp_count > UPPERBOUND (iov$disk_pp_usage_p^) THEN
      dpp$put_critical_message (' Unable to extend PP statistics.', status);
      status.normal := TRUE;
      RETURN; {----->
    IFEND;

    unit_count := UPPERBOUND (cmv$logical_unit_table^);
    IF unit_count > UPPERBOUND (iov$disk_unit_usage_p^) THEN
      dpp$put_critical_message (' Unable to extend Unit statistics.', status);
      status.normal := TRUE;
      RETURN; {----->
    IFEND;

    FOR pp := 1 TO pp_count DO
      IF cmv$logical_pp_table_p^ [pp].flags.configured THEN
        controller_type := cmv$logical_pp_table_p^ [pp].controller_info.controller_type;
        CASE controller_type OF
        = cmc$ms7154_x, cmc$ms7155_1, cmc$ms7155_1x, cmc$ms7255_1_1, cmc$ms7255_1_2, cmc$mshydra_ct,
              cmc$ms7165_2x, cmc$mscm3_ct, cmc$ms5831_x =
          disk_channel := TRUE;
          pico_channel := FALSE;

        = cmc$msntdc_1, cmc$msntdc_2 =
          disk_channel := TRUE;
          pico_channel := TRUE;

        ELSE
          disk_channel := FALSE;
        CASEND;

        IF disk_channel AND ((cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p = NIL) OR
              (NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave)) THEN
          iou_number := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;

        /unit_descriptor_loop/
          FOR unit := LOWERBOUND (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors)
                TO UPPERBOUND (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors) DO
            IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                  unit_interface_table_rma = 0 THEN
              CYCLE /unit_descriptor_loop/; {----->
            IFEND;

            equipment := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                  physical_path.controller_number;
            channel.number := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.
                  unit_descriptors [unit].physical_path.channel_number;
            channel.concurrent := cmv$logical_pp_table_p^ [pp].pp_info.channel_interlock_p^.
                  channel_characteristics [channel.number].concurrent_channel;
            port_index := 0;

            unit_type := cmv$logical_unit_table^ [unit].unit_interface_table^.unit_type;
            bytes_per_mau := iov$disk_type_table [unit_type - 100(16) + 1].bytes_per_mau;

            IF channel.concurrent THEN
              IF (controller_type = cmc$ms5831_x) OR (controller_type = cmc$msntdc_1) OR
                    (controller_type = cmc$msntdc_2) OR (controller_type = cmc$mshydra_ct) OR
                    (controller_type = cmc$mscm3_ct) THEN
                IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                      physical_path.port = 1 THEN
                  channel.port := cmc$port_b;
                  port_index := 1;
                ELSE
                  channel.port := cmc$port_a;
                IFEND;
              ELSE
                channel.port := cmc$unspecified_port;
              IFEND;
            ELSE
              channel.port := cmc$unspecified_port;
            IFEND;


            IF iov$disk_pp_usage_p^ [pp] = NIL THEN
              ALLOCATE pp_usage_p IN osv$mainframe_wired_heap^;
              size := #SIZE (pp_usage_p^);
              pmp$zero_out_table (#LOC (pp_usage_p^), size);
              pp_usage_p^.iou_number := iou_number;
              pp_usage_p^.channel := channel;
              FOR i := 0 TO 7 DO
                pp_usage_p^.path_usage [0] [i].pico_usage_p := NIL;
                pp_usage_p^.path_usage [1] [i].pico_usage_p := NIL;
              FOREND;

              iov$disk_pp_usage_p^ [pp] := pp_usage_p;

              STRINGREP (str, i, ' Statistics established for PP ', pp);
              dpp$put_critical_message (str (1, i), status);
              status.normal := TRUE;
            IFEND;

            pp_usage_p := iov$disk_pp_usage_p^ [pp];
            IF NOT pp_usage_p^.path_usage [port_index] [equipment].path_configured THEN
              pp_usage_p^.path_usage [port_index] [equipment].path_configured := TRUE;
              pp_usage_p^.path_usage [port_index] [equipment].path_used := FALSE;
              pp_usage_p^.path_usage [port_index] [equipment].logical_unit := unit;
              pp_usage_p^.path_usage [port_index] [equipment].bytes_per_mau := bytes_per_mau;
              pp_usage_p^.path_usage [port_index] [equipment].path_type :=
                    cmv$logical_pp_table_p^ [pp].controller_info.controller_type;

              STRINGREP (str, i, ' Statistic path configured for PP ', pp, ' Port: ', port_index,
                    ' Equipment ', equipment);
              dpp$put_critical_message (str (1, i), status);
              status.normal := TRUE;
            IFEND;

            IF pico_channel THEN
              IF pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p = NIL THEN
                ALLOCATE pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p IN
                      osv$mainframe_wired_heap^;
                size := #SIZE (pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p^);
                pmp$zero_out_table (#LOC (pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p^),
                      size);
              IFEND;
            IFEND;

            IF iov$disk_unit_usage_p^ [unit] = NIL THEN
              ALLOCATE unit_usage_p IN osv$mainframe_wired_heap^;
              size := #SIZE (unit_usage_p^);
              pmp$zero_out_table (#LOC (unit_usage_p^), size);
              cmp$get_element_name_via_lun (unit, element_name, status);
              unit_usage_p^.unit_configured := TRUE;
              unit_usage_p^.unit_used := FALSE;
              unit_usage_p^.iou_number := iou_number;
              unit_usage_p^.channel := channel;
              unit_usage_p^.equipment := equipment;
              unit_usage_p^.recorded_vsn := '      ';
              unit_usage_p^.unit_type := unit_type;
              unit_usage_p^.bytes_per_mau := bytes_per_mau;
              unit_usage_p^.element_name := element_name;
              unit_usage_p^.last_request_good := TRUE;

              iov$disk_unit_usage_p^ [unit] := unit_usage_p;

              STRINGREP (str, i, ' Statistics established for unit', unit);
              dpp$put_critical_message (str (1, i), status);
              status.normal := TRUE;
            IFEND;
          FOREND /unit_descriptor_loop/;
        IFEND;
      IFEND;
    FOREND;

  PROCEND iop$update_usage_allocation;
?? OLDTITLE ??
?? NEWTITLE := 'iop$allocate_usage_counters', EJECT ??

  PROCEDURE [XDCL] iop$allocate_usage_counters
    (VAR status: ost$status);

    VAR
      bytes_per_mau: iot$bytes_per_mau,
      channel: cmt$physical_channel,
      controller_type: cmt$controller_type,
      disk_channel: boolean,
      element_name: cmt$element_name,
      equipment: cmt$physical_equipment_number,
      i: integer,
      iou_number: dst$iou_number,
      pico_channel: boolean,
      port_index: 0 .. 1,
      pp: integer,
      pp_count: integer,
      pp_usage_array_p: ^iot$disk_pp_array,
      pp_usage_p: ^iot$disk_pp_usage,
      size: integer,
      unit: iot$logical_unit,
      unit_count: integer,
      unit_type: iot$unit_type,
      unit_usage_array_p: ^iot$disk_unit_array,
      unit_usage_p: ^iot$disk_unit_usage;

    status.normal := TRUE;
    IF (cmv$logical_pp_table_p = NIL) OR (cmv$logical_unit_table = NIL) THEN
      RETURN; {----->
    IFEND;
    pp_count := UPPERBOUND (cmv$logical_pp_table_p^);
    ALLOCATE pp_usage_array_p: [1 .. pp_count] IN osv$mainframe_wired_heap^;
    FOR pp := 1 TO pp_count DO
      pp_usage_array_p^ [pp] := NIL;
    FOREND;
    unit_count := UPPERBOUND (cmv$logical_unit_table^);
    ALLOCATE unit_usage_array_p: [1 .. unit_count] IN osv$mainframe_wired_heap^;
    FOR unit := 1 TO unit_count DO
      unit_usage_array_p^ [unit] := NIL;
    FOREND;

    FOR pp := 1 TO pp_count DO
      IF cmv$logical_pp_table_p^ [pp].flags.configured THEN
        controller_type := cmv$logical_pp_table_p^ [pp].controller_info.controller_type;
        CASE controller_type OF
        = cmc$ms7154_x, cmc$ms7155_1, cmc$ms7155_1x, cmc$ms7255_1_1, cmc$ms7255_1_2, cmc$mshydra_ct,
              cmc$ms7165_2x, cmc$mscm3_ct, cmc$ms5831_x =

          disk_channel := TRUE;
          pico_channel := FALSE;

        = cmc$msntdc_1, cmc$msntdc_2 =

          disk_channel := TRUE;
          pico_channel := TRUE;

        ELSE
          disk_channel := FALSE;
        CASEND;

        IF disk_channel AND ((cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p = NIL) OR
              (NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave)) THEN
          iou_number := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;

        /unit_descriptor_loop/
          FOR unit := LOWERBOUND (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors)
                TO UPPERBOUND (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors) DO
            IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                  unit_interface_table_rma = 0 THEN
              CYCLE /unit_descriptor_loop/; {----->
            IFEND;

            equipment := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                  physical_path.controller_number;
            channel.number := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.
                  unit_descriptors [unit].physical_path.channel_number;
            channel.concurrent := cmv$logical_pp_table_p^ [pp].pp_info.channel_interlock_p^.
                  channel_characteristics [channel.number].concurrent_channel;
            port_index := 0;

            unit_type := cmv$logical_unit_table^ [unit].unit_interface_table^.unit_type;
            bytes_per_mau := iov$disk_type_table [unit_type - 100(16) + 1].bytes_per_mau;

            IF channel.concurrent THEN
              IF (controller_type = cmc$ms5831_x) OR (controller_type = cmc$msntdc_1) OR
                    (controller_type = cmc$msntdc_2) OR (controller_type = cmc$mshydra_ct) OR
                    (controller_type = cmc$mscm3_ct) THEN
                IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [unit].
                      physical_path.port = 1 THEN
                  channel.port := cmc$port_b;
                  port_index := 1;
                ELSE
                  channel.port := cmc$port_a;
                IFEND;
              ELSE
                channel.port := cmc$unspecified_port;
              IFEND;
            ELSE
              channel.port := cmc$unspecified_port;
            IFEND;

            IF pp_usage_array_p^ [pp] = NIL THEN
              ALLOCATE pp_usage_p IN osv$mainframe_wired_heap^;
              size := #SIZE (pp_usage_p^);
              pmp$zero_out_table (#LOC (pp_usage_p^), size);
              pp_usage_p^.iou_number := iou_number;
              pp_usage_p^.channel := channel;
              FOR i := 0 TO 7 DO
                pp_usage_p^.path_usage [0] [i].pico_usage_p := NIL;
                pp_usage_p^.path_usage [1] [i].pico_usage_p := NIL;
              FOREND;
              pp_usage_array_p^ [pp] := pp_usage_p;
            IFEND;

            pp_usage_p := pp_usage_array_p^ [pp];
            pp_usage_p^.path_usage [port_index] [equipment].path_configured := TRUE;
            pp_usage_p^.path_usage [port_index] [equipment].path_used := FALSE;
            pp_usage_p^.path_usage [port_index] [equipment].logical_unit := unit;
            pp_usage_p^.path_usage [port_index] [equipment].bytes_per_mau := bytes_per_mau;
            pp_usage_p^.path_usage [port_index] [equipment].path_type :=
                  cmv$logical_pp_table_p^ [pp].controller_info.controller_type;

            IF pico_channel THEN
              IF pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p = NIL THEN
                ALLOCATE pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p IN
                      osv$mainframe_wired_heap^;
                size := #SIZE (pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p^);
                pmp$zero_out_table (#LOC (pp_usage_p^.path_usage [port_index] [equipment].pico_usage_p^),
                      size);
              IFEND;
            IFEND;

            IF unit_usage_array_p^ [unit] = NIL THEN
              ALLOCATE unit_usage_p IN osv$mainframe_wired_heap^;
              size := #SIZE (unit_usage_p^);
              pmp$zero_out_table (#LOC (unit_usage_p^), size);
              cmp$get_element_name_via_lun (unit, element_name, status);
              unit_usage_p^.unit_configured := TRUE;
              unit_usage_p^.unit_used := FALSE;
              unit_usage_p^.iou_number := iou_number;
              unit_usage_p^.channel := channel;
              unit_usage_p^.equipment := equipment;
              unit_usage_p^.recorded_vsn := '      ';
              unit_usage_p^.unit_type := unit_type;
              unit_usage_p^.bytes_per_mau := bytes_per_mau;
              unit_usage_p^.element_name := element_name;
              unit_usage_p^.last_request_good := TRUE;
              unit_usage_array_p^ [unit] := unit_usage_p;
            IFEND;
          FOREND /unit_descriptor_loop/;
        IFEND;
      IFEND;
    FOREND;

    iov$disk_unit_usage_p := unit_usage_array_p;
    iov$disk_pp_usage_p := pp_usage_array_p;

  PROCEND iop$allocate_usage_counters;
?? OLDTITLE ??
?? TITLE := 'IOP$GET_PICO_STATISTICS', EJECT ??

{ Temporary interface, for debugging purposes only

  PROCEDURE [XDCL, #GATE] iop$get_pico_statistics
    (VAR accept_pico_statistics: boolean;
     VAR pico_statistics_call_count: integer;
     VAR pico_statistics_skip_count: integer;
     VAR pico_unsolicited_msg_count: integer);

    VAR
      iov$accept_pico_statistics: [XREF] boolean,
      iov$pico_statistics_call_count: [XREF] integer,
      iov$pico_statistics_skip_count: [XREF] integer,
      iov$pico_unsolicited_msg_count: [XREF] integer;

    accept_pico_statistics := iov$accept_pico_statistics;
    pico_statistics_call_count := iov$pico_statistics_call_count;
    pico_statistics_skip_count := iov$pico_statistics_skip_count;
    pico_unsolicited_msg_count := iov$pico_unsolicited_msg_count;

  PROCEND iop$get_pico_statistics;

MODEND iom$allocate_usage_counters;

