Annotation of qemu/hw/slavio_misc.c, revision 1.1.1.4

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.4 ! root       24: #include "hw.h"
        !            25: #include "sun4m.h"
        !            26: #include "sysemu.h"
        !            27: 
1.1       root       28: /* debug misc */
                     29: //#define DEBUG_MISC
                     30: 
                     31: /*
                     32:  * This is the auxio port, chip control and system control part of
                     33:  * chip STP2001 (Slave I/O), also produced as NCR89C105. See
                     34:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
                     35:  *
                     36:  * This also includes the PMC CPU idle controller.
                     37:  */
                     38: 
                     39: #ifdef DEBUG_MISC
                     40: #define MISC_DPRINTF(fmt, args...) \
                     41: do { printf("MISC: " fmt , ##args); } while (0)
                     42: #else
                     43: #define MISC_DPRINTF(fmt, args...)
                     44: #endif
                     45: 
                     46: typedef struct MiscState {
1.1.1.4 ! root       47:     qemu_irq irq;
1.1       root       48:     uint8_t config;
                     49:     uint8_t aux1, aux2;
1.1.1.4 ! root       50:     uint8_t diag, mctrl;
        !            51:     uint32_t sysctrl;
        !            52:     uint16_t leds;
        !            53:     target_phys_addr_t power_base;
1.1       root       54: } MiscState;
                     55: 
1.1.1.4 ! root       56: #define MISC_SIZE 1
        !            57: #define SYSCTRL_MAXADDR 3
        !            58: #define SYSCTRL_SIZE (SYSCTRL_MAXADDR + 1)
        !            59: #define LED_MAXADDR 1
        !            60: #define LED_SIZE (LED_MAXADDR + 1)
        !            61: 
        !            62: #define MISC_MASK 0x0fff0000
        !            63: #define MISC_LEDS 0x01600000
        !            64: #define MISC_CFG  0x01800000
        !            65: #define MISC_AUX1 0x01900000
        !            66: #define MISC_AUX2 0x01910000
        !            67: #define MISC_DIAG 0x01a00000
        !            68: #define MISC_MDM  0x01b00000
        !            69: #define MISC_SYS  0x01f00000
        !            70: 
        !            71: #define AUX2_PWROFF    0x01
        !            72: #define AUX2_PWRINTCLR 0x02
        !            73: #define AUX2_PWRFAIL   0x20
        !            74: 
        !            75: #define CFG_PWRINTEN   0x08
        !            76: 
        !            77: #define SYS_RESET      0x01
        !            78: #define SYS_RESETSTAT  0x02
1.1       root       79: 
                     80: static void slavio_misc_update_irq(void *opaque)
                     81: {
                     82:     MiscState *s = opaque;
                     83: 
1.1.1.4 ! root       84:     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
        !            85:         MISC_DPRINTF("Raise IRQ\n");
        !            86:         qemu_irq_raise(s->irq);
1.1       root       87:     } else {
1.1.1.4 ! root       88:         MISC_DPRINTF("Lower IRQ\n");
        !            89:         qemu_irq_lower(s->irq);
1.1       root       90:     }
                     91: }
                     92: 
                     93: static void slavio_misc_reset(void *opaque)
                     94: {
                     95:     MiscState *s = opaque;
                     96: 
1.1.1.2   root       97:     // Diagnostic and system control registers not cleared in reset
1.1       root       98:     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
                     99: }
                    100: 
                    101: void slavio_set_power_fail(void *opaque, int power_failing)
                    102: {
                    103:     MiscState *s = opaque;
                    104: 
                    105:     MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
1.1.1.4 ! root      106:     if (power_failing && (s->config & CFG_PWRINTEN)) {
        !           107:         s->aux2 |= AUX2_PWRFAIL;
1.1       root      108:     } else {
1.1.1.4 ! root      109:         s->aux2 &= ~AUX2_PWRFAIL;
1.1       root      110:     }
                    111:     slavio_misc_update_irq(s);
                    112: }
                    113: 
1.1.1.4 ! root      114: static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr,
        !           115:                                    uint32_t val)
