Search
lxdream.org :: lxdream/src/mem.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/mem.c
changeset 10:c898b37506e0
next11: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 +0000
1.2 +++ b/src/mem.c Sun Dec 11 05:15:36 2005 +0000
1.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 memory
1.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 modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.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 of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.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 +}
.