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.)
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.
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, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "sim-assert.h"
34 nvram - Non Volatile Ram
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.
49 Boolean property which indicates whether the device can overlap
50 another device. By default, overlapping is not allowed.
54 Base and size of the non-volatile ram bank.
58 Path where the memory must be saved or loaded when we start.
60 mode {map | save-modified | save-all}
62 Controls how to load and save the memory content.
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
68 save-all The simulator saves the complete memory each time
69 it's modified (it does not keep an open file
80 This device is independent of the Motorola 68hc11.
86 /* static functions */
88 /* Control of how to access the ram and save its content. */
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. */
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. */
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
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. */
121 /* Finish off the partially created hw device. Attach our local
122 callbacks. Wire up our port names etc. */
124 static hw_io_read_buffer_method nvram_io_read_buffer
;
125 static hw_io_write_buffer_method nvram_io_write_buffer
;
130 attach_nvram_regs (struct hw
*me
, struct nvram
*controller
)
132 unsigned_word attach_address
;
134 unsigned attach_size
;
135 reg_property_spec reg
;
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;
143 /* Get ram bank description (base and size). */
144 if (hw_find_property (me
, "reg") == NULL
)
145 hw_abort (me
, "Missing \"reg\" property");
147 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
148 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
150 hw_unit_address_to_attach_address (hw_parent (me
),
155 hw_unit_size_to_attach_size (hw_parent (me
),
159 hw_attach_address (hw_parent (me
), 0,
160 attach_space
, attach_address
, attach_size
,
163 controller
->mode
= NVRAM_SAVE_ALL
;
164 controller
->base_address
= attach_address
;
165 controller
->size
= attach_size
;
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");
172 controller
->file_name
= hw_find_string_property (me
, "file");
174 /* Get the mode which defines how to save the memory. */
175 if(hw_find_property (me
, "mode") != NULL
)
177 const char *value
= hw_find_string_property (me
, "mode");
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
;
186 hw_abort (me
, "illegal value for mode parameter `%s': "
187 "use map, save-modified or save-all", value
);
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
)
195 hw_abort (me
, "'map' mode is not yet implemented, use 'save-modified'");
198 case NVRAM_SAVE_MODIFIED
:
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'");
204 memset (controller
->data
, 0, attach_size
);
205 controller
->fd
= open (controller
->file_name
, O_RDWR
);
206 if (controller
->fd
< 0)
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
)
217 free (controller
->data
);
218 close (controller
->fd
);
220 hw_abort (me
, "Failed to save the ram content");
225 result
= read (controller
->fd
, controller
->data
, attach_size
);
226 if (result
!= attach_size
)
229 free (controller
->data
);
230 close (controller
->fd
);
232 hw_abort (me
, "Failed to load the ram content");
235 if (controller
->mode
== NVRAM_SAVE_ALL
)
237 close (controller
->fd
);
249 nvram_finish (struct hw
*me
)
251 struct nvram
*controller
;
253 controller
= HW_ZALLOC (me
, struct nvram
);
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
);
259 /* Attach ourself to our parent bus. */
260 attach_nvram_regs (me
, controller
);
265 /* generic read/write */
268 nvram_io_read_buffer (struct hw
*me
,
274 struct nvram
*controller
= hw_data (me
);
276 HW_TRACE ((me
, "read 0x%08lx %d [%ld]",
277 (long) base
, (int) nr_bytes
,
278 (long) (base
- controller
->base_address
)));
280 base
-= controller
->base_address
;
281 if (base
+ nr_bytes
> controller
->size
)
282 nr_bytes
= controller
->size
- base
;
284 memcpy (dest
, &controller
->data
[base
], nr_bytes
);
291 nvram_io_write_buffer (struct hw
*me
,
297 struct nvram
*controller
= hw_data (me
);
299 HW_TRACE ((me
, "write 0x%08lx %d [%ld]",
300 (long) base
, (int) nr_bytes
,
301 (long) (base
- controller
->base_address
)));
303 base
-= controller
->base_address
;
304 if (base
+ nr_bytes
> controller
->size
)
305 nr_bytes
= controller
->size
- base
;
307 switch (controller
->mode
)
311 int fd
, result
, oerrno
;
313 fd
= open (controller
->file_name
, O_WRONLY
, 0644);
319 memcpy (&controller
->data
[base
], source
, nr_bytes
);
320 result
= write (fd
, controller
->data
, controller
->size
);
325 if (result
!= controller
->size
)
332 case NVRAM_SAVE_MODIFIED
:
337 pos
= lseek (controller
->fd
, (off_t
) base
, SEEK_SET
);
338 if (pos
!= (off_t
) base
)
341 result
= write (controller
->fd
, source
, nr_bytes
);
352 memcpy (&controller
->data
[base
], source
, nr_bytes
);
357 const struct hw_descriptor dv_nvram_descriptor
[] = {
358 { "nvram", nvram_finish
, },