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
18 #include "qemu/osdep.h"
19 #include "hw/register.h"
23 static inline void register_write_val(RegisterInfo
*reg
, uint64_t val
)
27 switch (reg
->data_size
) {
29 *(uint8_t *)reg
->data
= val
;
32 *(uint16_t *)reg
->data
= val
;
35 *(uint32_t *)reg
->data
= val
;
38 *(uint64_t *)reg
->data
= val
;
41 g_assert_not_reached();
45 static inline uint64_t register_read_val(RegisterInfo
*reg
)
47 switch (reg
->data_size
) {
49 return *(uint8_t *)reg
->data
;
51 return *(uint16_t *)reg
->data
;
53 return *(uint32_t *)reg
->data
;
55 return *(uint64_t *)reg
->data
;
57 g_assert_not_reached();
59 return 0; /* unreachable */
62 void register_write(RegisterInfo
*reg
, uint64_t val
, uint64_t we
,
63 const char *prefix
, bool debug
)
65 uint64_t old_val
, new_val
, test
, no_w_mask
;
66 const RegisterAccessInfo
*ac
;
72 if (!ac
|| !ac
->name
) {
73 qemu_log_mask(LOG_GUEST_ERROR
, "%s: write to undefined device state "
74 "(written value: %#" PRIx64
")\n", prefix
, val
);
78 old_val
= reg
->data
? register_read_val(reg
) : ac
->reset
;
80 test
= (old_val
^ val
) & ac
->rsvd
;
82 qemu_log_mask(LOG_GUEST_ERROR
, "%s: change of value in reserved bit"
83 "fields: %#" PRIx64
")\n", prefix
, test
);
86 test
= val
& ac
->unimp
;
88 qemu_log_mask(LOG_UNIMP
,
89 "%s:%s writing %#" PRIx64
" to unimplemented bits:" \
91 prefix
, reg
->access
->name
, val
, ac
->unimp
);
94 /* Create the no write mask based on the read only, write to clear and
97 no_w_mask
= ac
->ro
| ac
->w1c
| ac
->rsvd
| ~we
;
98 new_val
= (val
& ~no_w_mask
) | (old_val
& no_w_mask
);
99 new_val
&= ~(val
& ac
->w1c
);
102 new_val
= ac
->pre_write(reg
, new_val
);
106 qemu_log("%s:%s: write of value %#" PRIx64
"\n", prefix
, ac
->name
,
110 register_write_val(reg
, new_val
);
112 if (ac
->post_write
) {
113 ac
->post_write(reg
, new_val
);
117 uint64_t register_read(RegisterInfo
*reg
, uint64_t re
, const char* prefix
,
121 const RegisterAccessInfo
*ac
;
126 if (!ac
|| !ac
->name
) {
127 qemu_log_mask(LOG_GUEST_ERROR
, "%s: read from undefined device state\n",
132 ret
= reg
->data
? register_read_val(reg
) : ac
->reset
;
134 register_write_val(reg
, ret
& ~(ac
->cor
& re
));
136 /* Mask based on the read enable size */
140 ret
= ac
->post_read(reg
, ret
);
144 qemu_log("%s:%s: read of value %#" PRIx64
"\n", prefix
,
151 void register_reset(RegisterInfo
*reg
)
155 if (!reg
->data
|| !reg
->access
) {
159 register_write_val(reg
, reg
->access
->reset
);
162 void register_init(RegisterInfo
*reg
)
166 if (!reg
->data
|| !reg
->access
) {
170 object_initialize((void *)reg
, sizeof(*reg
), TYPE_REGISTER
);
173 void register_write_memory(void *opaque
, hwaddr addr
,
174 uint64_t value
, unsigned size
)
176 RegisterInfoArray
*reg_array
= opaque
;
177 RegisterInfo
*reg
= NULL
;
181 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
182 if (reg_array
->r
[i
]->access
->addr
== addr
) {
183 reg
= reg_array
->r
[i
];
189 qemu_log_mask(LOG_GUEST_ERROR
, "Write to unimplemented register at " \
190 "address: %#" PRIx64
"\n", addr
);
194 /* Generate appropriate write enable mask */
195 if (reg
->data_size
< size
) {
196 we
= MAKE_64BIT_MASK(0, reg
->data_size
* 8);
198 we
= MAKE_64BIT_MASK(0, size
* 8);
201 register_write(reg
, value
, we
, reg_array
->prefix
,
205 uint64_t register_read_memory(void *opaque
, hwaddr addr
,
208 RegisterInfoArray
*reg_array
= opaque
;
209 RegisterInfo
*reg
= NULL
;
213 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
214 if (reg_array
->r
[i
]->access
->addr
== addr
) {
215 reg
= reg_array
->r
[i
];
221 qemu_log_mask(LOG_GUEST_ERROR
, "Read to unimplemented register at " \
222 "address: %#" PRIx64
"\n", addr
);
226 read_val
= register_read(reg
, size
* 8, reg_array
->prefix
,
229 return extract64(read_val
, 0, size
* 8);
232 RegisterInfoArray
*register_init_block32(DeviceState
*owner
,
233 const RegisterAccessInfo
*rae
,
234 int num
, RegisterInfo
*ri
,
236 const MemoryRegionOps
*ops
,
238 uint64_t memory_size
)
240 const char *device_prefix
= object_get_typename(OBJECT(owner
));
241 RegisterInfoArray
*r_array
= g_new0(RegisterInfoArray
, 1);
244 r_array
->r
= g_new0(RegisterInfo
*, num
);
245 r_array
->num_elements
= num
;
246 r_array
->debug
= debug_enabled
;
247 r_array
->prefix
= device_prefix
;
249 for (i
= 0; i
< num
; i
++) {
250 int index
= rae
[i
].addr
/ 4;
251 RegisterInfo
*r
= &ri
[index
];
253 *r
= (RegisterInfo
) {
254 .data
= &data
[index
],
255 .data_size
= sizeof(uint32_t),
264 memory_region_init_io(&r_array
->mem
, OBJECT(owner
), ops
, r_array
,
265 device_prefix
, memory_size
);
270 void register_finalize_block(RegisterInfoArray
*r_array
)
272 object_unparent(OBJECT(&r_array
->mem
));
277 static const TypeInfo register_info
= {
278 .name
= TYPE_REGISTER
,
279 .parent
= TYPE_DEVICE
,
282 static void register_register_types(void)
284 type_register_static(®ister_info
);
287 type_init(register_register_types
)