1 /*
2 * HP-PARISC Lasi chipset emulation.
3 *
4 * (C) 2019 by Helge Deller <deller@gmx.de>
5 *
6 * This work is licensed under the GNU GPL license version 2 or later.
7 *
8 * Documentation available at:
9 * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
10 */
11
12 #include "qemu/osdep.h"
13 #include "qemu/units.h"
14 #include "qemu/log.h"
15 #include "qapi/error.h"
16 #include "trace.h"
17 #include "hw/irq.h"
18 #include "sysemu/sysemu.h"
19 #include "sysemu/runstate.h"
20 #include "migration/vmstate.h"
21 #include "qom/object.h"
22 #include "hw/misc/lasi.h"
23
24
lasi_chip_mem_valid(void * opaque,hwaddr addr,unsigned size,bool is_write,MemTxAttrs attrs)25 static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
26 unsigned size, bool is_write,
27 MemTxAttrs attrs)
28 {
29 bool ret = false;
30
31 switch (addr) {
32 case LASI_IRR:
33 case LASI_IMR:
34 case LASI_IPR:
35 case LASI_ICR:
36 case LASI_IAR:
37
38 case LASI_LPT:
39 case LASI_AUDIO:
40 case LASI_AUDIO + 4:
41 case LASI_UART:
42 case LASI_LAN:
43 case LASI_LAN + 12: /* LASI LAN MAC */
44 case LASI_RTC:
45 case LASI_FDC:
46
47 case LASI_PCR ... LASI_AMR:
48 ret = true;
49 }
50
51 trace_lasi_chip_mem_valid(addr, ret);
52 return ret;
53 }
54
lasi_chip_read_with_attrs(void * opaque,hwaddr addr,uint64_t * data,unsigned size,MemTxAttrs attrs)55 static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
56 uint64_t *data, unsigned size,
57 MemTxAttrs attrs)
58 {
59 LasiState *s = opaque;
60 MemTxResult ret = MEMTX_OK;
61 uint32_t val;
62
63 switch (addr) {
64 case LASI_IRR:
65 val = s->irr;
66 break;
67 case LASI_IMR:
68 val = s->imr;
69 break;
70 case LASI_IPR:
71 val = s->ipr;
72 /* Any read to IPR clears the register. */
73 s->ipr = 0;
74 break;
75 case LASI_ICR:
76 val = s->icr & ICR_BUS_ERROR_BIT; /* bus_error */
77 break;
78 case LASI_IAR:
79 val = s->iar;
80 break;
81
82 case LASI_LPT:
83 case LASI_UART:
84 case LASI_LAN:
85 case LASI_LAN + 12:
86 case LASI_FDC:
87 val = 0;
88 break;
89 case LASI_RTC:
90 val = time(NULL);
91 val += s->rtc_ref;
92 break;
93
94 case LASI_PCR:
95 case LASI_VER: /* only version 0 existed. */
96 case LASI_IORESET:
97 val = 0;
98 break;
99 case LASI_ERRLOG:
100 val = s->errlog;
101 break;
102 case LASI_AMR:
103 val = s->amr;
104 break;
105
106 default:
107 /* Controlled by lasi_chip_mem_valid above. */
108 g_assert_not_reached();
109 }
110
111 trace_lasi_chip_read(addr, val);
112
113 *data = val;
114 return ret;
115 }
116
lasi_chip_write_with_attrs(void * opaque,hwaddr addr,uint64_t val,unsigned size,MemTxAttrs attrs)117 static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
118 uint64_t val, unsigned size,
119 MemTxAttrs attrs)
120 {
121 LasiState *s = opaque;
122
123 trace_lasi_chip_write(addr, val);
124
125 switch (addr) {
126 case LASI_IRR:
127 /* read-only. */
128 break;
129 case LASI_IMR:
130 s->imr = val;
131 if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
132 qemu_log_mask(LOG_GUEST_ERROR,
133 "LASI: tried to set invalid %lx IMR value.\n",
134 (unsigned long) val);
135 }
136 break;
137 case LASI_IPR:
138 /* Any write to IPR clears the register. */
139 s->ipr = 0;
140 break;
141 case LASI_ICR:
142 s->icr = val;
143 /* if (val & ICR_TOC_BIT) issue_toc(); */
144 break;
145 case LASI_IAR:
146 s->iar = val;
147 break;
148
149 case LASI_LPT:
150 /* XXX: reset parallel port */
151 break;
152 case LASI_AUDIO:
153 case LASI_AUDIO + 4:
154 /* XXX: reset audio port */
155 break;
156 case LASI_UART:
157 /* XXX: reset serial port */
158 break;
159 case LASI_LAN:
160 /* XXX: reset LAN card */
161 break;
162 case LASI_FDC:
163 /* XXX: reset Floppy controller */
164 break;
165 case LASI_RTC:
166 s->rtc_ref = val - time(NULL);
167 break;
168
169 case LASI_PCR:
170 if (val == 0x02) { /* immediately power off */
171 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
172 }
173 break;
174 case LASI_ERRLOG:
175 s->errlog = val;
176 break;
177 case LASI_VER:
178 /* read-only. */
179 break;
180 case LASI_IORESET:
181 break; /* XXX: TODO: Reset various devices. */
182 case LASI_AMR:
183 s->amr = val;
184 break;
185
186 default:
187 /* Controlled by lasi_chip_mem_valid above. */
188 g_assert_not_reached();
189 }
190 return MEMTX_OK;
191 }
192
193 static const MemoryRegionOps lasi_chip_ops = {
194 .read_with_attrs = lasi_chip_read_with_attrs,
195 .write_with_attrs = lasi_chip_write_with_attrs,
196 .endianness = DEVICE_BIG_ENDIAN,
197 .valid = {
198 .min_access_size = 1,
199 .max_access_size = 4,
200 .accepts = lasi_chip_mem_valid,
201 },
202 .impl = {
203 .min_access_size = 1,
204 .max_access_size = 4,
205 },
206 };
207
208 static const VMStateDescription vmstate_lasi = {
209 .name = "Lasi",
210 .version_id = 2,
211 .minimum_version_id = 1,
212 .fields = (const VMStateField[]) {
213 VMSTATE_UINT32(irr, LasiState),
214 VMSTATE_UINT32(imr, LasiState),
215 VMSTATE_UINT32(ipr, LasiState),
216 VMSTATE_UINT32(icr, LasiState),
217 VMSTATE_UINT32(iar, LasiState),
218 VMSTATE_UINT32(errlog, LasiState),
219 VMSTATE_UINT32(amr, LasiState),
220 VMSTATE_UINT32_V(rtc_ref, LasiState, 2),
221 VMSTATE_END_OF_LIST()
222 }
223 };
224
225
lasi_set_irq(void * opaque,int irq,int level)226 static void lasi_set_irq(void *opaque, int irq, int level)
227 {
228 LasiState *s = opaque;
229 uint32_t bit = 1u << irq;
230
231 if (level) {
232 s->ipr |= bit;
233 if (bit & s->imr) {
234 uint32_t iar = s->iar;
235 s->irr |= bit;
236 if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
237 stl_be_phys(&address_space_memory, iar & -32, iar & 31);
238 }
239 }
240 }
241 }
242
lasi_reset(DeviceState * dev)243 static void lasi_reset(DeviceState *dev)
244 {
245 LasiState *s = LASI_CHIP(dev);
246
247 s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
248
249 /* Real time clock (RTC), it's only one 32-bit counter @9000 */
250 s->rtc_ref = 0;
251 }
252
lasi_init(Object * obj)253 static void lasi_init(Object *obj)
254 {
255 LasiState *s = LASI_CHIP(obj);
256 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
257
258 memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
259 s, "lasi", 0x100000);
260
261 sysbus_init_mmio(sbd, &s->this_mem);
262
263 qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
264 }
265
lasi_class_init(ObjectClass * klass,void * data)266 static void lasi_class_init(ObjectClass *klass, void *data)
267 {
268 DeviceClass *dc = DEVICE_CLASS(klass);
269
270 device_class_set_legacy_reset(dc, lasi_reset);
271 dc->vmsd = &vmstate_lasi;
272 }
273
274 static const TypeInfo lasi_pcihost_info = {
275 .name = TYPE_LASI_CHIP,
276 .parent = TYPE_SYS_BUS_DEVICE,
277 .instance_init = lasi_init,
278 .instance_size = sizeof(LasiState),
279 .class_init = lasi_class_init,
280 };
281
lasi_register_types(void)282 static void lasi_register_types(void)
283 {
284 type_register_static(&lasi_pcihost_info);
285 }
286
287 type_init(lasi_register_types)
288