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 }