--- trunk/src/devices/dev_ram.c 2007/10/08 16:19:05 17 +++ trunk/src/devices/dev_ram.c 2007/10/08 16:19:11 18 @@ -25,9 +25,9 @@ * SUCH DAMAGE. * * - * $Id: dev_ram.c,v 1.14 2005/05/23 14:22:02 debug Exp $ + * $Id: dev_ram.c,v 1.19 2005/10/25 15:51:04 debug Exp $ * - * A generic RAM (memory) device. Can also be used to mirror/alias another + * A generic RAM (memory) device. Can also be used to mirror/alias another * part of RAM. */ @@ -37,9 +37,9 @@ #include #include -#include "console.h" #include "cpu.h" #include "devices.h" +#include "machine.h" #include "memory.h" #include "misc.h" @@ -50,6 +50,9 @@ int mode; uint64_t otheraddress; + /* If mode = DEV_RAM_MIRROR: */ + uint64_t offset; + /* If mode = DEV_RAM_RAM: */ unsigned char *data; uint64_t length; @@ -101,11 +104,16 @@ /* * dev_ram_init(): + * + * Initializes a RAM or mirror device. Things get a bit complicated because + * of dyntrans (i.e. mirrored memory ranges should be entered into the + * translation arrays just as normal memory and other devices are). */ -void dev_ram_init(struct memory *mem, uint64_t baseaddr, uint64_t length, +void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length, int mode, uint64_t otheraddress) { struct ram_data *d; + int flags = MEM_DEFAULT, points_to_ram = 1; d = malloc(sizeof(struct ram_data)); if (d == NULL) { @@ -115,12 +123,37 @@ memset(d, 0, sizeof(struct ram_data)); + if (mode & DEV_RAM_MIGHT_POINT_TO_DEVICES) { + mode &= ~DEV_RAM_MIGHT_POINT_TO_DEVICES; + points_to_ram = 0; + } + d->mode = mode; d->otheraddress = otheraddress; switch (d->mode) { + case DEV_RAM_MIRROR: + /* + * Calculate the amount that the mirror memory is offset from + * the real (physical) memory. This is used in src/memory_rw.c + * with dyntrans accesses if MEM_EMULATED_RAM is set. + */ + d->offset = baseaddr - otheraddress; + + /* Aligned RAM? Then it works with dyntrans. */ + if (points_to_ram && + (baseaddr & (machine->arch_pagesize-1)) == 0 && + (otheraddress & (machine->arch_pagesize - 1)) == 0 && + (length & (machine->arch_pagesize - 1)) == 0) + flags |= MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK + | MEM_EMULATED_RAM; + + memory_device_register(machine->memory, "ram [mirror]", + baseaddr, length, dev_ram_access, d, flags + | MEM_READING_HAS_NO_SIDE_EFFECTS, (void *) &d->offset); break; + case DEV_RAM_RAM: /* * Allocate zero-filled RAM using mmap(). If mmap() failed, @@ -138,15 +171,20 @@ } memset(d->data, 0, length); } + + /* Aligned memory? Then it works with dyntrans. */ + if ((baseaddr & (machine->arch_pagesize - 1)) == 0 && + (length & (machine->arch_pagesize - 1)) == 0) + flags |= MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK; + + memory_device_register(machine->memory, "ram", baseaddr, + d->length, dev_ram_access, d, flags + | MEM_READING_HAS_NO_SIDE_EFFECTS, d->data); break; + default: fatal("dev_ram_access(): unknown mode %i\n", d->mode); exit(1); } - - memory_device_register(mem, d->mode == DEV_RAM_MIRROR? - "ram [mirror]" : "ram", baseaddr, length, - dev_ram_access, d, MEM_DEFAULT | MEM_READING_HAS_NO_SIDE_EFFECTS, - NULL); }