]> git.proxmox.com Git - qemu.git/blame - hw/misc/slavio_misc.c
s390x: fix flat file load on 32 bit systems
[qemu.git] / hw / misc / slavio_misc.c
CommitLineData
3475187d
FB
1/*
2 * QEMU Sparc SLAVIO aux io port emulation
5fafdf24 3 *
3475187d 4 * Copyright (c) 2005 Fabrice Bellard
5fafdf24 5 *
3475187d
FB
6 * 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 */
2582cfa0 24
9c17d615 25#include "sysemu/sysemu.h"
83c9f4ca 26#include "hw/sysbus.h"
97bf4851 27#include "trace.h"
3475187d
FB
28
29/*
30 * This is the auxio port, chip control and system control part of
31 * chip STP2001 (Slave I/O), also produced as NCR89C105. See
32 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
33 *
34 * This also includes the PMC CPU idle controller.
35 */
36
95eb2084
AF
37#define TYPE_SLAVIO_MISC "slavio_misc"
38#define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC)
39
3475187d 40typedef struct MiscState {
95eb2084
AF
41 SysBusDevice parent_obj;
42
dd703aae 43 MemoryRegion cfg_iomem;
96891e59 44 MemoryRegion diag_iomem;
2e66ac3d 45 MemoryRegion mdm_iomem;
aca23c71 46 MemoryRegion led_iomem;
cd64a524 47 MemoryRegion sysctrl_iomem;
cccd43c5 48 MemoryRegion aux1_iomem;
40ce02fc 49 MemoryRegion aux2_iomem;
d537cf6c 50 qemu_irq irq;
97bbb109 51 qemu_irq fdc_tc;
d37adb09 52 uint32_t dummy;
3475187d
FB
53 uint8_t config;
54 uint8_t aux1, aux2;
bfa30a38 55 uint8_t diag, mctrl;
d37adb09 56 uint8_t sysctrl;
6a3b9cc9 57 uint16_t leds;
3475187d
FB
58} MiscState;
59
f1a0a79f
AF
60#define TYPE_APC "apc"
61#define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC)
62
2582cfa0 63typedef struct APCState {
f1a0a79f
AF
64 SysBusDevice parent_obj;
65
9c48dee6 66 MemoryRegion iomem;
2582cfa0
BS
67 qemu_irq cpu_halt;
68} APCState;
69
5aca8c3b 70#define MISC_SIZE 1
a8f48dcc 71#define SYSCTRL_SIZE 4
3475187d 72
2be17ebd
BS
73#define AUX1_TC 0x02
74
7debeb82
BS
75#define AUX2_PWROFF 0x01
76#define AUX2_PWRINTCLR 0x02
77#define AUX2_PWRFAIL 0x20
78
79#define CFG_PWRINTEN 0x08
80
81#define SYS_RESET 0x01
82#define SYS_RESETSTAT 0x02
83
3475187d
FB
84static void slavio_misc_update_irq(void *opaque)
85{
86 MiscState *s = opaque;
87
7debeb82 88 if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
97bf4851 89 trace_slavio_misc_update_irq_raise();
d537cf6c 90 qemu_irq_raise(s->irq);
3475187d 91 } else {
97bf4851 92 trace_slavio_misc_update_irq_lower();
d537cf6c 93 qemu_irq_lower(s->irq);
3475187d
FB
94 }
95}
96
1795057a 97static void slavio_misc_reset(DeviceState *d)
3475187d 98{
95eb2084 99 MiscState *s = SLAVIO_MISC(d);
3475187d 100
4e3b1ea1 101 // Diagnostic and system control registers not cleared in reset
3475187d
FB
102 s->config = s->aux1 = s->aux2 = s->mctrl = 0;
103}
104
b2b6f6ec 105static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
3475187d
FB
106{
107 MiscState *s = opaque;
108
97bf4851 109 trace_slavio_set_power_fail(power_failing, s->config);
7debeb82
BS
110 if (power_failing && (s->config & CFG_PWRINTEN)) {
111 s->aux2 |= AUX2_PWRFAIL;
3475187d 112 } else {
7debeb82 113 s->aux2 &= ~AUX2_PWRFAIL;
3475187d
FB
114 }
115 slavio_misc_update_irq(s);
116}
117
a8170e5e 118static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
dd703aae 119 uint64_t val, unsigned size)
a8f48dcc
BS
120{
121 MiscState *s = opaque;
122
97bf4851 123 trace_slavio_cfg_mem_writeb(val & 0xff);
a8f48dcc
BS
124 s->config = val & 0xff;
125 slavio_misc_update_irq(s);
126}
127
a8170e5e 128static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
dd703aae 129 unsigned size)
a8f48dcc
BS
130{
131 MiscState *s = opaque;
132 uint32_t ret = 0;
133
134 ret = s->config;
97bf4851 135 trace_slavio_cfg_mem_readb(ret);
a8f48dcc
BS
136 return ret;
137}
138
dd703aae
BC
139static const MemoryRegionOps slavio_cfg_mem_ops = {
140 .read = slavio_cfg_mem_readb,
141 .write = slavio_cfg_mem_writeb,
142 .endianness = DEVICE_NATIVE_ENDIAN,
143 .valid = {
144 .min_access_size = 1,
145 .max_access_size = 1,
146 },
a8f48dcc
BS
147};
148
a8170e5e 149static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
96891e59 150 uint64_t val, unsigned size)
3475187d
FB
151{
152 MiscState *s = opaque;
153
97bf4851 154 trace_slavio_diag_mem_writeb(val & 0xff);
a8f48dcc 155 s->diag = val & 0xff;
3475187d
FB
156}
157
a8170e5e 158static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
96891e59 159 unsigned size)
3475187d
FB
160{
161 MiscState *s = opaque;
162 uint32_t ret = 0;
163
a8f48dcc 164 ret = s->diag;
97bf4851 165 trace_slavio_diag_mem_readb(ret);
a8f48dcc
BS
166 return ret;
167}
168
96891e59
BC
169static const MemoryRegionOps slavio_diag_mem_ops = {
170 .read = slavio_diag_mem_readb,
171 .write = slavio_diag_mem_writeb,
172 .endianness = DEVICE_NATIVE_ENDIAN,
173 .valid = {
174 .min_access_size = 1,
175 .max_access_size = 1,
176 },
a8f48dcc
BS
177};
178
a8170e5e 179static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
2e66ac3d 180 uint64_t val, unsigned size)
a8f48dcc
BS
181{
182 MiscState *s = opaque;
183
97bf4851 184 trace_slavio_mdm_mem_writeb(val & 0xff);
a8f48dcc
BS
185 s->mctrl = val & 0xff;
186}
187
a8170e5e 188static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
2e66ac3d 189 unsigned size)
a8f48dcc
BS
190{
191 MiscState *s = opaque;
192 uint32_t ret = 0;
193
194 ret = s->mctrl;
97bf4851 195 trace_slavio_mdm_mem_readb(ret);
3475187d
FB
196 return ret;
197}
198
2e66ac3d
BC
199static const MemoryRegionOps slavio_mdm_mem_ops = {
200 .read = slavio_mdm_mem_readb,
201 .write = slavio_mdm_mem_writeb,
202 .endianness = DEVICE_NATIVE_ENDIAN,
203 .valid = {
204 .min_access_size = 1,
205 .max_access_size = 1,
206 },
3475187d
FB
207};
208
a8170e5e 209static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
cccd43c5 210 uint64_t val, unsigned size)
0019ad53
BS
211{
212 MiscState *s = opaque;
213
97bf4851 214 trace_slavio_aux1_mem_writeb(val & 0xff);
2be17ebd
BS
215 if (val & AUX1_TC) {
216 // Send a pulse to floppy terminal count line
217 if (s->fdc_tc) {
218 qemu_irq_raise(s->fdc_tc);
219 qemu_irq_lower(s->fdc_tc);
220 }
221 val &= ~AUX1_TC;
222 }
0019ad53
BS
223 s->aux1 = val & 0xff;
224}
225
a8170e5e 226static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
cccd43c5 227 unsigned size)
0019ad53
BS
228{
229 MiscState *s = opaque;
230 uint32_t ret = 0;
231
232 ret = s->aux1;
97bf4851 233 trace_slavio_aux1_mem_readb(ret);
0019ad53
BS
234 return ret;
235}
236
cccd43c5
BC
237static const MemoryRegionOps slavio_aux1_mem_ops = {
238 .read = slavio_aux1_mem_readb,
239 .write = slavio_aux1_mem_writeb,
240 .endianness = DEVICE_NATIVE_ENDIAN,
241 .valid = {
242 .min_access_size = 1,
243 .max_access_size = 1,
244 },
0019ad53
BS
245};
246
a8170e5e 247static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
40ce02fc 248 uint64_t val, unsigned size)
0019ad53
BS
249{
250 MiscState *s = opaque;
251
252 val &= AUX2_PWRINTCLR | AUX2_PWROFF;
97bf4851 253 trace_slavio_aux2_mem_writeb(val & 0xff);
0019ad53
BS
254 val |= s->aux2 & AUX2_PWRFAIL;
255 if (val & AUX2_PWRINTCLR) // Clear Power Fail int
256 val &= AUX2_PWROFF;
257 s->aux2 = val;
258 if (val & AUX2_PWROFF)
259 qemu_system_shutdown_request();
260 slavio_misc_update_irq(s);
261}
262
a8170e5e 263static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
40ce02fc 264 unsigned size)
0019ad53
BS
265{
266 MiscState *s = opaque;
267 uint32_t ret = 0;
268
269 ret = s->aux2;
97bf4851 270 trace_slavio_aux2_mem_readb(ret);
0019ad53
BS
271 return ret;
272}
273
40ce02fc
BC
274static const MemoryRegionOps slavio_aux2_mem_ops = {
275 .read = slavio_aux2_mem_readb,
276 .write = slavio_aux2_mem_writeb,
277 .endianness = DEVICE_NATIVE_ENDIAN,
278 .valid = {
279 .min_access_size = 1,
280 .max_access_size = 1,
281 },
0019ad53
BS
282};
283
a8170e5e 284static void apc_mem_writeb(void *opaque, hwaddr addr,
9c48dee6 285 uint64_t val, unsigned size)
0019ad53 286{
2582cfa0 287 APCState *s = opaque;
0019ad53 288
97bf4851 289 trace_apc_mem_writeb(val & 0xff);
6d0c293d 290 qemu_irq_raise(s->cpu_halt);
0019ad53
BS
291}
292
a8170e5e 293static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
9c48dee6 294 unsigned size)
0019ad53
BS
295{
296 uint32_t ret = 0;
297
97bf4851 298 trace_apc_mem_readb(ret);
0019ad53
BS
299 return ret;
300}
301
9c48dee6
BC
302static const MemoryRegionOps apc_mem_ops = {
303 .read = apc_mem_readb,
304 .write = apc_mem_writeb,
305 .endianness = DEVICE_NATIVE_ENDIAN,
306 .valid = {
307 .min_access_size = 1,
308 .max_access_size = 1,
309 }
0019ad53
BS
310};
311
a8170e5e 312static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
cd64a524 313 unsigned size)
bfa30a38
BS
314{
315 MiscState *s = opaque;
a8f48dcc 316 uint32_t ret = 0;
bfa30a38 317
a8f48dcc 318 switch (addr) {
bfa30a38
BS
319 case 0:
320 ret = s->sysctrl;
321 break;
322 default:
323 break;
324 }
97bf4851 325 trace_slavio_sysctrl_mem_readl(ret);
bfa30a38
BS
326 return ret;
327}
328
a8170e5e 329static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
cd64a524 330 uint64_t val, unsigned size)
bfa30a38
BS
331{
332 MiscState *s = opaque;
bfa30a38 333
97bf4851 334 trace_slavio_sysctrl_mem_writel(val);
a8f48dcc 335 switch (addr) {
bfa30a38 336 case 0:
7debeb82
BS
337 if (val & SYS_RESET) {
338 s->sysctrl = SYS_RESETSTAT;
bfa30a38
BS
339 qemu_system_reset_request();
340 }
341 break;
342 default:
343 break;
344 }
345}
346
cd64a524
BC
347static const MemoryRegionOps slavio_sysctrl_mem_ops = {
348 .read = slavio_sysctrl_mem_readl,
349 .write = slavio_sysctrl_mem_writel,
350 .endianness = DEVICE_NATIVE_ENDIAN,
351 .valid = {
352 .min_access_size = 4,
353 .max_access_size = 4,
354 },
bfa30a38
BS
355};
356
a8170e5e 357static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
aca23c71 358 unsigned size)
6a3b9cc9
BS
359{
360 MiscState *s = opaque;
a8f48dcc 361 uint32_t ret = 0;
6a3b9cc9 362
a8f48dcc 363 switch (addr) {
6a3b9cc9
BS
364 case 0:
365 ret = s->leds;
366 break;
367 default:
368 break;
369 }
97bf4851 370 trace_slavio_led_mem_readw(ret);
6a3b9cc9
BS
371 return ret;
372}
373
a8170e5e 374static void slavio_led_mem_writew(void *opaque, hwaddr addr,
aca23c71 375 uint64_t val, unsigned size)
6a3b9cc9
BS
376{
377 MiscState *s = opaque;
6a3b9cc9 378
f3a64b8c 379 trace_slavio_led_mem_writew(val & 0xffff);
a8f48dcc 380 switch (addr) {
6a3b9cc9 381 case 0:
d5296cb5 382 s->leds = val;
6a3b9cc9
BS
383 break;
384 default:
385 break;
386 }
387}
388
aca23c71
BC
389static const MemoryRegionOps slavio_led_mem_ops = {
390 .read = slavio_led_mem_readw,
391 .write = slavio_led_mem_writew,
392 .endianness = DEVICE_NATIVE_ENDIAN,
393 .valid = {
394 .min_access_size = 2,
395 .max_access_size = 2,
396 },
6a3b9cc9
BS
397};
398
d37adb09
BS
399static const VMStateDescription vmstate_misc = {
400 .name ="slavio_misc",
401 .version_id = 1,
402 .minimum_version_id = 1,
403 .minimum_version_id_old = 1,
404 .fields = (VMStateField []) {
405 VMSTATE_UINT32(dummy, MiscState),
406 VMSTATE_UINT8(config, MiscState),
407 VMSTATE_UINT8(aux1, MiscState),
408 VMSTATE_UINT8(aux2, MiscState),
409 VMSTATE_UINT8(diag, MiscState),
410 VMSTATE_UINT8(mctrl, MiscState),
411 VMSTATE_UINT8(sysctrl, MiscState),
412 VMSTATE_END_OF_LIST()
413 }
414};
3475187d 415
81a322d4 416static int apc_init1(SysBusDevice *dev)
2582cfa0 417{
f1a0a79f 418 APCState *s = APC(dev);
3475187d 419
2582cfa0
BS
420 sysbus_init_irq(dev, &s->cpu_halt);
421
422 /* Power management (APC) XXX: not a Slavio device */
3c161542 423 memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s,
9c48dee6 424 "apc", MISC_SIZE);
750ecd44 425 sysbus_init_mmio(dev, &s->iomem);
81a322d4 426 return 0;
2582cfa0
BS
427}
428
95eb2084 429static int slavio_misc_init1(SysBusDevice *sbd)
2582cfa0 430{
95eb2084
AF
431 DeviceState *dev = DEVICE(sbd);
432 MiscState *s = SLAVIO_MISC(dev);
2582cfa0 433
95eb2084
AF
434 sysbus_init_irq(sbd, &s->irq);
435 sysbus_init_irq(sbd, &s->fdc_tc);
2582cfa0
BS
436
437 /* 8 bit registers */
438 /* Slavio control */
3c161542 439 memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s,
dd703aae 440 "configuration", MISC_SIZE);
95eb2084 441 sysbus_init_mmio(sbd, &s->cfg_iomem);
2582cfa0
BS
442
443 /* Diagnostics */
3c161542 444 memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s,
96891e59 445 "diagnostic", MISC_SIZE);
95eb2084 446 sysbus_init_mmio(sbd, &s->diag_iomem);
2582cfa0
BS
447
448 /* Modem control */
3c161542 449 memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s,
2e66ac3d 450 "modem", MISC_SIZE);
95eb2084 451 sysbus_init_mmio(sbd, &s->mdm_iomem);
2582cfa0
BS
452
453 /* 16 bit registers */
454 /* ss600mp diag LEDs */
3c161542 455 memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s,
aca23c71 456 "leds", MISC_SIZE);
95eb2084 457 sysbus_init_mmio(sbd, &s->led_iomem);
2582cfa0
BS
458
459 /* 32 bit registers */
460 /* System control */
3c161542 461 memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s,
cd64a524 462 "system-control", MISC_SIZE);
95eb2084 463 sysbus_init_mmio(sbd, &s->sysctrl_iomem);
2582cfa0
BS
464
465 /* AUX 1 (Misc System Functions) */
3c161542 466 memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s,
cccd43c5 467 "misc-system-functions", MISC_SIZE);
95eb2084 468 sysbus_init_mmio(sbd, &s->aux1_iomem);
2582cfa0
BS
469
470 /* AUX 2 (Software Powerdown Control) */
3c161542 471 memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s,
40ce02fc 472 "software-powerdown-control", MISC_SIZE);
95eb2084 473 sysbus_init_mmio(sbd, &s->aux2_iomem);
2582cfa0 474
95eb2084 475 qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
b2b6f6ec 476
81a322d4 477 return 0;
2582cfa0 478}
0019ad53 479
999e12bb
AL
480static void slavio_misc_class_init(ObjectClass *klass, void *data)
481{
39bffca2 482 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
483 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
484
485 k->init = slavio_misc_init1;
39bffca2
AL
486 dc->reset = slavio_misc_reset;
487 dc->vmsd = &vmstate_misc;
999e12bb
AL
488}
489
8c43a6f0 490static const TypeInfo slavio_misc_info = {
95eb2084 491 .name = TYPE_SLAVIO_MISC,
39bffca2
AL
492 .parent = TYPE_SYS_BUS_DEVICE,
493 .instance_size = sizeof(MiscState),
494 .class_init = slavio_misc_class_init,
2582cfa0
BS
495};
496
999e12bb
AL
497static void apc_class_init(ObjectClass *klass, void *data)
498{
499 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
500
501 k->init = apc_init1;
502}
503
8c43a6f0 504static const TypeInfo apc_info = {
f1a0a79f 505 .name = TYPE_APC,
39bffca2
AL
506 .parent = TYPE_SYS_BUS_DEVICE,
507 .instance_size = sizeof(MiscState),
508 .class_init = apc_class_init,
2582cfa0
BS
509};
510
83f7d43a 511static void slavio_misc_register_types(void)
2582cfa0 512{
39bffca2
AL
513 type_register_static(&slavio_misc_info);
514 type_register_static(&apc_info);
3475187d 515}
2582cfa0 516
83f7d43a 517type_init(slavio_misc_register_types)