xref: /qemu/hw/misc/slavio_misc.c (revision f3a64b8c89ac9b5111f97e2653d249e4668764b3)
13475187dSbellard /*
23475187dSbellard  * QEMU Sparc SLAVIO aux io port emulation
33475187dSbellard  *
43475187dSbellard  * Copyright (c) 2005 Fabrice Bellard
53475187dSbellard  *
63475187dSbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
73475187dSbellard  * of this software and associated documentation files (the "Software"), to deal
83475187dSbellard  * in the Software without restriction, including without limitation the rights
93475187dSbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
103475187dSbellard  * copies of the Software, and to permit persons to whom the Software is
113475187dSbellard  * furnished to do so, subject to the following conditions:
123475187dSbellard  *
133475187dSbellard  * The above copyright notice and this permission notice shall be included in
143475187dSbellard  * all copies or substantial portions of the Software.
153475187dSbellard  *
163475187dSbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
173475187dSbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183475187dSbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
193475187dSbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
203475187dSbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
213475187dSbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
223475187dSbellard  * THE SOFTWARE.
233475187dSbellard  */
242582cfa0SBlue Swirl 
259c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
2683c9f4caSPaolo Bonzini #include "hw/sysbus.h"
2797bf4851SBlue Swirl #include "trace.h"
283475187dSbellard 
293475187dSbellard /*
303475187dSbellard  * This is the auxio port, chip control and system control part of
313475187dSbellard  * chip STP2001 (Slave I/O), also produced as NCR89C105. See
323475187dSbellard  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
333475187dSbellard  *
343475187dSbellard  * This also includes the PMC CPU idle controller.
353475187dSbellard  */
363475187dSbellard 
373475187dSbellard typedef struct MiscState {
382582cfa0SBlue Swirl     SysBusDevice busdev;
39dd703aaeSBenoît Canet     MemoryRegion cfg_iomem;
4096891e59SBenoît Canet     MemoryRegion diag_iomem;
412e66ac3dSBenoît Canet     MemoryRegion mdm_iomem;
42aca23c71SBenoît Canet     MemoryRegion led_iomem;
43cd64a524SBenoît Canet     MemoryRegion sysctrl_iomem;
44cccd43c5SBenoît Canet     MemoryRegion aux1_iomem;
4540ce02fcSBenoît Canet     MemoryRegion aux2_iomem;
46d537cf6cSpbrook     qemu_irq irq;
4797bbb109SBlue Swirl     qemu_irq fdc_tc;
48d37adb09SBlue Swirl     uint32_t dummy;
493475187dSbellard     uint8_t config;
503475187dSbellard     uint8_t aux1, aux2;
51bfa30a38Sblueswir1     uint8_t diag, mctrl;
52d37adb09SBlue Swirl     uint8_t sysctrl;
536a3b9cc9Sblueswir1     uint16_t leds;
543475187dSbellard } MiscState;
553475187dSbellard 
562582cfa0SBlue Swirl typedef struct APCState {
572582cfa0SBlue Swirl     SysBusDevice busdev;
589c48dee6SBenoît Canet     MemoryRegion iomem;
592582cfa0SBlue Swirl     qemu_irq cpu_halt;
602582cfa0SBlue Swirl } APCState;
612582cfa0SBlue Swirl 
625aca8c3bSblueswir1 #define MISC_SIZE 1
63a8f48dccSblueswir1 #define SYSCTRL_SIZE 4
643475187dSbellard 
652be17ebdSblueswir1 #define AUX1_TC        0x02
662be17ebdSblueswir1 
677debeb82Sblueswir1 #define AUX2_PWROFF    0x01
687debeb82Sblueswir1 #define AUX2_PWRINTCLR 0x02
697debeb82Sblueswir1 #define AUX2_PWRFAIL   0x20
707debeb82Sblueswir1 
717debeb82Sblueswir1 #define CFG_PWRINTEN   0x08
727debeb82Sblueswir1 
737debeb82Sblueswir1 #define SYS_RESET      0x01
747debeb82Sblueswir1 #define SYS_RESETSTAT  0x02
757debeb82Sblueswir1 
763475187dSbellard static void slavio_misc_update_irq(void *opaque)
773475187dSbellard {
783475187dSbellard     MiscState *s = opaque;
793475187dSbellard 
807debeb82Sblueswir1     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
8197bf4851SBlue Swirl         trace_slavio_misc_update_irq_raise();
82d537cf6cSpbrook         qemu_irq_raise(s->irq);
833475187dSbellard     } else {
8497bf4851SBlue Swirl         trace_slavio_misc_update_irq_lower();
85d537cf6cSpbrook         qemu_irq_lower(s->irq);
863475187dSbellard     }
873475187dSbellard }
883475187dSbellard 
891795057aSBlue Swirl static void slavio_misc_reset(DeviceState *d)
903475187dSbellard {
911795057aSBlue Swirl     MiscState *s = container_of(d, MiscState, busdev.qdev);
923475187dSbellard 
934e3b1ea1Sbellard     // Diagnostic and system control registers not cleared in reset
943475187dSbellard     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
953475187dSbellard }
963475187dSbellard 
97b2b6f6ecSBlue Swirl static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
983475187dSbellard {
993475187dSbellard     MiscState *s = opaque;
1003475187dSbellard 
10197bf4851SBlue Swirl     trace_slavio_set_power_fail(power_failing, s->config);
1027debeb82Sblueswir1     if (power_failing && (s->config & CFG_PWRINTEN)) {
1037debeb82Sblueswir1         s->aux2 |= AUX2_PWRFAIL;
1043475187dSbellard     } else {
1057debeb82Sblueswir1         s->aux2 &= ~AUX2_PWRFAIL;
1063475187dSbellard     }
1073475187dSbellard     slavio_misc_update_irq(s);
1083475187dSbellard }
1093475187dSbellard 
110a8170e5eSAvi Kivity static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
111dd703aaeSBenoît Canet                                   uint64_t val, unsigned size)
1123475187dSbellard {
1133475187dSbellard     MiscState *s = opaque;
1143475187dSbellard 
11597bf4851SBlue Swirl     trace_slavio_cfg_mem_writeb(val & 0xff);
1163475187dSbellard     s->config = val & 0xff;
1173475187dSbellard     slavio_misc_update_irq(s);
1183475187dSbellard }
1193475187dSbellard 
120a8170e5eSAvi Kivity static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
121dd703aaeSBenoît Canet                                      unsigned size)
1223475187dSbellard {
1233475187dSbellard     MiscState *s = opaque;
1243475187dSbellard     uint32_t ret = 0;
1253475187dSbellard 
1263475187dSbellard     ret = s->config;
12797bf4851SBlue Swirl     trace_slavio_cfg_mem_readb(ret);
1283475187dSbellard     return ret;
1293475187dSbellard }
1303475187dSbellard 
131dd703aaeSBenoît Canet static const MemoryRegionOps slavio_cfg_mem_ops = {
132dd703aaeSBenoît Canet     .read = slavio_cfg_mem_readb,
133dd703aaeSBenoît Canet     .write = slavio_cfg_mem_writeb,
134dd703aaeSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
135dd703aaeSBenoît Canet     .valid = {
136dd703aaeSBenoît Canet         .min_access_size = 1,
137dd703aaeSBenoît Canet         .max_access_size = 1,
138dd703aaeSBenoît Canet     },
139a8f48dccSblueswir1 };
140a8f48dccSblueswir1 
141a8170e5eSAvi Kivity static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
14296891e59SBenoît Canet                                    uint64_t val, unsigned size)
143a8f48dccSblueswir1 {
144a8f48dccSblueswir1     MiscState *s = opaque;
145a8f48dccSblueswir1 
14697bf4851SBlue Swirl     trace_slavio_diag_mem_writeb(val & 0xff);
147a8f48dccSblueswir1     s->diag = val & 0xff;
148a8f48dccSblueswir1 }
149a8f48dccSblueswir1 
150a8170e5eSAvi Kivity static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
15196891e59SBenoît Canet                                       unsigned size)
152a8f48dccSblueswir1 {
153a8f48dccSblueswir1     MiscState *s = opaque;
154a8f48dccSblueswir1     uint32_t ret = 0;
155a8f48dccSblueswir1 
156a8f48dccSblueswir1     ret = s->diag;
15797bf4851SBlue Swirl     trace_slavio_diag_mem_readb(ret);
158a8f48dccSblueswir1     return ret;
159a8f48dccSblueswir1 }
160a8f48dccSblueswir1 
16196891e59SBenoît Canet static const MemoryRegionOps slavio_diag_mem_ops = {
16296891e59SBenoît Canet     .read = slavio_diag_mem_readb,
16396891e59SBenoît Canet     .write = slavio_diag_mem_writeb,
16496891e59SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
16596891e59SBenoît Canet     .valid = {
16696891e59SBenoît Canet         .min_access_size = 1,
16796891e59SBenoît Canet         .max_access_size = 1,
16896891e59SBenoît Canet     },
169a8f48dccSblueswir1 };
170a8f48dccSblueswir1 
171a8170e5eSAvi Kivity static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
1722e66ac3dSBenoît Canet                                   uint64_t val, unsigned size)
173a8f48dccSblueswir1 {
174a8f48dccSblueswir1     MiscState *s = opaque;
175a8f48dccSblueswir1 
17697bf4851SBlue Swirl     trace_slavio_mdm_mem_writeb(val & 0xff);
177a8f48dccSblueswir1     s->mctrl = val & 0xff;
178a8f48dccSblueswir1 }
179a8f48dccSblueswir1 
180a8170e5eSAvi Kivity static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
1812e66ac3dSBenoît Canet                                      unsigned size)
182a8f48dccSblueswir1 {
183a8f48dccSblueswir1     MiscState *s = opaque;
184a8f48dccSblueswir1     uint32_t ret = 0;
185a8f48dccSblueswir1 
186a8f48dccSblueswir1     ret = s->mctrl;
18797bf4851SBlue Swirl     trace_slavio_mdm_mem_readb(ret);
188a8f48dccSblueswir1     return ret;
189a8f48dccSblueswir1 }
190a8f48dccSblueswir1 
1912e66ac3dSBenoît Canet static const MemoryRegionOps slavio_mdm_mem_ops = {
1922e66ac3dSBenoît Canet     .read = slavio_mdm_mem_readb,
1932e66ac3dSBenoît Canet     .write = slavio_mdm_mem_writeb,
1942e66ac3dSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
1952e66ac3dSBenoît Canet     .valid = {
1962e66ac3dSBenoît Canet         .min_access_size = 1,
1972e66ac3dSBenoît Canet         .max_access_size = 1,
1982e66ac3dSBenoît Canet     },
1993475187dSbellard };
2003475187dSbellard 
201a8170e5eSAvi Kivity static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
202cccd43c5SBenoît Canet                                    uint64_t val, unsigned size)
2030019ad53Sblueswir1 {
2040019ad53Sblueswir1     MiscState *s = opaque;
2050019ad53Sblueswir1 
20697bf4851SBlue Swirl     trace_slavio_aux1_mem_writeb(val & 0xff);
2072be17ebdSblueswir1     if (val & AUX1_TC) {
2082be17ebdSblueswir1         // Send a pulse to floppy terminal count line
2092be17ebdSblueswir1         if (s->fdc_tc) {
2102be17ebdSblueswir1             qemu_irq_raise(s->fdc_tc);
2112be17ebdSblueswir1             qemu_irq_lower(s->fdc_tc);
2122be17ebdSblueswir1         }
2132be17ebdSblueswir1         val &= ~AUX1_TC;
2142be17ebdSblueswir1     }
2150019ad53Sblueswir1     s->aux1 = val & 0xff;
2160019ad53Sblueswir1 }
2170019ad53Sblueswir1 
218a8170e5eSAvi Kivity static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
219cccd43c5SBenoît Canet                                       unsigned size)
2200019ad53Sblueswir1 {
2210019ad53Sblueswir1     MiscState *s = opaque;
2220019ad53Sblueswir1     uint32_t ret = 0;
2230019ad53Sblueswir1 
2240019ad53Sblueswir1     ret = s->aux1;
22597bf4851SBlue Swirl     trace_slavio_aux1_mem_readb(ret);
2260019ad53Sblueswir1     return ret;
2270019ad53Sblueswir1 }
2280019ad53Sblueswir1 
229cccd43c5SBenoît Canet static const MemoryRegionOps slavio_aux1_mem_ops = {
230cccd43c5SBenoît Canet     .read = slavio_aux1_mem_readb,
231cccd43c5SBenoît Canet     .write = slavio_aux1_mem_writeb,
232cccd43c5SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
233cccd43c5SBenoît Canet     .valid = {
234cccd43c5SBenoît Canet         .min_access_size = 1,
235cccd43c5SBenoît Canet         .max_access_size = 1,
236cccd43c5SBenoît Canet     },
2370019ad53Sblueswir1 };
2380019ad53Sblueswir1 
239a8170e5eSAvi Kivity static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
24040ce02fcSBenoît Canet                                    uint64_t val, unsigned size)
2410019ad53Sblueswir1 {
2420019ad53Sblueswir1     MiscState *s = opaque;
2430019ad53Sblueswir1 
2440019ad53Sblueswir1     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
24597bf4851SBlue Swirl     trace_slavio_aux2_mem_writeb(val & 0xff);
2460019ad53Sblueswir1     val |= s->aux2 & AUX2_PWRFAIL;
2470019ad53Sblueswir1     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
2480019ad53Sblueswir1         val &= AUX2_PWROFF;
2490019ad53Sblueswir1     s->aux2 = val;
2500019ad53Sblueswir1     if (val & AUX2_PWROFF)
2510019ad53Sblueswir1         qemu_system_shutdown_request();
2520019ad53Sblueswir1     slavio_misc_update_irq(s);
2530019ad53Sblueswir1 }
2540019ad53Sblueswir1 
255a8170e5eSAvi Kivity static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
25640ce02fcSBenoît Canet                                       unsigned size)
2570019ad53Sblueswir1 {
2580019ad53Sblueswir1     MiscState *s = opaque;
2590019ad53Sblueswir1     uint32_t ret = 0;
2600019ad53Sblueswir1 
2610019ad53Sblueswir1     ret = s->aux2;
26297bf4851SBlue Swirl     trace_slavio_aux2_mem_readb(ret);
2630019ad53Sblueswir1     return ret;
2640019ad53Sblueswir1 }
2650019ad53Sblueswir1 
26640ce02fcSBenoît Canet static const MemoryRegionOps slavio_aux2_mem_ops = {
26740ce02fcSBenoît Canet     .read = slavio_aux2_mem_readb,
26840ce02fcSBenoît Canet     .write = slavio_aux2_mem_writeb,
26940ce02fcSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
27040ce02fcSBenoît Canet     .valid = {
27140ce02fcSBenoît Canet         .min_access_size = 1,
27240ce02fcSBenoît Canet         .max_access_size = 1,
27340ce02fcSBenoît Canet     },
2740019ad53Sblueswir1 };
2750019ad53Sblueswir1 
276a8170e5eSAvi Kivity static void apc_mem_writeb(void *opaque, hwaddr addr,
2779c48dee6SBenoît Canet                            uint64_t val, unsigned size)
2780019ad53Sblueswir1 {
2792582cfa0SBlue Swirl     APCState *s = opaque;
2800019ad53Sblueswir1 
28197bf4851SBlue Swirl     trace_apc_mem_writeb(val & 0xff);
2826d0c293dSblueswir1     qemu_irq_raise(s->cpu_halt);
2830019ad53Sblueswir1 }
2840019ad53Sblueswir1 
285a8170e5eSAvi Kivity static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
2869c48dee6SBenoît Canet                               unsigned size)
2870019ad53Sblueswir1 {
2880019ad53Sblueswir1     uint32_t ret = 0;
2890019ad53Sblueswir1 
29097bf4851SBlue Swirl     trace_apc_mem_readb(ret);
2910019ad53Sblueswir1     return ret;
2920019ad53Sblueswir1 }
2930019ad53Sblueswir1 
2949c48dee6SBenoît Canet static const MemoryRegionOps apc_mem_ops = {
2959c48dee6SBenoît Canet     .read = apc_mem_readb,
2969c48dee6SBenoît Canet     .write = apc_mem_writeb,
2979c48dee6SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
2989c48dee6SBenoît Canet     .valid = {
2999c48dee6SBenoît Canet         .min_access_size = 1,
3009c48dee6SBenoît Canet         .max_access_size = 1,
3019c48dee6SBenoît Canet     }
3020019ad53Sblueswir1 };
3030019ad53Sblueswir1 
304a8170e5eSAvi Kivity static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
305cd64a524SBenoît Canet                                          unsigned size)
306bfa30a38Sblueswir1 {
307bfa30a38Sblueswir1     MiscState *s = opaque;
308a8f48dccSblueswir1     uint32_t ret = 0;
309bfa30a38Sblueswir1 
310a8f48dccSblueswir1     switch (addr) {
311bfa30a38Sblueswir1     case 0:
312bfa30a38Sblueswir1         ret = s->sysctrl;
313bfa30a38Sblueswir1         break;
314bfa30a38Sblueswir1     default:
315bfa30a38Sblueswir1         break;
316bfa30a38Sblueswir1     }
31797bf4851SBlue Swirl     trace_slavio_sysctrl_mem_readl(ret);
318bfa30a38Sblueswir1     return ret;
319bfa30a38Sblueswir1 }
320bfa30a38Sblueswir1 
321a8170e5eSAvi Kivity static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
322cd64a524SBenoît Canet                                       uint64_t val, unsigned size)
323bfa30a38Sblueswir1 {
324bfa30a38Sblueswir1     MiscState *s = opaque;
325bfa30a38Sblueswir1 
32697bf4851SBlue Swirl     trace_slavio_sysctrl_mem_writel(val);
327a8f48dccSblueswir1     switch (addr) {
328bfa30a38Sblueswir1     case 0:
3297debeb82Sblueswir1         if (val & SYS_RESET) {
3307debeb82Sblueswir1             s->sysctrl = SYS_RESETSTAT;
331bfa30a38Sblueswir1             qemu_system_reset_request();
332bfa30a38Sblueswir1         }
333bfa30a38Sblueswir1         break;
334bfa30a38Sblueswir1     default:
335bfa30a38Sblueswir1         break;
336bfa30a38Sblueswir1     }
337bfa30a38Sblueswir1 }
338bfa30a38Sblueswir1 
339cd64a524SBenoît Canet static const MemoryRegionOps slavio_sysctrl_mem_ops = {
340cd64a524SBenoît Canet     .read = slavio_sysctrl_mem_readl,
341cd64a524SBenoît Canet     .write = slavio_sysctrl_mem_writel,
342cd64a524SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
343cd64a524SBenoît Canet     .valid = {
344cd64a524SBenoît Canet         .min_access_size = 4,
345cd64a524SBenoît Canet         .max_access_size = 4,
346cd64a524SBenoît Canet     },
347bfa30a38Sblueswir1 };
348bfa30a38Sblueswir1 
349a8170e5eSAvi Kivity static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
350aca23c71SBenoît Canet                                      unsigned size)
3516a3b9cc9Sblueswir1 {
3526a3b9cc9Sblueswir1     MiscState *s = opaque;
353a8f48dccSblueswir1     uint32_t ret = 0;
3546a3b9cc9Sblueswir1 
355a8f48dccSblueswir1     switch (addr) {
3566a3b9cc9Sblueswir1     case 0:
3576a3b9cc9Sblueswir1         ret = s->leds;
3586a3b9cc9Sblueswir1         break;
3596a3b9cc9Sblueswir1     default:
3606a3b9cc9Sblueswir1         break;
3616a3b9cc9Sblueswir1     }
36297bf4851SBlue Swirl     trace_slavio_led_mem_readw(ret);
3636a3b9cc9Sblueswir1     return ret;
3646a3b9cc9Sblueswir1 }
3656a3b9cc9Sblueswir1 
366a8170e5eSAvi Kivity static void slavio_led_mem_writew(void *opaque, hwaddr addr,
367aca23c71SBenoît Canet                                   uint64_t val, unsigned size)
3686a3b9cc9Sblueswir1 {
3696a3b9cc9Sblueswir1     MiscState *s = opaque;
3706a3b9cc9Sblueswir1 
371*f3a64b8cSMarkus Armbruster     trace_slavio_led_mem_writew(val & 0xffff);
372a8f48dccSblueswir1     switch (addr) {
3736a3b9cc9Sblueswir1     case 0:
374d5296cb5Sblueswir1         s->leds = val;
3756a3b9cc9Sblueswir1         break;
3766a3b9cc9Sblueswir1     default:
3776a3b9cc9Sblueswir1         break;
3786a3b9cc9Sblueswir1     }
3796a3b9cc9Sblueswir1 }
3806a3b9cc9Sblueswir1 
381aca23c71SBenoît Canet static const MemoryRegionOps slavio_led_mem_ops = {
382aca23c71SBenoît Canet     .read = slavio_led_mem_readw,
383aca23c71SBenoît Canet     .write = slavio_led_mem_writew,
384aca23c71SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
385aca23c71SBenoît Canet     .valid = {
386aca23c71SBenoît Canet         .min_access_size = 2,
387aca23c71SBenoît Canet         .max_access_size = 2,
388aca23c71SBenoît Canet     },
3896a3b9cc9Sblueswir1 };
3906a3b9cc9Sblueswir1 
391d37adb09SBlue Swirl static const VMStateDescription vmstate_misc = {
392d37adb09SBlue Swirl     .name ="slavio_misc",
393d37adb09SBlue Swirl     .version_id = 1,
394d37adb09SBlue Swirl     .minimum_version_id = 1,
395d37adb09SBlue Swirl     .minimum_version_id_old = 1,
396d37adb09SBlue Swirl     .fields      = (VMStateField []) {
397d37adb09SBlue Swirl         VMSTATE_UINT32(dummy, MiscState),
398d37adb09SBlue Swirl         VMSTATE_UINT8(config, MiscState),
399d37adb09SBlue Swirl         VMSTATE_UINT8(aux1, MiscState),
400d37adb09SBlue Swirl         VMSTATE_UINT8(aux2, MiscState),
401d37adb09SBlue Swirl         VMSTATE_UINT8(diag, MiscState),
402d37adb09SBlue Swirl         VMSTATE_UINT8(mctrl, MiscState),
403d37adb09SBlue Swirl         VMSTATE_UINT8(sysctrl, MiscState),
404d37adb09SBlue Swirl         VMSTATE_END_OF_LIST()
4053475187dSbellard     }
406d37adb09SBlue Swirl };
4073475187dSbellard 
40881a322d4SGerd Hoffmann static int apc_init1(SysBusDevice *dev)
4092582cfa0SBlue Swirl {
4102582cfa0SBlue Swirl     APCState *s = FROM_SYSBUS(APCState, dev);
4112582cfa0SBlue Swirl 
4122582cfa0SBlue Swirl     sysbus_init_irq(dev, &s->cpu_halt);
4132582cfa0SBlue Swirl 
4142582cfa0SBlue Swirl     /* Power management (APC) XXX: not a Slavio device */
4153c161542SPaolo Bonzini     memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s,
4169c48dee6SBenoît Canet                           "apc", MISC_SIZE);
417750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->iomem);
41881a322d4SGerd Hoffmann     return 0;
4192582cfa0SBlue Swirl }
4202582cfa0SBlue Swirl 
42181a322d4SGerd Hoffmann static int slavio_misc_init1(SysBusDevice *dev)
4222582cfa0SBlue Swirl {
4232582cfa0SBlue Swirl     MiscState *s = FROM_SYSBUS(MiscState, dev);
4242582cfa0SBlue Swirl 
4252582cfa0SBlue Swirl     sysbus_init_irq(dev, &s->irq);
4262582cfa0SBlue Swirl     sysbus_init_irq(dev, &s->fdc_tc);
4272582cfa0SBlue Swirl 
4282582cfa0SBlue Swirl     /* 8 bit registers */
4292582cfa0SBlue Swirl     /* Slavio control */
4303c161542SPaolo Bonzini     memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s,
431dd703aaeSBenoît Canet                           "configuration", MISC_SIZE);
432750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->cfg_iomem);
433a8f48dccSblueswir1 
4342582cfa0SBlue Swirl     /* Diagnostics */
4353c161542SPaolo Bonzini     memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s,
43696891e59SBenoît Canet                           "diagnostic", MISC_SIZE);
437750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->diag_iomem);
438a8f48dccSblueswir1 
4392582cfa0SBlue Swirl     /* Modem control */
4403c161542SPaolo Bonzini     memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s,
4412e66ac3dSBenoît Canet                           "modem", MISC_SIZE);
442750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->mdm_iomem);
4433475187dSbellard 
4446a3b9cc9Sblueswir1     /* 16 bit registers */
4452582cfa0SBlue Swirl     /* ss600mp diag LEDs */
4463c161542SPaolo Bonzini     memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s,
447aca23c71SBenoît Canet                           "leds", MISC_SIZE);
448750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->led_iomem);
4496a3b9cc9Sblueswir1 
450bfa30a38Sblueswir1     /* 32 bit registers */
4512582cfa0SBlue Swirl     /* System control */
4523c161542SPaolo Bonzini     memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s,
453cd64a524SBenoît Canet                           "system-control", MISC_SIZE);
454750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->sysctrl_iomem);
4550019ad53Sblueswir1 
4562582cfa0SBlue Swirl     /* AUX 1 (Misc System Functions) */
4573c161542SPaolo Bonzini     memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s,
458cccd43c5SBenoît Canet                           "misc-system-functions", MISC_SIZE);
459750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->aux1_iomem);
4600019ad53Sblueswir1 
4612582cfa0SBlue Swirl     /* AUX 2 (Software Powerdown Control) */
4623c161542SPaolo Bonzini     memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s,
46340ce02fcSBenoît Canet                           "software-powerdown-control", MISC_SIZE);
464750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->aux2_iomem);
4650019ad53Sblueswir1 
466b2b6f6ecSBlue Swirl     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
467b2b6f6ecSBlue Swirl 
46881a322d4SGerd Hoffmann     return 0;
4693475187dSbellard }
4702582cfa0SBlue Swirl 
471999e12bbSAnthony Liguori static void slavio_misc_class_init(ObjectClass *klass, void *data)
472999e12bbSAnthony Liguori {
47339bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
474999e12bbSAnthony Liguori     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
475999e12bbSAnthony Liguori 
476999e12bbSAnthony Liguori     k->init = slavio_misc_init1;
47739bffca2SAnthony Liguori     dc->reset = slavio_misc_reset;
47839bffca2SAnthony Liguori     dc->vmsd = &vmstate_misc;
479999e12bbSAnthony Liguori }
480999e12bbSAnthony Liguori 
4818c43a6f0SAndreas Färber static const TypeInfo slavio_misc_info = {
482999e12bbSAnthony Liguori     .name          = "slavio_misc",
48339bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
48439bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
485999e12bbSAnthony Liguori     .class_init    = slavio_misc_class_init,
4862582cfa0SBlue Swirl };
4872582cfa0SBlue Swirl 
488999e12bbSAnthony Liguori static void apc_class_init(ObjectClass *klass, void *data)
489999e12bbSAnthony Liguori {
490999e12bbSAnthony Liguori     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
491999e12bbSAnthony Liguori 
492999e12bbSAnthony Liguori     k->init = apc_init1;
493999e12bbSAnthony Liguori }
494999e12bbSAnthony Liguori 
4958c43a6f0SAndreas Färber static const TypeInfo apc_info = {
496999e12bbSAnthony Liguori     .name          = "apc",
49739bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
49839bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
499999e12bbSAnthony Liguori     .class_init    = apc_class_init,
5002582cfa0SBlue Swirl };
5012582cfa0SBlue Swirl 
50283f7d43aSAndreas Färber static void slavio_misc_register_types(void)
5032582cfa0SBlue Swirl {
50439bffca2SAnthony Liguori     type_register_static(&slavio_misc_info);
50539bffca2SAnthony Liguori     type_register_static(&apc_info);
5062582cfa0SBlue Swirl }
5072582cfa0SBlue Swirl 
50883f7d43aSAndreas Färber type_init(slavio_misc_register_types)
509