?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Tape Management: Manage Mainframe Tape Tables', EJECT ??
MODULE iom$manage_rvl_tusl_structures;

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmt$element_states
*copyc cmv$logical_unit_table
*copyc dme$tape_errors
*copyc dmt$global_file_name
*copyc iot$density_states
*copyc iot$new_vsns_online
*copyc iot$requested_volume_attributes
*copyc iot$requested_vsn_list_entry
*copyc iot$robotic_server_entry
*copyc iot$robotic_server_index
*copyc iot$rvl_entry_information
*copyc iot$set_assignment_results
*copyc iot$tape_unit_status_list
*copyc iot$tusl_ordinal
*copyc iot$tusl_entry_access
*copyc osd$integer_limits
*copyc oss$mainframe_pageable
*copyc oss$mainframe_paged_literal
*copyc ost$name
*copyc rmc$unspecified_vsn
*copyc rme$condition_codes
*copyc rmt$rbt_server_attribute
*copyc rmt$volume_list
*copyc rmt$write_ring
?? POP ??

*copyc clp$construct_path_handle_name
*copyc cmp$get_element_name_via_lun
*copyc cmp$get_element_state
*copyc cmp$get_logical_unit_number
*copyc cmp$lock_lun_entry
*copyc cmp$unlock_lun_entry
*copyc gfv$null_sfid
*copyc iop$determine_density_support
*copyc iov$tusl_lock
*copyc iov$tusl_p
*copyc jmp$find_jsn
*copyc jmv$jcb
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$clear_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$test_set_main_sig_lock
*copyc osp$test_sig_lock
*copyc osv$mainframe_pageable_heap
*copyc pmp$get_executing_task_gtid
*copyc pmp$get_time
*copyc pmp$ready_task
*copyc tmv$null_global_task_id

?? OLDTITLE ??
?? NEWTITLE := 'Global Variables Declared by This Module', EJECT ??

  CONST
    include_radix = TRUE,
    radix = 10;

  VAR
    iov$backward_rvl_p: [XDCL, oss$mainframe_pageable] ^iot$requested_vsn_list_entry := NIL,
    iov$forward_rvl_p: [XDCL, oss$mainframe_pageable] ^iot$requested_vsn_list_entry := NIL,
    iov$last_robotic_tusl_ordinal: [XDCL, oss$mainframe_pageable] iot$tusl_ordinal := 1,
    iov$robotic_request_id: [XDCL, oss$mainframe_pageable] rmt$rbt_request_id := 0,
    iov$robotic_server_array_p: [XDCL, oss$mainframe_pageable] ^array [ 1 .. * ]
          OF iot$robotic_server_entry := NIL,
    iov$rvl_lock: [XDCL, oss$mainframe_pageable] ost$signature_lock := [0];

  VAR
    rvl_entry_template: [READ, oss$mainframe_paged_literal] iot$requested_vsn_list_entry := [
          {ssn} osc$null_name,
          {sfid} [0, gfc$tr_null_residence, gfc$null_file_hash],
          {path_handle_name} osc$null_name,
          {global_file_name} [
            {serial_number} 0,
            {model_number} 0,
            {year} 1980,
            {month} 1,
            {day} 1,
            {hour} 0,
            {minute} 0,
            {second} 0,
            {sequence_number} 0,
            {fill} 0],
          {forward_link} NIL,
          {backward_link} NIL,
          {vsn_state} ioc$unassigned,
          {gtid} [0, 0],
          {assigned_element_name} osc$null_name,
          {assignment_terminated} FALSE,
          {recovery_assignment} FALSE,
          {message} '',
          {time_of_mount_request} '',
          {operator_assignment_type} ioc$unknown_assignment_type,
          {next_in_vsn_queue} NIL,
          {previous_in_vsn_queue} NIL,
          {current_vsn_p} NIL,
          {first_vsn_entry_p} NIL,
          {last_vsn_entry_p} NIL,
          {requested_tape_characteristics} [
            {label_type} amc$labelled,
            {character_set} amc$ascii,
            {write_ring} FALSE,
            {density} rmc$6250],
          {requested_volume_attributes } [
            {account } osc$null_name,
            {family } osc$null_name,
            {project } osc$null_name,
            {removable_media_group } osc$null_name,
            {removable_media_location } osc$null_name,
            {slot: } osc$null_name,
            {user:  } osc$null_name],
          {robotic_communication} NIL];

