|
|
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;
1.1.1.2 root 47: uint8_t diag, mctrl, sysctrl;
1.1 root 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:
1.1.1.2 root 67: // Diagnostic and system control registers not cleared in reset
1.1 root 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);
1.1.1.2 root 119: if (val & 1) {
120: s->sysctrl = 0x2;
1.1 root 121: qemu_system_reset_request();
1.1.1.2 root 122: }
1.1 root 123: break;
124: case 0xa000000:
125: MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
1.1.1.2 root 126: cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
1.1 root 127: break;
128: }
129: }
130:
131: static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr)
132: {
133: MiscState *s = opaque;
134: uint32_t ret = 0;
135:
136: switch (addr & 0xfff0000) {
137: case 0x1800000:
138: ret = s->config;
139: MISC_DPRINTF("Read config %2.2x\n", ret);
140: break;
141: case 0x1900000:
142: ret = s->aux1;
143: MISC_DPRINTF("Read aux1 %2.2x\n", ret);
144: break;
145: case 0x1910000:
146: ret = s->aux2;
147: MISC_DPRINTF("Read aux2 %2.2x\n", ret);
148: break;
149: case 0x1a00000:
150: ret = s->diag;
151: MISC_DPRINTF("Read diag %2.2x\n", ret);
152: break;
153: case 0x1b00000:
154: ret = s->mctrl;
155: MISC_DPRINTF("Read modem control %2.2x\n", ret);
156: break;
157: case 0x1f00000:
158: MISC_DPRINTF("Read system control %2.2x\n", ret);
1.1.1.2 root 159: ret = s->sysctrl;
1.1 root 160: break;
161: case 0xa000000:
162: MISC_DPRINTF("Read power management %2.2x\n", ret);
163: break;
164: }
165: return ret;
166: }
167:
168: static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
169: slavio_misc_mem_readb,
170: slavio_misc_mem_readb,
171: slavio_misc_mem_readb,
172: };
173:
174: static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
175: slavio_misc_mem_writeb,
176: slavio_misc_mem_writeb,
177: slavio_misc_mem_writeb,
178: };
179:
180: static void slavio_misc_save(QEMUFile *f, void *opaque)
181: {
182: MiscState *s = opaque;
183:
184: qemu_put_be32s(f, &s->irq);
185: qemu_put_8s(f, &s->config);
186: qemu_put_8s(f, &s->aux1);
187: qemu_put_8s(f, &s->aux2);
188: qemu_put_8s(f, &s->diag);
189: qemu_put_8s(f, &s->mctrl);
1.1.1.2 root 190: qemu_put_8s(f, &s->sysctrl);
1.1 root 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);
1.1.1.2 root 206: qemu_get_8s(f, &s->sysctrl);
1.1 root 207: return 0;
208: }
209:
210: void *slavio_misc_init(uint32_t base, int irq)
211: {
212: int slavio_misc_io_memory;
213: MiscState *s;
214:
215: s = qemu_mallocz(sizeof(MiscState));
216: if (!s)
217: return NULL;
218:
219: slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s);
220: // Slavio control
221: cpu_register_physical_memory(base + 0x1800000, MISC_MAXADDR, slavio_misc_io_memory);
222: // AUX 1
223: cpu_register_physical_memory(base + 0x1900000, MISC_MAXADDR, slavio_misc_io_memory);
224: // AUX 2
225: cpu_register_physical_memory(base + 0x1910000, MISC_MAXADDR, slavio_misc_io_memory);
226: // Diagnostics
227: cpu_register_physical_memory(base + 0x1a00000, MISC_MAXADDR, slavio_misc_io_memory);
228: // Modem control
229: cpu_register_physical_memory(base + 0x1b00000, MISC_MAXADDR, slavio_misc_io_memory);
230: // System control
231: cpu_register_physical_memory(base + 0x1f00000, MISC_MAXADDR, slavio_misc_io_memory);
232: // Power management
233: cpu_register_physical_memory(base + 0xa000000, MISC_MAXADDR, slavio_misc_io_memory);
234:
235: s->irq = irq;
236:
237: register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, s);
238: qemu_register_reset(slavio_misc_reset, s);
239: slavio_misc_reset(s);
240: return s;
241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.