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 MemoryRegion iomem; 52 qemu_irq cpu_halt; 53 } APCState; 54 55 #define MISC_SIZE 1 56 #define SYSCTRL_SIZE 4 57 58 #define AUX1_TC 0x02 59 60 #define AUX2_PWROFF 0x01 61 #define AUX2_PWRINTCLR 0x02 62 #define AUX2_PWRFAIL 0x20 63 64 #define CFG_PWRINTEN 0x08 65 66 #define SYS_RESET 0x01 67 #define SYS_RESETSTAT 0x02 68 69 static void slavio_misc_update_irq(void *opaque) 70 { 71 MiscState *s = opaque; 72 73 if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) { 74 trace_slavio_misc_update_irq_raise(); 75 qemu_irq_raise(s->irq); 76 } else { 77 trace_slavio_misc_update_irq_lower(); 78 qemu_irq_lower(s->irq); 79 } 80 } 81 82 static void slavio_misc_reset(DeviceState *d) 83 { 84 MiscState *s = container_of(d, MiscState, busdev.qdev); 85 86 // Diagnostic and system control registers not cleared in reset 87 s->config = s->aux1 = s->aux2 = s->mctrl = 0; 88 } 89 90 static void slavio_set_power_fail(void *opaque, int irq, int power_failing) 91 { 92 MiscState *s = opaque; 93 94 trace_slavio_set_power_fail(power_failing, s->config); 95 if (power_failing && (s->config & CFG_PWRINTEN)) { 96 s->aux2 |= AUX2_PWRFAIL; 97 } else { 98 s->aux2 &= ~AUX2_PWRFAIL; 99 } 100 slavio_misc_update_irq(s); 101 } 102 103 static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr, 104 uint32_t val) 105 { 106 MiscState *s = opaque; 107 108 trace_slavio_cfg_mem_writeb(val & 0xff); 109 s->config = val & 0xff; 110 slavio_misc_update_irq(s); 111 } 112 113 static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr) 114 { 115 MiscState *s = opaque; 116 uint32_t ret = 0; 117 118 ret = s->config; 119 trace_slavio_cfg_mem_readb(ret); 120 return ret; 121 } 122 123 static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = { 124 slavio_cfg_mem_readb, 125 NULL, 126 NULL, 127 }; 128 129 static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = { 130 slavio_cfg_mem_writeb, 131 NULL, 132 NULL, 133 }; 134 135 static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr, 136 uint32_t val) 137 { 138 MiscState *s = opaque; 139 140 trace_slavio_diag_mem_writeb(val & 0xff); 141 s->diag = val & 0xff; 142 } 143 144 static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr) 145 { 146 MiscState *s = opaque; 147 uint32_t ret = 0; 148 149 ret = s->diag; 150 trace_slavio_diag_mem_readb(ret); 151 return ret; 152 } 153 154 static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = { 155 slavio_diag_mem_readb, 156 NULL, 157 NULL, 158 }; 159 160 static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = { 161 slavio_diag_mem_writeb, 162 NULL, 163 NULL, 164 }; 165 166 static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr, 167 uint32_t val) 168 { 169 MiscState *s = opaque; 170 171 trace_slavio_mdm_mem_writeb(val & 0xff); 172 s->mctrl = val & 0xff; 173 } 174 175 static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr) 176 { 177 MiscState *s = opaque; 178 uint32_t ret = 0; 179 180 ret = s->mctrl; 181 trace_slavio_mdm_mem_readb(ret); 182 return ret; 183 } 184 185 static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = { 186 slavio_mdm_mem_readb, 187 NULL, 188 NULL, 189 }; 190 191 static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = { 192 slavio_mdm_mem_writeb, 193 NULL, 194 NULL, 195 }; 196 197 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr, 198 uint32_t val) 199 { 200 MiscState *s = opaque; 201 202 trace_slavio_aux1_mem_writeb(val & 0xff); 203 if (val & AUX1_TC) { 204 // Send a pulse to floppy terminal count line 205 if (s->fdc_tc) { 206 qemu_irq_raise(s->fdc_tc); 207 qemu_irq_lower(s->fdc_tc); 208 } 209 val &= ~AUX1_TC; 210 } 211 s->aux1 = val & 0xff; 212 } 213 214 static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr) 215 { 216 MiscState *s = opaque; 217 uint32_t ret = 0; 218 219 ret = s->aux1; 220 trace_slavio_aux1_mem_readb(ret); 221 return ret; 222 } 223 224 static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = { 225 slavio_aux1_mem_readb, 226 NULL, 227 NULL, 228 }; 229 230 static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = { 231 slavio_aux1_mem_writeb, 232 NULL, 233 NULL, 234 }; 235 236 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr, 237 uint32_t val) 238 { 239 MiscState *s = opaque; 240 241 val &= AUX2_PWRINTCLR | AUX2_PWROFF; 242 trace_slavio_aux2_mem_writeb(val & 0xff); 243 val |= s->aux2 & AUX2_PWRFAIL; 244 if (val & AUX2_PWRINTCLR) // Clear Power Fail int 245 val &= AUX2_PWROFF; 246 s->aux2 = val; 247 if (val & AUX2_PWROFF) 248 qemu_system_shutdown_request(); 249 slavio_misc_update_irq(s); 250 } 251 252 static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr) 253 { 254 MiscState *s = opaque; 255 uint32_t ret = 0; 256 257 ret = s->aux2; 258 trace_slavio_aux2_mem_readb(ret); 259 return ret; 260 } 261 262 static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = { 263 slavio_aux2_mem_readb, 264 NULL, 265 NULL, 266 }; 267 268 static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = { 269 slavio_aux2_mem_writeb, 270 NULL, 271 NULL, 272 }; 273 274 static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, 275 uint64_t val, unsigned size) 276 { 277 APCState *s = opaque; 278 279 trace_apc_mem_writeb(val & 0xff); 280 qemu_irq_raise(s->cpu_halt); 281 } 282 283 static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr, 284 unsigned size) 285 { 286 uint32_t ret = 0; 287 288 trace_apc_mem_readb(ret); 289 return ret; 290 } 291 292 static const MemoryRegionOps apc_mem_ops = { 293 .read = apc_mem_readb, 294 .write = apc_mem_writeb, 295 .endianness = DEVICE_NATIVE_ENDIAN, 296 .valid = { 297 .min_access_size = 1, 298 .max_access_size = 1, 299 } 300 }; 301 302 static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr) 303 { 304 MiscState *s = opaque; 305 uint32_t ret = 0; 306 307 switch (addr) { 308 case 0: 309 ret = s->sysctrl; 310 break; 311 default: 312 break; 313 } 314 trace_slavio_sysctrl_mem_readl(ret); 315 return ret; 316 } 317 318 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr, 319 uint32_t val) 320 { 321 MiscState *s = opaque; 322 323 trace_slavio_sysctrl_mem_writel(val); 324 switch (addr) { 325 case 0: 326 if (val & SYS_RESET) { 327 s->sysctrl = SYS_RESETSTAT; 328 qemu_system_reset_request(); 329 } 330 break; 331 default: 332 break; 333 } 334 } 335 336 static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = { 337 NULL, 338 NULL, 339 slavio_sysctrl_mem_readl, 340 }; 341 342 static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = { 343 NULL, 344 NULL, 345 slavio_sysctrl_mem_writel, 346 }; 347 348 static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr) 349 { 350 MiscState *s = opaque; 351 uint32_t ret = 0; 352 353 switch (addr) { 354 case 0: 355 ret = s->leds; 356 break; 357 default: 358 break; 359 } 360 trace_slavio_led_mem_readw(ret); 361 return ret; 362 } 363 364 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr, 365 uint32_t val) 366 { 367 MiscState *s = opaque; 368 369 trace_slavio_led_mem_readw(val & 0xffff); 370 switch (addr) { 371 case 0: 372 s->leds = val; 373 break; 374 default: 375 break; 376 } 377 } 378 379 static CPUReadMemoryFunc * const slavio_led_mem_read[3] = { 380 NULL, 381 slavio_led_mem_readw, 382 NULL, 383 }; 384 385 static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = { 386 NULL, 387 slavio_led_mem_writew, 388 NULL, 389 }; 390 391 static const VMStateDescription vmstate_misc = { 392 .name ="slavio_misc", 393 .version_id = 1, 394 .minimum_version_id = 1, 395 .minimum_version_id_old = 1, 396 .fields = (VMStateField []) { 397 VMSTATE_UINT32(dummy, MiscState), 398 VMSTATE_UINT8(config, MiscState), 399 VMSTATE_UINT8(aux1, MiscState), 400 VMSTATE_UINT8(aux2, MiscState), 401 VMSTATE_UINT8(diag, MiscState), 402 VMSTATE_UINT8(mctrl, MiscState), 403 VMSTATE_UINT8(sysctrl, MiscState), 404 VMSTATE_END_OF_LIST() 405 } 406 }; 407 408 static int apc_init1(SysBusDevice *dev) 409 { 410 APCState *s = FROM_SYSBUS(APCState, dev); 411 412 sysbus_init_irq(dev, &s->cpu_halt); 413 414 /* Power management (APC) XXX: not a Slavio device */ 415 memory_region_init_io(&s->iomem, &apc_mem_ops, s, 416 "apc", MISC_SIZE); 417 sysbus_init_mmio_region(dev, &s->iomem); 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