/******************************************************************** * Description: physmem.cc * Provides the member functions for the PHYSMEM_HANDLE class. This * is a C++ interface for portable access to physical memory. * * Derived from a work by Fred Proctor & Will Shackleford * * Author: * License: LGPL Version 2 * System: Linux * * Copyright (c) 2004 All rights reserved. * * Last change: ********************************************************************/ #ifdef __cplusplus extern "C" { #endif #include /* memcpy(), memset() */ #include // sprintf() #include /* malloc() */ #ifdef __cplusplus } #endif #include "physmem.hh" /* class PHYSMEM_HANDLE */ #include "rcs_print.hh" PHYSMEM_HANDLE::PHYSMEM_HANDLE() { size = 0; offset = 0; temp_buf = NULL; local_address = (LOCAL_ADDRESS_TYPE) NULL; physical_address = 0; using_bit3 = 0; isvalid = 1; total_bytes_moved = 0; enable_byte_counting = 0; } PHYSMEM_HANDLE::PHYSMEM_HANDLE(unsigned long _physical_address, long _address_code, long _size) { temp_buf = NULL; physical_address = _physical_address; size = _size; address_code = _address_code; local_address = (LOCAL_ADDRESS_TYPE) NULL; isvalid = 1; offset = 0; using_bit3 = 0; if (0 == physical_address) { local_address = (LOCAL_ADDRESS_TYPE) NULL; return; } local_address = (LOCAL_ADDRESS_TYPE) physical_address; } /* Destructor. */ PHYSMEM_HANDLE::~PHYSMEM_HANDLE() { } /* Use an ordinary pointer to access memory. */ void PHYSMEM_HANDLE::set_to_ptr(void *_ptr, long _size) { local_address = (LOCAL_ADDRESS_TYPE) _ptr; size = _size; offset = 0; } static int physmem_read_local_address_is_null_error_print_count = 0; /*********************************************************** * Read _read_size bytes from physical memory to store at _to. * Returns: 0 for success or -1 for failure. **********************************************************/ int PHYSMEM_HANDLE::read(void *_to, long _read_size) { if (NULL == _to) { rcs_print_error("PHYSMEM_HANDLE::read _to = NULL.\n"); return (-1); } /* Check sizes. */ if (_read_size + offset > size || offset < 0) { rcs_print_error ("PHYSMEM_HANDLE: Can't read %ld bytes at offset %ld from buffer of size %ld.\n", _read_size, offset, size); return (-1); } if (enable_byte_counting) { total_bytes_moved += _read_size; } /* If local_address has been initialized use it as an ordinary pointer. */ if (NULL != local_address) { char *from; from = ((char *) local_address) + offset; if (_read_size == 2) { short *sfrom = (short *) from; short sval; sval = *sfrom; short *sto = (short *) _to; *sto = sval; } else { memcpy(_to, from, _read_size); } return (0); } /* include platform specific ways of accessing phsical memory here. */ if (!(physmem_read_local_address_is_null_error_print_count % 100000)) { rcs_print_error ("PHYSMEM_HANDLE: Cannot read from physical memory when local address is NULL.\n"); rcs_print_error("(This error has occured %d times.)\n", physmem_read_local_address_is_null_error_print_count + 1); } physmem_read_local_address_is_null_error_print_count++; return (-1); } static int physmem_write_local_address_is_null_error_print_count = 0; /*********************************************************** * Write _write_size bytes from memory at _from to physical memory. * Returns: 0 for success or -1 for failure. **********************************************************/ int PHYSMEM_HANDLE::write(void *_from, long _write_size) { if (NULL == _from) { rcs_print_error("PHYSMEM_HANDLE:write _from = NULL\n"); return -1; } /* Check sizes. */ if (_write_size + offset > size || offset < 0) { rcs_print_error ("PHYSMEM_HANDLE: Can't write %ld bytes at offset %ld from buffer of size %ld.\n", _write_size, offset, size); return (-1); } if (enable_byte_counting) { total_bytes_moved += _write_size; } /* If local_address has been initialized use it as an ordinary pointer. */ if (NULL != local_address) { char *to; to = ((char *) local_address) + offset; if (_write_size == 2) { short *sto = (short *) to; short sval = *(short *) _from; *sto = sval; } else { memcpy(to, _from, _write_size); } return (0); } /* include platform specific ways of accessing phsical memory here. */ if (!(physmem_write_local_address_is_null_error_print_count % 100000)) { rcs_print_error ("PHYSMEM_HANDLE: Cannot write to physical memory when local address is NULL.\n"); rcs_print_error("(This error has occured %d times.)\n", physmem_write_local_address_is_null_error_print_count + 1); } physmem_write_local_address_is_null_error_print_count++; return (-1); } void PHYSMEM_HANDLE::memsetf(long _memset_offset, char _byte, long _memset_size) { /* Check sizes. */ if (_memset_size + _memset_offset > size) { return; } /* If local_address has been initialized use it as an ordinary pointer. */ if (NULL != local_address) { char *temp_addr; temp_addr = ((char *) local_address) + _memset_offset; memset(temp_addr, _byte, _memset_size); return; } else { /* Since local address is not initialized use temp_buf and write to access the physical memory in an platform specific way. */ if (NULL == temp_buf) { temp_buf = (char *) malloc(size); } if (NULL != temp_buf) { if (_memset_size + _memset_offset <= size) { memset(temp_buf, _byte, _memset_size); unsigned long old_offset; old_offset = offset; offset = _memset_offset; write(temp_buf, _memset_size); offset = old_offset; } else { memset(temp_buf, _byte, size - _memset_offset); unsigned long old_offset; old_offset = offset; offset = _memset_offset; write(temp_buf, size - offset); offset = old_offset; } } } } int PHYSMEM_HANDLE::clear_memory() { /* If local_address has been initialized use it as an ordinary pointer. */ if (NULL != local_address) { memset(local_address, 0, size); return (0); } else { /* Since local address is not initialized use temp_buf and write to access the physical memory in an platform specific way. */ if (NULL == temp_buf) { temp_buf = (char *) malloc(size); } if (NULL == temp_buf) { return (-1); } memset(temp_buf, 0, size); unsigned long old_offset; old_offset = offset; offset = 0; if (-1 == write(temp_buf, size)) { offset = old_offset; return (-1); } offset = old_offset; } return (0); } int PHYSMEM_HANDLE::valid() { return isvalid; }