?? RIGHT := 110 ??
?? NEWTITLE := 'NOSVE Device Management' ??
MODULE dmm$volume_attribute_manager;
?? RIGHT := 110 ??
?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dmt$error_condition_codes
*copyc dmp$get_logical_attributes
*copyc dmt$ms_active_vol_table_entry
*copyc dmt$volume_attribute_info
*copyc dmt$volume_attributes
?? POP ??
*copyc dmp$close_file
*copyc dmp$get_mat_pointer
*copyc dmp$open_dat
*copyc dmp$search_avt_by_lun
*copyc dmp$verify_access
*copyc mmp$write_modified_pages
*copyc osp$clear_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$test_set_main_sig_lock
*copyc syp$cycle
*copyc dmv$active_volume_table
*copyc cmv$logical_unit_table
*copyc cmv$product_id_string
?? TITLE := '  dmp$change_volume_attributes', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$change_volume_attributes
    (    logical_unit_number: iot$logical_unit;
         p_volume_attributes: ^dmt$volume_attributes;
     VAR status: ost$status);

    CONST
      c$lock_retry_count = 5;

    VAR
      able_to_set_lock: boolean,
      avt_entry_found: boolean,
      avt_index: dmt$active_volume_table_index,
      cylinder_allocation_size: integer,
      bytes_per_position: integer,
      i: integer,
      index: integer,
      logical_attributes_p: ^dmt$logical_device_attributes,
      p_dat: ^dmt$ms_device_allocation_table,
      p_mat: ^dmt$mainframe_allocation_table,
      retry: integer,
      status_p: ^ost$status,
      unit_type: iot$unit_type,
      volume_accessible: boolean;

    status.normal := TRUE;
    dmp$search_avt_by_lun (logical_unit_number, avt_index, avt_entry_found);
    IF NOT avt_entry_found THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$avt_entry_not_found,
            'Avt entry not found for logical unit', status);
      RETURN; {----->
    IFEND;

    dmp$verify_access (avt_index, volume_accessible);
    IF NOT volume_accessible THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable, 'Cannot access volume',
            status);
      RETURN; {----->
    IFEND;

    IF p_volume_attributes = NIL THEN
      RETURN; {----->
    IFEND;

{Convert Cylinder Allocation
    cylinder_allocation_size := dmc$max_bytes_per_allocation;
    FOR index := LOWERBOUND (p_volume_attributes^) TO UPPERBOUND (p_volume_attributes^) DO
      IF p_volume_attributes^ [index].keyword = dmc$vol_default_allocation_size THEN
        cylinder_allocation_size := p_volume_attributes^ [index].default_allocation_size;
        IF cylinder_allocation_size = dmc$max_bytes_per_allocation THEN
          IF (cmv$logical_unit_table <> NIL)
{       } AND (logical_unit_number <= UPPERBOUND (cmv$logical_unit_table^))
{       } AND (cmv$logical_unit_table^ [logical_unit_number].configured)
{       } AND (cmv$logical_unit_table^ [logical_unit_number].unit_interface_table <> NIL) THEN
            unit_type := cmv$logical_unit_table^ [logical_unit_number].unit_interface_table^.unit_type;

            IF cmv$product_id_ptr <> NIL THEN

            /find_product/
              FOR i := LOWERBOUND (cmv$product_id_ptr^) TO UPPERBOUND (cmv$product_id_ptr^) DO
                IF cmv$product_id_ptr^ [i].io_unit_type = unit_type THEN
                  PUSH logical_attributes_p: [1 .. 1];
                  logical_attributes_p^ [1].keyword := dmc$cylinder_allocation_size;
                  dmp$get_logical_attributes (cmv$product_id_ptr^ [i].product_id, logical_attributes_p,
                        status);
                  IF status.normal THEN
                    cylinder_allocation_size := logical_attributes_p^ [1].bytes_per_cylinder;
                    EXIT /find_product/;
                  IFEND;
                IFEND;
              FOREND /find_product/;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    FOREND;

    status.normal := TRUE; {Reset the status, in case dmp$get_logical_attributes returned a bad status
    dmp$get_mat_pointer (avt_index, p_mat);

    dmp$open_dat (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_device_allocation_table,
          osc$os_ring_1, osc$tsrv_ring, mmc$sar_write_extend, mmc$as_sequential, p_dat, status);
    IF NOT status.normal THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_dat_failure,
            'unable to open dat - dmp$change_volume_attributes', status);
      RETURN; {----->
    IFEND;

  /dat_open/
    BEGIN
      retry := 0;
      REPEAT
        osp$test_set_main_sig_lock (dmv$active_volume_table.table_p^ [avt_index].mass_storage.update_lock,
              able_to_set_lock);
        IF NOT able_to_set_lock THEN
          retry := retry + 1;
          IF retry > c$lock_retry_count THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$unable_to_lock_dat,
                  'unable to lock dat - dmp$change_volume_attributes', status);
            EXIT /dat_open/; {----->
          IFEND;
          syp$cycle;
        IFEND;
      UNTIL able_to_set_lock;

      FOR index := LOWERBOUND (p_volume_attributes^) TO UPPERBOUND (p_volume_attributes^) DO
        CASE p_volume_attributes^ [index].keyword OF
        = dmc$vol_default_allocation_size =
          bytes_per_position := p_volume_attributes^ [index].default_allocation_size;
          IF bytes_per_position <> 0 THEN
            IF bytes_per_position = dmc$max_bytes_per_allocation THEN
              IF cylinder_allocation_size <> dmc$max_bytes_per_allocation THEN
                bytes_per_position := cylinder_allocation_size;
              ELSE
                bytes_per_position := p_mat^.bytes_per_dau * p_mat^.daus_per_position;
              IFEND;
            IFEND;
            p_dat^.header.default_allocation_size := bytes_per_position;
            p_mat^.default_allocation_size := bytes_per_position;
          IFEND;

        = dmc$vol_default_transfer_size =
          bytes_per_position := p_volume_attributes^ [index].default_transfer_size;
          IF bytes_per_position <> 0 THEN
            IF bytes_per_position = dmc$max_transfer_size THEN
              bytes_per_position := p_mat^.bytes_per_dau * p_mat^.daus_per_position;
            IFEND;
            p_dat^.header.default_transfer_size := bytes_per_position;
            p_mat^.default_transfer_size := bytes_per_position;
          IFEND;
        ELSE
        CASEND;
      FOREND;

      mmp$write_modified_pages (p_dat, #SIZE (p_dat^), osc$wait, status);
      IF NOT status.normal THEN
        osp$set_status_abnormal (dmc$device_manager_ident, dme$unable_to_change_vol_attr,
              'Unable to change volume attribute(s) - dmp$change_volume_attributes', status);
      IFEND;

      osp$clear_mainframe_sig_lock (dmv$active_volume_table.table_p^ [avt_index].mass_storage.update_lock);
    END /dat_open/;

    IF status.normal THEN
      status_p := ^status;
    ELSE
      PUSH status_p;
    IFEND;

    dmp$close_file (p_dat, status_p^);

  PROCEND dmp$change_volume_attributes;
?? TITLE := '  dmp$get_volume_attributes', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$get_volume_attributes
    (    logical_unit_number: iot$logical_unit;
     VAR volume_attribute_info: dmt$volume_attribute_info;
     VAR status: ost$status);

    VAR
      avt_entry_found: boolean,
      avt_index: dmt$active_volume_table_index,
      p_mat: ^dmt$mainframe_allocation_table;

    status.normal := TRUE;
    dmp$search_avt_by_lun (logical_unit_number, avt_index, avt_entry_found);
    IF NOT avt_entry_found THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$avt_entry_not_found,
            'Avt entry not found for logical unit', status);
      RETURN; {----->
    IFEND;

    dmp$get_mat_pointer (avt_index, p_mat);

    IF (p_mat = NIL) THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$avt_entry_not_found,
            'Avt entry not found for logical unit', status);
      RETURN; {----->
    IFEND;

    volume_attribute_info.default_allocation_size := p_mat^.default_allocation_size;
    volume_attribute_info.default_transfer_size := p_mat^.default_transfer_size;

  PROCEND dmp$get_volume_attributes;

MODEND dmm$volume_attribute_manager;