1.1       root      116: {
                    117:     MiscState *s = opaque;
                    118: 
1.1.1.4 ! root      119:     switch (addr & MISC_MASK) {
        !           120:     case MISC_CFG:
        !           121:         MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
        !           122:         s->config = val & 0xff;
        !           123:         slavio_misc_update_irq(s);
        !           124:         break;
        !           125:     case MISC_AUX1:
        !           126:         MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
        !           127:         s->aux1 = val & 0xff;
        !           128:         break;
        !           129:     case MISC_AUX2:
        !           130:         val &= AUX2_PWRINTCLR | AUX2_PWROFF;
        !           131:         MISC_DPRINTF("Write aux2 %2.2x\n", val);
        !           132:         val |= s->aux2 & AUX2_PWRFAIL;
        !           133:         if (val & AUX2_PWRINTCLR) // Clear Power Fail int
        !           134:             val &= AUX2_PWROFF;
        !           135:         s->aux2 = val;
        !           136:         if (val & AUX2_PWROFF)
        !           137:             qemu_system_shutdown_request();
        !           138:         slavio_misc_update_irq(s);
        !           139:         break;
        !           140:     case MISC_DIAG:
        !           141:         MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
        !           142:         s->diag = val & 0xff;
        !           143:         break;
        !           144:     case MISC_MDM:
        !           145:         MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
        !           146:         s->mctrl = val & 0xff;
        !           147:         break;
        !           148:     default:
        !           149:         if (addr == s->power_base) {
        !           150:             MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
        !           151:             cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
        !           152:         }
        !           153:         break;
1.1       root      154:     }
                    155: }
                    156: 
                    157: static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr)
                    158: {
                    159:     MiscState *s = opaque;
                    160:     uint32_t ret = 0;
                    161: 
1.1.1.4 ! root      162:     switch (addr & MISC_MASK) {
        !           163:     case MISC_CFG:
        !           164:         ret = s->config;
        !           165:         MISC_DPRINTF("Read config %2.2x\n", ret);
        !           166:         break;
        !           167:     case MISC_AUX1:
        !           168:         ret = s->aux1;
        !           169:         MISC_DPRINTF("Read aux1 %2.2x\n", ret);
        !           170:         break;
        !           171:     case MISC_AUX2:
        !           172:         ret = s->aux2;
        !           173:         MISC_DPRINTF("Read aux2 %2.2x\n", ret);
        !           174:         break;
        !           175:     case MISC_DIAG:
        !           176:         ret = s->diag;
        !           177:         MISC_DPRINTF("Read diag %2.2x\n", ret);
        !           178:         break;
        !           179:     case MISC_MDM:
        !           180:         ret = s->mctrl;
        !           181:         MISC_DPRINTF("Read modem control %2.2x\n", ret);
        !           182:         break;
        !           183:     default:
        !           184:         if (addr == s->power_base) {
        !           185:             MISC_DPRINTF("Read power management %2.2x\n", ret);
        !           186:         }
        !           187:         break;
1.1       root      188:     }
                    189:     return ret;
                    190: }
                    191: 
                    192: static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
                    193:     slavio_misc_mem_readb,
1.1.1.4 ! root      194:     NULL,
        !           195:     NULL,
1.1       root      196: };
                    197: 
                    198: static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
                    199:     slavio_misc_mem_writeb,
