?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE File Server: ESM Definition Manager and Malet Interface.' ??
MODULE dfm$esm_definition_manager;

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmt$channel_descriptor
*copyc cmt$data_channel_definition
*copyc cmt$element_definition
*copyc cmt$element_descriptor
*copyc cmt$element_type
*copyc cmt$esm_definition
*copyc cmt$upline_connection
*copyc dfc$esm_allocation_constants
*copyc dfc$iou_names
*copyc dfe$error_condition_codes
*copyc dfi$display
*copyc dfi$log_display
*copyc dft$cpu_queue
*copyc dft$esm_definition_table
*copyc dft$esms_defined
*copyc dft$queue_interface_directory
*copyc osd$integer_limits
*copyc oss$job_paged_literal
*copyc pmt$mainframe_id
?? POP ??
*copyc clp$evaluate_parameters
*copyc cmp$get_channel_definition
*copyc cmp$get_element_definition
*copyc dfp$count_mainframes_per_esm
*copyc dfp$log_side_door_port_status
*copyc dfp$verify_element_name
*copyc dfp$verify_system_administrator
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc pmp$convert_mainframe_to_binary
*copyc pmp$get_mainframe_id
*copyc pmp$zero_out_table
?? EJECT ??
*copyc dfv$file_server_debug_enabled
*copyc dfv$p_esm_definition_table
*copyc dfv$server_wired_heap
*copyc osv$page_size
?? OLDTITLE ??
?? NEWTITLE := 'dfp$any_esm_defined', EJECT ??

