|
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.h" |
|
26 #include "mips.h" |
|
27 #include "nvram.h" |
|
28 |
|
29 //#define DEBUG_NVRAM |
|
30 |
|
31 typedef struct ds1225y_t |
|
32 { |
|
33 uint32_t chip_size; |
|
34 QEMUFile *file; |
|
35 uint8_t *contents; |
|
36 uint8_t protection; |
|
37 } ds1225y_t; |
|
38 |
|
39 |
|
40 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) |
|
41 { |
|
42 ds1225y_t *s = opaque; |
|
43 uint32_t val; |
|
44 |
|
45 val = s->contents[addr]; |
|
46 |
|
47 #ifdef DEBUG_NVRAM |
|
48 printf("nvram: read 0x%x at " TARGET_FMT_lx "\n", val, addr); |
|
49 #endif |
|
50 return val; |
|
51 } |
|
52 |
|
53 static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) |
|
54 { |
|
55 uint32_t v; |
|
56 v = nvram_readb(opaque, addr); |
|
57 v |= nvram_readb(opaque, addr + 1) << 8; |
|
58 return v; |
|
59 } |
|
60 |
|
61 static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr) |
|
62 { |
|
63 uint32_t v; |
|
64 v = nvram_readb(opaque, addr); |
|
65 v |= nvram_readb(opaque, addr + 1) << 8; |
|
66 v |= nvram_readb(opaque, addr + 2) << 16; |
|
67 v |= nvram_readb(opaque, addr + 3) << 24; |
|
68 return v; |
|
69 } |
|
70 |
|
71 static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
72 { |
|
73 ds1225y_t *s = opaque; |
|
74 |
|
75 #ifdef DEBUG_NVRAM |
|
76 printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr); |
|
77 #endif |
|
78 |
|
79 s->contents[addr] = val & 0xff; |
|
80 if (s->file) { |
|
81 qemu_fseek(s->file, addr, SEEK_SET); |
|
82 qemu_put_byte(s->file, (int)val); |
|
83 qemu_fflush(s->file); |
|
84 } |
|
85 } |
|
86 |
|
87 static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
88 { |
|
89 nvram_writeb(opaque, addr, val & 0xff); |
|
90 nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
|
91 } |
|
92 |
|
93 static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
94 { |
|
95 nvram_writeb(opaque, addr, val & 0xff); |
|
96 nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff); |
|
97 nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff); |
|
98 nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff); |
|
99 } |
|
100 |
|
101 static void nvram_writeb_protected (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
102 { |
|
103 ds1225y_t *s = opaque; |
|
104 |
|
105 if (s->protection != 7) { |
|
106 #ifdef DEBUG_NVRAM |
|
107 printf("nvram: prevent write of 0x%x at " TARGET_FMT_lx "\n", val, addr); |
|
108 #endif |
|
109 return; |
|
110 } |
|
111 |
|
112 nvram_writeb(opaque, addr, val); |
|
113 } |
|
114 |
|
115 static void nvram_writew_protected (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
116 { |
|
117 nvram_writeb_protected(opaque, addr, val & 0xff); |
|
118 nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff); |
|
119 } |
|
120 |
|
121 static void nvram_writel_protected (void *opaque, target_phys_addr_t addr, uint32_t val) |
|
122 { |
|
123 nvram_writeb_protected(opaque, addr, val & 0xff); |
|
124 nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff); |
|
125 nvram_writeb_protected(opaque, addr + 2, (val >> 16) & 0xff); |
|
126 nvram_writeb_protected(opaque, addr + 3, (val >> 24) & 0xff); |
|
127 } |
|
128 |
|
129 static CPUReadMemoryFunc *nvram_read[] = { |
|
130 &nvram_readb, |
|
131 &nvram_readw, |
|
132 &nvram_readl, |
|
133 }; |
|
134 |
|
135 static CPUWriteMemoryFunc *nvram_write[] = { |
|
136 &nvram_writeb, |
|
137 &nvram_writew, |
|
138 &nvram_writel, |
|
139 }; |
|
140 |
|
141 static CPUWriteMemoryFunc *nvram_write_protected[] = { |
|
142 &nvram_writeb_protected, |
|
143 &nvram_writew_protected, |
|
144 &nvram_writel_protected, |
|
145 }; |
|
146 |
|
147 /* Initialisation routine */ |
|
148 void *ds1225y_init(target_phys_addr_t mem_base, const char *filename) |
|
149 { |
|
150 ds1225y_t *s; |
|
151 int mem_indexRW, mem_indexRP; |
|
152 QEMUFile *file; |
|
153 |
|
154 s = qemu_mallocz(sizeof(ds1225y_t)); |
|
155 if (!s) |
|
156 return NULL; |
|
157 s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */ |
|
158 s->contents = qemu_mallocz(s->chip_size); |
|
159 if (!s->contents) { |
|
160 return NULL; |
|
161 } |
|
162 s->protection = 7; |
|
163 |
|
164 /* Read current file */ |
|
165 file = qemu_fopen(filename, "rb"); |
|
166 if (file) { |
|
167 /* Read nvram contents */ |
|
168 qemu_get_buffer(file, s->contents, s->chip_size); |
|
169 qemu_fclose(file); |
|
170 } |
|
171 s->file = qemu_fopen(filename, "wb"); |
|
172 if (s->file) { |
|
173 /* Write back contents, as 'wb' mode cleaned the file */ |
|
174 qemu_put_buffer(s->file, s->contents, s->chip_size); |
|
175 qemu_fflush(s->file); |
|
176 } |
|
177 |
|
178 /* Read/write memory */ |
|
179 mem_indexRW = cpu_register_io_memory(0, nvram_read, nvram_write, s); |
|
180 cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW); |
|
181 /* Read/write protected memory */ |
|
182 mem_indexRP = cpu_register_io_memory(0, nvram_read, nvram_write_protected, s); |
|
183 cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP); |
|
184 return s; |
|
185 } |