?? TITLE := 'NOS/VE Subsystem IO' ??
MODULE iom$subsystem_io_r113;
?? RIGHT := 110 ??
{
{  PURPOSE: This module contains the ring 1 code to support subsystem io.
{           The code consists of procedures involved in queuing requests
{           to io queues.
{
{  DESIGN:  An io request has an associated wired io request which is used
{           to communicate between the PP system and the CP system.  The
{           wired io request is dynamically allocated in the mainframe wired
{           heap.  Currently, for unit requests, io pages are locked and
{           converted to rmas via a monitor request.  For pp requests, io
{           pages are assumed to be in mainframe wired (thus no locking is
{           required), the io page rma translation is done in ring 1 and
{           the request is queued by ring 1 code.
{
?? TITLE := '  Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc osc$purge_map_and_cache
*copyc cyd$cybil_structure_definitions
*copyc osd$virtual_address
*copyc ioe$st_errors
*copyc mme$condition_codes
*copyc cmt$io_command_table
*copyc cmt$io_commands
*copyc cmt$subsystem_equip_description
*copyc iot$io_completion_table
*copyc iot$io_request
*copyc iot$logical_unit
*copyc iot$pp_interface_table
*copyc iot$pva_list
*copyc iot$request_recovery
*copyc ost$hardware_subranges
*copyc ost$page_size
*copyc ost$signature_lock
?? POP ??
*copyc cmp$clear_ioct_serial_lock
*copyc cmp$get_io_completion_tbl_entry
*copyc cmp$get_logical_pp_number
*copyc cmp$get_logical_unit_number
*copyc cmp$set_ioct_serial_lock
*copyc iop$clear_queue_lockword_sc
*copyc iop$set_queue_lockword_sc
*copyc iop$set_status_abnormal
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc pmp$cycle
*copyc pmp$get_compact_date_time
*copyc pmp$zero_out_table
*copyc cmv$logical_pp_table_p
*copyc cmv$logical_unit_table
*copyc cmv$subsys_io_responses
*copyc iov$subsys_process_pp_response
*copyc osv$external_interrupt_selector
*copyc osv$mainframe_wired_cb_heap
*copyc osv$mainframe_wired_heap
*copyc osv$page_size
*copyc i#build_adaptable_seq_pointer
*copyc i#call_monitor
*copyc i#real_memory_address

  VAR
    dmv$external_interrupt_selector: [XREF] 0 .. 0ff(16);

?? TITLE := '  build_wired_unit_queue_request', EJECT ??

  PROCEDURE build_wired_queue_request
    (    io_request_id: cmt$subsystem_io_request_id;
         data_command_descriptors_p: ^cmt$data_command_descriptors;
         command_table_p: ^cmt$io_command_table;
     VAR status: ost$status);

    VAR
      wired_queue_request_p: ^cmt$wired_unit_queue_request,
      io_request_p: ^iot$io_request,
      pp_response_p: ^cmt$collected_pp_response,
      wired_data_command_descript_p: ^cmt$wired_data_descriptors,
      command_table_index: cmt$command_index,
      number_of_wired_descriptors: cmt$command_index,
      lock_data_pages: boolean,
      data_cannot_span_pages: boolean,
      number_of_command_entries: integer,
      command_heap_p: ^cmt$subsystem_command_heap,
      number_of_command_heap_entries: integer,
      data_p: ^SEQ ( * ),
      move_data_from_wired_area: boolean,
      request_block_p: ^iot$monitor_request_block,
      pva: ^cell,
      move_data_to_wired_area: boolean,
      length: ost$segment_length,
      io_completion_queue_index: cmt$io_completion_queue_index,
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      data_command_descriptor_index: integer,
      page_offset: 0 .. 65535,
      wired_data_descriptor_area_p: ^cmt$wired_descriptor_area,
      wired_data_area_p: ^SEQ ( * ),
      global_task_id: ost$global_task_id,
      wired_heap_p: ^ost$heap,
      number_data_command_descriptors: cmt$command_index;

  /process_request/
    BEGIN

      status.normal := TRUE;

      wired_data_command_descript_p := NIL;
      command_heap_p := NIL;
      wired_heap_p := osv$mainframe_wired_cb_heap;
      number_of_command_heap_entries := 0;
      number_of_wired_descriptors := 0;
      io_completion_queue_index := io_request_id.system_supplied;
      number_of_command_entries := UPPERBOUND (command_table_p^);

      cmp$get_io_completion_tbl_entry (io_completion_queue_index, io_completion_table_entry_p);

      wired_queue_request_p := io_completion_table_entry_p^.wired_unit_queue_request_p;
      IF wired_queue_request_p = NIL THEN
        ALLOCATE wired_queue_request_p: [1 .. cmc$max_command_index] IN wired_heap_p^;
        ALLOCATE pp_response_p IN wired_heap_p^;
        ALLOCATE io_request_p IN wired_heap_p^;
        io_request_p^.device_request_p := wired_queue_request_p;
        io_request_p^.response_processor_p := iov$subsys_process_pp_response;
        ALLOCATE wired_data_command_descript_p: [1 .. cmc$max_command_index] IN wired_heap_p^;
        ALLOCATE command_heap_p: [1 .. mmc$max_rma_list_length] IN wired_heap_p^;
        ALLOCATE request_block_p IN wired_heap_p^;

        wired_queue_request_p^.wired_pp_response_p := pp_response_p;
        wired_queue_request_p^.wired_io_request_p := io_request_p;
        wired_queue_request_p^.wired_data_command_descript_p := wired_data_command_descript_p;
        wired_queue_request_p^.wired_command_heap_p := command_heap_p;
        wired_queue_request_p^.response_area_p := cmv$subsys_io_responses_p;
        wired_queue_request_p^.monitor_request_block_p := request_block_p;

        io_completion_table_entry_p^.wired_unit_queue_request_p := wired_queue_request_p;
      IFEND;
      pp_response_p := wired_queue_request_p^.wired_pp_response_p;
      pp_response_p^.response_status := cmc$subsys_io_resp_not_avail;
      pp_response_p^.pp_number := 0;
      pmp$zero_out_table (#LOC (pp_response_p^.pp_response), #SIZE (pp_response_p^.pp_response));
      pmp$zero_out_table (#LOC (pp_response_p^.detailed_status), #SIZE (pp_response_p^.detailed_status));

      cmp$create_io_queue_request (command_table_p, wired_queue_request_p, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      global_task_id := io_completion_table_entry_p^.global_task_id;

      IF data_command_descriptors_p <> NIL THEN

        number_data_command_descriptors := UPPERBOUND (data_command_descriptors_p^);

        wired_data_command_descript_p := wired_queue_request_p^.wired_data_command_descript_p;

        FOR data_command_descriptor_index := 1 TO number_data_command_descriptors DO
          move_data_to_wired_area := data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_to_wired_area;
          move_data_from_wired_area := data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_from_wired_area;
          lock_data_pages := data_command_descriptors_p^ [data_command_descriptor_index].lock_data_pages;
          pva := data_command_descriptors_p^ [data_command_descriptor_index].address;
          length := data_command_descriptors_p^ [data_command_descriptor_index].length;
          command_table_index := data_command_descriptors_p^ [data_command_descriptor_index].command_index;

          IF move_data_to_wired_area OR move_data_from_wired_area OR lock_data_pages THEN
            number_of_wired_descriptors := number_of_wired_descriptors + 1;
            wired_data_command_descript_p^ [number_of_wired_descriptors].command_index := command_table_index;
            wired_data_command_descript_p^ [number_of_wired_descriptors].rma_list_index := 0;
            wired_data_command_descript_p^ [number_of_wired_descriptors].lock_data_pages := lock_data_pages;
            wired_data_command_descript_p^ [number_of_wired_descriptors].io_direction :=
                  data_command_descriptors_p^ [data_command_descriptor_index].io_direction;
            wired_data_command_descript_p^ [number_of_wired_descriptors].data_descriptor_index :=
                  data_command_descriptor_index;
            wired_data_command_descript_p^ [number_of_wired_descriptors].length := length;
            wired_data_command_descript_p^ [number_of_wired_descriptors].address := pva;

            IF move_data_to_wired_area OR move_data_from_wired_area THEN
              data_cannot_span_pages := NOT command_table_p^ [command_table_index].flags.indirect_address;
              get_wired_data_seq (data_cannot_span_pages, length, wired_data_descriptor_area_p);
              wired_data_area_p := ^wired_data_descriptor_area_p^.data_area;
              RESET wired_data_area_p;
              IF move_data_to_wired_area THEN
                i#build_adaptable_seq_pointer (#RING (pva), #SEGMENT (pva), #OFFSET (pva), length, 0, data_p);
                RESET data_p;
                wired_data_area_p^ := data_p^;
              ELSE
                pmp$zero_out_table (#LOC (wired_data_area_p^), length);
              IFEND;
              wired_data_command_descript_p^ [number_of_wired_descriptors].
                    address := #LOC (wired_data_descriptor_area_p^);
            IFEND;
            page_offset := #OFFSET (wired_data_command_descript_p^ [number_of_wired_descriptors].address) MOD
                  osv$page_size;
            number_of_command_heap_entries := number_of_command_heap_entries +
                  ((page_offset + length + osv$page_size - 1) DIV osv$page_size);
          IFEND;
        FOREND;

      IFEND;

      IF number_of_command_heap_entries > 0 THEN

        command_heap_p := wired_queue_request_p^.wired_command_heap_p;

        pmp$zero_out_table (#LOC (command_heap_p^), #SIZE (command_heap_p^));

      IFEND;

      wired_queue_request_p^.io_identification := io_request_id;
      wired_queue_request_p^.task_id := global_task_id;
      wired_queue_request_p^.number_of_commands := number_of_command_entries;
      wired_queue_request_p^.unit_queuing_control := cmc$first_in_first_out_queue;
      wired_queue_request_p^.task_is_to_be_readied := FALSE;
      wired_queue_request_p^.number_of_data_descriptors := number_of_wired_descriptors;
      IF dmv$external_interrupt_selector = 1 THEN
        wired_queue_request_p^.request.interrupt.value := TRUE;
      ELSE
        wired_queue_request_p^.request.interrupt.value := FALSE;
      IFEND;
      wired_queue_request_p^.request.interrupt.port_number := osv$external_interrupt_selector;
      wired_queue_request_p^.address_word_pair_count := 0;

    END /process_request/;

  PROCEND build_wired_queue_request;
?? TITLE := '  create_peripheral_request', EJECT ??

  PROCEDURE create_peripheral_request
    (    pp_request_p: ^cmt$pp_request;
     VAR status: ost$status);

    status.normal := TRUE;

    pp_request_p^.fill1 := 0;
    pp_request_p^.next_pp_request := NIL;
    pp_request_p^.fill2 := 0;
    pp_request_p^.next_pp_request_rma := 0;
    pp_request_p^.request_length := #SIZE (pp_request_p^);
    pp_request_p^.logical_unit := 0;
    pp_request_p^.recovery := ioc$terminate_at_error;
    pp_request_p^.interrupt.value := FALSE;
    pp_request_p^.interrupt.port_number := 1;
    pp_request_p^.priority := 0;
    pp_request_p^.alert_mask.compare_not_satisfied := FALSE;
    pp_request_p^.alert_mask.long_input_block := FALSE;
    pp_request_p^.alert_mask.physical_delimiter := FALSE;
    pp_request_p^.alert_mask.logical_delimiter := FALSE;
    pp_request_p^.alert_mask.character_fill := FALSE;
    pp_request_p^.alert_mask.fill := 0;
    pp_request_p^.current_command_index := 0;
    pp_request_p^.fill3 := 0;

    pmp$zero_out_table (#LOC (pp_request_p^.commands), #SIZE (pp_request_p^.commands));

  PROCEND create_peripheral_request;
?? TITLE := '  get_wired_data_seq', EJECT ??

  PROCEDURE get_wired_data_seq
    (    data_cannot_span_pages: boolean;
         data_length: ost$segment_length;
     VAR wired_data_descriptor_area_p: ^cmt$wired_descriptor_area);

    VAR
      wired_data_area_p: ^SEQ ( * );

    wired_data_area_p := NIL;

    ALLOCATE wired_data_descriptor_area_p: [[REP data_length OF ost$byte]] IN osv$mainframe_wired_cb_heap^;

    wired_data_area_p := ^wired_data_descriptor_area_p^.data_area;

  PROCEND get_wired_data_seq;

?? TITLE := '  [XDCL, #GATE] cmp$build_wired_queue_request', EJECT ??

*copyc cmh$build_wired_queue_request

  PROCEDURE [XDCL, #GATE] cmp$build_wired_queue_request
    (    element_name: cmt$element_name;
         request_type: cmt$io_request_type;
         command_table_p: ^cmt$io_command_table;
         data_command_descriptors_p: ^cmt$data_command_descriptors;
         request_id: cmt$subsystem_io_request_id;
         io_response_p: ^cmt$os_subsystem_io_response;
     VAR status: ost$status);

    VAR
      io_completion_table_entry_p: ^cmt$io_completion_table_entry;


    status.normal := TRUE;

  /process_request/
    BEGIN

      build_wired_queue_request (request_id, data_command_descriptors_p, command_table_p, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      cmp$get_io_completion_tbl_entry (request_id.system_supplied, io_completion_table_entry_p);

      io_completion_table_entry_p^.io_request_type.kind := request_type;
      io_completion_table_entry_p^.io_request_type.element_name := element_name;

    END /process_request/;


  PROCEND cmp$build_wired_queue_request;
?? TITLE := '  cmp$build_rma_list', EJECT ??

*copyc ioh$build_rma_list

  PROCEDURE cmp$build_rma_list
    (    pva_list_p: ^iot$pva_list;
         rma_list_p: ^mmt$rma_list;
         rma_list_length: mmt$rma_list_length);

    VAR
      rma_list_index: mmt$rma_list_index,
      length: ost$segment_length,
      page_offset: ost$segment_offset,
      unused_rma_list_index: mmt$rma_list_index,
      pva: ^cell,
      rma: integer,
      pva_list_index: integer;

    rma_list_index := LOWERBOUND (rma_list_p^);

    FOR pva_list_index := 1 TO UPPERBOUND (pva_list_p^) DO
      pva := pva_list_p^ [pva_list_index].address;
      length := pva_list_p^ [pva_list_index].length;
      page_offset := #OFFSET (pva) MOD osv$page_size;

      WHILE length <> 0 DO
        i#real_memory_address (pva, rma);

        rma_list_p^ [rma_list_index].rma := rma;
        rma_list_p^ [rma_list_index].fill := 0;

        IF page_offset + length > osv$page_size THEN
          rma_list_p^ [rma_list_index].length := osv$page_size - page_offset;
        ELSE
          rma_list_p^ [rma_list_index].length := length;
        IFEND;

        length := length - rma_list_p^ [rma_list_index].length;
        page_offset := 0;
        pva := #ADDRESS (#RING (pva), #SEGMENT (pva), rma_list_p^ [rma_list_index].length);
        rma_list_index := rma_list_index + 1;
        IF rma_list_index > (rma_list_length + 1) THEN
          osp$system_error ('RMA list length error - IOMSSIOR113', NIL);
        IFEND;

      WHILEND;

    FOREND;

    {
    { Fill unused rma list entries.
    {
    unused_rma_list_index := rma_list_index;
    WHILE unused_rma_list_index <= rma_list_length DO
      rma_list_p^ [unused_rma_list_index].rma := 0;
      rma_list_p^ [unused_rma_list_index].length := 0;
      rma_list_p^ [unused_rma_list_index].fill := 0;
      unused_rma_list_index := unused_rma_list_index + 1;
    WHILEND;

  PROCEND cmp$build_rma_list;
?? TITLE := '  cmp$create_io_queue_request', EJECT ??

  PROCEDURE cmp$create_io_queue_request
    (    command_table_p: ^cmt$io_command_table;
     VAR queue_request_p: ^cmt$wired_unit_queue_request;
     VAR status: ost$status);

    VAR
      command_index: cmt$command_index,
      command_code: cmt$command_code,
      command_table_size: cmt$command_index,
      pp_request_p: ^cmt$pp_request;

    status.normal := TRUE;

  /process_request/
    BEGIN

      command_table_size := UPPERBOUND (command_table_p^);

      pp_request_p := ^queue_request_p^.request;

      create_peripheral_request (pp_request_p, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      FOR command_index := LOWERBOUND (command_table_p^) TO command_table_size DO
        command_code := command_table_p^ [command_index].command_code;
        pp_request_p^.commands [command_index].command_code := command_code;
        pp_request_p^.commands [command_index].flags := command_table_p^ [command_index].flags;
        CASE command_code OF
        = cmc$cc_acknowledge .. cmc$cc_resume, cmc$cc_start_ready_scan .. cmc$cc_select_pp_address,
              cmc$cc_enable_unit .. cmc$cc_master_clear_controller, cmc$cc_function, cmc$cc_select_density,
              cmc$first_pp_dependent_cc .. cmc$last_pp_dependent_cc,
              cmc$first_unit_dependent_cc .. cmc$last_unit_dependent_cc =
          pp_request_p^.commands [command_index].length := command_table_p^ [command_index].length;
          pp_request_p^.commands [command_index].address := command_table_p^ [command_index].value;
        ELSE
        CASEND;
      FOREND;

      pp_request_p^.request_length := pp_request_p^.request_length -
            (cmc$max_command_index - command_table_size) * #SIZE (cmt$command);

    END /process_request/;

  PROCEND cmp$create_io_queue_request;
?? TITLE := '  [XDCL, #GATE] cmp$get_subsys_equip_desc_r1', EJECT ??

*copyc cmh$get_subsys_equip_desc_r1

  PROCEDURE [XDCL, #GATE] cmp$get_subsys_equip_desc_r1
    (    pp_number: iot$pp_number;
         logical_unit: iot$logical_unit;
     VAR equipment_description: cmt$subsystem_equip_description;
     VAR status: ost$status);

    VAR
      equipment: cmt$physical_equipment_number,
      controller_type: cmt$controller_type,
      unit_descriptor_index: integer,
      physical_unit: iot$physical_unit_number,
      physical_channel: iot$channel_number,
      unit_descriptor_found: boolean,
      unit_descriptor_entry_p: ^iot$unit_descriptor_entry,
      unit_type: iot$unit_type;

    status.normal := TRUE;

    unit_type := 0;
    unit_descriptor_found := FALSE;

  /locate_unit_descriptor/
    FOR unit_descriptor_index := UPPERBOUND (cmv$logical_pp_table_p^ [pp_number].pp_info.
          pp_interface_table_p^.unit_descriptors) DOWNTO LOWERBOUND (cmv$logical_pp_table_p^ [pp_number].
          pp_info.pp_interface_table_p^.unit_descriptors) DO
      unit_descriptor_entry_p := ^cmv$logical_pp_table_p^ [pp_number].pp_info.pp_interface_table_p^.
            unit_descriptors [unit_descriptor_index];
      IF unit_descriptor_entry_p^.logical_unit = logical_unit THEN
        unit_descriptor_found := TRUE;
        EXIT /locate_unit_descriptor/; {----->
      IFEND;
    FOREND /locate_unit_descriptor/;

    IF NOT unit_descriptor_found THEN
      iop$set_status_abnormal (ioe$unable_to_destroy_io_req, 'Unable to locate unit descriptor - IOMSSIOR113',
            status);
      RETURN; {----->
    IFEND;

    equipment_description.physical_channel := unit_descriptor_entry_p^.physical_path.channel_number;
    equipment_description.physical_unit := unit_descriptor_entry_p^.physical_path.physical_unit_number;
    equipment_description.equipment := unit_descriptor_entry_p^.physical_path.controller_number;
    equipment_description.unit_type := cmv$logical_unit_table^ [logical_unit].unit_interface_table^.unit_type;
    equipment_description.controller_type := cmv$logical_pp_table_p^ [pp_number].controller_info.
          controller_type;
    equipment_description.pp_number := pp_number;
    equipment_description.logical_unit := logical_unit;

  PROCEND cmp$get_subsys_equip_desc_r1;
?? TITLE := '  [XDCL, #GATE] cmp$queue_request_r1', EJECT ??

*copyc cmh$queue_request_r1

  PROCEDURE [XDCL, #GATE] cmp$queue_request_r1
    (    request_id: cmt$subsystem_io_request_id;
         queue_control: cmt$unit_queuing_options;
         recovery_options: iot$request_recovery;
         ready_task_upon_io_completion: boolean;
     VAR status: ost$status);

    VAR
      wired_queue_request_p: ^cmt$wired_unit_queue_request,
      element_name: cmt$element_name,
      job_io_completion_queue_index: cmt$io_completion_queue_index,
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      binary_time: ost$date_time,
      command_table_index: cmt$command_index,
      data_command_descriptors_p: ^cmt$data_command_descriptors,
      logical_pp_number: iot$pp_number,
      logical_unit_number: iot$logical_unit,
      command_code: cmt$command_code,
      data_command_descriptor_index: cmt$command_index,
      request_type: cmt$io_request_type;


  /process_request/
    BEGIN

      status.normal := TRUE;


      job_io_completion_queue_index := request_id.system_supplied;

      cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);

      wired_queue_request_p := io_completion_table_entry_p^.wired_unit_queue_request_p;

      IF (request_id.system_supplied = 0) OR (request_id <> wired_queue_request_p^.io_identification) THEN
        iop$set_status_abnormal (ioe$request_id_mismatch,
              'Request id mismatch when queuing pp request - IOMSSIOR113', status);
        EXIT /process_request/; {----->
      IFEND;

      request_type := io_completion_table_entry_p^.io_request_type.kind;
      data_command_descriptors_p := io_completion_table_entry_p^.data_command_descriptors_p;

      element_name := io_completion_table_entry_p^.io_request_type.element_name;

{ Check if PP is already loaded.

      cmp$get_logical_pp_number (element_name, logical_pp_number, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;
      IF NOT cmv$logical_pp_table_p^ [logical_pp_number].flags.pp_loaded THEN
        iop$set_status_abnormal (ioc$pp_not_configured,
              'IO queue request aborted, PP not loaded/assigned - IOMSSIOR113', status);
        EXIT /process_request/; {----->
      IFEND;

      cmp$get_logical_unit_number (element_name, logical_unit_number, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;
      wired_queue_request_p^.task_is_to_be_readied := ready_task_upon_io_completion;
      wired_queue_request_p^.unit_queuing_control := queue_control;
      wired_queue_request_p^.request.recovery := recovery_options;
      wired_queue_request_p^.request.logical_unit := logical_unit_number;

      CASE request_type OF
      = cmc$pp_io =
        queue_pp_request (element_name, wired_queue_request_p, status);
      = cmc$unit_io =
        queue_unit_request (element_name, wired_queue_request_p, status);
      CASEND;


    END /process_request/;


  PROCEND cmp$queue_request_r1;

?? TITLE := '  queue_pp_request', EJECT ??

  PROCEDURE queue_pp_request
    (    element_name: cmt$element_name;
         wired_pp_queue_request_p: ^cmt$wired_unit_queue_request;
     VAR status: ost$status);

    VAR
      pp_interface_queue_lockword_p: ^iot$lockword,
      pp_interface_table_p: ^iot$pp_interface_table,
      pp_number: iot$pp_number,
      pp_request_p: ^cmt$pp_request,
      data_length: cmt$data_descriptor_length,
      command_heap_p: ^cmt$subsystem_command_heap,
      command_length: cmt$command_length,
      pva_list_p: ^iot$pva_list,
      rma_list_index: 0 .. mmc$max_rma_list_length,
      command_index: 0 .. mmc$max_rma_list_length,
      command_address_word_pair_count: 0 .. mmc$max_rma_list_length,
      address_word_pair_count: 0 .. mmc$max_rma_list_length,
      rma: integer,
      command_rma_list_p: ^mmt$rma_list,
      create_indirect_rma_list: boolean,
      data_command_descriptors_p: ^cmt$data_command_descriptors,
      wired_data_descriptors_p: ^cmt$wired_data_descriptors,
      byte_p: ^ost$byte,
      ring: ost$ring,
      segment: ost$segment,
      offset: ost$segment_offset,
      number_data_command_descriptors: integer,
      data_in_wired_area: boolean,
      address_p: ^cell,
      first_byte_in_page_to_touch: ost$byte,
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      job_io_completion_queue_index: cmt$io_completion_queue_index,
      last_byte_to_touch: ost$byte,
      wired_data_descriptor_index: cmt$command_index,
      data_command_descriptor_index: cmt$command_index,
      page_index: 0 .. osc$max_segment_length DIV osc$min_page_size,
      number_of_pages: 0 .. osc$max_segment_length DIV osc$min_page_size,
      lock_data_pages: boolean,
      command_code: cmt$command_code,
      request_id_to_terminate_p: ^cmt$subsystem_io_request_id,
      jcq_index_to_terminate: cmt$io_completion_queue_index,
      ioct_entry_to_terminate_p: ^cmt$io_completion_table_entry,
      jcq_request_rma_to_terminate: integer,
      page_size: ost$page_size;


  /process_request/
    BEGIN

      status.normal := TRUE;

      page_size := osv$page_size;
      job_io_completion_queue_index := wired_pp_queue_request_p^.io_identification.system_supplied;
      wired_data_descriptors_p := wired_pp_queue_request_p^.wired_data_command_descript_p;
      wired_data_descriptor_index := 0;

      cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);

      data_command_descriptors_p := io_completion_table_entry_p^.data_command_descriptors_p;

      cmp$get_logical_pp_number (element_name, pp_number, status);
      IF NOT status.normal THEN
        EXIT /process_request/; {----->
      IFEND;

      IF data_command_descriptors_p <> NIL THEN
        number_data_command_descriptors := UPPERBOUND (data_command_descriptors_p^);
        PUSH pva_list_p: [1 .. 1];
        pp_request_p := ^wired_pp_queue_request_p^.request;
        command_heap_p := wired_pp_queue_request_p^.wired_command_heap_p;
        address_word_pair_count := 0;
        {
        {  Create rma lists
        {
        rma_list_index := 1;

      /process_data_descriptors/
        FOR data_command_descriptor_index := 1 TO number_data_command_descriptors DO
          command_index := data_command_descriptors_p^ [data_command_descriptor_index].command_index;
          command_code := pp_request_p^.commands [command_index].command_code;
          data_in_wired_area := (data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_from_wired_area) OR (data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_to_wired_area);
          lock_data_pages := data_command_descriptors_p^ [data_command_descriptor_index].lock_data_pages;
          data_length := data_command_descriptors_p^ [data_command_descriptor_index].length;
          CASE command_code OF
          = cmc$cc_stop_unit =
            request_id_to_terminate_p := data_command_descriptors_p^ [data_command_descriptor_index].address;
            jcq_index_to_terminate := request_id_to_terminate_p^.system_supplied;
            cmp$get_io_completion_tbl_entry (jcq_index_to_terminate, ioct_entry_to_terminate_p);
            IF ioct_entry_to_terminate_p^.wired_unit_queue_request_p = NIL THEN
              iop$set_status_abnormal (ioe$unable_to_queue_io_request,
                    'Trying to terminate invalid request id - IOMSSIOR113', status);
              EXIT /process_request/; {----->
            IFEND;
            address_p := #LOC (ioct_entry_to_terminate_p^.wired_unit_queue_request_p^.request);
            i#real_memory_address (address_p, jcq_request_rma_to_terminate);
            IF (ioct_entry_to_terminate_p^.wired_unit_queue_request_p^.io_identification <>
                  request_id_to_terminate_p^) THEN
              iop$set_status_abnormal (ioe$unable_to_queue_io_request,
                    'Trying to terminate invalid request id - IOMSSIOR113', status);
              EXIT /process_request/; {----->
            IFEND;
          ELSE
            address_p := data_command_descriptors_p^ [data_command_descriptor_index].address;
          CASEND;

          command_rma_list_p := #LOC (command_heap_p^.rma_list [rma_list_index]);

          IF lock_data_pages THEN
            iop$set_status_abnormal (ioe$unable_to_queue_io_request,
                  'Locking pages for PP IO not supported - IOMSSIOR113', status);
            EXIT /process_request/; {----->
          IFEND;

          IF data_in_wired_area THEN
            wired_data_descriptor_index := wired_data_descriptor_index + 1;
            address_p := wired_data_descriptors_p^ [wired_data_descriptor_index].address;
          IFEND;

          create_indirect_rma_list := pp_request_p^.commands [command_index].flags.indirect_address;

          IF create_indirect_rma_list THEN
            offset := #OFFSET (address_p);
            command_address_word_pair_count := (((offset + data_length + (page_size * 2) - 1)) DIV
                  page_size) - ((offset + page_size) DIV page_size);
          ELSE
            command_address_word_pair_count := 1;
          IFEND;

          pva_list_p^ [1].address := address_p;
          pva_list_p^ [1].length := data_length;

          cmp$build_rma_list (pva_list_p, command_rma_list_p, command_address_word_pair_count);

          address_word_pair_count := address_word_pair_count + command_address_word_pair_count;

          IF create_indirect_rma_list THEN
            i#real_memory_address (command_rma_list_p, rma);
            command_length := command_address_word_pair_count * 8;
          ELSE
            rma := command_heap_p^.rma_list [rma_list_index].rma;
            command_length := command_heap_p^.rma_list [rma_list_index].length;
          IFEND;

          pp_request_p^.commands [command_index].length := command_length;
          pp_request_p^.commands [command_index].address := rma;

          IF data_in_wired_area THEN
            wired_data_descriptors_p^ [wired_data_descriptor_index].rma_list_index := rma_list_index;
          IFEND;

          rma_list_index := rma_list_index + command_address_word_pair_count;

        FOREND /process_data_descriptors/;

        wired_pp_queue_request_p^.address_word_pair_count := address_word_pair_count;

      IFEND;

      pp_interface_table_p := cmv$logical_pp_table_p^ [pp_number].pp_info.pp_interface_table_p;
      pp_interface_queue_lockword_p := ^pp_interface_table_p^.lockword;

      cmp$queue_request (wired_pp_queue_request_p, wired_pp_queue_request_p^.unit_queuing_control,
            pp_interface_queue_lockword_p, ^pp_interface_table_p^.pp_request_queue, NIL,
            ^pp_interface_table_p^.pp_request_queue_rma, status);

    END /process_request/;


  PROCEND queue_pp_request;
?? TITLE := '  [XDCL] cmp$queue_request', EJECT ??

  PROCEDURE [XDCL] cmp$queue_request
    (    request_p: ^cmt$wired_unit_queue_request;
         queue_control: cmt$unit_queuing_options;
         lockword_p: ^iot$lockword;
         request_queue_p: ^^iot$io_request;
         request_queue_count_p: ^0 .. 0FFFF(16);
         request_queue_rma_p: ^ost$real_memory_address;
     VAR status: ost$status);

    VAR
      lock_set: boolean,
      lock_cleared: boolean,
      io_request_p: ^iot$io_request,
      request_queue_is_empty: boolean,
      next_io_request_p: ^iot$io_request,
      rma: integer,
      previous_request_p: ^cmt$max_wired_unit_queue_req,
      pp_request_p: ^cmt$pp_request;

    status.normal := TRUE;

    request_queue_is_empty := TRUE;
    next_io_request_p := NIL;
    previous_request_p := NIL;

    io_request_p := request_p^.wired_io_request_p;
    pp_request_p := ^request_p^.request;

    pp_request_p^.next_pp_request := NIL;
    pp_request_p^.next_pp_request_rma := 0;

    i#real_memory_address (#LOC (pp_request_p^), rma);

    iop$set_queue_lockword_sc (lockword_p^, lock_set);

  /queue_lock_set/
    BEGIN
      {
      {Insert request in queue.}
      {
      request_queue_is_empty := (request_queue_p^ = NIL);

      IF request_queue_is_empty THEN
        request_queue_p^ := io_request_p;
        request_queue_rma_p^ := rma;
      ELSE
        next_io_request_p := request_queue_p^;

        CASE queue_control OF

        = cmc$first_in_first_out_queue =

        /insert_request_loop/
          WHILE next_io_request_p <> NIL DO
            previous_request_p := next_io_request_p^.device_request_p;
            next_io_request_p := previous_request_p^.request.next_pp_request;
          WHILEND /insert_request_loop/;

        ELSE
          iop$set_status_abnormal (ioe$io_completion_table_error, 'Unsupported queuing option - IOMSSIOR113',
                status);
          EXIT /queue_lock_set/; {----->
        CASEND;

        previous_request_p^.request.next_pp_request := io_request_p;
        previous_request_p^.request.next_pp_request_rma := rma;
      IFEND;

    END /queue_lock_set/;

    IF request_queue_count_p <> NIL THEN
      request_queue_count_p^ := (request_queue_count_p^ +1) MOD (0FFFF(16) + 1);
    IFEND;

    iop$clear_queue_lockword_sc (lockword_p^);

  PROCEND cmp$queue_request;
?? TITLE := '  queue_unit_request', EJECT ??

  PROCEDURE queue_unit_request
    (    element_name: cmt$element_name;
         wired_unit_queue_request_p: ^cmt$wired_unit_queue_request;
     VAR status: ost$status);

    VAR
      pp_request_p: ^cmt$pp_request,
      data_length: cmt$data_descriptor_length,
      command_heap_p: ^cmt$subsystem_command_heap,
      command_length: cmt$command_length,
      pva_list_p: ^iot$pva_list,
      rma_list_index: 0 .. mmc$max_rma_list_length,
      command_index: 0 .. mmc$max_rma_list_length,
      command_address_word_pair_count: 0 .. mmc$max_rma_list_length,
      address_word_pair_count: 0 .. mmc$max_rma_list_length,
      rma: integer,
      command_rma_list_p: ^mmt$rma_list,
      create_indirect_rma_list: boolean,
      request_block_p: ^iot$monitor_request_block,
      unit_interface_table_p: ^iot$unit_interface_table,
      unit_queue_lockword_p: ^iot$lockword,
      queue_entry_in_monitor: boolean,
      data_command_descriptors_p: ^cmt$data_command_descriptors,
      wired_data_descriptors_p: ^cmt$wired_data_descriptors,
      byte_p: ^ost$byte,
      ring: ost$ring,
      segment: ost$segment,
      offset: ost$segment_offset,
      number_data_command_descriptors: integer,
      data_in_wired_area: boolean,
      address_p: ^cell,
      first_byte_in_page_to_touch: ost$byte,
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      job_io_completion_queue_index: cmt$io_completion_queue_index,
      last_byte_to_touch: ost$byte,
      wired_data_descriptor_index: cmt$command_index,
      data_command_descriptor_index: cmt$command_index,
      page_index: 0 .. osc$max_segment_length DIV osc$min_page_size,
      null_sva: 0 .. 0ffffffffffff(16),
      number_of_pages: 0 .. osc$max_segment_length DIV osc$min_page_size,
      lock_data_pages: boolean,
      page_size: ost$page_size;


  /process_request/
    BEGIN

      status.normal := TRUE;

      page_size := osv$page_size;
      job_io_completion_queue_index := wired_unit_queue_request_p^.io_identification.system_supplied;
      wired_data_descriptors_p := wired_unit_queue_request_p^.wired_data_command_descript_p;
      wired_data_descriptor_index := 0;

      cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);

      data_command_descriptors_p := io_completion_table_entry_p^.data_command_descriptors_p;

      queue_entry_in_monitor := FALSE;

      IF data_command_descriptors_p <> NIL THEN
        number_data_command_descriptors := UPPERBOUND (data_command_descriptors_p^);
        PUSH pva_list_p: [1 .. 1];
        pp_request_p := ^wired_unit_queue_request_p^.request;
        command_heap_p := wired_unit_queue_request_p^.wired_command_heap_p;
        address_word_pair_count := 0;
        {
        {  Create rma lists
        {
        rma_list_index := 1;

      /process_data_descriptors/
        FOR data_command_descriptor_index := 1 TO number_data_command_descriptors DO
          data_in_wired_area := (data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_from_wired_area) OR (data_command_descriptors_p^ [data_command_descriptor_index].
                move_data_to_wired_area);
          lock_data_pages := data_command_descriptors_p^ [data_command_descriptor_index].lock_data_pages;
          data_length := data_command_descriptors_p^ [data_command_descriptor_index].length;
          address_p := data_command_descriptors_p^ [data_command_descriptor_index].address;
          command_rma_list_p := #LOC (command_heap_p^.rma_list [rma_list_index]);

          queue_entry_in_monitor := queue_entry_in_monitor OR lock_data_pages;

          IF lock_data_pages THEN
            wired_data_descriptor_index := wired_data_descriptor_index + 1;
            {
            { Reference each page to cause a load.
            {
            byte_p := address_p;
            ring := #RING (address_p);
            segment := #SEGMENT (address_p);
            offset := #OFFSET (address_p);
            first_byte_in_page_to_touch := byte_p^;

            IF (offset MOD page_size + data_length) > page_size THEN
              number_of_pages := ((offset + data_length - 1) DIV page_size) -
                    ((offset + page_size) DIV page_size);
              offset := (offset DIV page_size) * page_size;
              page_index := number_of_pages;

            /touch_full_pages/
              WHILE page_index > 0 DO
                offset := offset + page_size;
                byte_p := #ADDRESS (ring, segment, offset);
                first_byte_in_page_to_touch := byte_p^;
                page_index := page_index - 1;
              WHILEND /touch_full_pages/;
            IFEND;
            offset := #OFFSET (address_p) + data_length - 1;
            byte_p := #ADDRESS (ring, segment, offset);
            last_byte_to_touch := byte_p^;
            CYCLE /process_data_descriptors/; {----->
          IFEND;

          IF data_in_wired_area THEN
            wired_data_descriptor_index := wired_data_descriptor_index + 1;
            address_p := wired_data_descriptors_p^ [wired_data_descriptor_index].address;
          IFEND;

          command_index := data_command_descriptors_p^ [data_command_descriptor_index].command_index;
          create_indirect_rma_list := pp_request_p^.commands [command_index].flags.indirect_address;

          IF create_indirect_rma_list THEN
            offset := #OFFSET (address_p);
            command_address_word_pair_count := (((offset + data_length + (page_size * 2) - 1)) DIV
                  page_size) - ((offset + page_size) DIV page_size);
          ELSE
            command_address_word_pair_count := 1;
          IFEND;

          pva_list_p^ [1].address := address_p;
          pva_list_p^ [1].length := data_length;

          cmp$build_rma_list (pva_list_p, command_rma_list_p, command_address_word_pair_count);

          address_word_pair_count := address_word_pair_count + command_address_word_pair_count;

          IF create_indirect_rma_list THEN
            i#real_memory_address (command_rma_list_p, rma);
            command_length := command_address_word_pair_count * 8;
          ELSE
            rma := command_heap_p^.rma_list [rma_list_index].rma;
            command_length := command_heap_p^.rma_list [rma_list_index].length;
          IFEND;

          pp_request_p^.commands [command_index].length := command_length;
          pp_request_p^.commands [command_index].address := rma;

          IF data_in_wired_area THEN
            wired_data_descriptors_p^ [wired_data_descriptor_index].rma_list_index := rma_list_index;
          IFEND;

          rma_list_index := rma_list_index + command_address_word_pair_count;

        FOREND /process_data_descriptors/;

        wired_unit_queue_request_p^.address_word_pair_count := address_word_pair_count;

      IFEND;

      IF queue_entry_in_monitor THEN
        request_block_p := wired_unit_queue_request_p^.monitor_request_block_p;
        request_block_p^.request_code := syc$rc_subsystem_request;
        request_block_p^.subsystem_request_code := ioc$queue_io_request;
        request_block_p^.io_request_p := wired_unit_queue_request_p^.wired_io_request_p;

      /touch_pages/
        WHILE TRUE DO
          i#call_monitor (#LOC (request_block_p^), #SIZE (request_block_p^));
          status.normal := request_block_p^.status.normal;
          status.condition := request_block_p^.status.condition;
          IF status.normal THEN
            EXIT /touch_pages/; {----->
          IFEND;
          IF (status.condition <> mme$page_frame_not_assigned) AND
                (status.condition <> ioe$unable_to_queue_io_request) THEN
            EXIT /touch_pages/; {----->
          IFEND;

          #PURGE_BUFFER (osc$purge_all_cache, null_sva);


          number_data_command_descriptors := wired_unit_queue_request_p^.number_of_data_descriptors;

        /touch_data/
          FOR wired_data_descriptor_index := 1 TO number_data_command_descriptors DO
            data_length := wired_data_descriptors_p^ [wired_data_descriptor_index].length;
            address_p := wired_data_descriptors_p^ [wired_data_descriptor_index].address;
            IF NOT wired_data_descriptors_p^ [wired_data_descriptor_index].lock_data_pages THEN
              CYCLE /touch_data/; {----->
            IFEND;
            {
            { Reference each page to cause a load.
            {
            byte_p := address_p;
            ring := #RING (address_p);
            segment := #SEGMENT (address_p);
            offset := #OFFSET (address_p);
            first_byte_in_page_to_touch := byte_p^;

            IF (offset MOD page_size + data_length) > page_size THEN
              number_of_pages := ((offset + data_length - 1) DIV page_size) -
                    ((offset + page_size) DIV page_size);
              offset := (offset DIV page_size) * page_size;
              page_index := number_of_pages;

              WHILE page_index > 0 DO
                offset := offset + page_size;
                byte_p := #ADDRESS (ring, segment, offset);
                first_byte_in_page_to_touch := byte_p^;
                page_index := page_index - 1;
              WHILEND;
            IFEND;
            offset := #OFFSET (address_p) + data_length - 1;
            byte_p := #ADDRESS (ring, segment, offset);
            last_byte_to_touch := byte_p^;

          FOREND /touch_data/;

        WHILEND /touch_pages/;

        IF NOT status.normal THEN
          iop$set_status_abnormal (request_block_p^.status.condition, 'Bad monitor status from IOMSSRQP ',
                status);
        IFEND;

      ELSE
        unit_interface_table_p := cmv$logical_unit_table^ [wired_unit_queue_request_p^.request.logical_unit].
              unit_interface_table;

        IF unit_interface_table_p^.unit_status.disabled THEN
          iop$set_status_abnormal (ioe$unable_to_queue_io_request, 'Unit queuing disabled - IOMSSIOR113',
                status);
          EXIT /process_request/; {----->
        IFEND;

        unit_queue_lockword_p := ^unit_interface_table_p^.unit_q_lockword;
        cmp$queue_request (wired_unit_queue_request_p, wired_unit_queue_request_p^.unit_queuing_control,
              unit_queue_lockword_p, ^unit_interface_table_p^.next_request, NIL,
              ^unit_interface_table_p^.next_request_rma, status);
      IFEND;
    END /process_request/;


  PROCEND queue_unit_request;
?? TITLE := '  [XDCL, #GATE] iop$return_wired_request', EJECT ??

*copyc ioh$return_wired_request

  PROCEDURE [XDCL, #GATE] iop$return_wired_request
    (    job_io_completion_queue_index: cmt$io_completion_queue_index;
     VAR status: ost$status);

    VAR
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      wired_request_p: ^cmt$wired_unit_queue_request,
      data_command_descriptor_index: integer,
      move_data_from_wired_area: boolean,
      move_data_to_wired_area: boolean,
      data_pages_were_locked: boolean,
      wired_data_pva: ^cell,
      data_pva: ^cell,
      data_p: ^SEQ ( * ),
      wired_data_length: ost$segment_length,
      wired_data_seq_p: ^SEQ ( * ),
      number_of_data_descriptors: integer,
      wired_heap_p: ^ost$heap,
      descriptor_index: cmt$command_index,
      data_command_descriptors_p: ^cmt$data_command_descriptors,
      wired_data_command_descript_p: ^cmt$wired_data_descriptors;

  /process_request/
    BEGIN

      status.normal := TRUE;

      cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);

      wired_request_p := io_completion_table_entry_p^.wired_unit_queue_request_p;

      wired_heap_p := osv$mainframe_wired_cb_heap;
      wired_data_command_descript_p := wired_request_p^.wired_data_command_descript_p;
      number_of_data_descriptors := wired_request_p^.number_of_data_descriptors;
      data_command_descriptors_p := io_completion_table_entry_p^.data_command_descriptors_p;
      data_pages_were_locked := FALSE;


      IF (wired_data_command_descript_p <> NIL) AND (number_of_data_descriptors > 0) THEN
        FOR data_command_descriptor_index := 1 TO number_of_data_descriptors DO
          descriptor_index := wired_data_command_descript_p^ [data_command_descriptor_index].
                data_descriptor_index;
          move_data_from_wired_area := data_command_descriptors_p^ [descriptor_index].
                move_data_from_wired_area;
          move_data_to_wired_area := data_command_descriptors_p^ [descriptor_index].move_data_to_wired_area;
          IF move_data_from_wired_area OR move_data_to_wired_area THEN
            wired_data_pva := wired_data_command_descript_p^ [data_command_descriptor_index].address;
            wired_data_length := wired_data_command_descript_p^ [data_command_descriptor_index].length;
            i#build_adaptable_seq_pointer (#RING (wired_data_pva), #SEGMENT (wired_data_pva),
                  #OFFSET (wired_data_pva), wired_data_length, 0, wired_data_seq_p);
            RESET wired_data_seq_p;
          IFEND;
          IF move_data_from_wired_area THEN
            data_pva := data_command_descriptors_p^ [descriptor_index].address;

            i#build_adaptable_seq_pointer (#RING (data_pva), #SEGMENT (data_pva), #OFFSET (data_pva),
                  wired_data_length, 0, data_p);
            RESET data_p;

            data_p^ := wired_data_seq_p^;

          IFEND;

          IF move_data_to_wired_area OR move_data_from_wired_area THEN
            FREE wired_data_seq_p IN osv$mainframe_wired_cb_heap^;
          IFEND;

        FOREND;

      IFEND;

      wired_request_p^.request.next_pp_request := NIL;
      wired_request_p^.request.next_pp_request_rma := 0;
      wired_request_p^.io_identification.user_supplied := 0;
      wired_request_p^.io_identification.system_supplied := 0;
      wired_request_p^.number_of_commands := 0;
      wired_request_p^.number_of_data_descriptors := 0;
      wired_request_p^.response_area_p^ (job_io_completion_queue_index, 1) := 'N';

    END /process_request/;

  PROCEND iop$return_wired_request;

?? OLDTITLE ??

  PROCEDURE [XDCL, #GATE] cmp$unlock_the_rma_list
    (    job_io_completion_queue_index: cmt$io_completion_queue_index;
     VAR status: ost$status);

    VAR
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      wired_request_p: ^cmt$wired_unit_queue_request,
      data_index: integer,
      normal_termination: boolean,
      request_block_p: ^iot$monitor_request_block,
      address_word_pair_count: 0 .. mmc$max_rma_list_length,
      monitor_status: syt$monitor_status,
      number_of_data_descriptors: integer,
      descriptor_index: cmt$command_index,
      data_command_descriptors_p: ^cmt$data_command_descriptors,
      wired_data_command_descript_p: ^cmt$wired_data_descriptors;


    status.normal := TRUE;
    normal_termination := TRUE;

    cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);
    wired_request_p := io_completion_table_entry_p^.wired_unit_queue_request_p;

    IF wired_request_p <> NIL THEN
      number_of_data_descriptors := wired_request_p^.number_of_data_descriptors;
      IF number_of_data_descriptors = 0 THEN
        RETURN; {----->
      IFEND;
      data_command_descriptors_p := io_completion_table_entry_p^.data_command_descriptors_p;
      address_word_pair_count := wired_request_p^.address_word_pair_count;
      IF address_word_pair_count <> 0 THEN
        wired_data_command_descript_p := wired_request_p^.wired_data_command_descript_p;
        FOR data_index := 1 TO number_of_data_descriptors DO

          request_block_p := wired_request_p^.monitor_request_block_p;
          request_block_p^.request_code := syc$rc_subsystem_request;
          request_block_p^.subsystem_request_code := ioc$unlock_rma_list;
          request_block_p^.wired_request := wired_request_p;

          i#call_monitor (#LOC (request_block_p^), #SIZE (request_block_p^));
          status.normal := request_block_p^.status.normal;
          status.condition := request_block_p^.status.condition;
          IF NOT status.normal THEN
            osp$set_status_abnormal ('IO', ioe$unable_to_unlock_rma_list,
                  'Unable to unlock rma list in cleanup', status);
            RETURN; {----->
          IFEND;
        FOREND;
      IFEND;
    IFEND;


  PROCEND cmp$unlock_the_rma_list;








?? TITLE := '  [XDCL, #GATE] cmp$check_io_status', EJECT ??


  PROCEDURE [XDCL, #GATE] cmp$check_io_status
    (    request_id: cmt$subsystem_io_request_id;
     VAR status: ost$status);

    VAR
      element_name: cmt$element_name,
      job_io_completion_queue_index: cmt$io_completion_queue_index,
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      logical_pp_number: iot$pp_number;



    status.normal := TRUE;

    job_io_completion_queue_index := request_id.system_supplied;

    cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);

    element_name := io_completion_table_entry_p^.io_request_type.element_name;

{ Check if PP is loaded.

    cmp$get_logical_pp_number (element_name, logical_pp_number, status);

  PROCEND cmp$check_io_status;

?? TITLE := '  [XDCL, #GATE] iop$clear_response_p', EJECT ??


  PROCEDURE [XDCL, #GATE] iop$clear_response_ptr
    (    job_io_completion_queue_index: cmt$io_completion_queue_index;
     VAR status: ost$status);

    VAR
      io_completion_table_entry_p: ^cmt$io_completion_table_entry,
      wired_request_p: ^cmt$wired_unit_queue_request,
      wired_heap_p: ^ost$heap;

    status.normal := TRUE;

    cmp$get_io_completion_tbl_entry (job_io_completion_queue_index, io_completion_table_entry_p);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;
    IF io_completion_table_entry_p^.available THEN
{  Entry not in use.
      RETURN; {----->
    IFEND;

    wired_request_p := io_completion_table_entry_p^.wired_unit_queue_request_p;
    wired_request_p^.response_area_p^ (job_io_completion_queue_index, 1) := 'N';

  PROCEND iop$clear_response_ptr;

  PROCEDURE [XDCL, #GATE] iop$get_in_out_ptrs
    (    pp: iot$pp_number;
     VAR inn: iot$response_buffer_offset;
     VAR out: iot$response_buffer_offset);


    VAR
      ppit: ^iot$pp_interface_table;


    ppit := cmv$logical_pp_table_p^ [pp].pp_info.pp_interface_table_p;
    inn := ppit^.inn;
    out := ppit^.out;

  PROCEND iop$get_in_out_ptrs;

MODEND iom$subsystem_io_r113;