1.1.1.4 ! root      200:     NULL,
        !           201:     NULL,
        !           202: };
        !           203: 
        !           204: static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
        !           205: {
        !           206:     MiscState *s = opaque;
        !           207:     uint32_t ret = 0, saddr;
        !           208: 
        !           209:     saddr = addr & SYSCTRL_MAXADDR;
        !           210:     switch (saddr) {
        !           211:     case 0:
        !           212:         ret = s->sysctrl;
        !           213:         break;
        !           214:     default:
        !           215:         break;
        !           216:     }
        !           217:     MISC_DPRINTF("Read system control reg 0x" TARGET_FMT_plx " = %x\n", addr,
        !           218:                  ret);
        !           219:     return ret;
        !           220: }
        !           221: 
        !           222: static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
        !           223:                                       uint32_t val)
        !           224: {
        !           225:     MiscState *s = opaque;
        !           226:     uint32_t saddr;
        !           227: 
        !           228:     saddr = addr & SYSCTRL_MAXADDR;
        !           229:     MISC_DPRINTF("Write system control reg 0x" TARGET_FMT_plx " =  %x\n", addr,
        !           230:                  val);
        !           231:     switch (saddr) {
        !           232:     case 0:
        !           233:         if (val & SYS_RESET) {
        !           234:             s->sysctrl = SYS_RESETSTAT;
        !           235:             qemu_system_reset_request();
        !           236:         }
        !           237:         break;
        !           238:     default:
        !           239:         break;
        !           240:     }
        !           241: }
        !           242: 
        !           243: static CPUReadMemoryFunc *slavio_sysctrl_mem_read[3] = {
        !           244:     NULL,
        !           245:     NULL,
        !           246:     slavio_sysctrl_mem_readl,
        !           247: };
        !           248: 
        !           249: static CPUWriteMemoryFunc *slavio_sysctrl_mem_write[3] = {
        !           250:     NULL,
        !           251:     NULL,
        !           252:     slavio_sysctrl_mem_writel,
        !           253: };
        !           254: 
        !           255: static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
        !           256: {
        !           257:     MiscState *s = opaque;
        !           258:     uint32_t ret = 0, saddr;
        !           259: 
        !           260:     saddr = addr & LED_MAXADDR;
        !           261:     switch (saddr) {
        !           262:     case 0:
        !           263:         ret = s->leds;
        !           264:         break;
        !           265:     default:
        !           266:         break;
        !           267:     }
        !           268:     MISC_DPRINTF("Read diagnostic LED reg 0x" TARGET_FMT_plx " = %x\n", addr,
        !           269:                  ret);
        !           270:     return ret;
        !           271: }
        !           272: 
        !           273: static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
        !           274:                                   uint32_t val)
        !           275: {
        !           276:     MiscState *s = opaque;
        !           277:     uint32_t saddr;
        !           278: 
        !           279:     saddr = addr & LED_MAXADDR;
        !           280:     MISC_DPRINTF("Write diagnostic LED reg 0x" TARGET_FMT_plx " =  %x\n", addr,
        !           281:                  val);
        !           282:     switch (saddr) {
        !           283:     case 0:
        !           284:         s->leds = val;
        !           285:         break;
        !           286:     default:
        !           287:         break;
        !           288:     }
        !           289: }
        !           290: 
        !           291: static CPUReadMemoryFunc *slavio_led_mem_read[3] = {
        !           292:     NULL,
        !           293:     slavio_led_mem_readw,
        !           294:     NULL,
        !           295: };
        !           296: 
        !           297: static CPUWriteMemoryFunc *slavio_led_mem_write[3] = {
        !           298:     NULL,
        !           299:     slavio_led_mem_writew,
        !           300:     NULL,
1.1       root      301: };
                    302: 
                    303: static void slavio_misc_save(QEMUFile *f, void *opaque)
                    304: {
                    305:     MiscState *s = opaque;
1.1.1.4 ! root      306:     int tmp;
        !           307:     uint8_t tmp8;
1.1       root      308: 
1.1.1.4 ! root      309:     tmp = 0;
        !           310:     qemu_put_be32s(f, &tmp); /* ignored, was IRQ.  */
1.1       root      311:     qemu_put_8s(f, &s->config);
                    312:     qemu_put_8s(f, &s->aux1);
                    313:     qemu_put_8s(f, &s->aux2);
                    314:     qemu_put_8s(f, &s->diag);
                    315:     qemu_put_8s(f, &s->mctrl);
1.1.1.4 ! root      316:     tmp8 = s->sysctrl & 0xff;
        !           317:     qemu_put_8s(f, &tmp8);
1.1       root      318: }
                    319: 
                    320: static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
                    321: {
                    322:     MiscState *s = opaque;
1.1.1.4 ! root      323:     int tmp;
        !           324:     uint8_t tmp8;
1.1       root      325: 
                    326:     if (version_id != 1)
                    327:         return -EINVAL;
                    328: 
1.1.1.4 ! root      329:     qemu_get_be32s(f, &tmp);
1.1       root      330:     qemu_get_8s(f, &s->config);
                    331:     qemu_get_8s(f, &s->aux1);
                    332:     qemu_get_8s(f, &s->aux2);
                    333:     qemu_get_8s(f, &s->diag);
                    334:     qemu_get_8s(f, &s->mctrl);
1.1.1.4 ! root      335:     qemu_get_8s(f, &tmp8);
        !           336:     s->sysctrl = (uint32_t)tmp8;
1.1       root      337:     return 0;
                    338: }
                    339: 
