diff options
Diffstat (limited to 'sim/ppc/hw_memory.c')
-rw-r--r-- | sim/ppc/hw_memory.c | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/sim/ppc/hw_memory.c b/sim/ppc/hw_memory.c deleted file mode 100644 index 7e4204d..0000000 --- a/sim/ppc/hw_memory.c +++ /dev/null @@ -1,316 +0,0 @@ -/* 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 2 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, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - - -#ifndef _HW_MEMORY_C_ -#define _HW_MEMORY_C_ - -#ifndef STATIC_INLINE_HW_MEMORY -#define STATIC_INLINE_HW_MEMORY STATIC_INLINE -#endif - -#include "device_table.h" - -/* DEVICE - - memory - description of system memory - - DESCRIPTION - - This device describes the size and location of the banks of - physical memory within the simulation. - - In addition, this device supports the "claim" and "release" methods - that can be used by OpenBoot client programs to manage the - allocation of physical memory. - - PROPERTIES - - reg = { <address> <size> } (required) - - Each pair specify one bank of memory. - - available = { <address> <size> } (automatic) - - Each pair specifies a block of memory that is currently unallocated. - - */ - -typedef struct _memory_reg_spec { - unsigned32 base; - unsigned32 size; -} memory_reg_spec; - -typedef struct _hw_memory_chunk hw_memory_chunk; -struct _hw_memory_chunk { - unsigned_word address; - unsigned_word size; - unsigned_word alloc_address; - unsigned_word alloc_size; - int available; - hw_memory_chunk *next; -}; - -typedef struct _hw_memory_device { - hw_memory_chunk *heap; -} hw_memory_device; - - -static void * -hw_memory_create(const char *name, - const device_unit *unit_address, - const char *args) -{ - hw_memory_device *hw_memory = ZALLOC(hw_memory_device); - return hw_memory; -} - - -static void -hw_memory_set_available(device *me, - hw_memory_device *hw_memory) -{ - hw_memory_chunk *chunk = NULL; - memory_reg_spec *available = NULL; - int nr_available = 0; - int curr = 0; - int sizeof_available = 0; - /* determine the nr of available chunks */ - chunk = hw_memory->heap; - nr_available = 0; - while (chunk != NULL) { - if (chunk->available) - nr_available += 1; - chunk = chunk->next; - } - /* now create the available struct */ - ASSERT(nr_available > 0); - sizeof_available = sizeof(memory_reg_spec) * nr_available; - available = zalloc(sizeof_available); - chunk = hw_memory->heap; - curr = 0; - while (chunk != NULL) { - if (chunk->available) { - available[curr].base = H2BE_4(chunk->address); - available[curr].size = H2BE_4(chunk->size); - curr += 1; - } - chunk = chunk->next; - } - /* update */ - device_set_array_property(me, "available", available, sizeof_available); - zfree(available); -} - - -static void -hw_memory_init_address(device *me) -{ - hw_memory_device *hw_memory = (hw_memory_device*)device_data(me); - const device_property *reg = device_find_array_property(me, "reg"); - const memory_reg_spec *spec = reg->array; - int nr_entries = reg->sizeof_array / sizeof(*spec); - - /* sanity check reg property */ - if ((reg->sizeof_array % sizeof(*spec)) != 0) - error("devices/%s reg property of incorrect size\n", device_name(me)); - - /* free up any previous structures */ - { - hw_memory_chunk *curr_chunk = hw_memory->heap; - hw_memory->heap = NULL; - while (curr_chunk != NULL) { - hw_memory_chunk *dead_chunk = curr_chunk; - curr_chunk = dead_chunk->next; - dead_chunk->next = NULL; - zfree(dead_chunk); - } - } - - /* count/allocate memory entries */ - { - hw_memory_chunk **curr_chunk = &hw_memory->heap; - while (nr_entries > 0) { - hw_memory_chunk *new_chunk = ZALLOC(hw_memory_chunk); - new_chunk->address = BE2H_4(spec->base); - new_chunk->size = BE2H_4(spec->size); - new_chunk->available = 1; - device_attach_address(device_parent(me), - device_name(me), - attach_raw_memory, - 0 /*address space*/, - new_chunk->address, - new_chunk->size, - access_read_write_exec, - me); - spec++; - nr_entries--; - *curr_chunk = new_chunk; - curr_chunk = &new_chunk->next; - } - } - - /* initialize the alloc property for this device */ - hw_memory_set_available(me, hw_memory); -} - -static void -hw_memory_instance_delete(device_instance *instance) -{ - return; -} - -static unsigned_word -hw_memory_instance_claim(device_instance *instance, - unsigned_word address, - unsigned_word size, - unsigned_word alignment) -{ - hw_memory_device *hw_memory = device_instance_data(instance); - hw_memory_chunk *chunk = NULL; - DTRACE(memory, ("claim - address=0x%lx size=0x%lx alignment=%d\n", - (unsigned long)address, - (unsigned long)size, - (int)alignment)); - /* find a chunk candidate, either according to address or alignment */ - if (alignment == 0) { - chunk = hw_memory->heap; - while (chunk != NULL - && (address+size) > (chunk->address+chunk->size)) - chunk = chunk->next; - if (chunk == NULL || address < chunk->address || !chunk->available) - error("hw_memory_instance_claim: failed to allocate @0x%lx, size %ld\n", - (unsigned long)address, (unsigned long)size); - } - else { - chunk = hw_memory->heap; - while (chunk != NULL && chunk->size < size) - chunk = chunk->next; - if (chunk == NULL || FLOOR_PAGE(alignment-1) > 0) - error("hw_memory_instance_claim: failed to allocate %ld, align %ld\n", - (unsigned long)size, (unsigned long)size); - address = chunk->address; - } - /* break of a part before this memory if needed */ - ASSERT(address >= chunk->address); - if (FLOOR_PAGE(address) > chunk->address) { - hw_memory_chunk *last_chunk = chunk; - /* insert a new earlier chunk */ - chunk = ZALLOC(hw_memory_chunk); - chunk->next = last_chunk->next; - last_chunk->next = chunk; - /* adjust the address/size */ - chunk->address = FLOOR_PAGE(address); - chunk->size = last_chunk->size - (chunk->address - last_chunk->address); - last_chunk->size = chunk->address - last_chunk->address; - } - ASSERT(FLOOR_PAGE(address) == chunk->address); - /* break of a bit after this chunk if needed */ - if (ALIGN_PAGE(address+size) < chunk->address + chunk->size) { - hw_memory_chunk *next_chunk = ZALLOC(hw_memory_chunk); - /* insert it in to the list */ - next_chunk->next = chunk->next; - chunk->next = next_chunk; - next_chunk->available = 1; - /* adjust the address/size */ - next_chunk->address = ALIGN_PAGE(address+size); - next_chunk->size = chunk->address + chunk->size - next_chunk->address; - chunk->size = next_chunk->address - chunk->address; - } - ASSERT(ALIGN_PAGE(address+size) == chunk->address + chunk->size); - /* now allocate it */ - chunk->alloc_address = address; - chunk->alloc_size = size; - chunk->available = 0; - hw_memory_set_available(device_instance_device(instance), hw_memory); - return address; -} - -static void -hw_memory_instance_release(device_instance *instance, - unsigned_word address, - unsigned_word length) -{ - hw_memory_device *hw_memory = device_instance_data(instance); - hw_memory_chunk *chunk = hw_memory->heap; - while (chunk != NULL) { - if (chunk->alloc_address == address - && chunk->alloc_size == length - && chunk->available == 0) { - /* free this chunk */ - chunk->available = 1; - /* check for merge */ - chunk = hw_memory->heap; - while (chunk != NULL) { - if (chunk->available - && chunk->next != NULL && chunk->next->available) { - /* adjacent */ - hw_memory_chunk *delete = chunk->next; - ASSERT(chunk->address + chunk->size == delete->address); - chunk->size += delete->size; - chunk->next = delete->next; - zfree(delete); - } - } - /* update the corresponding property */ - hw_memory_set_available(device_instance_device(instance), hw_memory); - return; - } - chunk = chunk->next; - } - error("hw_memory_instance_release: Address 0x%lx, size %ld not found\n", - (unsigned long)address, (unsigned long)length); - /* FIXME - dump allocated */ - /* FIXME - dump arguments */ -} - -static device_instance_callbacks const hw_memory_instance_callbacks = { - hw_memory_instance_delete, - NULL /*read*/, NULL /*write*/, NULL /*seek*/, - hw_memory_instance_claim, hw_memory_instance_release -}; - -static device_instance * -hw_memory_create_instance(device *me, - const char *path, - const char *args) -{ - return device_create_instance_from(me, NULL, - device_data(me), /* nothing better */ - path, args, - &hw_memory_instance_callbacks); -} - -static device_callbacks const hw_memory_callbacks = { - { hw_memory_init_address, }, - { NULL, }, /* address */ - { NULL, }, /* IO */ - { NULL, }, /* DMA */ - { NULL, }, /* interrupt */ - { NULL, }, /* unit */ - hw_memory_create_instance, -}; - -const device_descriptor hw_memory_device_descriptor[] = { - { "memory", hw_memory_create, &hw_memory_callbacks }, - { NULL }, -}; - -#endif /* _HW_MEMORY_C_ */ |