1 /* This file is part of the program psim. 2 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. 17 18 */ 19 20 21 #ifndef _CORE_C_ 22 #define _CORE_C_ 23 24 #include "basics.h" 25 #include "device_table.h" 26 #include "corefile.h" 27 #include "symcat.h" 28 29 typedef struct _core_mapping core_mapping; 30 struct _core_mapping { 31 /* common */ 32 int level; 33 int space; 34 unsigned_word base; 35 unsigned_word bound; 36 unsigned nr_bytes; 37 /* memory map */ 38 void *free_buffer; 39 void *buffer; 40 /* callback map */ 41 device *device; 42 /* growth */ 43 core_mapping *next; 44 }; 45 46 struct _core_map { 47 core_mapping *first; 48 }; 49 50 typedef enum { 51 core_read_map, 52 core_write_map, 53 core_execute_map, 54 nr_core_map_types, 55 } core_map_types; 56 57 struct _core { 58 core_map map[nr_core_map_types]; 59 }; 60 61 62 INLINE_CORE\ 63 (core *) 64 core_create(void) 65 { 66 return ZALLOC(core); 67 } 68 69 70 INLINE_CORE\ 71 (core *) 72 core_from_device(device *root) 73 { 74 root = device_root(root); 75 ASSERT(strcmp(device_name(root), "core") == 0); 76 return device_data(root); 77 } 78 79 80 INLINE_CORE\ 81 (void) 82 core_init(core *memory) 83 { 84 core_map_types access_type; 85 for (access_type = 0; 86 access_type < nr_core_map_types; 87 access_type++) { 88 core_map *map = memory->map + access_type; 89 /* blow away old mappings */ 90 core_mapping *curr = map->first; 91 while (curr != NULL) { 92 core_mapping *tbd = curr; 93 curr = curr->next; 94 if (tbd->free_buffer != NULL) { 95 ASSERT(tbd->buffer != NULL); 96 free(tbd->free_buffer); 97 } 98 free(tbd); 99 } 100 map->first = NULL; 101 } 102 } 103 104 105 106 /* the core has three sub mappings that the more efficient 107 read/write fixed quantity functions use */ 108 109 INLINE_CORE\ 110 (core_map *) 111 core_readable(core *memory) 112 { 113 return memory->map + core_read_map; 114 } 115 116 INLINE_CORE\ 117 (core_map *) 118 core_writeable(core *memory) 119 { 120 return memory->map + core_write_map; 121 } 122 123 INLINE_CORE\ 124 (core_map *) 125 core_executable(core *memory) 126 { 127 return memory->map + core_execute_map; 128 } 129 130 131 132 STATIC_INLINE_CORE\ 133 (core_mapping *) 134 new_core_mapping(attach_type attach, 135 int space, 136 unsigned_word addr, 137 unsigned nr_bytes, 138 device *device, 139 void *buffer, 140 void *free_buffer) 141 { 142 core_mapping *new_mapping = ZALLOC(core_mapping); 143 /* common */ 144 new_mapping->level = attach; 145 new_mapping->space = space; 146 new_mapping->base = addr; 147 new_mapping->nr_bytes = nr_bytes; 148 new_mapping->bound = addr + (nr_bytes - 1); 149 if (attach == attach_raw_memory) { 150 new_mapping->buffer = buffer; 151 new_mapping->free_buffer = free_buffer; 152 } 153 else if (attach >= attach_callback) { 154 new_mapping->device = device; 155 } 156 else { 157 error("new_core_mapping() - internal error - unknown attach type %d\n", 158 attach); 159 } 160 return new_mapping; 161 } 162 163 164 STATIC_INLINE_CORE\ 165 (void) 166 core_map_attach(core_map *access_map, 167 attach_type attach, 168 int space, 169 unsigned_word addr, 170 unsigned nr_bytes, /* host limited */ 171 device *client, /*callback/default*/ 172 void *buffer, /*raw_memory*/ 173 void *free_buffer) /*raw_memory*/ 174 { 175 /* find the insertion point for this additional mapping and insert */ 176 core_mapping *next_mapping; 177 core_mapping **last_mapping; 178 179 /* actually do occasionally get a zero size map */ 180 if (nr_bytes == 0) { 181 device_error(client, "called on core_map_attach() with size zero"); 182 } 183 184 /* find the insertion point (between last/next) */ 185 next_mapping = access_map->first; 186 last_mapping = &access_map->first; 187 while(next_mapping != NULL 188 && (next_mapping->level < attach 189 || (next_mapping->level == attach 190 && next_mapping->bound < addr))) { 191 /* provided levels are the same */ 192 /* assert: next_mapping->base > all bases before next_mapping */ 193 /* assert: next_mapping->bound >= all bounds before next_mapping */ 194 last_mapping = &next_mapping->next; 195 next_mapping = next_mapping->next; 196 } 197 198 /* check insertion point correct */ 199 ASSERT(next_mapping == NULL || next_mapping->level >= attach); 200 if (next_mapping != NULL && next_mapping->level == attach 201 && next_mapping->base < (addr + (nr_bytes - 1))) { 202 device_error(client, "map overlap when attaching %d:0x%lx (%ld)", 203 space, (long)addr, (long)nr_bytes); 204 } 205 206 /* create/insert the new mapping */ 207 *last_mapping = new_core_mapping(attach, 208 space, addr, nr_bytes, 209 client, buffer, free_buffer); 210 (*last_mapping)->next = next_mapping; 211 } 212 213 214 INLINE_CORE\ 215 (void) 216 core_attach(core *memory, 217 attach_type attach, 218 int space, 219 access_type access, 220 unsigned_word addr, 221 unsigned nr_bytes, /* host limited */ 222 device *client) /*callback/default*/ 223 { 224 core_map_types access_map; 225 void *buffer; 226 void *free_buffer; 227 if (attach == attach_raw_memory) { 228 /* Padd out the raw buffer to ensure that ADDR starts on a 229 correctly aligned boundary */ 230 int padding = (addr % sizeof (uint64_t)); 231 free_buffer = zalloc(nr_bytes + padding); 232 buffer = (char*)free_buffer + padding; 233 } 234 else { 235 buffer = NULL; 236 free_buffer = &buffer; /* marker for assertion */ 237 } 238 for (access_map = 0; 239 access_map < nr_core_map_types; 240 access_map++) { 241 switch (access_map) { 242 case core_read_map: 243 if (access & access_read) 244 core_map_attach(memory->map + access_map, 245 attach, 246 space, addr, nr_bytes, 247 client, buffer, free_buffer); 248 free_buffer = NULL; 249 break; 250 case core_write_map: 251 if (access & access_write) 252 core_map_attach(memory->map + access_map, 253 attach, 254 space, addr, nr_bytes, 255 client, buffer, free_buffer); 256 free_buffer = NULL; 257 break; 258 case core_execute_map: 259 if (access & access_exec) 260 core_map_attach(memory->map + access_map, 261 attach, 262 space, addr, nr_bytes, 263 client, buffer, free_buffer); 264 free_buffer = NULL; 265 break; 266 default: 267 error("core_attach() internal error\n"); 268 break; 269 } 270 } 271 /* allocated buffer must attach to at least one thing */ 272 ASSERT(free_buffer == NULL); 273 } 274 275 276 STATIC_INLINE_CORE\ 277 (core_mapping *) 278 core_map_find_mapping(core_map *map, 279 unsigned_word addr, 280 unsigned nr_bytes, 281 cpu *processor, 282 unsigned_word cia, 283 int abort) /*either 0 or 1 - helps inline */ 284 { 285 core_mapping *mapping = map->first; 286 ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */ 287 ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */ 288 while (mapping != NULL) { 289 if (addr >= mapping->base 290 && (addr + (nr_bytes - 1)) <= mapping->bound) 291 return mapping; 292 mapping = mapping->next; 293 } 294 if (abort) 295 error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=%p cia=0x%x\n", 296 addr, nr_bytes, (void *) processor, cia); 297 return NULL; 298 } 299 300 301 STATIC_INLINE_CORE\ 302 (void *) 303 core_translate(core_mapping *mapping, 304 unsigned_word addr) 305 { 306 return (void *)(((char *)mapping->buffer) + addr - mapping->base); 307 } 308 309 310 INLINE_CORE\ 311 (unsigned) 312 core_map_read_buffer(core_map *map, 313 void *buffer, 314 unsigned_word addr, 315 unsigned len) 316 { 317 unsigned count = 0; 318 while (count < len) { 319 unsigned_word raddr = addr + count; 320 core_mapping *mapping = 321 core_map_find_mapping(map, 322 raddr, 1, 323 NULL, /*processor*/ 324 0, /*cia*/ 325 0); /*dont-abort*/ 326 if (mapping == NULL) 327 break; 328 if (mapping->device != NULL) { 329 int nr_bytes = len - count; 330 if (raddr + nr_bytes - 1> mapping->bound) 331 nr_bytes = mapping->bound - raddr + 1; 332 if (device_io_read_buffer(mapping->device, 333 (unsigned_1*)buffer + count, 334 mapping->space, 335 raddr, 336 nr_bytes, 337 0, /*processor*/ 338 0 /*cpu*/) != nr_bytes) 339 break; 340 count += nr_bytes; 341 } 342 else { 343 ((unsigned_1*)buffer)[count] = 344 *(unsigned_1*)core_translate(mapping, raddr); 345 count += 1; 346 } 347 } 348 return count; 349 } 350 351 352 INLINE_CORE\ 353 (unsigned) 354 core_map_write_buffer(core_map *map, 355 const void *buffer, 356 unsigned_word addr, 357 unsigned len) 358 { 359 unsigned count = 0; 360 while (count < len) { 361 unsigned_word raddr = addr + count; 362 core_mapping *mapping = core_map_find_mapping(map, 363 raddr, 1, 364 NULL, /*processor*/ 365 0, /*cia*/ 366 0); /*dont-abort*/ 367 if (mapping == NULL) 368 break; 369 if (mapping->device != NULL) { 370 int nr_bytes = len - count; 371 if (raddr + nr_bytes - 1 > mapping->bound) 372 nr_bytes = mapping->bound - raddr + 1; 373 if (device_io_write_buffer(mapping->device, 374 (unsigned_1*)buffer + count, 375 mapping->space, 376 raddr, 377 nr_bytes, 378 0, /*processor*/ 379 0 /*cpu*/) != nr_bytes) 380 break; 381 count += nr_bytes; 382 } 383 else { 384 *(unsigned_1*)core_translate(mapping, raddr) = 385 ((unsigned_1*)buffer)[count]; 386 count += 1; 387 } 388 } 389 return count; 390 } 391 392 393 /* define the read/write 1/2/4/8/word functions */ 394 395 #define N 1 396 #include "corefile-n.h" 397 #undef N 398 399 #define N 2 400 #include "corefile-n.h" 401 #undef N 402 403 #define N 4 404 #include "corefile-n.h" 405 #undef N 406 407 #define N 8 408 #include "corefile-n.h" 409 #undef N 410 411 #define N word 412 #include "corefile-n.h" 413 #undef N 414 415 #endif /* _CORE_C_ */ 416