1 /* 2 * QEMU Sparc SLAVIO aux io port emulation 3 * 4 * Copyright (c) 2005 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "sysemu.h" 26 #include "sysbus.h" 27 #include "trace.h" 28 29 /* 30 * This is the auxio port, chip control and system control part of 31 * chip STP2001 (Slave I/O), also produced as NCR89C105. See 32 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt 33 * 34 * This also includes the PMC CPU idle controller. 35 */ 36 37 typedef struct MiscState { 38 SysBusDevice busdev; 39 qemu_irq irq; 40 qemu_irq fdc_tc; 41 uint32_t dummy; 42 uint8_t config; 43 uint8_t aux1, aux2; 44 uint8_t diag, mctrl; 45 uint8_t sysctrl; 46 uint16_t leds; 47 } MiscState; 48 49 typedef struct APCState { 50 SysBusDevice busdev; 51 qemu_irq cpu_halt; 52 } APCState; 53 54 #define MISC_SIZE 1 55 #define SYSCTRL_SIZE 4 56 57 #define AUX1_TC 0x02 58 59 #define AUX2_PWROFF 0x01 60 #define AUX2_PWRINTCLR 0x02 61 #define AUX2_PWRFAIL 0x20 62 63 #define CFG_PWRINTEN 0x08 64 65 #define SYS_RESET 0x01 66 #define SYS_RESETSTAT 0x02 67 68 static void slavio_misc_update_irq(void *opaque) 69 { 70 MiscState *s = opaque; 71 72 if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) { 73 trace_slavio_misc_update_irq_raise(); 74 qemu_irq_raise(s->irq); 75 } else { 76 trace_slavio_misc_update_irq_lower(); 77 qemu_irq_lower(s->irq); 78 } 79 } 80 81 static void slavio_misc_reset(DeviceState *d) 82 { 83 MiscState *s = container_of(d, MiscState, busdev.qdev); 84 85 // Diagnostic and system control registers not cleared in reset 86 s->config = s->aux1 = s->aux2 = s->mctrl = 0; 87 } 88 89 static void slavio_set_power_fail(void *opaque, int irq, int power_failing) 90 { 91 MiscState *s = opaque; 92 93 trace_slavio_set_power_fail(power_failing, s->config); 94 if (power_failing && (s->config & CFG_PWRINTEN)) { 95 s->aux2 |= AUX2_PWRFAIL; 96 } else { 97 s->aux2 &= ~AUX2_PWRFAIL; 98 } 99 slavio_misc_update_irq(s); 100 } 101 102 static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr, 103 uint32_t val) 104 { 105 MiscState *s = opaque; 106 107 trace_slavio_cfg_mem_writeb(val & 0xff); 108 s->config = val & 0xff; 109 slavio_misc_update_irq(s); 110 } 111 112 static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr) 113 { 114 MiscState *s = opaque; 115 uint32_t ret = 0; 116 117 ret = s->config; 118 trace_slavio_cfg_mem_readb(ret); 119 return ret; 120 } 121 122 static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = { 123 slavio_cfg_mem_readb, 124 NULL, 125 NULL, 126 }; 127 128 static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = { 129 slavio_cfg_mem_writeb, 130 NULL, 131 NULL, 132 }; 133 134 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr, 135 uint32_t val) 136 { 137 MiscState *s = opaque; 138 139 trace_slavio_diag_mem_writeb(val & 0xff); 140 s->diag = val & 0xff; 141 } 142 143 static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr) 144 { 145 MiscState *s = opaque; 146 uint32_t ret = 0; 147 148 ret = s->diag; 149 trace_slavio_diag_mem_readb(ret); 150 return ret; 151 } 152 153 static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = { 154 slavio_diag_mem_readb, 155 NULL, 156 NULL, 157 }; 158 159 static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = { 160 slavio_diag_mem_writeb, 161 NULL, 162 NULL, 163 }; 164 165 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr, 166 uint32_t val) 167 { 168 MiscState *s = opaque; 169 170 trace_slavio_mdm_mem_writeb(val & 0xff); 171 s->mctrl = val & 0xff; 172 } 173 174 static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr) 175 { 176 MiscState *s = opaque; 177 uint32_t ret = 0; 178 179 ret = s->mctrl; 180 trace_slavio_mdm_mem_readb(ret); 181 return ret; 182 } 183 184 static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = { 185 slavio_mdm_mem_readb, 186 NULL, 187 NULL, 188 }; 189 190 static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = { 191 slavio_mdm_mem_writeb, 192 NULL, 193 NULL, 194 }; 195 196 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr, 197 uint32_t val) 198 { 199 MiscState *s = opaque; 200 201 trace_slavio_aux1_mem_writeb(val & 0xff); 202 if (val & AUX1_TC) { 203 // Send a pulse to floppy terminal count line 204 if (s->fdc_tc) { 205 qemu_irq_raise(s->fdc_tc); 206 qemu_irq_lower(s->fdc_tc); 207 } 208 val &= ~AUX1_TC; 209 } 210 s->aux1 = val & 0xff; 211 } 212 213 static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr) 214 { 215 MiscState *s = opaque; 216 uint32_t ret = 0; 217 218 ret = s->aux1; 219 trace_slavio_aux1_mem_readb(ret); 220 return ret; 221 } 222 223 static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = { 224 slavio_aux1_mem_readb, 225 NULL, 226 NULL, 227 }; 228 229 static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = { 230 slavio_aux1_mem_writeb, 231 NULL, 232 NULL, 233 }; 234 235 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr, 236 uint32_t val) 237 { 238 MiscState *s = opaque; 239 240 val &= AUX2_PWRINTCLR | AUX2_PWROFF; 241 trace_slavio_aux2_mem_writeb(val & 0xff); 242 val |= s->aux2 & AUX2_PWRFAIL; 243 if (val & AUX2_PWRINTCLR) // Clear Power Fail int 244 val &= AUX2_PWROFF; 245 s->aux2 = val; 246 if (val & AUX2_PWROFF) 247 qemu_system_shutdown_request(); 248 slavio_misc_update_irq(s); 249 } 250 251 static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr) 252 { 253 MiscState *s = opaque; 254 uint32_t ret = 0; 255 256 ret = s->aux2; 257 trace_slavio_aux2_mem_readb(ret); 258 return ret; 259 } 260 261 static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = { 262 slavio_aux2_mem_readb, 263 NULL, 264 NULL, 265 }; 266 267 static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = { 268 slavio_aux2_mem_writeb, 269 NULL, 270 NULL, 271 }; 272 273 static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) 274 { 275 APCState *s = opaque; 276 277 trace_apc_mem_writeb(val & 0xff); 278 qemu_irq_raise(s->cpu_halt); 279 } 280 281 static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr) 282 { 283 uint32_t ret = 0; 284 285 trace_apc_mem_readb(ret); 286 return ret; 287 } 288 289 static CPUReadMemoryFunc * const apc_mem_read[3] = { 290 apc_mem_readb, 291 NULL, 292 NULL, 293 }; 294 295 static CPUWriteMemoryFunc * const apc_mem_write[3] = { 296 apc_mem_writeb, 297 NULL, 298 NULL, 299 }; 300 301 static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr) 302 { 303 MiscState *s = opaque; 304 uint32_t ret = 0; 305 306 switch (addr) { 307 case 0: 308 ret = s->sysctrl; 309 break; 310 default: 311 break; 312 } 313 trace_slavio_sysctrl_mem_readl(ret); 314 return ret; 315 } 316 317 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr, 318 uint32_t val) 319 { 320 MiscState *s = opaque; 321 322 trace_slavio_sysctrl_mem_writel(val); 323 switch (addr) { 324 case 0: 325 if (val & SYS_RESET) { 326 s->sysctrl = SYS_RESETSTAT; 327 qemu_system_reset_request(); 328 } 329 break; 330 default: 331 break; 332 } 333 } 334 335 static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = { 336 NULL, 337 NULL, 338 slavio_sysctrl_mem_readl, 339 }; 340 341 static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = { 342 NULL, 343 NULL, 344 slavio_sysctrl_mem_writel, 345 }; 346 347 static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr) 348 { 349 MiscState *s = opaque; 350 uint32_t ret = 0; 351 352 switch (addr) { 353 case 0: 354 ret = s->leds; 355 break; 356 default: 357 break; 358 } 359 trace_slavio_led_mem_readw(ret); 360 return ret; 361 } 362 363 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr, 364 uint32_t val) 365 { 366 MiscState *s = opaque; 367 368 trace_slavio_led_mem_readw(val & 0xffff); 369 switch (addr) { 370 case 0: 371 s->leds = val; 372 break; 373 default: 374 break; 375 } 376 } 377 378 static CPUReadMemoryFunc * const slavio_led_mem_read[3] = { 379 NULL, 380 slavio_led_mem_readw, 381 NULL, 382 }; 383 384 static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = { 385 NULL, 386 slavio_led_mem_writew, 387 NULL, 388 }; 389 390 static const VMStateDescription vmstate_misc = { 391 .name ="slavio_misc", 392 .version_id = 1, 393 .minimum_version_id = 1, 394 .minimum_version_id_old = 1, 395 .fields = (VMStateField []) { 396 VMSTATE_UINT32(dummy, MiscState), 397 VMSTATE_UINT8(config, MiscState), 398 VMSTATE_UINT8(aux1, MiscState), 399 VMSTATE_UINT8(aux2, MiscState), 400 VMSTATE_UINT8(diag, MiscState), 401 VMSTATE_UINT8(mctrl, MiscState), 402 VMSTATE_UINT8(sysctrl, MiscState), 403 VMSTATE_END_OF_LIST() 404 } 405 }; 406 407 static int apc_init1(SysBusDevice *dev) 408 { 409 APCState *s = FROM_SYSBUS(APCState, dev); 410 int io; 411 412 sysbus_init_irq(dev, &s->cpu_halt); 413 414 /* Power management (APC) XXX: not a Slavio device */ 415 io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s, 416 DEVICE_NATIVE_ENDIAN); 417 sysbus_init_mmio(dev, MISC_SIZE, io); 418 return 0; 419 } 420 421 static int slavio_misc_init1(SysBusDevice *dev) 422 { 423 MiscState *s = FROM_SYSBUS(MiscState, dev); 424 int io; 425 426 sysbus_init_irq(dev, &s->irq); 427 sysbus_init_irq(dev, &s->fdc_tc); 428 429 /* 8 bit registers */ 430 /* Slavio control */ 431 io = cpu_register_io_memory(slavio_cfg_mem_read, 432 slavio_cfg_mem_write, s, 433 DEVICE_NATIVE_ENDIAN); 434 sysbus_init_mmio(dev, MISC_SIZE, io); 435 436 /* Diagnostics */ 437 io = cpu_register_io_memory(slavio_diag_mem_read, 438 slavio_diag_mem_write, s, 439 DEVICE_NATIVE_ENDIAN); 440 sysbus_init_mmio(dev, MISC_SIZE, io); 441 442 /* Modem control */ 443 io = cpu_register_io_memory(slavio_mdm_mem_read, 444 slavio_mdm_mem_write, s, 445 DEVICE_NATIVE_ENDIAN); 446 sysbus_init_mmio(dev, MISC_SIZE, io); 447 448 /* 16 bit registers */ 449 /* ss600mp diag LEDs */ 450 io = cpu_register_io_memory(slavio_led_mem_read, 451 slavio_led_mem_write, s, 452 DEVICE_NATIVE_ENDIAN); 453 sysbus_init_mmio(dev, MISC_SIZE, io); 454 455 /* 32 bit registers */ 456 /* System control */ 457 io = cpu_register_io_memory(slavio_sysctrl_mem_read, 458 slavio_sysctrl_mem_write, s, 459 DEVICE_NATIVE_ENDIAN); 460 sysbus_init_mmio(dev, SYSCTRL_SIZE, io); 461 462 /* AUX 1 (Misc System Functions) */ 463 io = cpu_register_io_memory(slavio_aux1_mem_read, 464 slavio_aux1_mem_write, s, 465 DEVICE_NATIVE_ENDIAN); 466 sysbus_init_mmio(dev, MISC_SIZE, io); 467 468 /* AUX 2 (Software Powerdown Control) */ 469 io = cpu_register_io_memory(slavio_aux2_mem_read, 470 slavio_aux2_mem_write, s, 471 DEVICE_NATIVE_ENDIAN); 472 sysbus_init_mmio(dev, MISC_SIZE, io); 473 474 qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1); 475 476 return 0; 477 } 478 479 static SysBusDeviceInfo slavio_misc_info = { 480 .init = slavio_misc_init1, 481 .qdev.name = "slavio_misc", 482 .qdev.size = sizeof(MiscState), 483 .qdev.vmsd = &vmstate_misc, 484 .qdev.reset = slavio_misc_reset, 485 }; 486 487 static SysBusDeviceInfo apc_info = { 488 .init = apc_init1, 489 .qdev.name = "apc", 490 .qdev.size = sizeof(MiscState), 491 }; 492 493 static void slavio_misc_register_devices(void) 494 { 495 sysbus_register_withprop(&slavio_misc_info); 496 sysbus_register_withprop(&apc_info); 497 } 498 499 device_init(slavio_misc_register_devices) 500