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

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$mainframe_wired
*copyc ioe$st_errors
*copyc mme$condition_codes
*copyc amt$file_byte_address
*copyc cmt$element_capabilities
*copyc cmt$element_name
*copyc cmt$element_state
*copyc cmt$physical_address
*copyc cmt$physical_equipment_number
*copyc cmt$signal_contents
*copyc dmt$minimum_allocation_unit
*copyc dmt$ms_logical_device_address
*copyc gft$system_file_identifier
*copyc iot$completion_status
*copyc iot$cylinder
*copyc iot$disk_request
*copyc iot$io_function
*copyc iot$io_request
*copyc iot$lockword
*copyc iot$logical_unit
*copyc iot$pp_interface_table
*copyc iot$pp_number
*copyc iot$pp_table
*copyc iot$request_heap_map
*copyc iot$unit_type
*copyc jmt$ijl_ordinal
*copyc mmt$io_identifier
*copyc mmt$rma_list
*copyc ost$cpu_state_table
*copyc ost$physical_channel_number
*copyc syt$monitor_status
?? POP ??
*copyc clp$trimmed_string_size
*copyc cmp$change_connection_status
*copyc cmp$locate_element_via_adr
*copyc cmp$reenable_unit
*copyc cmp$switch_to_redundant_path
*copyc cmp$verify_active_path_exists
*copyc dfp$fetch_server_iocb
*copyc dmp$transfer_unit_completed
*copyc dmp$volume_down
*copyc dmp$volume_up
*copyc dpp$convert_int_to_str_octal
*copyc dpp$convert_int_to_str_hex
*copyc dpp$display_error
*copyc dsp$mtr_save_disk_error
*copyc dsp$perform_cpu_pp_handshaking
*copyc iop$check_idle_pps
*copyc iop$clear_queue_lockword
*copyc iop$idle_resume
*copyc iop$process_disk_response
*copyc iop$set_queue_lockword
*copyc mmp$mtr_process_io_completion
*copyc mmp$mtr_process_server_complete
*copyc mmp$process_read_ahead_complete
*copyc mmp$unlock_rma_list
*copyc mtp$cst_p
*copyc mtp$error_stop
*copyc tmp$send_signal
*copyc cmv$controller_address
*copyc cmv$enable_auto_reconfiguration
*copyc cmv$logical_pp_table_p
*copyc cmv$logical_unit_table
*copyc cmv$peripheral_element_table
*copyc cmv$pp_element_table
*copyc iov$disk_pp_usage_p
*copyc iov$disk_unit_usage_p
*copyc mtv$time_to_call_handshaking
*copyc tmv$system_job_monitor_gtid
*copyc i#real_memory_address

  VAR
    iov$reject_interlock_set: [XREF] integer,
    iov$request_heap_map: [XREF] iot$request_heap_map,
    iov$command_heap_map: [XREF] iot$command_heap_map,
    iov$stream_requests: [XREF] array [0 .. 300] of ^iot$io_request,
    iov$stream_requests_end: [XREF] array [0 .. 300] of ^^iot$io_request,
    iov$empty_requests: [XREF] ^iot$io_request,
    iov$empty_requests_end: [XREF] ^^iot$io_request,
    iov$empty_request_count: [XREF] integer;

  VAR
    cmv$display_config_debug_msg: [XREF] boolean;

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

  VAR
    iov$debug: [XDCL, #GATE] 0 .. 255 := 0,
    iov$requests_dequeued: [XDCL, STATIC, oss$mainframe_wired] integer := 0,
    iov$unit_not_disabled: [XDCL, STATIC, oss$mainframe_wired] integer := 0,
    iov$no_idle_request: [XDCL, STATIC, oss$mainframe_wired] integer := 0,
    iov$no_resume_request: [XDCL, STATIC, oss$mainframe_wired] integer := 0;

?? TITLE := '  iop$down_disk_unit', EJECT ??

  PROCEDURE [XDCL] iop$down_disk_unit
    (    pp: iot$pp_number;
         channel: cmt$physical_channel;
         equipment: cmt$physical_equipment_number;
         unit: cmt$physical_unit_number;
         logical_unit: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      active_controller_path_exists: boolean,
      active_unit_path_exists: boolean,
      controller_path: cmt$physical_address,
      element_p: ^cmt$peripheral_element_entry,
      number_of_units: iot$logical_unit,
      signal_contents: cmt$signal_contents,
      successful: boolean,
      unit_element_p: ^cmt$peripheral_element_entry,
      unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      unit_path: cmt$physical_address;

    status.normal := TRUE;

    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$DOWN_DISK_UNIT');
    IFEND;

    controller_path.address_specifier := $cmt$physical_address_specifier
          [cmc$iou, cmc$channel, cmc$channel_address];
    controller_path.iou := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;
    controller_path.channel := channel;
    controller_path.channel_address := equipment;
    controller_path.unit_address := 0;

    unit_path := controller_path;
    unit_path.address_specifier := $cmt$physical_address_specifier
          [cmc$iou, cmc$channel, cmc$channel_address, cmc$unit_address];
    unit_path.unit_address := unit;


  /locate_redundant_path/
    BEGIN
      cmp$change_connection_status (unit_path, cmc$disabled);
      IF NOT cmv$enable_auto_reconfiguration THEN
        EXIT /locate_redundant_path/; {----->
      IFEND;

      cmp$verify_active_path_exists (unit_path, active_unit_path_exists);
      cmp$verify_active_path_exists (controller_path, active_controller_path_exists);

      IF NOT active_controller_path_exists THEN
        signal_contents.signal_type := cmc$disable_element_signal;
        signal_contents.disable_element_address := controller_path;
        signal_contents.fill3 := ' ';

        send_cm_signal (signal_contents);

        {
        { Even though this controller has no active paths the unit may have
        { other controllers connected to it, so attempt reconfiguration.
        {
      ELSEIF NOT active_unit_path_exists THEN
        signal_contents.signal_type := cmc$disable_element_signal;
        signal_contents.disable_element_address := unit_path;
        signal_contents.fill3 := ' ';

        send_cm_signal (signal_contents);

        {
        { If the unit has no active paths, do not attempt reconfiguration.
        {
        EXIT /locate_redundant_path/; {----->
      IFEND;

      cmp$switch_to_redundant_path (pp, unit_path, successful);
      IF successful THEN
        signal_contents.signal_type := cmc$reconfiguration_signal;
        signal_contents.reconfig_element_address := unit_path;
        signal_contents.failing_element_address := unit_path;
        signal_contents.fill1 := ' ';

        send_cm_signal (signal_contents);
        dpp$display_error ('Successfully reconfigured to redundant_access.');
        {
        {If reconfiguration is successful exit without disabling any units.
        {
        RETURN; {----->
      IFEND;

    END /locate_redundant_path/;

    number_of_units := 1;
    PUSH unit_list_p: [1 .. 1];
    unit_list_p^ [1] := logical_unit;
    auto_disable (pp, unit_list_p, number_of_units, status);

  PROCEND iop$down_disk_unit;

?? TITLE := '  iop$down_disk_controller', EJECT ??

  PROCEDURE [XDCL] iop$down_disk_controller
    (    pp: iot$pp_number;
         channel: cmt$physical_channel;
         equipment: cmt$physical_equipment_number;
     VAR status: syt$monitor_status);

    VAR
      controller_path: cmt$physical_address,
      local_status: syt$monitor_status,
      nu: iot$logical_unit,
      number_of_units: iot$logical_unit,
      path: cmt$physical_address,
      signal_contents: cmt$signal_contents,
      successful: boolean,
      unit_list_p: ^array [1 .. * ] of iot$logical_unit;

    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$DOWN_DISK_CONTROLLER');
    IFEND;

    controller_path.address_specifier := $cmt$physical_address_specifier
          [cmc$iou, cmc$channel, cmc$channel_address];
    controller_path.iou := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;
    controller_path.channel := channel;
    controller_path.channel_address := equipment;
    controller_path.unit_address := 0;

  /locate_redundant_path/
    BEGIN
      cmp$change_connection_status (controller_path, cmc$disabled);
      IF NOT cmv$enable_auto_reconfiguration THEN
        EXIT /locate_redundant_path/; {----->
      IFEND;

      cmp$switch_to_redundant_path (pp, controller_path, successful);
      IF successful THEN
        signal_contents.signal_type := cmc$reconfiguration_signal;
        signal_contents.reconfig_element_address := controller_path;
        signal_contents.failing_element_address := controller_path;
        signal_contents.fill1 := ' ';

        send_cm_signal (signal_contents);
        dpp$display_error ('Successfully reconfigured to redundant_access.');
        {
        {If reconfiguration is successful exit without disabling any units.
        {
        RETURN; {----->
      IFEND;

    END /locate_redundant_path/;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH unit_list_p: [1 .. nu];
    get_controller_units (pp, channel.number, equipment, unit_list_p, number_of_units);
    auto_disable (pp, unit_list_p, number_of_units, status);
    {
    { By reaching this point in the code we know that reconfiguration
    { has failed and one or more units have been disabled.
    { We will send a disable controller signal to assist analysis.
    {
    signal_contents.signal_type := cmc$disable_element_signal;
    signal_contents.disable_element_address := controller_path;
    signal_contents.fill3 := ' ';

    send_cm_signal (signal_contents);

  PROCEND iop$down_disk_controller;

?? TITLE := '  iop$down_disk_channel', EJECT ??

  PROCEDURE [XDCL] iop$down_disk_channel
    (    pp: iot$pp_number;
         channel: cmt$physical_channel;
     VAR status: syt$monitor_status);

    VAR
      channel_path: cmt$physical_address,
      signal: pmt$signal,
      signal_contents: cmt$signal_contents,
      successful: boolean,
      unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      number_of_units: iot$logical_unit,
      nu: iot$logical_unit;

    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$DOWN_DISK_CHANNEL');
    IFEND;

    channel_path.address_specifier := $cmt$physical_address_specifier [cmc$iou, cmc$channel];
    channel_path.iou := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;
    channel_path.channel := channel;
    channel_path.channel_address := 0;
    channel_path.unit_address := 0;

  /locate_redundant_path/
    BEGIN
      cmp$change_connection_status (channel_path, cmc$disabled);
      IF NOT cmv$enable_auto_reconfiguration THEN
        EXIT /locate_redundant_path/; {----->
      IFEND;

      cmp$switch_to_redundant_path (pp, channel_path, successful);
      IF successful THEN
        signal_contents.signal_type := cmc$reconfiguration_signal;
        signal_contents.reconfig_element_address := channel_path;
        signal_contents.failing_element_address := channel_path;
        signal_contents.fill1 := ' ';

        send_cm_signal (signal_contents);
        dpp$display_error ('Successfully reconfigured to redundant_access.');
        {
        {If reconfiguration is successful exit without disabling any units.
        {
        RETURN; {----->
      IFEND;
    END /locate_redundant_path/;


    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH unit_list_p: [1 .. nu];
    get_channel_units (pp, channel.number, unit_list_p, number_of_units);
    auto_disable (pp, unit_list_p, number_of_units, status);
    {
    { By reaching this point in the code we know that reconfiguration
    { has failed and one or more units have been disabled.
    { We will send a disable channel signal to assist analysis.
    {
    signal_contents.signal_type := cmc$disable_element_signal;
    signal_contents.disable_element_address := channel_path;
    signal_contents.fill3 := ' ';

    send_cm_signal (signal_contents);

  PROCEND iop$down_disk_channel;

?? TITLE := '  iop$change_disk_unit', EJECT ??

  PROCEDURE [XDCL] iop$change_disk_unit
    (    new_state: cmt$element_state;
         logical_unit: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      number_of_units: iot$logical_unit,
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      np: iot$pp_number,
      number_of_pps: iot$pp_number;



    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$CHANGE_DISK_UNIT');
    IFEND;

    number_of_units := 1;
    PUSH unit_list_p: [1 .. 1];
    np := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list_p: [1 .. np];

    unit_list_p^ [1] := logical_unit;

    get_pps_to_units (unit_list_p, number_of_units, pp_list_p, number_of_pps);

    enable_disable (pp_list_p, number_of_pps, unit_list_p, number_of_units, status);

    IF ((NOT status.normal) AND (status.condition = ioc$critical_device_disabled)) THEN
      RETURN; {----->
    IFEND;

    IF new_state = cmc$down THEN

      cmv$logical_unit_table^ [logical_unit].element_capability :=
            $cmt$element_capabilities [cmc$concurrent_maintenance, cmc$dedicated_maintenance];
    ELSEIF new_state = cmc$off THEN

      cmv$logical_unit_table^ [logical_unit].element_capability := $cmt$element_capabilities [];
      cmv$logical_unit_table^ [logical_unit].element_access := $cmt$element_access [];

    IFEND;



  PROCEND iop$change_disk_unit;

?? TITLE := '  iop$change_disk_controller', EJECT ??

  PROCEDURE [XDCL] iop$change_disk_controller
    (    new_state: cmt$element_state;
         pp: 1 .. ioc$pp_count;
         channel: ost$physical_channel_number;
         controller: cmt$physical_equipment_number;
     VAR status: syt$monitor_status);

    VAR
      unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      number_of_units: iot$logical_unit,
      nu: iot$logical_unit,
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      np: iot$pp_number,
      number_of_pps: iot$pp_number;

    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$CHANGE_DISK_CONTROLLER');
    IFEND;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH unit_list_p: [1 .. nu];
    np := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list_p: [1 .. np];

    get_controller_units (pp, channel, controller, unit_list_p, number_of_units);

    get_pps_to_units (unit_list_p, number_of_units, pp_list_p, number_of_pps);

    enable_disable (pp_list_p, number_of_pps, unit_list_p, number_of_units, status);

  PROCEND iop$change_disk_controller;

?? TITLE := '  iop$change_disk_channel', EJECT ??

  PROCEDURE [XDCL] iop$change_disk_channel
    (    new_state: cmt$element_state;
         pp: 1 .. ioc$pp_count;
         channel: ost$physical_channel_number;
     VAR status: syt$monitor_status);

    VAR
      unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      number_of_units: iot$logical_unit,
      nu: iot$logical_unit,
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      number_of_pps: iot$pp_number;

    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$CHANGE_DISK_CHANNEL');
    IFEND;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH unit_list_p: [1 .. nu];
    number_of_pps := 1;
    PUSH pp_list_p: [1 .. number_of_pps];

    get_channel_units (pp, channel, unit_list_p, number_of_units);

    pp_list_p^ [number_of_pps] := pp;

    IF iov$debug = 01(16) THEN
      mtp$error_stop (' Debug stop 01(16) in iop$change_disk_channel');
    IFEND;

    enable_disable (pp_list_p, number_of_pps, unit_list_p, number_of_units, status);

  PROCEND iop$change_disk_channel;

?? TITLE := '  iop$enable_all_disk_units', EJECT ??

  PROCEDURE [XDCL] iop$enable_all_disk_units
    (VAR status: syt$monitor_status);

    VAR
      unit_interface_table: ^iot$unit_interface_table,
      pp: iot$pp_number,
      p: iot$pp_number,
      ud: integer,
      logical_unit: iot$logical_unit,
      lu: iot$logical_unit,
      i: integer,
      eu: integer,
      meu: integer,
      l: integer,
      u: integer,
      mep: integer,
      rr: integer,
      ep: integer,
      ed: integer,
      enable_disable_list_p: ^array [1 .. * ] of iot$logical_unit,
      enable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      maybe_enable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      nu: iot$logical_unit,
      np: iot$pp_number,
      pp_list2_p: ^array [1 .. * ] of iot$pp_number,
      maybe_enable_pp_p: ^array [1 .. * ] of iot$pp_number,
      enable_pp_list_p: ^array [1 .. * ] of iot$pp_number,
      npp: iot$pp_number,
      enabled_path: boolean,
      disabled_pp_path: boolean,
      enabled_unit: boolean,
      path: cmt$physical_address;

    status.normal := TRUE;
    IF cmv$display_config_debug_msg THEN
      dpp$display_error ('IOP$ENABLE_ALL_DISK_UNITS');
    IFEND;

    IF cmv$logical_unit_table = NIL THEN
      RETURN; {----->
    IFEND;

    eu := 0;
    meu := 0;
    mep := 0;
    ep := 0;
    ed := 0;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH enable_disable_list_p: [1 .. nu];
    PUSH enable_unit_list_p: [1 .. nu];
    PUSH maybe_enable_unit_list_p: [1 .. nu];
    np := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list2_p: [1 .. np];
    PUSH maybe_enable_pp_p: [1 .. np];
    PUSH enable_pp_list_p: [1 .. np];


{ Get list of units to possibly enable.

    FOR i := 1 TO UPPERBOUND (cmv$logical_unit_table^) DO
      IF cmv$logical_unit_table^ [i].configured THEN
        unit_interface_table := cmv$logical_unit_table^ [i].unit_interface_table;
        IF unit_interface_table <> NIL THEN
          IF (unit_interface_table^.unit_type >= ioc$lowest_disk_unit) AND
                (unit_interface_table^.unit_type <= ioc$highest_disk_unit) THEN
            lu := unit_interface_table^.logical_unit;
            IF (NOT (cmc$io_request_submission IN cmv$logical_unit_table^ [lu].element_capability) OR
                  unit_interface_table^.unit_status.disabled) THEN
              ed := ed + 1;
              enable_disable_list_p^ [ed] := i;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    FOREND;


{ Determine which units to enable.

    IF ed > 0 THEN
      get_pps_to_units (enable_disable_list_p, ed, pp_list2_p, npp);

    /check2/
      FOR lu := 1 TO ed DO
        logical_unit := enable_disable_list_p^ [lu];
        enabled_path := FALSE;
        disabled_pp_path := FALSE;
        rr := mep;

        IF npp > 0 THEN

        /pp_check/
          FOR p := 1 TO npp DO
            pp := pp_list2_p^ [p];

          /units/
            FOR ud := 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 [ud].
                    unit_interface_table_rma <> 0) THEN
                IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                      logical_unit = logical_unit THEN
                  get_path (pp, ud, path);
                  IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN
                    IF NOT (cmp$reenable_unit (path)) THEN
                      CYCLE /check2/; {----->
                    ELSE
                      enabled_path := TRUE;
                    IFEND;
                  ELSEIF (cmp$reenable_unit (path)) THEN
                    disabled_pp_path := TRUE;
                    IF rr > 0 THEN
                      FOR i := 1 TO rr DO
                        IF (maybe_enable_pp_p^ [i] = pp) THEN
                          CYCLE /units/; {----->
                        IFEND;
                      FOREND;
                    IFEND;
                    rr := rr + 1;
                    maybe_enable_pp_p^ [rr] := pp;
                  IFEND;
                IFEND;
              IFEND;
            FOREND /units/;
          FOREND /pp_check/;
        IFEND;

        IF enabled_path THEN
          eu := eu + 1;
          enable_unit_list_p^ [eu] := logical_unit;
          mep := rr;
        ELSEIF disabled_pp_path THEN
          meu := meu + 1;
          maybe_enable_unit_list_p^ [meu] := logical_unit;
          mep := rr;
        IFEND;
      FOREND /check2/;
    IFEND;


{ Enable units.

    IF eu > 0 THEN
      enable_units (enable_unit_list_p, eu, status);
    IFEND;


{ Determine if any PP should be enabled.

    IF mep > 0 THEN

    /enable_pp/
      FOR p := 1 TO mep DO
        pp := maybe_enable_pp_p^ [p];
        enabled_unit := FALSE;

      /unit_search/
        FOR ud := 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 [ud].
                unit_interface_table_rma <> 0) THEN

            get_path (pp, ud, path);
            IF meu > 0 THEN
              FOR u := 1 TO meu DO
                IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                      logical_unit = maybe_enable_unit_list_p^ [u]) THEN
                  IF (cmp$reenable_unit (path)) THEN
                    enabled_unit := TRUE;
                    CYCLE /unit_search/; {----->
                  ELSE
                    CYCLE /enable_pp/; {----->
                  IFEND;
                IFEND;
              FOREND;
            IFEND;
            IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table^.unit_status.disabled THEN
              IF NOT (cmp$reenable_unit (path)) THEN
                CYCLE /enable_pp/; {----->
              ELSE
                enabled_unit := TRUE;
              IFEND;
            IFEND;
          IFEND;
        FOREND /unit_search/;

        IF enabled_unit THEN
          ep := ep + 1;
          enable_pp_list_p^ [ep] := pp;


{ Enable units.

          eu := 0;
          IF meu > 0 THEN
            FOR u := 1 TO meu DO
              FOR ud := 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 [ud].
                      unit_interface_table_rma <> 0) THEN
                  IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                        logical_unit = maybe_enable_unit_list_p^ [u]) THEN
                    get_path (pp, ud, path);
                    IF (cmp$reenable_unit (path)) THEN
                      eu := eu + 1;
                      enable_unit_list_p^ [eu] := maybe_enable_unit_list_p^ [u];
                      maybe_enable_unit_list_p^ [u] := 0;
                    IFEND;
                  IFEND;
                IFEND;
              FOREND;
            FOREND;
          IFEND;
          IF eu > 0 THEN
            enable_units (enable_unit_list_p, eu, status);
          IFEND;
        IFEND;
      FOREND /enable_pp/;
    IFEND;


{ Enable_pps.

    IF ep > 0 THEN
      enable_pps (enable_pp_list_p, ep);
    IFEND;


{ Check for other disabled disk pps.

  /find_pps/
    FOR pp := 1 TO UPPERBOUND (cmv$logical_pp_table_p^) DO
      IF cmv$logical_pp_table_p^ [pp].flags.configured AND cmv$logical_pp_table_p^ [pp].flags.pp_loaded AND
            cmv$logical_pp_table_p^ [pp].flags.disabled AND (cmv$logical_pp_table_p^ [pp].pp_info.pp_type =
            cmc$lpt_disk_pp_type) THEN
        IF (cmv$logical_pp_table_p^ [pp].pp_info.logical_partner_pp_index > 0) AND
              cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave THEN
          CYCLE /find_pps/; {----->
        IFEND;

        enabled_unit := FALSE;

        FOR ud := 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 [ud].
                unit_interface_table_rma <> 0) THEN
            unit_interface_table := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.
                  unit_descriptors [ud].unit_interface_table;
            IF unit_interface_table <> NIL THEN
              IF (cmv$logical_pp_table_p^ [pp].handlers.response_handler_p <> ^iop$process_disk_response) THEN
                CYCLE /find_pps/; {----->
              IFEND;

              get_path (pp, ud, path);
              IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                    unit_interface_table^.unit_status.disabled THEN
                IF NOT (cmp$reenable_unit (path)) THEN
                  CYCLE /find_pps/; {----->
                ELSE
                  enabled_unit := TRUE;
                IFEND;
              IFEND;
            IFEND;
          IFEND;
        FOREND;

        IF enabled_unit THEN
          ep := 1;
          enable_pp_list_p^ [ep] := pp;
          enable_pps (enable_pp_list_p, ep);
        IFEND;
      IFEND;
    FOREND /find_pps/;



  PROCEND iop$enable_all_disk_units;

?? TITLE := '  get_controller_units', EJECT ??

  PROCEDURE get_controller_units
    (    pp: 1 .. ioc$pp_count;
         channel: ost$physical_channel_number;
         controller: cmt$physical_equipment_number;
     VAR unit_list_p: ^array [1 .. * ] of iot$logical_unit;
     VAR number_of_units: iot$logical_unit);

    VAR
      ud: iot$logical_unit,
      ppit_p: ^iot$pp_interface_table;

    number_of_units := 0;
    IF NOT cmv$logical_pp_table_p^ [pp].flags.configured THEN
      RETURN; {----->
    IFEND;

    ppit_p := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;

  /ud_loop/
    FOR ud := LOWERBOUND (ppit_p^.unit_descriptors) TO UPPERBOUND (ppit_p^.unit_descriptors) DO
      IF ppit_p^.unit_descriptors [ud].unit_interface_table = NIL THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      IF ppit_p^.unit_descriptors [ud].unit_interface_table_rma = 0 THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      IF ppit_p^.unit_descriptors [ud].physical_path.channel_number <> channel THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      IF ppit_p^.unit_descriptors [ud].physical_path.controller_number <> controller THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      number_of_units := number_of_units + 1;
      IF number_of_units <= UPPERBOUND (unit_list_p^) THEN
        unit_list_p^ [number_of_units] := ppit_p^.unit_descriptors [ud].logical_unit;
      IFEND;
    FOREND /ud_loop/;

  PROCEND get_controller_units;

?? TITLE := '  get_channel_units', EJECT ??

  PROCEDURE get_channel_units
    (    pp: 1 .. ioc$pp_count;
         channel: ost$physical_channel_number;
     VAR unit_list_p: ^array [1 .. * ] of iot$logical_unit;
     VAR number_of_units: iot$logical_unit);

    VAR
      ud: iot$logical_unit,
      ppit_p: ^iot$pp_interface_table;

    number_of_units := 0;
    IF NOT cmv$logical_pp_table_p^ [pp].flags.configured THEN
      RETURN; {----->
    IFEND;

    ppit_p := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;

  /ud_loop/
    FOR ud := LOWERBOUND (ppit_p^.unit_descriptors) TO UPPERBOUND (ppit_p^.unit_descriptors) DO
      IF ppit_p^.unit_descriptors [ud].unit_interface_table = NIL THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      IF ppit_p^.unit_descriptors [ud].unit_interface_table_rma = 0 THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      IF ppit_p^.unit_descriptors [ud].physical_path.channel_number <> channel THEN
        CYCLE /ud_loop/; {----->
      IFEND;

      number_of_units := number_of_units + 1;
      IF number_of_units <= UPPERBOUND (unit_list_p^) THEN
        unit_list_p^ [number_of_units] := ppit_p^.unit_descriptors [ud].logical_unit;
      IFEND;
    FOREND /ud_loop/;

  PROCEND get_channel_units;

?? TITLE := '  get_pps_to_units', EJECT ??

  PROCEDURE get_pps_to_units
    (    unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR pp_list_p: ^array [1 .. * ] of iot$pp_number;
     VAR number_of_pps: iot$pp_number);

    VAR
      i: integer,
      pp: iot$pp_number,
      ppit_p: ^iot$pp_interface_table,
      ud: iot$logical_unit;

    number_of_pps := 0;
    IF cmv$logical_pp_table_p = NIL THEN
      RETURN; {----->
    IFEND;

    IF number_of_units = 0 THEN
      RETURN; {----->
    IFEND;

  /find_pps/
    FOR pp := LOWERBOUND (cmv$logical_pp_table_p^) TO UPPERBOUND (cmv$logical_pp_table_p^) DO
      IF NOT cmv$logical_pp_table_p^ [pp].flags.configured THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF NOT cmv$logical_pp_table_p^ [pp].flags.pp_loaded THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF cmv$logical_pp_table_p^ [pp].pp_info.pp_type <> cmc$lpt_disk_pp_type THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF cmv$logical_pp_table_p^ [pp].pp_info.logical_partner_pp_index <> 0 THEN
        IF cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave THEN
          CYCLE /find_pps/; {----->
        IFEND;
      IFEND;

      ppit_p := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;

    /ud_loop/
      FOR ud := LOWERBOUND (ppit_p^.unit_descriptors) TO UPPERBOUND (ppit_p^.unit_descriptors) DO
        IF ppit_p^.unit_descriptors [ud].unit_interface_table = NIL THEN
          CYCLE /ud_loop/; {----->
        IFEND;

        IF ppit_p^.unit_descriptors [ud].unit_interface_table_rma = 0 THEN
          CYCLE /ud_loop/; {----->
        IFEND;

      /unit_loop/
        FOR i := 1 TO number_of_units DO
          IF ppit_p^.unit_descriptors [ud].logical_unit = unit_list_p^ [i] THEN
            number_of_pps := number_of_pps + 1;
            IF number_of_pps <= UPPERBOUND (pp_list_p^) THEN
              pp_list_p^ [number_of_pps] := pp;
            IFEND;
            CYCLE /find_pps/; {----->
          IFEND;
        FOREND /unit_loop/;
      FOREND /ud_loop/;
    FOREND /find_pps/;

  PROCEND get_pps_to_units;

?? TITLE := '  get_pps_to_controller', EJECT ??

  PROCEDURE get_pps_to_controller
    (    p: iot$pp_number;
         channel: ost$physical_channel_number;
         controller: cmt$physical_equipment_number;
     VAR pp_list_p: ^array [1 .. * ] of iot$pp_number;
     VAR number_of_pps: iot$pp_number);

    VAR
      channel_interlock_rma: ost$real_memory_address,
      pp: iot$pp_number,
      ppit_p: ^iot$pp_interface_table,
      ud: integer;

    channel_interlock_rma := cmv$logical_pp_table_p^ [p].pp_info.pp_interface_table_p^.channel_interlock_rma;
    number_of_pps := 0;

    IF cmv$logical_pp_table_p = NIL THEN
      RETURN; {----->
    IFEND;

  /find_pps/
    FOR pp := 1 TO UPPERBOUND (cmv$logical_pp_table_p^) DO
      IF NOT cmv$logical_pp_table_p^ [pp].flags.configured THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF NOT cmv$logical_pp_table_p^ [pp].flags.pp_loaded THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF cmv$logical_pp_table_p^ [pp].pp_info.pp_type <> cmc$lpt_disk_pp_type THEN
        CYCLE /find_pps/; {----->
      IFEND;

      IF cmv$logical_pp_table_p^ [pp].pp_info.logical_partner_pp_index <> 0 THEN
        IF cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave THEN
          CYCLE /find_pps/; {----->
        IFEND;
      IFEND;

      ppit_p := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;

    /ud_loop/
      FOR ud := LOWERBOUND (ppit_p^.unit_descriptors) TO UPPERBOUND (ppit_p^.unit_descriptors) DO
        IF ppit_p^.unit_descriptors [ud].unit_interface_table = NIL THEN
          CYCLE /ud_loop/; {----->
        IFEND;

        IF ppit_p^.unit_descriptors [ud].unit_interface_table_rma = 0 THEN
          CYCLE /ud_loop/; {----->
        IFEND;

        IF ppit_p^.unit_descriptors [ud].physical_path.channel_number <> channel THEN
          CYCLE /ud_loop/; {----->
        IFEND;

        IF ppit_p^.unit_descriptors [ud].physical_path.controller_number <> controller THEN
          CYCLE /ud_loop/; {----->
        IFEND;

        IF ppit_p^.channel_interlock_rma = channel_interlock_rma THEN
          number_of_pps := number_of_pps + 1;
          IF number_of_pps <= UPPERBOUND (pp_list_p^) THEN
            pp_list_p^ [number_of_pps] := pp;
          IFEND;
          CYCLE /find_pps/; {----->
        IFEND;

      FOREND /ud_loop/;
    FOREND /find_pps/;

  PROCEND get_pps_to_controller;

?? TITLE := '  enable_disable', EJECT ??

  PROCEDURE enable_disable
    (    pp_list_p: ^array [1 .. * ] of iot$pp_number;
         number_of_pps: iot$pp_number;
         unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      pp: iot$pp_number,
      p: iot$pp_number,
      ud: integer,
      logical_unit: iot$logical_unit,
      lu: iot$logical_unit,
      number_disabled_pps: iot$pp_number,
      i: integer,
      du: integer,
      eu: integer,
      meu: integer,
      l: integer,
      u: integer,
      mep: integer,
      rr: integer,
      ep: integer,
      ed: integer,
      enable_disable_list_p: ^array [1 .. * ] of iot$logical_unit,
      enable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      disable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      maybe_enable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      nu: iot$logical_unit,
      np: iot$pp_number,
      pp_disabled_list_p: ^array [1 .. * ] of iot$pp_number,
      pp_list2_p: ^array [1 .. * ] of iot$pp_number,
      maybe_enable_pp_p: ^array [1 .. * ] of iot$pp_number,
      enable_pp_list_p: ^array [1 .. * ] of iot$pp_number,
      npp: iot$pp_number,
      enabled_path: boolean,
      disabled_pp_path: boolean,
      enabled_unit: boolean,
      path: cmt$physical_address;

    status.normal := TRUE;


    du := 0;
    eu := 0;
    meu := 0;
    mep := 0;
    ep := 0;
    ed := 0;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH enable_disable_list_p: [1 .. nu];
    PUSH enable_unit_list_p: [1 .. nu];
    PUSH disable_unit_list_p: [1 .. nu];
    PUSH maybe_enable_unit_list_p: [1 .. nu];
    np := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_disabled_list_p: [1 .. np];
    PUSH pp_list2_p: [1 .. np];
    PUSH maybe_enable_pp_p: [1 .. np];
    PUSH enable_pp_list_p: [1 .. np];

    IF iov$debug = 10(16) THEN
      mtp$error_stop (' Debug stop 10(16) in enable_disable');
    IFEND;

{ Determine if PP should be disabled.

    number_disabled_pps := 0;
    IF number_of_pps > 0 THEN

    /disable_pps/
      FOR p := 1 TO number_of_pps DO
        pp := pp_list_p^ [p];
        IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN
          FOR ud := 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 [ud].
                  unit_interface_table_rma <> 0) THEN
              get_path (pp, ud, path);

              IF number_of_units > 0 THEN
                FOR u := 1 TO number_of_units DO
                  IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                        logical_unit = unit_list_p^ [u]) THEN
                    IF cmp$reenable_unit (path) THEN
                      CYCLE /disable_pps/; {----->
                    IFEND;
                  IFEND;
                FOREND;
              IFEND;

              IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                    unit_interface_table^.unit_status.disabled THEN
                IF cmp$reenable_unit (path) THEN
                  CYCLE /disable_pps/; {----->
                IFEND;
              IFEND;

            IFEND;
          FOREND;
        ELSE
          CYCLE /disable_pps/; {----->
        IFEND;
        disable_pp (pp);
        number_disabled_pps := number_disabled_pps + 1;
        pp_disabled_list_p^ [number_disabled_pps] := pp;
      FOREND /disable_pps/;
    IFEND;

    IF iov$debug = 11(16) THEN
      mtp$error_stop (' Debug stop 11(16) in enable_disable.');
    IFEND;

{ Get list of units to disable or enable.

    IF number_disabled_pps > 0 THEN
      FOR p := 1 TO number_disabled_pps DO
        pp := pp_disabled_list_p^ [p];

      /unit_list/
        FOR ud := 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 [ud].
                unit_interface_table_rma <> 0) THEN
            logical_unit := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  logical_unit;
            IF ed > 0 THEN
              FOR lu := 1 TO ed DO
                IF (enable_disable_list_p^ [lu] = logical_unit) THEN
                  CYCLE /unit_list/; {----->
                IFEND;
              FOREND;
            IFEND;
            ed := ed + 1;
            enable_disable_list_p^ [ed] := logical_unit;
          IFEND;
        FOREND /unit_list/;
      FOREND;
    ELSE
      IF number_of_units > 0 THEN
        FOR u := 1 TO number_of_units DO
          ed := ed + 1;
          enable_disable_list_p^ [ed] := unit_list_p^ [u];
        FOREND;
      IFEND;
    IFEND;

    IF iov$debug = 12(16) THEN
      mtp$error_stop (' Debug stop 12(16) in enable_disable.');
    IFEND;

{ Determine which units to disable and enable.

    IF ed > 0 THEN
      get_pps_to_units (enable_disable_list_p, ed, pp_list2_p, npp);

    /check2/
      FOR lu := 1 TO ed DO
        logical_unit := enable_disable_list_p^ [lu];
        enabled_path := FALSE;
        disabled_pp_path := FALSE;
        rr := mep;

        IF npp > 0 THEN

        /pp_check/
          FOR p := 1 TO npp DO
            pp := pp_list2_p^ [p];
            IF number_disabled_pps > 0 THEN
              FOR i := 1 TO number_disabled_pps DO
                IF pp_disabled_list_p^ [i] = pp THEN
                  CYCLE /pp_check/; {----->
                IFEND;
              FOREND;
            IFEND;

          /units/
            FOR ud := 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 [ud].
                    unit_interface_table_rma <> 0) THEN
                IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                      logical_unit = logical_unit THEN
                  get_path (pp, ud, path);
                  IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN
                    IF NOT (cmp$reenable_unit (path)) THEN
                      du := du + 1;
                      disable_unit_list_p^ [du] := logical_unit;
                      CYCLE /check2/; {----->
                    ELSE
                      enabled_path := TRUE;
                    IFEND;
                  ELSEIF (cmp$reenable_unit (path)) THEN
                    disabled_pp_path := TRUE;
                    IF rr > 0 THEN
                      FOR i := 1 TO rr DO
                        IF (maybe_enable_pp_p^ [i] = pp) THEN
                          CYCLE /units/; {----->
                        IFEND;
                      FOREND;
                    IFEND;
                    rr := rr + 1;
                    maybe_enable_pp_p^ [rr] := pp;
                  IFEND;
                IFEND;
              IFEND;
            FOREND /units/;
          FOREND /pp_check/;
        IFEND;

        IF enabled_path THEN
          eu := eu + 1;
          enable_unit_list_p^ [eu] := logical_unit;
          mep := rr;
        ELSEIF disabled_pp_path THEN
          meu := meu + 1;
          maybe_enable_unit_list_p^ [meu] := logical_unit;
          mep := rr;
        ELSE
          du := du + 1;
          disable_unit_list_p^ [du] := logical_unit;
        IFEND;
      FOREND /check2/;
    IFEND;

    IF iov$debug = 13(16) THEN
      mtp$error_stop (' Debug stop 13(16) in enable_disable.');
    IFEND;

{ Disable units.

    IF du > 0 THEN
      disable_units (disable_unit_list_p, du, status);

      IF ((NOT status.normal) AND (status.condition = ioc$critical_device_disabled)) THEN
        RETURN; {----->
      IFEND;

    IFEND;


    IF iov$debug = 14(16) THEN
      mtp$error_stop (' Debug stop 14(16) in enable_disable.');
    IFEND;
{ Enable units.

    IF eu > 0 THEN
      enable_units (enable_unit_list_p, eu, status);
    IFEND;


{ Determine if any PP should be enabled.

    IF mep > 0 THEN

    /enable_pp/
      FOR p := 1 TO mep DO
        pp := maybe_enable_pp_p^ [p];
        enabled_unit := FALSE;

      /unit_search/
        FOR ud := 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 [ud].
                unit_interface_table_rma <> 0) THEN

            get_path (pp, ud, path);
            IF meu > 0 THEN
              FOR u := 1 TO meu DO
                IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                      logical_unit = maybe_enable_unit_list_p^ [u]) THEN
                  IF (cmp$reenable_unit (path)) THEN
                    enabled_unit := TRUE;
                    CYCLE /unit_search/; {----->
                  ELSE
                    CYCLE /enable_pp/; {----->
                  IFEND;
                IFEND;
              FOREND;
            IFEND;

            IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table^.unit_status.disabled THEN
              IF NOT (cmp$reenable_unit (path)) THEN
                CYCLE /enable_pp/; {----->
              ELSE
                enabled_unit := TRUE;
              IFEND;
            IFEND;
          IFEND;
        FOREND /unit_search/;

        IF enabled_unit THEN
          ep := ep + 1;
          enable_pp_list_p^ [ep] := pp;


{ Enable units.

          eu := 0;
          IF meu > 0 THEN
            FOR u := 1 TO meu DO
              FOR ud := 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 [ud].
                      unit_interface_table_rma <> 0) THEN
                  IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                        logical_unit = maybe_enable_unit_list_p^ [u]) THEN
                    get_path (pp, ud, path);
                    IF (cmp$reenable_unit (path)) THEN
                      eu := eu + 1;
                      enable_unit_list_p^ [eu] := maybe_enable_unit_list_p^ [u];
                      maybe_enable_unit_list_p^ [u] := 0;
                    IFEND;
                  IFEND;
                IFEND;
              FOREND;
            FOREND;
          IFEND;
          IF eu > 0 THEN
            enable_units (enable_unit_list_p, eu, status);
          IFEND;

        IFEND;

      FOREND /enable_pp/;
    IFEND;

    IF iov$debug = 15(16) THEN
      mtp$error_stop (' Debug stop 15(16) in enable_disable.');
    IFEND;

{ Disable units.

    IF meu > 0 THEN
      du := 0;
      FOR u := 1 TO meu DO
        IF (maybe_enable_unit_list_p^ [u] <> 0) THEN
          du := du + 1;
          disable_unit_list_p^ [du] := maybe_enable_unit_list_p^ [u];
        IFEND;
      FOREND;
      IF du > 0 THEN
        disable_units (disable_unit_list_p, du, status);

        IF ((NOT status.normal) AND (status.condition = ioc$critical_device_disabled)) THEN
          RETURN; {----->
        IFEND;

      IFEND;
    IFEND;

    IF iov$debug = 16(16) THEN
      mtp$error_stop (' Debug stop 16(16) in enable_disable.');
    IFEND;

{ Enable_pps.

    IF ep > 0 THEN
      enable_pps (enable_pp_list_p, ep);
    IFEND;

  PROCEND enable_disable;

?? TITLE := '  auto_disable', EJECT ??

  PROCEDURE auto_disable
    (    pp: 1 .. ioc$pp_count;
         unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      p: iot$pp_number,
      pp2: iot$pp_number,
      ud: integer,
      logical_unit: iot$logical_unit,
      lu: iot$logical_unit,
      i: integer,
      j: integer,
      du: integer,
      eu: integer,
      l: integer,
      u: integer,
      ed: integer,
      enable_disable_list_p: ^array [1 .. * ] of iot$logical_unit,
      enable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      disable_unit_list_p: ^array [1 .. * ] of iot$logical_unit,
      nu: iot$logical_unit,
      np: iot$pp_number,
      pp_list2_p: ^array [1 .. * ] of iot$pp_number,
      npp: iot$pp_number,
      enabled_path: boolean,
      pp_disabled: boolean,
      path: cmt$physical_address,
      id_status: syt$monitor_status;



    status.normal := TRUE;


    du := 0;
    eu := 0;
    ed := 0;

    nu := UPPERBOUND (cmv$logical_unit_table^);
    PUSH enable_disable_list_p: [1 .. nu];
    PUSH enable_unit_list_p: [1 .. nu];
    PUSH disable_unit_list_p: [1 .. nu];
    np := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list2_p: [1 .. np];


{ Determine if PP should be disabled.

  /disable/
    BEGIN
      pp_disabled := FALSE;
      IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN

      /units/
        FOR ud := 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 [ud].
                unit_interface_table_rma <> 0) THEN

            logical_unit := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  logical_unit;
            IF number_of_units > 0 THEN
              FOR u := 1 TO number_of_units DO
                IF (logical_unit = unit_list_p^ [u]) THEN
                  CYCLE /units/; {----->
                IFEND;
              FOREND;
            IFEND;

            IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table^.unit_status.disabled THEN
              EXIT /disable/; {----->
            ELSEIF (cmc$io_request_submission IN cmv$logical_unit_table^ [logical_unit].element_capability)
                  THEN
              EXIT /disable/; {----->
            IFEND;

          IFEND;
        FOREND /units/;
      ELSE
        pp_disabled := TRUE;
        EXIT /disable/; {----->
      IFEND;
      disable_pp (pp);
      pp_disabled := TRUE;
    END /disable/;


{ Idle all the PPs configured to the units which
{ were disabled.
{
{   get_pps_to_units (unit_list_p, number_of_units, pp_list2_p, npp);
{
{   IF npp > 0 THEN
{     iop$idle_pps_and_wait (pp_list2_p, npp, status);
{
{ Resume the pps.
{
{     FOR j := 1 TO npp DO
{       p := pp_list2_p^ [j];
{       IF NOT cmv$logical_pp_table_p^ [p].flags.disabled THEN
{         iop$idle_resume (p, ioc$ira_resume, id_status);
{         IF NOT id_status.normal THEN
{           iov$no_resume_request := iov$no_resume_request + 1;
{         IFEND;
{       IFEND;
{     FOREND;
{   IFEND;



{ Disable units.

    IF NOT pp_disabled THEN
      IF number_of_units > 0 THEN
        disable_units (unit_list_p, number_of_units, status);
      IFEND;
      RETURN; {----->
    IFEND;


{ Get list of units to disable or enable.

    FOR ud := 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 [ud].
            unit_interface_table_rma <> 0) THEN
        logical_unit := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
              logical_unit;
        ed := ed + 1;
        enable_disable_list_p^ [ed] := logical_unit;
      IFEND;
    FOREND;


{ Determine which units to disable and enable.

    IF ed > 0 THEN
      get_pps_to_units (enable_disable_list_p, ed, pp_list2_p, npp);

    /check2/
      FOR lu := 1 TO ed DO
        logical_unit := enable_disable_list_p^ [lu];
        enabled_path := FALSE;
        FOR p := 1 TO npp DO
          pp2 := pp_list2_p^ [p];
          FOR ud := LOWERBOUND (cmv$logical_pp_table_p^ [pp2].pp_info.pp_interface_table_p^.unit_descriptors)
                TO UPPERBOUND (cmv$logical_pp_table_p^ [pp2].pp_info.pp_interface_table_p^.unit_descriptors)
                DO
            IF (cmv$logical_pp_table_p^ [pp2].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table_rma <> 0) THEN
              IF cmv$logical_pp_table_p^ [pp2].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                    logical_unit = logical_unit THEN
                get_path (pp2, ud, path);
                IF NOT cmv$logical_pp_table_p^ [pp2].flags.disabled THEN
                  IF NOT (cmp$reenable_unit (path)) THEN
                    du := du + 1;
                    disable_unit_list_p^ [du] := logical_unit;
                    CYCLE /check2/; {----->
                  ELSE
                    enabled_path := TRUE;
                  IFEND;
                IFEND;
              IFEND;
            IFEND;
          FOREND;
        FOREND;
        IF enabled_path THEN
          eu := eu + 1;
          enable_unit_list_p^ [eu] := logical_unit;
        ELSE
          du := du + 1;
          disable_unit_list_p^ [du] := logical_unit;
        IFEND;
      FOREND /check2/;
    IFEND;


{ Disable units.

    IF du > 0 THEN
      disable_units (disable_unit_list_p, du, status);
    IFEND;


{ Enable units.

    IF eu > 0 THEN
      enable_units (enable_unit_list_p, eu, status);
    IFEND;



  PROCEND auto_disable;

?? TITLE := '  iop$idle_pps_and_wait', EJECT ??

  PROCEDURE [XDCL] iop$idle_pps_and_wait
    (    pp_list_p: ^array [1 .. * ] of iot$pp_number;
         number_of_pps: iot$pp_number;
     VAR status: syt$monitor_status);

    VAR
      list_p: ^array [1 .. * ] of iot$pp_number,
      j: integer,
      pp: iot$pp_number,
      p: iot$pp_number,
      new_time: integer,
      old_time: integer,
      loop: boolean,
      port: integer,
      msg: string (63),
      message_displayed: boolean,
      cpu_state_table_p: ^ost$cpu_state_table,
      id_status: syt$monitor_status;



    status.normal := TRUE;


    IF number_of_pps = 0 THEN
      RETURN; {----->
    IFEND;

    PUSH list_p: [1 .. number_of_pps];
    list_p^ := pp_list_p^;

    FOR p := 1 TO number_of_pps DO
      pp := list_p^ [p];
      IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN
        iop$idle_resume (pp, ioc$ira_idle, id_status);
        IF NOT id_status.normal THEN
          list_p^ [p] := 0ffff(16);
          iov$no_idle_request := iov$no_idle_request + 1;
        IFEND;
      IFEND;
    FOREND;


{Get time request was queued.}

    port := 0;
    old_time := #FREE_RUNNING_CLOCK (port);

{Wait for pps to reply to idle command.}

    loop := TRUE;
    message_displayed := FALSE;

  /wait_for_reply/
    WHILE loop DO

{ Update the clock.

      mtp$cst_p (cpu_state_table_p);
      cpu_state_table_p^.cpu_alive_flag := #FREE_RUNNING_CLOCK (port);


      iop$check_idle_pps;

      loop := FALSE;

    /check_idle_pps/
      FOR j := 1 TO number_of_pps DO
        p := list_p^ [j];
        IF p <> 0ffff(16) THEN
          IF NOT cmv$logical_pp_table_p^ [p].flags.disabled THEN
            #SPOIL (cmv$logical_pp_table_p^ [p].pp_info.pp_interface_table_p^.idle_status);
            IF NOT cmv$logical_pp_table_p^ [p].pp_info.pp_interface_table_p^.idle_status THEN
              loop := TRUE;
              EXIT /check_idle_pps/; {----->
            IFEND;
          IFEND;
        IFEND;
      FOREND /check_idle_pps/;

      new_time := #FREE_RUNNING_CLOCK (port);

      IF (new_time > (old_time + 10000000)) THEN
        IF NOT message_displayed THEN
          msg := 'WAITING FOR PP TO IDLE';
          dpp$display_error (msg);
          message_displayed := TRUE;
        IFEND;
      IFEND;

{ Wait up to 1 minute for the pps to idle.

      IF new_time >= old_time + 60000000 THEN
        loop := FALSE;
        msg := 'LOGICAL PP     DID NOT RESPOND TO IDLE REQUEST';
        dpp$convert_int_to_str_hex (2, p, msg (12, * ));
        dpp$display_error (msg);
        status.normal := FALSE;
        status.condition := ioc$no_idle_response;
      IFEND;

{ Check if monitor timeout word needs updating.

      IF (mtv$time_to_call_handshaking - #FREE_RUNNING_CLOCK (0)) < 0 THEN
        dsp$perform_cpu_pp_handshaking;
      IFEND;

    WHILEND /wait_for_reply/;

    IF (message_displayed AND status.normal) THEN
      dpp$display_error ('PP responded to idle request.');
    IFEND;



  PROCEND iop$idle_pps_and_wait;

?? TITLE := '  get_path', EJECT ??

  PROCEDURE get_path
    (    pp: iot$pp_number;
         ud: integer;
     VAR path: cmt$physical_address);

    VAR
      msg: string (63),
      unit_type: iot$unit_type,
      iou_number: dst$iou_number;

    iou_number := cmv$logical_pp_table_p^ [pp].pp_info.channel.iou_number;

    unit_type := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
          unit_interface_table^.unit_type;
    IF unit_type = ioc$dt_mshydra THEN
      path.address_specifier := $cmt$physical_address_specifier [cmc$iou, cmc$channel, cmc$unit_address];
    ELSE
      path.address_specifier := $cmt$physical_address_specifier
            [cmc$iou, cmc$channel, cmc$channel_address, cmc$unit_address];
    IFEND;

    path.iou := iou_number;
    path.channel.number := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
          physical_path.channel_number;

    path.channel.concurrent := cmv$logical_pp_table_p^ [pp].pp_info.channel_interlock_p^.
          channel_characteristics [path.channel.number].concurrent_channel;

    path.channel.port := cmc$unspecified_port;
    IF path.channel.concurrent THEN
      IF (unit_type = ioc$dt_mshydra) OR (unit_type = ioc$dt_msxmd_3) OR (unit_type = ioc$dt_ms5832_1) OR
            (unit_type = ioc$dt_ms5832_2) OR (unit_type = ioc$dt_ms5833_1) OR
            (unit_type = ioc$dt_ms5833_1p) OR (unit_type = ioc$dt_ms5833_2) OR
            (unit_type = ioc$dt_ms5833_3p) OR (unit_type = ioc$dt_ms5833_4) OR
            (unit_type = ioc$dt_ms5837_1) OR (unit_type = ioc$dt_ms5837_1p) OR
            (unit_type = ioc$dt_ms5837_2) OR (unit_type = ioc$dt_ms5837_3p) OR
            (unit_type = ioc$dt_ms5837_4) OR (unit_type = ioc$dt_ms5838_1) OR
            (unit_type = ioc$dt_ms5838_1p) OR (unit_type = ioc$dt_ms5838_2) OR
            (unit_type = ioc$dt_ms5838_3p) OR (unit_type = ioc$dt_ms5838_4) OR
            (unit_type = ioc$dt_ms47444_1) OR (unit_type = ioc$dt_ms47444_1p) OR
            (unit_type = ioc$dt_ms47444_2) OR (unit_type = ioc$dt_ms47444_3p) OR
            (unit_type = ioc$dt_ms47444_4) OR (unit_type = ioc$dt_msntdd_1) OR
            (unit_type = ioc$dt_msntdd_2) OR (unit_type = ioc$dt_msntdd_3) OR (unit_type = ioc$dt_msntdd_4) OR
            (unit_type = ioc$dt_msntdd_5) OR (unit_type = ioc$dt_msntdd_6) THEN
        IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].physical_path.
              port = 0 THEN
          path.channel.port := cmc$port_a;
        ELSE
          path.channel.port := cmc$port_b;
        IFEND;
      IFEND;
    IFEND;

    path.channel_address := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
          physical_path.controller_number;
    path.unit_address := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
          physical_path.physical_unit_number;

    IF unit_type = ioc$dt_mshydra THEN
      path.unit_address := path.channel_address;
      path.channel_address := 0;
    IFEND;

    IF cmv$display_config_debug_msg THEN
      msg := '      PP=   LU=   CH=   PORT       IOU=  CONTROLLER=   UNIT=  ';
      dpp$convert_int_to_str_hex (2, pp, msg (10, * ));
      dpp$convert_int_to_str_hex (2, cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.
            unit_descriptors [ud].logical_unit, msg (16, * ));
      dpp$convert_int_to_str_octal (2, path.channel.number, msg (22, * ));
      dpp$convert_int_to_str_octal (2, path.channel_address, msg (53, * ));
      dpp$convert_int_to_str_octal (2, path.unit_address, msg (61, * ));
      IF path.channel.concurrent THEN
        msg (32, 3) := 'CIO';
      ELSE
        msg (32, 3) := 'NIO';
      IFEND;
      IF path.channel.port = cmc$port_a THEN
        msg (30, 1) := 'A';
      ELSEIF path.channel.port = cmc$port_b THEN
        msg (30, 1) := 'B';
      ELSE
        msg (30, 1) := 'U';
      IFEND;
      IF cmp$reenable_unit (path) THEN
        msg (1, 4) := 'ON  ';
      ELSE
        msg (1, 4) := 'DOWN';
      IFEND;

      dpp$display_error (msg);
    IFEND;

  PROCEND get_path;

?? TITLE := '  enable_pps', EJECT ??

  PROCEDURE enable_pps
    (    pp_list_p: ^array [1 .. * ] of iot$pp_number;
         number_of_pps: iot$pp_number);

    VAR
      pp: iot$pp_number,
      status: syt$monitor_status,
      msg: string (63),
      j: integer;


{ Resume the pps.
    IF number_of_pps > 0 THEN
      FOR j := 1 TO number_of_pps DO
        pp := pp_list_p^ [j];
        IF cmv$logical_pp_table_p^ [pp].flags.disabled THEN
          cmv$logical_pp_table_p^ [pp].flags.disabled := FALSE;
          iop$idle_resume (pp, ioc$ira_resume, status);
          IF NOT status.normal THEN
            iov$no_resume_request := iov$no_resume_request + 1;
          IFEND;

          IF cmv$display_config_debug_msg THEN
            msg := 'ENABLED  PP     (16)';
            dpp$convert_int_to_str_hex (2, pp, msg (15, * ));
            dpp$display_error (msg);
          IFEND;
        IFEND;
      FOREND;
    IFEND;

  PROCEND enable_pps;

?? TITLE := '  disable_pp', EJECT ??

  PROCEDURE disable_pp
    (    pp: iot$pp_number);

    VAR
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      number_of_pps: iot$pp_number,
      msg: string (63),
      status: syt$monitor_status;


    IF NOT cmv$logical_pp_table_p^ [pp].flags.disabled THEN

      number_of_pps := 1;
      PUSH pp_list_p: [1 .. number_of_pps];

      pp_list_p^ [1] := pp;
      iop$idle_pps_and_wait (pp_list_p, number_of_pps, status);

{ Set the pp disabled flag.

      cmv$logical_pp_table_p^ [pp].flags.disabled := TRUE;

      IF cmv$display_config_debug_msg THEN
        msg := 'DISABLED  PP    (16)';
        dpp$convert_int_to_str_hex (2, pp, msg (15, * ));
        dpp$display_error (msg);
      IFEND;
    IFEND;

  PROCEND disable_pp;

?? TITLE := '  enable_units', EJECT ??

  PROCEDURE enable_units
    (    unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      logical_unit: iot$logical_unit,
      lu: iot$logical_unit,
      pp_interface_table: ^iot$pp_interface_table,
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      pp: 1 .. ioc$pp_count,
      p: 1 .. ioc$pp_count,
      number_of_pp: 1 .. ioc$pp_count,
      npp: iot$pp_number,
      j: iot$pp_number,
      u: integer,
      ud: integer,
      msg: string (63),
      id_status: syt$monitor_status;

    IF iov$debug = 02(16) THEN
      mtp$error_stop (' Debug stop 02(16) in enable_units.');
    IFEND;

    status.normal := TRUE;

{ Idle all the PPs configured to the units which
{ are to be enabled.

    IF cmv$logical_pp_table_p = NIL THEN
      RETURN; {----->
    IFEND;

    IF number_of_units = 0 THEN
      RETURN; {----->
    IFEND;

    number_of_pp := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list_p: [1 .. number_of_pp];

    npp := 0;

  /idle_pps/
    FOR pp := 1 TO number_of_pp DO
      IF cmv$logical_pp_table_p^ [pp].flags.configured AND cmv$logical_pp_table_p^ [pp].flags.
            pp_loaded AND NOT cmv$logical_pp_table_p^ [pp].flags.disabled AND
            (cmv$logical_pp_table_p^ [pp].pp_info.pp_type = cmc$lpt_disk_pp_type) THEN
        pp_interface_table := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;
        IF pp_interface_table <> NIL THEN
          IF (cmv$logical_pp_table_p^ [pp].pp_info.logical_partner_pp_index > 0) AND
                cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave THEN
            CYCLE /idle_pps/; {----->
          IFEND;

          FOR ud := LOWERBOUND (pp_interface_table^.unit_descriptors)
                TO UPPERBOUND (pp_interface_table^.unit_descriptors) DO
            IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table_rma <> 0) THEN
              IF cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                    unit_interface_table^.unit_status.disabled THEN
                FOR u := 1 TO number_of_units DO
                  IF pp_interface_table^.unit_descriptors [ud].logical_unit = unit_list_p^ [u] THEN
                    npp := npp + 1;
                    pp_list_p^ [npp] := pp;
                  IFEND;
                FOREND;
              IFEND;
            IFEND;
          FOREND;

        IFEND;
      IFEND;
    FOREND /idle_pps/;

    iop$idle_pps_and_wait (pp_list_p, npp, status);


{ Clear the disable bit in the unit interface tables.

    FOR u := 1 TO number_of_units DO
      lu := unit_list_p^ [u];
      IF cmv$logical_unit_table^ [lu].unit_interface_table^.unit_status.disabled THEN
        cmv$logical_unit_table^ [lu].unit_interface_table^.unit_status.disabled := FALSE;
      IFEND;
    FOREND;


{ Resume the pps.

    IF npp > 0 THEN
      FOR j := 1 TO npp DO
        p := pp_list_p^ [j];
        IF NOT cmv$logical_pp_table_p^ [p].flags.disabled THEN
          iop$idle_resume (p, ioc$ira_resume, id_status);
          IF NOT id_status.normal THEN
            iov$no_resume_request := iov$no_resume_request + 1;
          IFEND;
        IFEND;
      FOREND;
    IFEND;


{ Set element capabilities.

    FOR u := 1 TO number_of_units DO
      lu := unit_list_p^ [u];
      IF NOT (cmc$io_request_submission IN cmv$logical_unit_table^ [lu].element_capability) THEN
        cmv$logical_unit_table^ [lu].element_capability := $cmt$element_capabilities
              [cmc$volume_assignment, cmc$file_allocation, cmc$io_request_submission,
              cmc$concurrent_maintenance];
        cmv$logical_unit_table^ [lu].element_access := $cmt$element_access [cmc$read, cmc$write];
        dmp$volume_up (lu);

        IF cmv$display_config_debug_msg THEN
          msg := 'ENABLED  UNIT   (16)';
          dpp$convert_int_to_str_hex (2, lu, msg (15, * ));
          dpp$display_error (msg);
        IFEND;
      IFEND;
    FOREND;

  PROCEND enable_units;

?? TITLE := '  disable_units', EJECT ??

  PROCEDURE disable_units
    (    unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      logical_unit: iot$logical_unit,
      lu: iot$logical_unit,
      pp_interface_table: ^iot$pp_interface_table,
      pp_list_p: ^array [1 .. * ] of iot$pp_number,
      pp: 1 .. ioc$pp_count,
      p: 1 .. ioc$pp_count,
      number_of_pp: 1 .. ioc$pp_count,
      npp: iot$pp_number,
      j: iot$pp_number,
      u: integer,
      ud: integer,
      new_time: integer,
      msg: string (63),
      id_status: syt$monitor_status;


    status.normal := TRUE;

{ Idle all the PPs configured to the units which
{ are to be disabled.

    IF cmv$logical_pp_table_p = NIL THEN
      RETURN; {----->
    IFEND;

    IF number_of_units = 0 THEN
      RETURN; {----->
    IFEND;

    number_of_pp := UPPERBOUND (cmv$logical_pp_table_p^);
    PUSH pp_list_p: [1 .. number_of_pp];

    npp := 0;

  /idle_pps/
    FOR pp := 1 TO number_of_pp DO
      IF cmv$logical_pp_table_p^ [pp].flags.configured AND cmv$logical_pp_table_p^ [pp].flags.
            pp_loaded AND NOT cmv$logical_pp_table_p^ [pp].flags.disabled AND
            (cmv$logical_pp_table_p^ [pp].pp_info.pp_type = cmc$lpt_disk_pp_type) THEN
        pp_interface_table := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;
        IF pp_interface_table <> NIL THEN
          IF (cmv$logical_pp_table_p^ [pp].pp_info.logical_partner_pp_index > 0) AND
                cmv$logical_pp_table_p^ [pp].pp_info.pp_communication_buffer_p^.slave THEN
            CYCLE /idle_pps/; {----->
          IFEND;

          FOR ud := LOWERBOUND (pp_interface_table^.unit_descriptors)
                TO UPPERBOUND (pp_interface_table^.unit_descriptors) DO
            IF (cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                  unit_interface_table_rma <> 0) THEN
              IF NOT cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p^.unit_descriptors [ud].
                    unit_interface_table^.unit_status.disabled THEN
                FOR u := 1 TO number_of_units DO
                  IF pp_interface_table^.unit_descriptors [ud].logical_unit = unit_list_p^ [u] THEN
                    npp := npp + 1;
                    pp_list_p^ [npp] := pp;
                  IFEND;
                FOREND;
              IFEND;
            IFEND;
          FOREND;

        IFEND;
      IFEND;
    FOREND /idle_pps/;

    iop$idle_pps_and_wait (pp_list_p, npp, status);


{ Set the disable bit in the unit interface tables.

    FOR u := 1 TO number_of_units DO
      lu := unit_list_p^ [u];
      IF NOT cmv$logical_unit_table^ [lu].unit_interface_table^.unit_status.disabled THEN
        cmv$logical_unit_table^ [lu].unit_interface_table^.unit_status.disabled := TRUE;

        IF cmv$display_config_debug_msg THEN
          msg := 'DISABLED UNIT   (16)';
          dpp$convert_int_to_str_hex (2, lu, msg (15, * ));
          dpp$display_error (msg);
        IFEND;
      IFEND;
    FOREND;


{ Resume the pps.

    IF npp > 0 THEN
      FOR j := 1 TO npp DO
        p := pp_list_p^ [j];
        IF NOT cmv$logical_pp_table_p^ [p].flags.disabled THEN
          iop$idle_resume (p, ioc$ira_resume, id_status);
          IF NOT id_status.normal THEN
            iov$no_resume_request := iov$no_resume_request + 1;
          IFEND;
        IFEND;
      FOREND;
    IFEND;


{ Return the requests from the unit queues.

    return_requests (unit_list_p, number_of_units, status);

    IF ((NOT status.normal) AND (status.condition = ioc$critical_device_disabled)) THEN
      RETURN; {----->
    IFEND;

  PROCEND disable_units;

?? TITLE := '  return_requests', EJECT ??

  PROCEDURE [XDCL] return_requests
    (    unit_list_p: ^array [1 .. * ] of iot$logical_unit;
         number_of_units: iot$logical_unit;
     VAR status: syt$monitor_status);

    VAR
      logical_unit: iot$logical_unit,
      critical: boolean,
      p_unit_table: ^iot$unit_interface_table,
      i: integer,
      lock_set: boolean,
      search_test: boolean,
      old_time: integer,
      new_time: integer,
      loop: boolean,
      completed_request_p: ^iot$disk_request,
      msg: string (72),
      next_io_request: ^iot$io_request,
      io_function: iot$io_function,
      list_p: ^mmt$rma_list,
      address_pair_count: mmt$rma_list_length,
      job_id: jmt$ijl_ordinal,
      server_iocb_p: ^mmt$server_iocb_entry,
      system_file_id: gft$system_file_identifier,
      byte_address: amt$file_byte_address,
      write_tu_status: dmt$write_tu_status,
      media_error: boolean,
      requested_cylinder: iot$cylinder,
      cylinder: iot$cylinder,
      mau_offset_in_cylinder: dmt$maus_per_position,
      au_was_previously_written: boolean,
      t_status: syt$monitor_status,
      c_status: syt$monitor_status,
      m_status: syt$monitor_status,
      normal: iot$io_error,
      m: 0 .. ioc$command_map_count,
      index: 0 .. ioc$request_heap_count,
      c_index: 0 .. ioc$command_map_count;

    status.normal := TRUE;

  /units/
    FOR i := 1 TO number_of_units DO
      logical_unit := unit_list_p^ [i];
      p_unit_table := cmv$logical_unit_table^ [logical_unit].unit_interface_table;
      IF NOT p_unit_table^.unit_status.disabled THEN
        iov$unit_not_disabled := iov$unit_not_disabled + 1;
        status.normal := FALSE;
        CYCLE /units/; {----->
      IFEND;

      IF (iov$disk_unit_usage_p <> NIL) AND (iov$disk_unit_usage_p^ [logical_unit] <> NIL) THEN
        IF iov$disk_unit_usage_p^ [logical_unit]^.last_request_good THEN
          dsp$mtr_save_disk_error (dsc$ssr_sds_disk_request_bad, #FREE_RUNNING_CLOCK (0),
                iov$disk_unit_usage_p^ [logical_unit]^.element_name);
          iov$disk_unit_usage_p^ [logical_unit]^.last_request_good := FALSE;
        IFEND;
      IFEND;


{Set unit queue lockword.}
      iop$set_queue_lockword (p_unit_table^.unit_q_lockword, lock_set);

      IF NOT lock_set AND (iov$reject_interlock_set < 0ffffffffffff(16)) THEN
        iov$reject_interlock_set := iov$reject_interlock_set + 1;
      IFEND;

      next_io_request := p_unit_table^.next_request;

      IF p_unit_table^.queue_count <> 0 THEN
        search_test := TRUE;

      /loop1/
        WHILE search_test DO
          IF next_io_request = NIL THEN
            IF (iov$stream_requests [logical_unit] <> NIL) THEN
              iov$empty_requests_end^ := iov$stream_requests [logical_unit];
              iov$empty_requests_end := iov$stream_requests_end [logical_unit];
              iov$stream_requests_end [logical_unit] := ^iov$stream_requests [logical_unit];
              iov$stream_requests [logical_unit] := NIL;
            IFEND;
            EXIT /loop1/; {----->
          IFEND;

          completed_request_p := next_io_request^.device_request_p;
          cylinder := 0;
          mau_offset_in_cylinder := 0;
          media_error := FALSE;
          IF (completed_request_p^.request_info.request_type <> ioc$device_io) AND
                (NOT completed_request_p^.request_info.au_was_previously_written) THEN
            normal := ioc$unit_down_on_init;
          ELSE
            normal := ioc$unrecovered_error_unit_down;
          IFEND;
          write_tu_status := dmc$tu_not_written;
          c_status.condition := mme$volume_unavailable;


{Unlock pages.

          IF completed_request_p^.request_info.list_length <> 0 THEN
            io_function := completed_request_p^.request_info.io_function;
            list_p := completed_request_p^.request_info.list_p;
            address_pair_count := completed_request_p^.request_info.list_length;
            mmp$unlock_rma_list (io_function, list_p, address_pair_count,
                  completed_request_p^.request_info.io_identifier,
                  (completed_request_p^.request_info.system_file_id.residence = gfc$tr_job), normal,
                  m_status);
            IF m_status.normal = FALSE THEN
              mtp$error_stop ('IO12 - abnormal unlock status');
            IFEND;

{ It is possible that the job has terminated or the file deleted if this is for a local
{ file write.  We do not need to reset the fau state in dmp$transfer_unit_completed if this
{ is the case.  So, we will lie and say write_tu_status is written.
{ Mmp$unlock_rma_list returns ioc$no_error in normal if it has processed the
{ error.  Errors are not processed if the page is in the free queue (i.e. the job
{ had terminated or the file deleted) and normal will still indicate an error.

            IF (completed_request_p^.request_info.system_file_id.residence = gfc$tr_job) AND
                  ((io_function = ioc$write_page) OR (io_function = ioc$write_locked_page)) AND
                  (normal <> ioc$no_error) THEN
              write_tu_status := dmc$tu_written;
            IFEND;
          IFEND;

{Call mmp$mtr_process_io_completion.

          IF completed_request_p^.request_info.io_identifier.specified THEN
            c_status.normal := normal = ioc$no_error;
            CASE io_function OF
            = ioc$read_for_server .. ioc$write_to_client =
              dfp$fetch_server_iocb (completed_request_p^.request_info.io_identifier.queue_entry_location,
                    server_iocb_p);
              mmp$mtr_process_server_complete (dfc$completing_previous_request,
                    completed_request_p^.request_info.io_identifier, server_iocb_p, c_status);
            = ioc$read_ahead_on_server =
              mmp$process_read_ahead_complete (completed_request_p^.request_info.io_identifier, c_status);
            ELSE
              mmp$mtr_process_io_completion (completed_request_p^.request_info.io_identifier,
                    completed_request_p^.request_info.io_function, c_status);
            CASEND;
          IFEND;

{check if transfer unit was previously written.}
          IF completed_request_p^.request_info.request_type <> ioc$device_io THEN
            job_id := completed_request_p^.request_info.job_id;
            system_file_id := completed_request_p^.request_info.system_file_id;
            byte_address := completed_request_p^.request_info.byte_address;
            au_was_previously_written := completed_request_p^.request_info.au_was_previously_written;
            dmp$transfer_unit_completed (job_id, system_file_id, byte_address, write_tu_status,
                  au_was_previously_written, media_error, cylinder, mau_offset_in_cylinder, io_function,
                  t_status);
            IF t_status.normal = FALSE THEN
              mtp$error_stop ('IO13 - abnormal dmp status');
            IFEND;

{If ioc$device_io request, return completion status.
          ELSE
            completed_request_p^.request_info.completion^ := 2;
          IFEND;

{Clear request packet allocation.}
          completed_request_p^.link := NIL;
          iov$empty_requests_end^ := next_io_request;
          iov$empty_requests_end := ^completed_request_p^.link;
          index := completed_request_p^.request_index;


{ Don't stop on a bad request, just note the fact in the critial log and continue.
{ Since there is nothing to respond to, just clear the lock and continue.

          IF iov$request_heap_map [index] = FALSE THEN
            msg := ' Invalid PP response discarded in Return_Request for unit ';
            dpp$convert_int_to_str_hex (2, logical_unit, msg (59, * ));
            dpp$display_error (msg);
            EXIT /loop1/; {----->

{           mtp$error_stop ('IO02 - invalid pp response');
          IFEND;

          iov$request_heap_map [index] := FALSE;
          iov$empty_request_count := iov$empty_request_count + 1;
          IF completed_request_p^.request_info.command_group_count <> 0 THEN
            c_index := completed_request_p^.request_info.command_index;
            FOR m := 0 TO completed_request_p^.request_info.command_group_count - 1 DO
              IF iov$command_heap_map [c_index + m] = FALSE THEN
                mtp$error_stop ('IO03 - invalid pp response');
              IFEND;
              iov$command_heap_map [c_index + m] := FALSE;
            FOREND;
          IFEND;

          next_io_request := completed_request_p^.request.next_pp_request;

          IF iov$requests_dequeued < 0ffffffffffff(16) THEN
            iov$requests_dequeued := iov$requests_dequeued + 1;
          IFEND;
        WHILEND /loop1/;

        p_unit_table^.next_request_rma := 0;
        p_unit_table^.next_request := NIL;
        p_unit_table^.queue_count := 0;
      IFEND;

{Clear unit queue lockword.}
      iop$clear_queue_lockword (p_unit_table^.unit_q_lockword);

{ Change element capabilities, tell device management.

      IF (cmc$io_request_submission IN cmv$logical_unit_table^ [logical_unit].element_capability) THEN
        cmv$logical_unit_table^ [logical_unit].element_capability :=
              $cmt$element_capabilities [cmc$concurrent_maintenance];
        dmp$volume_down (logical_unit, critical);

        IF critical THEN

          iop$enable_all_disk_units (status);

          status.normal := FALSE;
          status.condition := ioc$critical_device_disabled;
          RETURN; {----->
        IFEND;

      IFEND;

    FOREND /units/;

  PROCEND return_requests;
?? TITLE := ' send_cm_signal ', EJECT ??

  PROCEDURE send_cm_signal
    (    signal_contents: cmt$signal_contents);

    VAR
      signal: pmt$signal,
      status: syt$monitor_status;

    signal.identifier := cmc$configuration_signal_id;
    #UNCHECKED_CONVERSION (signal_contents, signal.contents);

    send_reconfiguration_message (signal_contents);
    tmp$send_signal (tmv$system_job_monitor_gtid, signal, status);
    IF NOT status.normal THEN
      dpp$display_error ('Unable to send reconfiguration signal to job monitor task.');
    IFEND;

  PROCEND send_cm_signal;

?? TITLE := ' send_reconfiguration_message ', EJECT ??

  PROCEDURE send_reconfiguration_message
    (    signal_contents: cmt$signal_contents);

    VAR
      controller_address: cmt$physical_address,
      msg: ost$string,
      p_downline_element: ^cmt$peripheral_element_entry,
      p_upline_element: ^cmt$peripheral_element_entry,
      status: syt$monitor_status;

    msg.value (1, 18) := 'DISABLED ELEMENT: ';
    msg.size := 19;

    CASE signal_contents.signal_type OF
    = cmc$disable_element_signal =
      cmp$locate_element_via_adr (signal_contents.disable_element_address, p_downline_element);
      IF p_downline_element = NIL THEN
        RETURN; {----->
      IFEND;
      msg.value (msg.size, 31) := p_downline_element^.element_name;
      msg.size := msg.size + clp$trimmed_string_size (p_downline_element^.element_name);

    = cmc$reconfiguration_signal =
      cmp$locate_element_via_adr (signal_contents.reconfig_element_address, p_downline_element);
      IF p_downline_element = NIL THEN
        RETURN; {----->
      IFEND;

      IF p_downline_element^.physical_descriptor.element_type = cmc$storage_device_element THEN
        controller_address := signal_contents.reconfig_element_address;
        controller_address.address_specifier := cmv$controller_address;
        controller_address.unit_address := 0;

        cmp$locate_element_via_adr (controller_address, p_upline_element);
        IF p_upline_element = NIL THEN
          RETURN; {----->
        IFEND;

        msg.value (1, 21) := 'DISABLED CONNECTION: ';
        msg.size := 22;

        msg.value (msg.size, 31) := p_upline_element^.element_name;
        msg.size := msg.size + clp$trimmed_string_size (p_upline_element^.element_name);

        msg.value (msg.size, 1) := '.';
        msg.size := msg.size + 1;

        msg.value (msg.size, 31) := p_downline_element^.element_name;
        msg.size := msg.size + clp$trimmed_string_size (p_downline_element^.element_name);
      ELSE
        msg.value (msg.size, 31) := p_downline_element^.element_name;
        msg.size := msg.size + clp$trimmed_string_size (p_downline_element^.element_name);
      IFEND;
    ELSE
    CASEND;

    dpp$display_error (msg.value (1, msg.size - 1));

  PROCEND send_reconfiguration_message;

MODEND iom$down_disk_unit;
