diff options
author | Andrew Cagney <cagney@redhat.com> | 2000-07-27 11:23:39 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2000-07-27 11:23:39 +0000 |
commit | e0709f5044a0e824475defef03f86346ed9a292e (patch) | |
tree | e06389fffbbc598f7e212d1eedd4688720a72ca9 /sim/m68hc11/dv-nvram.c | |
parent | 3c765a54971db6d8dbeafdf5230ad692cad271b3 (diff) | |
download | gdb-e0709f5044a0e824475defef03f86346ed9a292e.zip gdb-e0709f5044a0e824475defef03f86346ed9a292e.tar.gz gdb-e0709f5044a0e824475defef03f86346ed9a292e.tar.bz2 |
New simulator.
Diffstat (limited to 'sim/m68hc11/dv-nvram.c')
-rw-r--r-- | sim/m68hc11/dv-nvram.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/sim/m68hc11/dv-nvram.c b/sim/m68hc11/dv-nvram.c new file mode 100644 index 0000000..6ffea5d --- /dev/null +++ b/sim/m68hc11/dv-nvram.c @@ -0,0 +1,361 @@ +/* dv-nvram.c -- Generic driver for a non volatile ram (battery saved) + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Written by Stephane Carrez (stcarrez@worldnet.fr) + (From a driver model Contributed by Cygnus Solutions.) + + 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. + + */ + + +#include "sim-main.h" +#include "hw-main.h" +#include "sim-assert.h" + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + + +/* DEVICE + + nvram - Non Volatile Ram + + + DESCRIPTION + + Implements a generic battery saved CMOS ram. This ram device does + not contain any realtime clock and does not generate any interrupt. + The ram content is loaded from a file and saved when it is changed. + It is intended to be generic. + + + PROPERTIES + + overlap? <bool> + + Boolean property which indicates whether the device can overlap + another device. By default, overlapping is not allowed. + + reg <base> <length> + + Base and size of the non-volatile ram bank. + + file <path> + + Path where the memory must be saved or loaded when we start. + + mode {map | save-modified | save-all} + + Controls how to load and save the memory content. + + map The file is mapped in memory + save-modified The simulator keeps an open file descriptor to + the file and saves portion of memory which are + modified. + save-all The simulator saves the complete memory each time + it's modified (it does not keep an open file + descriptor). + + + PORTS + + None. + + + NOTES + + This device is independent of the Motorola 68hc11. + + */ + + + +/* static functions */ + +/* Control of how to access the ram and save its content. */ + +enum nvram_mode +{ + /* Save the complete ram block each time it's changed. + We don't keep an open file descriptor. This should be + ok for small memory banks. */ + NVRAM_SAVE_ALL, + + /* Save only the memory bytes which are modified. + This mode means that we have to keep an open file + descriptor (O_RDWR). It's good for middle sized memory banks. */ + NVRAM_SAVE_MODIFIED, + + /* Map file in memory (not yet implemented). + This mode is suitable for large memory banks. We don't allocate + a buffer to represent the ram, instead it's mapped in memory + with mmap. */ + NVRAM_MAP_FILE +}; + +struct nvram +{ + address_word base_address; /* Base address of ram. */ + unsigned size; /* Size of ram. */ + unsigned8 *data; /* Pointer to ram memory. */ + const char *file_name; /* Path of ram file. */ + int fd; /* File description of opened ram file. */ + enum nvram_mode mode; /* How load/save ram file. */ +}; + + + +/* Finish off the partially created hw device. Attach our local + callbacks. Wire up our port names etc. */ + +static hw_io_read_buffer_method nvram_io_read_buffer; +static hw_io_write_buffer_method nvram_io_write_buffer; + + + +static void +attach_nvram_regs (struct hw *me, struct nvram *controller) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + int result, oerrno; + + /* Get the flag that controls overlapping of ram bank to another device. */ + if (hw_find_property (me, "overlap?") != NULL + && hw_find_boolean_property (me, "overlap?")) + me->overlap_mode_hw = 1; + + /* Get ram bank description (base and size). */ + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain one addr/size entry"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, + &attach_address, + me); + hw_unit_size_to_attach_size (hw_parent (me), + ®.size, + &attach_size, me); + + hw_attach_address (hw_parent (me), 0, + attach_space, attach_address, attach_size, + me); + + controller->mode = NVRAM_SAVE_ALL; + controller->base_address = attach_address; + controller->size = attach_size; + controller->fd = -1; + + /* Get the file where the ram content must be loaded/saved. */ + if(hw_find_property (me, "file") == NULL) + hw_abort (me, "Missing \"file\" property"); + + controller->file_name = hw_find_string_property (me, "file"); + + /* Get the mode which defines how to save the memory. */ + if(hw_find_property (me, "mode") != NULL) + { + const char *value = hw_find_string_property (me, "mode"); + + if (strcmp (value, "map") == 0) + controller->mode = NVRAM_MAP_FILE; + else if (strcmp (value, "save-modified") == 0) + controller->mode = NVRAM_SAVE_MODIFIED; + else if (strcmp (value, "save-all") == 0) + controller->mode = NVRAM_SAVE_ALL; + else + hw_abort (me, "illegal value for mode parameter `%s': " + "use map, save-modified or save-all", value); + } + + /* Initialize the ram by loading/mapping the file in memory. + If the file does not exist, create and give it some content. */ + switch (controller->mode) + { + case NVRAM_MAP_FILE: + hw_abort (me, "'map' mode is not yet implemented, use 'save-modified'"); + break; + + case NVRAM_SAVE_MODIFIED: + case NVRAM_SAVE_ALL: + controller->data = (char*) malloc (attach_size); + if (controller->data == 0) + hw_abort (me, "Not enough memory, try to use the mode 'map'"); + + memset (controller->data, 0, attach_size); + controller->fd = open (controller->file_name, O_RDWR); + if (controller->fd < 0) + { + controller->fd = open (controller->file_name, + O_RDWR | O_CREAT, 0644); + if (controller->fd < 0) + hw_abort (me, "Cannot open or create file '%s'", + controller->file_name); + result = write (controller->fd, controller->data, attach_size); + if (result != attach_size) + { + oerrno = errno; + free (controller->data); + close (controller->fd); + errno = oerrno; + hw_abort (me, "Failed to save the ram content"); + } + } + else + { + result = read (controller->fd, controller->data, attach_size); + if (result != attach_size) + { + oerrno = errno; + free (controller->data); + close (controller->fd); + errno = oerrno; + hw_abort (me, "Failed to load the ram content"); + } + } + if (controller->mode == NVRAM_SAVE_ALL) + { + close (controller->fd); + controller->fd = -1; + } + break; + + default: + break; + } +} + + +static void +nvram_finish (struct hw *me) +{ + struct nvram *controller; + + controller = HW_ZALLOC (me, struct nvram); + + set_hw_data (me, controller); + set_hw_io_read_buffer (me, nvram_io_read_buffer); + set_hw_io_write_buffer (me, nvram_io_write_buffer); + + /* Attach ourself to our parent bus. */ + attach_nvram_regs (me, controller); +} + + + +/* generic read/write */ + +static unsigned +nvram_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct nvram *controller = hw_data (me); + + HW_TRACE ((me, "read 0x%08lx %d [%ld]", + (long) base, (int) nr_bytes, + (long) (base - controller->base_address))); + + base -= controller->base_address; + if (base + nr_bytes > controller->size) + nr_bytes = controller->size - base; + + memcpy (dest, &controller->data[base], nr_bytes); + return nr_bytes; +} + + + +static unsigned +nvram_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct nvram *controller = hw_data (me); + + HW_TRACE ((me, "write 0x%08lx %d [%ld]", + (long) base, (int) nr_bytes, + (long) (base - controller->base_address))); + + base -= controller->base_address; + if (base + nr_bytes > controller->size) + nr_bytes = controller->size - base; + + switch (controller->mode) + { + case NVRAM_SAVE_ALL: + { + int fd, result, oerrno; + + fd = open (controller->file_name, O_WRONLY, 0644); + if (fd < 0) + { + return 0; + } + + memcpy (&controller->data[base], source, nr_bytes); + result = write (fd, controller->data, controller->size); + oerrno = errno; + close (fd); + errno = oerrno; + + if (result != controller->size) + { + return 0; + } + return nr_bytes; + } + + case NVRAM_SAVE_MODIFIED: + { + off_t pos; + int result; + + pos = lseek (controller->fd, (off_t) base, SEEK_SET); + if (pos != (off_t) base) + return 0; + + result = write (controller->fd, source, nr_bytes); + if (result < 0) + return 0; + + nr_bytes = result; + break; + } + + default: + break; + } + memcpy (&controller->data[base], source, nr_bytes); + return nr_bytes; +} + + +const struct hw_descriptor dv_nvram_descriptor[] = { + { "nvram", nvram_finish, }, + { NULL }, +}; + |