blob: 57d5ab2154564b45d96425be09d53ddcebb9e34d [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
Peter Maydell04308912016-01-26 18:17:30 +000025#include "qemu/osdep.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010026#include "hw/sysbus.h"
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020027#include "trace.h"
aurel3230aa5c02008-03-13 01:19:15 +000028
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020029typedef struct {
Avi Kivity871321a2011-11-10 11:24:24 +020030 MemoryRegion iomem;
aurel3202cb1582008-03-13 19:23:00 +000031 uint32_t chip_size;
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020032 char *filename;
Juan Quintela3a230252011-09-13 14:41:18 +020033 FILE *file;
aurel3202cb1582008-03-13 19:23:00 +000034 uint8_t *contents;
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020035} NvRamState;
aurel3230aa5c02008-03-13 01:19:15 +000036
Avi Kivitya8170e52012-10-23 12:30:10 +020037static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size)
aurel3230aa5c02008-03-13 01:19:15 +000038{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020039 NvRamState *s = opaque;
aurel3202cb1582008-03-13 19:23:00 +000040 uint32_t val;
aurel3230aa5c02008-03-13 01:19:15 +000041
pbrook8da3ff12008-12-01 18:59:50 +000042 val = s->contents[addr];
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020043 trace_nvram_read(addr, val);
aurel3202cb1582008-03-13 19:23:00 +000044 return val;
aurel3230aa5c02008-03-13 01:19:15 +000045}
46
Avi Kivitya8170e52012-10-23 12:30:10 +020047static void nvram_write(void *opaque, hwaddr addr, uint64_t val,
Avi Kivity871321a2011-11-10 11:24:24 +020048 unsigned size)
aurel3202cb1582008-03-13 19:23:00 +000049{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020050 NvRamState *s = opaque;
aurel3230aa5c02008-03-13 01:19:15 +000051
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020052 val &= 0xff;
53 trace_nvram_write(addr, s->contents[addr], val);
aurel3202cb1582008-03-13 19:23:00 +000054
Hervé Poussineaud43ed9e2011-07-18 23:34:21 +020055 s->contents[addr] = val;
aurel3202cb1582008-03-13 19:23:00 +000056 if (s->file) {
Juan Quintela3a230252011-09-13 14:41:18 +020057 fseek(s->file, addr, SEEK_SET);
58 fputc(val, s->file);
59 fflush(s->file);
aurel3230aa5c02008-03-13 01:19:15 +000060 }
61}
62
Avi Kivity871321a2011-11-10 11:24:24 +020063static 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,
aurel3230aa5c02008-03-13 01:19:15 +000071};
72
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020073static int nvram_post_load(void *opaque, int version_id)
aurel3230aa5c02008-03-13 01:19:15 +000074{
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020075 NvRamState *s = opaque;
aurel3230aa5c02008-03-13 01:19:15 +000076
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020077 /* Close file, as filename may has changed in load/store process */
78 if (s->file) {
Juan Quintela3a230252011-09-13 14:41:18 +020079 fclose(s->file);
aurel3202cb1582008-03-13 19:23:00 +000080 }
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020081
82 /* Write back nvram contents */
Juan Quintela3a230252011-09-13 14:41:18 +020083 s->file = fopen(s->filename, "wb");
aurel3202cb1582008-03-13 19:23:00 +000084 if (s->file) {
85 /* Write back contents, as 'wb' mode cleaned the file */
Juan Quintela3a230252011-09-13 14:41:18 +020086 if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) {
87 printf("nvram_post_load: short write\n");
88 }
89 fflush(s->file);
aurel3202cb1582008-03-13 19:23:00 +000090 }
aurel3230aa5c02008-03-13 01:19:15 +000091
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020092 return 0;
aurel3230aa5c02008-03-13 01:19:15 +000093}
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020094
95static const VMStateDescription vmstate_nvram = {
96 .name = "nvram",
97 .version_id = 0,
98 .minimum_version_id = 0,
Hervé Poussineaucd3e2402011-07-18 23:34:22 +020099 .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)