/ src / libnml / buffer / physmem.cc
physmem.cc
  1  /********************************************************************
  2  * Description: physmem.cc
  3  *   Provides the member functions for the PHYSMEM_HANDLE class. This
  4  *   is a C++ interface for portable access to physical memory.
  5  *
  6  *   Derived from a work by Fred Proctor & Will Shackleford
  7  *
  8  * Author:
  9  * License: LGPL Version 2
 10  * System: Linux
 11  *    
 12  * Copyright (c) 2004 All rights reserved.
 13  *
 14  * Last change: 
 15  ********************************************************************/
 16  
 17  #ifdef __cplusplus
 18  extern "C" {
 19  #endif
 20  
 21  #include <string.h>		/* memcpy(), memset() */
 22  #include <stdio.h>		// sprintf()
 23  #include <stdlib.h>		/* malloc() */
 24  
 25  #ifdef __cplusplus
 26  }
 27  #endif
 28  #include "physmem.hh"		/* class PHYSMEM_HANDLE */
 29  #include "rcs_print.hh"
 30  PHYSMEM_HANDLE::PHYSMEM_HANDLE()
 31  {
 32      size = 0;
 33      offset = 0;
 34      temp_buf = NULL;
 35      local_address = (LOCAL_ADDRESS_TYPE) NULL;
 36      physical_address = 0;
 37      using_bit3 = 0;
 38      isvalid = 1;
 39      total_bytes_moved = 0;
 40      enable_byte_counting = 0;
 41  
 42  }
 43  
 44  PHYSMEM_HANDLE::PHYSMEM_HANDLE(unsigned long _physical_address,
 45      long _address_code, long _size)
 46  {
 47      temp_buf = NULL;
 48      physical_address = _physical_address;
 49      size = _size;
 50      address_code = _address_code;
 51      local_address = (LOCAL_ADDRESS_TYPE) NULL;
 52      isvalid = 1;
 53      offset = 0;
 54      using_bit3 = 0;
 55  
 56      if (0 == physical_address) {
 57  	local_address = (LOCAL_ADDRESS_TYPE) NULL;
 58  	return;
 59      }
 60      local_address = (LOCAL_ADDRESS_TYPE) physical_address;
 61  }
 62  
 63  /* Destructor. */
 64  PHYSMEM_HANDLE::~PHYSMEM_HANDLE()
 65  {
 66  }
 67  
 68  /* Use an ordinary pointer to access memory. */
 69  void
 70    PHYSMEM_HANDLE::set_to_ptr(void *_ptr, long _size)
 71  {
 72      local_address = (LOCAL_ADDRESS_TYPE) _ptr;
 73      size = _size;
 74      offset = 0;
 75  }
 76  
 77  static int physmem_read_local_address_is_null_error_print_count = 0;
 78  
 79  /***********************************************************
 80  * Read _read_size bytes from physical memory to store at _to.
 81  * Returns: 0 for success or -1 for failure.
 82  **********************************************************/
 83  int PHYSMEM_HANDLE::read(void *_to, long _read_size)
 84  {
 85      if (NULL == _to) {
 86  	rcs_print_error("PHYSMEM_HANDLE::read _to = NULL.\n");
 87  	return (-1);
 88      }
 89      /* Check sizes. */
 90      if (_read_size + offset > size || offset < 0) {
 91  	rcs_print_error
 92  	    ("PHYSMEM_HANDLE: Can't read %ld bytes at offset %ld from buffer of size %ld.\n",
 93  	    _read_size, offset, size);
 94  	return (-1);
 95      }
 96  
 97      if (enable_byte_counting) {
 98  	total_bytes_moved += _read_size;
 99      }
100  
101      /* If local_address has been initialized use it as an ordinary pointer. */
102      if (NULL != local_address) {
103  	char *from;
104  	from = ((char *) local_address) + offset;
105  	if (_read_size == 2) {
106  	    short *sfrom = (short *) from;
107  	    short sval;
108  	    sval = *sfrom;
109  	    short *sto = (short *) _to;
110  	    *sto = sval;
111  	} else {
112  	    memcpy(_to, from, _read_size);
113  	}
114  	return (0);
115      }
116  
117      /* include platform specific ways of accessing phsical memory here. */
118      if (!(physmem_read_local_address_is_null_error_print_count % 100000)) {
119  	rcs_print_error
120  	    ("PHYSMEM_HANDLE: Cannot read from physical memory when local address is NULL.\n");
121  	rcs_print_error("(This error has occurred %d times.)\n",
122  	    physmem_read_local_address_is_null_error_print_count + 1);
123      }
124      physmem_read_local_address_is_null_error_print_count++;
125      return (-1);
126  }
127  
128  static int physmem_write_local_address_is_null_error_print_count = 0;
129  
130  /***********************************************************
131  * Write _write_size bytes from memory at _from to physical memory.
132  * Returns: 0 for success or -1 for failure.
133  **********************************************************/
134  int PHYSMEM_HANDLE::write(void *_from, long _write_size)
135  {
136      if (NULL == _from) {
137  	rcs_print_error("PHYSMEM_HANDLE:write _from = NULL\n");
138  	return -1;
139      }
140  
141      /* Check sizes. */
142      if (_write_size + offset > size || offset < 0) {
143  	rcs_print_error
144  	    ("PHYSMEM_HANDLE: Can't write %ld bytes at offset %ld from buffer of size %ld.\n",
145  	    _write_size, offset, size);
146  	return (-1);
147      }
148      if (enable_byte_counting) {
149  	total_bytes_moved += _write_size;
150      }
151      /* If local_address has been initialized use it as an ordinary pointer. */
152      if (NULL != local_address) {
153  	char *to;
154  	to = ((char *) local_address) + offset;
155  	if (_write_size == 2) {
156  	    short *sto = (short *) to;
157  	    short sval = *(short *) _from;
158  	    *sto = sval;
159  	} else {
160  	    memcpy(to, _from, _write_size);
161  	}
162  	return (0);
163      }
164  
165      /* include platform specific ways of accessing phsical memory here. */
166      if (!(physmem_write_local_address_is_null_error_print_count % 100000)) {
167  	rcs_print_error
168  	    ("PHYSMEM_HANDLE: Cannot write to physical memory when local address is NULL.\n");
169  	rcs_print_error("(This error has occurred %d times.)\n",
170  	    physmem_write_local_address_is_null_error_print_count + 1);
171      }
172      physmem_write_local_address_is_null_error_print_count++;
173      return (-1);
174  }
175  
176  void PHYSMEM_HANDLE::memsetf(long _memset_offset, char _byte,
177      long _memset_size)
178  {
179      /* Check sizes. */
180      if (_memset_size + _memset_offset > size) {
181  	return;
182      }
183  
184      /* If local_address has been initialized use it as an ordinary pointer. */
185      if (NULL != local_address) {
186  	char *temp_addr;
187  	temp_addr = ((char *) local_address) + _memset_offset;
188  	memset(temp_addr, _byte, _memset_size);
189  	return;
190      } else {
191  	/* Since local address is not initialized use temp_buf and write to
192  	   access the physical memory in an platform specific way. */
193  	if (NULL == temp_buf) {
194  	    temp_buf = (char *) malloc(size);
195  	}
196  	if (NULL != temp_buf) {
197  	    if (_memset_size + _memset_offset <= size) {
198  		memset(temp_buf, _byte, _memset_size);
199  		unsigned long old_offset;
200  		old_offset = offset;
201  		offset = _memset_offset;
202  		write(temp_buf, _memset_size);
203  		offset = old_offset;
204  	    } else {
205  		memset(temp_buf, _byte, size - _memset_offset);
206  		unsigned long old_offset;
207  		old_offset = offset;
208  		offset = _memset_offset;
209  		write(temp_buf, size - offset);
210  		offset = old_offset;
211  	    }
212  	}
213      }
214  }
215  
216  int PHYSMEM_HANDLE::clear_memory()
217  {
218      /* If local_address has been initialized use it as an ordinary pointer. */
219      if (NULL != local_address) {
220  	memset(local_address, 0, size);
221  	return (0);
222      } else {
223  	/* Since local address is not initialized use temp_buf and write to
224  	   access the physical memory in an platform specific way. */
225  	if (NULL == temp_buf) {
226  	    temp_buf = (char *) malloc(size);
227  	}
228  	if (NULL == temp_buf) {
229  	    return (-1);
230  	}
231  	memset(temp_buf, 0, size);
232  	unsigned long old_offset;
233  	old_offset = offset;
234  	offset = 0;
235  	if (-1 == write(temp_buf, size)) {
236  	    offset = old_offset;
237  	    return (-1);
238  	}
239  	offset = old_offset;
240      }
241      return (0);
242  }
243  
244  int PHYSMEM_HANDLE::valid()
245  {
246      return isvalid;
247  }