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