xref: /qemu/hw/misc/slavio_misc.c (revision f1a0a79f4faeac50ea490496e92d00d7260d9437)
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 
3795eb2084SAndreas Färber #define TYPE_SLAVIO_MISC "slavio_misc"
3895eb2084SAndreas Färber #define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC)
3995eb2084SAndreas Färber 
403475187dSbellard typedef struct MiscState {
4195eb2084SAndreas Färber     SysBusDevice parent_obj;
4295eb2084SAndreas Färber 
43dd703aaeSBenoît Canet     MemoryRegion cfg_iomem;
4496891e59SBenoît Canet     MemoryRegion diag_iomem;
452e66ac3dSBenoît Canet     MemoryRegion mdm_iomem;
46aca23c71SBenoît Canet     MemoryRegion led_iomem;
47cd64a524SBenoît Canet     MemoryRegion sysctrl_iomem;
48cccd43c5SBenoît Canet     MemoryRegion aux1_iomem;
4940ce02fcSBenoît Canet     MemoryRegion aux2_iomem;
50d537cf6cSpbrook     qemu_irq irq;
5197bbb109SBlue Swirl     qemu_irq fdc_tc;
52d37adb09SBlue Swirl     uint32_t dummy;
533475187dSbellard     uint8_t config;
543475187dSbellard     uint8_t aux1, aux2;
55bfa30a38Sblueswir1     uint8_t diag, mctrl;
56d37adb09SBlue Swirl     uint8_t sysctrl;
576a3b9cc9Sblueswir1     uint16_t leds;
583475187dSbellard } MiscState;
593475187dSbellard 
60*f1a0a79fSAndreas Färber #define TYPE_APC "apc"
61*f1a0a79fSAndreas Färber #define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC)
62*f1a0a79fSAndreas Färber 
632582cfa0SBlue Swirl typedef struct APCState {
64*f1a0a79fSAndreas Färber     SysBusDevice parent_obj;
65*f1a0a79fSAndreas Färber 
669c48dee6SBenoît Canet     MemoryRegion iomem;
672582cfa0SBlue Swirl     qemu_irq cpu_halt;
682582cfa0SBlue Swirl } APCState;
692582cfa0SBlue Swirl 
705aca8c3bSblueswir1 #define MISC_SIZE 1
71a8f48dccSblueswir1 #define SYSCTRL_SIZE 4
723475187dSbellard 
732be17ebdSblueswir1 #define AUX1_TC        0x02
742be17ebdSblueswir1 
757debeb82Sblueswir1 #define AUX2_PWROFF    0x01
767debeb82Sblueswir1 #define AUX2_PWRINTCLR 0x02
777debeb82Sblueswir1 #define AUX2_PWRFAIL   0x20
787debeb82Sblueswir1 
797debeb82Sblueswir1 #define CFG_PWRINTEN   0x08
807debeb82Sblueswir1 
817debeb82Sblueswir1 #define SYS_RESET      0x01
827debeb82Sblueswir1 #define SYS_RESETSTAT  0x02
837debeb82Sblueswir1 
843475187dSbellard static void slavio_misc_update_irq(void *opaque)
853475187dSbellard {
863475187dSbellard     MiscState *s = opaque;
873475187dSbellard 
887debeb82Sblueswir1     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
8997bf4851SBlue Swirl         trace_slavio_misc_update_irq_raise();
90d537cf6cSpbrook         qemu_irq_raise(s->irq);
913475187dSbellard     } else {
9297bf4851SBlue Swirl         trace_slavio_misc_update_irq_lower();
93d537cf6cSpbrook         qemu_irq_lower(s->irq);
943475187dSbellard     }
953475187dSbellard }
963475187dSbellard 
971795057aSBlue Swirl static void slavio_misc_reset(DeviceState *d)
983475187dSbellard {
9995eb2084SAndreas Färber     MiscState *s = SLAVIO_MISC(d);
1003475187dSbellard 
1014e3b1ea1Sbellard     // Diagnostic and system control registers not cleared in reset
1023475187dSbellard     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
1033475187dSbellard }
1043475187dSbellard 
105b2b6f6ecSBlue Swirl static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
1063475187dSbellard {
1073475187dSbellard     MiscState *s = opaque;
1083475187dSbellard 
10997bf4851SBlue Swirl     trace_slavio_set_power_fail(power_failing, s->config);
1107debeb82Sblueswir1     if (power_failing && (s->config & CFG_PWRINTEN)) {
1117debeb82Sblueswir1         s->aux2 |= AUX2_PWRFAIL;
1123475187dSbellard     } else {
1137debeb82Sblueswir1         s->aux2 &= ~AUX2_PWRFAIL;
1143475187dSbellard     }
1153475187dSbellard     slavio_misc_update_irq(s);
1163475187dSbellard }
1173475187dSbellard 
118a8170e5eSAvi Kivity static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
119dd703aaeSBenoît Canet                                   uint64_t val, unsigned size)
1203475187dSbellard {
1213475187dSbellard     MiscState *s = opaque;
1223475187dSbellard 
12397bf4851SBlue Swirl     trace_slavio_cfg_mem_writeb(val & 0xff);
1243475187dSbellard     s->config = val & 0xff;
1253475187dSbellard     slavio_misc_update_irq(s);
1263475187dSbellard }
1273475187dSbellard 
128a8170e5eSAvi Kivity static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
129dd703aaeSBenoît Canet                                      unsigned size)
1303475187dSbellard {
1313475187dSbellard     MiscState *s = opaque;
1323475187dSbellard     uint32_t ret = 0;
1333475187dSbellard 
1343475187dSbellard     ret = s->config;
13597bf4851SBlue Swirl     trace_slavio_cfg_mem_readb(ret);
1363475187dSbellard     return ret;
1373475187dSbellard }
1383475187dSbellard 
139dd703aaeSBenoît Canet static const MemoryRegionOps slavio_cfg_mem_ops = {
140dd703aaeSBenoît Canet     .read = slavio_cfg_mem_readb,
141dd703aaeSBenoît Canet     .write = slavio_cfg_mem_writeb,
142dd703aaeSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
143dd703aaeSBenoît Canet     .valid = {
144dd703aaeSBenoît Canet         .min_access_size = 1,
145dd703aaeSBenoît Canet         .max_access_size = 1,
146dd703aaeSBenoît Canet     },
147a8f48dccSblueswir1 };
148a8f48dccSblueswir1 
149a8170e5eSAvi Kivity static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
15096891e59SBenoît Canet                                    uint64_t val, unsigned size)
151a8f48dccSblueswir1 {
152a8f48dccSblueswir1     MiscState *s = opaque;
153a8f48dccSblueswir1 
15497bf4851SBlue Swirl     trace_slavio_diag_mem_writeb(val & 0xff);
155a8f48dccSblueswir1     s->diag = val & 0xff;
156a8f48dccSblueswir1 }
157a8f48dccSblueswir1 
158a8170e5eSAvi Kivity static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
15996891e59SBenoît Canet                                       unsigned size)
160a8f48dccSblueswir1 {
161a8f48dccSblueswir1     MiscState *s = opaque;
162a8f48dccSblueswir1     uint32_t ret = 0;
163a8f48dccSblueswir1 
164a8f48dccSblueswir1     ret = s->diag;
16597bf4851SBlue Swirl     trace_slavio_diag_mem_readb(ret);
166a8f48dccSblueswir1     return ret;
167a8f48dccSblueswir1 }
168a8f48dccSblueswir1 
16996891e59SBenoît Canet static const MemoryRegionOps slavio_diag_mem_ops = {
17096891e59SBenoît Canet     .read = slavio_diag_mem_readb,
17196891e59SBenoît Canet     .write = slavio_diag_mem_writeb,
17296891e59SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
17396891e59SBenoît Canet     .valid = {
17496891e59SBenoît Canet         .min_access_size = 1,
17596891e59SBenoît Canet         .max_access_size = 1,
17696891e59SBenoît Canet     },
177a8f48dccSblueswir1 };
178a8f48dccSblueswir1 
179a8170e5eSAvi Kivity static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
1802e66ac3dSBenoît Canet                                   uint64_t val, unsigned size)
181a8f48dccSblueswir1 {
182a8f48dccSblueswir1     MiscState *s = opaque;
183a8f48dccSblueswir1 
18497bf4851SBlue Swirl     trace_slavio_mdm_mem_writeb(val & 0xff);
185a8f48dccSblueswir1     s->mctrl = val & 0xff;
186a8f48dccSblueswir1 }
187a8f48dccSblueswir1 
188a8170e5eSAvi Kivity static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
1892e66ac3dSBenoît Canet                                      unsigned size)
190a8f48dccSblueswir1 {
191a8f48dccSblueswir1     MiscState *s = opaque;
192a8f48dccSblueswir1     uint32_t ret = 0;
193a8f48dccSblueswir1 
194a8f48dccSblueswir1     ret = s->mctrl;
19597bf4851SBlue Swirl     trace_slavio_mdm_mem_readb(ret);
196a8f48dccSblueswir1     return ret;
197a8f48dccSblueswir1 }
198a8f48dccSblueswir1 
1992e66ac3dSBenoît Canet static const MemoryRegionOps slavio_mdm_mem_ops = {
2002e66ac3dSBenoît Canet     .read = slavio_mdm_mem_readb,
2012e66ac3dSBenoît Canet     .write = slavio_mdm_mem_writeb,
2022e66ac3dSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
2032e66ac3dSBenoît Canet     .valid = {
2042e66ac3dSBenoît Canet         .min_access_size = 1,
2052e66ac3dSBenoît Canet         .max_access_size = 1,
2062e66ac3dSBenoît Canet     },
2073475187dSbellard };
2083475187dSbellard 
209a8170e5eSAvi Kivity static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
210cccd43c5SBenoît Canet                                    uint64_t val, unsigned size)
2110019ad53Sblueswir1 {
2120019ad53Sblueswir1     MiscState *s = opaque;
2130019ad53Sblueswir1 
21497bf4851SBlue Swirl     trace_slavio_aux1_mem_writeb(val & 0xff);
2152be17ebdSblueswir1     if (val & AUX1_TC) {
2162be17ebdSblueswir1         // Send a pulse to floppy terminal count line
2172be17ebdSblueswir1         if (s->fdc_tc) {
2182be17ebdSblueswir1             qemu_irq_raise(s->fdc_tc);
2192be17ebdSblueswir1             qemu_irq_lower(s->fdc_tc);
2202be17ebdSblueswir1         }
2212be17ebdSblueswir1         val &= ~AUX1_TC;
2222be17ebdSblueswir1     }
2230019ad53Sblueswir1     s->aux1 = val & 0xff;
2240019ad53Sblueswir1 }
2250019ad53Sblueswir1 
226a8170e5eSAvi Kivity static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
227cccd43c5SBenoît Canet                                       unsigned size)
2280019ad53Sblueswir1 {
2290019ad53Sblueswir1     MiscState *s = opaque;
2300019ad53Sblueswir1     uint32_t ret = 0;
2310019ad53Sblueswir1 
2320019ad53Sblueswir1     ret = s->aux1;
23397bf4851SBlue Swirl     trace_slavio_aux1_mem_readb(ret);
2340019ad53Sblueswir1     return ret;
2350019ad53Sblueswir1 }
2360019ad53Sblueswir1 
237cccd43c5SBenoît Canet static const MemoryRegionOps slavio_aux1_mem_ops = {
238cccd43c5SBenoît Canet     .read = slavio_aux1_mem_readb,
239cccd43c5SBenoît Canet     .write = slavio_aux1_mem_writeb,
240cccd43c5SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
241cccd43c5SBenoît Canet     .valid = {
242cccd43c5SBenoît Canet         .min_access_size = 1,
243cccd43c5SBenoît Canet         .max_access_size = 1,
244cccd43c5SBenoît Canet     },
2450019ad53Sblueswir1 };
2460019ad53Sblueswir1 
247a8170e5eSAvi Kivity static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
24840ce02fcSBenoît Canet                                    uint64_t val, unsigned size)
2490019ad53Sblueswir1 {
2500019ad53Sblueswir1     MiscState *s = opaque;
2510019ad53Sblueswir1 
2520019ad53Sblueswir1     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
25397bf4851SBlue Swirl     trace_slavio_aux2_mem_writeb(val & 0xff);
2540019ad53Sblueswir1     val |= s->aux2 & AUX2_PWRFAIL;
2550019ad53Sblueswir1     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
2560019ad53Sblueswir1         val &= AUX2_PWROFF;
2570019ad53Sblueswir1     s->aux2 = val;
2580019ad53Sblueswir1     if (val & AUX2_PWROFF)
2590019ad53Sblueswir1         qemu_system_shutdown_request();
2600019ad53Sblueswir1     slavio_misc_update_irq(s);
2610019ad53Sblueswir1 }
2620019ad53Sblueswir1 
263a8170e5eSAvi Kivity static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
26440ce02fcSBenoît Canet                                       unsigned size)
2650019ad53Sblueswir1 {
2660019ad53Sblueswir1     MiscState *s = opaque;
2670019ad53Sblueswir1     uint32_t ret = 0;
2680019ad53Sblueswir1 
2690019ad53Sblueswir1     ret = s->aux2;
27097bf4851SBlue Swirl     trace_slavio_aux2_mem_readb(ret);
2710019ad53Sblueswir1     return ret;
2720019ad53Sblueswir1 }
2730019ad53Sblueswir1 
27440ce02fcSBenoît Canet static const MemoryRegionOps slavio_aux2_mem_ops = {
27540ce02fcSBenoît Canet     .read = slavio_aux2_mem_readb,
27640ce02fcSBenoît Canet     .write = slavio_aux2_mem_writeb,
27740ce02fcSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
27840ce02fcSBenoît Canet     .valid = {
27940ce02fcSBenoît Canet         .min_access_size = 1,
28040ce02fcSBenoît Canet         .max_access_size = 1,
28140ce02fcSBenoît Canet     },
2820019ad53Sblueswir1 };
2830019ad53Sblueswir1 
284a8170e5eSAvi Kivity static void apc_mem_writeb(void *opaque, hwaddr addr,
2859c48dee6SBenoît Canet                            uint64_t val, unsigned size)
2860019ad53Sblueswir1 {
2872582cfa0SBlue Swirl     APCState *s = opaque;
2880019ad53Sblueswir1 
28997bf4851SBlue Swirl     trace_apc_mem_writeb(val & 0xff);
2906d0c293dSblueswir1     qemu_irq_raise(s->cpu_halt);
2910019ad53Sblueswir1 }
2920019ad53Sblueswir1 
293a8170e5eSAvi Kivity static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
2949c48dee6SBenoît Canet                               unsigned size)
2950019ad53Sblueswir1 {
2960019ad53Sblueswir1     uint32_t ret = 0;
2970019ad53Sblueswir1 
29897bf4851SBlue Swirl     trace_apc_mem_readb(ret);
2990019ad53Sblueswir1     return ret;
3000019ad53Sblueswir1 }
3010019ad53Sblueswir1 
3029c48dee6SBenoît Canet static const MemoryRegionOps apc_mem_ops = {
3039c48dee6SBenoît Canet     .read = apc_mem_readb,
3049c48dee6SBenoît Canet     .write = apc_mem_writeb,
3059c48dee6SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
3069c48dee6SBenoît Canet     .valid = {
3079c48dee6SBenoît Canet         .min_access_size = 1,
3089c48dee6SBenoît Canet         .max_access_size = 1,
3099c48dee6SBenoît Canet     }
3100019ad53Sblueswir1 };
3110019ad53Sblueswir1 
312a8170e5eSAvi Kivity static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
313cd64a524SBenoît Canet                                          unsigned size)
314bfa30a38Sblueswir1 {
315bfa30a38Sblueswir1     MiscState *s = opaque;
316a8f48dccSblueswir1     uint32_t ret = 0;
317bfa30a38Sblueswir1 
318a8f48dccSblueswir1     switch (addr) {
319bfa30a38Sblueswir1     case 0:
320bfa30a38Sblueswir1         ret = s->sysctrl;
321bfa30a38Sblueswir1         break;
322bfa30a38Sblueswir1     default:
323bfa30a38Sblueswir1         break;
324bfa30a38Sblueswir1     }
32597bf4851SBlue Swirl     trace_slavio_sysctrl_mem_readl(ret);
326bfa30a38Sblueswir1     return ret;
327bfa30a38Sblueswir1 }
328bfa30a38Sblueswir1 
329a8170e5eSAvi Kivity static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
330cd64a524SBenoît Canet                                       uint64_t val, unsigned size)
331bfa30a38Sblueswir1 {
332bfa30a38Sblueswir1     MiscState *s = opaque;
333bfa30a38Sblueswir1 
33497bf4851SBlue Swirl     trace_slavio_sysctrl_mem_writel(val);
335a8f48dccSblueswir1     switch (addr) {
336bfa30a38Sblueswir1     case 0:
3377debeb82Sblueswir1         if (val & SYS_RESET) {
3387debeb82Sblueswir1             s->sysctrl = SYS_RESETSTAT;
339bfa30a38Sblueswir1             qemu_system_reset_request();
340bfa30a38Sblueswir1         }
341bfa30a38Sblueswir1         break;
342bfa30a38Sblueswir1     default:
343bfa30a38Sblueswir1         break;
344bfa30a38Sblueswir1     }
345bfa30a38Sblueswir1 }
346bfa30a38Sblueswir1 
347cd64a524SBenoît Canet static const MemoryRegionOps slavio_sysctrl_mem_ops = {
348cd64a524SBenoît Canet     .read = slavio_sysctrl_mem_readl,
349cd64a524SBenoît Canet     .write = slavio_sysctrl_mem_writel,
350cd64a524SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
351cd64a524SBenoît Canet     .valid = {
352cd64a524SBenoît Canet         .min_access_size = 4,
353cd64a524SBenoît Canet         .max_access_size = 4,
354cd64a524SBenoît Canet     },
355bfa30a38Sblueswir1 };
356bfa30a38Sblueswir1 
357a8170e5eSAvi Kivity static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
358aca23c71SBenoît Canet                                      unsigned size)
3596a3b9cc9Sblueswir1 {
3606a3b9cc9Sblueswir1     MiscState *s = opaque;
361a8f48dccSblueswir1     uint32_t ret = 0;
3626a3b9cc9Sblueswir1 
363a8f48dccSblueswir1     switch (addr) {
3646a3b9cc9Sblueswir1     case 0:
3656a3b9cc9Sblueswir1         ret = s->leds;
3666a3b9cc9Sblueswir1         break;
3676a3b9cc9Sblueswir1     default:
3686a3b9cc9Sblueswir1         break;
3696a3b9cc9Sblueswir1     }
37097bf4851SBlue Swirl     trace_slavio_led_mem_readw(ret);
3716a3b9cc9Sblueswir1     return ret;
3726a3b9cc9Sblueswir1 }
3736a3b9cc9Sblueswir1 
374a8170e5eSAvi Kivity static void slavio_led_mem_writew(void *opaque, hwaddr addr,
375aca23c71SBenoît Canet                                   uint64_t val, unsigned size)
3766a3b9cc9Sblueswir1 {
3776a3b9cc9Sblueswir1     MiscState *s = opaque;
3786a3b9cc9Sblueswir1 
379f3a64b8cSMarkus Armbruster     trace_slavio_led_mem_writew(val & 0xffff);
380a8f48dccSblueswir1     switch (addr) {
3816a3b9cc9Sblueswir1     case 0:
382d5296cb5Sblueswir1         s->leds = val;
3836a3b9cc9Sblueswir1         break;
3846a3b9cc9Sblueswir1     default:
3856a3b9cc9Sblueswir1         break;
3866a3b9cc9Sblueswir1     }
3876a3b9cc9Sblueswir1 }
3886a3b9cc9Sblueswir1 
389aca23c71SBenoît Canet static const MemoryRegionOps slavio_led_mem_ops = {
390aca23c71SBenoît Canet     .read = slavio_led_mem_readw,
391aca23c71SBenoît Canet     .write = slavio_led_mem_writew,
392aca23c71SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
393aca23c71SBenoît Canet     .valid = {
394aca23c71SBenoît Canet         .min_access_size = 2,
395aca23c71SBenoît Canet         .max_access_size = 2,
396aca23c71SBenoît Canet     },
3976a3b9cc9Sblueswir1 };
3986a3b9cc9Sblueswir1 
399d37adb09SBlue Swirl static const VMStateDescription vmstate_misc = {
400d37adb09SBlue Swirl     .name ="slavio_misc",
401d37adb09SBlue Swirl     .version_id = 1,
402d37adb09SBlue Swirl     .minimum_version_id = 1,
403d37adb09SBlue Swirl     .minimum_version_id_old = 1,
404d37adb09SBlue Swirl     .fields      = (VMStateField []) {
405d37adb09SBlue Swirl         VMSTATE_UINT32(dummy, MiscState),
406d37adb09SBlue Swirl         VMSTATE_UINT8(config, MiscState),
407d37adb09SBlue Swirl         VMSTATE_UINT8(aux1, MiscState),
408d37adb09SBlue Swirl         VMSTATE_UINT8(aux2, MiscState),
409d37adb09SBlue Swirl         VMSTATE_UINT8(diag, MiscState),
410d37adb09SBlue Swirl         VMSTATE_UINT8(mctrl, MiscState),
411d37adb09SBlue Swirl         VMSTATE_UINT8(sysctrl, MiscState),
412d37adb09SBlue Swirl         VMSTATE_END_OF_LIST()
4133475187dSbellard     }
414d37adb09SBlue Swirl };
4153475187dSbellard 
41681a322d4SGerd Hoffmann static int apc_init1(SysBusDevice *dev)
4172582cfa0SBlue Swirl {
418*f1a0a79fSAndreas Färber     APCState *s = APC(dev);
4192582cfa0SBlue Swirl 
4202582cfa0SBlue Swirl     sysbus_init_irq(dev, &s->cpu_halt);
4212582cfa0SBlue Swirl 
4222582cfa0SBlue Swirl     /* Power management (APC) XXX: not a Slavio device */
4233c161542SPaolo Bonzini     memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s,
4249c48dee6SBenoît Canet                           "apc", MISC_SIZE);
425750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->iomem);
42681a322d4SGerd Hoffmann     return 0;
4272582cfa0SBlue Swirl }
4282582cfa0SBlue Swirl 
42995eb2084SAndreas Färber static int slavio_misc_init1(SysBusDevice *sbd)
4302582cfa0SBlue Swirl {
43195eb2084SAndreas Färber     DeviceState *dev = DEVICE(sbd);
43295eb2084SAndreas Färber     MiscState *s = SLAVIO_MISC(dev);
4332582cfa0SBlue Swirl 
43495eb2084SAndreas Färber     sysbus_init_irq(sbd, &s->irq);
43595eb2084SAndreas Färber     sysbus_init_irq(sbd, &s->fdc_tc);
4362582cfa0SBlue Swirl 
4372582cfa0SBlue Swirl     /* 8 bit registers */
4382582cfa0SBlue Swirl     /* Slavio control */
4393c161542SPaolo Bonzini     memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s,
440dd703aaeSBenoît Canet                           "configuration", MISC_SIZE);
44195eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->cfg_iomem);
442a8f48dccSblueswir1 
4432582cfa0SBlue Swirl     /* Diagnostics */
4443c161542SPaolo Bonzini     memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s,
44596891e59SBenoît Canet                           "diagnostic", MISC_SIZE);
44695eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->diag_iomem);
447a8f48dccSblueswir1 
4482582cfa0SBlue Swirl     /* Modem control */
4493c161542SPaolo Bonzini     memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s,
4502e66ac3dSBenoît Canet                           "modem", MISC_SIZE);
45195eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->mdm_iomem);
4523475187dSbellard 
4536a3b9cc9Sblueswir1     /* 16 bit registers */
4542582cfa0SBlue Swirl     /* ss600mp diag LEDs */
4553c161542SPaolo Bonzini     memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s,
456aca23c71SBenoît Canet                           "leds", MISC_SIZE);
45795eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->led_iomem);
4586a3b9cc9Sblueswir1 
459bfa30a38Sblueswir1     /* 32 bit registers */
4602582cfa0SBlue Swirl     /* System control */
4613c161542SPaolo Bonzini     memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s,
462cd64a524SBenoît Canet                           "system-control", MISC_SIZE);
46395eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->sysctrl_iomem);
4640019ad53Sblueswir1 
4652582cfa0SBlue Swirl     /* AUX 1 (Misc System Functions) */
4663c161542SPaolo Bonzini     memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s,
467cccd43c5SBenoît Canet                           "misc-system-functions", MISC_SIZE);
46895eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->aux1_iomem);
4690019ad53Sblueswir1 
4702582cfa0SBlue Swirl     /* AUX 2 (Software Powerdown Control) */
4713c161542SPaolo Bonzini     memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s,
47240ce02fcSBenoît Canet                           "software-powerdown-control", MISC_SIZE);
47395eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->aux2_iomem);
4740019ad53Sblueswir1 
47595eb2084SAndreas Färber     qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
476b2b6f6ecSBlue Swirl 
47781a322d4SGerd Hoffmann     return 0;
4783475187dSbellard }
4792582cfa0SBlue Swirl 
480999e12bbSAnthony Liguori static void slavio_misc_class_init(ObjectClass *klass, void *data)
481999e12bbSAnthony Liguori {
48239bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
483999e12bbSAnthony Liguori     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
484999e12bbSAnthony Liguori 
485999e12bbSAnthony Liguori     k->init = slavio_misc_init1;
48639bffca2SAnthony Liguori     dc->reset = slavio_misc_reset;
48739bffca2SAnthony Liguori     dc->vmsd = &vmstate_misc;
488999e12bbSAnthony Liguori }
489999e12bbSAnthony Liguori 
4908c43a6f0SAndreas Färber static const TypeInfo slavio_misc_info = {
49195eb2084SAndreas Färber     .name          = TYPE_SLAVIO_MISC,
49239bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
49339bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
494999e12bbSAnthony Liguori     .class_init    = slavio_misc_class_init,
4952582cfa0SBlue Swirl };
4962582cfa0SBlue Swirl 
497999e12bbSAnthony Liguori static void apc_class_init(ObjectClass *klass, void *data)
498999e12bbSAnthony Liguori {
499999e12bbSAnthony Liguori     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
500999e12bbSAnthony Liguori 
501999e12bbSAnthony Liguori     k->init = apc_init1;
502999e12bbSAnthony Liguori }
503999e12bbSAnthony Liguori 
5048c43a6f0SAndreas Färber static const TypeInfo apc_info = {
505*f1a0a79fSAndreas Färber     .name          = TYPE_APC,
50639bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
50739bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
508999e12bbSAnthony Liguori     .class_init    = apc_class_init,
5092582cfa0SBlue Swirl };
5102582cfa0SBlue Swirl 
51183f7d43aSAndreas Färber static void slavio_misc_register_types(void)
5122582cfa0SBlue Swirl {
51339bffca2SAnthony Liguori     type_register_static(&slavio_misc_info);
51439bffca2SAnthony Liguori     type_register_static(&apc_info);
5152582cfa0SBlue Swirl }
5162582cfa0SBlue Swirl 
51783f7d43aSAndreas Färber type_init(slavio_misc_register_types)
518