|
|
1.1 ! root 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: #include "vl.h" ! 25: /* debug misc */ ! 26: //#define DEBUG_MISC ! 27: ! 28: /* ! 29: * This is the auxio port, chip control and system control part of ! 30: * chip STP2001 (Slave I/O), also produced as NCR89C105. See ! 31: * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt ! 32: * ! 33: * This also includes the PMC CPU idle controller. ! 34: */ ! 35: ! 36: #ifdef DEBUG_MISC ! 37: #define MISC_DPRINTF(fmt, args...) \ ! 38: do { printf("MISC: " fmt , ##args); } while (0) ! 39: #else ! 40: #define MISC_DPRINTF(fmt, args...) ! 41: #endif ! 42: ! 43: typedef struct MiscState { ! 44: int irq; ! 45: uint8_t config; ! 46: uint8_t aux1, aux2; ! 47: uint8_t diag, mctrl; ! 48: } MiscState; ! 49: ! 50: #define MISC_MAXADDR 1 ! 51: ! 52: static void slavio_misc_update_irq(void *opaque) ! 53: { ! 54: MiscState *s = opaque; ! 55: ! 56: if ((s->aux2 & 0x4) && (s->config & 0x8)) { ! 57: pic_set_irq(s->irq, 1); ! 58: } else { ! 59: pic_set_irq(s->irq, 0); ! 60: } ! 61: } ! 62: ! 63: static void slavio_misc_reset(void *opaque) ! 64: { ! 65: MiscState *s = opaque; ! 66: ! 67: // Diagnostic register not cleared in reset ! 68: s->config = s->aux1 = s->aux2 = s->mctrl = 0; ! 69: } ! 70: ! 71: void slavio_set_power_fail(void *opaque, int power_failing) ! 72: { ! 73: MiscState *s = opaque; ! 74: ! 75: MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config); ! 76: if (power_failing && (s->config & 0x8)) { ! 77: s->aux2 |= 0x4; ! 78: } else { ! 79: s->aux2 &= ~0x4; ! 80: } ! 81: slavio_misc_update_irq(s); ! 82: } ! 83: ! 84: static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) ! 85: { ! 86: MiscState *s = opaque; ! 87: ! 88: switch (addr & 0xfff0000) { ! 89: case 0x1800000: ! 90: MISC_DPRINTF("Write config %2.2x\n", val & 0xff); ! 91: s->config = val & 0xff; ! 92: slavio_misc_update_irq(s); ! 93: break; ! 94: case 0x1900000: ! 95: MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff); ! 96: s->aux1 = val & 0xff; ! 97: break; ! 98: case 0x1910000: ! 99: val &= 0x3; ! 100: MISC_DPRINTF("Write aux2 %2.2x\n", val); ! 101: val |= s->aux2 & 0x4; ! 102: if (val & 0x2) // Clear Power Fail int ! 103: val &= 0x1; ! 104: s->aux2 = val; ! 105: if (val & 1) ! 106: qemu_system_shutdown_request(); ! 107: slavio_misc_update_irq(s); ! 108: break; ! 109: case 0x1a00000: ! 110: MISC_DPRINTF("Write diag %2.2x\n", val & 0xff); ! 111: s->diag = val & 0xff; ! 112: break; ! 113: case 0x1b00000: ! 114: MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff); ! 115: s->mctrl = val & 0xff; ! 116: break; ! 117: case 0x1f00000: ! 118: MISC_DPRINTF("Write system control %2.2x\n", val & 0xff); ! 119: if (val & 1) ! 120: qemu_system_reset_request(); ! 121: break; ! 122: case 0xa000000: ! 123: MISC_DPRINTF("Write power management %2.2x\n", val & 0xff); ! 124: #if 0 ! 125: // XXX: halting CPU does not work ! 126: raise_exception(EXCP_HLT); ! 127: cpu_loop_exit(); ! 128: #endif ! 129: break; ! 130: } ! 131: } ! 132: ! 133: static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr) ! 134: { ! 135: MiscState *s = opaque; ! 136: uint32_t ret = 0; ! 137: ! 138: switch (addr & 0xfff0000) { ! 139: case 0x1800000: ! 140: ret = s->config; ! 141: MISC_DPRINTF("Read config %2.2x\n", ret); ! 142: break; ! 143: case 0x1900000: ! 144: ret = s->aux1; ! 145: MISC_DPRINTF("Read aux1 %2.2x\n", ret); ! 146: break; ! 147: case 0x1910000: ! 148: ret = s->aux2; ! 149: MISC_DPRINTF("Read aux2 %2.2x\n", ret); ! 150: break; ! 151: case 0x1a00000: ! 152: ret = s->diag; ! 153: MISC_DPRINTF("Read diag %2.2x\n", ret); ! 154: break; ! 155: case 0x1b00000: ! 156: ret = s->mctrl; ! 157: MISC_DPRINTF("Read modem control %2.2x\n", ret); ! 158: break; ! 159: case 0x1f00000: ! 160: MISC_DPRINTF("Read system control %2.2x\n", ret); ! 161: break; ! 162: case 0xa000000: ! 163: MISC_DPRINTF("Read power management %2.2x\n", ret); ! 164: break; ! 165: } ! 166: return ret; ! 167: } ! 168: ! 169: static CPUReadMemoryFunc *slavio_misc_mem_read[3] = { ! 170: slavio_misc_mem_readb, ! 171: slavio_misc_mem_readb, ! 172: slavio_misc_mem_readb, ! 173: }; ! 174: ! 175: static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = { ! 176: slavio_misc_mem_writeb, ! 177: slavio_misc_mem_writeb, ! 178: slavio_misc_mem_writeb, ! 179: }; ! 180: ! 181: static void slavio_misc_save(QEMUFile *f, void *opaque) ! 182: { ! 183: MiscState *s = opaque; ! 184: ! 185: qemu_put_be32s(f, &s->irq); ! 186: qemu_put_8s(f, &s->config); ! 187: qemu_put_8s(f, &s->aux1); ! 188: qemu_put_8s(f, &s->aux2); ! 189: qemu_put_8s(f, &s->diag); ! 190: qemu_put_8s(f, &s->mctrl); ! 191: } ! 192: ! 193: static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id) ! 194: { ! 195: MiscState *s = opaque; ! 196: ! 197: if (version_id != 1) ! 198: return -EINVAL; ! 199: ! 200: qemu_get_be32s(f, &s->irq); ! 201: qemu_get_8s(f, &s->config); ! 202: qemu_get_8s(f, &s->aux1); ! 203: qemu_get_8s(f, &s->aux2); ! 204: qemu_get_8s(f, &s->diag); ! 205: qemu_get_8s(f, &s->mctrl); ! 206: return 0; ! 207: } ! 208: ! 209: void *slavio_misc_init(uint32_t base, int irq) ! 210: { ! 211: int slavio_misc_io_memory; ! 212: MiscState *s; ! 213: ! 214: s = qemu_mallocz(sizeof(MiscState)); ! 215: if (!s) ! 216: return NULL; ! 217: ! 218: slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s); ! 219: // Slavio control ! 220: cpu_register_physical_memory(base + 0x1800000, MISC_MAXADDR, slavio_misc_io_memory); ! 221: // AUX 1 ! 222: cpu_register_physical_memory(base + 0x1900000, MISC_MAXADDR, slavio_misc_io_memory); ! 223: // AUX 2 ! 224: cpu_register_physical_memory(base + 0x1910000, MISC_MAXADDR, slavio_misc_io_memory); ! 225: // Diagnostics ! 226: cpu_register_physical_memory(base + 0x1a00000, MISC_MAXADDR, slavio_misc_io_memory); ! 227: // Modem control ! 228: cpu_register_physical_memory(base + 0x1b00000, MISC_MAXADDR, slavio_misc_io_memory); ! 229: // System control ! 230: cpu_register_physical_memory(base + 0x1f00000, MISC_MAXADDR, slavio_misc_io_memory); ! 231: // Power management ! 232: cpu_register_physical_memory(base + 0xa000000, MISC_MAXADDR, slavio_misc_io_memory); ! 233: ! 234: s->irq = irq; ! 235: ! 236: register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, s); ! 237: qemu_register_reset(slavio_misc_reset, s); ! 238: slavio_misc_reset(s); ! 239: return s; ! 240: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.