?? OLDTITLE ??
?? NEWTITLE := 'Pictorial Overview of the RVL.', EJECT ??
{
{
{                                      PICTORIAL REPRESENTATION OF RVL
{
{
{
{
{ iov$backward_rvl_p ________________________________________________________
{ iov$forward_rvl_p ___                                                      |
{                      |   ____________________________________________      |
{  ____________________|  |                                            |     |
{ |                       |                           _________________|_____|_________________________
{ |                       |                          |                 |     |                         |
{ |    ___________________V____          ____________V___________      |    _V______________________   |
{ --->|REQUESTED_VSN_LIST_ENTRY|  ----->|REQUESTED_VSN_LIST_ENTRY|  ---|-->|REQUESTED_VSN_LIST_ENTRY|  |
{     |------------------------|  |     |------------------------|  |  |   |------------------------|  |
{     |forward_link            |__|     |forward_link            |__|  |   |forward_link      = NIL |  |
{     |backward_link     = NIL |        |backward_link           |_____|   |backward_link           |__|
{     |      .                 |        |      .                 |         |      .                 |
{     |      .                 |        |      .                 |         |      .                 |
{     |first_vsn_entry_p       |____    |first_vsn_entry_p       |____     |first_vsn_entry_p       |____
{     |last_vsn_entry_p        |__  |   |last_vsn_entry_p        |__  |    |last_vsn_entry_p        |__  |
{     |________________________|  | |   |________________________|  | |    |________________________|  | |
{  _______________________________| |    ___________________________| |  ______________________________| |
{ |    _____________________________|   |  ___________________________| |   _____________________________|
{ |   |  ____________________________   | |                             |  |   ______________________________
{ |   | |                            |  | |                             |  |  |                              |
{ |   V_V______________________      |  V_V______________________       |  V__V_____________________         |
{ |   |       VSN_ENTRY        |     |  |       VSN_ENTRY        |      |  |       VSN_ENTRY        |        |
{ |   |------------------------|     |  |------------------------|      |  |------------------------|        |
{ |   |next_vsn_p              |__   |  |next_vsn_p        =NIL  |      |  |next_vsn_p              |__      |
{ |   |previous_vsn_p    =NIL  |  |  |  |previous_vsn_p    =NIL  |      |  |previous_vsn_p    =NIL  |  |     |
{ |   |________________________|  |  |  |________________________|      |  |________________________|  |     |
{ |                               |  |                                  |   ___________________________|     |
{ |    ___________________________|  |                                  |  |   ___________________________   |
{ |   |                              |                                  |  |  |                           |  |
{ |   V________________________      |                                  |  V__V_____________________      |  |
{ --->|       VSN_ENTRY        |     |                                  |  |       VSN_ENTRY        |     |  |
{     |------------------------|     |                                  |  |------------------------|     |  |
{     |next_vsn_p        =NIL  |     |                                  |  |next_vsn_p              |__   |  |
{     |previous_vsn_p          |_____|                                  |  |previous_vsn_p          |__|__|__|
{     |________________________|                                        |  |________________________|  |  |
{                                                                       |   ___________________________|  |
{                                                                       |  |                              |
{                                                                       |  |                              |
{                                                                       |  V________________________      |
{                                                                       -->|       VSN_ENTRY        |     |
{                                                                          |------------------------|     |
{                                                                          |next_vsn_p        =NIL  |     |
{                                                                          |previous_vsn_p          |_____|
{                                                                          |________________________|
{
{
{

?? OLDTITLE ??
?? NEWTITLE := 'clear_mainframe_sig_lock', EJECT ??

  PROCEDURE clear_mainframe_sig_lock
    (VAR lock: ost$signature_lock);

    VAR
      lock_status: ost$signature_lock_status,
      locked: boolean;

      osp$test_sig_lock (lock, lock_status);
      IF lock_status = osc$sls_locked_by_current_task THEN
        osp$clear_mainframe_sig_lock  (lock);
      IFEND;

  PROCEND clear_mainframe_sig_lock;

?? OLDTITLE ??
?? NEWTITLE := 'delete_rvl_entry', EJECT ??

  PROCEDURE delete_rvl_entry
    (    path_handle: fmt$path_handle;
     VAR status: ost$status);

    VAR
      local_path_handle: fmt$path_handle,
      path_handle_name: fst$path_handle_name,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_entry_found: boolean,
      tusl_ordinal: iot$tusl_ordinal,
      unit_type: iot$unit_type,
      vsn_p: ^iot$vsn_entry;

    status.normal := TRUE;

    local_path_handle := path_handle;
    local_path_handle.open_position.specified := FALSE;
    clp$construct_path_handle_name (local_path_handle, path_handle_name);

  /rvl_search/
    BEGIN
      rvl_p := iov$forward_rvl_p;
      WHILE rvl_p <> NIL DO
        IF (rvl_p^.ssn = jmv$jcb.system_name) AND (rvl_p^.path_handle_name = path_handle_name) THEN
          EXIT /rvl_search/;
        IFEND;
        rvl_p := rvl_p^.forward_link;
      WHILEND;
      osp$set_status_abnormal (rmc$resource_management_id, rme$cant_find_rvl_entry, 'delete_rvl_entry',
            status);
      RETURN;
    END /rvl_search/;

    WHILE rvl_p^.first_vsn_entry_p <> NIL DO
      vsn_p := rvl_p^.last_vsn_entry_p;
      IF rvl_p^.first_vsn_entry_p = rvl_p^.last_vsn_entry_p THEN
        rvl_p^.first_vsn_entry_p := NIL;
        rvl_p^.last_vsn_entry_p := NIL;
      ELSE
        rvl_p^.last_vsn_entry_p := rvl_p^.last_vsn_entry_p^.previous_vsn_p;
        rvl_p^.last_vsn_entry_p^.next_vsn_p := NIL;
      IFEND;
      FREE vsn_p IN osv$mainframe_pageable_heap^;
    WHILEND;

    IF iov$forward_rvl_p = iov$backward_rvl_p THEN
      iov$forward_rvl_p := NIL;
      iov$backward_rvl_p := NIL;
    ELSEIF iov$forward_rvl_p = rvl_p THEN
      iov$forward_rvl_p := rvl_p^.forward_link;
      iov$forward_rvl_p^.backward_link := NIL;
    ELSEIF iov$backward_rvl_p = rvl_p THEN
      iov$backward_rvl_p := rvl_p^.backward_link;
      iov$backward_rvl_p^.forward_link := NIL;
    ELSE
      rvl_p^.backward_link^.forward_link := rvl_p^.forward_link;
      rvl_p^.forward_link^.backward_link := rvl_p^.backward_link;
    IFEND;

    FREE rvl_p IN osv$mainframe_pageable_heap^;

  PROCEND delete_rvl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'delete_rvl_entry_from_vsn_queue ', EJECT ??

  PROCEDURE delete_rvl_entry_from_vsn_queue
    (    rvl_p: ^iot$requested_vsn_list_entry);

    VAR
      current_time: ost$time,
      ignore_status: ost$status;;

      IF rvl_p^.next_in_vsn_queue = NIL THEN
        IF rvl_p^.previous_in_vsn_queue <> NIL THEN
          rvl_p^.previous_in_vsn_queue^.next_in_vsn_queue := NIL;
          rvl_p^.previous_in_vsn_queue := NIL;
        IFEND;
      ELSE
        IF rvl_p^.previous_in_vsn_queue = NIL THEN
          rvl_p^.next_in_vsn_queue^.previous_in_vsn_queue := NIL;
          IF rvl_p^.next_in_vsn_queue^.gtid <> tmv$null_global_task_id THEN
            pmp$ready_task (rvl_p^.next_in_vsn_queue^.gtid, ignore_status);
          IFEND;
          rvl_p^.next_in_vsn_queue := NIL;
        ELSE
          rvl_p^.next_in_vsn_queue^.previous_in_vsn_queue := rvl_p^.previous_in_vsn_queue;
          rvl_p^.previous_in_vsn_queue^.next_in_vsn_queue := rvl_p^.next_in_vsn_queue;
          rvl_p^.next_in_vsn_queue := NIL;
          rvl_p^.previous_in_vsn_queue := NIL;
        IFEND;
      IFEND;

  PROCEND delete_rvl_entry_from_vsn_queue;

?? OLDTITLE ??
?? NEWTITLE := 'locate_element_in_tusl', EJECT ??

  PROCEDURE locate_element_in_tusl
    (    element_name: cmt$element_name;
     VAR tusl_ordinal: iot$tusl_ordinal;
     VAR status: ost$status);

    VAR
      local_tusl_ordinal: iot$tusl_ordinal;

    status.normal := TRUE;

    FOR local_tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
      IF iov$tusl_p^ [local_tusl_ordinal].element_name = element_name THEN
        tusl_ordinal := local_tusl_ordinal;
        RETURN;
      IFEND;
    FOREND;

    osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_undefined, element_name,
          status);

  PROCEND locate_element_in_tusl;

?? OLDTITLE ??
?? NEWTITLE := 'locate_first_queued_rvl_p ', EJECT ??

  PROCEDURE locate_first_queued_rvl_p
    (    requested_density: rmt$density;
         requested_evsn: rmt$external_vsn;
         requested_rvsn: rmt$recorded_vsn;
     VAR first_queued_rvl_p: ^iot$requested_vsn_list_entry);

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    first_queued_rvl_p := NIL;
    rvl_p := iov$forward_rvl_p;
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.requested_tape_characteristics.density = requested_density) AND
            (rvl_p^.current_vsn_p <> NIL) AND
            (rvl_p^.current_vsn_p^.rvsn = requested_rvsn) AND
            (rvl_p^.current_vsn_p^.evsn = requested_evsn) AND
            (rvl_p^.vsn_state >= ioc$queued_for_assignment) THEN
        WHILE rvl_p^.previous_in_vsn_queue <> NIL DO
          rvl_p := rvl_p^.previous_in_vsn_queue;
        WHILEND;
        first_queued_rvl_p := rvl_p;
        RETURN;
      ELSE
        rvl_p := rvl_p^.forward_link;
      IFEND;
    WHILEND;
  PROCEND locate_first_queued_rvl_p;

?? OLDTITLE ??
?? NEWTITLE := 'locate_new_request_in_rvl', EJECT ??

  PROCEDURE locate_new_request_in_rvl
    (VAR rvl_p: ^iot$requested_vsn_list_entry;
     VAR status: ost$status);

    status.normal := TRUE;
    rvl_p := iov$forward_rvl_p;

  /locate_new_client_request/
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.robotic_communication <> NIL) AND
            NOT rvl_p^.robotic_communication^.server_received_request THEN
        EXIT /locate_new_client_request/;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND /locate_new_client_request/;

    IF rvl_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$no_requests_available,
            'LOCATE_NEW_REQUEST_IN_RVL', status);
    IFEND;

  PROCEND locate_new_request_in_rvl;

?? OLDTITLE ??
?? NEWTITLE := 'locate_request_id_in_rvl', EJECT ??

  PROCEDURE locate_request_id_in_rvl
    (    request_id: rmt$rbt_request_id;
     VAR rvl_p: ^iot$requested_vsn_list_entry;
     VAR status: ost$status);

    status.normal := TRUE;
    rvl_p := iov$forward_rvl_p;

  /locate_request_id/
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.robotic_communication <> NIL) AND
            (rvl_p^.robotic_communication^.client_request.request_id = request_id) THEN
        EXIT /locate_request_id/;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND /locate_request_id/;

    IF rvl_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$request_not_found, 'LOCATE_REQUEST_ID_IN_RVL',
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, request_id, radix, NOT include_radix,
            status);
    IFEND;

  PROCEND locate_request_id_in_rvl;

?? OLDTITLE ??
?? NEWTITLE := 'locate_robotic_server_entry', EJECT ??

  PROCEDURE locate_robotic_server_entry
    (    server_name: ost$name;
     VAR p_robotic_server_entry: ^iot$robotic_server_entry;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      ijl_ordinal: jmt$ijl_ordinal,
      ijle_p: ^jmt$initiated_job_list_entry,
      robotic_server_index: ost$positive_integers;

    status.normal := TRUE;
    p_robotic_server_entry := NIL;

    IF iov$robotic_server_array_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$server_not_defined,
            'LOCATE_ROBOTIC_SERVER_ENTRY', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
      RETURN;
    IFEND;

    FOR robotic_server_index := LOWERBOUND (iov$robotic_server_array_p^)
          TO UPPERBOUND (iov$robotic_server_array_p^) DO
      IF iov$robotic_server_array_p^ [robotic_server_index].server_name = server_name THEN
        p_robotic_server_entry := ^iov$robotic_server_array_p^ [robotic_server_index];
        jmp$find_jsn (iov$robotic_server_array_p^ [robotic_server_index].server_job_name, ijle_p,
              ijl_ordinal);
        IF ijle_p = NIL THEN
          remove_robotic_server_entry (p_robotic_server_entry, ignore_status);
          osp$set_status_abnormal (rmc$resource_management_id, rme$server_not_defined,
                'LOCATE_ROBOTIC_SERVER_ENTRY', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
        IFEND;
        RETURN;
      IFEND;
    FOREND;

    osp$set_status_abnormal (rmc$resource_management_id, rme$server_not_defined,
          'LOCATE_ROBOTIC_SERVER_ENTRY', status);
    osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);

  PROCEND locate_robotic_server_entry;

?? OLDTITLE ??
?? NEWTITLE := 'locate_rvl_entry_by_sfid', EJECT ??

  PROCEDURE locate_rvl_entry_by_sfid
    (    sfid: gft$system_file_identifier;
         ssn: jmt$system_supplied_name;
     VAR rvl_p: ^iot$requested_vsn_list_entry;
     VAR status: ost$status);

    VAR
      sfid_string: string (13),
      sfid_string_length: integer;

    status.normal := TRUE;
    rvl_p := iov$forward_rvl_p;

    WHILE rvl_p <> NIL DO
      IF (rvl_p^.ssn = ssn) AND (rvl_p^.sfid = sfid) THEN
        RETURN;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND;

    IF rvl_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$sfid_not_found,
            'LOCATE_RVL_ENTRY_BY_SFID', status);
      STRINGREP (sfid_string, sfid_string_length, '[', sfid.file_entry_index, ',', sfid.residence, ',',
            sfid.file_hash, ']');
      osp$append_status_parameter (osc$status_parameter_delimiter, sfid_string, status);
    IFEND;

  PROCEND locate_rvl_entry_by_sfid;

?? OLDTITLE ??
?? NEWTITLE := 'locate_volume_in_rvl_entry', EJECT ??

  PROCEDURE locate_volume_in_rvl_entry
    (    rvl_p: ^iot$requested_vsn_list_entry;
         requested_density: rmt$density;
         requested_evsn: rmt$external_vsn;
         requested_rvsn: rmt$recorded_vsn;
     VAR volume_p: ^iot$vsn_entry;
     VAR status: ost$status);

    status.normal := TRUE;
    volume_p := rvl_p^.first_vsn_entry_p;
    IF (rvl_p^.requested_tape_characteristics.density = requested_density) THEN
      WHILE volume_p <> NIL DO
        IF (volume_p^.rvsn = requested_rvsn) AND (volume_p^.evsn = requested_evsn) THEN
          RETURN;
        IFEND;
        volume_p := volume_p^.next_vsn_p;
      WHILEND;
    IFEND;
    osp$set_status_abnormal (rmc$resource_management_id, rme$cant_find_specified_vsn,
          'LOCATE_RVL_ENTRY_BY_VOLUME', status);

  PROCEND locate_volume_in_rvl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'remove_robotic_server_entry', EJECT ??

  PROCEDURE remove_robotic_server_entry
    (    p_robotic_server_entry: ^iot$robotic_server_entry;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      new_robotic_server_array_p: ^array [1 .. * ] of iot$robotic_server_entry,
      new_robotic_server_index: ost$positive_integers,
      old_robotic_server_index: ost$positive_integers,
      rvl_p: ^iot$requested_vsn_list_entry;

    IF p_robotic_server_entry^.managed_elements_p <> NIL THEN
      FREE p_robotic_server_entry^.managed_elements_p IN osv$mainframe_pageable_heap^;
    IFEND;

    IF UPPERBOUND (iov$robotic_server_array_p^) = 1 THEN
      new_robotic_server_array_p := NIL;
    ELSE
      ALLOCATE new_robotic_server_array_p: [1 .. (UPPERBOUND (iov$robotic_server_array_p^) - 1)] IN
            osv$mainframe_pageable_heap^;
      new_robotic_server_index := 1;
      FOR old_robotic_server_index := 1 TO UPPERBOUND (iov$robotic_server_array_p^) DO
        IF iov$robotic_server_array_p^ [old_robotic_server_index].server_name <>
              p_robotic_server_entry^.server_name THEN
          new_robotic_server_array_p^ [new_robotic_server_index] :=
                iov$robotic_server_array_p^ [old_robotic_server_index];
          new_robotic_server_index := new_robotic_server_index + 1;
        IFEND;
      FOREND;
    IFEND;

    rvl_p := iov$forward_rvl_p;
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.robotic_communication <> NIL) AND (rvl_p^.gtid <> tmv$null_global_task_id) AND
            (rvl_p^.robotic_communication^.server_name = p_robotic_server_entry^.server_name) THEN
        pmp$ready_task (rvl_p^.gtid, ignore_status);
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND;

    FREE iov$robotic_server_array_p IN osv$mainframe_pageable_heap^;

    iov$robotic_server_array_p := new_robotic_server_array_p;

  PROCEND remove_robotic_server_entry;

?? OLDTITLE ??
?? NEWTITLE := 'set_mainframe_sig_lock', EJECT ??

  PROCEDURE set_mainframe_sig_lock
    (    lock_string: string ( * <= osc$max_string_size);
     VAR lock: ost$signature_lock;
     VAR status: ost$status);

    VAR
      local_status: ost$status,
      lock_status: ost$signature_lock_status,
      locked: boolean;

      status.normal := TRUE;

      osp$test_sig_lock (lock, lock_status);
      IF lock_status = osc$sls_locked_by_current_task THEN
        clear_mainframe_sig_lock  (lock);
      ELSEIF lock_status = osc$sls_locked_by_another_task THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_lock_tape_table, lock_string,
              status);
      IFEND;

      IF status.normal THEN
        osp$test_set_main_sig_lock (lock, locked);
        IF NOT locked THEN
          osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_lock_tape_table, lock_string,
                status);
        IFEND;
      IFEND;

  PROCEND set_mainframe_sig_lock;

?? OLDTITLE ??
?? NEWTITLE := 'validate_candidate_element', EJECT ??

  PROCEDURE validate_candidate_element
    (    candidate_element: cmt$element_name;
         acceptable_states: set of cmt$element_state;
     VAR status: ost$status);

    VAR
      element_state: cmt$element_state,
      tusl_ordinal: iot$tusl_ordinal;

    status.normal := TRUE;

  /validate_candidate_state/
    BEGIN

      cmp$get_element_state (candidate_element, {iou_name} osc$null_name, element_state, status);
      IF NOT status.normal THEN
        EXIT /validate_candidate_state/;
      IFEND;

      IF NOT (element_state IN acceptable_states) THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
              'VALIDATE_CANDIDATE_ELEMENT', status);
        EXIT /validate_candidate_state/;
      IFEND;

      FOR tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
        IF (iov$tusl_p^ [tusl_ordinal].element_name = candidate_element) THEN
          IF (iov$tusl_p^ [tusl_ordinal].assignment_state = ioc$not_assigned) AND
             (iov$tusl_p^ [tusl_ordinal].tape_unit_state = cmc$on) THEN
            EXIT /validate_candidate_state/;
          ELSE
            osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
              'VALIDATE_CANDIDATE_ELEMENT', status);
            EXIT /validate_candidate_state/;
          IFEND;
        IFEND;
      FOREND;

      osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
            'VALIDATE_CANDIDATE_ELEMENT', status);

    END /validate_candidate_state/;

  PROCEND validate_candidate_element;

?? OLDTITLE ??
?? NEWTITLE := 'iop$access_tusl_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$access_tusl_entry
    (    tusl_ordinal: iot$tusl_ordinal;
     VAR tusl_entry_access: iot$tusl_entry_access;
     VAR status: ost$status);

    VAR
      global_task_id: ost$global_task_id,
      ignore_status: ost$status;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('TUSL_ENTRY_LOCK', iov$tusl_p^ [tusl_ordinal].lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$tusl_lock);
      RETURN;
    IFEND;

    CASE tusl_entry_access.operation OF

      = ioc$disable_operator_reassign =
        iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_allowed := FALSE;

      = ioc$enable_operator_reassign =
        pmp$get_executing_task_gtid (global_task_id);
        iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_allowed := TRUE;
        iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_entered := FALSE;
        iov$tusl_p^ [tusl_ordinal].reassign_device_control.global_task_id:= global_task_id;

      = ioc$fetch_operator_reassign =
        tusl_entry_access.fetch_operator_reassign :=
              iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_entered;

      = ioc$set_operator_reassign =
        IF iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_allowed THEN
          IF (iov$tusl_p^ [tusl_ordinal].assignment_state = ioc$manually_assigned) OR
                (iov$tusl_p^ [tusl_ordinal].assignment_state = ioc$automatically_assigned) THEN
            iov$tusl_p^ [tusl_ordinal].reassign_device_control.command_entered := TRUE;
            pmp$ready_task (iov$tusl_p^ [tusl_ordinal].reassign_device_control.global_task_id, ignore_status);
          ELSE
            osp$set_status_abnormal (rmc$resource_management_id, rme$element_name_not_assigned,
                  iov$tusl_p^ [tusl_ordinal].element_name, status);
          IFEND;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, rme$reassign_not_allowed,
                iov$tusl_p^ [tusl_ordinal].element_name, status);
        IFEND;

      = ioc$store_tape_characteristics =
        iov$tusl_p^ [tusl_ordinal].detected_tape_characteristics.write_ring :=
              tusl_entry_access.store_write_ring;
        iov$tusl_p^ [tusl_ordinal].detected_tape_characteristics.density :=
              tusl_entry_access.store_density;

      = ioc$store_unit_ready =
        iov$tusl_p^ [tusl_ordinal].unit_ready := tusl_entry_access.store_unit_ready;
      ELSE
    CASEND;

    clear_mainframe_sig_lock (iov$tusl_p^ [tusl_ordinal].lock);
    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$access_tusl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'iop$any_task_waiting_assignment', EJECT ??

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

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    tasks_are_waiting := FALSE;

  /search_rvl/
    BEGIN
      rvl_p := iov$forward_rvl_p;
      WHILE rvl_p <> NIL DO
        IF (rvl_p^.vsn_state = ioc$ready_for_assignment) AND
              (rvl_p^.operator_assignment_type = ioc$expecting_auto_assignment) THEN
          tasks_are_waiting := TRUE;
          EXIT /search_rvl/
        IFEND;
        rvl_p := rvl_p^.forward_link;
      WHILEND;
    END /search_rvl/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$any_task_waiting_assignment;

?? OLDTITLE ??
?? NEWTITLE := 'iop$assign_tape_unit', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$assign_tape_unit
    (    sfid: gft$system_file_identifier;
         element_name: cmt$element_name;
         acceptable_states: cmt$element_states;
         label_type: amt$label_type;
     VAR logical_unit: iot$logical_unit;
     VAR status: ost$status);

    VAR
      entry_locked: boolean,
      entry_unlocked: boolean,
      ijl_ordinal: jmt$ijl_ordinal,
      ijle_p: ^jmt$initiated_job_list_entry,
      multiple_volumes_with_same_vsn: boolean,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_ordinal: iot$tusl_ordinal;

    entry_locked := FALSE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$rvl_lock);
      RETURN;
    IFEND;

  /assign_tape_unit/
    BEGIN
      IF sfid <> gfv$null_sfid THEN
        locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
        IF NOT status.normal THEN
          EXIT /assign_tape_unit/;
        IFEND;

        locate_element_in_tusl (element_name, tusl_ordinal, status);
        IF NOT status.normal THEN
          EXIT /assign_tape_unit/;
        IFEND;
      IFEND;

      cmp$get_logical_unit_number (element_name, logical_unit, status);
      IF NOT status.normal THEN
        EXIT /assign_tape_unit/;
      IFEND;

      cmp$lock_lun_entry (logical_unit, entry_locked);
      IF NOT entry_locked THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_lock_tape_table,
              'MAINFRAME LUN ENTRY', status);
        EXIT /assign_tape_unit/;
      IFEND;

      IF NOT (cmv$logical_unit_table^ [logical_unit].configured AND
            cmv$logical_unit_table^ [logical_unit].status.assignable_device) THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_undefined, '', status);
        EXIT /assign_tape_unit/;
      IFEND;

      IF cmv$logical_unit_table^ [logical_unit].element_capability = $cmt$element_capabilities [] THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_off, element_name, status);
        EXIT /assign_tape_unit/;
      IFEND;

      IF (cmc$volume_assignment IN cmv$logical_unit_table^ [logical_unit].element_capability) AND
            (acceptable_states * $cmt$element_states [cmc$on] = $cmt$element_states []) THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
              'IOP$ASSIGN_TAPE_UNIT', status);
        EXIT /assign_tape_unit/;
      IFEND;

      IF (cmv$logical_unit_table^ [logical_unit].element_capability =
            $cmt$element_capabilities [cmc$concurrent_maintenance,
            cmc$dedicated_maintenance]) AND (acceptable_states * $cmt$element_states [cmc$down] =
            $cmt$element_states []) THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_down, element_name, status);
        EXIT /assign_tape_unit/;
      IFEND;

      IF cmv$logical_unit_table^ [logical_unit].status.assigned THEN
        jmp$find_jsn (cmv$logical_unit_table^ [logical_unit].status.assigned_jsn, ijle_p, ijl_ordinal);
        IF ijle_p <> NIL THEN
          osp$set_status_abnormal (rmc$resource_management_id, dme$unit_assigned, element_name, status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                cmv$logical_unit_table^ [logical_unit].status.assigned_jsn, status);
          EXIT /assign_tape_unit/;
        IFEND;
      IFEND;

      IF sfid <> gfv$null_sfid THEN
        IF rvl_p^.current_vsn_p = NIL THEN
          osp$set_status_abnormal (rmc$resource_management_id, dme$no_vsn_selected,
                'IOP$ASSIGN_TAPE_UNIT', status);
          EXIT /assign_tape_unit/;
        IFEND;
        rvl_p^.vsn_state := ioc$assigned;
        rvl_p^.assigned_element_name := element_name;
        rvl_p^.assignment_terminated := FALSE;

        IF label_type = amc$labelled THEN
          rvl_p^.requested_tape_characteristics.label_type := amc$labelled;
        ELSE
          rvl_p^.requested_tape_characteristics.label_type := amc$unlabelled;
        IFEND;

        iov$tusl_p^ [tusl_ordinal].sfid := rvl_p^.sfid;
        iov$tusl_p^ [tusl_ordinal].assignment_state := ioc$automatically_assigned;
        iov$tusl_p^ [tusl_ordinal].ssn := rvl_p^.ssn;
        iov$tusl_p^ [tusl_ordinal].evsn := rvl_p^.current_vsn_p^.evsn;
        iov$tusl_p^ [tusl_ordinal].rvsn := rvl_p^.current_vsn_p^.rvsn;
        iov$tusl_p^ [tusl_ordinal].path_handle_name := rvl_p^.path_handle_name;
      IFEND;

      cmv$logical_unit_table^ [logical_unit].status.assigned := TRUE;
      cmv$logical_unit_table^ [logical_unit].status.assigned_jsn := jmv$jcb.system_name;

    END /assign_tape_unit/;

    IF entry_locked THEN
      cmp$unlock_lun_entry (logical_unit, entry_unlocked);
      IF status.normal AND (NOT entry_unlocked) THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_release_lun_lock,
              'Unable to release lun entry in IOP$ASSIGN_TAPE_UNIT', status);
      IFEND;
    IFEND;

    clear_mainframe_sig_lock (iov$tusl_lock);
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$assign_tape_unit;

?? OLDTITLE ??
?? NEWTITLE := 'iop$client_cancel_request', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$client_cancel_request
    (    server_name: ost$name;
         sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      sfid_string: string (13),
      sfid_string_length: integer;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /client_cancel_request/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /client_cancel_request/;
      IFEND;

      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /client_cancel_request/;
      IFEND;

      IF rvl_p^.robotic_communication = NIL THEN
        EXIT /client_cancel_request/;
      IFEND;

      IF NOT (rvl_p^.ssn = jmv$jcb.system_name) AND (rvl_p^.robotic_communication^.server_name = server_name)
            THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$sfid_not_found, 'LOCATE_SFID_IN_RVL',
              status);
        STRINGREP (sfid_string, sfid_string_length, '[', sfid.file_entry_index, ',', sfid.residence, ',',
              sfid.file_hash, ']');
        osp$append_status_parameter (osc$status_parameter_delimiter, sfid_string, status);
        EXIT /client_cancel_request/;
      IFEND;

      IF rvl_p^.robotic_communication^.server_received_request AND
            rvl_p^.robotic_communication^.server_response_received THEN
        IF rvl_p^.robotic_communication^.server_response.request_processed AND
              (rvl_p^.robotic_communication^.server_response.processed_request = rmc$rbt_query) AND
              rvl_p^.robotic_communication^.server_response.query.volume_located AND
              NOT rvl_p^.robotic_communication^.server_response.query.already_mounted THEN

          IF rvl_p^.robotic_communication^.server_response.query.preferred_candidates <> NIL THEN
            FREE rvl_p^.robotic_communication^.server_response.query.preferred_candidates IN
                  osv$mainframe_pageable_heap^;
          IFEND;

          IF rvl_p^.robotic_communication^.server_response.query.remaining_candidates <> NIL THEN
            FREE rvl_p^.robotic_communication^.server_response.query.remaining_candidates IN
                  osv$mainframe_pageable_heap^;
          IFEND;
        IFEND;

        IF NOT rvl_p^.robotic_communication^.server_response.request_processed AND
              (rvl_p^.robotic_communication^.server_response.server_messages <> NIL) THEN
          FREE rvl_p^.robotic_communication^.server_response.server_messages IN osv$mainframe_pageable_heap^
        IFEND;
      IFEND;

      FREE rvl_p^.robotic_communication IN osv$mainframe_pageable_heap^;
    END /client_cancel_request/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$client_cancel_request;

?? OLDTITLE ??
?? NEWTITLE := 'iop$client_delete_request', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$client_delete_request
    (    server_name: ost$name;
         request_id: rmt$rbt_request_id;
     VAR status: ost$status);

    VAR
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /client_delete_request/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /client_delete_request/;
      IFEND;

      locate_request_id_in_rvl (request_id, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /client_delete_request/;
      IFEND;

      IF NOT ((rvl_p^.ssn = jmv$jcb.system_name) AND (rvl_p^.robotic_communication^.server_name =
            server_name) AND rvl_p^.robotic_communication^.server_received_request AND
            rvl_p^.robotic_communication^.server_response_received) THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$request_not_found,
              'IOP$CLIENT_DELETE_REQUEST', status);
        osp$append_status_integer (osc$status_parameter_delimiter, request_id, radix, NOT include_radix,
              status);
        EXIT /client_delete_request/;
      IFEND;

      IF rvl_p^.robotic_communication^.server_received_request AND
            rvl_p^.robotic_communication^.server_response_received THEN
        IF rvl_p^.robotic_communication^.server_response.request_processed AND
              (rvl_p^.robotic_communication^.server_response.processed_request = rmc$rbt_query) AND
              rvl_p^.robotic_communication^.server_response.query.volume_located AND
              NOT rvl_p^.robotic_communication^.server_response.query.already_mounted THEN

          IF rvl_p^.robotic_communication^.server_response.query.preferred_candidates <> NIL THEN
            FREE rvl_p^.robotic_communication^.server_response.query.preferred_candidates IN
                  osv$mainframe_pageable_heap^;
          IFEND;

          IF rvl_p^.robotic_communication^.server_response.query.remaining_candidates <> NIL THEN
            FREE rvl_p^.robotic_communication^.server_response.query.remaining_candidates IN
                  osv$mainframe_pageable_heap^;
          IFEND;
        IFEND;

        IF NOT rvl_p^.robotic_communication^.server_response.request_processed AND
              (rvl_p^.robotic_communication^.server_response.server_messages <> NIL) THEN
          FREE rvl_p^.robotic_communication^.server_response.server_messages IN osv$mainframe_pageable_heap^
        IFEND;
      IFEND;

      FREE rvl_p^.robotic_communication IN osv$mainframe_pageable_heap^;
    END /client_delete_request/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$client_delete_request;

?? OLDTITLE ??
?? NEWTITLE := 'iop$client_get_response', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$client_get_response
    (    server_name: ost$name;
         request_id: rmt$rbt_request_id;
     VAR server_response: iot$formatted_server_response;
     VAR status: ost$status);

    VAR
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /client_get_response/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /client_get_response/;
      IFEND;

      locate_request_id_in_rvl (request_id, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /client_get_response/;
      IFEND;

      IF NOT ((rvl_p^.ssn = jmv$jcb.system_name) AND (rvl_p^.robotic_communication^.server_name =
            server_name)) THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$request_not_found, 'IOP$CLIENT_GET_RESPONSE',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, request_id, radix, NOT include_radix,
              status);
        EXIT /client_get_response/;
      IFEND;

      IF NOT (rvl_p^.robotic_communication^.server_received_request AND
            rvl_p^.robotic_communication^.server_response_received) THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$response_unavailable,
              'IOP$CLIENT_GET_RESPONSE', status);
        osp$append_status_integer (osc$status_parameter_delimiter, request_id, radix, NOT include_radix,
              status);
        EXIT /client_get_response/;
      IFEND;

      server_response := rvl_p^.robotic_communication^.server_response;

    END /client_get_response/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$client_get_response;

?? OLDTITLE ??
?? NEWTITLE := 'iop$client_put_request', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$client_put_request
    (    server_name: ost$name;
         sfid: gft$system_file_identifier;
         client_request: rmt$rbt_request;
     VAR request_id: rmt$rbt_request_id;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      waiting_tasks_index: ost$positive_integers;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /client_put_request/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /client_put_request/;
      IFEND;

      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /client_put_request/;
      IFEND;

      IF rvl_p^.robotic_communication <> NIL THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$client_request_active,
              'IOP$CLIENT_PUT_REQUEST', status);
        EXIT /client_put_request/;
      IFEND;

      ALLOCATE rvl_p^.robotic_communication IN osv$mainframe_pageable_heap^;
      rvl_p^.robotic_communication^.server_received_request := FALSE;
      rvl_p^.robotic_communication^.server_name := server_name;
      rvl_p^.robotic_communication^.client_request := client_request;
      iov$robotic_request_id := (iov$robotic_request_id + 1) MOD rmc$rbt_max_request_id;
      request_id := iov$robotic_request_id;
      rvl_p^.robotic_communication^.client_request.request_id := request_id;
      pmp$get_executing_task_gtid (rvl_p^.robotic_communication^.requesting_task);
      rvl_p^.robotic_communication^.server_response_received := FALSE;

      FOR waiting_tasks_index := LOWERBOUND (p_robotic_server_entry^.waiting_tasks)
            TO UPPERBOUND (p_robotic_server_entry^.waiting_tasks) DO
        IF p_robotic_server_entry^.waiting_tasks [waiting_tasks_index] <> tmv$null_global_task_id THEN
          pmp$ready_task (p_robotic_server_entry^.waiting_tasks [waiting_tasks_index], ignore_status);
        IFEND;
      FOREND;

    END /client_put_request/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$client_put_request;

?? OLDTITLE ??
?? NEWTITLE := 'iop$create_rvl_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$create_rvl_entry
    (    sfid: gft$system_file_identifier;
         density: rmt$density;
         global_file_name: dmt$global_file_name;
         path_handle: fmt$path_handle;
         requested_volume_attributes: iot$requested_volume_attributes,
         volume_list: rmt$volume_list;
         write_ring: rmt$write_ring;
     VAR status: ost$status);

    VAR
      alloc_vsn_p: ^iot$vsn_entry,
      ignore_status: ost$status,
      local_path_handle: fmt$path_handle,
      path_handle_name: fst$path_handle_name,
      rvl_p: ^iot$requested_vsn_list_entry,
      volume_list_index: ost$positive_integers;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    delete_rvl_entry (path_handle, ignore_status);

    local_path_handle := path_handle;
    local_path_handle.open_position.specified := FALSE;
    clp$construct_path_handle_name (local_path_handle, path_handle_name);

    ALLOCATE rvl_p IN osv$mainframe_pageable_heap^;

    rvl_p^ := rvl_entry_template;
    rvl_p^.ssn := jmv$jcb.system_name;
    rvl_p^.sfid := sfid;
    rvl_p^.global_file_name := global_file_name;
    rvl_p^.path_handle_name := path_handle_name;
    IF write_ring = rmc$no_write_ring THEN
      rvl_p^.requested_tape_characteristics.write_ring := FALSE;
    ELSE
      rvl_p^.requested_tape_characteristics.write_ring := TRUE;
    IFEND;
    rvl_p^.requested_tape_characteristics.density := density;
    rvl_p^.requested_volume_attributes := requested_volume_attributes;

    FOR volume_list_index := LOWERBOUND (volume_list) TO UPPERBOUND (volume_list) DO
      ALLOCATE alloc_vsn_p IN osv$mainframe_pageable_heap^;
      IF rvl_p^.first_vsn_entry_p = NIL THEN
        rvl_p^.first_vsn_entry_p := alloc_vsn_p;
        alloc_vsn_p^.previous_vsn_p := NIL;
      ELSE
        rvl_p^.last_vsn_entry_p^.next_vsn_p := alloc_vsn_p;
        alloc_vsn_p^.previous_vsn_p := rvl_p^.last_vsn_entry_p;
      IFEND;
      alloc_vsn_p^.next_vsn_p := NIL;
      rvl_p^.last_vsn_entry_p := alloc_vsn_p;
      rvl_p^.last_vsn_entry_p^.rvsn := volume_list [volume_list_index].recorded_vsn;
      rvl_p^.last_vsn_entry_p^.evsn := volume_list [volume_list_index].external_vsn;
    FOREND;

    IF iov$forward_rvl_p = NIL THEN
      iov$forward_rvl_p := rvl_p;
      iov$backward_rvl_p := rvl_p;
    ELSE
      rvl_p^.backward_link := iov$backward_rvl_p;
      iov$backward_rvl_p^.forward_link := rvl_p;
      iov$backward_rvl_p := rvl_p;
    IFEND;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$create_rvl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'iop$define_robotic_server', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$define_robotic_server
    (    server_name: ost$name;
         managed_elements: array [1 .. * ] of cmt$element_name;
         server_attributes: iot$robotic_server_attributes;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      managed_densities: iot$managed_densities,
      managed_element_index: ost$positive_integers,
      new_robotic_server_array_p: ^array [1 .. * ] of iot$robotic_server_entry,
      new_robotic_server_index: ost$positive_integers,
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_index: ost$positive_integers,
      unit_type: iot$unit_type,
      waiting_tasks_index: ost$positive_integers;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /define_robotic_server/
    BEGIN

      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);

      IF status.normal THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$duplicate_server,
              'IOP$DEFINE_ROBOTIC_SERVER', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
        EXIT /define_robotic_server/;
      ELSEIF status.condition = rme$server_not_defined THEN
        status.normal := TRUE;
      ELSE
        EXIT /define_robotic_server/;
      IFEND;

      managed_densities := $iot$managed_densities [];

    /validate_managed_elements/
      FOR managed_element_index := LOWERBOUND (managed_elements) TO UPPERBOUND (managed_elements) DO
        FOR tusl_index := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
          IF iov$tusl_p^ [tusl_index].element_name = managed_elements [managed_element_index] THEN
            unit_type := iov$tusl_p^ [tusl_index].unit_type;
            IF (unit_type = ioc$dt_mt679_2) OR (unit_type = ioc$dt_mt679_3) OR
                  (unit_type = ioc$dt_mt679_4) THEN
              managed_densities := managed_densities + $iot$managed_densities [rmc$800];
            IFEND;
            IF (unit_type <> ioc$dt_mt5682_1x) THEN
              managed_densities := managed_densities + $iot$managed_densities [rmc$1600];
            IFEND;
            IF NOT ((unit_type = ioc$dt_mt679_2) OR (unit_type = ioc$dt_mt679_3) OR
                  (unit_type = ioc$dt_mt679_4) OR (unit_type = ioc$dt_mt5682_1x)) THEN
              managed_densities := managed_densities + $iot$managed_densities [rmc$6250];
            IFEND;
            IF (unit_type = ioc$dt_mt5682_1x) THEN
              managed_densities := managed_densities + $iot$managed_densities [rmc$38000];
            IFEND;
            CYCLE /validate_managed_elements/;
          IFEND;
        FOREND;
        osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_element_name,
              'IOP$DEFINE_ROBOTIC_SERVER', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, managed_elements [managed_element_index],
              status);
        EXIT /define_robotic_server/;
      FOREND /validate_managed_elements/;

      IF iov$robotic_server_array_p = NIL THEN
        ALLOCATE new_robotic_server_array_p: [1 .. 1] IN osv$mainframe_pageable_heap^;
        new_robotic_server_index := 1;
      ELSE
        ALLOCATE new_robotic_server_array_p: [1 .. (UPPERBOUND (iov$robotic_server_array_p^) + 1)] IN
              osv$mainframe_pageable_heap^;
        FOR new_robotic_server_index := 1 TO UPPERBOUND (iov$robotic_server_array_p^) DO
          new_robotic_server_array_p^ [new_robotic_server_index] :=
                iov$robotic_server_array_p^ [new_robotic_server_index];
        FOREND;
        new_robotic_server_index := UPPERBOUND (new_robotic_server_array_p^);
      IFEND;

      new_robotic_server_array_p^ [new_robotic_server_index].server_name := server_name;

      ALLOCATE new_robotic_server_array_p^ [new_robotic_server_index].managed_elements_p:
            [1 .. UPPERBOUND (managed_elements)] IN osv$mainframe_pageable_heap^;

      FOR managed_element_index := LOWERBOUND (managed_elements) TO UPPERBOUND (managed_elements) DO
        new_robotic_server_array_p^ [new_robotic_server_index].managed_elements_p^ [managed_element_index] :=
              managed_elements [managed_element_index];
      FOREND;

      new_robotic_server_array_p^ [new_robotic_server_index].managed_densities := managed_densities;
      new_robotic_server_array_p^ [new_robotic_server_index].server_attributes := server_attributes;
      new_robotic_server_array_p^ [new_robotic_server_index].server_job_name := jmv$jcb.system_name;

      FOR waiting_tasks_index := LOWERBOUND (new_robotic_server_array_p^ [new_robotic_server_index].
            waiting_tasks) TO UPPERBOUND (new_robotic_server_array_p^ [new_robotic_server_index].
            waiting_tasks) DO
        new_robotic_server_array_p^ [new_robotic_server_index].waiting_tasks [waiting_tasks_index] :=
              tmv$null_global_task_id
      FOREND;

      IF iov$robotic_server_array_p <> NIL THEN
        FREE iov$robotic_server_array_p IN osv$mainframe_pageable_heap^;
      IFEND;

      iov$robotic_server_array_p := new_robotic_server_array_p;

      rvl_p := iov$forward_rvl_p;

      WHILE rvl_p <> NIL DO
        CASE rvl_p^.vsn_state OF
          = ioc$queued_for_assignment, ioc$ready_for_assignment=
            IF (rvl_p^.requested_tape_characteristics.density IN managed_densities) AND
               (rvl_p^.gtid <> tmv$null_global_task_id) THEN
              pmp$ready_task (rvl_p^.gtid, ignore_status);
            IFEND;
          = ioc$assigned, ioc$unassigned =
            {no need to ready these};
        CASEND;
        rvl_p := rvl_p^.forward_link;
      WHILEND;

    END /define_robotic_server/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$define_robotic_server;

?? OLDTITLE ??
?? NEWTITLE := 'iop$delete_rvl_entries_via_ssn', EJECT ??

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

    VAR
      next_rvl_p: ^iot$requested_vsn_list_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      vsn_p: ^iot$vsn_entry;

    status.normal := TRUE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /delete_rvl_entries_via_ssn/
    BEGIN

      rvl_p := iov$forward_rvl_p;
      WHILE rvl_p <> NIL DO
        next_rvl_p := rvl_p^.forward_link;
        IF rvl_p^.ssn = jmv$jcb.system_name THEN

          delete_rvl_entry_from_vsn_queue (rvl_p);

          WHILE rvl_p^.first_vsn_entry_p <> NIL DO
            vsn_p := rvl_p^.last_vsn_entry_p;
            IF rvl_p^.first_vsn_entry_p = rvl_p^.last_vsn_entry_p THEN
              rvl_p^.first_vsn_entry_p := NIL;
              rvl_p^.last_vsn_entry_p := NIL;
            ELSE
              rvl_p^.last_vsn_entry_p := rvl_p^.last_vsn_entry_p^.previous_vsn_p;
              rvl_p^.last_vsn_entry_p^.next_vsn_p := NIL;
            IFEND;
            FREE vsn_p IN osv$mainframe_pageable_heap^;
          WHILEND;

          IF iov$forward_rvl_p = iov$backward_rvl_p THEN
            iov$forward_rvl_p := NIL;
            iov$backward_rvl_p := NIL;
          ELSEIF iov$forward_rvl_p = rvl_p THEN
            iov$forward_rvl_p := rvl_p^.forward_link;
            iov$forward_rvl_p^.backward_link := NIL;
          ELSEIF iov$backward_rvl_p = rvl_p THEN
            iov$backward_rvl_p := rvl_p^.backward_link;
            iov$backward_rvl_p^.forward_link := NIL;
          ELSE
            rvl_p^.backward_link^.forward_link := rvl_p^.forward_link;
            rvl_p^.forward_link^.backward_link := rvl_p^.backward_link;
          IFEND;

          FREE rvl_p IN osv$mainframe_pageable_heap^;

        IFEND;
        rvl_p := next_rvl_p;
      WHILEND;

    END /delete_rvl_entries_via_ssn/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$delete_rvl_entries_via_ssn;

?? OLDTITLE ??
?? NEWTITLE := 'iop$delete_rvl_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$delete_rvl_entry
    (    sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      rvl_p: ^iot$requested_vsn_list_entry,
      vsn_p: ^iot$vsn_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /delete_rvl_entry/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /delete_rvl_entry/;
      IFEND;

      delete_rvl_entry_from_vsn_queue (rvl_p);

      WHILE rvl_p^.first_vsn_entry_p <> NIL DO
        vsn_p := rvl_p^.last_vsn_entry_p;
        IF rvl_p^.first_vsn_entry_p = rvl_p^.last_vsn_entry_p THEN
          rvl_p^.first_vsn_entry_p := NIL;
          rvl_p^.last_vsn_entry_p := NIL;
        ELSE
          rvl_p^.last_vsn_entry_p := rvl_p^.last_vsn_entry_p^.previous_vsn_p;
          rvl_p^.last_vsn_entry_p^.next_vsn_p := NIL;
        IFEND;
        FREE vsn_p IN osv$mainframe_pageable_heap^;
      WHILEND;

      IF iov$forward_rvl_p = iov$backward_rvl_p THEN
        iov$forward_rvl_p := NIL;
        iov$backward_rvl_p := NIL;
      ELSEIF iov$forward_rvl_p = rvl_p THEN
        iov$forward_rvl_p := rvl_p^.forward_link;
        iov$forward_rvl_p^.backward_link := NIL;
      ELSEIF iov$backward_rvl_p = rvl_p THEN
        iov$backward_rvl_p := rvl_p^.backward_link;
        iov$backward_rvl_p^.forward_link := NIL;
      ELSE
        rvl_p^.backward_link^.forward_link := rvl_p^.forward_link;
        rvl_p^.forward_link^.backward_link := rvl_p^.backward_link;
      IFEND;

      FREE rvl_p IN osv$mainframe_pageable_heap^;

    END /delete_rvl_entry/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$delete_rvl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'iop$extend_volume_list_in_rvl', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$extend_volume_list_in_rvl
    (    sfid: gft$system_file_identifier;
         evsn: rmt$external_vsn;
         rvsn: rmt$recorded_vsn;
         requested_volume_attributes: iot$requested_volume_attributes,
         vsn_number: integer;
     VAR status: ost$status);

    VAR
      alloc_vsn_p: ^iot$vsn_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      temp_vsn_p: ^iot$vsn_entry,
      volume_index: ost$positive_integers;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /extend_volume_list_in_rvl/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /extend_volume_list_in_rvl/;
      IFEND;

      IF vsn_number = 1 THEN
        IF rvl_p^.first_vsn_entry_p <> NIL THEN { change first entry
          rvl_p^.first_vsn_entry_p^.evsn := evsn;
          rvl_p^.first_vsn_entry_p^.rvsn := rvsn;
          rvl_p^.requested_volume_attributes := requested_volume_attributes;
          EXIT /extend_volume_list_in_rvl/;
        IFEND;
      ELSE
        temp_vsn_p := rvl_p^.first_vsn_entry_p;

      /determine_if_change/
        FOR volume_index := 1 TO vsn_number - 1 DO
          IF temp_vsn_p <> NIL THEN
            temp_vsn_p := temp_vsn_p^.next_vsn_p;
          ELSE
            EXIT /determine_if_change/;
          IFEND;
        FOREND /determine_if_change/;

        IF temp_vsn_p <> NIL THEN
          temp_vsn_p^.evsn := evsn;
          temp_vsn_p^.rvsn := rvsn;
          rvl_p^.requested_volume_attributes := requested_volume_attributes;
          EXIT /extend_volume_list_in_rvl/;
        IFEND;
      IFEND;

      ALLOCATE alloc_vsn_p IN osv$mainframe_pageable_heap^;

      IF rvl_p^.first_vsn_entry_p = NIL THEN
        rvl_p^.first_vsn_entry_p := alloc_vsn_p;
        alloc_vsn_p^.previous_vsn_p := NIL;
      ELSE
        rvl_p^.last_vsn_entry_p^.next_vsn_p := alloc_vsn_p;
        alloc_vsn_p^.previous_vsn_p := rvl_p^.last_vsn_entry_p;
      IFEND;

      alloc_vsn_p^.next_vsn_p := NIL;
      rvl_p^.last_vsn_entry_p := alloc_vsn_p;
      rvl_p^.last_vsn_entry_p^.evsn := evsn;
      rvl_p^.last_vsn_entry_p^.rvsn := rvsn;
      rvl_p^.requested_volume_attributes := requested_volume_attributes;

    END /extend_volume_list_in_rvl/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$extend_volume_list_in_rvl;

?? OLDTITLE ??
?? NEWTITLE := 'iop$get_density_states', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$get_density_states
    (VAR density_states: array [rmc$800 .. rmc$38000] of iot$density_states;
     VAR status: ost$status);

    VAR
      density_state_index: rmc$800 .. rmc$38000,
      tusl_index: ost$positive_integers,
      unit_type: iot$unit_type;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR density_state_index := LOWERBOUND (density_states) TO UPPERBOUND (density_states) DO
      density_states [density_state_index].down_count := 0;
      density_states [density_state_index].off_count := 0;
      density_states [density_state_index].on_count := 0;
    FOREND;

  /scan_tusl_entries/
    FOR tusl_index := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
      unit_type := iov$tusl_p^ [tusl_index].unit_type;
      IF (unit_type = ioc$dt_mt679_2) OR (unit_type = ioc$dt_mt679_3) OR (unit_type = ioc$dt_mt679_4) THEN
        CASE iov$tusl_p^ [tusl_index].tape_unit_state OF
        = cmc$down =
          density_states [rmc$800].down_count := density_states [rmc$800].down_count + 1;
        = cmc$off =
          density_states [rmc$800].off_count := density_states [rmc$800].off_count + 1;
        = cmc$on =
          density_states [rmc$800].on_count := density_states [rmc$800].on_count + 1;
        CASEND;
      IFEND;
      IF (unit_type <> ioc$dt_mt5682_1x) THEN
        CASE iov$tusl_p^ [tusl_index].tape_unit_state OF
        = cmc$down =
          density_states [rmc$1600].down_count := density_states [rmc$1600].down_count + 1;
        = cmc$off =
          density_states [rmc$1600].off_count := density_states [rmc$1600].off_count + 1;
        = cmc$on =
          density_states [rmc$1600].on_count := density_states [rmc$1600].on_count + 1;
        CASEND;
      IFEND;
      IF NOT ((unit_type = ioc$dt_mt679_2) OR (unit_type = ioc$dt_mt679_3) OR
            (unit_type = ioc$dt_mt679_4) OR (unit_type = ioc$dt_mt5682_1x)) THEN
        CASE iov$tusl_p^ [tusl_index].tape_unit_state OF
        = cmc$down =
          density_states [rmc$6250].down_count := density_states [rmc$6250].down_count + 1;
        = cmc$off =
          density_states [rmc$6250].off_count := density_states [rmc$6250].off_count + 1;
        = cmc$on =
          density_states [rmc$6250].on_count := density_states [rmc$6250].on_count + 1;
        CASEND;
      IFEND;
      IF (unit_type = ioc$dt_mt5682_1x) THEN
        CASE iov$tusl_p^ [tusl_index].tape_unit_state OF
        = cmc$down =
          density_states [rmc$38000].down_count := density_states [rmc$38000].down_count + 1;
        = cmc$off =
          density_states [rmc$38000].off_count := density_states [rmc$38000].off_count + 1;
        = cmc$on =
          density_states [rmc$38000].on_count := density_states [rmc$38000].on_count + 1;
        CASEND;
      IFEND;
      CYCLE /scan_tusl_entries/;

    FOREND /scan_tusl_entries/;

    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$get_density_states;

?? OLDTITLE ??
?? NEWTITLE := 'iop$get_selected_element', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$get_selected_element
    (    sfid: gft$system_file_identifier;
         external_vsn: rmt$external_vsn;
         recorded_vsn: rmt$recorded_vsn;
         density: rmt$density;
     VAR element_name: cmt$element_name;
     VAR status: ost$status);

?? NEWTITLE := '  select_by_external_vsn', EJECT ??

  PROCEDURE select_by_external_vsn
    (    sfid: gft$system_file_identifier;
         system_supplied_name: jmt$system_supplied_name;
         external_vsn: rmt$external_vsn;
         density: rmt$density;
     VAR tusl_ordinal: iot$tusl_ordinal;
     VAR status: ost$status);

    VAR
      density_supported: boolean,
      local_tusl_ordinal: iot$tusl_ordinal;

    status.normal := TRUE;

    IF (external_vsn <> rmc$unspecified_vsn) THEN
      FOR local_tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
        IF (iov$tusl_p^ [local_tusl_ordinal].sfid = sfid) AND
              (iov$tusl_p^ [local_tusl_ordinal].ssn = system_supplied_name) AND
              (iov$tusl_p^ [local_tusl_ordinal].evsn = external_vsn) AND
              (iov$tusl_p^ [local_tusl_ordinal].tape_unit_state = cmc$on) AND
              (iov$tusl_p^ [local_tusl_ordinal].assignment_state = ioc$man_assignment_in_progress) THEN
          iop$determine_density_support (iov$tusl_p^ [local_tusl_ordinal].unit_type, density,
                density_supported);
          IF density_supported THEN
            tusl_ordinal := local_tusl_ordinal;
            RETURN;
          IFEND;
        IFEND;
      FOREND;
    IFEND;
    osp$set_status_abnormal (rmc$resource_management_id, rme$volume_not_mounted, '', status);

  PROCEND select_by_external_vsn;

?? OLDTITLE ??
?? NEWTITLE := '  select_by_recorded_vsn', EJECT ??

  PROCEDURE select_by_recorded_vsn
    (    recorded_vsn: rmt$recorded_vsn;
         density: rmt$density;
     VAR multiple_volumes_with_same_vsn: boolean;
     VAR tusl_ordinal: iot$tusl_ordinal;
     VAR status: ost$status);

    VAR
      all_tape_units_assigned: boolean,
      density_supported: boolean,
      local_tusl_ordinal: iot$tusl_ordinal,
      volume_found: boolean,
      vsns_match: boolean;

    status.normal := TRUE;

    all_tape_units_assigned := TRUE;
    multiple_volumes_with_same_vsn := FALSE;
    volume_found := FALSE;

    IF (recorded_vsn <> rmc$unspecified_vsn) THEN
      FOR local_tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
        IF (iov$tusl_p^ [local_tusl_ordinal].tape_unit_state = cmc$on) AND
              (iov$tusl_p^ [local_tusl_ordinal].assignment_state = ioc$not_assigned) THEN
          iop$determine_density_support (iov$tusl_p^ [local_tusl_ordinal].unit_type, density,
                density_supported);
          IF (recorded_vsn = iov$tusl_p^ [local_tusl_ordinal].rvsn) AND density_supported THEN
            IF volume_found THEN
              multiple_volumes_with_same_vsn := TRUE;
            ELSE
              volume_found := TRUE;
              tusl_ordinal := local_tusl_ordinal;
            IFEND;
          ELSEIF density_supported THEN
            all_tape_units_assigned := FALSE;
          IFEND;
        IFEND;
      FOREND;
    IFEND;
    IF NOT volume_found THEN
      IF all_tape_units_assigned THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$tape_unit_available, '', status);
      ELSE
        osp$set_status_abnormal (rmc$resource_management_id, rme$volume_not_mounted, '', status);
      IFEND;
    IFEND;

  PROCEND select_by_recorded_vsn;

?? OLDTITLE ??
?? EJECT ??

    VAR
      multiple_volumes_with_same_vsn: boolean,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_ordinal: iot$tusl_ordinal;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$rvl_lock);
      RETURN;
    IFEND;

  /get_selected_element/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /get_selected_element/;
      IFEND;

      IF rvl_p^.assignment_terminated THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$operator_stop, rvl_p^.message, status);
        EXIT /get_selected_element/;
      IFEND;

      IF (rvl_p^.operator_assignment_type = ioc$expecting_auto_assignment) THEN
        select_by_recorded_vsn (recorded_vsn, density, multiple_volumes_with_same_vsn, tusl_ordinal,
            status);
        IF status.normal THEN
          IF multiple_volumes_with_same_vsn THEN
            rvl_p^.operator_assignment_type := ioc$expecting_manual_assignment;
            select_by_external_vsn (rvl_p^.sfid, rvl_p^.ssn, external_vsn, density, tusl_ordinal, status);
            IF status.normal THEN
              element_name := iov$tusl_p^ [tusl_ordinal].element_name;
            IFEND;
          ELSE
            element_name := iov$tusl_p^ [tusl_ordinal].element_name;
          IFEND;
        IFEND;
      ELSEIF status.normal AND (rvl_p^.operator_assignment_type = ioc$expecting_manual_assignment) THEN
        select_by_external_vsn (rvl_p^.sfid, rvl_p^.ssn, external_vsn, density, tusl_ordinal, status);
        IF status.normal THEN
          element_name := iov$tusl_p^ [tusl_ordinal].element_name;
        IFEND;
      ELSE
        osp$set_status_abnormal (rmc$resource_management_id, dme$improper_op_assign_state,
              'IOP$GET_SELECTED_ELEMENT', status);
      IFEND;

    END /get_selected_element/;

    clear_mainframe_sig_lock (iov$tusl_lock);
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$get_selected_element;

?? OLDTITLE ??
?? NEWTITLE := 'iop$get_server_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$get_server_entry
    (    server_index: iot$robotic_server_index;
     VAR server_entry: iot$robotic_server_entry;
     VAR status: ost$status);

    VAR
      p_robotic_server_entry: ^iot$robotic_server_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (iov$robotic_server_array_p = NIL) OR (server_index > UPPERBOUND (iov$robotic_server_array_p^)) THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_server_index, 'IOP$GET_SERVER_ENTRY',
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, server_index, radix, NOT include_radix,
            status);
    ELSE
      server_entry := iov$robotic_server_array_p^ [server_index];
    IFEND;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$get_server_entry;

?? OLDTITLE ??
?? NEWTITLE := 'iop$get_tape_mount_information', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$get_tape_mount_information
    (    rvl_info_array_p: ^array [1 .. * ] of iot$rvl_entry_information;
     VAR all_tape_mounts_found: boolean;
     VAR status: ost$status);

    VAR
      info_array_index: ost$non_negative_integers,
      rvl_p: ^iot$requested_vsn_list_entry;

    all_tape_mounts_found := TRUE;
    info_array_index := 0;

    IF rvl_info_array_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$nil_rvl_info_array_p,
            'iop$get_tape_mount_information', status);
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rvl_p := iov$forward_rvl_p;
  /search_rvl/
    BEGIN
      WHILE rvl_p <> NIL DO
        IF rvl_p^.vsn_state = ioc$ready_for_assignment THEN
          IF info_array_index < UPPERBOUND (rvl_info_array_p^) THEN
            info_array_index := info_array_index + 1;
          ELSE
            all_tape_mounts_found := FALSE;
            EXIT /search_rvl/;
          IFEND;

          rvl_info_array_p^ [info_array_index].null_entry := FALSE;
          rvl_info_array_p^ [info_array_index].ssn := rvl_p^.ssn;
          rvl_info_array_p^ [info_array_index].sfid := rvl_p^.sfid;
          rvl_info_array_p^ [info_array_index].path_handle_name := rvl_p^.path_handle_name;
          rvl_info_array_p^ [info_array_index].vsn_state := rvl_p^.vsn_state;
          rvl_info_array_p^ [info_array_index].gtid := rvl_p^.gtid;
          rvl_info_array_p^ [info_array_index].assigned_element_name := rvl_p^.assigned_element_name;
          rvl_info_array_p^ [info_array_index].time_of_mount_request := rvl_p^.time_of_mount_request;
          rvl_info_array_p^ [info_array_index].operator_assignment_type := rvl_p^.operator_assignment_type;

          IF rvl_p^.current_vsn_p <> NIL THEN
            rvl_info_array_p^ [info_array_index].current_vsn := rvl_p^.current_vsn_p^.evsn;
            IF rvl_p^.current_vsn_p^.previous_vsn_p = NIL THEN
              rvl_info_array_p^ [info_array_index].previous_vsn := rmc$unspecified_vsn;
            ELSE
              rvl_info_array_p^ [info_array_index].previous_vsn := rvl_p^.current_vsn_p^.previous_vsn_p^.evsn;
            IFEND;
            IF rvl_p^.current_vsn_p^.next_vsn_p = NIL THEN
              rvl_info_array_p^ [info_array_index].next_vsn := rmc$unspecified_vsn;
            ELSE
              rvl_info_array_p^ [info_array_index].next_vsn := rvl_p^.current_vsn_p^.next_vsn_p^.evsn;
            IFEND;
          ELSE
            rvl_info_array_p^ [info_array_index].current_vsn := rmc$unspecified_vsn;
            rvl_info_array_p^ [info_array_index].previous_vsn := rmc$unspecified_vsn;
            rvl_info_array_p^ [info_array_index].next_vsn := rmc$unspecified_vsn;
          IFEND;
          rvl_info_array_p^ [info_array_index].requested_tape_characteristics :=
                rvl_p^.requested_tape_characteristics;
          rvl_info_array_p^ [info_array_index].requested_volume_attributes := rvl_p^.
                requested_volume_attributes;
        IFEND;
        rvl_p := rvl_p^.forward_link;
      WHILEND;

    END /search_rvl/;

    IF info_array_index < UPPERBOUND (rvl_info_array_p^) THEN
      info_array_index := info_array_index + 1;
      rvl_info_array_p^ [info_array_index].null_entry := TRUE;
    IFEND;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$get_tape_mount_information;

?? OLDTITLE ??
?? NEWTITLE := 'iop$job_tape_mounts_active', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$job_tape_mounts_active
    (    job_name: jmt$system_supplied_name;
     VAR job_tape_mounts_active: boolean;
     VAR status: ost$status);

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    status.normal := TRUE;
    job_tape_mounts_active := FALSE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rvl_p := iov$forward_rvl_p;
  /search/
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.ssn = job_name) AND (rvl_p^.vsn_state = ioc$ready_for_assignment) THEN
        job_tape_mounts_active := TRUE;
        EXIT /search/;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND /search/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$job_tape_mounts_active;

?? OLDTITLE ??
?? NEWTITLE := 'iop$queue_volume_assignment', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$queue_volume_assignment
    (    sfid: gft$system_file_identifier;
         label_type: amt$label_type;
         requested_density: rmt$density;
         requested_evsn: rmt$external_vsn;
         requested_rvsn: rmt$recorded_vsn;
         requested_volume_attributes: iot$requested_volume_attributes;
     VAR first_in_queue: boolean;
     VAR status: ost$status);

    VAR
      first_queued_rvl_p: ^iot$requested_vsn_list_entry,
      last_queued_rvl_p: ^iot$requested_vsn_list_entry,
      requestor_rvl_p: ^iot$requested_vsn_list_entry;

    first_in_queue := FALSE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /table_locked/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, requestor_rvl_p, status);

      IF status.normal THEN
        locate_volume_in_rvl_entry (requestor_rvl_p, requested_density,
              requested_evsn, requested_rvsn, requestor_rvl_p^.current_vsn_p,
              status);
        locate_first_queued_rvl_p (requested_density, requested_evsn,
              requested_rvsn, first_queued_rvl_p);
        IF status.normal THEN
          CASE requestor_rvl_p^.vsn_state OF
          = ioc$unassigned =
            requestor_rvl_p^.vsn_state := ioc$queued_for_assignment;
            pmp$get_executing_task_gtid (requestor_rvl_p^.gtid);
            IF (label_type = amc$labelled) THEN
              requestor_rvl_p^.requested_tape_characteristics.label_type := amc$labelled;
              IF (requested_rvsn = requested_evsn) THEN
                requestor_rvl_p^.operator_assignment_type := ioc$expecting_auto_assignment;
              ELSE
                requestor_rvl_p^.operator_assignment_type := ioc$expecting_manual_assignment;
              IFEND;
            ELSE
              requestor_rvl_p^.requested_tape_characteristics.label_type := amc$unlabelled;
              requestor_rvl_p^.operator_assignment_type := ioc$expecting_manual_assignment;
            IFEND;
             requestor_rvl_p^.requested_volume_attributes := requested_volume_attributes;
          = ioc$queued_for_assignment =
            {ignore redundant call}
          ELSE {ioc$ready_for_assignment, ioc$assigned }
            osp$set_status_abnormal (rmc$resource_management_id, dme$improper_vsn_transition,
                  'IOP$QUEUE_VOLUME_ASSIGNMENT - READY FOR ASSIGNMENT OR ASSIGNED', status);
          CASEND;
        IFEND;
      IFEND;

      IF status.normal THEN
        IF (first_queued_rvl_p = NIL) OR (first_queued_rvl_p = requestor_rvl_p) THEN
          first_in_queue := TRUE;
          EXIT /table_locked/;
        ELSE {queue requestor if not already queued}
          last_queued_rvl_p := first_queued_rvl_p;
          WHILE last_queued_rvl_p^.next_in_vsn_queue <> NIL DO
            IF last_queued_rvl_p^.next_in_vsn_queue = requestor_rvl_p THEN
              EXIT /table_locked/;
            ELSE
              last_queued_rvl_p := last_queued_rvl_p^.next_in_vsn_queue;
            IFEND;
          WHILEND;

          last_queued_rvl_p^.next_in_vsn_queue := requestor_rvl_p;
          requestor_rvl_p^.previous_in_vsn_queue := last_queued_rvl_p;
          requestor_rvl_p^.next_in_vsn_queue := NIL;
        IFEND;
      IFEND;

    END /table_locked/;
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$queue_volume_assignment;

?? OLDTITLE ??
?? NEWTITLE := 'iop$rdy_task_waiting_assignment', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$rdy_task_waiting_assignment
    (VAR new_vsns_online_p: iot$new_vsns_online;
     VAR status: ost$status);

    VAR
      density_supported: boolean,
      ignore_status: ost$status,
      new_vsns_online_index: ost$positive_integers,
      rvl_p: ^iot$requested_vsn_list_entry;

    IF new_vsns_online_p = NIL THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$nil_new_vsns_online_p,
            'iop$rdy_task_waiting_assignment', status);
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rvl_p := iov$forward_rvl_p;
    WHILE rvl_p <> NIL DO
      IF (rvl_p^.current_vsn_p <> NIL) AND (rvl_p^.vsn_state = ioc$ready_for_assignment) AND
            (rvl_p^.operator_assignment_type = ioc$expecting_auto_assignment) THEN
      /new_vsn_search/
        BEGIN
          FOR new_vsns_online_index := LOWERBOUND (new_vsns_online_p^) TO UPPERBOUND (new_vsns_online_p^) DO
            IF new_vsns_online_p^ [new_vsns_online_index].rvsn = rmc$unspecified_vsn THEN
              EXIT /new_vsn_search/;
            IFEND;
            IF new_vsns_online_p^ [new_vsns_online_index].rvsn = rvl_p^.current_vsn_p^.rvsn THEN
              iop$determine_density_support (new_vsns_online_p^ [new_vsns_online_index].unit_type,
                    rvl_p^.requested_tape_characteristics.density, density_supported);
              IF density_supported AND (rvl_p^.gtid <> tmv$null_global_task_id) THEN
                pmp$ready_task (rvl_p^.gtid, ignore_status);
              IFEND;
            IFEND;
          FOREND;
        END /new_vsn_search/;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$rdy_task_waiting_assignment;

?? OLDTITLE ??
?? NEWTITLE := 'iop$ready_waiting_tape_tasks', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$ready_waiting_tape_tasks
    (    unit_type: iot$unit_type);

    VAR
      density_supported: boolean,
      ignore_status: ost$status,
      managed_densities: iot$managed_densities,
      robotic_server_index: ost$positive_integers,
      rvl_p: ^iot$requested_vsn_list_entry;

    IF iov$robotic_server_array_p <> NIL THEN

      managed_densities := $iot$managed_densities [];
      FOR robotic_server_index := LOWERBOUND (iov$robotic_server_array_p^)
            TO UPPERBOUND (iov$robotic_server_array_p^) DO
        managed_densities := managed_densities + iov$robotic_server_array_p^ [robotic_server_index].
              managed_densities;
      FOREND;

      rvl_p := iov$forward_rvl_p;
      WHILE rvl_p <> NIL DO
        iop$determine_density_support (unit_type, rvl_p^.requested_tape_characteristics.density,
              density_supported);
        IF density_supported AND (rvl_p^.requested_tape_characteristics.density IN managed_densities) AND
          (rvl_p^.gtid <> tmv$null_global_task_id) THEN
          pmp$ready_task (rvl_p^.gtid, ignore_status);
        IFEND;
        rvl_p := rvl_p^.forward_link;
      WHILEND;
    IFEND;

  PROCEND iop$ready_waiting_tape_tasks;

?? OLDTITLE ??
?? NEWTITLE := 'iop$read_lock_tusl_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$read_lock_tusl_entry
    (    tusl_ordinal: iot$tusl_ordinal;
     VAR tusl_entry_template: iot$tape_unit_status_entry;
     VAR status: ost$status);

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('TUSL_ENTRY_LOCK', iov$tusl_p^ [tusl_ordinal].lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$tusl_lock);
      RETURN;
    IFEND;

    tusl_entry_template := iov$tusl_p^ [tusl_ordinal];

    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$read_lock_tusl_entry;

?? OLDTITLE ??
?? NEWTITLE := 'iop$release_assignment_in_rvl', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$release_assignment_in_rvl
    (    sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      current_time: ost$time,
      ignore_status: ost$status,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_ordinal: iot$tusl_ordinal,
      unit_type: iot$unit_type;

    current_time.hms := '';

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$rvl_lock);
      RETURN;
    IFEND;

  /release_assignment_in_rvl/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /release_assignment_in_rvl/;
      IFEND;

      delete_rvl_entry_from_vsn_queue (rvl_p);

      rvl_p^.vsn_state := ioc$unassigned;
      rvl_p^.assigned_element_name := osc$null_name;
      rvl_p^.assignment_terminated := FALSE;
      rvl_p^.time_of_mount_request := '';
      rvl_p^.operator_assignment_type := ioc$unknown_assignment_type;

    /tusl_search/
      BEGIN
        FOR tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
          IF (iov$tusl_p^ [tusl_ordinal].sfid = sfid) AND
                (iov$tusl_p^ [tusl_ordinal].ssn = jmv$jcb.system_name) THEN
            unit_type := iov$tusl_p^ [tusl_ordinal].unit_type;
            iov$tusl_p^ [tusl_ordinal].assignment_state := ioc$not_assigned;
            iov$tusl_p^ [tusl_ordinal].sfid := gfv$null_sfid;
            iov$tusl_p^ [tusl_ordinal].evsn := rmc$unspecified_vsn;
            iov$tusl_p^ [tusl_ordinal].rvsn := rmc$unspecified_vsn;
            iov$tusl_p^ [tusl_ordinal].ssn := jmc$blank_system_supplied_name;
            iop$ready_waiting_tape_tasks (unit_type);
            EXIT /tusl_search/;
          IFEND;
        FOREND;
      END /tusl_search/;

    END /release_assignment_in_rvl/;

    clear_mainframe_sig_lock (iov$tusl_lock);
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$release_assignment_in_rvl;

?? OLDTITLE ??
?? NEWTITLE := 'iop$release_tape_unit', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$release_tape_unit
    (    sfid: gft$system_file_identifier;
         logical_unit: iot$logical_unit;
         delete_request_from_vsn_queue: boolean;
     VAR status: ost$status);

    VAR
      element_name: cmt$element_name,
      entry_locked: boolean,
      entry_unlocked: boolean,
      rvl_p: ^iot$requested_vsn_list_entry,
      tusl_ordinal: iot$tusl_ordinal;

    entry_locked := FALSE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$rvl_lock);
      RETURN;
    IFEND;

  /release_tape_unit/
    BEGIN

      IF sfid <> gfv$null_sfid THEN
        locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, rvl_p, status);
        IF NOT status.normal THEN
          EXIT /release_tape_unit/;
        IFEND;

        locate_element_in_tusl (rvl_p^.assigned_element_name, tusl_ordinal, status);
        IF NOT status.normal THEN
          EXIT /release_tape_unit/;
        IFEND;
      IFEND;

      cmp$lock_lun_entry (logical_unit, entry_locked);
      IF NOT entry_locked THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_lock_tape_table,
              'MAINFRAME LUN ENTRY', status);
        EXIT /release_tape_unit/;
      IFEND;

      IF NOT (cmv$logical_unit_table^ [logical_unit].configured AND
            cmv$logical_unit_table^ [logical_unit].status.assignable_device) THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_undefined, '', status);
        EXIT /release_tape_unit/;
      IFEND;

      IF NOT cmv$logical_unit_table^ [logical_unit].status.assigned THEN
        cmp$get_element_name_via_lun (logical_unit, element_name, status);
        IF NOT status.normal THEN
          element_name := osc$null_name;
        IFEND;
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_unit_unassigned,
              element_name, status);
        EXIT /release_tape_unit/;
      IFEND;

      IF cmv$logical_unit_table^ [logical_unit].status.assigned_jsn <> jmv$jcb.system_name THEN
        cmp$get_element_name_via_lun (logical_unit, element_name, status);
        IF NOT status.normal THEN
          element_name := osc$null_name;
        IFEND;
        osp$set_status_abnormal (rmc$resource_management_id, dme$unit_assigned, element_name, status);
        EXIT /release_tape_unit/;
      IFEND;


      IF sfid <> gfv$null_sfid THEN
        IF delete_request_from_vsn_queue THEN
          delete_rvl_entry_from_vsn_queue (rvl_p);
          rvl_p^.current_vsn_p := NIL;
          rvl_p^.vsn_state := ioc$unassigned;
          rvl_p^.operator_assignment_type := ioc$unknown_assignment_type;
        ELSE
          rvl_p^.vsn_state := ioc$queued_for_assignment;
          {This allows cases of dme$operator_reassign to remount volume}
        IFEND;

        rvl_p^.assigned_element_name := osc$null_name;
        rvl_p^.assignment_terminated := FALSE;
        rvl_p^.time_of_mount_request := '';

        iov$tusl_p^ [tusl_ordinal].assignment_state := ioc$not_assigned;
        iov$tusl_p^ [tusl_ordinal].evsn := rmc$unspecified_vsn;
        iov$tusl_p^ [tusl_ordinal].rvsn := rmc$unspecified_vsn;
        iov$tusl_p^ [tusl_ordinal].sfid := gfv$null_sfid;
        iov$tusl_p^ [tusl_ordinal].ssn := jmc$blank_system_supplied_name;

        iop$ready_waiting_tape_tasks (iov$tusl_p^ [tusl_ordinal].unit_type);
      IFEND;

      cmv$logical_unit_table^ [logical_unit].status.assigned := FALSE;
      cmv$logical_unit_table^ [logical_unit].status.assigned_jsn := jmc$blank_system_supplied_name;

    END /release_tape_unit/;

    IF entry_locked THEN
      cmp$unlock_lun_entry (logical_unit, entry_unlocked);
      IF status.normal AND (NOT entry_unlocked) THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$unable_to_release_lun_lock,
              'Unable to release lun entry in IOP$RELEASE_TAPE_UNIT', status);
      IFEND;
    IFEND;

    clear_mainframe_sig_lock (iov$tusl_lock);
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$release_tape_unit;

?? OLDTITLE ??
?? NEWTITLE := 'iop$remove_robotic_server', EJECT ??

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

    VAR
      p_robotic_server_entry: ^iot$robotic_server_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    locate_robotic_server_entry (server_name, p_robotic_server_entry, status);

    IF status.normal THEN
      remove_robotic_server_entry (p_robotic_server_entry, status);
    IFEND;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$remove_robotic_server;

?? OLDTITLE ??
?? NEWTITLE := 'iop$request_assignment_in_rvl', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$request_assignment_in_rvl
    (    sfid: gft$system_file_identifier;
         requested_density: rmt$density;
         requested_evsn: rmt$external_vsn;
         requested_rvsn: rmt$recorded_vsn;
     VAR status: ost$status);

    VAR
      current_time: ost$time,
      first_queued_rvl_p: ^iot$requested_vsn_list_entry,
      requestor_rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /request_assignment_in_rvl/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, jmv$jcb.system_name, requestor_rvl_p, status);
      IF NOT status.normal THEN
        EXIT /request_assignment_in_rvl/;
      IFEND;

      CASE requestor_rvl_p^.vsn_state OF

      = ioc$unassigned, ioc$queued_for_assignment =
        locate_first_queued_rvl_p (requested_density, requested_evsn, requested_rvsn, first_queued_rvl_p);
        IF (first_queued_rvl_p = requestor_rvl_p) THEN
          requestor_rvl_p^.vsn_state := ioc$ready_for_assignment;

          pmp$get_time (osc$hms_time, current_time, status);
          IF NOT status.normal THEN
            EXIT /request_assignment_in_rvl/;
          IFEND;
          requestor_rvl_p^.time_of_mount_request := current_time.hms;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, dme$improper_vsn_transition,
                'IOP$REQUEST_ASSIGNMENT_IN_RVL - NOT FIRST IN QUEUE', status);
          EXIT /request_assignment_in_rvl/;
        IFEND;

      = ioc$ready_for_assignment =
        {ignore redundant call}

      ELSE {ioc$assigned}
        osp$set_status_abnormal (rmc$resource_management_id, dme$improper_vsn_transition,
              'IOP$REQUEST_ASSIGNMENT_IN_RVL - ASSIGNED', status);
        EXIT /request_assignment_in_rvl/;
      CASEND;

    END /request_assignment_in_rvl/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$request_assignment_in_rvl;

?? OLDTITLE ??
?? NEWTITLE := 'iop$select_best_element', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$select_best_element
    (    preferred_elements: ^array [1 .. * ] of cmt$element_name;
         remaining_elements: ^array [1 .. * ] of cmt$element_name;
     VAR selected_element: cmt$element_name;
     VAR status: ost$status);

?? NEWTITLE := '  get_next_element', EJECT ??

    PROCEDURE get_next_element
      (VAR selected_element: cmt$element_name;
       VAR tusl_ordinal {input/output} : iot$tusl_ordinal;
       VAR tusl_scan_count {input/output} : integer);

      selected_element := osc$null_name;

      REPEAT
        IF tusl_ordinal = UPPERBOUND (iov$tusl_p^) THEN
          tusl_ordinal := LOWERBOUND (iov$tusl_p^);
        ELSE
          tusl_ordinal := tusl_ordinal + 1;
        IFEND;

        validate_candidate_element (iov$tusl_p^ [tusl_ordinal].element_name, $cmt$element_states [cmc$on],
              status);
        IF status.normal THEN
          selected_element := iov$tusl_p^ [tusl_ordinal].element_name;
          RETURN;
        IFEND;
        tusl_scan_count := tusl_scan_count + 1;
      UNTIL tusl_scan_count > (UPPERBOUND (iov$tusl_p^) - LOWERBOUND (iov$tusl_p^));

    PROCEND get_next_element;
?? OLDTITLE ??

    VAR
      candidate_element_index: ost$positive_integers,
      managed_element_index: ost$positive_integers,
      managed_elements_p: ^array [1 .. * ] of cmt$element_name,
      robotic_element_monopoly: boolean,
      robotic_server_index: iot$robotic_server_index,
      tusl_scan_count: integer,
      tusl_ordinal: iot$tusl_ordinal;

    selected_element := osc$null_name;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /select_best_element/
    BEGIN

      IF preferred_elements <> NIL THEN
        tusl_scan_count := 0;
        tusl_ordinal := iov$last_robotic_tusl_ordinal;

        get_next_element (selected_element, tusl_ordinal, tusl_scan_count);
        WHILE selected_element <> osc$null_name DO
          FOR candidate_element_index := LOWERBOUND (preferred_elements^)
                TO UPPERBOUND (preferred_elements^) DO
            IF preferred_elements^ [candidate_element_index] = selected_element THEN
              iov$last_robotic_tusl_ordinal := tusl_ordinal;
              EXIT /select_best_element/;
            IFEND;
          FOREND;
          get_next_element (selected_element, tusl_ordinal, tusl_scan_count);
        WHILEND;
      IFEND;

      IF remaining_elements <> NIL THEN
        tusl_scan_count := 0;
        tusl_ordinal := iov$last_robotic_tusl_ordinal;

        get_next_element (selected_element, tusl_ordinal, tusl_scan_count);
        WHILE selected_element <> osc$null_name DO
          FOR candidate_element_index := LOWERBOUND (remaining_elements^)
                TO UPPERBOUND (remaining_elements^) DO
            IF remaining_elements^ [candidate_element_index] = selected_element THEN
              iov$last_robotic_tusl_ordinal := tusl_ordinal;
              EXIT /select_best_element/;
            IFEND;
          FOREND;
          get_next_element (selected_element, tusl_ordinal, tusl_scan_count);
        WHILEND;
      IFEND;

      IF selected_element = osc$null_name THEN
        robotic_element_monopoly := FALSE;
        IF iov$robotic_server_array_p <> NIL THEN
          robotic_element_monopoly := TRUE;
          FOR robotic_server_index := LOWERBOUND (iov$robotic_server_array_p^)
                TO UPPERBOUND (iov$robotic_server_array_p^) DO
            managed_elements_p := iov$robotic_server_array_p^ [robotic_server_index].managed_elements_p;
            IF managed_elements_p <> NIL THEN
              FOR managed_element_index := LOWERBOUND (managed_elements_p^)
                    TO UPPERBOUND (managed_elements_p^) DO
                FOR tusl_ordinal := LOWERBOUND (iov$tusl_p^) TO UPPERBOUND (iov$tusl_p^) DO
                  IF managed_elements_p^ [managed_element_index] = iov$tusl_p^ [tusl_ordinal].
                        element_name THEN
                    robotic_element_monopoly := robotic_element_monopoly AND
                          ((iov$tusl_p^ [tusl_ordinal].assignment_state <> ioc$not_assigned) AND
                          (iov$tusl_p^ [tusl_ordinal].ssn = jmv$jcb.system_name));
                  IFEND;
                FOREND;
              FOREND;
            IFEND;
          FOREND;
        IFEND;

        IF robotic_element_monopoly THEN
          osp$set_status_abnormal (rmc$resource_management_id, rme$robotic_element_monopoly,
                'IOP$SELECT_BEST_ELEMENT', status);
          EXIT /select_best_element/;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
                'IOP$SELECT_BEST_ELEMENT', status);
          EXIT /select_best_element/;
        IFEND;
      IFEND;

    END /select_best_element/;

    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$select_best_element;

?? OLDTITLE ??
?? NEWTITLE := 'iop$server_get_request', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$server_get_request
    (    server_name: ost$name;
         wait: boolean;
     VAR client_request: rmt$rbt_request;
     VAR status: ost$status);

    VAR
      global_task_id: ost$global_task_id,
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry,
      waiting_tasks_index: ost$positive_integers;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /server_get_request/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /server_get_request/;
      IFEND;

      locate_new_request_in_rvl (rvl_p, status);

      IF status.normal THEN
        client_request := rvl_p^.robotic_communication^.client_request;
        rvl_p^.robotic_communication^.server_received_request := TRUE;
      ELSE
        IF wait THEN
          pmp$get_executing_task_gtid (global_task_id);
          FOR waiting_tasks_index := LOWERBOUND (p_robotic_server_entry^.waiting_tasks)
                TO UPPERBOUND (p_robotic_server_entry^.waiting_tasks) DO
            IF p_robotic_server_entry^.waiting_tasks [waiting_tasks_index] = global_task_id THEN
              EXIT /server_get_request/;
            IFEND;
          FOREND;
          FOR waiting_tasks_index := LOWERBOUND (p_robotic_server_entry^.waiting_tasks)
                TO UPPERBOUND (p_robotic_server_entry^.waiting_tasks) DO
            IF p_robotic_server_entry^.waiting_tasks [waiting_tasks_index] = tmv$null_global_task_id THEN
              p_robotic_server_entry^.waiting_tasks [waiting_tasks_index] := global_task_id;
              EXIT /server_get_request/;
            IFEND;
          FOREND;
        IFEND;
      IFEND;

    END /server_get_request/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$server_get_request;

?? OLDTITLE ??
?? NEWTITLE := 'iop$server_put_response', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$server_put_response
    (    server_name: ost$name;
         server_response: iot$formatted_server_response;
     VAR status: ost$status);

    VAR
      element_index: ost$positive_integers,
      ignore_status: ost$status,
      p_robotic_server_entry: ^iot$robotic_server_entry,
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /server_put_response/
    BEGIN
      locate_robotic_server_entry (server_name, p_robotic_server_entry, status);
      IF NOT status.normal THEN
        EXIT /server_put_response/;
      IFEND;

      locate_request_id_in_rvl (server_response.request_id, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /server_put_response/;
      IFEND;

      IF rvl_p^.robotic_communication^.server_name <> server_name THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$request_not_found, 'IOP$SERVER_PUT_RESPONSE',
              status);
        osp$append_status_integer (osc$status_parameter_delimiter, server_response.request_id, radix,
              NOT include_radix, status);
        EXIT /server_put_response/;
      IFEND;

      IF NOT rvl_p^.robotic_communication^.server_received_request THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$premature_server_response,
              'IOP$SERVER_PUT_RESPONSE', status);
        osp$append_status_integer (osc$status_parameter_delimiter, server_response.request_id, radix,
              NOT include_radix, status);
        EXIT /server_put_response/;
      IFEND;

      IF rvl_p^.robotic_communication^.server_response_received THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$redundant_server_response,
              'IOP$SERVER_PUT_RESPONSE', status);
        osp$append_status_integer (osc$status_parameter_delimiter, server_response.request_id, radix,
              NOT include_radix, status);
        EXIT /server_put_response/;
      IFEND;

      rvl_p^.robotic_communication^.server_response := server_response;
      rvl_p^.robotic_communication^.server_response_received := TRUE;

      IF server_response.request_processed THEN
        IF (server_response.processed_request = rmc$rbt_query) AND
              server_response.query.volume_located AND NOT server_response.query.already_mounted THEN
          IF server_response.query.preferred_candidates <> NIL THEN
            ALLOCATE rvl_p^.robotic_communication^.server_response.query.preferred_candidates:
                  [1 .. UPPERBOUND (server_response.query.preferred_candidates^)] IN
                  osv$mainframe_pageable_heap^;
            FOR element_index := LOWERBOUND (server_response.query.preferred_candidates^)
                  TO UPPERBOUND (server_response.query.preferred_candidates^) DO
              rvl_p^.robotic_communication^.server_response.query.preferred_candidates^ [element_index] :=
                    server_response.query.preferred_candidates^ [element_index];
            FOREND;
          IFEND;
          IF server_response.query.remaining_candidates <> NIL THEN
            ALLOCATE rvl_p^.robotic_communication^.server_response.query.remaining_candidates:
                  [1 .. UPPERBOUND (server_response.query.remaining_candidates^)] IN
                  osv$mainframe_pageable_heap^;
            FOR element_index := LOWERBOUND (server_response.query.remaining_candidates^)
                  TO UPPERBOUND (server_response.query.remaining_candidates^) DO
              rvl_p^.robotic_communication^.server_response.query.remaining_candidates^ [element_index] :=
                    server_response.query.remaining_candidates^ [element_index];
            FOREND;
          IFEND;
        IFEND;
      ELSE
        IF server_response.server_messages <> NIL THEN
          ALLOCATE rvl_p^.robotic_communication^.server_response.server_messages IN
                osv$mainframe_pageable_heap^;
          rvl_p^.robotic_communication^.server_response.server_messages^ := server_response.server_messages^;
        ELSE
          rvl_p^.robotic_communication^.server_response.server_messages := NIL;
        IFEND;
      IFEND;

      pmp$ready_task (rvl_p^.robotic_communication^.requesting_task, ignore_status);

    END /server_put_response/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$server_put_response;

?? OLDTITLE ??
?? NEWTITLE := 'iop$set_assignment_in_tusl', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$set_assignment_in_tusl
    (    tusl_ordinal: iot$tusl_ordinal;
         sfid: gft$system_file_identifier;
         ssn: jmt$system_supplied_name;
         external_vsn: rmt$external_vsn;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      clear_mainframe_sig_lock (iov$rvl_lock);
      RETURN;
    IFEND;

  /set_assignment_in_tusl/
    BEGIN
    locate_rvl_entry_by_sfid (sfid, ssn, rvl_p, status);
    IF NOT status.normal THEN
      EXIT /set_assignment_in_tusl/;
    IFEND;

    IF iov$tusl_p^ [tusl_ordinal].tape_unit_state = cmc$on THEN
      IF iov$tusl_p^ [tusl_ordinal].assignment_state = ioc$not_assigned THEN
        IF rvl_p^.operator_assignment_type = ioc$expecting_auto_assignment THEN
          rvl_p^.operator_assignment_type := ioc$expecting_manual_assignment;
        IFEND;
        iov$tusl_p^ [tusl_ordinal].assignment_state := ioc$man_assignment_in_progress;
        iov$tusl_p^ [tusl_ordinal].sfid := rvl_p^.sfid;
        iov$tusl_p^ [tusl_ordinal].evsn := external_vsn;
        iov$tusl_p^ [tusl_ordinal].ssn := rvl_p^.ssn;
        iov$tusl_p^ [tusl_ordinal].path_handle_name := rvl_p^.path_handle_name;
        rvl_p^.assigned_element_name := iov$tusl_p^ [tusl_ordinal].element_name;
        pmp$ready_task (rvl_p^.gtid, ignore_status);
      ELSE
        osp$set_status_abnormal (rmc$resource_management_id, rme$element_name_assigned,
              iov$tusl_p^ [tusl_ordinal].element_name, status);
        EXIT /set_assignment_in_tusl/;
      IFEND;
    ELSE
      osp$set_status_abnormal (rmc$resource_management_id, rme$element_name_not_on,
            iov$tusl_p^ [tusl_ordinal].element_name, status);
      EXIT /set_assignment_in_tusl/;
    IFEND;

    END /set_assignment_in_tusl/;

    clear_mainframe_sig_lock (iov$tusl_lock);
    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$set_assignment_in_tusl;

?? OLDTITLE ??
?? NEWTITLE := 'iop$tape_file_attached', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$tape_file_attached
    (    global_file_name: dmt$global_file_name;
     VAR tape_file_attached: boolean;
     VAR status: ost$status);

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    tape_file_attached := FALSE;
    rvl_p := iov$forward_rvl_p;
  /search_rvl/
    WHILE rvl_p <> NIL DO
      IF rvl_p^.global_file_name = global_file_name THEN
        tape_file_attached := TRUE;
        EXIT /search_rvl/
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND /search_rvl/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$tape_file_attached;

?? OLDTITLE ??
?? NEWTITLE := 'iop$tape_mounts_pending', EJECT ??

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

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    status.normal := TRUE;
    tape_mounts_pending := FALSE;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rvl_p := iov$forward_rvl_p;
  /search/
    WHILE rvl_p <> NIL DO
      IF rvl_p^.vsn_state = ioc$ready_for_assignment THEN
        tape_mounts_pending := TRUE;
        EXIT /search/;
      IFEND;

      rvl_p := rvl_p^.forward_link;
    WHILEND /search/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$tape_mounts_pending;

?? OLDTITLE ??
?? NEWTITLE := 'iop$tape_mount_count', EJECT ??

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

    VAR
      rvl_p: ^iot$requested_vsn_list_entry;

    status.normal := TRUE;
    tape_mount_count := 0;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    tape_mount_count := 0;
    rvl_p := iov$forward_rvl_p;
  /search/
    WHILE rvl_p <> NIL DO
      IF rvl_p^.vsn_state = ioc$ready_for_assignment THEN
        tape_mount_count := tape_mount_count + 1;
      IFEND;
      rvl_p := rvl_p^.forward_link;
    WHILEND /search/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$tape_mount_count;

?? OLDTITLE ??
?? NEWTITLE := 'iop$terminate_assignment', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$terminate_assignment
    (    sfid: gft$system_file_identifier;
         ssn: jmt$system_supplied_name;
         message: string (osc$max_string_size);
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      rvl_p: ^iot$requested_vsn_list_entry;

    set_mainframe_sig_lock ('IOV$RVL_LOCK', iov$rvl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /terminate_assignment/
    BEGIN
      locate_rvl_entry_by_sfid (sfid, ssn, rvl_p, status);
      IF NOT status.normal THEN
        EXIT /terminate_assignment/;
      IFEND;

      IF rvl_p^.vsn_state = ioc$assigned THEN
        IF rvl_p^.current_vsn_p = NIL THEN
          osp$set_status_abnormal (rmc$resource_management_id, rme$volume_already_assigned, ' ', status);
          EXIT /terminate_assignment/;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, rme$volume_already_assigned,
                rvl_p^.current_vsn_p^.evsn, status);
          EXIT /terminate_assignment/;
        IFEND;
      IFEND;

      rvl_p^.assignment_terminated := TRUE;
      rvl_p^.message := message;

      IF rvl_p^.gtid <> tmv$null_global_task_id THEN
        pmp$ready_task (rvl_p^.gtid, ignore_status);
      IFEND;

    END /terminate_assignment/;

    clear_mainframe_sig_lock (iov$rvl_lock);

  PROCEND iop$terminate_assignment;

?? OLDTITLE ??
?? NEWTITLE := 'iop$validate_candidate_element', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$validate_candidate_element
    (    candidate_element: cmt$element_name;
         acceptable_states: set of cmt$element_state;
     VAR status: ost$status);

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    validate_candidate_element (candidate_element, acceptable_states, status);

    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$validate_candidate_element;

?? OLDTITLE ??
?? NEWTITLE := 'iop$write_unlock_tusl_entry', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$write_unlock_tusl_entry
    (    update_entry: boolean;
         tusl_ordinal: iot$tusl_ordinal;
         tusl_entry_template: iot$tape_unit_status_entry;
     VAR status: ost$status);

    set_mainframe_sig_lock ('IOV$TUSL_LOCK', iov$tusl_lock, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF update_entry THEN
      iov$tusl_p^ [tusl_ordinal] := tusl_entry_template;
    IFEND;

    clear_mainframe_sig_lock (iov$tusl_p^ [tusl_ordinal].lock);
    clear_mainframe_sig_lock (iov$tusl_lock);

  PROCEND iop$write_unlock_tusl_entry;

MODEND iom$manage_rvl_tusl_structures;
