1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "hw/sysbus.h"
27#include "migration/vmstate.h"
28#include "qemu/module.h"
29#include "trace.h"
30#include "qom/object.h"
31
32
33
34
35#define CS_SIZE 0x40
36#define CS_REGS 16
37#define CS_DREGS 32
38#define CS_MAXDREG (CS_DREGS - 1)
39
40#define TYPE_CS4231 "sun-CS4231"
41typedef struct CSState CSState;
42DECLARE_INSTANCE_CHECKER(CSState, CS4231,
43 TYPE_CS4231)
44
45struct CSState {
46 SysBusDevice parent_obj;
47
48 MemoryRegion iomem;
49 qemu_irq irq;
50 uint32_t regs[CS_REGS];
51 uint8_t dregs[CS_DREGS];
52};
53
54#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
55#define CS_VER 0xa0
56#define CS_CDC_VER 0x8a
57
58static void cs_reset(DeviceState *d)
59{
60 CSState *s = CS4231(d);
61
62 memset(s->regs, 0, CS_REGS * 4);
63 memset(s->dregs, 0, CS_DREGS);
64 s->dregs[12] = CS_CDC_VER;
65 s->dregs[25] = CS_VER;
66}
67
68static uint64_t cs_mem_read(void *opaque, hwaddr addr,
69 unsigned size)
70{
71 CSState *s = opaque;
72 uint32_t saddr, ret;
73
74 saddr = addr >> 2;
75 switch (saddr) {
76 case 1:
77 switch (CS_RAP(s)) {
78 case 3:
79 ret = 0;
80 break;
81 default:
82 ret = s->dregs[CS_RAP(s)];
83 break;
84 }
85 trace_cs4231_mem_readl_dreg(CS_RAP(s), ret);
86 break;
87 default:
88 ret = s->regs[saddr];
89 trace_cs4231_mem_readl_reg(saddr, ret);
90 break;
91 }
92 return ret;
93}
94
95static void cs_mem_write(void *opaque, hwaddr addr,
96 uint64_t val, unsigned size)
97{
98 CSState *s = opaque;
99 uint32_t saddr;
100
101 saddr = addr >> 2;
102 trace_cs4231_mem_writel_reg(saddr, s->regs[saddr], val);
103 switch (saddr) {
104 case 1:
105 trace_cs4231_mem_writel_dreg(CS_RAP(s), s->dregs[CS_RAP(s)], val);
106 switch(CS_RAP(s)) {
107 case 11:
108 case 25:
109 break;
110 case 12:
111 val &= 0x40;
112 val |= CS_CDC_VER;
113 s->dregs[CS_RAP(s)] = val;
114 break;
115 default:
116 s->dregs[CS_RAP(s)] = val;
117 break;
118 }
119 break;
120 case 2:
121 break;
122 case 4:
123 if (val & 1) {
124 cs_reset(DEVICE(s));
125 }
126 val &= 0x7f;
127 s->regs[saddr] = val;
128 break;
129 default:
130 s->regs[saddr] = val;
131 break;
132 }
133}
134
135static const MemoryRegionOps cs_mem_ops = {
136 .read = cs_mem_read,
137 .write = cs_mem_write,
138 .endianness = DEVICE_NATIVE_ENDIAN,
139};
140
141static const VMStateDescription vmstate_cs4231 = {
142 .name ="cs4231",
143 .version_id = 1,
144 .minimum_version_id = 1,
145 .fields = (VMStateField[]) {
146 VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
147 VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS),
148 VMSTATE_END_OF_LIST()
149 }
150};
151
152static void cs4231_init(Object *obj)
153{
154 CSState *s = CS4231(obj);
155 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
156
157 memory_region_init_io(&s->iomem, obj, &cs_mem_ops, s, "cs4321",
158 CS_SIZE);
159 sysbus_init_mmio(dev, &s->iomem);
160 sysbus_init_irq(dev, &s->irq);
161}
162
163static void cs4231_class_init(ObjectClass *klass, void *data)
164{
165 DeviceClass *dc = DEVICE_CLASS(klass);
166
167 dc->reset = cs_reset;
168 dc->vmsd = &vmstate_cs4231;
169}
170
171static const TypeInfo cs4231_info = {
172 .name = TYPE_CS4231,
173 .parent = TYPE_SYS_BUS_DEVICE,
174 .instance_size = sizeof(CSState),
175 .instance_init = cs4231_init,
176 .class_init = cs4231_class_init,
177};
178
179static void cs4231_register_types(void)
180{
181 type_register_static(&cs4231_info);
182}
183
184type_init(cs4231_register_types)
185