123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- /* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- */
- #ifndef _CORE_C_
- #define _CORE_C_
- #include "basics.h"
- #include "device_table.h"
- #include "corefile.h"
- typedef struct _core_mapping core_mapping;
- struct _core_mapping {
- /* common */
- int level;
- int space;
- unsigned_word base;
- unsigned_word bound;
- unsigned nr_bytes;
- /* memory map */
- void *free_buffer;
- void *buffer;
- /* callback map */
- device *device;
- /* growth */
- core_mapping *next;
- };
- struct _core_map {
- core_mapping *first;
- };
- typedef enum {
- core_read_map,
- core_write_map,
- core_execute_map,
- nr_core_map_types,
- } core_map_types;
- struct _core {
- core_map map[nr_core_map_types];
- };
- INLINE_CORE\
- (core *)
- core_create(void)
- {
- return ZALLOC(core);
- }
- INLINE_CORE\
- (core *)
- core_from_device(device *root)
- {
- root = device_root(root);
- ASSERT(strcmp(device_name(root), "core") == 0);
- return device_data(root);
- }
- INLINE_CORE\
- (void)
- core_init(core *memory)
- {
- core_map_types access_type;
- for (access_type = 0;
- access_type < nr_core_map_types;
- access_type++) {
- core_map *map = memory->map + access_type;
- /* blow away old mappings */
- core_mapping *curr = map->first;
- while (curr != NULL) {
- core_mapping *tbd = curr;
- curr = curr->next;
- if (tbd->free_buffer != NULL) {
- ASSERT(tbd->buffer != NULL);
- free(tbd->free_buffer);
- }
- free(tbd);
- }
- map->first = NULL;
- }
- }
- /* the core has three sub mappings that the more efficient
- read/write fixed quantity functions use */
- INLINE_CORE\
- (core_map *)
- core_readable(core *memory)
- {
- return memory->map + core_read_map;
- }
- INLINE_CORE\
- (core_map *)
- core_writeable(core *memory)
- {
- return memory->map + core_write_map;
- }
- INLINE_CORE\
- (core_map *)
- core_executable(core *memory)
- {
- return memory->map + core_execute_map;
- }
- STATIC_INLINE_CORE\
- (core_mapping *)
- new_core_mapping(attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- device *device,
- void *buffer,
- void *free_buffer)
- {
- core_mapping *new_mapping = ZALLOC(core_mapping);
- /* common */
- new_mapping->level = attach;
- new_mapping->space = space;
- new_mapping->base = addr;
- new_mapping->nr_bytes = nr_bytes;
- new_mapping->bound = addr + (nr_bytes - 1);
- if (attach == attach_raw_memory) {
- new_mapping->buffer = buffer;
- new_mapping->free_buffer = free_buffer;
- }
- else if (attach >= attach_callback) {
- new_mapping->device = device;
- }
- else {
- error("new_core_mapping() - internal error - unknown attach type %d\n",
- attach);
- }
- return new_mapping;
- }
- STATIC_INLINE_CORE\
- (void)
- core_map_attach(core_map *access_map,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes, /* host limited */
- device *client, /*callback/default*/
- void *buffer, /*raw_memory*/
- void *free_buffer) /*raw_memory*/
- {
- /* find the insertion point for this additional mapping and insert */
- core_mapping *next_mapping;
- core_mapping **last_mapping;
- /* actually do occasionally get a zero size map */
- if (nr_bytes == 0) {
- device_error(client, "called on core_map_attach() with size zero");
- }
- /* find the insertion point (between last/next) */
- next_mapping = access_map->first;
- last_mapping = &access_map->first;
- while(next_mapping != NULL
- && (next_mapping->level < attach
- || (next_mapping->level == attach
- && next_mapping->bound < addr))) {
- /* provided levels are the same */
- /* assert: next_mapping->base > all bases before next_mapping */
- /* assert: next_mapping->bound >= all bounds before next_mapping */
- last_mapping = &next_mapping->next;
- next_mapping = next_mapping->next;
- }
- /* check insertion point correct */
- ASSERT(next_mapping == NULL || next_mapping->level >= attach);
- if (next_mapping != NULL && next_mapping->level == attach
- && next_mapping->base < (addr + (nr_bytes - 1))) {
- device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
- space, (long)addr, (long)nr_bytes);
- }
- /* create/insert the new mapping */
- *last_mapping = new_core_mapping(attach,
- space, addr, nr_bytes,
- client, buffer, free_buffer);
- (*last_mapping)->next = next_mapping;
- }
- INLINE_CORE\
- (void)
- core_attach(core *memory,
- attach_type attach,
- int space,
- access_type access,
- unsigned_word addr,
- unsigned nr_bytes, /* host limited */
- device *client) /*callback/default*/
- {
- core_map_types access_map;
- void *buffer;
- void *free_buffer;
- if (attach == attach_raw_memory) {
- /* Padd out the raw buffer to ensure that ADDR starts on a
- correctly aligned boundary */
- int padding = (addr % sizeof (unsigned64));
- free_buffer = zalloc(nr_bytes + padding);
- buffer = (char*)free_buffer + padding;
- }
- else {
- buffer = NULL;
- free_buffer = &buffer; /* marker for assertion */
- }
- for (access_map = 0;
- access_map < nr_core_map_types;
- access_map++) {
- switch (access_map) {
- case core_read_map:
- if (access & access_read)
- core_map_attach(memory->map + access_map,
- attach,
- space, addr, nr_bytes,
- client, buffer, free_buffer);
- free_buffer = NULL;
- break;
- case core_write_map:
- if (access & access_write)
- core_map_attach(memory->map + access_map,
- attach,
- space, addr, nr_bytes,
- client, buffer, free_buffer);
- free_buffer = NULL;
- break;
- case core_execute_map:
- if (access & access_exec)
- core_map_attach(memory->map + access_map,
- attach,
- space, addr, nr_bytes,
- client, buffer, free_buffer);
- free_buffer = NULL;
- break;
- default:
- error("core_attach() internal error\n");
- break;
- }
- }
- /* allocated buffer must attach to at least one thing */
- ASSERT(free_buffer == NULL);
- }
- STATIC_INLINE_CORE\
- (core_mapping *)
- core_map_find_mapping(core_map *map,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia,
- int abort) /*either 0 or 1 - helps inline */
- {
- core_mapping *mapping = map->first;
- ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
- ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
- while (mapping != NULL) {
- if (addr >= mapping->base
- && (addr + (nr_bytes - 1)) <= mapping->bound)
- return mapping;
- mapping = mapping->next;
- }
- if (abort)
- error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=0x%x cia=0x%x\n",
- addr, nr_bytes, processor, cia);
- return NULL;
- }
- STATIC_INLINE_CORE\
- (void *)
- core_translate(core_mapping *mapping,
- unsigned_word addr)
- {
- return (void *)(((char *)mapping->buffer) + addr - mapping->base);
- }
- INLINE_CORE\
- (unsigned)
- core_map_read_buffer(core_map *map,
- void *buffer,
- unsigned_word addr,
- unsigned len)
- {
- unsigned count = 0;
- while (count < len) {
- unsigned_word raddr = addr + count;
- core_mapping *mapping =
- core_map_find_mapping(map,
- raddr, 1,
- NULL, /*processor*/
- 0, /*cia*/
- 0); /*dont-abort*/
- if (mapping == NULL)
- break;
- if (mapping->device != NULL) {
- int nr_bytes = len - count;
- if (raddr + nr_bytes - 1> mapping->bound)
- nr_bytes = mapping->bound - raddr + 1;
- if (device_io_read_buffer(mapping->device,
- (unsigned_1*)buffer + count,
- mapping->space,
- raddr,
- nr_bytes,
- 0, /*processor*/
- 0 /*cpu*/) != nr_bytes)
- break;
- count += nr_bytes;
- }
- else {
- ((unsigned_1*)buffer)[count] =
- *(unsigned_1*)core_translate(mapping, raddr);
- count += 1;
- }
- }
- return count;
- }
- INLINE_CORE\
- (unsigned)
- core_map_write_buffer(core_map *map,
- const void *buffer,
- unsigned_word addr,
- unsigned len)
- {
- unsigned count = 0;
- while (count < len) {
- unsigned_word raddr = addr + count;
- core_mapping *mapping = core_map_find_mapping(map,
- raddr, 1,
- NULL, /*processor*/
- 0, /*cia*/
- 0); /*dont-abort*/
- if (mapping == NULL)
- break;
- if (mapping->device != NULL) {
- int nr_bytes = len - count;
- if (raddr + nr_bytes - 1 > mapping->bound)
- nr_bytes = mapping->bound - raddr + 1;
- if (device_io_write_buffer(mapping->device,
- (unsigned_1*)buffer + count,
- mapping->space,
- raddr,
- nr_bytes,
- 0, /*processor*/
- 0 /*cpu*/) != nr_bytes)
- break;
- count += nr_bytes;
- }
- else {
- *(unsigned_1*)core_translate(mapping, raddr) =
- ((unsigned_1*)buffer)[count];
- count += 1;
- }
- }
- return count;
- }
- /* define the read/write 1/2/4/8/word functions */
- #define N 1
- #include "corefile-n.h"
- #undef N
- #define N 2
- #include "corefile-n.h"
- #undef N
- #define N 4
- #include "corefile-n.h"
- #undef N
- #define N 8
- #include "corefile-n.h"
- #undef N
- #define N word
- #include "corefile-n.h"
- #undef N
- #endif /* _CORE_C_ */
|