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

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc osd$virtual_address
*copyc dmt$addr_length_pair
*copyc dmt$disk_file_descriptor
*copyc dmt$error_condition_codes
*copyc dmt$file_allocation_descriptor
*copyc gft$locked_file_desc_entry_p
*copyc gft$system_file_identifier
*copyc ost$status
*copyc ost$wait
?? POP ??
*copyc dmp$get_disk_file_descriptor_p
*copyc dmp$get_level_2_ptr
*copyc gfp$get_locked_fde_p
*copyc gfp$unlock_fde_p
*copyc osp$set_status_abnormal
?? TITLE := '  dmp$get_initialized_addresses', EJECT ??
*copyc dmh$get_initialized_addresses

  PROCEDURE [XDCL, #GATE] dmp$get_initialized_addresses
    (    sfid: gft$system_file_identifier;
         starting_byte_address: ost$segment_offset;
     VAR addr_list: array [ * ] of dmt$addr_length_pair;
     VAR number_of_addresses: integer;
     VAR list_overflow: boolean;
     VAR status: ost$status);

    VAR
      bytes_per_allocation: dmt$bytes_per_allocation,
      p_dfd: ^dmt$disk_file_descriptor,
      p_fde: gft$locked_file_desc_entry_p,
      previous_offset: integer,
      level_1_index: dmt$level_1_index,
      level_1_start: dmt$level_1_index,
      level_2_index: dmt$level_2_index,
      level_2_start: dmt$level_2_index,
      list_index: integer,
      offset: integer,
      p_level_2: ^dmt$level_2_table;

    number_of_addresses := 0;
    list_overflow := FALSE;
    status.normal := TRUE;
    previous_offset := -1;

    list_index := LOWERBOUND (addr_list) - 1;

{ Lock the file descriptor entry.
    gfp$get_locked_fde_p (sfid, p_fde);
    dmp$get_disk_file_descriptor_p (p_fde, p_dfd);

  /file_descriptor_locked/
    BEGIN
      IF p_dfd^.file_allocation_table <> NIL THEN
        bytes_per_allocation := p_dfd^.bytes_per_allocation;
        level_1_start := starting_byte_address DIV p_dfd^.bytes_per_level_2;
        level_2_start := starting_byte_address MOD p_dfd^.bytes_per_level_2 DIV bytes_per_allocation;
        FOR level_1_index := level_1_start TO p_dfd^.fat_upper_bound DO
          dmp$get_level_2_ptr (^p_dfd^.file_allocation_table^ [level_1_index], p_level_2);
          IF p_level_2 <> NIL THEN
            FOR level_2_index := level_2_start TO (p_dfd^.bytes_per_level_2 DIV bytes_per_allocation - 1) DO
              IF (p_level_2^ [level_2_index].state = dmc$fau_initialized) OR
                    (p_level_2^ [level_2_index].state = dmc$fau_initialized_and_flawed) THEN
                offset := (level_1_index * p_dfd^.bytes_per_level_2) + (level_2_index * bytes_per_allocation);

                IF offset >= p_fde^.eoi_byte_address THEN
                  {Stop at current eoi
                  EXIT /file_descriptor_locked/; {----->
                IFEND;

                IF offset <> (previous_offset + bytes_per_allocation) THEN
                  list_index := list_index + 1;
                  IF list_index > UPPERBOUND (addr_list) THEN
                    list_overflow := TRUE;
                    EXIT /file_descriptor_locked/; {----->
                  ELSE
                    number_of_addresses := number_of_addresses + 1;
                    addr_list [list_index].addr := offset;
                    addr_list [list_index].length := bytes_per_allocation;
                  IFEND;
                ELSE
                  addr_list [list_index].length := addr_list [list_index].length + bytes_per_allocation;
                IFEND;
                previous_offset := offset;
              IFEND;
            FOREND;
          IFEND;
          level_2_start := 0;
        FOREND;
      IFEND;

    END /file_descriptor_locked/;

    gfp$unlock_fde_p (p_fde);

  PROCEND dmp$get_initialized_addresses;
MODEND dmm$get_initialized_addresses;