{ PURPOSE:
{   Determine if there is a STORNET/ESM connection defined on this mainframe.

  FUNCTION [XDCL] dfp$any_esm_defined: boolean;

    dfp$any_esm_defined := dfv$p_esm_definition_table <> NIL;

  FUNCEND dfp$any_esm_defined;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$any_sdp_defined', EJECT ??

{ PURPOSE:
{   Determine if there is a STORNET/ESM side door port defined on this mainframe.  This is used by side door
{   port logging.

  PROCEDURE [XDCL] dfp$any_sdp_defined
    (VAR any_sdp_defined: boolean);

    VAR
      current_mainframe_id: pmt$mainframe_id,
      ignore_status: ost$status,
      p_esm_table_entry: ^dft$esm_definition_table_entry,
      side_door_port_index: 1 .. cmc$max_side_door_port_number;

    any_sdp_defined := FALSE;
    pmp$get_mainframe_id (current_mainframe_id, ignore_status);
    p_esm_table_entry := dfv$p_esm_definition_table;

  /for_all_defined_stornets/
    WHILE p_esm_table_entry <> NIL DO

    /determine_if_side_door_port/
      FOR side_door_port_index := 1 TO cmc$max_side_door_port_number DO
        IF (p_esm_table_entry^.p_side_door_ports [side_door_port_index] <> NIL) AND
              (p_esm_table_entry^.p_side_door_ports [side_door_port_index]^.mainframe_id =
              current_mainframe_id) THEN
          any_sdp_defined := TRUE;
          RETURN;
        IFEND;
      FOREND /determine_if_side_door_port/;
      p_esm_table_entry := p_esm_table_entry^.p_next_table_entry;
    WHILEND /for_all_defined_stornets/;
  PROCEND dfp$any_sdp_defined;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$define_esm_command ', EJECT ??

  PROCEDURE [XDCL, #GATE] dfp$define_esm_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      current_mainframe_id: pmt$mainframe_id,
      esm_parameters: dft$esm_specifications,
      port: integer;

    status.normal := TRUE;
    dfp$verify_system_administrator ('DEFINE_STORNET_CONNECTION', status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF osv$page_size < dfc$command_buffer_size THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$page_size_too_small, '', status);
      RETURN;
    IFEND;

    crack_esm_parameters (parameter_list, esm_parameters, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    create_esm_def_table_entry (esm_parameters, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pmp$get_mainframe_id (current_mainframe_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

   /start_side_door_port_logging/
    FOR port := 1 TO esm_parameters.side_door_ports.number DO
      IF esm_parameters.side_door_ports.ports [port].mainframe_id = current_mainframe_id THEN
        IF dfv$file_server_debug_enabled THEN
          display ('SIDE DOOR PORT LOGGING INITIATED');
        IFEND;
        log_display ($pmt$ascii_logset [pmc$system_log, pmc$job_log], 'SIDE DOOR PORT LOGGING INITIATED');
        dfp$log_side_door_port_status (dfc$sdp_initialization, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        EXIT /start_side_door_port_logging/;
      IFEND;
    FOREND;

  PROCEND dfp$define_esm_command;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$delete_esm_command ', EJECT ??
  PROCEDURE [XDCL, #GATE] dfp$delete_esm_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE delete_stornet_connection, delsc (
{   element_name, en: name = $required
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??
  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 3] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type2: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [91, 9, 4, 11, 16, 39, 267],
    clc$command, 3, 2, 1, 0, 0, 0, 2, ''], [
    ['ELEMENT_NAME                   ',clc$nominal_entry, 1],
    ['EN                             ',clc$abbreviation_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 2]],
    [
{ PARAMETER 1
    [1, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 5, clc$required_parameter, 0
  , 0],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 2
    [[1, 0, clc$status_type]]];
?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$element_name = 1,
      p$status = 2;

    VAR
      pvt: array [1 .. 2] of clt$parameter_value;

    VAR
      any_side_door_port_defined: boolean,
      element_name: cmt$element_name;

    status.normal := TRUE;
    dfp$verify_system_administrator ('DELETE_STORNET_CONNECTION', status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    dfp$any_sdp_defined (any_side_door_port_defined);

    IF any_side_door_port_defined THEN
      IF dfv$file_server_debug_enabled THEN
        display ('SIDE DOOR PORT LOGGING TERMINATED');
      IFEND;
      log_display ($pmt$ascii_logset [pmc$system_log, pmc$job_log], 'SIDE DOOR PORT LOGGING TERMINATED');
    IFEND;

    element_name := pvt [p$element_name].value^.name_value;
    delete_esm_def_table_entry (element_name, status);

  PROCEND dfp$delete_esm_command;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$locate_esm_definition', EJECT ??

{ PURPOSE:
{   This procedures scans the ESM_DEFINITION_TABLE looking for a match on ELEMENT_NAME. If the element is
{   found in the table then ESM_TABLE_ENTRY_P contains the pointer to the matched table entry.  If the
{   element name is not found in the table then the pointer is returned with a NIL value.

  PROCEDURE [XDCL] dfp$locate_esm_definition
    (    esm_name: cmt$element_name;
     VAR esm_table_entry_p: ^dft$esm_definition_table_entry);

    VAR
      current_esm_table_entry_p: ^dft$esm_definition_table_entry;

    esm_table_entry_p := NIL;
    current_esm_table_entry_p := dfv$p_esm_definition_table;
    WHILE current_esm_table_entry_p <> NIL DO
      IF current_esm_table_entry_p^.element_name = esm_name THEN
        esm_table_entry_p := current_esm_table_entry_p;
        RETURN;
      IFEND;
      current_esm_table_entry_p := current_esm_table_entry_p^.p_next_table_entry;
    WHILEND;

  PROCEND dfp$locate_esm_definition;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$return_esm_base_addresses ', EJECT ??

{ PURPOSE:
{   This procedure pulls ESM base addresses from ESM_DEFINITION_TABLE and returns this record to the caller.

  PROCEDURE [XDCL] dfp$return_esm_base_addresses
    (    element: cmt$element_name;
     VAR esm_base_addresses: dft$esm_base_addresses;
     VAR status: ost$status);

    VAR
      esm_def_table_entry_p: ^dft$esm_definition_table_entry;

    status.normal := TRUE;
    dfp$locate_esm_definition (element, esm_def_table_entry_p);
    IF esm_def_table_entry_p = NIL THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_not_defined, element, status);
      RETURN;
    IFEND;

    esm_base_addresses := esm_def_table_entry_p^.esm_base_addresses;

  PROCEND dfp$return_esm_base_addresses;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$return_esm_definition ', EJECT ??
  PROCEDURE [XDCL, #GATE] dfp$return_esm_definition
    (    element: cmt$element_descriptor;
     VAR definition: cmt$esm_definition;
     VAR status: ost$status);

    VAR
      channel_configured: boolean,
      element_definition: cmt$element_definition,
      low_speed_port_index: 1 .. cmc$max_low_speed_port_number,
      mainframe_name: pmt$mainframe_id,
      p_esm_def_table_entry: ^dft$esm_definition_table_entry,
      port_number: cmt$communications_port_number,
      side_door_port: boolean,
      side_door_port_index: 1 .. cmc$max_side_door_port_number;

{------------------------------------------------------------------------
{  This procedure pulls information about ESM from CM ELEMENT_DEFINITION
{  and DF ESM_DEFINITION tables and returns it to the caller.
{------------------------------------------------------------------------

    status.normal := TRUE;

{   Get the channel/mainframe_id array for the element.
    cmp$get_element_definition (element, element_definition, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{   Verify that the specified element is the ESM product.
    dfp$verify_esm_product_id (element_definition.product_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{   Get the location of ESM_DEFINITION_TABLE.
    dfp$locate_esm_definition (element_definition.element_name, p_esm_def_table_entry);
    IF p_esm_def_table_entry = NIL THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_not_defined, element_definition.
           element_name, status);
      RETURN;
    IFEND;

{   Initialize all ports to NOT CONFIGURED.
    FOR side_door_port_index := 1 TO cmc$max_side_door_port_number DO
      definition.side_door_port [side_door_port_index].configured := FALSE;
    FOREND;
    FOR port_number := 1 TO cmc$max_low_speed_port_number DO
      definition.low_speed_port [port_number].configured := FALSE;
    FOREND;

    definition.element_name := element_definition.element_name;
    definition.product_id := element_definition.product_id;
    definition.serial_number := element_definition.serial_number;
    definition.peripheral_driver_name := element_definition.communications_element.peripheral_driver_name;
    definition.memory_size := p_esm_def_table_entry^.memory_size;
    definition.maintenance_buffer_location := p_esm_def_table_entry^.maintenance_buffer_loc;

    channel_configured := FALSE;
    low_speed_port_index := 1;
  /get_channel_info/
    FOR port_number := LOWERVALUE (cmt$communications_port_number)
          TO UPPERVALUE (cmt$communications_port_number) DO
      IF element_definition.communications_element.connection.port [port_number].configured THEN
        channel_configured := TRUE;

        side_door_port := FALSE;

      /determine_if_side_door_port/
        FOR side_door_port_index := 1 to cmc$max_side_door_port_number DO
          IF p_esm_def_table_entry^.p_side_door_ports [side_door_port_index] = NIL THEN
            EXIT /determine_if_side_door_port/;

          ELSE
            IF (p_esm_def_table_entry^.p_side_door_ports [side_door_port_index]^.channel_name =
                    element_definition.communications_element.connection.port [port_number].element_name) AND
              (p_esm_def_table_entry^.p_side_door_ports [side_door_port_index]^.mainframe_id =
                    element_definition.communications_element.connection.port [port_number].
                    mainframe_ownership) THEN
              definition.side_door_port [side_door_port_index] := element_definition.communications_element.
                   connection.port [port_number];
              side_door_port := TRUE;
              EXIT /determine_if_side_door_port/;
            IFEND;
          IFEND;
        FOREND /determine_if_side_door_port/;

        IF NOT side_door_port THEN
          IF low_speed_port_index = cmc$max_low_speed_port_number THEN
            osp$set_status_abnormal (dfc$file_server_id, dfe$too_many_low_speed_ports,
                 element_definition.element_name, status);
            RETURN;
          IFEND;
          definition.low_speed_port [low_speed_port_index] := element_definition.communications_element.
               connection.port [port_number];
          low_speed_port_index := low_speed_port_index + 1;
        IFEND;
      IFEND;
    FOREND /get_channel_info/;

    IF NOT channel_configured THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$no_configured_channel,
           element_definition.element_name, status);
      RETURN;
    IFEND;

  PROCEND dfp$return_esm_definition;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$return_esms_defined ', EJECT ??

{ PURPOSE:
{   This procedure returns all STORNET/ESM element names defined on this mainframe.

  PROCEDURE [XDCL] dfp$return_esms_defined
    (VAR esms_defined: dft$esms_defined_count;
     VAR esm_name_array: dft$esms_defined);

    VAR
      p_esm_table_entry: ^dft$esm_definition_table_entry;

    esms_defined := 0;
    p_esm_table_entry := dfv$p_esm_definition_table;
    WHILE p_esm_table_entry <> NIL DO
      esms_defined := esms_defined + 1;
      IF esms_defined <= UPPERBOUND (esm_name_array) THEN
        esm_name_array [esms_defined] := p_esm_table_entry^.element_name;
      IFEND;
      p_esm_table_entry := p_esm_table_entry^.p_next_table_entry;
    WHILEND;

  PROCEND dfp$return_esms_defined;
?? OLDTITLE ??
?? NEWTITLE := 'dfp$verify_esm_product_id ', EJECT ??

  PROCEDURE [XDCL, #GATE] dfp$verify_esm_product_id
    (    product_id: cmt$product_identification;
     VAR status: ost$status);

    VAR
      esm2_product_id: [READ, OSS$JOB_PAGED_LITERAL] cmt$product_identification :=
         [' $7040', '_', '200'],
      stornet_product_id: [READ, OSS$JOB_PAGED_LITERAL] cmt$product_identification :=
         [' $5380', '_', '100'];

    status.normal := TRUE;
    IF product_id = esm2_product_id THEN

      { Valid ESM product identification, DO NOTHING.

    ELSEIF product_id = stornet_product_id THEN

      { Valid ESM product identification, DO NOTHING.

    ELSE {invalid ESM product identification.}
      osp$set_status_abnormal (dfc$file_server_id, dfe$invalid_stornet_product_id, product_id.product_number,
            status);
      osp$append_status_parameter (osc$status_parameter_delimiter, product_id.model_number, status);
    IFEND;

  PROCEND dfp$verify_esm_product_id;
?? OLDTITLE ??
?? NEWTITLE := 'calculate_division_size ', EJECT ??

{ PURPOSE:
{   This procedure calculates the size of the ESM division so that
{    1. ESM division size is a multiple of 100 octal 60 bit ESM words.
{    2. The ESM starting address of both the Command record and the Data record is a multiple of 10 octal 60
{       bit ESM words.
{    3. The space provided for the Data record within the division is at least three ESM 8 word records larger
{       than what is required for the data, and the division size is a multiple of 8 ESM words (ESM records).
{       The extra division space is necessary so that the driver can write beyond what is actually required to
{       clear ESM memory parity errors caused by power loss. Because ESM reads ahead, any parity error beyond
{       the real data will be detected.
{
{   The maximum_data_bytes field of the esm_specifications record is the number of bytes which will fit into
{   the Data record. This value may be specified as the input parameter requested_data_bytes. If a value of
{   zero is specified, the largest value which will fit within the available ESM space and which meets the
{   following criteria will be calculated.  The value of maximum_data_bytes must be within the range of
{   (dfc$min_data_record_bytes * 4 .. dfc$max_data_record_bytes), and values in between must be equal to
{   (dfc$min_data_record_bytes * 4) times a power of 2 multiplier.
{
{     The following values are stored into the ESM_SPECIFICATIONS record :
{
{     MAXIMUM_DATA_BYTES   - The maximum number of data bytes which may be sent/received by this machine in a
{                            single File Server transaction.
{
{     ESM_DIVISION_SIZE    - The number of 60 bit ESM words divided by 100 octal per ESM division.
{
{     ESM_DIVSIZ_12BIT_CW  - The ESM division size in 12 bit channel words divided by 100 octal.
{
{     ESM_DIVSIZ_16BIT_CW  - The ESM division size in 16 bit channel words divided by 100 octal.

  PROCEDURE calculate_division_size
    (    requested_data_bytes: 0 .. dfc$max_data_record_bytes;
     VAR esm_specifications: dft$esm_specifications;
     VAR status: ost$status);

    VAR
      base_esm_address: 0 .. dfc$max_esm_memory_size,
      data_record_bytes: 0 .. dfc$max_data_record_bytes,
      division_size: integer,
      division_space: integer,
      esm_space: integer,
      esm_space_per_mf: integer,
      number_of_divisions: 1 .. dfc$max_esm_divisions,
      number_of_mainframes: 1 .. dfc$max_number_of_mainframes,
      total_required: integer;

    status.normal := TRUE;

    number_of_divisions := esm_specifications.esm_base_addresses.divisions_per_mainframe;
    number_of_mainframes := esm_specifications.esm_base_addresses.number_of_mainframes;
    base_esm_address := (esm_specifications.esm_base_addresses.esm_memory_base * dfc$esm_memory_base_shift);
    esm_space := (esm_specifications.memory_size - base_esm_address) - dfc$esm_maintenance_buf_size;
    esm_space_per_mf := esm_space DIV number_of_mainframes;
    division_space := esm_space_per_mf DIV number_of_divisions;

    IF requested_data_bytes > 0 THEN
      data_record_bytes := requested_data_bytes;
      division_size := ((((((((data_record_bytes * 8) DIV 60) + 7 + dfc$division_overwrite_words) DIV 8) * 8)
          + (dfc$esm_command_record_size + dfc$esm_header_record_size)) + dfc$esm_memory_base_shift-1)
          DIV dfc$esm_memory_base_shift) * dfc$esm_memory_base_shift;

    ELSE
      data_record_bytes := dfc$max_data_record_bytes;
      WHILE ((((((((data_record_bytes * 8) DIV 60) + 7 + dfc$division_overwrite_words) DIV 8) * 8) +
             (dfc$esm_command_record_size + dfc$esm_header_record_size)) + dfc$esm_memory_base_shift-1)
              DIV dfc$esm_memory_base_shift) * dfc$esm_memory_base_shift > division_space DO
        data_record_bytes := data_record_bytes DIV 2;
      WHILEND;
      IF data_record_bytes < dfc$min_data_record_bytes THEN
        data_record_bytes := dfc$min_data_record_bytes;
      IFEND;
      division_size := ((((((((data_record_bytes * 8) DIV 60) + 7 + dfc$division_overwrite_words) DIV 8) * 8)
          + (dfc$esm_command_record_size + dfc$esm_header_record_size)) + dfc$esm_memory_base_shift-1)
          DIV dfc$esm_memory_base_shift) * dfc$esm_memory_base_shift;
    IFEND;

    IF division_size > division_space THEN

      { Not enough ESM space for requested Data Transfer Size.

      total_required := (division_size * esm_specifications.esm_base_addresses.divisions_per_mainframe) *
            esm_specifications.esm_base_addresses.number_of_mainframes;
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_memory_surpassed, '', status);
      osp$append_status_integer (osc$status_parameter_delimiter, total_required, 10, FALSE, status);
      osp$append_status_integer (osc$status_parameter_delimiter,
            esm_specifications.esm_base_addresses.esm_memory_base * dfc$esm_memory_base_shift, 10, FALSE,
            status);
      osp$append_status_integer (osc$status_parameter_delimiter, esm_specifications.memory_size, 10, FALSE,
            status);
      RETURN;
    IFEND;

    esm_specifications.maximum_data_bytes := data_record_bytes;
    esm_specifications.esm_base_addresses.esm_division_size := division_size DIV dfc$esm_memory_base_shift;

    { Calculate number of channel words per ESM division for PP driver.

    esm_specifications.esm_base_addresses.esm_divsiz_12bit_cw :=
          ((division_size * 60) DIV 12) DIV dfc$esm_division_chwrds_shift;
    esm_specifications.esm_base_addresses.esm_divsiz_16bit_cw :=
          ((division_size * 60) DIV 16) DIV dfc$esm_division_chwrds_shift;

  PROCEND calculate_division_size;
?? OLDTITLE ??
?? NEWTITLE := 'crack_esm_parameters ', EJECT ??

{ PURPOSE:
{   This procedure cracks the command parameters.

  PROCEDURE crack_esm_parameters
    (    parameter_list: clt$parameter_list;
     VAR esm_parameters: dft$esm_specifications;
     VAR status: ost$status);

{ PROCEDURE define_stornet_connection, defsc (
{   element_name, en: name = $required
{   memory_size, ms: integer dfc$min_esm_memory_size .. dfc$max_esm_memory_size = 4194304
{   memory_base, mb: integer 0 .. dfc$max_esm_memory_base = 0
{   flag_base, fb: integer  0 ..16000 = 0
{   half_ecs_switch, hes: boolean = FALSE
{   number_of_mainframes, nom: integer 1 .. dfc$max_number_of_mainframes = 2
{   divisions_per_mainframe, dpm: integer 1 .. dfc$max_esm_divisions = 8
{   data_transfer_size, dts: key #16K, #32K, #65K, #131K, #262K keyend = #16K
{   side_door_port, side_door_ports, sdp: list 1 .. 2 of list 1 .. 3 of name
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??
  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 20] of clt$pdt_parameter_name,
      parameters: array [1 .. 10] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$name_type_qualifier,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (7),
      recend,
      type3: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type4: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type5: record
        header: clt$type_specification_header,
        default_value: string (5),
      recend,
      type6: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type7: record
        header: clt$type_specification_header,
        qualifier: clt$integer_type_qualifier,
        default_value: string (1),
      recend,
      type8: record
        header: clt$type_specification_header,
        qualifier: clt$keyword_type_qualifier,
        keyword_specs: array [1 .. 5] of clt$keyword_specification,
        default_value: string (4),
      recend,
      type9: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier_v2,
        element_type_spec: record
          header: clt$type_specification_header,
          qualifier: clt$list_type_qualifier_v2,
          element_type_spec: record
            header: clt$type_specification_header,
            qualifier: clt$name_type_qualifier,
          recend,
        recend,
      recend,
      type10: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [91, 9, 19, 8, 31, 3, 858],
    clc$command, 20, 10, 1, 0, 0, 0, 10, ''], [
    ['DATA_TRANSFER_SIZE             ',clc$nominal_entry, 8],
    ['DIVISIONS_PER_MAINFRAME        ',clc$nominal_entry, 7],
    ['DPM                            ',clc$abbreviation_entry, 7],
    ['DTS                            ',clc$abbreviation_entry, 8],
    ['ELEMENT_NAME                   ',clc$nominal_entry, 1],
    ['EN                             ',clc$abbreviation_entry, 1],
    ['FB                             ',clc$abbreviation_entry, 4],
    ['FLAG_BASE                      ',clc$nominal_entry, 4],
    ['HALF_ECS_SWITCH                ',clc$nominal_entry, 5],
    ['HES                            ',clc$abbreviation_entry, 5],
    ['MB                             ',clc$abbreviation_entry, 3],
    ['MEMORY_BASE                    ',clc$nominal_entry, 3],
    ['MEMORY_SIZE                    ',clc$nominal_entry, 2],
    ['MS                             ',clc$abbreviation_entry, 2],
    ['NOM                            ',clc$abbreviation_entry, 6],
    ['NUMBER_OF_MAINFRAMES           ',clc$nominal_entry, 6],
    ['SDP                            ',clc$abbreviation_entry, 9],
    ['SIDE_DOOR_PORT                 ',clc$nominal_entry, 9],
    ['SIDE_DOOR_PORTS                ',clc$alias_entry, 9],
    ['STATUS                         ',clc$nominal_entry, 10]],
    [
{ PARAMETER 1
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 5, clc$required_parameter, 0
  , 0],
{ PARAMETER 2
    [13, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 7],
{ PARAMETER 3
    [12, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 4
    [8, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 5
    [9, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 5],
{ PARAMETER 6
    [16, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 7
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 20,
  clc$optional_default_parameter, 0, 1],
{ PARAMETER 8
    [1, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 192,
  clc$optional_default_parameter, 0, 4],
{ PARAMETER 9
    [18, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 37, clc$optional_parameter,
  0, 0],
{ PARAMETER 10
    [20, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$name_type], [1, osc$max_name_size]],
{ PARAMETER 2
    [[1, 0, clc$integer_type], [dfc$min_esm_memory_size, dfc$max_esm_memory_size, 10],
    '4194304'],
{ PARAMETER 3
    [[1, 0, clc$integer_type], [0, dfc$max_esm_memory_base, 10],
    '0'],
{ PARAMETER 4
    [[1, 0, clc$integer_type], [0, 16000, 10],
    '0'],
{ PARAMETER 5
    [[1, 0, clc$boolean_type],
    'FALSE'],
{ PARAMETER 6
    [[1, 0, clc$integer_type], [1, dfc$max_number_of_mainframes, 10],
    '2'],
{ PARAMETER 7
    [[1, 0, clc$integer_type], [1, dfc$max_esm_divisions, 10],
    '8'],
{ PARAMETER 8
    [[1, 0, clc$keyword_type], [5], [
    ['#131K                          ', clc$nominal_entry, clc$normal_usage_entry, 4],
    ['#16K                           ', clc$nominal_entry, clc$normal_usage_entry, 1],
    ['#262K                          ', clc$nominal_entry, clc$normal_usage_entry, 5],
    ['#32K                           ', clc$nominal_entry, clc$normal_usage_entry, 2],
    ['#65K                           ', clc$nominal_entry, clc$normal_usage_entry, 3]]
    ,
    '#16K'],
{ PARAMETER 9
    [[1, 0, clc$list_type], [21, 1, 2, 0, FALSE, FALSE],
      [[1, 0, clc$list_type], [5, 1, 3, 0, FALSE, FALSE],
        [[1, 0, clc$name_type], [1, osc$max_name_size]]
      ]
    ],
{ PARAMETER 10
    [[1, 0, clc$status_type]]];
?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$element_name = 1,
      p$memory_size = 2,
      p$memory_base = 3,
      p$flag_base = 4,
      p$half_ecs_switch = 5,
      p$number_of_mainframes = 6,
      p$divisions_per_mainframe = 7,
      p$data_transfer_size = 8,
      p$side_door_port = 9,
      p$status = 10;

    VAR
      pvt: array [1 .. 10] of clt$parameter_value;

    VAR
      ignore_binary_id: pmt$binary_mainframe_id,
      index: 1 .. cmc$max_side_door_port_number,
      list_1_p: ^clt$data_value,
      list_2_p: ^clt$data_value,
      mainframe_name: pmt$mainframe_id,
      requested_data_bytes: 0 .. dfc$max_data_record_bytes;

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Verify that the specified element is the ESM product.

    esm_parameters.element_name := pvt [p$element_name].value^.name_value;
    dfp$verify_element_name (esm_parameters.element_name, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    esm_parameters.memory_size := pvt [p$memory_size].value^.integer_value.value;
    IF (esm_parameters.memory_size DIV 1000(8)) * 1000(8) <> esm_parameters.memory_size THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$invalid_base_address, 'MEMORY_SIZE', status);
      RETURN;
    IFEND;

    esm_parameters.half_ecs_switch := pvt [p$half_ecs_switch].value^.boolean_value.value;
    IF esm_parameters.half_ecs_switch THEN
      esm_parameters.memory_size := esm_parameters.memory_size DIV 2;
    ELSE
      IF esm_parameters.memory_size > dfc$max_driver_formed_esm_adrs + 1 THEN
        osp$set_status_abnormal (dfc$file_server_id, dfe$driver_cannot_form_adrs, '', status);
        RETURN;
      IFEND;
    IFEND;

    esm_parameters.esm_base_addresses.esm_flag_base := pvt [p$flag_base].value^.integer_value.value;
    esm_parameters.esm_base_addresses.number_of_mainframes :=
          pvt [p$number_of_mainframes].value^.integer_value.value;
    esm_parameters.esm_base_addresses.divisions_per_mainframe :=
          pvt [p$divisions_per_mainframe].value^.integer_value.value;

    IF (pvt [p$memory_base].value^.integer_value.value DIV 1000(8)) * 1000(8) <>
          pvt [p$memory_base].value^.integer_value.value THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$invalid_base_address, 'MEMORY_BASE', status);
      RETURN;
    IFEND;
    esm_parameters.esm_base_addresses.esm_memory_base :=
          pvt [p$memory_base].value^.integer_value.value DIV dfc$esm_memory_base_shift;

    esm_parameters.maintenance_buffer_loc.length := dfc$esm_maintenance_buf_size;

    IF NOT pvt [p$data_transfer_size].specified THEN
      requested_data_bytes := 0;
    ELSE
      IF pvt [p$data_transfer_size].value^.keyword_value = '#16K' THEN
        requested_data_bytes := dfc$min_data_record_bytes;
      ELSEIF pvt [p$data_transfer_size].value^.keyword_value = '#32K' THEN
        requested_data_bytes := dfc$min_data_record_bytes * 2;
      ELSEIF pvt [p$data_transfer_size].value^.keyword_value = '#65K' THEN
        requested_data_bytes := dfc$min_data_record_bytes * 4;
      ELSEIF pvt [p$data_transfer_size].value^.keyword_value = '#131K' THEN
        requested_data_bytes := dfc$min_data_record_bytes * 8;
      ELSEIF pvt [p$data_transfer_size].value^.keyword_value = '#262K' THEN
        requested_data_bytes := dfc$min_data_record_bytes * 16;
      ELSE
        requested_data_bytes := 0;
      IFEND;
    IFEND;

    calculate_division_size (requested_data_bytes, esm_parameters, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    esm_parameters.maintenance_buffer_loc.first_word_address :=
          ((esm_parameters.esm_base_addresses.number_of_mainframes *
          esm_parameters.esm_base_addresses.divisions_per_mainframe) *
          (esm_parameters.esm_base_addresses.esm_division_size * dfc$esm_memory_base_shift)) +
          (esm_parameters.esm_base_addresses.esm_memory_base * dfc$esm_memory_base_shift);

    { Side_door_ports is an optional parameter and is a list of lists.  Maximum number of side door ports that
    { may appear on the DEFINE_STORNET_CONNECTION command is cmc$max_side_door_port_number.  Within each
    { side_door_port specification is a list of three names: channel name, mainframe name and iou name. Only
    { channel name is required to define side_door_port. Iou name defaults to IOU0, and mainframe name
    { defaults to the mainframe_id of the machine on which the procedure executes.

    esm_parameters.side_door_ports.number := 0;
    IF pvt [p$side_door_port].specified THEN
      pmp$get_mainframe_id (mainframe_name, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      list_1_p := pvt [p$side_door_port].value;
      WHILE list_1_p <> NIL DO
        esm_parameters.side_door_ports.number := esm_parameters.side_door_ports.number + 1;
        index := esm_parameters.side_door_ports.number;
        list_2_p := list_1_p^.element_value;
        list_1_p := list_1_p^.link;

        { Get channel_name. This is the mandatory name for the side_door_port.

        esm_parameters.side_door_ports.ports [index].channel_name := list_2_p^.element_value^.name_value;
        list_2_p := list_2_p^.link;

        IF list_2_p = NIL THEN
          esm_parameters.side_door_ports.ports [index].mainframe_id := mainframe_name;
        ELSE
          esm_parameters.side_door_ports.ports [index].mainframe_id := list_2_p^.element_value^.name_value;
          pmp$convert_mainframe_to_binary (esm_parameters.side_door_ports.ports [index].mainframe_id,
                ignore_binary_id, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          list_2_p := list_2_p^.link;
        IFEND;

        IF list_2_p = NIL THEN
          esm_parameters.side_door_ports.ports [index].iou_name := dfc$iou_name0;
        ELSE
          IF (list_2_p^.element_value^.name_value <> dfc$iou_name0) AND
                (list_2_p^.element_value^.name_value <> dfc$iou_name1) THEN
            osp$set_status_abnormal (dfc$file_server_id, dfe$side_door_iou_name_err,
                  list_2_p^.element_value^.name_value, status);
            RETURN;
          IFEND;
          esm_parameters.side_door_ports.ports [index].iou_name := list_2_p^.element_value^.name_value;
        IFEND;

        verify_esm_configured (esm_parameters.element_name, esm_parameters.side_door_ports.ports [index],
              mainframe_name, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      WHILEND;
    IFEND;

  PROCEND crack_esm_parameters;
?? OLDTITLE ??
?? NEWTITLE := 'create_esm_def_table_entry ', EJECT ??

{ PURPOSE:
{   The purpose of this routine is to allocate esm_definition_table entry, to initialize it, and to link it
{   to the previous entry in the table.

  PROCEDURE create_esm_def_table_entry
    (    esm_parameters: dft$esm_specifications;
     VAR status: ost$status);

    VAR
      current_esm_table_entry_p: ^dft$esm_definition_table_entry,
      last_esm_table_entry_p: ^dft$esm_definition_table_entry,
      port_index: 1 .. cmc$max_side_door_port_number;

    status.normal := TRUE;

    { Make sure that this ESM is not allocated already.

    dfp$locate_esm_definition (esm_parameters.element_name, current_esm_table_entry_p);
    IF current_esm_table_entry_p <> NIL THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_already_defined, esm_parameters.element_name,
           status);
      RETURN;
    IFEND;

    { Allocate new table entry.

    ALLOCATE current_esm_table_entry_p IN dfv$server_wired_heap^;
    IF current_esm_table_entry_p = NIL THEN
      osp$system_error ('NIL current_esm_table_entry_p.', NIL);
    IFEND;

    current_esm_table_entry_p^.element_name := esm_parameters.element_name;
    current_esm_table_entry_p^.memory_size := esm_parameters.memory_size;
    current_esm_table_entry_p^.half_ecs_switch := esm_parameters.half_ecs_switch;
    current_esm_table_entry_p^.esm_base_addresses := esm_parameters.esm_base_addresses;
    current_esm_table_entry_p^.maximum_data_bytes := esm_parameters.maximum_data_bytes;
    current_esm_table_entry_p^.maintenance_buffer_loc := esm_parameters.maintenance_buffer_loc;
    current_esm_table_entry_p^.number_of_pps_using_esm := 0;
    current_esm_table_entry_p^.p_element_reservation := NIL;
    current_esm_table_entry_p^.p_next_table_entry := NIL;

    { Move side_door_port information into table entry.

    FOR port_index := 1 to cmc$max_side_door_port_number DO
      current_esm_table_entry_p^.p_side_door_ports [port_index] := NIL;
    FOREND;
    IF esm_parameters.side_door_ports.number <> 0 THEN
      FOR port_index := 1 TO esm_parameters.side_door_ports.number DO
        ALLOCATE current_esm_table_entry_p^.p_side_door_ports [port_index] IN dfv$server_wired_heap^;
        IF current_esm_table_entry_p^.p_side_door_ports [port_index] = NIL THEN
          osp$system_error ('NIL p_side_door_ports.', NIL);
        IFEND;
        current_esm_table_entry_p^.p_side_door_ports [port_index]^ :=
              esm_parameters.side_door_ports.ports [port_index];
      FOREND;
    IFEND;

    { Link the new entry to the previous one.

    get_last_esm_definition (last_esm_table_entry_p);
    IF last_esm_table_entry_p <> NIL THEN
      last_esm_table_entry_p^.p_next_table_entry := current_esm_table_entry_p;
    ELSE
      dfv$p_esm_definition_table := current_esm_table_entry_p;
    IFEND;

  PROCEND create_esm_def_table_entry;
?? OLDTITLE ??
?? NEWTITLE := 'delete_esm_def_table_entry ', EJECT ??

{ PURPOSE:
{   The purpose of this routine is to find and delete the ESM table entry for the ESM element name specified
{   on input. The remaining entries are re-linked.

  PROCEDURE delete_esm_def_table_entry
    (    esm_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      current_esm_table_entry_p: ^dft$esm_definition_table_entry,
      mainframe_count: 0 .. dfc$max_number_of_mainframes,
      previous_esm_table_entry_p: ^dft$esm_definition_table_entry;

    status.normal := TRUE;

    { Make sure that this ESM is defined.

    get_esm_definition_pointers (esm_name, current_esm_table_entry_p, previous_esm_table_entry_p);
    IF current_esm_table_entry_p = NIL THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_not_defined, esm_name, status);
      RETURN;
    IFEND;

    { Make sure there are neither Clients nor Servers are defined with this ESM element.

    dfp$count_mainframes_per_esm (esm_name, mainframe_count);
    IF mainframe_count <> 0 THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$stornet_has_mainframes, esm_name, status);
      RETURN;
    IFEND;

    { Relink the ESM_Definition_Table entries.

    IF previous_esm_table_entry_p <> NIL THEN
      previous_esm_table_entry_p^.p_next_table_entry := current_esm_table_entry_p^.p_next_table_entry;
    ELSE
      dfv$p_esm_definition_table := current_esm_table_entry_p^.p_next_table_entry;
    IFEND;

    { De-allocate the old entry.

    FREE current_esm_table_entry_p IN dfv$server_wired_heap^;

  PROCEND delete_esm_def_table_entry;
?? OLDTITLE ??
?? NEWTITLE := 'get_esm_definition_pointers', EJECT ??

{ PURPOSE:
{   This procedures scans the ESM_DEFINITION_TABLE looking for a match on ESM element_name. If the element is
{   found in the table then CURRENT_ESM_TABLE_ENTRY_P contains the pointer to the matched table entry and the
{   PREVIOUS_ESM_TABLE_ENTRY_P contains the pointer to the previous entry. If current_esm_table_entry_p is not
{   NIL and the previous_esm_table_entry_p is NIL then the found entry is the first one in the list.  If the
{   element name is not found in the table then current_esm_table_entry_p is returned with NIL value and
{   previous_esm_table_entry_p points to the last entry in the table.

  PROCEDURE get_esm_definition_pointers
    (    esm_name: cmt$element_name;
     VAR current_esm_table_entry_p: ^dft$esm_definition_table_entry;
     VAR previous_esm_table_entry_p: ^dft$esm_definition_table_entry);

    current_esm_table_entry_p := NIL;
    previous_esm_table_entry_p := NIL;
    IF dfv$p_esm_definition_table <> NIL THEN
      current_esm_table_entry_p := dfv$p_esm_definition_table;
      REPEAT
        IF current_esm_table_entry_p^.element_name = esm_name THEN
          RETURN;
        IFEND;
        previous_esm_table_entry_p := current_esm_table_entry_p;
        current_esm_table_entry_p := current_esm_table_entry_p^.p_next_table_entry;
      UNTIL current_esm_table_entry_p = NIL;
    IFEND;

  PROCEND get_esm_definition_pointers;
?? OLDTITLE ??
?? NEWTITLE := 'get_last_esm_definition', EJECT ??

{ PURPOSE:
{   This procedures scans the ESM_DEFINITION_TABLE entries examining the pointers to the next table entry. The
{   NIL pointer indicates the last valid entry. The pointer to the last valid entry is returned to the caller.
{   If no entry has been allocated the returned pointer is NIL.

  PROCEDURE get_last_esm_definition
    (VAR last_esm_table_entry_p: ^dft$esm_definition_table_entry);

    VAR
      current_esm_table_entry_p: ^dft$esm_definition_table_entry;

    last_esm_table_entry_p := NIL;
    IF dfv$p_esm_definition_table <> NIL THEN
      current_esm_table_entry_p := dfv$p_esm_definition_table;
      REPEAT
        last_esm_table_entry_p := current_esm_table_entry_p;
        current_esm_table_entry_p := current_esm_table_entry_p^.p_next_table_entry;
      UNTIL current_esm_table_entry_p = NIL;
    IFEND;

  PROCEND get_last_esm_definition;
?? OLDTITLE ??
?? NEWTITLE := 'verify_esm_configured ', EJECT ??

{ PURPOSE:
{   This procedure verifies that the specified element with the namedchannel is an ESM device, configured on
{   this mainframe.

  PROCEDURE verify_esm_configured
    (    esm_element_name: cmt$element_name;
         channel_name: dft$channel_definition;
         mainframe_name: pmt$mainframe_id;
     VAR status: ost$status);

    VAR
      channel_address: cmt$physical_equipment_number,
      channel_definition: cmt$data_channel_definition,
      channel_descriptor: cmt$channel_descriptor,
      element_definition: cmt$element_definition,
      element_descriptor: cmt$element_descriptor,
      element_found: boolean,
      port_number: cmt$communications_port_number;

    status.normal := TRUE;

    element_descriptor.element_type := cmc$communications_element;
    element_descriptor.peripheral_descriptor.use_logical_identification := TRUE;
    element_descriptor.peripheral_descriptor.element_name := esm_element_name;

    { Get the channel/mainframe_id array for the element.

    cmp$get_element_definition (element_descriptor, element_definition, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Verify that the specified element is the ESM product.

    dfp$verify_esm_product_id (element_definition.product_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    element_found := FALSE;
  /verify_mainframe_iou_names/
    FOR port_number := LOWERVALUE (cmt$communications_port_number)
          TO UPPERVALUE (cmt$communications_port_number) DO
      IF element_definition.communications_element.connection.port [port_number].configured THEN
        IF ((channel_name.mainframe_id = element_definition.communications_element.
                connection.port [port_number].mainframe_ownership) AND
            (channel_name.iou_name = element_definition.communications_element.
                connection.port [port_number].iou) AND
            (channel_name.channel_name = element_definition.communications_element.
                connection.port [port_number].element_name)) THEN
          element_found := TRUE;

          IF element_definition.communications_element.connection.port[port_number]
             .mainframe_ownership = mainframe_name THEN

            { Make sure that the channel definition is around.

            channel_descriptor.use_logical_identification := TRUE;
            channel_descriptor.iou := channel_name.iou_name;
            channel_descriptor.name := channel_name.channel_name;
            cmp$get_channel_definition (channel_descriptor, channel_definition, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
          IFEND;
          EXIT /verify_mainframe_iou_names/;
        IFEND;
      IFEND;
    FOREND /verify_mainframe_iou_names/;

    IF NOT element_found THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$no_configured_channel, channel_name.channel_name,
            status);
      RETURN;
    IFEND;

  PROCEND verify_esm_configured;
?? OLDTITLE ??
MODEND dfm$esm_definition_manager;
