?? NEWTITLE := 'NOS/VE Device Management' ??
MODULE dmm$file_access_routines;
?? RIGHT := 110 ??

{   PURPOSE:
{      This module contains procedures used to access device management tables.
{
{   DESIGN:
{      The device management tables are accessed as segment access files.
{

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc mme$condition_codes
*copyc dmt$error_condition_codes
*copyc dmt$ms_device_allocation_table
*copyc dmt$ms_device_file_list_entry
*copyc dmt$ms_login_table
*copyc dmt$ms_volume_directory
*copyc dmt$ms_volume_label
?? POP ??
*copyc dmp$close_file
*copyc dmp$open_file
*copyc osp$set_status_abnormal
*copyc syp$continue_to_cause
*copyc syp$disestablish_cond_handler
*copyc syp$establish_condition_handler
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] DMP$OPEN_DFLT', EJECT ??
*copy dmh$open_dflt

  PROCEDURE [XDCL, #GATE] dmp$open_dflt
    (    dflt_sfid: gft$system_file_identifier;
         ring1: ost$valid_ring;
         ring2: ost$valid_ring;
         access_rights: mmt$segment_access_rights;
         access_selections: mmt$access_selections;
     VAR p_dflt: ^dmt$ms_device_file_list_table;
     VAR status: ost$status);

    VAR
      segment_pointer: mmt$segment_pointer,
      p_dflt_seq: ^SEQ ( * ),
      p_dflt_header: ^dmt$ms_device_file_list_header,
      number_dflt_entries: dmt$device_file_list_index;

?? NEWTITLE := 'HANDLER', EJECT ??

    PROCEDURE handler
      (    mf: ost$monitor_fault;
           p_msa: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        exit_open: boolean,
        ignore_status: ost$status,
        p_scc: ^syt$system_core_condition,
        p_sac: ^mmt$segment_access_condition,
        p_mcr: ^tmt$mcr_faults;

      exit_open := FALSE;
      CASE mf.identifier OF
      = mmc$segment_fault_processor_id =
        p_sac := #LOC (mf.contents);
        CASE p_sac^.identifier OF
        = mmc$sac_io_read_error =
          osp$set_status_abnormal ('MM', mme$io_read_error, 'io error opening DFLT - dmp$open_dflt', status);
          exit_open := TRUE;
        ELSE
        CASEND;

      = syc$system_core_condition =
        p_scc := #LOC (mf.system_core_condition);
        CASE p_scc^.condition OF
        = syc$user_defined_condition =
          IF p_scc^.user_defined_condition = syc$udc_volume_unavailable THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable,
                  'volume unavailable in dmp$open_dflt', status);
            exit_open := TRUE;
          IFEND;
        ELSE
        CASEND;

      = tmc$mcr_fault =
        p_mcr := #LOC (mf.mcr_fault);
        IF osc$invalid_segment_ring_0 IN p_mcr^.faults THEN
          IF p_dflt_header = NIL THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_dflt_failure,
                  'NEXT nil during open of dfl header - dmp$open_dflt', status);
            exit_open := TRUE;
          IFEND;
        IFEND;
      ELSE
        ;
      CASEND;

      IF exit_open THEN
        IF p_dflt_seq <> NIL THEN
          dmp$close_file (p_dflt_seq, ignore_status);
        IFEND;

        p_dflt := NIL;
        EXIT dmp$open_dflt; {----->
      IFEND;

      syp$continue_to_cause (mf, p_msa, syc$condition_ignored, continue);

    PROCEND handler;
?? OLDTITLE ??
?? EJECT ??
    p_dflt := NIL;
    p_dflt_seq := NIL;
    segment_pointer.kind := mmc$sequence_pointer;

    dmp$open_file (dflt_sfid, ring1, ring2, access_rights, access_selections, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    syp$establish_condition_handler (^handler);

    p_dflt_seq := segment_pointer.seq_pointer;
    RESET p_dflt_seq;
    NEXT p_dflt_header IN p_dflt_seq;

    number_dflt_entries := p_dflt_header^.number_of_entries;

    RESET p_dflt_seq;
    NEXT p_dflt: [1 .. number_dflt_entries] IN p_dflt_seq;

    IF p_dflt = NIL THEN
      dmp$close_file (p_dflt_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_dflt_failure,
            'NEXT nil during open of dflt - dmp$open_dflt', status);
    IFEND;

    syp$disestablish_cond_handler;

  PROCEND dmp$open_dflt;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] DMP$OPEN_DAT', EJECT ??
*copy dmh$open_dat

  PROCEDURE [XDCL, #GATE] dmp$open_dat
    (    dat_sfid: gft$system_file_identifier;
         ring1: ost$valid_ring;
         ring2: ost$valid_ring;
         access_rights: mmt$segment_access_rights;
         access_selections: mmt$access_selections;
     VAR p_dat: ^dmt$ms_device_allocation_table;
     VAR status: ost$status);

    VAR
      segment_pointer: mmt$segment_pointer,
      p_dat_seq: ^SEQ ( * ),
      p_dat_header: ^dmt$ms_device_alloc_table_head,
      number_dat_entries: dmt$dau_address;

?? NEWTITLE := 'HANDLER', EJECT ??

    PROCEDURE handler
      (    mf: ost$monitor_fault;
           p_msa: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        exit_open: boolean,
        ignore_status: ost$status,
        p_scc: ^syt$system_core_condition,
        p_sac: ^mmt$segment_access_condition,
        p_mcr: ^tmt$mcr_faults;

      exit_open := FALSE;
      CASE mf.identifier OF
      = mmc$segment_fault_processor_id =
        p_sac := #LOC (mf.contents);
        CASE p_sac^.identifier OF
        = mmc$sac_io_read_error =
          osp$set_status_abnormal ('MM', mme$io_read_error, 'io error opening DAT - dmp$open_dat', status);
          exit_open := TRUE;

        ELSE
        CASEND;

      = syc$system_core_condition =
        p_scc := #LOC (mf.system_core_condition);
        CASE p_scc^.condition OF
        = syc$user_defined_condition =
          IF p_scc^.user_defined_condition = syc$udc_volume_unavailable THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable,
                  'volume unavailable in dmp$open_dat', status);
            exit_open := TRUE;
          IFEND;
        ELSE
        CASEND;

      = tmc$mcr_fault =
        p_mcr := #LOC (mf.mcr_fault);
        IF osc$invalid_segment_ring_0 IN p_mcr^.faults THEN
          IF p_dat_header = NIL THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_dflt_failure,
                  'NEXT nil during open of dfl header - dmp$open_dflt', status);
            exit_open := TRUE;
          IFEND;
        IFEND;
      ELSE
        ;
      CASEND;

      IF exit_open THEN
        IF p_dat_seq <> NIL THEN
          dmp$close_file (p_dat_seq, ignore_status);
        IFEND;

        p_dat := NIL;
        EXIT dmp$open_dat; {----->
      IFEND;

      syp$continue_to_cause (mf, p_msa, syc$condition_ignored, continue);

    PROCEND handler;
?? OLDTITLE ??
?? EJECT ??
    p_dat := NIL;
    segment_pointer.kind := mmc$sequence_pointer;

    dmp$open_file (dat_sfid, ring1, ring2, access_rights, access_selections, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    syp$establish_condition_handler (^handler);

    p_dat_seq := segment_pointer.seq_pointer;
    RESET p_dat_seq;
    NEXT p_dat_header IN p_dat_seq;

    number_dat_entries := p_dat_header^.number_of_entries;
    syp$disestablish_cond_handler;

    RESET p_dat_seq;
    NEXT p_dat: [0 .. number_dat_entries - 1] IN p_dat_seq;

    IF p_dat = NIL THEN
      dmp$close_file (p_dat_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_dat_failure,
            'NEXT nil during open of dat - dmp$open_dat', status);
    IFEND;

  PROCEND dmp$open_dat;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] DMP$OPEN_DIRECTORY', EJECT ??
*copy dmh$open_directory

  PROCEDURE [XDCL, #GATE] dmp$open_directory
    (    directory_sfid: gft$system_file_identifier;
         ring1: ost$valid_ring;
         ring2: ost$valid_ring;
         access_rights: mmt$segment_access_rights;
         access_selections: mmt$access_selections;
     VAR p_directory: ^dmt$ms_volume_directory;
     VAR status: ost$status);

    VAR
      segment_pointer: mmt$segment_pointer,
      p_directory_seq: ^SEQ ( * ),
      number_directory_entries: dmt$directory_index,
      p_directory_header: ^dmt$ms_volume_directory_head;

?? NEWTITLE := 'HANDLER', EJECT ??

    PROCEDURE handler
      (    mf: ost$monitor_fault;
           p_msa: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        exit_open: boolean,
        ignore_status: ost$status,
        p_scc: ^syt$system_core_condition,
        p_sac: ^mmt$segment_access_condition,
        p_mcr: ^tmt$mcr_faults;

      exit_open := FALSE;
      CASE mf.identifier OF
      = mmc$segment_fault_processor_id =
        p_sac := #LOC (mf.contents);
        CASE p_sac^.identifier OF
        = mmc$sac_io_read_error =
          osp$set_status_abnormal ('MM', mme$io_read_error, 'io error opening DIRECTORY - dmp$open_directory',
                status);
          exit_open := TRUE;
        ELSE
        CASEND;

      = syc$system_core_condition =
        p_scc := #LOC (mf.system_core_condition);
        CASE p_scc^.condition OF
        = syc$user_defined_condition =
          IF p_scc^.user_defined_condition = syc$udc_volume_unavailable THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable,
                  'volume unavailable in dmp$open_directory', status);
            exit_open := TRUE;
          IFEND;
        ELSE
        CASEND;

      = tmc$mcr_fault =
        p_mcr := #LOC (mf.mcr_fault);
        IF osc$invalid_segment_ring_0 IN p_mcr^.faults THEN
          IF p_directory_header = NIL THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_directory_failure,
                  'NEXT nil during open of directo' CAT 'ry header - dmp$open_directory', status);
            exit_open := TRUE;
          IFEND;
        IFEND;
      ELSE
        ;
      CASEND;

      IF exit_open THEN
        IF p_directory_seq <> NIL THEN
          dmp$close_file (p_directory_seq, ignore_status);
        IFEND;

        p_directory := NIL;
        EXIT dmp$open_directory; {----->
      IFEND;

      syp$continue_to_cause (mf, p_msa, syc$condition_ignored, continue);

    PROCEND handler;
?? OLDTITLE ??
?? EJECT ??
    segment_pointer.kind := mmc$sequence_pointer;
    p_directory_seq := NIL;
    p_directory := NIL;

    dmp$open_file (directory_sfid, ring1, ring2, access_rights, access_selections, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    syp$establish_condition_handler (^handler);
    p_directory_seq := segment_pointer.seq_pointer;
    RESET p_directory_seq;
    NEXT p_directory_header IN p_directory_seq;

    number_directory_entries := p_directory_header^.number_of_entries;
    syp$disestablish_cond_handler;

    RESET p_directory_seq;
    NEXT p_directory: [1 .. number_directory_entries] IN p_directory_seq;

    IF p_directory = NIL THEN
      dmp$close_file (p_directory_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_directory_failure,
            'NEXT nil during open of directory - dmp$open_directory', status);
    IFEND;

  PROCEND dmp$open_directory;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] DMP$OPEN_LOGIN_TABLE', EJECT ??
*copy dmh$open_login_table

  PROCEDURE [XDCL, #GATE] dmp$open_login_table
    (    sfid: gft$system_file_identifier;
         ring1: ost$valid_ring;
         ring2: ost$valid_ring;
         access_rights: mmt$segment_access_rights;
         access_selections: mmt$access_selections;
     VAR p_login_table: ^dmt$ms_mainframe_login_table;
     VAR status: ost$status);

    VAR
      segment_pointer: mmt$segment_pointer,
      p_login_table_seq: ^SEQ ( * ),
      upper_bound: dmt$login_table_entry_index,
      lower_bound: dmt$login_table_entry_index,
      p_login_table_header: ^dmt$ms_mf_login_table_header;

?? NEWTITLE := 'HANDLER', EJECT ??

    PROCEDURE handler
      (    mf: ost$monitor_fault;
           p_msa: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        exit_open: boolean,
        ignore_status: ost$status,
        p_scc: ^syt$system_core_condition,
        p_sac: ^mmt$segment_access_condition,
        p_mcr: ^tmt$mcr_faults;

      exit_open := FALSE;
      CASE mf.identifier OF
      = mmc$segment_fault_processor_id =
        p_sac := #LOC (mf.contents);
        CASE p_sac^.identifier OF
        = mmc$sac_io_read_error =
          osp$set_status_abnormal ('MM', mme$io_read_error,
                'io error opening LOGIN TABLE - dmp$open_login_table', status);
          exit_open := TRUE;
        ELSE
        CASEND;

      = syc$system_core_condition =
        p_scc := #LOC (mf.system_core_condition);
        CASE p_scc^.condition OF
        = syc$user_defined_condition =
          IF p_scc^.user_defined_condition = syc$udc_volume_unavailable THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable,
                  'volume unavailable in dmp$open_login_table', status);
            exit_open := TRUE;
          IFEND;
        ELSE
        CASEND;

      = tmc$mcr_fault =
        p_mcr := #LOC (mf.mcr_fault);
        IF osc$invalid_segment_ring_0 IN p_mcr^.faults THEN
          IF p_login_table_header = NIL THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_login_table_failure,
                  'NEXT nil during open of login' CAT '_table header - dmp$open_login_table', status);
            exit_open := TRUE;
          IFEND;
        IFEND;
      ELSE
        ;
      CASEND;

      IF exit_open THEN
        IF p_login_table_seq <> NIL THEN
          dmp$close_file (p_login_table_seq, ignore_status);
        IFEND;

        p_login_table := NIL;
        EXIT dmp$open_login_table; {----->
      IFEND;

      syp$continue_to_cause (mf, p_msa, syc$condition_ignored, continue);

    PROCEND handler;
?? OLDTITLE ??
?? EJECT ??
    segment_pointer.kind := mmc$sequence_pointer;
    p_login_table_seq := NIL;
    p_login_table := NIL;

    dmp$open_file (sfid, ring1, ring2, access_rights, access_selections, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    syp$establish_condition_handler (^handler);

    p_login_table_seq := segment_pointer.seq_pointer;
    RESET p_login_table_seq;
    NEXT p_login_table_header IN p_login_table_seq;

    lower_bound := p_login_table_header^.lower_bound;
    upper_bound := p_login_table_header^.upper_bound;

    syp$disestablish_cond_handler;

    RESET p_login_table_seq;
    NEXT p_login_table: [lower_bound .. upper_bound] IN p_login_table_seq;

    IF p_login_table = NIL THEN
      dmp$close_file (p_login_table_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_login_table_failure,
            'NEXT nil during open of log' CAT 'in_table - dmp$open_login_table', status);
    IFEND;

  PROCEND dmp$open_login_table;
?? OLDTITLE ??
?? NEWTITLE := '  dmp$open_label', EJECT ??
*copy dmh$open_label

  PROCEDURE [XDCL, #GATE] dmp$open_label
    (    label_sfid: gft$system_file_identifier;
         ring1: ost$valid_ring;
         ring2: ost$valid_ring;
         access_rights: mmt$segment_access_rights;
         access_selections: mmt$access_selections;
     VAR p_label: ^dmt$ms_volume_label;
     VAR status: ost$status);

    VAR
      segment_pointer: mmt$segment_pointer,
      p_label_seq: ^dmt$ms_volume_label,
      p_label_header: ^dmt$volume_label_header,
      p_label_0_0: ^dmt$ms_label_0_0,
      bytes_per_au: amt$file_byte_address,
      number_of_aus: dmt$dau_address;

?? NEWTITLE := 'HANDLER', EJECT ??

    PROCEDURE handler
      (    mf: ost$monitor_fault;
           p_msa: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        exit_open: boolean,
        ignore_status: ost$status,
        p_scc: ^syt$system_core_condition,
        p_sac: ^mmt$segment_access_condition,
        p_mcr: ^tmt$mcr_faults;

      exit_open := FALSE;
      CASE mf.identifier OF
      = mmc$segment_fault_processor_id =
        p_sac := #LOC (mf.contents);
        CASE p_sac^.identifier OF
        = mmc$sac_io_read_error =
          osp$set_status_abnormal ('MM', mme$io_read_error, 'io error opening LABEL- dmp$open_label', status);
          exit_open := TRUE;
        ELSE
        CASEND;

      = syc$system_core_condition =
        p_scc := #LOC (mf.system_core_condition);
        CASE p_scc^.condition OF
        = syc$ucr_condition =
          IF osc$divide_fault IN p_scc^.ucr THEN

{This means actially, that the label is not properly initialized or that we have an undetected
{unrecovered IO error - I mean, I put this code in, as we kust crashed because of this!

            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_label_failure,
                  '0 Bytes per Allocation Unit', status);
            exit_open := TRUE;
          IFEND;

        = syc$user_defined_condition =
          IF p_scc^.user_defined_condition = syc$udc_volume_unavailable THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$volume_unavailable,
                  'volume unavailable in dmp$open_label', status);
            exit_open := TRUE;
          IFEND;
        ELSE
        CASEND;

      = tmc$mcr_fault =
        p_mcr := #LOC (mf.mcr_fault);
        IF osc$invalid_segment_ring_0 IN p_mcr^.faults THEN
          IF (p_label_header = NIL)
{       } OR ((p_label_header^.version_number = dmc$ms_label_0_0) AND (p_label_0_0 = NIL)) THEN
            osp$set_status_abnormal (dmc$device_manager_ident, dme$open_label_failure,
                  'NEXT nil during open of label header - dmp$open_label', status);
            exit_open := TRUE;
          IFEND;
        IFEND;
      ELSE
        ;
      CASEND;

      IF exit_open THEN
        IF p_label_seq <> NIL THEN
          dmp$close_file (p_label_seq, ignore_status);
        IFEND;

        p_label := NIL;
        EXIT dmp$open_label; {----->
      IFEND;

      syp$continue_to_cause (mf, p_msa, syc$condition_ignored, continue);

    PROCEND handler;
?? OLDTITLE ??
?? EJECT ??
    segment_pointer.kind := mmc$sequence_pointer;
    p_label_seq := NIL;
    p_label := NIL;

    dmp$open_file (label_sfid, ring1, ring2, access_rights, access_selections, segment_pointer, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    syp$establish_condition_handler (^handler);

    p_label_seq := segment_pointer.seq_pointer;
    RESET p_label_seq;
    NEXT p_label_header IN p_label_seq;

    CASE p_label_header^.version_number OF
    = dmc$ms_label_0_0 =
      NEXT p_label_0_0 IN p_label_seq;

      bytes_per_au := p_label_header^.bytes_per_dau * p_label_0_0^.dat_dfl_entry.daus_per_allocation_unit;
      number_of_aus := (p_label_0_0^.dat_dfl_entry.fmd_length + bytes_per_au - 1) DIV bytes_per_au;

    ELSE
      dmp$close_file (p_label_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$unsupported_label_version,
            'unsupported label version number - dmp$open_label', status);
      syp$disestablish_cond_handler;
      RETURN; {----->
    CASEND;

    syp$disestablish_cond_handler;

    IF #SIZE (p_label_seq^) < (#SIZE (dmt$volume_label_header) + #SIZE (dmt$ms_label_0_0) +
          #SIZE (dmt$stored_ms_device_file_fat: [1 .. number_of_aus])) THEN
      dmp$close_file (p_label_seq, status);
      osp$set_status_abnormal (dmc$device_manager_ident, dme$open_label_failure,
            'unable to locate dat fat in label - dmp$open_label', status);
    ELSE
      RESET p_label_seq;
      p_label := p_label_seq;
    IFEND;

  PROCEND dmp$open_label;
?? OLDTITLE ??
MODEND dmm$file_access_routines;
