10Sduke/* This file is part of the program psim. 210287Sddmitriev 30Sduke Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> 40Sduke 50Sduke This program is free software; you can redistribute it and/or modify 60Sduke it under the terms of the GNU General Public License as published by 70Sduke the Free Software Foundation; either version 2 of the License, or 80Sduke (at your option) any later version. 90Sduke 100Sduke This program is distributed in the hope that it will be useful, 110Sduke but WITHOUT ANY WARRANTY; without even the implied warranty of 120Sduke MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 130Sduke GNU General Public License for more details. 140Sduke 150Sduke You should have received a copy of the GNU General Public License 160Sduke along with this program; if not, write to the Free Software 170Sduke Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 180Sduke 191472Strims */ 201472Strims 211472Strims 220Sduke#ifndef _CORE_C_ 230Sduke#define _CORE_C_ 240Sduke 251879Sstefank#include "basics.h" 261879Sstefank#include "device_table.h" 271879Sstefank#include "corefile.h" 281879Sstefank 291879Sstefanktypedef struct _core_mapping core_mapping; 301879Sstefankstruct _core_mapping { 318569Sgziemski /* common */ 3211219Sgziemski int level; 338569Sgziemski int space; 347331Sgoetz unsigned_word base; 358569Sgziemski unsigned_word bound; 367425Sstefank unsigned nr_bytes; 3711219Sgziemski /* memory map */ 388413Spliden void *free_buffer; 391879Sstefank void *buffer; 404107Sjprovino /* callback map */ 418413Spliden device *device; 424107Sjprovino /* growth */ 431879Sstefank core_mapping *next; 441879Sstefank}; 451879Sstefank 469111Stwististruct _core_map { 479111Stwisti core_mapping *first; 489111Stwisti}; 491879Sstefank 501879Sstefanktypedef enum { 511879Sstefank core_read_map, 521879Sstefank core_write_map, 531879Sstefank core_execute_map, 541879Sstefank nr_core_map_types, 550Sduke} core_map_types; 568569Sgziemski 578569Sgziemskistruct _core { 588569Sgziemski core_map map[nr_core_map_types]; 598569Sgziemski}; 608569Sgziemski 6111390Scsahu 628569SgziemskiINLINE_CORE\ 632852Sphh(core *) 648569Sgziemskicore_create(void) 658569Sgziemski{ 668569Sgziemski return ZALLOC(core); 678569Sgziemski} 6811219Sgziemski 6911219Sgziemski 700SdukeINLINE_CORE\ 718569Sgziemski(core *) 728569Sgziemskicore_from_device(device *root) 738569Sgziemski{ 748569Sgziemski root = device_root(root); 758569Sgziemski ASSERT(strcmp(device_name(root), "core") == 0); 7611390Scsahu return device_data(root); 778569Sgziemski} 788569Sgziemski 7911219Sgziemski 8011219SgziemskiINLINE_CORE\ 810Sduke(void) 828569Sgziemskicore_init(core *memory) 838569Sgziemski{ 848569Sgziemski core_map_types access_type; 858569Sgziemski for (access_type = 0; 868569Sgziemski access_type < nr_core_map_types; 878569Sgziemski access_type++) { 8811219Sgziemski core_map *map = memory->map + access_type; 8911219Sgziemski /* blow away old mappings */ 903585Stwisti core_mapping *curr = map->first; 912868Sphh while (curr != NULL) { 922868Sphh core_mapping *tbd = curr; 9310722Sgziemski curr = curr->next; 9410722Sgziemski if (tbd->free_buffer != NULL) { 9510722Sgziemski ASSERT(tbd->buffer != NULL); 9610722Sgziemski free(tbd->free_buffer); 9710722Sgziemski } 9810722Sgziemski free(tbd); 9910722Sgziemski } 10010722Sgziemski map->first = NULL; 10110722Sgziemski } 10210722Sgziemski} 10310722Sgziemski 10410722Sgziemski 10510722Sgziemski 10610722Sgziemski/* the core has three sub mappings that the more efficient 10710722Sgziemski read/write fixed quantity functions use */ 10810722Sgziemski 10910722SgziemskiINLINE_CORE\ 11010722Sgziemski(core_map *) 11110722Sgziemskicore_readable(core *memory) 11210722Sgziemski{ 11310722Sgziemski return memory->map + core_read_map; 11410722Sgziemski} 11510722Sgziemski 11610722SgziemskiINLINE_CORE\ 11710722Sgziemski(core_map *) 11810722Sgziemskicore_writeable(core *memory) 11910722Sgziemski{ 12010722Sgziemski return memory->map + core_write_map; 12110722Sgziemski} 12210722Sgziemski 12310722SgziemskiINLINE_CORE\ 12410722Sgziemski(core_map *) 12510722Sgziemskicore_executable(core *memory) 12610722Sgziemski{ 12710722Sgziemski return memory->map + core_execute_map; 12810722Sgziemski} 12910722Sgziemski 13010722Sgziemski 13110722Sgziemski 13210722SgziemskiSTATIC_INLINE_CORE\ 13310722Sgziemski(core_mapping *) 13410722Sgziemskinew_core_mapping(attach_type attach, 13510722Sgziemski int space, 13610722Sgziemski unsigned_word addr, 13710722Sgziemski unsigned nr_bytes, 13810722Sgziemski device *device, 13910722Sgziemski void *buffer, 14010722Sgziemski void *free_buffer) 14110722Sgziemski{ 14210722Sgziemski core_mapping *new_mapping = ZALLOC(core_mapping); 1435829Sccheung /* common */ 1445829Sccheung new_mapping->level = attach; 1455829Sccheung new_mapping->space = space; 1465829Sccheung new_mapping->base = addr; 1475829Sccheung new_mapping->nr_bytes = nr_bytes; 1485829Sccheung new_mapping->bound = addr + (nr_bytes - 1); 1495829Sccheung if (attach == attach_raw_memory) { 1505829Sccheung new_mapping->buffer = buffer; 15111219Sgziemski new_mapping->free_buffer = free_buffer; 1525355Stwisti } 1539056Sdavid else if (attach >= attach_callback) { 1545355Stwisti new_mapping->device = device; 15511219Sgziemski } 15611219Sgziemski else { 15711219Sgziemski error("new_core_mapping() - internal error - unknown attach type %d\n", 15811219Sgziemski attach); 15911219Sgziemski } 16011219Sgziemski return new_mapping; 16111219Sgziemski} 16211219Sgziemski 16311219Sgziemski 16411219SgziemskiSTATIC_INLINE_CORE\ 16511219Sgziemski(void) 16611219Sgziemskicore_map_attach(core_map *access_map, 16711219Sgziemski attach_type attach, 16811219Sgziemski int space, 16911219Sgziemski unsigned_word addr, 17011219Sgziemski unsigned nr_bytes, /* host limited */ 17111219Sgziemski device *client, /*callback/default*/ 17211219Sgziemski void *buffer, /*raw_memory*/ 17311219Sgziemski void *free_buffer) /*raw_memory*/ 17411219Sgziemski{ 17511219Sgziemski /* find the insertion point for this additional mapping and insert */ 17611219Sgziemski core_mapping *next_mapping; 17711219Sgziemski core_mapping **last_mapping; 17811219Sgziemski 17911219Sgziemski /* actually do occasionally get a zero size map */ 1805355Stwisti if (nr_bytes == 0) { 1815355Stwisti device_error(client, "called on core_map_attach() with size zero"); 1825355Stwisti } 1835355Stwisti 1845355Stwisti /* find the insertion point (between last/next) */ 1855355Stwisti next_mapping = access_map->first; 1865355Stwisti last_mapping = &access_map->first; 1875355Stwisti while(next_mapping != NULL 1885355Stwisti && (next_mapping->level < attach 1895355Stwisti || (next_mapping->level == attach 19011219Sgziemski && next_mapping->bound < addr))) { 19111219Sgziemski /* provided levels are the same */ 19211219Sgziemski /* assert: next_mapping->base > all bases before next_mapping */ 19311219Sgziemski /* assert: next_mapping->bound >= all bounds before next_mapping */ 19411219Sgziemski last_mapping = &next_mapping->next; 19511219Sgziemski next_mapping = next_mapping->next; 1965355Stwisti } 1975355Stwisti 1988522Sdavid /* check insertion point correct */ 1998522Sdavid ASSERT(next_mapping == NULL || next_mapping->level >= attach); 2008522Sdavid if (next_mapping != NULL && next_mapping->level == attach 2018522Sdavid && next_mapping->base < (addr + (nr_bytes - 1))) { 2028522Sdavid device_error(client, "map overlap when attaching %d:0x%lx (%ld)", 2038522Sdavid space, (long)addr, (long)nr_bytes); 2048522Sdavid } 2058522Sdavid 20611219Sgziemski /* create/insert the new mapping */ 20711219Sgziemski *last_mapping = new_core_mapping(attach, 20811219Sgziemski space, addr, nr_bytes, 20911219Sgziemski client, buffer, free_buffer); 21011219Sgziemski (*last_mapping)->next = next_mapping; 21111219Sgziemski} 2128522Sdavid 2138522Sdavid 2148522SdavidINLINE_CORE\ 2158522Sdavid(void) 2168522Sdavidcore_attach(core *memory, 2178522Sdavid attach_type attach, 2188522Sdavid int space, 2198522Sdavid access_type access, 2208522Sdavid unsigned_word addr, 2218522Sdavid unsigned nr_bytes, /* host limited */ 22211219Sgziemski device *client) /*callback/default*/ 22311219Sgziemski{ 22411219Sgziemski core_map_types access_map; 22511219Sgziemski void *buffer; 22611219Sgziemski void *free_buffer; 22711219Sgziemski if (attach == attach_raw_memory) { 2288522Sdavid /* Padd out the raw buffer to ensure that ADDR starts on a 2298522Sdavid correctly aligned boundary */ 2305355Stwisti int padding = (addr % sizeof (unsigned64)); 2315355Stwisti free_buffer = zalloc(nr_bytes + padding); 2325355Stwisti buffer = (char*)free_buffer + padding; 2335355Stwisti } 2345355Stwisti else { 2355355Stwisti buffer = NULL; 2365355Stwisti free_buffer = &buffer; /* marker for assertion */ 2375355Stwisti } 23811219Sgziemski for (access_map = 0; 23911219Sgziemski access_map < nr_core_map_types; 24011219Sgziemski access_map++) { 24111219Sgziemski switch (access_map) { 24211219Sgziemski case core_read_map: 24311219Sgziemski if (access & access_read) 2445355Stwisti core_map_attach(memory->map + access_map, 2455355Stwisti attach, 2465355Stwisti space, addr, nr_bytes, 2475355Stwisti client, buffer, free_buffer); 2485355Stwisti free_buffer = NULL; 2495355Stwisti break; 2505355Stwisti case core_write_map: 2515355Stwisti if (access & access_write) 2525355Stwisti core_map_attach(memory->map + access_map, 2535355Stwisti attach, 25411219Sgziemski space, addr, nr_bytes, 25511219Sgziemski client, buffer, free_buffer); 25611219Sgziemski free_buffer = NULL; 25711219Sgziemski break; 25811219Sgziemski case core_execute_map: 25911219Sgziemski if (access & access_exec) 2605355Stwisti core_map_attach(memory->map + access_map, 2615355Stwisti attach, 2625355Stwisti space, addr, nr_bytes, 2635355Stwisti client, buffer, free_buffer); 2645355Stwisti free_buffer = NULL; 2655355Stwisti break; 2665355Stwisti default: 2675355Stwisti error("core_attach() internal error\n"); 2685355Stwisti break; 2695355Stwisti } 27011219Sgziemski } 27111219Sgziemski /* allocated buffer must attach to at least one thing */ 27211219Sgziemski ASSERT(free_buffer == NULL); 27311219Sgziemski} 27411219Sgziemski 27511219Sgziemski 2765355StwistiSTATIC_INLINE_CORE\ 2775355Stwisti(core_mapping *) 2786866Sstefankcore_map_find_mapping(core_map *map, 2796866Sstefank unsigned_word addr, 2806866Sstefank unsigned nr_bytes, 2816866Sstefank cpu *processor, 2826866Sstefank unsigned_word cia, 2836866Sstefank int abort) /*either 0 or 1 - helps inline */ 2846866Sstefank{ 2856866Sstefank core_mapping *mapping = map->first; 28611219Sgziemski ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */ 28711219Sgziemski ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */ 28811219Sgziemski while (mapping != NULL) { 28911219Sgziemski if (addr >= mapping->base 29011219Sgziemski && (addr + (nr_bytes - 1)) <= mapping->bound) 29111219Sgziemski return mapping; 2926866Sstefank mapping = mapping->next; 2936866Sstefank } 2945355Stwisti if (abort) 2955355Stwisti 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", 2965355Stwisti addr, nr_bytes, processor, cia); 2975355Stwisti return NULL; 2985355Stwisti} 2995355Stwisti 3005355Stwisti 3015355StwistiSTATIC_INLINE_CORE\ 30211219Sgziemski(void *) 30311219Sgziemskicore_translate(core_mapping *mapping, 30411219Sgziemski unsigned_word addr) 30511219Sgziemski{ 30611219Sgziemski return (void *)(((char *)mapping->buffer) + addr - mapping->base); 30711219Sgziemski} 3085355Stwisti 3095355Stwisti 3105355StwistiINLINE_CORE\ 3115355Stwisti(unsigned) 3125355Stwisticore_map_read_buffer(core_map *map, 3135355Stwisti void *buffer, 3145355Stwisti unsigned_word addr, 3155355Stwisti unsigned len) 3165355Stwisti{ 3175355Stwisti unsigned count = 0; 3185355Stwisti while (count < len) { 3195355Stwisti unsigned_word raddr = addr + count; 3205355Stwisti core_mapping *mapping = 3215355Stwisti core_map_find_mapping(map, 32211219Sgziemski raddr, 1, 32311219Sgziemski NULL, /*processor*/ 32411219Sgziemski 0, /*cia*/ 32511219Sgziemski 0); /*dont-abort*/ 32611219Sgziemski if (mapping == NULL) 32711219Sgziemski break; 3285355Stwisti if (mapping->device != NULL) { 3295355Stwisti int nr_bytes = len - count; 3305355Stwisti if (raddr + nr_bytes - 1> mapping->bound) 3315355Stwisti nr_bytes = mapping->bound - raddr + 1; 3325355Stwisti if (device_io_read_buffer(mapping->device, 3335355Stwisti (unsigned_1*)buffer + count, 3345355Stwisti mapping->space, 3355355Stwisti raddr, 3365355Stwisti nr_bytes, 33711608Sjwilhelm 0, /*processor*/ 33811608Sjwilhelm 0 /*cpu*/) != nr_bytes) 3395355Stwisti break; 3405355Stwisti count += nr_bytes; 3415355Stwisti } 3425355Stwisti else { 3435355Stwisti ((unsigned_1*)buffer)[count] = 3445355Stwisti *(unsigned_1*)core_translate(mapping, raddr); 3455355Stwisti count += 1; 3465355Stwisti } 3475355Stwisti } 3485355Stwisti return count; 3495355Stwisti} 35011608Sjwilhelm 35111608Sjwilhelm 35211608SjwilhelmINLINE_CORE\ 35311608Sjwilhelm(unsigned) 35411608Sjwilhelmcore_map_write_buffer(core_map *map, 3555355Stwisti const void *buffer, 3565355Stwisti unsigned_word addr, 3575355Stwisti unsigned len) 3585355Stwisti{ 3595355Stwisti unsigned count = 0; 3605355Stwisti while (count < len) { 3615355Stwisti unsigned_word raddr = addr + count; 3625355Stwisti core_mapping *mapping = core_map_find_mapping(map, 3635355Stwisti raddr, 1, 3645355Stwisti NULL, /*processor*/ 3655355Stwisti 0, /*cia*/ 3665355Stwisti 0); /*dont-abort*/ 3675355Stwisti if (mapping == NULL) 3685355Stwisti break; 3695355Stwisti if (mapping->device != NULL) { 3705355Stwisti int nr_bytes = len - count; 3715355Stwisti if (raddr + nr_bytes - 1 > mapping->bound) 3725355Stwisti nr_bytes = mapping->bound - raddr + 1; 3735355Stwisti if (device_io_write_buffer(mapping->device, 3745355Stwisti (unsigned_1*)buffer + count, 3755355Stwisti mapping->space, 3765355Stwisti raddr, 3775355Stwisti nr_bytes, 3785355Stwisti 0, /*processor*/ 3795355Stwisti 0 /*cpu*/) != nr_bytes) 3805355Stwisti break; 3815355Stwisti count += nr_bytes; 3825355Stwisti } 3835355Stwisti else { 3845355Stwisti *(unsigned_1*)core_translate(mapping, raddr) = 3855355Stwisti ((unsigned_1*)buffer)[count]; 3865355Stwisti count += 1; 3875355Stwisti } 3885355Stwisti } 3895355Stwisti return count; 3905355Stwisti} 3915355Stwisti 3925355Stwisti 3935355Stwisti/* define the read/write 1/2/4/8/word functions */ 3945355Stwisti 3955355Stwisti#define N 1 3965355Stwisti#include "corefile-n.h" 3975355Stwisti#undef N 3985355Stwisti 3995355Stwisti#define N 2 4005355Stwisti#include "corefile-n.h" 4010Sduke#undef N 4025355Stwisti 4035355Stwisti#define N 4 4042868Sphh#include "corefile-n.h" 4050Sduke#undef N 4060Sduke 4070Sduke#define N 8 4085355Stwisti#include "corefile-n.h" 4090Sduke#undef N 4105355Stwisti 4115355Stwisti#define N word 412350Sysr#include "corefile-n.h" 4130Sduke#undef N 4145355Stwisti 4150Sduke#endif /* _CORE_C_ */ 4160Sduke