xref: /qemu/hw/misc/slavio_misc.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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 
250d1c9782SPeter Maydell #include "qemu/osdep.h"
2664552b6bSMarkus Armbruster #include "hw/irq.h"
2783c9f4caSPaolo Bonzini #include "hw/sysbus.h"
28d6454270SMarkus Armbruster #include "migration/vmstate.h"
290b8fa32fSMarkus Armbruster #include "qemu/module.h"
3032cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
3197bf4851SBlue Swirl #include "trace.h"
32db1015e9SEduardo Habkost #include "qom/object.h"
333475187dSbellard 
343475187dSbellard /*
353475187dSbellard  * This is the auxio port, chip control and system control part of
363475187dSbellard  * chip STP2001 (Slave I/O), also produced as NCR89C105. See
373475187dSbellard  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
383475187dSbellard  *
393475187dSbellard  * This also includes the PMC CPU idle controller.
403475187dSbellard  */
413475187dSbellard 
4295eb2084SAndreas Färber #define TYPE_SLAVIO_MISC "slavio_misc"
438063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(MiscState, SLAVIO_MISC)
4495eb2084SAndreas Färber 
45db1015e9SEduardo Habkost struct MiscState {
4695eb2084SAndreas Färber     SysBusDevice parent_obj;
4795eb2084SAndreas Färber 
48dd703aaeSBenoît Canet     MemoryRegion cfg_iomem;
4996891e59SBenoît Canet     MemoryRegion diag_iomem;
502e66ac3dSBenoît Canet     MemoryRegion mdm_iomem;
51aca23c71SBenoît Canet     MemoryRegion led_iomem;
52cd64a524SBenoît Canet     MemoryRegion sysctrl_iomem;
53cccd43c5SBenoît Canet     MemoryRegion aux1_iomem;
5440ce02fcSBenoît Canet     MemoryRegion aux2_iomem;
55d537cf6cSpbrook     qemu_irq irq;
5697bbb109SBlue Swirl     qemu_irq fdc_tc;
57d37adb09SBlue Swirl     uint32_t dummy;
583475187dSbellard     uint8_t config;
593475187dSbellard     uint8_t aux1, aux2;
60bfa30a38Sblueswir1     uint8_t diag, mctrl;
61d37adb09SBlue Swirl     uint8_t sysctrl;
626a3b9cc9Sblueswir1     uint16_t leds;
63db1015e9SEduardo Habkost };
643475187dSbellard 
65f1a0a79fSAndreas Färber #define TYPE_APC "apc"
66db1015e9SEduardo Habkost typedef struct APCState APCState;
678110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(APCState, APC,
688110fa1dSEduardo Habkost                          TYPE_APC)
69f1a0a79fSAndreas Färber 
70db1015e9SEduardo Habkost struct APCState {
71f1a0a79fSAndreas Färber     SysBusDevice parent_obj;
72f1a0a79fSAndreas Färber 
739c48dee6SBenoît Canet     MemoryRegion iomem;
742582cfa0SBlue Swirl     qemu_irq cpu_halt;
75db1015e9SEduardo Habkost };
762582cfa0SBlue Swirl 
775aca8c3bSblueswir1 #define MISC_SIZE 1
780e1cd657SMark Cave-Ayland #define LED_SIZE 2
79a8f48dccSblueswir1 #define SYSCTRL_SIZE 4
803475187dSbellard 
812be17ebdSblueswir1 #define AUX1_TC        0x02
822be17ebdSblueswir1 
837debeb82Sblueswir1 #define AUX2_PWROFF    0x01
847debeb82Sblueswir1 #define AUX2_PWRINTCLR 0x02
857debeb82Sblueswir1 #define AUX2_PWRFAIL   0x20
867debeb82Sblueswir1 
877debeb82Sblueswir1 #define CFG_PWRINTEN   0x08
887debeb82Sblueswir1 
897debeb82Sblueswir1 #define SYS_RESET      0x01
907debeb82Sblueswir1 #define SYS_RESETSTAT  0x02
917debeb82Sblueswir1 
slavio_misc_update_irq(void * opaque)923475187dSbellard static void slavio_misc_update_irq(void *opaque)
933475187dSbellard {
943475187dSbellard     MiscState *s = opaque;
953475187dSbellard 
967debeb82Sblueswir1     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
9797bf4851SBlue Swirl         trace_slavio_misc_update_irq_raise();
98d537cf6cSpbrook         qemu_irq_raise(s->irq);
993475187dSbellard     } else {
10097bf4851SBlue Swirl         trace_slavio_misc_update_irq_lower();
101d537cf6cSpbrook         qemu_irq_lower(s->irq);
1023475187dSbellard     }
1033475187dSbellard }
1043475187dSbellard 
slavio_misc_reset(DeviceState * d)1051795057aSBlue Swirl static void slavio_misc_reset(DeviceState *d)
1063475187dSbellard {
10795eb2084SAndreas Färber     MiscState *s = SLAVIO_MISC(d);
1083475187dSbellard 
1094e3b1ea1Sbellard     // Diagnostic and system control registers not cleared in reset
1103475187dSbellard     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
1113475187dSbellard }
1123475187dSbellard 
slavio_set_power_fail(void * opaque,int irq,int power_failing)113b2b6f6ecSBlue Swirl static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
1143475187dSbellard {
1153475187dSbellard     MiscState *s = opaque;
1163475187dSbellard 
11797bf4851SBlue Swirl     trace_slavio_set_power_fail(power_failing, s->config);
1187debeb82Sblueswir1     if (power_failing && (s->config & CFG_PWRINTEN)) {
1197debeb82Sblueswir1         s->aux2 |= AUX2_PWRFAIL;
1203475187dSbellard     } else {
1217debeb82Sblueswir1         s->aux2 &= ~AUX2_PWRFAIL;
1223475187dSbellard     }
1233475187dSbellard     slavio_misc_update_irq(s);
1243475187dSbellard }
1253475187dSbellard 
slavio_cfg_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)126a8170e5eSAvi Kivity static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
127dd703aaeSBenoît Canet                                   uint64_t val, unsigned size)
1283475187dSbellard {
1293475187dSbellard     MiscState *s = opaque;
1303475187dSbellard 
13197bf4851SBlue Swirl     trace_slavio_cfg_mem_writeb(val & 0xff);
1323475187dSbellard     s->config = val & 0xff;
1333475187dSbellard     slavio_misc_update_irq(s);
1343475187dSbellard }
1353475187dSbellard 
slavio_cfg_mem_readb(void * opaque,hwaddr addr,unsigned size)136a8170e5eSAvi Kivity static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
137dd703aaeSBenoît Canet                                      unsigned size)
1383475187dSbellard {
1393475187dSbellard     MiscState *s = opaque;
1403475187dSbellard     uint32_t ret = 0;
1413475187dSbellard 
1423475187dSbellard     ret = s->config;
14397bf4851SBlue Swirl     trace_slavio_cfg_mem_readb(ret);
1443475187dSbellard     return ret;
1453475187dSbellard }
1463475187dSbellard 
147dd703aaeSBenoît Canet static const MemoryRegionOps slavio_cfg_mem_ops = {
148dd703aaeSBenoît Canet     .read = slavio_cfg_mem_readb,
149dd703aaeSBenoît Canet     .write = slavio_cfg_mem_writeb,
150dd703aaeSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
151dd703aaeSBenoît Canet     .valid = {
152dd703aaeSBenoît Canet         .min_access_size = 1,
153dd703aaeSBenoît Canet         .max_access_size = 1,
154dd703aaeSBenoît Canet     },
155a8f48dccSblueswir1 };
156a8f48dccSblueswir1 
slavio_diag_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)157a8170e5eSAvi Kivity static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
15896891e59SBenoît Canet                                    uint64_t val, unsigned size)
159a8f48dccSblueswir1 {
160a8f48dccSblueswir1     MiscState *s = opaque;
161a8f48dccSblueswir1 
16297bf4851SBlue Swirl     trace_slavio_diag_mem_writeb(val & 0xff);
163a8f48dccSblueswir1     s->diag = val & 0xff;
164a8f48dccSblueswir1 }
165a8f48dccSblueswir1 
slavio_diag_mem_readb(void * opaque,hwaddr addr,unsigned size)166a8170e5eSAvi Kivity static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
16796891e59SBenoît Canet                                       unsigned size)
168a8f48dccSblueswir1 {
169a8f48dccSblueswir1     MiscState *s = opaque;
170a8f48dccSblueswir1     uint32_t ret = 0;
171a8f48dccSblueswir1 
172a8f48dccSblueswir1     ret = s->diag;
17397bf4851SBlue Swirl     trace_slavio_diag_mem_readb(ret);
174a8f48dccSblueswir1     return ret;
175a8f48dccSblueswir1 }
176a8f48dccSblueswir1 
17796891e59SBenoît Canet static const MemoryRegionOps slavio_diag_mem_ops = {
17896891e59SBenoît Canet     .read = slavio_diag_mem_readb,
17996891e59SBenoît Canet     .write = slavio_diag_mem_writeb,
18096891e59SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
18196891e59SBenoît Canet     .valid = {
18296891e59SBenoît Canet         .min_access_size = 1,
18396891e59SBenoît Canet         .max_access_size = 1,
18496891e59SBenoît Canet     },
185a8f48dccSblueswir1 };
186a8f48dccSblueswir1 
slavio_mdm_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)187a8170e5eSAvi Kivity static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
1882e66ac3dSBenoît Canet                                   uint64_t val, unsigned size)
189a8f48dccSblueswir1 {
190a8f48dccSblueswir1     MiscState *s = opaque;
191a8f48dccSblueswir1 
19297bf4851SBlue Swirl     trace_slavio_mdm_mem_writeb(val & 0xff);
193a8f48dccSblueswir1     s->mctrl = val & 0xff;
194a8f48dccSblueswir1 }
195a8f48dccSblueswir1 
slavio_mdm_mem_readb(void * opaque,hwaddr addr,unsigned size)196a8170e5eSAvi Kivity static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
1972e66ac3dSBenoît Canet                                      unsigned size)
198a8f48dccSblueswir1 {
199a8f48dccSblueswir1     MiscState *s = opaque;
200a8f48dccSblueswir1     uint32_t ret = 0;
201a8f48dccSblueswir1 
202a8f48dccSblueswir1     ret = s->mctrl;
20397bf4851SBlue Swirl     trace_slavio_mdm_mem_readb(ret);
204a8f48dccSblueswir1     return ret;
205a8f48dccSblueswir1 }
206a8f48dccSblueswir1 
2072e66ac3dSBenoît Canet static const MemoryRegionOps slavio_mdm_mem_ops = {
2082e66ac3dSBenoît Canet     .read = slavio_mdm_mem_readb,
2092e66ac3dSBenoît Canet     .write = slavio_mdm_mem_writeb,
2102e66ac3dSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
2112e66ac3dSBenoît Canet     .valid = {
2122e66ac3dSBenoît Canet         .min_access_size = 1,
2132e66ac3dSBenoît Canet         .max_access_size = 1,
2142e66ac3dSBenoît Canet     },
2153475187dSbellard };
2163475187dSbellard 
slavio_aux1_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)217a8170e5eSAvi Kivity static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
218cccd43c5SBenoît Canet                                    uint64_t val, unsigned size)
2190019ad53Sblueswir1 {
2200019ad53Sblueswir1     MiscState *s = opaque;
2210019ad53Sblueswir1 
22297bf4851SBlue Swirl     trace_slavio_aux1_mem_writeb(val & 0xff);
2232be17ebdSblueswir1     if (val & AUX1_TC) {
2242be17ebdSblueswir1         // Send a pulse to floppy terminal count line
2252be17ebdSblueswir1         if (s->fdc_tc) {
2262be17ebdSblueswir1             qemu_irq_raise(s->fdc_tc);
2272be17ebdSblueswir1             qemu_irq_lower(s->fdc_tc);
2282be17ebdSblueswir1         }
2292be17ebdSblueswir1         val &= ~AUX1_TC;
2302be17ebdSblueswir1     }
2310019ad53Sblueswir1     s->aux1 = val & 0xff;
2320019ad53Sblueswir1 }
2330019ad53Sblueswir1 
slavio_aux1_mem_readb(void * opaque,hwaddr addr,unsigned size)234a8170e5eSAvi Kivity static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
235cccd43c5SBenoît Canet                                       unsigned size)
2360019ad53Sblueswir1 {
2370019ad53Sblueswir1     MiscState *s = opaque;
2380019ad53Sblueswir1     uint32_t ret = 0;
2390019ad53Sblueswir1 
2400019ad53Sblueswir1     ret = s->aux1;
24197bf4851SBlue Swirl     trace_slavio_aux1_mem_readb(ret);
2420019ad53Sblueswir1     return ret;
2430019ad53Sblueswir1 }
2440019ad53Sblueswir1 
245cccd43c5SBenoît Canet static const MemoryRegionOps slavio_aux1_mem_ops = {
246cccd43c5SBenoît Canet     .read = slavio_aux1_mem_readb,
247cccd43c5SBenoît Canet     .write = slavio_aux1_mem_writeb,
248cccd43c5SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
249cccd43c5SBenoît Canet     .valid = {
250cccd43c5SBenoît Canet         .min_access_size = 1,
251cccd43c5SBenoît Canet         .max_access_size = 1,
252cccd43c5SBenoît Canet     },
2530019ad53Sblueswir1 };
2540019ad53Sblueswir1 
slavio_aux2_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)255a8170e5eSAvi Kivity static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
25640ce02fcSBenoît Canet                                    uint64_t val, unsigned size)
2570019ad53Sblueswir1 {
2580019ad53Sblueswir1     MiscState *s = opaque;
2590019ad53Sblueswir1 
2600019ad53Sblueswir1     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
26197bf4851SBlue Swirl     trace_slavio_aux2_mem_writeb(val & 0xff);
2620019ad53Sblueswir1     val |= s->aux2 & AUX2_PWRFAIL;
2630019ad53Sblueswir1     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
2640019ad53Sblueswir1         val &= AUX2_PWROFF;
2650019ad53Sblueswir1     s->aux2 = val;
2660019ad53Sblueswir1     if (val & AUX2_PWROFF)
267cf83f140SEric Blake         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
2680019ad53Sblueswir1     slavio_misc_update_irq(s);
2690019ad53Sblueswir1 }
2700019ad53Sblueswir1 
slavio_aux2_mem_readb(void * opaque,hwaddr addr,unsigned size)271a8170e5eSAvi Kivity static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
27240ce02fcSBenoît Canet                                       unsigned size)
2730019ad53Sblueswir1 {
2740019ad53Sblueswir1     MiscState *s = opaque;
2750019ad53Sblueswir1     uint32_t ret = 0;
2760019ad53Sblueswir1 
2770019ad53Sblueswir1     ret = s->aux2;
27897bf4851SBlue Swirl     trace_slavio_aux2_mem_readb(ret);
2790019ad53Sblueswir1     return ret;
2800019ad53Sblueswir1 }
2810019ad53Sblueswir1 
28240ce02fcSBenoît Canet static const MemoryRegionOps slavio_aux2_mem_ops = {
28340ce02fcSBenoît Canet     .read = slavio_aux2_mem_readb,
28440ce02fcSBenoît Canet     .write = slavio_aux2_mem_writeb,
28540ce02fcSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
28640ce02fcSBenoît Canet     .valid = {
28740ce02fcSBenoît Canet         .min_access_size = 1,
28840ce02fcSBenoît Canet         .max_access_size = 1,
28940ce02fcSBenoît Canet     },
2900019ad53Sblueswir1 };
2910019ad53Sblueswir1 
apc_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)292a8170e5eSAvi Kivity static void apc_mem_writeb(void *opaque, hwaddr addr,
2939c48dee6SBenoît Canet                            uint64_t val, unsigned size)
2940019ad53Sblueswir1 {
2952582cfa0SBlue Swirl     APCState *s = opaque;
2960019ad53Sblueswir1 
29797bf4851SBlue Swirl     trace_apc_mem_writeb(val & 0xff);
2986d0c293dSblueswir1     qemu_irq_raise(s->cpu_halt);
2990019ad53Sblueswir1 }
3000019ad53Sblueswir1 
apc_mem_readb(void * opaque,hwaddr addr,unsigned size)301a8170e5eSAvi Kivity static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
3029c48dee6SBenoît Canet                               unsigned size)
3030019ad53Sblueswir1 {
3040019ad53Sblueswir1     uint32_t ret = 0;
3050019ad53Sblueswir1 
30697bf4851SBlue Swirl     trace_apc_mem_readb(ret);
3070019ad53Sblueswir1     return ret;
3080019ad53Sblueswir1 }
3090019ad53Sblueswir1 
3109c48dee6SBenoît Canet static const MemoryRegionOps apc_mem_ops = {
3119c48dee6SBenoît Canet     .read = apc_mem_readb,
3129c48dee6SBenoît Canet     .write = apc_mem_writeb,
3139c48dee6SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
3149c48dee6SBenoît Canet     .valid = {
3159c48dee6SBenoît Canet         .min_access_size = 1,
3169c48dee6SBenoît Canet         .max_access_size = 1,
3179c48dee6SBenoît Canet     }
3180019ad53Sblueswir1 };
3190019ad53Sblueswir1 
slavio_sysctrl_mem_readl(void * opaque,hwaddr addr,unsigned size)320a8170e5eSAvi Kivity static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
321cd64a524SBenoît Canet                                          unsigned size)
322bfa30a38Sblueswir1 {
323bfa30a38Sblueswir1     MiscState *s = opaque;
324a8f48dccSblueswir1     uint32_t ret = 0;
325bfa30a38Sblueswir1 
326a8f48dccSblueswir1     switch (addr) {
327bfa30a38Sblueswir1     case 0:
328bfa30a38Sblueswir1         ret = s->sysctrl;
329bfa30a38Sblueswir1         break;
330bfa30a38Sblueswir1     default:
331bfa30a38Sblueswir1         break;
332bfa30a38Sblueswir1     }
33397bf4851SBlue Swirl     trace_slavio_sysctrl_mem_readl(ret);
334bfa30a38Sblueswir1     return ret;
335bfa30a38Sblueswir1 }
336bfa30a38Sblueswir1 
slavio_sysctrl_mem_writel(void * opaque,hwaddr addr,uint64_t val,unsigned size)337a8170e5eSAvi Kivity static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
338cd64a524SBenoît Canet                                       uint64_t val, unsigned size)
339bfa30a38Sblueswir1 {
340bfa30a38Sblueswir1     MiscState *s = opaque;
341bfa30a38Sblueswir1 
34297bf4851SBlue Swirl     trace_slavio_sysctrl_mem_writel(val);
343a8f48dccSblueswir1     switch (addr) {
344bfa30a38Sblueswir1     case 0:
3457debeb82Sblueswir1         if (val & SYS_RESET) {
3467debeb82Sblueswir1             s->sysctrl = SYS_RESETSTAT;
347cf83f140SEric Blake             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
348bfa30a38Sblueswir1         }
349bfa30a38Sblueswir1         break;
350bfa30a38Sblueswir1     default:
351bfa30a38Sblueswir1         break;
352bfa30a38Sblueswir1     }
353bfa30a38Sblueswir1 }
354bfa30a38Sblueswir1 
355cd64a524SBenoît Canet static const MemoryRegionOps slavio_sysctrl_mem_ops = {
356cd64a524SBenoît Canet     .read = slavio_sysctrl_mem_readl,
357cd64a524SBenoît Canet     .write = slavio_sysctrl_mem_writel,
358cd64a524SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
359cd64a524SBenoît Canet     .valid = {
360cd64a524SBenoît Canet         .min_access_size = 4,
361cd64a524SBenoît Canet         .max_access_size = 4,
362cd64a524SBenoît Canet     },
363bfa30a38Sblueswir1 };
364bfa30a38Sblueswir1 
slavio_led_mem_readw(void * opaque,hwaddr addr,unsigned size)365a8170e5eSAvi Kivity static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
366aca23c71SBenoît Canet                                      unsigned size)
3676a3b9cc9Sblueswir1 {
3686a3b9cc9Sblueswir1     MiscState *s = opaque;
369a8f48dccSblueswir1     uint32_t ret = 0;
3706a3b9cc9Sblueswir1 
371a8f48dccSblueswir1     switch (addr) {
3726a3b9cc9Sblueswir1     case 0:
3736a3b9cc9Sblueswir1         ret = s->leds;
3746a3b9cc9Sblueswir1         break;
3756a3b9cc9Sblueswir1     default:
3766a3b9cc9Sblueswir1         break;
3776a3b9cc9Sblueswir1     }
37897bf4851SBlue Swirl     trace_slavio_led_mem_readw(ret);
3796a3b9cc9Sblueswir1     return ret;
3806a3b9cc9Sblueswir1 }
3816a3b9cc9Sblueswir1 
slavio_led_mem_writew(void * opaque,hwaddr addr,uint64_t val,unsigned size)382a8170e5eSAvi Kivity static void slavio_led_mem_writew(void *opaque, hwaddr addr,
383aca23c71SBenoît Canet                                   uint64_t val, unsigned size)
3846a3b9cc9Sblueswir1 {
3856a3b9cc9Sblueswir1     MiscState *s = opaque;
3866a3b9cc9Sblueswir1 
387f3a64b8cSMarkus Armbruster     trace_slavio_led_mem_writew(val & 0xffff);
388a8f48dccSblueswir1     switch (addr) {
3896a3b9cc9Sblueswir1     case 0:
390d5296cb5Sblueswir1         s->leds = val;
3916a3b9cc9Sblueswir1         break;
3926a3b9cc9Sblueswir1     default:
3936a3b9cc9Sblueswir1         break;
3946a3b9cc9Sblueswir1     }
3956a3b9cc9Sblueswir1 }
3966a3b9cc9Sblueswir1 
397aca23c71SBenoît Canet static const MemoryRegionOps slavio_led_mem_ops = {
398aca23c71SBenoît Canet     .read = slavio_led_mem_readw,
399aca23c71SBenoît Canet     .write = slavio_led_mem_writew,
400aca23c71SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
401aca23c71SBenoît Canet     .valid = {
402aca23c71SBenoît Canet         .min_access_size = 2,
403aca23c71SBenoît Canet         .max_access_size = 2,
404aca23c71SBenoît Canet     },
4056a3b9cc9Sblueswir1 };
4066a3b9cc9Sblueswir1 
407d37adb09SBlue Swirl static const VMStateDescription vmstate_misc = {
408d37adb09SBlue Swirl     .name ="slavio_misc",
409d37adb09SBlue Swirl     .version_id = 1,
410d37adb09SBlue Swirl     .minimum_version_id = 1,
411e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
412d37adb09SBlue Swirl         VMSTATE_UINT32(dummy, MiscState),
413d37adb09SBlue Swirl         VMSTATE_UINT8(config, MiscState),
414d37adb09SBlue Swirl         VMSTATE_UINT8(aux1, MiscState),
415d37adb09SBlue Swirl         VMSTATE_UINT8(aux2, MiscState),
416d37adb09SBlue Swirl         VMSTATE_UINT8(diag, MiscState),
417d37adb09SBlue Swirl         VMSTATE_UINT8(mctrl, MiscState),
418d37adb09SBlue Swirl         VMSTATE_UINT8(sysctrl, MiscState),
419d37adb09SBlue Swirl         VMSTATE_END_OF_LIST()
4203475187dSbellard     }
421d37adb09SBlue Swirl };
4223475187dSbellard 
apc_init(Object * obj)42346eedc0eSxiaoqiang zhao static void apc_init(Object *obj)
4242582cfa0SBlue Swirl {
42546eedc0eSxiaoqiang zhao     APCState *s = APC(obj);
42646eedc0eSxiaoqiang zhao     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
4272582cfa0SBlue Swirl 
4282582cfa0SBlue Swirl     sysbus_init_irq(dev, &s->cpu_halt);
4292582cfa0SBlue Swirl 
4302582cfa0SBlue Swirl     /* Power management (APC) XXX: not a Slavio device */
43146eedc0eSxiaoqiang zhao     memory_region_init_io(&s->iomem, obj, &apc_mem_ops, s,
4329c48dee6SBenoît Canet                           "apc", MISC_SIZE);
433750ecd44SAvi Kivity     sysbus_init_mmio(dev, &s->iomem);
4342582cfa0SBlue Swirl }
4352582cfa0SBlue Swirl 
slavio_misc_init(Object * obj)43646eedc0eSxiaoqiang zhao static void slavio_misc_init(Object *obj)
4372582cfa0SBlue Swirl {
43846eedc0eSxiaoqiang zhao     DeviceState *dev = DEVICE(obj);
43946eedc0eSxiaoqiang zhao     MiscState *s = SLAVIO_MISC(obj);
44046eedc0eSxiaoqiang zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
4412582cfa0SBlue Swirl 
44295eb2084SAndreas Färber     sysbus_init_irq(sbd, &s->irq);
44395eb2084SAndreas Färber     sysbus_init_irq(sbd, &s->fdc_tc);
4442582cfa0SBlue Swirl 
4452582cfa0SBlue Swirl     /* 8 bit registers */
4462582cfa0SBlue Swirl     /* Slavio control */
44746eedc0eSxiaoqiang zhao     memory_region_init_io(&s->cfg_iomem, obj, &slavio_cfg_mem_ops, s,
448dd703aaeSBenoît Canet                           "configuration", MISC_SIZE);
44995eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->cfg_iomem);
450a8f48dccSblueswir1 
4512582cfa0SBlue Swirl     /* Diagnostics */
45246eedc0eSxiaoqiang zhao     memory_region_init_io(&s->diag_iomem, obj, &slavio_diag_mem_ops, s,
45396891e59SBenoît Canet                           "diagnostic", MISC_SIZE);
45495eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->diag_iomem);
455a8f48dccSblueswir1 
4562582cfa0SBlue Swirl     /* Modem control */
45746eedc0eSxiaoqiang zhao     memory_region_init_io(&s->mdm_iomem, obj, &slavio_mdm_mem_ops, s,
4582e66ac3dSBenoît Canet                           "modem", MISC_SIZE);
45995eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->mdm_iomem);
4603475187dSbellard 
4616a3b9cc9Sblueswir1     /* 16 bit registers */
4622582cfa0SBlue Swirl     /* ss600mp diag LEDs */
46346eedc0eSxiaoqiang zhao     memory_region_init_io(&s->led_iomem, obj, &slavio_led_mem_ops, s,
4640e1cd657SMark Cave-Ayland                           "leds", LED_SIZE);
46595eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->led_iomem);
4666a3b9cc9Sblueswir1 
467bfa30a38Sblueswir1     /* 32 bit registers */
4682582cfa0SBlue Swirl     /* System control */
46946eedc0eSxiaoqiang zhao     memory_region_init_io(&s->sysctrl_iomem, obj, &slavio_sysctrl_mem_ops, s,
4700e1cd657SMark Cave-Ayland                           "system-control", SYSCTRL_SIZE);
47195eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->sysctrl_iomem);
4720019ad53Sblueswir1 
4732582cfa0SBlue Swirl     /* AUX 1 (Misc System Functions) */
47446eedc0eSxiaoqiang zhao     memory_region_init_io(&s->aux1_iomem, obj, &slavio_aux1_mem_ops, s,
475cccd43c5SBenoît Canet                           "misc-system-functions", MISC_SIZE);
47695eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->aux1_iomem);
4770019ad53Sblueswir1 
4782582cfa0SBlue Swirl     /* AUX 2 (Software Powerdown Control) */
47946eedc0eSxiaoqiang zhao     memory_region_init_io(&s->aux2_iomem, obj, &slavio_aux2_mem_ops, s,
48040ce02fcSBenoît Canet                           "software-powerdown-control", MISC_SIZE);
48195eb2084SAndreas Färber     sysbus_init_mmio(sbd, &s->aux2_iomem);
4820019ad53Sblueswir1 
48395eb2084SAndreas Färber     qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
4843475187dSbellard }
4852582cfa0SBlue Swirl 
slavio_misc_class_init(ObjectClass * klass,const void * data)486*12d1a768SPhilippe Mathieu-Daudé static void slavio_misc_class_init(ObjectClass *klass, const void *data)
487999e12bbSAnthony Liguori {
48839bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
489999e12bbSAnthony Liguori 
490e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, slavio_misc_reset);
49139bffca2SAnthony Liguori     dc->vmsd = &vmstate_misc;
492999e12bbSAnthony Liguori }
493999e12bbSAnthony Liguori 
4948c43a6f0SAndreas Färber static const TypeInfo slavio_misc_info = {
49595eb2084SAndreas Färber     .name          = TYPE_SLAVIO_MISC,
49639bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
49739bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
49846eedc0eSxiaoqiang zhao     .instance_init = slavio_misc_init,
499999e12bbSAnthony Liguori     .class_init    = slavio_misc_class_init,
5002582cfa0SBlue Swirl };
5012582cfa0SBlue Swirl 
5028c43a6f0SAndreas Färber static const TypeInfo apc_info = {
503f1a0a79fSAndreas Färber     .name          = TYPE_APC,
50439bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
50539bffca2SAnthony Liguori     .instance_size = sizeof(MiscState),
50646eedc0eSxiaoqiang zhao     .instance_init = apc_init,
5072582cfa0SBlue Swirl };
5082582cfa0SBlue Swirl 
slavio_misc_register_types(void)50983f7d43aSAndreas Färber static void slavio_misc_register_types(void)
5102582cfa0SBlue Swirl {
51139bffca2SAnthony Liguori     type_register_static(&slavio_misc_info);
51239bffca2SAnthony Liguori     type_register_static(&apc_info);
5132582cfa0SBlue Swirl }
5142582cfa0SBlue Swirl 
51583f7d43aSAndreas Färber type_init(slavio_misc_register_types)
516