]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/dv-nvram.c
Update the copyright notice of some of the files I missed
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-nvram.c
1 /* dv-nvram.c -- Generic driver for a non volatile ram (battery saved)
2 Copyright (C) 1999, 2000, 2007, 2008, 2009 Free Software Foundation, Inc.
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
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
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.
15
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/>.
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
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
84 enum 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
103 struct 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
118 static hw_io_read_buffer_method nvram_io_read_buffer;
119 static hw_io_write_buffer_method nvram_io_write_buffer;
120
121
122
123 static void
124 attach_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
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:
189 controller->data = (char*) hw_malloc (me, attach_size);
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;
206 hw_free (me, controller->data);
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;
218 hw_free (me, controller->data);
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
237 static void
238 nvram_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
256 static unsigned
257 nvram_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
279 static unsigned
280 nvram_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
346 const struct hw_descriptor dv_nvram_descriptor[] = {
347 { "nvram", nvram_finish, },
348 { NULL },
349 };
350