virtio-ccw-input: fix description
[qemu/ar7.git] / hw / core / register.c
blobddf91eb445e169b9e7b91f4240e6a9b6ff30c7fc
1 /*
2 * Register Definition API
4 * Copyright (c) 2016 Xilinx Inc.
5 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
18 #include "qemu/osdep.h"
19 #include "hw/register.h"
20 #include "qemu/log.h"
21 #include "qemu/module.h"
23 static inline void register_write_val(RegisterInfo *reg, uint64_t val)
25 g_assert(reg->data);
27 switch (reg->data_size) {
28 case 1:
29 *(uint8_t *)reg->data = val;
30 break;
31 case 2:
32 *(uint16_t *)reg->data = val;
33 break;
34 case 4:
35 *(uint32_t *)reg->data = val;
36 break;
37 case 8:
38 *(uint64_t *)reg->data = val;
39 break;
40 default:
41 g_assert_not_reached();
45 static inline uint64_t register_read_val(RegisterInfo *reg)
47 switch (reg->data_size) {
48 case 1:
49 return *(uint8_t *)reg->data;
50 case 2:
51 return *(uint16_t *)reg->data;
52 case 4:
53 return *(uint32_t *)reg->data;
54 case 8:
55 return *(uint64_t *)reg->data;
56 default:
57 g_assert_not_reached();
59 return 0; /* unreachable */
62 static inline uint64_t register_enabled_mask(int data_size, unsigned size)
64 if (data_size < size) {
65 size = data_size;
68 return MAKE_64BIT_MASK(0, size * 8);
71 void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
72 const char *prefix, bool debug)
74 uint64_t old_val, new_val, test, no_w_mask;
75 const RegisterAccessInfo *ac;
77 assert(reg);
79 ac = reg->access;
81 if (!ac || !ac->name) {
82 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
83 "(written value: %#" PRIx64 ")\n", prefix, val);
84 return;
87 old_val = reg->data ? register_read_val(reg) : ac->reset;
89 test = (old_val ^ val) & ac->rsvd;
90 if (test) {
91 qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
92 "fields: %#" PRIx64 ")\n", prefix, test);
95 test = val & ac->unimp;
96 if (test) {
97 qemu_log_mask(LOG_UNIMP,
98 "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
99 " %#" PRIx64 "\n",
100 prefix, reg->access->name, val, ac->unimp);
103 /* Create the no write mask based on the read only, write to clear and
104 * reserved bit masks.
106 no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
107 new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
108 new_val &= ~(val & ac->w1c);
110 if (ac->pre_write) {
111 new_val = ac->pre_write(reg, new_val);
114 if (debug) {
115 qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
116 new_val);
119 register_write_val(reg, new_val);
121 if (ac->post_write) {
122 ac->post_write(reg, new_val);
126 uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
127 bool debug)
129 uint64_t ret;
130 const RegisterAccessInfo *ac;
132 assert(reg);
134 ac = reg->access;
135 if (!ac || !ac->name) {
136 qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
137 prefix);
138 return 0;
141 ret = reg->data ? register_read_val(reg) : ac->reset;
143 register_write_val(reg, ret & ~(ac->cor & re));
145 /* Mask based on the read enable size */
146 ret &= re;
148 if (ac->post_read) {
149 ret = ac->post_read(reg, ret);
152 if (debug) {
153 qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
154 ac->name, ret);
157 return ret;
160 void register_reset(RegisterInfo *reg)
162 const RegisterAccessInfo *ac;
164 g_assert(reg);
166 if (!reg->data || !reg->access) {
167 return;
170 ac = reg->access;
172 register_write_val(reg, reg->access->reset);
174 if (ac->post_write) {
175 ac->post_write(reg, reg->access->reset);
179 void register_init(RegisterInfo *reg)
181 assert(reg);
183 if (!reg->data || !reg->access) {
184 return;
187 object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
190 void register_write_memory(void *opaque, hwaddr addr,
191 uint64_t value, unsigned size)
193 RegisterInfoArray *reg_array = opaque;
194 RegisterInfo *reg = NULL;
195 uint64_t we;
196 int i;
198 for (i = 0; i < reg_array->num_elements; i++) {
199 if (reg_array->r[i]->access->addr == addr) {
200 reg = reg_array->r[i];
201 break;
205 if (!reg) {
206 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
207 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
208 return;
211 /* Generate appropriate write enable mask */
212 we = register_enabled_mask(reg->data_size, size);
214 register_write(reg, value, we, reg_array->prefix,
215 reg_array->debug);
218 uint64_t register_read_memory(void *opaque, hwaddr addr,
219 unsigned size)
221 RegisterInfoArray *reg_array = opaque;
222 RegisterInfo *reg = NULL;
223 uint64_t read_val;
224 uint64_t re;
225 int i;
227 for (i = 0; i < reg_array->num_elements; i++) {
228 if (reg_array->r[i]->access->addr == addr) {
229 reg = reg_array->r[i];
230 break;
234 if (!reg) {
235 qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
236 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
237 return 0;
240 /* Generate appropriate read enable mask */
241 re = register_enabled_mask(reg->data_size, size);
243 read_val = register_read(reg, re, reg_array->prefix,
244 reg_array->debug);
246 return extract64(read_val, 0, size * 8);
249 static RegisterInfoArray *register_init_block(DeviceState *owner,
250 const RegisterAccessInfo *rae,
251 int num, RegisterInfo *ri,
252 void *data,
253 const MemoryRegionOps *ops,
254 bool debug_enabled,
255 uint64_t memory_size,
256 size_t data_size_bits)
258 const char *device_prefix = object_get_typename(OBJECT(owner));
259 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
260 int data_size = data_size_bits >> 3;
261 int i;
263 r_array->r = g_new0(RegisterInfo *, num);
264 r_array->num_elements = num;
265 r_array->debug = debug_enabled;
266 r_array->prefix = device_prefix;
268 for (i = 0; i < num; i++) {
269 int index = rae[i].addr / data_size;
270 RegisterInfo *r = &ri[index];
272 *r = (RegisterInfo) {
273 .data = data + data_size * index,
274 .data_size = data_size,
275 .access = &rae[i],
276 .opaque = owner,
278 register_init(r);
280 r_array->r[i] = r;
283 memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
284 device_prefix, memory_size);
286 return r_array;
289 RegisterInfoArray *register_init_block8(DeviceState *owner,
290 const RegisterAccessInfo *rae,
291 int num, RegisterInfo *ri,
292 uint8_t *data,
293 const MemoryRegionOps *ops,
294 bool debug_enabled,
295 uint64_t memory_size)
297 return register_init_block(owner, rae, num, ri, (void *)
298 data, ops, debug_enabled, memory_size, 8);
301 RegisterInfoArray *register_init_block32(DeviceState *owner,
302 const RegisterAccessInfo *rae,
303 int num, RegisterInfo *ri,
304 uint32_t *data,
305 const MemoryRegionOps *ops,
306 bool debug_enabled,
307 uint64_t memory_size)
309 return register_init_block(owner, rae, num, ri, (void *)
310 data, ops, debug_enabled, memory_size, 32);
313 void register_finalize_block(RegisterInfoArray *r_array)
315 object_unparent(OBJECT(&r_array->mem));
316 g_free(r_array->r);
317 g_free(r_array);
320 static void register_class_init(ObjectClass *oc, void *data)
322 DeviceClass *dc = DEVICE_CLASS(oc);
324 /* Reason: needs to be wired up to work */
325 dc->user_creatable = false;
328 static const TypeInfo register_info = {
329 .name = TYPE_REGISTER,
330 .parent = TYPE_DEVICE,
331 .class_init = register_class_init,
334 static void register_register_types(void)
336 type_register_static(&register_info);
339 type_init(register_register_types)