?? RIGHT := 110 ??                                                                                            
?? NEWTITLE := 'NOS/VE Dump Analyzer : Real Memory Access Routines' ??                                        
MODULE dum$real_memory_access;                                                                                
                                                                                                              
{ PURPOSE:                                                                                                    
{   This module contains procedures used for real memory access.                                              
                                                                                                              
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??                                      
?? PUSH (LISTEXT := ON) ??                                                                                    
*copyc due$exception_condition_codes                                                                          
*copyc ost$hardware_subranges                                                                                 
?? POP ??                                                                                                     
*copyc osp$set_status_abnormal                                                                                
?? EJECT ??                                                                                                   
*copyc duv$dump_environment_p                                                                                 
*copyc duv$execution_environment                                                                              
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'dup$access_real_memory', EJECT ??                                                             
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure retrieves a pointer to the desired area in real memory.  The new byte size returned        
{   contains the byte size of the data found in memory.                                                       
                                                                                                              
  PROCEDURE [XDCL] dup$access_real_memory                                                                     
    (    size: ost$real_memory_address;                                                                       
         offset: ost$real_memory_address;                                                                     
     VAR memory_p: ^cell;                                                                                     
     VAR new_byte_size: ost$segment_length;                                                                   
     VAR status: ost$status);                                                                                 
                                                                                                              
    VAR                                                                                                       
      adjusted_size: ost$real_memory_address,                                                                 
      all_pages_available: boolean,                                                                           
      cpt_p: ^cell,                                                                                           
      critical_page_table_p: ^ARRAY [0 .. *] OF dut$de_critical_page_entry,                                   
      last_available_page: 0 .. 0ffffffff(16),                                                                
      last_page_number: 0 .. 0ffffffff(16),                                                                   
      number_page_entries: 0 .. 0ffffffff(16),                                                                
      page_number: 0 .. 0ffffffff(16),                                                                        
      page_offset: amt$file_byte_address,                                                                     
      page_size: 0 .. duc$de_max_page_size,                                                                   
      remainder: ost$real_memory_address;                                                                     
                                                                                                              
    status.normal := TRUE;                                                                                    
                                                                                                              
    { Check for a valid rma.                                                                                  
                                                                                                              
    IF offset > duc$de_maximum_rma THEN                                                                       
      osp$set_status_abnormal (duc$dump_analyzer_id, due$invalid_offset, '', status);                         
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Check if the memory is available on the memory file.                                                    
                                                                                                              
    IF (duv$execution_environment.processing_options = duc$ee_po_no_memory) OR                                
          (NOT duv$dump_environment_p^.central_memory.available AND                                           
          NOT duv$dump_environment_p^.critical_memory.available) THEN                                         
      osp$set_status_abnormal (duc$dump_analyzer_id, due$data_not_on_dump, 'The central memory is', status);  
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Check if the memory is within the bounds of the MEM record.                                             
                                                                                                              
    IF duv$dump_environment_p^.central_memory.available AND                                                   
          (offset >= duv$dump_environment_p^.central_memory.first_byte) AND                                   
          (offset <= duv$dump_environment_p^.central_memory.last_byte) THEN                                   
                                                                                                              
      IF (offset + size - 1) > duv$dump_environment_p^.central_memory.last_byte THEN                          
        osp$set_status_abnormal (duc$dump_analyzer_id, due$memory_partially_avail, '', status);               
        adjusted_size := duv$dump_environment_p^.central_memory.last_byte - offset + 1;                       
      ELSE                                                                                                    
        adjusted_size := size;                                                                                
      IFEND;                                                                                                  
      memory_p := #ADDRESS (#RING (duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer),
            #SEGMENT (duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer),             
            (offset - duv$dump_environment_p^.central_memory.first_byte) +                                    
            duv$dump_environment_p^.central_memory.bias);                                                     
      new_byte_size := adjusted_size;                                                                         
                                                                                                              
    { Check if the memory is within the bounds of the critical memory.                                        
                                                                                                              
    ELSEIF duv$dump_environment_p^.critical_memory.available AND                                              
          (offset >= duv$dump_environment_p^.critical_memory.first_rma_available) AND                         
          (offset <= duv$dump_environment_p^.critical_memory.last_rma_available) THEN                         
                                                                                                              
      IF (offset + size - 1) > duv$dump_environment_p^.critical_memory.last_rma_available THEN                
        osp$set_status_abnormal (duc$dump_analyzer_id, due$memory_partially_avail, '', status);               
        adjusted_size := duv$dump_environment_p^.critical_memory.last_rma_available - offset + 1;             
      ELSE                                                                                                    
        adjusted_size := size;                                                                                
      IFEND;                                                                                                  
                                                                                                              
      page_size := duv$dump_environment_p^.critical_memory.page_size;                                         
      page_number := offset DIV page_size;                                                                    
      remainder := offset MOD page_size;                                                                      
                                                                                                              
      cpt_p := #ADDRESS (#RING (duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer),     
            #SEGMENT (duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer),               
            duv$dump_environment_p^.critical_memory.critical_page_table_offset);                              
      RESET duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer TO cpt_p;                 
                                                                                                              
      number_page_entries := duv$dump_environment_p^.critical_memory.page_table_size * 64;                    
      NEXT critical_page_table_p: [0 .. (number_page_entries - 1)] IN                                         
            duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer;                          
      IF critical_page_table_p = NIL THEN                                                                     
        osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
      IF NOT critical_page_table_p^ [page_number].available THEN                                              
        osp$set_status_abnormal (duc$dump_analyzer_id, due$memory_not_critical, '', status);                  
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      page_offset := critical_page_table_p^ [page_number].page_offset;                                        
      memory_p := #ADDRESS (#RING (duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer),
            #SEGMENT (duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer),             
            (page_offset + remainder));                                                                       
                                                                                                              
      last_page_number := (offset + adjusted_size - 1) DIV page_size;                                         
      all_pages_available := TRUE;                                                                            
                                                                                                              
     /check_page_availability/                                                                                
      FOR last_available_page := page_number TO last_page_number DO                                           
        IF NOT critical_page_table_p^ [last_available_page].available THEN                                    
          all_pages_available := FALSE;                                                                       
          EXIT /check_page_availability/;  {---->                                                             
        IFEND;                                                                                                
      FOREND /check_page_availability/;                                                                       
                                                                                                              
      IF NOT all_pages_available THEN                                                                         
        osp$set_status_abnormal (duc$dump_analyzer_id, due$memory_partially_avail, '', status);               
        new_byte_size := (last_available_page * page_size) - offset;                                          
      ELSE                                                                                                    
        new_byte_size := adjusted_size;                                                                       
      IFEND;                                                                                                  
                                                                                                              
    ELSE  { memory not contained in MEM or critical memory }                                                  
      osp$set_status_abnormal (duc$dump_analyzer_id, due$memory_out_of_bounds, '', status);                   
    IFEND;                                                                                                    
                                                                                                              
  PROCEND dup$access_real_memory;                                                                             
MODEND dum$real_memory_access;                                                                                
