root / hw / nvram / ds1225y.c @ 49ab747f
History | View | Annotate | Download (4.5 kB)
1 |
/*
|
---|---|
2 |
* QEMU NVRAM emulation for DS1225Y chip
|
3 |
*
|
4 |
* Copyright (c) 2007-2008 Hervé Poussineau
|
5 |
*
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 |
* of this software and associated documentation files (the "Software"), to deal
|
8 |
* in the Software without restriction, including without limitation the rights
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 |
* copies of the Software, and to permit persons to whom the Software is
|
11 |
* furnished to do so, subject to the following conditions:
|
12 |
*
|
13 |
* The above copyright notice and this permission notice shall be included in
|
14 |
* all copies or substantial portions of the Software.
|
15 |
*
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 |
* THE SOFTWARE.
|
23 |
*/
|
24 |
|
25 |
#include "hw/sysbus.h" |
26 |
#include "trace.h" |
27 |
|
28 |
typedef struct { |
29 |
DeviceState qdev; |
30 |
MemoryRegion iomem; |
31 |
uint32_t chip_size; |
32 |
char *filename;
|
33 |
FILE *file; |
34 |
uint8_t *contents; |
35 |
} NvRamState; |
36 |
|
37 |
static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size) |
38 |
{ |
39 |
NvRamState *s = opaque; |
40 |
uint32_t val; |
41 |
|
42 |
val = s->contents[addr]; |
43 |
trace_nvram_read(addr, val); |
44 |
return val;
|
45 |
} |
46 |
|
47 |
static void nvram_write(void *opaque, hwaddr addr, uint64_t val, |
48 |
unsigned size)
|
49 |
{ |
50 |
NvRamState *s = opaque; |
51 |
|
52 |
val &= 0xff;
|
53 |
trace_nvram_write(addr, s->contents[addr], val); |
54 |
|
55 |
s->contents[addr] = val; |
56 |
if (s->file) {
|
57 |
fseek(s->file, addr, SEEK_SET); |
58 |
fputc(val, s->file); |
59 |
fflush(s->file); |
60 |
} |
61 |
} |
62 |
|
63 |
static const MemoryRegionOps nvram_ops = { |
64 |
.read = nvram_read, |
65 |
.write = nvram_write, |
66 |
.impl = { |
67 |
.min_access_size = 1,
|
68 |
.max_access_size = 1,
|
69 |
}, |
70 |
.endianness = DEVICE_LITTLE_ENDIAN, |
71 |
}; |
72 |
|
73 |
static int nvram_post_load(void *opaque, int version_id) |
74 |
{ |
75 |
NvRamState *s = opaque; |
76 |
|
77 |
/* Close file, as filename may has changed in load/store process */
|
78 |
if (s->file) {
|
79 |
fclose(s->file); |
80 |
} |
81 |
|
82 |
/* Write back nvram contents */
|
83 |
s->file = fopen(s->filename, "wb");
|
84 |
if (s->file) {
|
85 |
/* Write back contents, as 'wb' mode cleaned the file */
|
86 |
if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) { |
87 |
printf("nvram_post_load: short write\n");
|
88 |
} |
89 |
fflush(s->file); |
90 |
} |
91 |
|
92 |
return 0; |
93 |
} |
94 |
|
95 |
static const VMStateDescription vmstate_nvram = { |
96 |
.name = "nvram",
|
97 |
.version_id = 0,
|
98 |
.minimum_version_id = 0,
|
99 |
.minimum_version_id_old = 0,
|
100 |
.post_load = nvram_post_load, |
101 |
.fields = (VMStateField[]) { |
102 |
VMSTATE_VARRAY_UINT32(contents, NvRamState, chip_size, 0,
|
103 |
vmstate_info_uint8, uint8_t), |
104 |
VMSTATE_END_OF_LIST() |
105 |
} |
106 |
}; |
107 |
|
108 |
typedef struct { |
109 |
SysBusDevice busdev; |
110 |
NvRamState nvram; |
111 |
} SysBusNvRamState; |
112 |
|
113 |
static int nvram_sysbus_initfn(SysBusDevice *dev) |
114 |
{ |
115 |
NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram; |
116 |
FILE *file; |
117 |
|
118 |
s->contents = g_malloc0(s->chip_size); |
119 |
|
120 |
memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size);
|
121 |
sysbus_init_mmio(dev, &s->iomem); |
122 |
|
123 |
/* Read current file */
|
124 |
file = fopen(s->filename, "rb");
|
125 |
if (file) {
|
126 |
/* Read nvram contents */
|
127 |
if (fread(s->contents, s->chip_size, 1, file) != 1) { |
128 |
printf("nvram_sysbus_initfn: short read\n");
|
129 |
} |
130 |
fclose(file); |
131 |
} |
132 |
nvram_post_load(s, 0);
|
133 |
|
134 |
return 0; |
135 |
} |
136 |
|
137 |
static Property nvram_sysbus_properties[] = {
|
138 |
DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000), |
139 |
DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
|
140 |
DEFINE_PROP_END_OF_LIST(), |
141 |
}; |
142 |
|
143 |
static void nvram_sysbus_class_init(ObjectClass *klass, void *data) |
144 |
{ |
145 |
DeviceClass *dc = DEVICE_CLASS(klass); |
146 |
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |
147 |
|
148 |
k->init = nvram_sysbus_initfn; |
149 |
dc->vmsd = &vmstate_nvram; |
150 |
dc->props = nvram_sysbus_properties; |
151 |
} |
152 |
|
153 |
static const TypeInfo nvram_sysbus_info = { |
154 |
.name = "ds1225y",
|
155 |
.parent = TYPE_SYS_BUS_DEVICE, |
156 |
.instance_size = sizeof(SysBusNvRamState),
|
157 |
.class_init = nvram_sysbus_class_init, |
158 |
}; |
159 |
|
160 |
static void nvram_register_types(void) |
161 |
{ |
162 |
type_register_static(&nvram_sysbus_info); |
163 |
} |
164 |
|
165 |
type_init(nvram_register_types) |