Remove spurious empty line in changelog entry.
[deliverable/binutils-gdb.git] / sim / m68hc11 / dv-nvram.c
CommitLineData
e0709f50 1/* dv-nvram.c -- Generic driver for a non volatile ram (battery saved)
618f726f 2 Copyright (C) 1999-2016 Free Software Foundation, Inc.
e0709f50
AC
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
5
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
4744ac1b 8 the Free Software Foundation; either version 3 of the License, or
e0709f50 9 (at your option) any later version.
4744ac1b 10
e0709f50
AC
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.
4744ac1b 15
e0709f50 16 You should have received a copy of the GNU General Public License
4744ac1b 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
e0709f50
AC
18
19 */
20
21
22#include "sim-main.h"
23#include "hw-main.h"
24#include "sim-assert.h"
25
26#include <unistd.h>
27#include <fcntl.h>
28#include <errno.h>
29
30
31/* DEVICE
32
33 nvram - Non Volatile Ram
34
35
36 DESCRIPTION
37
38 Implements a generic battery saved CMOS ram. This ram device does
39 not contain any realtime clock and does not generate any interrupt.
40 The ram content is loaded from a file and saved when it is changed.
41 It is intended to be generic.
42
43
44 PROPERTIES
45
e0709f50
AC
46 reg <base> <length>
47
48 Base and size of the non-volatile ram bank.
49
50 file <path>
51
52 Path where the memory must be saved or loaded when we start.
53
54 mode {map | save-modified | save-all}
55
56 Controls how to load and save the memory content.
57
58 map The file is mapped in memory
59 save-modified The simulator keeps an open file descriptor to
60 the file and saves portion of memory which are
61 modified.
62 save-all The simulator saves the complete memory each time
63 it's modified (it does not keep an open file
64 descriptor).
65
66
67 PORTS
68
69 None.
70
71
72 NOTES
73
74 This device is independent of the Motorola 68hc11.
75
76 */
77
78
79
80/* static functions */
81
82/* Control of how to access the ram and save its content. */
83
84enum nvram_mode
85{
86 /* Save the complete ram block each time it's changed.
87 We don't keep an open file descriptor. This should be
88 ok for small memory banks. */
89 NVRAM_SAVE_ALL,
90
91 /* Save only the memory bytes which are modified.
92 This mode means that we have to keep an open file
93 descriptor (O_RDWR). It's good for middle sized memory banks. */
94 NVRAM_SAVE_MODIFIED,
95
96 /* Map file in memory (not yet implemented).
97 This mode is suitable for large memory banks. We don't allocate
98 a buffer to represent the ram, instead it's mapped in memory
99 with mmap. */
100 NVRAM_MAP_FILE
101};
102
103struct nvram
104{
105 address_word base_address; /* Base address of ram. */
106 unsigned size; /* Size of ram. */
107 unsigned8 *data; /* Pointer to ram memory. */
108 const char *file_name; /* Path of ram file. */
109 int fd; /* File description of opened ram file. */
110 enum nvram_mode mode; /* How load/save ram file. */
111};
112
113
114
115/* Finish off the partially created hw device. Attach our local
116 callbacks. Wire up our port names etc. */
117
118static hw_io_read_buffer_method nvram_io_read_buffer;
119static hw_io_write_buffer_method nvram_io_write_buffer;
120
121
122
123static void
124attach_nvram_regs (struct hw *me, struct nvram *controller)
125{
126 unsigned_word attach_address;
127 int attach_space;
128 unsigned attach_size;
129 reg_property_spec reg;
130 int result, oerrno;
131
e0709f50
AC
132 /* Get ram bank description (base and size). */
133 if (hw_find_property (me, "reg") == NULL)
134 hw_abort (me, "Missing \"reg\" property");
135
136 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
137 hw_abort (me, "\"reg\" property must contain one addr/size entry");
138
139 hw_unit_address_to_attach_address (hw_parent (me),
140 &reg.address,
141 &attach_space,
142 &attach_address,
143 me);
144 hw_unit_size_to_attach_size (hw_parent (me),
145 &reg.size,
146 &attach_size, me);
147
148 hw_attach_address (hw_parent (me), 0,
149 attach_space, attach_address, attach_size,
150 me);
151
152 controller->mode = NVRAM_SAVE_ALL;
153 controller->base_address = attach_address;
154 controller->size = attach_size;
155 controller->fd = -1;
156
157 /* Get the file where the ram content must be loaded/saved. */
158 if(hw_find_property (me, "file") == NULL)
159 hw_abort (me, "Missing \"file\" property");
160
161 controller->file_name = hw_find_string_property (me, "file");
162
163 /* Get the mode which defines how to save the memory. */
164 if(hw_find_property (me, "mode") != NULL)
165 {
166 const char *value = hw_find_string_property (me, "mode");
167
168 if (strcmp (value, "map") == 0)
169 controller->mode = NVRAM_MAP_FILE;
170 else if (strcmp (value, "save-modified") == 0)
171 controller->mode = NVRAM_SAVE_MODIFIED;
172 else if (strcmp (value, "save-all") == 0)
173 controller->mode = NVRAM_SAVE_ALL;
174 else
175 hw_abort (me, "illegal value for mode parameter `%s': "
176 "use map, save-modified or save-all", value);
177 }
178
179 /* Initialize the ram by loading/mapping the file in memory.
180 If the file does not exist, create and give it some content. */
181 switch (controller->mode)
182 {
183 case NVRAM_MAP_FILE:
184 hw_abort (me, "'map' mode is not yet implemented, use 'save-modified'");
185 break;
186
187 case NVRAM_SAVE_MODIFIED:
188 case NVRAM_SAVE_ALL:
6e73e7ed 189 controller->data = (char*) hw_malloc (me, attach_size);
e0709f50
AC
190 if (controller->data == 0)
191 hw_abort (me, "Not enough memory, try to use the mode 'map'");
192
193 memset (controller->data, 0, attach_size);
194 controller->fd = open (controller->file_name, O_RDWR);
195 if (controller->fd < 0)
196 {
197 controller->fd = open (controller->file_name,
198 O_RDWR | O_CREAT, 0644);
199 if (controller->fd < 0)
200 hw_abort (me, "Cannot open or create file '%s'",
201 controller->file_name);
202 result = write (controller->fd, controller->data, attach_size);
203 if (result != attach_size)
204 {
205 oerrno = errno;
6e73e7ed 206 hw_free (me, controller->data);
e0709f50
AC
207 close (controller->fd);
208 errno = oerrno;
209 hw_abort (me, "Failed to save the ram content");
210 }
211 }
212 else
213 {
214 result = read (controller->fd, controller->data, attach_size);
215 if (result != attach_size)
216 {
217 oerrno = errno;
6e73e7ed 218 hw_free (me, controller->data);
e0709f50
AC
219 close (controller->fd);
220 errno = oerrno;
221 hw_abort (me, "Failed to load the ram content");
222 }
223 }
224 if (controller->mode == NVRAM_SAVE_ALL)
225 {
226 close (controller->fd);
227 controller->fd = -1;
228 }
229 break;
230
231 default:
232 break;
233 }
234}
235
236
237static void
238nvram_finish (struct hw *me)
239{
240 struct nvram *controller;
241
242 controller = HW_ZALLOC (me, struct nvram);
243
244 set_hw_data (me, controller);
245 set_hw_io_read_buffer (me, nvram_io_read_buffer);
246 set_hw_io_write_buffer (me, nvram_io_write_buffer);
247
248 /* Attach ourself to our parent bus. */
249 attach_nvram_regs (me, controller);
250}
251
252
253
254/* generic read/write */
255
256static unsigned
257nvram_io_read_buffer (struct hw *me,
258 void *dest,
259 int space,
260 unsigned_word base,
261 unsigned nr_bytes)
262{
263 struct nvram *controller = hw_data (me);
264
265 HW_TRACE ((me, "read 0x%08lx %d [%ld]",
266 (long) base, (int) nr_bytes,
267 (long) (base - controller->base_address)));
268
269 base -= controller->base_address;
270 if (base + nr_bytes > controller->size)
271 nr_bytes = controller->size - base;
272
273 memcpy (dest, &controller->data[base], nr_bytes);
274 return nr_bytes;
275}
276
277
278
279static unsigned
280nvram_io_write_buffer (struct hw *me,
281 const void *source,
282 int space,
283 unsigned_word base,
284 unsigned nr_bytes)
285{
286 struct nvram *controller = hw_data (me);
287
288 HW_TRACE ((me, "write 0x%08lx %d [%ld]",
289 (long) base, (int) nr_bytes,
290 (long) (base - controller->base_address)));
291
292 base -= controller->base_address;
293 if (base + nr_bytes > controller->size)
294 nr_bytes = controller->size - base;
295
296 switch (controller->mode)
297 {
298 case NVRAM_SAVE_ALL:
299 {
300 int fd, result, oerrno;
301
302 fd = open (controller->file_name, O_WRONLY, 0644);
303 if (fd < 0)
304 {
305 return 0;
306 }
307
308 memcpy (&controller->data[base], source, nr_bytes);
309 result = write (fd, controller->data, controller->size);
310 oerrno = errno;
311 close (fd);
312 errno = oerrno;
313
314 if (result != controller->size)
315 {
316 return 0;
317 }
318 return nr_bytes;
319 }
320
321 case NVRAM_SAVE_MODIFIED:
322 {
323 off_t pos;
324 int result;
325
326 pos = lseek (controller->fd, (off_t) base, SEEK_SET);
327 if (pos != (off_t) base)
328 return 0;
329
330 result = write (controller->fd, source, nr_bytes);
331 if (result < 0)
332 return 0;
333
334 nr_bytes = result;
335 break;
336 }
337
338 default:
339 break;
340 }
341 memcpy (&controller->data[base], source, nr_bytes);
342 return nr_bytes;
343}
344
345
346const struct hw_descriptor dv_nvram_descriptor[] = {
347 { "nvram", nvram_finish, },
348 { NULL },
349};
350
This page took 0.665826 seconds and 4 git commands to generate.