1.1.1.4 ! root      340: void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base,
        !           341:                        qemu_irq irq)
1.1       root      342: {
                    343:     int slavio_misc_io_memory;
                    344:     MiscState *s;
                    345: 
                    346:     s = qemu_mallocz(sizeof(MiscState));
                    347:     if (!s)
                    348:         return NULL;
                    349: 
1.1.1.4 ! root      350:     /* 8 bit registers */
        !           351:     slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read,
        !           352:                                                    slavio_misc_mem_write, s);
1.1       root      353:     // Slavio control
1.1.1.4 ! root      354:     cpu_register_physical_memory(base + MISC_CFG, MISC_SIZE,
        !           355:                                  slavio_misc_io_memory);
1.1       root      356:     // AUX 1
1.1.1.4 ! root      357:     cpu_register_physical_memory(base + MISC_AUX1, MISC_SIZE,
        !           358:                                  slavio_misc_io_memory);
1.1       root      359:     // AUX 2
1.1.1.4 ! root      360:     cpu_register_physical_memory(base + MISC_AUX2, MISC_SIZE,
        !           361:                                  slavio_misc_io_memory);
1.1       root      362:     // Diagnostics
1.1.1.4 ! root      363:     cpu_register_physical_memory(base + MISC_DIAG, MISC_SIZE,
        !           364:                                  slavio_misc_io_memory);
1.1       root      365:     // Modem control
1.1.1.4 ! root      366:     cpu_register_physical_memory(base + MISC_MDM, MISC_SIZE,
        !           367:                                  slavio_misc_io_memory);
1.1       root      368:     // Power management
1.1.1.4 ! root      369:     cpu_register_physical_memory(power_base, MISC_SIZE, slavio_misc_io_memory);
        !           370:     s->power_base = power_base;
        !           371: 
        !           372:     /* 16 bit registers */
        !           373:     slavio_misc_io_memory = cpu_register_io_memory(0, slavio_led_mem_read,
        !           374:                                                    slavio_led_mem_write, s);
        !           375:     /* ss600mp diag LEDs */
        !           376:     cpu_register_physical_memory(base + MISC_LEDS, MISC_SIZE,
        !           377:                                  slavio_misc_io_memory);
        !           378: 
        !           379:     /* 32 bit registers */
        !           380:     slavio_misc_io_memory = cpu_register_io_memory(0, slavio_sysctrl_mem_read,
        !           381:                                                    slavio_sysctrl_mem_write,
        !           382:                                                    s);
        !           383:     // System control
        !           384:     cpu_register_physical_memory(base + MISC_SYS, SYSCTRL_SIZE,
        !           385:                                  slavio_misc_io_memory);
1.1       root      386: 
                    387:     s->irq = irq;
                    388: 
1.1.1.4 ! root      389:     register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load,
        !           390:                     s);
1.1       root      391:     qemu_register_reset(slavio_misc_reset, s);
                    392:     slavio_misc_reset(s);
                    393:     return s;
                    394: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.