etrax: Don't keep the passed irq pointer.
[qemu] / hw / ds1225y.c
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     s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
156     s->contents = qemu_mallocz(s->chip_size);
157     s->protection = 7;
158
159     /* Read current file */
160     file = qemu_fopen(filename, "rb");
161     if (file) {
162         /* Read nvram contents */
163         qemu_get_buffer(file, s->contents, s->chip_size);
164         qemu_fclose(file);
165     }
166     s->file = qemu_fopen(filename, "wb");
167     if (s->file) {
168         /* Write back contents, as 'wb' mode cleaned the file */
169         qemu_put_buffer(s->file, s->contents, s->chip_size);
170         qemu_fflush(s->file);
171     }
172
173     /* Read/write memory */
174     mem_indexRW = cpu_register_io_memory(0, nvram_read, nvram_write, s);
175     cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
176     /* Read/write protected memory */
177     mem_indexRP = cpu_register_io_memory(0, nvram_read, nvram_write_protected, s);
178     cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
179     return s;
180 }