Automatic date update in version.in
[binutils-gdb.git] / sim / m68hc11 / dv-nvram.c
blob2765982164041f83cd0cc34299409a40e7765ee4
1 /* dv-nvram.c -- Generic driver for a non volatile ram (battery saved)
2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /* This must come before any other includes. */
22 #include "defs.h"
24 #include "sim-main.h"
25 #include "hw-main.h"
26 #include "sim-assert.h"
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
32 #include "m68hc11-sim.h"
34 /* DEVICE
36 nvram - Non Volatile Ram
39 DESCRIPTION
41 Implements a generic battery saved CMOS ram. This ram device does
42 not contain any realtime clock and does not generate any interrupt.
43 The ram content is loaded from a file and saved when it is changed.
44 It is intended to be generic.
47 PROPERTIES
49 reg <base> <length>
51 Base and size of the non-volatile ram bank.
53 file <path>
55 Path where the memory must be saved or loaded when we start.
57 mode {map | save-modified | save-all}
59 Controls how to load and save the memory content.
61 map The file is mapped in memory
62 save-modified The simulator keeps an open file descriptor to
63 the file and saves portion of memory which are
64 modified.
65 save-all The simulator saves the complete memory each time
66 it's modified (it does not keep an open file
67 descriptor).
70 PORTS
72 None.
75 NOTES
77 This device is independent of the Motorola 68hc11.
83 /* static functions */
85 /* Control of how to access the ram and save its content. */
87 enum nvram_mode
89 /* Save the complete ram block each time it's changed.
90 We don't keep an open file descriptor. This should be
91 ok for small memory banks. */
92 NVRAM_SAVE_ALL,
94 /* Save only the memory bytes which are modified.
95 This mode means that we have to keep an open file
96 descriptor (O_RDWR). It's good for middle sized memory banks. */
97 NVRAM_SAVE_MODIFIED,
99 /* Map file in memory (not yet implemented).
100 This mode is suitable for large memory banks. We don't allocate
101 a buffer to represent the ram, instead it's mapped in memory
102 with mmap. */
103 NVRAM_MAP_FILE
106 struct nvram
108 address_word base_address; /* Base address of ram. */
109 unsigned size; /* Size of ram. */
110 uint8_t *data; /* Pointer to ram memory. */
111 const char *file_name; /* Path of ram file. */
112 int fd; /* File description of opened ram file. */
113 enum nvram_mode mode; /* How load/save ram file. */
118 /* Finish off the partially created hw device. Attach our local
119 callbacks. Wire up our port names etc. */
121 static hw_io_read_buffer_method nvram_io_read_buffer;
122 static hw_io_write_buffer_method nvram_io_write_buffer;
126 static void
127 attach_nvram_regs (struct hw *me, struct nvram *controller)
129 unsigned_word attach_address;
130 int attach_space;
131 unsigned attach_size;
132 reg_property_spec reg;
133 int result, oerrno;
135 /* Get ram bank description (base and size). */
136 if (hw_find_property (me, "reg") == NULL)
137 hw_abort (me, "Missing \"reg\" property");
139 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
140 hw_abort (me, "\"reg\" property must contain one addr/size entry");
142 hw_unit_address_to_attach_address (hw_parent (me),
143 &reg.address,
144 &attach_space,
145 &attach_address,
146 me);
147 hw_unit_size_to_attach_size (hw_parent (me),
148 &reg.size,
149 &attach_size, me);
151 hw_attach_address (hw_parent (me), 0,
152 attach_space, attach_address, attach_size,
153 me);
155 controller->mode = NVRAM_SAVE_ALL;
156 controller->base_address = attach_address;
157 controller->size = attach_size;
158 controller->fd = -1;
160 /* Get the file where the ram content must be loaded/saved. */
161 if(hw_find_property (me, "file") == NULL)
162 hw_abort (me, "Missing \"file\" property");
164 controller->file_name = hw_find_string_property (me, "file");
166 /* Get the mode which defines how to save the memory. */
167 if(hw_find_property (me, "mode") != NULL)
169 const char *value = hw_find_string_property (me, "mode");
171 if (strcmp (value, "map") == 0)
172 controller->mode = NVRAM_MAP_FILE;
173 else if (strcmp (value, "save-modified") == 0)
174 controller->mode = NVRAM_SAVE_MODIFIED;
175 else if (strcmp (value, "save-all") == 0)
176 controller->mode = NVRAM_SAVE_ALL;
177 else
178 hw_abort (me, "illegal value for mode parameter `%s': "
179 "use map, save-modified or save-all", value);
182 /* Initialize the ram by loading/mapping the file in memory.
183 If the file does not exist, create and give it some content. */
184 switch (controller->mode)
186 case NVRAM_MAP_FILE:
187 hw_abort (me, "'map' mode is not yet implemented, use 'save-modified'");
188 break;
190 case NVRAM_SAVE_MODIFIED:
191 case NVRAM_SAVE_ALL:
192 controller->data = hw_malloc (me, attach_size);
193 if (controller->data == 0)
194 hw_abort (me, "Not enough memory, try to use the mode 'map'");
196 memset (controller->data, 0, attach_size);
197 controller->fd = open (controller->file_name, O_RDWR);
198 if (controller->fd < 0)
200 controller->fd = open (controller->file_name,
201 O_RDWR | O_CREAT, 0644);
202 if (controller->fd < 0)
203 hw_abort (me, "Cannot open or create file '%s'",
204 controller->file_name);
205 result = write (controller->fd, controller->data, attach_size);
206 if (result != attach_size)
208 oerrno = errno;
209 hw_free (me, controller->data);
210 close (controller->fd);
211 errno = oerrno;
212 hw_abort (me, "Failed to save the ram content");
215 else
217 result = read (controller->fd, controller->data, attach_size);
218 if (result != attach_size)
220 oerrno = errno;
221 hw_free (me, controller->data);
222 close (controller->fd);
223 errno = oerrno;
224 hw_abort (me, "Failed to load the ram content");
227 if (controller->mode == NVRAM_SAVE_ALL)
229 close (controller->fd);
230 controller->fd = -1;
232 break;
234 default:
235 break;
240 static void
241 nvram_finish (struct hw *me)
243 struct nvram *controller;
245 controller = HW_ZALLOC (me, struct nvram);
247 set_hw_data (me, controller);
248 set_hw_io_read_buffer (me, nvram_io_read_buffer);
249 set_hw_io_write_buffer (me, nvram_io_write_buffer);
251 /* Attach ourself to our parent bus. */
252 attach_nvram_regs (me, controller);
257 /* generic read/write */
259 static unsigned
260 nvram_io_read_buffer (struct hw *me,
261 void *dest,
262 int space,
263 unsigned_word base,
264 unsigned nr_bytes)
266 struct nvram *controller = hw_data (me);
268 HW_TRACE ((me, "read 0x%08lx %d [%ld]",
269 (long) base, (int) nr_bytes,
270 (long) (base - controller->base_address)));
272 base -= controller->base_address;
273 if (base + nr_bytes > controller->size)
274 nr_bytes = controller->size - base;
276 memcpy (dest, &controller->data[base], nr_bytes);
277 return nr_bytes;
282 static unsigned
283 nvram_io_write_buffer (struct hw *me,
284 const void *source,
285 int space,
286 unsigned_word base,
287 unsigned nr_bytes)
289 struct nvram *controller = hw_data (me);
291 HW_TRACE ((me, "write 0x%08lx %d [%ld]",
292 (long) base, (int) nr_bytes,
293 (long) (base - controller->base_address)));
295 base -= controller->base_address;
296 if (base + nr_bytes > controller->size)
297 nr_bytes = controller->size - base;
299 switch (controller->mode)
301 case NVRAM_SAVE_ALL:
303 int fd, result, oerrno;
305 fd = open (controller->file_name, O_WRONLY, 0644);
306 if (fd < 0)
308 return 0;
311 memcpy (&controller->data[base], source, nr_bytes);
312 result = write (fd, controller->data, controller->size);
313 oerrno = errno;
314 close (fd);
315 errno = oerrno;
317 if (result != controller->size)
319 return 0;
321 return nr_bytes;
324 case NVRAM_SAVE_MODIFIED:
326 off_t pos;
327 int result;
329 pos = lseek (controller->fd, (off_t) base, SEEK_SET);
330 if (pos != (off_t) base)
331 return 0;
333 result = write (controller->fd, source, nr_bytes);
334 if (result < 0)
335 return 0;
337 nr_bytes = result;
338 break;
341 default:
342 break;
344 memcpy (&controller->data[base], source, nr_bytes);
345 return nr_bytes;
349 const struct hw_descriptor dv_nvram_descriptor[] = {
350 { "nvram", nvram_finish, },
351 { NULL },