|
|
1.1 root 1: /*
2: * QEMU Sparc SLAVIO aux io port emulation
1.1.1.4 root 3: *
1.1 root 4: * Copyright (c) 2005 Fabrice Bellard
1.1.1.4 root 5: *
1.1 root 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: */
1.1.1.6 root 24:
1.1.1.4 root 25: #include "sysemu.h"
1.1.1.6 root 26: #include "sysbus.h"
1.1.1.8 ! root 27: #include "trace.h"
1.1 root 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 {
1.1.1.6 root 38: SysBusDevice busdev;
1.1.1.4 root 39: qemu_irq irq;
1.1.1.7 root 40: uint32_t dummy;
1.1 root 41: uint8_t config;
42: uint8_t aux1, aux2;
1.1.1.4 root 43: uint8_t diag, mctrl;
1.1.1.7 root 44: uint8_t sysctrl;
1.1.1.4 root 45: uint16_t leds;
1.1.1.5 root 46: qemu_irq fdc_tc;
1.1 root 47: } MiscState;
48:
1.1.1.6 root 49: typedef struct APCState {
50: SysBusDevice busdev;
51: qemu_irq cpu_halt;
52: } APCState;
53:
1.1.1.4 root 54: #define MISC_SIZE 1
1.1.1.5 root 55: #define SYSCTRL_SIZE 4
1.1.1.4 root 56:
1.1.1.5 root 57: #define AUX1_TC 0x02
58:
1.1.1.4 root 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
1.1 root 67:
68: static void slavio_misc_update_irq(void *opaque)
69: {
70: MiscState *s = opaque;
71:
1.1.1.4 root 72: if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
1.1.1.8 ! root 73: trace_slavio_misc_update_irq_raise();
1.1.1.4 root 74: qemu_irq_raise(s->irq);
1.1 root 75: } else {
1.1.1.8 ! root 76: trace_slavio_misc_update_irq_lower();
1.1.1.4 root 77: qemu_irq_lower(s->irq);
1.1 root 78: }
79: }
80:
1.1.1.7 root 81: static void slavio_misc_reset(DeviceState *d)
1.1 root 82: {
1.1.1.7 root 83: MiscState *s = container_of(d, MiscState, busdev.qdev);
1.1 root 84:
1.1.1.2 root 85: // Diagnostic and system control registers not cleared in reset
1.1 root 86: s->config = s->aux1 = s->aux2 = s->mctrl = 0;
87: }
88:
1.1.1.7 root 89: static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
1.1 root 90: {
91: MiscState *s = opaque;
92:
1.1.1.8 ! root 93: trace_slavio_set_power_fail(power_failing, s->config);
1.1.1.4 root 94: if (power_failing && (s->config & CFG_PWRINTEN)) {
95: s->aux2 |= AUX2_PWRFAIL;
1.1 root 96: } else {
1.1.1.4 root 97: s->aux2 &= ~AUX2_PWRFAIL;
1.1 root 98: }
99: slavio_misc_update_irq(s);
100: }
101:
1.1.1.5 root 102: static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
103: uint32_t val)
104: {
105: MiscState *s = opaque;
106:
1.1.1.8 ! root 107: trace_slavio_cfg_mem_writeb(val & 0xff);
1.1.1.5 root 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;
1.1.1.8 ! root 118: trace_slavio_cfg_mem_readb(ret);
1.1.1.5 root 119: return ret;
120: }
121:
1.1.1.7 root 122: static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
1.1.1.5 root 123: slavio_cfg_mem_readb,
124: NULL,
125: NULL,
126: };
127:
1.1.1.7 root 128: static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
1.1.1.5 root 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,
1.1.1.4 root 135: uint32_t val)
1.1 root 136: {
137: MiscState *s = opaque;
138:
1.1.1.8 ! root 139: trace_slavio_diag_mem_writeb(val & 0xff);
1.1.1.5 root 140: s->diag = val & 0xff;
1.1 root 141: }
142:
1.1.1.5 root 143: static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
1.1 root 144: {
145: MiscState *s = opaque;
146: uint32_t ret = 0;
147:
1.1.1.5 root 148: ret = s->diag;
1.1.1.8 ! root 149: trace_slavio_diag_mem_readb(ret);
1.1.1.5 root 150: return ret;
151: }
152:
1.1.1.7 root 153: static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
1.1.1.5 root 154: slavio_diag_mem_readb,
155: NULL,
156: NULL,
157: };
158:
1.1.1.7 root 159: static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
1.1.1.5 root 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:
1.1.1.8 ! root 170: trace_slavio_mdm_mem_writeb(val & 0xff);
1.1.1.5 root 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;
1.1.1.8 ! root 180: trace_slavio_mdm_mem_readb(ret);
1.1.1.5 root 181: return ret;
182: }
183:
1.1.1.7 root 184: static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
1.1.1.5 root 185: slavio_mdm_mem_readb,
186: NULL,
187: NULL,
188: };
189:
1.1.1.7 root 190: static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
1.1.1.5 root 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:
1.1.1.8 ! root 201: trace_slavio_aux1_mem_writeb(val & 0xff);
1.1.1.5 root 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);
1.1.1.4 root 207: }
1.1.1.5 root 208: val &= ~AUX1_TC;
1.1 root 209: }
1.1.1.5 root 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;
1.1.1.8 ! root 219: trace_slavio_aux1_mem_readb(ret);
1.1 root 220: return ret;
221: }
222:
1.1.1.7 root 223: static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
1.1.1.5 root 224: slavio_aux1_mem_readb,
225: NULL,
226: NULL,
227: };
228:
1.1.1.7 root 229: static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
1.1.1.5 root 230: slavio_aux1_mem_writeb,
1.1.1.4 root 231: NULL,
232: NULL,
1.1 root 233: };
234:
1.1.1.5 root 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;
1.1.1.8 ! root 241: trace_slavio_aux2_mem_writeb(val & 0xff);
1.1.1.5 root 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;
1.1.1.8 ! root 257: trace_slavio_aux2_mem_readb(ret);
1.1.1.5 root 258: return ret;
259: }
260:
1.1.1.7 root 261: static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
1.1.1.5 root 262: slavio_aux2_mem_readb,
263: NULL,
264: NULL,
265: };
266:
1.1.1.7 root 267: static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
1.1.1.5 root 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: {
1.1.1.6 root 275: APCState *s = opaque;
1.1.1.5 root 276:
1.1.1.8 ! root 277: trace_apc_mem_writeb(val & 0xff);
1.1.1.5 root 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:
1.1.1.8 ! root 285: trace_apc_mem_readb(ret);
1.1.1.5 root 286: return ret;
287: }
288:
1.1.1.7 root 289: static CPUReadMemoryFunc * const apc_mem_read[3] = {
1.1.1.5 root 290: apc_mem_readb,
291: NULL,
292: NULL,
293: };
294:
1.1.1.7 root 295: static CPUWriteMemoryFunc * const apc_mem_write[3] = {
1.1.1.5 root 296: apc_mem_writeb,
1.1.1.4 root 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;
1.1.1.5 root 304: uint32_t ret = 0;
1.1.1.4 root 305:
1.1.1.5 root 306: switch (addr) {
1.1.1.4 root 307: case 0:
308: ret = s->sysctrl;
309: break;
310: default:
311: break;
312: }
1.1.1.8 ! root 313: trace_slavio_sysctrl_mem_readl(ret);
1.1.1.4 root 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:
1.1.1.8 ! root 322: trace_slavio_sysctrl_mem_writel(val);
1.1.1.5 root 323: switch (addr) {
1.1.1.4 root 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:
1.1.1.7 root 335: static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
1.1.1.4 root 336: NULL,
337: NULL,
338: slavio_sysctrl_mem_readl,
339: };
340:
1.1.1.7 root 341: static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
1.1.1.4 root 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;
1.1.1.5 root 350: uint32_t ret = 0;
1.1.1.4 root 351:
1.1.1.5 root 352: switch (addr) {
1.1.1.4 root 353: case 0:
354: ret = s->leds;
355: break;
356: default:
357: break;
358: }
1.1.1.8 ! root 359: trace_slavio_led_mem_readw(ret);
1.1.1.4 root 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:
1.1.1.8 ! root 368: trace_slavio_led_mem_readw(val & 0xffff);
1.1.1.5 root 369: switch (addr) {
1.1.1.4 root 370: case 0:
371: s->leds = val;
372: break;
373: default:
374: break;
375: }
376: }
377:
1.1.1.7 root 378: static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
1.1.1.4 root 379: NULL,
380: slavio_led_mem_readw,
381: NULL,
382: };
383:
1.1.1.7 root 384: static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
1.1.1.4 root 385: NULL,
386: slavio_led_mem_writew,
387: NULL,
1.1 root 388: };
389:
1.1.1.7 root 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()
1.1.1.5 root 404: }
1.1.1.7 root 405: };
1.1.1.6 root 406:
1.1.1.7 root 407: static int apc_init1(SysBusDevice *dev)
1.1.1.6 root 408: {
409: APCState *s = FROM_SYSBUS(APCState, dev);
410: int io;
1.1 root 411:
1.1.1.6 root 412: sysbus_init_irq(dev, &s->cpu_halt);
1.1 root 413:
1.1.1.6 root 414: /* Power management (APC) XXX: not a Slavio device */
1.1.1.8 ! root 415: io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
! 416: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 417: sysbus_init_mmio(dev, MISC_SIZE, io);
1.1.1.7 root 418: return 0;
1.1.1.6 root 419: }
420:
1.1.1.7 root 421: static int slavio_misc_init1(SysBusDevice *dev)
1.1.1.6 root 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,
1.1.1.8 ! root 432: slavio_cfg_mem_write, s,
! 433: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 434: sysbus_init_mmio(dev, MISC_SIZE, io);
435:
436: /* Diagnostics */
437: io = cpu_register_io_memory(slavio_diag_mem_read,
1.1.1.8 ! root 438: slavio_diag_mem_write, s,
! 439: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 440: sysbus_init_mmio(dev, MISC_SIZE, io);
441:
442: /* Modem control */
443: io = cpu_register_io_memory(slavio_mdm_mem_read,
1.1.1.8 ! root 444: slavio_mdm_mem_write, s,
! 445: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 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,
1.1.1.8 ! root 451: slavio_led_mem_write, s,
! 452: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 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,
1.1.1.8 ! root 458: slavio_sysctrl_mem_write, s,
! 459: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 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,
1.1.1.8 ! root 464: slavio_aux1_mem_write, s,
! 465: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 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,
1.1.1.8 ! root 470: slavio_aux2_mem_write, s,
! 471: DEVICE_NATIVE_ENDIAN);
1.1.1.6 root 472: sysbus_init_mmio(dev, MISC_SIZE, io);
473:
1.1.1.7 root 474: qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
475:
476: return 0;
1.1.1.6 root 477: }
478:
479: static SysBusDeviceInfo slavio_misc_info = {
480: .init = slavio_misc_init1,
481: .qdev.name = "slavio_misc",
482: .qdev.size = sizeof(MiscState),
1.1.1.7 root 483: .qdev.vmsd = &vmstate_misc,
484: .qdev.reset = slavio_misc_reset,
1.1.1.6 root 485: };
1.1.1.5 root 486:
1.1.1.6 root 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);
1.1 root 497: }
1.1.1.6 root 498:
499: device_init(slavio_misc_register_devices)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.