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" 3054d31236SMarkus Armbruster #include "sysemu/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" 43db1015e9SEduardo Habkost typedef struct MiscState MiscState; 44*8110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(MiscState, SLAVIO_MISC, 45*8110fa1dSEduardo Habkost TYPE_SLAVIO_MISC) 4695eb2084SAndreas Färber 47db1015e9SEduardo Habkost struct MiscState { 4895eb2084SAndreas Färber SysBusDevice parent_obj; 4995eb2084SAndreas Färber 50dd703aaeSBenoît Canet MemoryRegion cfg_iomem; 5196891e59SBenoît Canet MemoryRegion diag_iomem; 522e66ac3dSBenoît Canet MemoryRegion mdm_iomem; 53aca23c71SBenoît Canet MemoryRegion led_iomem; 54cd64a524SBenoît Canet MemoryRegion sysctrl_iomem; 55cccd43c5SBenoît Canet MemoryRegion aux1_iomem; 5640ce02fcSBenoît Canet MemoryRegion aux2_iomem; 57d537cf6cSpbrook qemu_irq irq; 5897bbb109SBlue Swirl qemu_irq fdc_tc; 59d37adb09SBlue Swirl uint32_t dummy; 603475187dSbellard uint8_t config; 613475187dSbellard uint8_t aux1, aux2; 62bfa30a38Sblueswir1 uint8_t diag, mctrl; 63d37adb09SBlue Swirl uint8_t sysctrl; 646a3b9cc9Sblueswir1 uint16_t leds; 65db1015e9SEduardo Habkost }; 663475187dSbellard 67f1a0a79fSAndreas Färber #define TYPE_APC "apc" 68db1015e9SEduardo Habkost typedef struct APCState APCState; 69*8110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(APCState, APC, 70*8110fa1dSEduardo Habkost TYPE_APC) 71f1a0a79fSAndreas Färber 72db1015e9SEduardo Habkost struct APCState { 73f1a0a79fSAndreas Färber SysBusDevice parent_obj; 74f1a0a79fSAndreas Färber 759c48dee6SBenoît Canet MemoryRegion iomem; 762582cfa0SBlue Swirl qemu_irq cpu_halt; 77db1015e9SEduardo Habkost }; 782582cfa0SBlue Swirl 795aca8c3bSblueswir1 #define MISC_SIZE 1 800e1cd657SMark Cave-Ayland #define LED_SIZE 2 81a8f48dccSblueswir1 #define SYSCTRL_SIZE 4 823475187dSbellard 832be17ebdSblueswir1 #define AUX1_TC 0x02 842be17ebdSblueswir1 857debeb82Sblueswir1 #define AUX2_PWROFF 0x01 867debeb82Sblueswir1 #define AUX2_PWRINTCLR 0x02 877debeb82Sblueswir1 #define AUX2_PWRFAIL 0x20 887debeb82Sblueswir1 897debeb82Sblueswir1 #define CFG_PWRINTEN 0x08 907debeb82Sblueswir1 917debeb82Sblueswir1 #define SYS_RESET 0x01 927debeb82Sblueswir1 #define SYS_RESETSTAT 0x02 937debeb82Sblueswir1 943475187dSbellard static void slavio_misc_update_irq(void *opaque) 953475187dSbellard { 963475187dSbellard MiscState *s = opaque; 973475187dSbellard 987debeb82Sblueswir1 if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) { 9997bf4851SBlue Swirl trace_slavio_misc_update_irq_raise(); 100d537cf6cSpbrook qemu_irq_raise(s->irq); 1013475187dSbellard } else { 10297bf4851SBlue Swirl trace_slavio_misc_update_irq_lower(); 103d537cf6cSpbrook qemu_irq_lower(s->irq); 1043475187dSbellard } 1053475187dSbellard } 1063475187dSbellard 1071795057aSBlue Swirl static void slavio_misc_reset(DeviceState *d) 1083475187dSbellard { 10995eb2084SAndreas Färber MiscState *s = SLAVIO_MISC(d); 1103475187dSbellard 1114e3b1ea1Sbellard // Diagnostic and system control registers not cleared in reset 1123475187dSbellard s->config = s->aux1 = s->aux2 = s->mctrl = 0; 1133475187dSbellard } 1143475187dSbellard 115b2b6f6ecSBlue Swirl static void slavio_set_power_fail(void *opaque, int irq, int power_failing) 1163475187dSbellard { 1173475187dSbellard MiscState *s = opaque; 1183475187dSbellard 11997bf4851SBlue Swirl trace_slavio_set_power_fail(power_failing, s->config); 1207debeb82Sblueswir1 if (power_failing && (s->config & CFG_PWRINTEN)) { 1217debeb82Sblueswir1 s->aux2 |= AUX2_PWRFAIL; 1223475187dSbellard } else { 1237debeb82Sblueswir1 s->aux2 &= ~AUX2_PWRFAIL; 1243475187dSbellard } 1253475187dSbellard slavio_misc_update_irq(s); 1263475187dSbellard } 1273475187dSbellard 128a8170e5eSAvi Kivity static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr, 129dd703aaeSBenoît Canet uint64_t val, unsigned size) 1303475187dSbellard { 1313475187dSbellard MiscState *s = opaque; 1323475187dSbellard 13397bf4851SBlue Swirl trace_slavio_cfg_mem_writeb(val & 0xff); 1343475187dSbellard s->config = val & 0xff; 1353475187dSbellard slavio_misc_update_irq(s); 1363475187dSbellard } 1373475187dSbellard 138a8170e5eSAvi Kivity static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr, 139dd703aaeSBenoît Canet unsigned size) 1403475187dSbellard { 1413475187dSbellard MiscState *s = opaque; 1423475187dSbellard uint32_t ret = 0; 1433475187dSbellard 1443475187dSbellard ret = s->config; 14597bf4851SBlue Swirl trace_slavio_cfg_mem_readb(ret); 1463475187dSbellard return ret; 1473475187dSbellard } 1483475187dSbellard 149dd703aaeSBenoît Canet static const MemoryRegionOps slavio_cfg_mem_ops = { 150dd703aaeSBenoît Canet .read = slavio_cfg_mem_readb, 151dd703aaeSBenoît Canet .write = slavio_cfg_mem_writeb, 152dd703aaeSBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 153dd703aaeSBenoît Canet .valid = { 154dd703aaeSBenoît Canet .min_access_size = 1, 155dd703aaeSBenoît Canet .max_access_size = 1, 156dd703aaeSBenoît Canet }, 157a8f48dccSblueswir1 }; 158a8f48dccSblueswir1 159a8170e5eSAvi Kivity static void slavio_diag_mem_writeb(void *opaque, hwaddr addr, 16096891e59SBenoît Canet uint64_t val, unsigned size) 161a8f48dccSblueswir1 { 162a8f48dccSblueswir1 MiscState *s = opaque; 163a8f48dccSblueswir1 16497bf4851SBlue Swirl trace_slavio_diag_mem_writeb(val & 0xff); 165a8f48dccSblueswir1 s->diag = val & 0xff; 166a8f48dccSblueswir1 } 167a8f48dccSblueswir1 168a8170e5eSAvi Kivity static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr, 16996891e59SBenoît Canet unsigned size) 170a8f48dccSblueswir1 { 171a8f48dccSblueswir1 MiscState *s = opaque; 172a8f48dccSblueswir1 uint32_t ret = 0; 173a8f48dccSblueswir1 174a8f48dccSblueswir1 ret = s->diag; 17597bf4851SBlue Swirl trace_slavio_diag_mem_readb(ret); 176a8f48dccSblueswir1 return ret; 177a8f48dccSblueswir1 } 178a8f48dccSblueswir1 17996891e59SBenoît Canet static const MemoryRegionOps slavio_diag_mem_ops = { 18096891e59SBenoît Canet .read = slavio_diag_mem_readb, 18196891e59SBenoît Canet .write = slavio_diag_mem_writeb, 18296891e59SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 18396891e59SBenoît Canet .valid = { 18496891e59SBenoît Canet .min_access_size = 1, 18596891e59SBenoît Canet .max_access_size = 1, 18696891e59SBenoît Canet }, 187a8f48dccSblueswir1 }; 188a8f48dccSblueswir1 189a8170e5eSAvi Kivity static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr, 1902e66ac3dSBenoît Canet uint64_t val, unsigned size) 191a8f48dccSblueswir1 { 192a8f48dccSblueswir1 MiscState *s = opaque; 193a8f48dccSblueswir1 19497bf4851SBlue Swirl trace_slavio_mdm_mem_writeb(val & 0xff); 195a8f48dccSblueswir1 s->mctrl = val & 0xff; 196a8f48dccSblueswir1 } 197a8f48dccSblueswir1 198a8170e5eSAvi Kivity static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr, 1992e66ac3dSBenoît Canet unsigned size) 200a8f48dccSblueswir1 { 201a8f48dccSblueswir1 MiscState *s = opaque; 202a8f48dccSblueswir1 uint32_t ret = 0; 203a8f48dccSblueswir1 204a8f48dccSblueswir1 ret = s->mctrl; 20597bf4851SBlue Swirl trace_slavio_mdm_mem_readb(ret); 206a8f48dccSblueswir1 return ret; 207a8f48dccSblueswir1 } 208a8f48dccSblueswir1 2092e66ac3dSBenoît Canet static const MemoryRegionOps slavio_mdm_mem_ops = { 2102e66ac3dSBenoît Canet .read = slavio_mdm_mem_readb, 2112e66ac3dSBenoît Canet .write = slavio_mdm_mem_writeb, 2122e66ac3dSBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 2132e66ac3dSBenoît Canet .valid = { 2142e66ac3dSBenoît Canet .min_access_size = 1, 2152e66ac3dSBenoît Canet .max_access_size = 1, 2162e66ac3dSBenoît Canet }, 2173475187dSbellard }; 2183475187dSbellard 219a8170e5eSAvi Kivity static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr, 220cccd43c5SBenoît Canet uint64_t val, unsigned size) 2210019ad53Sblueswir1 { 2220019ad53Sblueswir1 MiscState *s = opaque; 2230019ad53Sblueswir1 22497bf4851SBlue Swirl trace_slavio_aux1_mem_writeb(val & 0xff); 2252be17ebdSblueswir1 if (val & AUX1_TC) { 2262be17ebdSblueswir1 // Send a pulse to floppy terminal count line 2272be17ebdSblueswir1 if (s->fdc_tc) { 2282be17ebdSblueswir1 qemu_irq_raise(s->fdc_tc); 2292be17ebdSblueswir1 qemu_irq_lower(s->fdc_tc); 2302be17ebdSblueswir1 } 2312be17ebdSblueswir1 val &= ~AUX1_TC; 2322be17ebdSblueswir1 } 2330019ad53Sblueswir1 s->aux1 = val & 0xff; 2340019ad53Sblueswir1 } 2350019ad53Sblueswir1 236a8170e5eSAvi Kivity static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr, 237cccd43c5SBenoît Canet unsigned size) 2380019ad53Sblueswir1 { 2390019ad53Sblueswir1 MiscState *s = opaque; 2400019ad53Sblueswir1 uint32_t ret = 0; 2410019ad53Sblueswir1 2420019ad53Sblueswir1 ret = s->aux1; 24397bf4851SBlue Swirl trace_slavio_aux1_mem_readb(ret); 2440019ad53Sblueswir1 return ret; 2450019ad53Sblueswir1 } 2460019ad53Sblueswir1 247cccd43c5SBenoît Canet static const MemoryRegionOps slavio_aux1_mem_ops = { 248cccd43c5SBenoît Canet .read = slavio_aux1_mem_readb, 249cccd43c5SBenoît Canet .write = slavio_aux1_mem_writeb, 250cccd43c5SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 251cccd43c5SBenoît Canet .valid = { 252cccd43c5SBenoît Canet .min_access_size = 1, 253cccd43c5SBenoît Canet .max_access_size = 1, 254cccd43c5SBenoît Canet }, 2550019ad53Sblueswir1 }; 2560019ad53Sblueswir1 257a8170e5eSAvi Kivity static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr, 25840ce02fcSBenoît Canet uint64_t val, unsigned size) 2590019ad53Sblueswir1 { 2600019ad53Sblueswir1 MiscState *s = opaque; 2610019ad53Sblueswir1 2620019ad53Sblueswir1 val &= AUX2_PWRINTCLR | AUX2_PWROFF; 26397bf4851SBlue Swirl trace_slavio_aux2_mem_writeb(val & 0xff); 2640019ad53Sblueswir1 val |= s->aux2 & AUX2_PWRFAIL; 2650019ad53Sblueswir1 if (val & AUX2_PWRINTCLR) // Clear Power Fail int 2660019ad53Sblueswir1 val &= AUX2_PWROFF; 2670019ad53Sblueswir1 s->aux2 = val; 2680019ad53Sblueswir1 if (val & AUX2_PWROFF) 269cf83f140SEric Blake qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 2700019ad53Sblueswir1 slavio_misc_update_irq(s); 2710019ad53Sblueswir1 } 2720019ad53Sblueswir1 273a8170e5eSAvi Kivity static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr, 27440ce02fcSBenoît Canet unsigned size) 2750019ad53Sblueswir1 { 2760019ad53Sblueswir1 MiscState *s = opaque; 2770019ad53Sblueswir1 uint32_t ret = 0; 2780019ad53Sblueswir1 2790019ad53Sblueswir1 ret = s->aux2; 28097bf4851SBlue Swirl trace_slavio_aux2_mem_readb(ret); 2810019ad53Sblueswir1 return ret; 2820019ad53Sblueswir1 } 2830019ad53Sblueswir1 28440ce02fcSBenoît Canet static const MemoryRegionOps slavio_aux2_mem_ops = { 28540ce02fcSBenoît Canet .read = slavio_aux2_mem_readb, 28640ce02fcSBenoît Canet .write = slavio_aux2_mem_writeb, 28740ce02fcSBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 28840ce02fcSBenoît Canet .valid = { 28940ce02fcSBenoît Canet .min_access_size = 1, 29040ce02fcSBenoît Canet .max_access_size = 1, 29140ce02fcSBenoît Canet }, 2920019ad53Sblueswir1 }; 2930019ad53Sblueswir1 294a8170e5eSAvi Kivity static void apc_mem_writeb(void *opaque, hwaddr addr, 2959c48dee6SBenoît Canet uint64_t val, unsigned size) 2960019ad53Sblueswir1 { 2972582cfa0SBlue Swirl APCState *s = opaque; 2980019ad53Sblueswir1 29997bf4851SBlue Swirl trace_apc_mem_writeb(val & 0xff); 3006d0c293dSblueswir1 qemu_irq_raise(s->cpu_halt); 3010019ad53Sblueswir1 } 3020019ad53Sblueswir1 303a8170e5eSAvi Kivity static uint64_t apc_mem_readb(void *opaque, hwaddr addr, 3049c48dee6SBenoît Canet unsigned size) 3050019ad53Sblueswir1 { 3060019ad53Sblueswir1 uint32_t ret = 0; 3070019ad53Sblueswir1 30897bf4851SBlue Swirl trace_apc_mem_readb(ret); 3090019ad53Sblueswir1 return ret; 3100019ad53Sblueswir1 } 3110019ad53Sblueswir1 3129c48dee6SBenoît Canet static const MemoryRegionOps apc_mem_ops = { 3139c48dee6SBenoît Canet .read = apc_mem_readb, 3149c48dee6SBenoît Canet .write = apc_mem_writeb, 3159c48dee6SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 3169c48dee6SBenoît Canet .valid = { 3179c48dee6SBenoît Canet .min_access_size = 1, 3189c48dee6SBenoît Canet .max_access_size = 1, 3199c48dee6SBenoît Canet } 3200019ad53Sblueswir1 }; 3210019ad53Sblueswir1 322a8170e5eSAvi Kivity static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr, 323cd64a524SBenoît Canet unsigned size) 324bfa30a38Sblueswir1 { 325bfa30a38Sblueswir1 MiscState *s = opaque; 326a8f48dccSblueswir1 uint32_t ret = 0; 327bfa30a38Sblueswir1 328a8f48dccSblueswir1 switch (addr) { 329bfa30a38Sblueswir1 case 0: 330bfa30a38Sblueswir1 ret = s->sysctrl; 331bfa30a38Sblueswir1 break; 332bfa30a38Sblueswir1 default: 333bfa30a38Sblueswir1 break; 334bfa30a38Sblueswir1 } 33597bf4851SBlue Swirl trace_slavio_sysctrl_mem_readl(ret); 336bfa30a38Sblueswir1 return ret; 337bfa30a38Sblueswir1 } 338bfa30a38Sblueswir1 339a8170e5eSAvi Kivity static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr, 340cd64a524SBenoît Canet uint64_t val, unsigned size) 341bfa30a38Sblueswir1 { 342bfa30a38Sblueswir1 MiscState *s = opaque; 343bfa30a38Sblueswir1 34497bf4851SBlue Swirl trace_slavio_sysctrl_mem_writel(val); 345a8f48dccSblueswir1 switch (addr) { 346bfa30a38Sblueswir1 case 0: 3477debeb82Sblueswir1 if (val & SYS_RESET) { 3487debeb82Sblueswir1 s->sysctrl = SYS_RESETSTAT; 349cf83f140SEric Blake qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 350bfa30a38Sblueswir1 } 351bfa30a38Sblueswir1 break; 352bfa30a38Sblueswir1 default: 353bfa30a38Sblueswir1 break; 354bfa30a38Sblueswir1 } 355bfa30a38Sblueswir1 } 356bfa30a38Sblueswir1 357cd64a524SBenoît Canet static const MemoryRegionOps slavio_sysctrl_mem_ops = { 358cd64a524SBenoît Canet .read = slavio_sysctrl_mem_readl, 359cd64a524SBenoît Canet .write = slavio_sysctrl_mem_writel, 360cd64a524SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 361cd64a524SBenoît Canet .valid = { 362cd64a524SBenoît Canet .min_access_size = 4, 363cd64a524SBenoît Canet .max_access_size = 4, 364cd64a524SBenoît Canet }, 365bfa30a38Sblueswir1 }; 366bfa30a38Sblueswir1 367a8170e5eSAvi Kivity static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr, 368aca23c71SBenoît Canet unsigned size) 3696a3b9cc9Sblueswir1 { 3706a3b9cc9Sblueswir1 MiscState *s = opaque; 371a8f48dccSblueswir1 uint32_t ret = 0; 3726a3b9cc9Sblueswir1 373a8f48dccSblueswir1 switch (addr) { 3746a3b9cc9Sblueswir1 case 0: 3756a3b9cc9Sblueswir1 ret = s->leds; 3766a3b9cc9Sblueswir1 break; 3776a3b9cc9Sblueswir1 default: 3786a3b9cc9Sblueswir1 break; 3796a3b9cc9Sblueswir1 } 38097bf4851SBlue Swirl trace_slavio_led_mem_readw(ret); 3816a3b9cc9Sblueswir1 return ret; 3826a3b9cc9Sblueswir1 } 3836a3b9cc9Sblueswir1 384a8170e5eSAvi Kivity static void slavio_led_mem_writew(void *opaque, hwaddr addr, 385aca23c71SBenoît Canet uint64_t val, unsigned size) 3866a3b9cc9Sblueswir1 { 3876a3b9cc9Sblueswir1 MiscState *s = opaque; 3886a3b9cc9Sblueswir1 389f3a64b8cSMarkus Armbruster trace_slavio_led_mem_writew(val & 0xffff); 390a8f48dccSblueswir1 switch (addr) { 3916a3b9cc9Sblueswir1 case 0: 392d5296cb5Sblueswir1 s->leds = val; 3936a3b9cc9Sblueswir1 break; 3946a3b9cc9Sblueswir1 default: 3956a3b9cc9Sblueswir1 break; 3966a3b9cc9Sblueswir1 } 3976a3b9cc9Sblueswir1 } 3986a3b9cc9Sblueswir1 399aca23c71SBenoît Canet static const MemoryRegionOps slavio_led_mem_ops = { 400aca23c71SBenoît Canet .read = slavio_led_mem_readw, 401aca23c71SBenoît Canet .write = slavio_led_mem_writew, 402aca23c71SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 403aca23c71SBenoît Canet .valid = { 404aca23c71SBenoît Canet .min_access_size = 2, 405aca23c71SBenoît Canet .max_access_size = 2, 406aca23c71SBenoît Canet }, 4076a3b9cc9Sblueswir1 }; 4086a3b9cc9Sblueswir1 409d37adb09SBlue Swirl static const VMStateDescription vmstate_misc = { 410d37adb09SBlue Swirl .name ="slavio_misc", 411d37adb09SBlue Swirl .version_id = 1, 412d37adb09SBlue Swirl .minimum_version_id = 1, 413d37adb09SBlue Swirl .fields = (VMStateField[]) { 414d37adb09SBlue Swirl VMSTATE_UINT32(dummy, MiscState), 415d37adb09SBlue Swirl VMSTATE_UINT8(config, MiscState), 416d37adb09SBlue Swirl VMSTATE_UINT8(aux1, MiscState), 417d37adb09SBlue Swirl VMSTATE_UINT8(aux2, MiscState), 418d37adb09SBlue Swirl VMSTATE_UINT8(diag, MiscState), 419d37adb09SBlue Swirl VMSTATE_UINT8(mctrl, MiscState), 420d37adb09SBlue Swirl VMSTATE_UINT8(sysctrl, MiscState), 421d37adb09SBlue Swirl VMSTATE_END_OF_LIST() 4223475187dSbellard } 423d37adb09SBlue Swirl }; 4243475187dSbellard 42546eedc0eSxiaoqiang zhao static void apc_init(Object *obj) 4262582cfa0SBlue Swirl { 42746eedc0eSxiaoqiang zhao APCState *s = APC(obj); 42846eedc0eSxiaoqiang zhao SysBusDevice *dev = SYS_BUS_DEVICE(obj); 4292582cfa0SBlue Swirl 4302582cfa0SBlue Swirl sysbus_init_irq(dev, &s->cpu_halt); 4312582cfa0SBlue Swirl 4322582cfa0SBlue Swirl /* Power management (APC) XXX: not a Slavio device */ 43346eedc0eSxiaoqiang zhao memory_region_init_io(&s->iomem, obj, &apc_mem_ops, s, 4349c48dee6SBenoît Canet "apc", MISC_SIZE); 435750ecd44SAvi Kivity sysbus_init_mmio(dev, &s->iomem); 4362582cfa0SBlue Swirl } 4372582cfa0SBlue Swirl 43846eedc0eSxiaoqiang zhao static void slavio_misc_init(Object *obj) 4392582cfa0SBlue Swirl { 44046eedc0eSxiaoqiang zhao DeviceState *dev = DEVICE(obj); 44146eedc0eSxiaoqiang zhao MiscState *s = SLAVIO_MISC(obj); 44246eedc0eSxiaoqiang zhao SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 4432582cfa0SBlue Swirl 44495eb2084SAndreas Färber sysbus_init_irq(sbd, &s->irq); 44595eb2084SAndreas Färber sysbus_init_irq(sbd, &s->fdc_tc); 4462582cfa0SBlue Swirl 4472582cfa0SBlue Swirl /* 8 bit registers */ 4482582cfa0SBlue Swirl /* Slavio control */ 44946eedc0eSxiaoqiang zhao memory_region_init_io(&s->cfg_iomem, obj, &slavio_cfg_mem_ops, s, 450dd703aaeSBenoît Canet "configuration", MISC_SIZE); 45195eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->cfg_iomem); 452a8f48dccSblueswir1 4532582cfa0SBlue Swirl /* Diagnostics */ 45446eedc0eSxiaoqiang zhao memory_region_init_io(&s->diag_iomem, obj, &slavio_diag_mem_ops, s, 45596891e59SBenoît Canet "diagnostic", MISC_SIZE); 45695eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->diag_iomem); 457a8f48dccSblueswir1 4582582cfa0SBlue Swirl /* Modem control */ 45946eedc0eSxiaoqiang zhao memory_region_init_io(&s->mdm_iomem, obj, &slavio_mdm_mem_ops, s, 4602e66ac3dSBenoît Canet "modem", MISC_SIZE); 46195eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->mdm_iomem); 4623475187dSbellard 4636a3b9cc9Sblueswir1 /* 16 bit registers */ 4642582cfa0SBlue Swirl /* ss600mp diag LEDs */ 46546eedc0eSxiaoqiang zhao memory_region_init_io(&s->led_iomem, obj, &slavio_led_mem_ops, s, 4660e1cd657SMark Cave-Ayland "leds", LED_SIZE); 46795eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->led_iomem); 4686a3b9cc9Sblueswir1 469bfa30a38Sblueswir1 /* 32 bit registers */ 4702582cfa0SBlue Swirl /* System control */ 47146eedc0eSxiaoqiang zhao memory_region_init_io(&s->sysctrl_iomem, obj, &slavio_sysctrl_mem_ops, s, 4720e1cd657SMark Cave-Ayland "system-control", SYSCTRL_SIZE); 47395eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->sysctrl_iomem); 4740019ad53Sblueswir1 4752582cfa0SBlue Swirl /* AUX 1 (Misc System Functions) */ 47646eedc0eSxiaoqiang zhao memory_region_init_io(&s->aux1_iomem, obj, &slavio_aux1_mem_ops, s, 477cccd43c5SBenoît Canet "misc-system-functions", MISC_SIZE); 47895eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->aux1_iomem); 4790019ad53Sblueswir1 4802582cfa0SBlue Swirl /* AUX 2 (Software Powerdown Control) */ 48146eedc0eSxiaoqiang zhao memory_region_init_io(&s->aux2_iomem, obj, &slavio_aux2_mem_ops, s, 48240ce02fcSBenoît Canet "software-powerdown-control", MISC_SIZE); 48395eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->aux2_iomem); 4840019ad53Sblueswir1 48595eb2084SAndreas Färber qdev_init_gpio_in(dev, slavio_set_power_fail, 1); 4863475187dSbellard } 4872582cfa0SBlue Swirl 488999e12bbSAnthony Liguori static void slavio_misc_class_init(ObjectClass *klass, void *data) 489999e12bbSAnthony Liguori { 49039bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 491999e12bbSAnthony Liguori 49239bffca2SAnthony Liguori dc->reset = slavio_misc_reset; 49339bffca2SAnthony Liguori dc->vmsd = &vmstate_misc; 494999e12bbSAnthony Liguori } 495999e12bbSAnthony Liguori 4968c43a6f0SAndreas Färber static const TypeInfo slavio_misc_info = { 49795eb2084SAndreas Färber .name = TYPE_SLAVIO_MISC, 49839bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 49939bffca2SAnthony Liguori .instance_size = sizeof(MiscState), 50046eedc0eSxiaoqiang zhao .instance_init = slavio_misc_init, 501999e12bbSAnthony Liguori .class_init = slavio_misc_class_init, 5022582cfa0SBlue Swirl }; 5032582cfa0SBlue Swirl 5048c43a6f0SAndreas Färber static const TypeInfo apc_info = { 505f1a0a79fSAndreas Färber .name = TYPE_APC, 50639bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 50739bffca2SAnthony Liguori .instance_size = sizeof(MiscState), 50846eedc0eSxiaoqiang zhao .instance_init = apc_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