filename | src/mem.c |
changeset | 10:c898b37506e0 |
next | 11:0a82ef380c45 |
author | nkeynes |
date | Sun Dec 11 05:15:36 2005 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Add CPU disasembly options to mode dropdown Split sh4/mem.c into core mem.c and sh4/mem.c Start adding copyright comments to file headers |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/mem.c Sun Dec 11 05:15:36 2005 +00001.3 @@ -0,0 +1,203 @@1.4 +/**1.5 + * $Id: mem.c,v 1.1 2005-12-11 05:15:36 nkeynes Exp $1.6 + * mem.c is responsible for creating and maintaining the overall system memory1.7 + * map, as visible from the SH4 processor.1.8 + *1.9 + * Copyright (c) 2005 Nathan Keynes.1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.14 + * (at your option) any later version.1.15 + *1.16 + * This program is distributed in the hope that it will be useful,1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.19 + * GNU General Public License for more details.1.20 + */1.21 +1.22 +#include <sys/mman.h>1.23 +#include <assert.h>1.24 +#include <stdint.h>1.25 +#include <stdlib.h>1.26 +#include <stdio.h>1.27 +#include <unistd.h>1.28 +#include <fcntl.h>1.29 +#include <errno.h>1.30 +#include <string.h>1.31 +#include <zlib.h>1.32 +#include "dream.h"1.33 +#include "mem.h"1.34 +#include "mmio.h"1.35 +#include "dreamcast.h"1.36 +1.37 +char **page_map = NULL;1.38 +1.39 +struct mem_region mem_rgn[MAX_MEM_REGIONS];1.40 +struct mmio_region *io_rgn[MAX_IO_REGIONS];1.41 +struct mmio_region *P4_io[4096];1.42 +1.43 +int num_io_rgns = 1, num_mem_rgns = 0;1.44 +1.45 +void *mem_alloc_pages( int n )1.46 +{1.47 + void *mem = mmap( NULL, n * 4096,1.48 + PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0 );1.49 + if( mem == MAP_FAILED ) {1.50 + ERROR( "Memory allocation failure! (%s)", strerror(errno) );1.51 + return NULL;1.52 + }1.53 + return mem;1.54 +}1.55 +1.56 +1.57 +void mem_init( void )1.58 +{1.59 + page_map = mmap( NULL, sizeof(char *) * PAGE_TABLE_ENTRIES,1.60 + PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0 );1.61 + if( page_map == MAP_FAILED ) {1.62 + ERROR( "Unable to allocate page map! (%s)", strerror(errno) );1.63 + page_map = NULL;1.64 + return;1.65 + }1.66 +1.67 + memset( page_map, 0, sizeof(uint32_t) * PAGE_TABLE_ENTRIES );1.68 +}1.69 +1.70 +void mem_reset( void )1.71 +{1.72 + /* Restore all mmio registers to their initial settings */1.73 + int i, j;1.74 + for( i=1; i<num_io_rgns; i++ ) {1.75 + for( j=0; io_rgn[i]->ports[j].id != NULL; j++ ) {1.76 + if( io_rgn[i]->ports[j].def_val != UNDEFINED &&1.77 + io_rgn[i]->ports[j].def_val != *io_rgn[i]->ports[j].val ) {1.78 + io_rgn[i]->io_write( io_rgn[i]->ports[j].offset,1.79 + io_rgn[i]->ports[j].def_val );1.80 + }1.81 + }1.82 + }1.83 +}1.84 +1.85 +struct mem_region *mem_map_region( void *mem, uint32_t base, uint32_t size,1.86 + char *name, int flags )1.87 +{1.88 + int i;1.89 + mem_rgn[num_mem_rgns].base = base;1.90 + mem_rgn[num_mem_rgns].size = size;1.91 + mem_rgn[num_mem_rgns].flags = flags;1.92 + mem_rgn[num_mem_rgns].name = name;1.93 + mem_rgn[num_mem_rgns].mem = mem;1.94 + num_mem_rgns++;1.95 +1.96 + for( i=0; i<size>>PAGE_BITS; i++ )1.97 + page_map[(base>>PAGE_BITS)+i] = mem + (i<<PAGE_BITS);1.98 +1.99 + return &mem_rgn[num_mem_rgns-1];1.100 +}1.101 +1.102 +void *mem_create_ram_region( uint32_t base, uint32_t size, char *name )1.103 +{1.104 + char *mem;1.105 +1.106 + assert( (base&0xFFFFF000) == base ); /* must be page aligned */1.107 + assert( (size&0x00000FFF) == 0 );1.108 + assert( num_mem_rgns < MAX_MEM_REGIONS );1.109 + assert( page_map != NULL );1.110 +1.111 + mem = mem_alloc_pages( size>>PAGE_BITS );1.112 +1.113 + mem_map_region( mem, base, size, name, 6 );1.114 + return mem;1.115 +}1.116 +1.117 +void *mem_load_rom( char *file, uint32_t base, uint32_t size, uint32_t crc )1.118 +{1.119 + char buf[512], *mem;1.120 + int fd;1.121 + uint32_t calc_crc;1.122 + snprintf( buf, 512, "%s/%s",BIOS_PATH, file );1.123 + fd = open( buf, O_RDONLY );1.124 + if( fd == -1 ) {1.125 + ERROR( "Bios file not found: %s", buf );1.126 + return NULL;1.127 + }1.128 + mem = mmap( NULL, size, PROT_READ, MAP_PRIVATE, fd, 0 );1.129 + if( mem == MAP_FAILED ) {1.130 + ERROR( "Unable to map bios file: %s (%s)", file, strerror(errno) );1.131 + close(fd);1.132 + return NULL;1.133 + }1.134 + mem_map_region( mem, base, size, file, 4 );1.135 +1.136 + /* CRC check */1.137 + calc_crc = crc32(0L, mem, size);1.138 + if( calc_crc != crc ) {1.139 + WARN( "Bios CRC Mismatch in %s: %08X (expected %08X)",1.140 + file, calc_crc, crc);1.141 + }1.142 + return mem;1.143 +}1.144 +1.145 +char *mem_get_region_by_name( char *name )1.146 +{1.147 + int i;1.148 + for( i=0; i<num_mem_rgns; i++ ) {1.149 + if( strcmp( mem_rgn[i].name, name ) == 0 )1.150 + return mem_rgn[i].mem;1.151 + }1.152 + return NULL;1.153 +}1.154 +1.155 +void register_io_region( struct mmio_region *io )1.156 +{1.157 + int i;1.158 +1.159 + assert(io);1.160 + io->mem = mem_alloc_pages(2);1.161 + io->save_mem = io->mem + PAGE_SIZE;1.162 + io->index = (struct mmio_port **)malloc(1024*sizeof(struct mmio_port *));1.163 + io->trace_flag = 1;1.164 + memset( io->index, 0, 1024*sizeof(struct mmio_port *) );1.165 + for( i=0; io->ports[i].id != NULL; i++ ) {1.166 + io->ports[i].val = (uint32_t *)(io->mem + io->ports[i].offset);1.167 + *io->ports[i].val = io->ports[i].def_val;1.168 + io->index[io->ports[i].offset>>2] = &io->ports[i];1.169 + }1.170 + memcpy( io->save_mem, io->mem, PAGE_SIZE );1.171 + if( (io->base & 0xFF000000) == 0xFF000000 ) {1.172 + /* P4 area (on-chip I/O channels */1.173 + P4_io[(io->base&0x1FFFFFFF)>>19] = io;1.174 + } else {1.175 + page_map[io->base>>12] = (char *)num_io_rgns;1.176 + }1.177 + io_rgn[num_io_rgns] = io;1.178 + num_io_rgns++;1.179 +}1.180 +1.181 +void register_io_regions( struct mmio_region **io )1.182 +{1.183 + while( *io ) register_io_region( *io++ );1.184 +}1.185 +1.186 +int mem_has_page( uint32_t addr )1.187 +{1.188 + char *page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];1.189 + return page != NULL;1.190 +}1.191 +1.192 +char *mem_get_page( uint32_t addr )1.193 +{1.194 + char *page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];1.195 + return page;1.196 +}1.197 +1.198 +char *mem_get_region( uint32_t addr )1.199 +{1.200 + char *page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];1.201 + if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */1.202 + return NULL;1.203 + } else {1.204 + return page+(addr&0xFFF);1.205 + }1.206 +}
.