blob: f9a700b01c9a58936f987c0e5d52c2e8d2383d9e [file] [log] [blame]
aurel3230aa5c02008-03-13 01:19:15 +00001/*
2 * QEMU NVRAM emulation for DS1225Y chip
aurel3202cb1582008-03-13 19:23:00 +00003 *
Stefan Weilbcc4e412011-12-02 10:30:41 +01004 * Copyright (c) 2007-2008 Hervé Poussineau
aurel3202cb1582008-03-13 19:23:00 +00005 *
aurel3230aa5c02008-03-13 01:19:15 +00006 * 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
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010025#include "hw/sysbus.h"
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020026#include "trace.h"
aurel3230aa5c02008-03-13 01:19:15 +000027
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020028typedef struct {
Avi Kivity871321a2011-11-10 11:24:24 +020029 MemoryRegion iomem;
aurel3202cb1582008-03-13 19:23:00 +000030 uint32_t chip_size;
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020031 char *filename;
Juan Quintela3a230252011-09-13 14:41:18 +020032 FILE *file;
aurel3202cb1582008-03-13 19:23:00 +000033 uint8_t *contents;
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020034} NvRamState;
aurel3230aa5c02008-03-13 01:19:15 +000035
Avi Kivitya8170e52012-10-23 12:30:10 +020036static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size)
aurel3230aa5c02008-03-13 01:19:15 +000037{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020038 NvRamState *s = opaque;
aurel3202cb1582008-03-13 19:23:00 +000039 uint32_t val;
aurel3230aa5c02008-03-13 01:19:15 +000040
pbrook8da3ff12008-12-01 18:59:50 +000041 val = s->contents[addr];
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020042 trace_nvram_read(addr, val);
aurel3202cb1582008-03-13 19:23:00 +000043 return val;
aurel3230aa5c02008-03-13 01:19:15 +000044}
45
Avi Kivitya8170e52012-10-23 12:30:10 +020046static void nvram_write(void *opaque, hwaddr addr, uint64_t val,
Avi Kivity871321a2011-11-10 11:24:24 +020047 unsigned size)
aurel3202cb1582008-03-13 19:23:00 +000048{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020049 NvRamState *s = opaque;
aurel3230aa5c02008-03-13 01:19:15 +000050
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020051 val &= 0xff;
52 trace_nvram_write(addr, s->contents[addr], val);
aurel3202cb1582008-03-13 19:23:00 +000053
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020054 s->contents[addr] = val;
aurel3202cb1582008-03-13 19:23:00 +000055 if (s->file) {
Juan Quintela3a230252011-09-13 14:41:18 +020056 fseek(s->file, addr, SEEK_SET);
57 fputc(val, s->file);
58 fflush(s->file);
aurel3230aa5c02008-03-13 01:19:15 +000059 }
60}
61
Avi Kivity871321a2011-11-10 11:24:24 +020062static const MemoryRegionOps nvram_ops = {
63 .read = nvram_read,
64 .write = nvram_write,
65 .impl = {
66 .min_access_size = 1,
67 .max_access_size = 1,
68 },
69 .endianness = DEVICE_LITTLE_ENDIAN,
aurel3230aa5c02008-03-13 01:19:15 +000070};
71
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020072static int nvram_post_load(void *opaque, int version_id)
aurel3230aa5c02008-03-13 01:19:15 +000073{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020074 NvRamState *s = opaque;
aurel3230aa5c02008-03-13 01:19:15 +000075
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020076 /* Close file, as filename may has changed in load/store process */
77 if (s->file) {
Juan Quintela3a230252011-09-13 14:41:18 +020078 fclose(s->file);
aurel3202cb1582008-03-13 19:23:00 +000079 }
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020080
81 /* Write back nvram contents */
Juan Quintela3a230252011-09-13 14:41:18 +020082 s->file = fopen(s->filename, "wb");
aurel3202cb1582008-03-13 19:23:00 +000083 if (s->file) {
84 /* Write back contents, as 'wb' mode cleaned the file */
Juan Quintela3a230252011-09-13 14:41:18 +020085 if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) {
86 printf("nvram_post_load: short write\n");
87 }
88 fflush(s->file);
aurel3202cb1582008-03-13 19:23:00 +000089 }
aurel3230aa5c02008-03-13 01:19:15 +000090
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020091 return 0;
aurel3230aa5c02008-03-13 01:19:15 +000092}
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020093
94static const VMStateDescription vmstate_nvram = {
95 .name = "nvram",
96 .version_id = 0,
97 .minimum_version_id = 0,
98 .minimum_version_id_old = 0,
99 .post_load = nvram_post_load,
100 .fields = (VMStateField[]) {
101 VMSTATE_VARRAY_UINT32(contents, NvRamState, chip_size, 0,
102 vmstate_info_uint8, uint8_t),
103 VMSTATE_END_OF_LIST()
104 }
105};
106
Andreas Färber8c1892c2013-07-27 12:50:29 +0200107#define TYPE_DS1225Y "ds1225y"
108#define DS1225Y(obj) OBJECT_CHECK(SysBusNvRamState, (obj), TYPE_DS1225Y)
109
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200110typedef struct {
Andreas Färber8c1892c2013-07-27 12:50:29 +0200111 SysBusDevice parent_obj;
112
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200113 NvRamState nvram;
114} SysBusNvRamState;
115
116static int nvram_sysbus_initfn(SysBusDevice *dev)
117{
Andreas Färber8c1892c2013-07-27 12:50:29 +0200118 SysBusNvRamState *sys = DS1225Y(dev);
119 NvRamState *s = &sys->nvram;
Juan Quintela3a230252011-09-13 14:41:18 +0200120 FILE *file;
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200121
Anthony Liguori7267c092011-08-20 22:09:37 -0500122 s->contents = g_malloc0(s->chip_size);
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200123
Paolo Bonzinieedfac62013-06-06 21:25:08 -0400124 memory_region_init_io(&s->iomem, OBJECT(s), &nvram_ops, s,
125 "nvram", s->chip_size);
Avi Kivity750ecd42011-11-27 11:38:10 +0200126 sysbus_init_mmio(dev, &s->iomem);
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200127
128 /* Read current file */
Juan Quintela3a230252011-09-13 14:41:18 +0200129 file = fopen(s->filename, "rb");
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200130 if (file) {
131 /* Read nvram contents */
Juan Quintela3a230252011-09-13 14:41:18 +0200132 if (fread(s->contents, s->chip_size, 1, file) != 1) {
133 printf("nvram_sysbus_initfn: short read\n");
134 }
135 fclose(file);
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200136 }
137 nvram_post_load(s, 0);
138
139 return 0;
140}
141
Anthony Liguori999e12b2012-01-24 13:12:29 -0600142static Property nvram_sysbus_properties[] = {
143 DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000),
144 DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
145 DEFINE_PROP_END_OF_LIST(),
146};
147
148static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
149{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600150 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600151 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
152
153 k->init = nvram_sysbus_initfn;
Anthony Liguori39bffca2011-12-07 21:34:16 -0600154 dc->vmsd = &vmstate_nvram;
155 dc->props = nvram_sysbus_properties;
Anthony Liguori999e12b2012-01-24 13:12:29 -0600156}
157
Andreas Färber8c43a6f2013-01-10 16:19:07 +0100158static const TypeInfo nvram_sysbus_info = {
Andreas Färber8c1892c2013-07-27 12:50:29 +0200159 .name = TYPE_DS1225Y,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600160 .parent = TYPE_SYS_BUS_DEVICE,
161 .instance_size = sizeof(SysBusNvRamState),
162 .class_init = nvram_sysbus_class_init,
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200163};
164
Andreas Färber83f7d432012-02-09 15:20:55 +0100165static void nvram_register_types(void)
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200166{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600167 type_register_static(&nvram_sysbus_info);
Hervé Poussineaucd3e2402011-07-18 23:34:22 +0200168}
169
Andreas Färber83f7d432012-02-09 15:20:55 +0100170type_init(nvram_register_types)