root / hw / ds1225y.c @ cd3e2409
History | View | Annotate | Download (5.1 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 "sysbus.h" |
26 |
#include "trace.h" |
27 |
|
28 |
typedef struct { |
29 |
DeviceState qdev; |
30 |
uint32_t chip_size; |
31 |
char *filename;
|
32 |
QEMUFile *file; |
33 |
uint8_t *contents; |
34 |
} NvRamState; |
35 |
|
36 |
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) |
37 |
{ |
38 |
NvRamState *s = opaque; |
39 |
uint32_t val; |
40 |
|
41 |
val = s->contents[addr]; |
42 |
trace_nvram_read(addr, val); |
43 |
return val;
|
44 |
} |
45 |
|
46 |
static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) |
47 |
{ |
48 |
uint32_t v; |
49 |
v = nvram_readb(opaque, addr); |
50 |
v |= nvram_readb(opaque, addr + 1) << 8; |
51 |
return v;
|
52 |
} |
53 |
|
54 |
static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr) |
55 |
{ |
56 |
uint32_t v; |
57 |
v = nvram_readb(opaque, addr); |
58 |
v |= nvram_readb(opaque, addr + 1) << 8; |
59 |
v |= nvram_readb(opaque, addr + 2) << 16; |
60 |
v |= nvram_readb(opaque, addr + 3) << 24; |
61 |
return v;
|
62 |
} |
63 |
|
64 |
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
65 |
{ |
66 |
NvRamState *s = opaque; |
67 |
|
68 |
val &= 0xff;
|
69 |
trace_nvram_write(addr, s->contents[addr], val); |
70 |
|
71 |
s->contents[addr] = val; |
72 |
if (s->file) {
|
73 |
qemu_fseek(s->file, addr, SEEK_SET); |
74 |
qemu_put_byte(s->file, (int)val);
|
75 |
qemu_fflush(s->file); |
76 |
} |
77 |
} |
78 |
|
79 |
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
80 |
{ |
81 |
nvram_writeb(opaque, addr, val & 0xff);
|
82 |
nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
83 |
} |
84 |
|
85 |
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
86 |
{ |
87 |
nvram_writeb(opaque, addr, val & 0xff);
|
88 |
nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
89 |
nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff); |
90 |
nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff); |
91 |
} |
92 |
|
93 |
static CPUReadMemoryFunc * const nvram_read[] = { |
94 |
&nvram_readb, |
95 |
&nvram_readw, |
96 |
&nvram_readl, |
97 |
}; |
98 |
|
99 |
static CPUWriteMemoryFunc * const nvram_write[] = { |
100 |
&nvram_writeb, |
101 |
&nvram_writew, |
102 |
&nvram_writel, |
103 |
}; |
104 |
|
105 |
static int nvram_post_load(void *opaque, int version_id) |
106 |
{ |
107 |
NvRamState *s = opaque; |
108 |
|
109 |
/* Close file, as filename may has changed in load/store process */
|
110 |
if (s->file) {
|
111 |
qemu_fclose(s->file); |
112 |
} |
113 |
|
114 |
/* Write back nvram contents */
|
115 |
s->file = qemu_fopen(s->filename, "wb");
|
116 |
if (s->file) {
|
117 |
/* Write back contents, as 'wb' mode cleaned the file */
|
118 |
qemu_put_buffer(s->file, s->contents, s->chip_size); |
119 |
qemu_fflush(s->file); |
120 |
} |
121 |
|
122 |
return 0; |
123 |
} |
124 |
|
125 |
static const VMStateDescription vmstate_nvram = { |
126 |
.name = "nvram",
|
127 |
.version_id = 0,
|
128 |
.minimum_version_id = 0,
|
129 |
.minimum_version_id_old = 0,
|
130 |
.post_load = nvram_post_load, |
131 |
.fields = (VMStateField[]) { |
132 |
VMSTATE_VARRAY_UINT32(contents, NvRamState, chip_size, 0,
|
133 |
vmstate_info_uint8, uint8_t), |
134 |
VMSTATE_END_OF_LIST() |
135 |
} |
136 |
}; |
137 |
|
138 |
typedef struct { |
139 |
SysBusDevice busdev; |
140 |
NvRamState nvram; |
141 |
} SysBusNvRamState; |
142 |
|
143 |
static int nvram_sysbus_initfn(SysBusDevice *dev) |
144 |
{ |
145 |
NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram; |
146 |
QEMUFile *file; |
147 |
int s_io;
|
148 |
|
149 |
s->contents = qemu_mallocz(s->chip_size); |
150 |
|
151 |
s_io = cpu_register_io_memory(nvram_read, nvram_write, s, |
152 |
DEVICE_NATIVE_ENDIAN); |
153 |
sysbus_init_mmio(dev, s->chip_size, s_io); |
154 |
|
155 |
/* Read current file */
|
156 |
file = qemu_fopen(s->filename, "rb");
|
157 |
if (file) {
|
158 |
/* Read nvram contents */
|
159 |
qemu_get_buffer(file, s->contents, s->chip_size); |
160 |
qemu_fclose(file); |
161 |
} |
162 |
nvram_post_load(s, 0);
|
163 |
|
164 |
return 0; |
165 |
} |
166 |
|
167 |
static SysBusDeviceInfo nvram_sysbus_info = {
|
168 |
.qdev.name = "ds1225y",
|
169 |
.qdev.size = sizeof(SysBusNvRamState),
|
170 |
.qdev.vmsd = &vmstate_nvram, |
171 |
.init = nvram_sysbus_initfn, |
172 |
.qdev.props = (Property[]) { |
173 |
DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000), |
174 |
DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
|
175 |
DEFINE_PROP_END_OF_LIST(), |
176 |
}, |
177 |
}; |
178 |
|
179 |
static void nvram_register(void) |
180 |
{ |
181 |
sysbus_register_withprop(&nvram_sysbus_info); |
182 |
} |
183 |
|
184 |
device_init(nvram_register) |