Minor formatting fixes.
[deliverable/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 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 2 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, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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
47 overlap? <bool>
48
49 Boolean property which indicates whether the device can overlap
50 another device. By default, overlapping is not allowed.
51
52 reg <base> <length>
53
54 Base and size of the non-volatile ram bank.
55
56 file <path>
57
58 Path where the memory must be saved or loaded when we start.
59
60 mode {map | save-modified | save-all}
61
62 Controls how to load and save the memory content.
63
64 map The file is mapped in memory
65 save-modified The simulator keeps an open file descriptor to
66 the file and saves portion of memory which are
67 modified.
68 save-all The simulator saves the complete memory each time
69 it's modified (it does not keep an open file
70 descriptor).
71
72
73 PORTS
74
75 None.
76
77
78 NOTES
79
80 This device is independent of the Motorola 68hc11.
81
82 */
83
84
85
86 /* static functions */
87
88 /* Control of how to access the ram and save its content. */
89
90 enum nvram_mode
91 {
92 /* Save the complete ram block each time it's changed.
93 We don't keep an open file descriptor. This should be
94 ok for small memory banks. */
95 NVRAM_SAVE_ALL,
96
97 /* Save only the memory bytes which are modified.
98 This mode means that we have to keep an open file
99 descriptor (O_RDWR). It's good for middle sized memory banks. */
100 NVRAM_SAVE_MODIFIED,
101
102 /* Map file in memory (not yet implemented).
103 This mode is suitable for large memory banks. We don't allocate
104 a buffer to represent the ram, instead it's mapped in memory
105 with mmap. */
106 NVRAM_MAP_FILE
107 };
108
109 struct nvram
110 {
111 address_word base_address; /* Base address of ram. */
112 unsigned size; /* Size of ram. */
113 unsigned8 *data; /* Pointer to ram memory. */
114 const char *file_name; /* Path of ram file. */
115 int fd; /* File description of opened ram file. */
116 enum nvram_mode mode; /* How load/save ram file. */
117 };
118
119
120
121 /* Finish off the partially created hw device. Attach our local
122 callbacks. Wire up our port names etc. */
123
124 static hw_io_read_buffer_method nvram_io_read_buffer;
125 static hw_io_write_buffer_method nvram_io_write_buffer;
126
127
128
129 static void
130 attach_nvram_regs (struct hw *me, struct nvram *controller)
131 {
132 unsigned_word attach_address;
133 int attach_space;
134 unsigned attach_size;
135 reg_property_spec reg;
136 int result, oerrno;
137
138 /* Get the flag that controls overlapping of ram bank to another device. */
139 if (hw_find_property (me, "overlap?") != NULL
140 && hw_find_boolean_property (me, "overlap?"))
141 me->overlap_mode_hw = 1;
142
143 /* Get ram bank description (base and size). */
144 if (hw_find_property (me, "reg") == NULL)
145 hw_abort (me, "Missing \"reg\" property");
146
147 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
148 hw_abort (me, "\"reg\" property must contain one addr/size entry");
149
150 hw_unit_address_to_attach_address (hw_parent (me),
151 &reg.address,
152 &attach_space,
153 &attach_address,
154 me);
155 hw_unit_size_to_attach_size (hw_parent (me),
156 &reg.size,
157 &attach_size, me);
158
159 hw_attach_address (hw_parent (me), 0,
160 attach_space, attach_address, attach_size,
161 me);
162
163 controller->mode = NVRAM_SAVE_ALL;
164 controller->base_address = attach_address;
165 controller->size = attach_size;
166 controller->fd = -1;
167
168 /* Get the file where the ram content must be loaded/saved. */
169 if(hw_find_property (me, "file") == NULL)
170 hw_abort (me, "Missing \"file\" property");
171
172 controller->file_name = hw_find_string_property (me, "file");
173
174 /* Get the mode which defines how to save the memory. */
175 if(hw_find_property (me, "mode") != NULL)
176 {
177 const char *value = hw_find_string_property (me, "mode");
178
179 if (strcmp (value, "map") == 0)
180 controller->mode = NVRAM_MAP_FILE;
181 else if (strcmp (value, "save-modified") == 0)
182 controller->mode = NVRAM_SAVE_MODIFIED;
183 else if (strcmp (value, "save-all") == 0)
184 controller->mode = NVRAM_SAVE_ALL;
185 else
186 hw_abort (me, "illegal value for mode parameter `%s': "
187 "use map, save-modified or save-all", value);
188 }
189
190 /* Initialize the ram by loading/mapping the file in memory.
191 If the file does not exist, create and give it some content. */
192 switch (controller->mode)
193 {
194 case NVRAM_MAP_FILE:
195 hw_abort (me, "'map' mode is not yet implemented, use 'save-modified'");
196 break;
197
198 case NVRAM_SAVE_MODIFIED:
199 case NVRAM_SAVE_ALL:
200 controller->data = (char*) malloc (attach_size);
201 if (controller->data == 0)
202 hw_abort (me, "Not enough memory, try to use the mode 'map'");
203
204 memset (controller->data, 0, attach_size);
205 controller->fd = open (controller->file_name, O_RDWR);
206 if (controller->fd < 0)
207 {
208 controller->fd = open (controller->file_name,
209 O_RDWR | O_CREAT, 0644);
210 if (controller->fd < 0)
211 hw_abort (me, "Cannot open or create file '%s'",
212 controller->file_name);
213 result = write (controller->fd, controller->data, attach_size);
214 if (result != attach_size)
215 {
216 oerrno = errno;
217 free (controller->data);
218 close (controller->fd);
219 errno = oerrno;
220 hw_abort (me, "Failed to save the ram content");
221 }
222 }
223 else
224 {
225 result = read (controller->fd, controller->data, attach_size);
226 if (result != attach_size)
227 {
228 oerrno = errno;
229 free (controller->data);
230 close (controller->fd);
231 errno = oerrno;
232 hw_abort (me, "Failed to load the ram content");
233 }
234 }
235 if (controller->mode == NVRAM_SAVE_ALL)
236 {
237 close (controller->fd);
238 controller->fd = -1;
239 }
240 break;
241
242 default:
243 break;
244 }
245 }
246
247
248 static void
249 nvram_finish (struct hw *me)
250 {
251 struct nvram *controller;
252
253 controller = HW_ZALLOC (me, struct nvram);
254
255 set_hw_data (me, controller);
256 set_hw_io_read_buffer (me, nvram_io_read_buffer);
257 set_hw_io_write_buffer (me, nvram_io_write_buffer);
258
259 /* Attach ourself to our parent bus. */
260 attach_nvram_regs (me, controller);
261 }
262
263
264
265 /* generic read/write */
266
267 static unsigned
268 nvram_io_read_buffer (struct hw *me,
269 void *dest,
270 int space,
271 unsigned_word base,
272 unsigned nr_bytes)
273 {
274 struct nvram *controller = hw_data (me);
275
276 HW_TRACE ((me, "read 0x%08lx %d [%ld]",
277 (long) base, (int) nr_bytes,
278 (long) (base - controller->base_address)));
279
280 base -= controller->base_address;
281 if (base + nr_bytes > controller->size)
282 nr_bytes = controller->size - base;
283
284 memcpy (dest, &controller->data[base], nr_bytes);
285 return nr_bytes;
286 }
287
288
289
290 static unsigned
291 nvram_io_write_buffer (struct hw *me,
292 const void *source,
293 int space,
294 unsigned_word base,
295 unsigned nr_bytes)
296 {
297 struct nvram *controller = hw_data (me);
298
299 HW_TRACE ((me, "write 0x%08lx %d [%ld]",
300 (long) base, (int) nr_bytes,
301 (long) (base - controller->base_address)));
302
303 base -= controller->base_address;
304 if (base + nr_bytes > controller->size)
305 nr_bytes = controller->size - base;
306
307 switch (controller->mode)
308 {
309 case NVRAM_SAVE_ALL:
310 {
311 int fd, result, oerrno;
312
313 fd = open (controller->file_name, O_WRONLY, 0644);
314 if (fd < 0)
315 {
316 return 0;
317 }
318
319 memcpy (&controller->data[base], source, nr_bytes);
320 result = write (fd, controller->data, controller->size);
321 oerrno = errno;
322 close (fd);
323 errno = oerrno;
324
325 if (result != controller->size)
326 {
327 return 0;
328 }
329 return nr_bytes;
330 }
331
332 case NVRAM_SAVE_MODIFIED:
333 {
334 off_t pos;
335 int result;
336
337 pos = lseek (controller->fd, (off_t) base, SEEK_SET);
338 if (pos != (off_t) base)
339 return 0;
340
341 result = write (controller->fd, source, nr_bytes);
342 if (result < 0)
343 return 0;
344
345 nr_bytes = result;
346 break;
347 }
348
349 default:
350 break;
351 }
352 memcpy (&controller->data[base], source, nr_bytes);
353 return nr_bytes;
354 }
355
356
357 const struct hw_descriptor dv_nvram_descriptor[] = {
358 { "nvram", nvram_finish, },
359 { NULL },
360 };
361
This page took 0.040463 seconds and 4 git commands to generate.