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

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.4   root       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
1.1.1.6   root       40: #define MISC_DPRINTF(fmt, ...)                                  \
                     41:     do { printf("MISC: " fmt , ## __VA_ARGS__); } while (0)
1.1       root       42: #else
1.1.1.6   root       43: #define MISC_DPRINTF(fmt, ...)
1.1       root       44: #endif
                     45: 
                     46: typedef struct MiscState {
1.1.1.6   root       47:     SysBusDevice busdev;
1.1.1.4   root       48:     qemu_irq irq;
1.1.1.7 ! root       49:     uint32_t dummy;
1.1       root       50:     uint8_t config;
                     51:     uint8_t aux1, aux2;
1.1.1.4   root       52:     uint8_t diag, mctrl;
1.1.1.7 ! root       53:     uint8_t sysctrl;
1.1.1.4   root       54:     uint16_t leds;
1.1.1.5   root       55:     qemu_irq fdc_tc;
1.1       root       56: } MiscState;
                     57: 
1.1.1.6   root       58: typedef struct APCState {
                     59:     SysBusDevice busdev;
                     60:     qemu_irq cpu_halt;
                     61: } APCState;
                     62: 
1.1.1.4   root       63: #define MISC_SIZE 1
1.1.1.5   root       64: #define SYSCTRL_SIZE 4
1.1.1.4   root       65: 
1.1.1.5   root       66: #define AUX1_TC        0x02
                     67: 
1.1.1.4   root       68: #define AUX2_PWROFF    0x01
                     69: #define AUX2_PWRINTCLR 0x02
                     70: #define AUX2_PWRFAIL   0x20
                     71: 
                     72: #define CFG_PWRINTEN   0x08
                     73: 
                     74: #define SYS_RESET      0x01
                     75: #define SYS_RESETSTAT  0x02
1.1       root       76: 
                     77: static void slavio_misc_update_irq(void *opaque)
                     78: {
                     79:     MiscState *s = opaque;
                     80: 
1.1.1.4   root       81:     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
                     82:         MISC_DPRINTF("Raise IRQ\n");
                     83:         qemu_irq_raise(s->irq);
1.1       root       84:     } else {
1.1.1.4   root       85:         MISC_DPRINTF("Lower IRQ\n");
                     86:         qemu_irq_lower(s->irq);
1.1       root       87:     }
                     88: }
                     89: 
1.1.1.7 ! root       90: static void slavio_misc_reset(DeviceState *d)
1.1       root       91: {
1.1.1.7 ! root       92:     MiscState *s = container_of(d, MiscState, busdev.qdev);
1.1       root       93: 
1.1.1.2   root       94:     // Diagnostic and system control registers not cleared in reset
1.1       root       95:     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
                     96: }
                     97: 
1.1.1.7 ! root       98: static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
1.1       root       99: {
                    100:     MiscState *s = opaque;
                    101: 
                    102:     MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
1.1.1.4   root      103:     if (power_failing && (s->config & CFG_PWRINTEN)) {
                    104:         s->aux2 |= AUX2_PWRFAIL;
1.1       root      105:     } else {
1.1.1.4   root      106:         s->aux2 &= ~AUX2_PWRFAIL;
1.1       root      107:     }
                    108:     slavio_misc_update_irq(s);
                    109: }
                    110: 
1.1.1.5   root      111: static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
                    112:                                   uint32_t val)
                    113: {
                    114:     MiscState *s = opaque;
                    115: 
                    116:     MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
                    117:     s->config = val & 0xff;
                    118:     slavio_misc_update_irq(s);
                    119: }
                    120: 
                    121: static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
                    122: {
                    123:     MiscState *s = opaque;
                    124:     uint32_t ret = 0;
                    125: 
                    126:     ret = s->config;
                    127:     MISC_DPRINTF("Read config %2.2x\n", ret);
                    128:     return ret;
                    129: }
                    130: 
1.1.1.7 ! root      131: static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
1.1.1.5   root      132:     slavio_cfg_mem_readb,
                    133:     NULL,
                    134:     NULL,
                    135: };
                    136: 
1.1.1.7 ! root      137: static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
1.1.1.5   root      138:     slavio_cfg_mem_writeb,
                    139:     NULL,
                    140:     NULL,
                    141: };
                    142: 
                    143: static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
1.1.1.4   root      144:                                    uint32_t val)
1.1       root      145: {
                    146:     MiscState *s = opaque;
                    147: 
1.1.1.5   root      148:     MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
                    149:     s->diag = val & 0xff;
1.1       root      150: }
                    151: 
1.1.1.5   root      152: static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
1.1       root      153: {
                    154:     MiscState *s = opaque;
                    155:     uint32_t ret = 0;
                    156: 
1.1.1.5   root      157:     ret = s->diag;
                    158:     MISC_DPRINTF("Read diag %2.2x\n", ret);
                    159:     return ret;
                    160: }
                    161: 
1.1.1.7 ! root      162: static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
1.1.1.5   root      163:     slavio_diag_mem_readb,
                    164:     NULL,
                    165:     NULL,
                    166: };
                    167: 
1.1.1.7 ! root      168: static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
1.1.1.5   root      169:     slavio_diag_mem_writeb,
                    170:     NULL,
                    171:     NULL,
                    172: };
                    173: 
                    174: static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
                    175:                                   uint32_t val)
                    176: {
                    177:     MiscState *s = opaque;
                    178: 
                    179:     MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
                    180:     s->mctrl = val & 0xff;
                    181: }
                    182: 
                    183: static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
                    184: {
                    185:     MiscState *s = opaque;
                    186:     uint32_t ret = 0;
                    187: 
                    188:     ret = s->mctrl;
                    189:     MISC_DPRINTF("Read modem control %2.2x\n", ret);
                    190:     return ret;
                    191: }
                    192: 
1.1.1.7 ! root      193: static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
1.1.1.5   root      194:     slavio_mdm_mem_readb,
                    195:     NULL,
                    196:     NULL,
                    197: };
                    198: 
1.1.1.7 ! root      199: static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
1.1.1.5   root      200:     slavio_mdm_mem_writeb,
                    201:     NULL,
                    202:     NULL,
                    203: };
                    204: 
                    205: static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
                    206:                                    uint32_t val)
                    207: {
                    208:     MiscState *s = opaque;
                    209: 
                    210:     MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
                    211:     if (val & AUX1_TC) {
                    212:         // Send a pulse to floppy terminal count line
                    213:         if (s->fdc_tc) {
                    214:             qemu_irq_raise(s->fdc_tc);
                    215:             qemu_irq_lower(s->fdc_tc);
1.1.1.4   root      216:         }
1.1.1.5   root      217:         val &= ~AUX1_TC;
1.1       root      218:     }
1.1.1.5   root      219:     s->aux1 = val & 0xff;
                    220: }
                    221: 
                    222: static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
                    223: {
                    224:     MiscState *s = opaque;
                    225:     uint32_t ret = 0;
                    226: 
                    227:     ret = s->aux1;
                    228:     MISC_DPRINTF("Read aux1 %2.2x\n", ret);
                    229: 
1.1       root      230:     return ret;
                    231: }
                    232: 
1.1.1.7 ! root      233: static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
1.1.1.5   root      234:     slavio_aux1_mem_readb,
                    235:     NULL,
                    236:     NULL,
                    237: };
                    238: 
1.1.1.7 ! root      239: static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
1.1.1.5   root      240:     slavio_aux1_mem_writeb,
1.1.1.4   root      241:     NULL,
                    242:     NULL,
1.1       root      243: };
                    244: 
1.1.1.5   root      245: static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
                    246:                                    uint32_t val)
                    247: {
                    248:     MiscState *s = opaque;
                    249: 
                    250:     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
                    251:     MISC_DPRINTF("Write aux2 %2.2x\n", val);
                    252:     val |= s->aux2 & AUX2_PWRFAIL;
                    253:     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
                    254:         val &= AUX2_PWROFF;
                    255:     s->aux2 = val;
                    256:     if (val & AUX2_PWROFF)
                    257:         qemu_system_shutdown_request();
                    258:     slavio_misc_update_irq(s);
                    259: }
                    260: 
                    261: static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
                    262: {
                    263:     MiscState *s = opaque;
                    264:     uint32_t ret = 0;
                    265: 
                    266:     ret = s->aux2;
                    267:     MISC_DPRINTF("Read aux2 %2.2x\n", ret);
                    268: 
                    269:     return ret;
                    270: }
                    271: 
1.1.1.7 ! root      272: static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
1.1.1.5   root      273:     slavio_aux2_mem_readb,
                    274:     NULL,
                    275:     NULL,
                    276: };
                    277: 
1.1.1.7 ! root      278: static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
1.1.1.5   root      279:     slavio_aux2_mem_writeb,
                    280:     NULL,
                    281:     NULL,
                    282: };
                    283: 
                    284: static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    285: {
1.1.1.6   root      286:     APCState *s = opaque;
1.1.1.5   root      287: 
                    288:     MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
                    289:     qemu_irq_raise(s->cpu_halt);
                    290: }
                    291: 
                    292: static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
                    293: {
                    294:     uint32_t ret = 0;
                    295: 
                    296:     MISC_DPRINTF("Read power management %2.2x\n", ret);
                    297:     return ret;
                    298: }
                    299: 
1.1.1.7 ! root      300: static CPUReadMemoryFunc * const apc_mem_read[3] = {
1.1.1.5   root      301:     apc_mem_readb,
                    302:     NULL,
                    303:     NULL,
                    304: };
                    305: 
1.1.1.7 ! root      306: static CPUWriteMemoryFunc * const apc_mem_write[3] = {
1.1.1.5   root      307:     apc_mem_writeb,
1.1.1.4   root      308:     NULL,
                    309:     NULL,
                    310: };
                    311: 
                    312: static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
                    313: {
                    314:     MiscState *s = opaque;
1.1.1.5   root      315:     uint32_t ret = 0;
1.1.1.4   root      316: 
1.1.1.5   root      317:     switch (addr) {
1.1.1.4   root      318:     case 0:
                    319:         ret = s->sysctrl;
                    320:         break;
                    321:     default:
                    322:         break;
                    323:     }
1.1.1.5   root      324:     MISC_DPRINTF("Read system control %08x\n", ret);
1.1.1.4   root      325:     return ret;
                    326: }
                    327: 
                    328: static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
                    329:                                       uint32_t val)
                    330: {
                    331:     MiscState *s = opaque;
                    332: 
1.1.1.5   root      333:     MISC_DPRINTF("Write system control %08x\n", val);
                    334:     switch (addr) {
1.1.1.4   root      335:     case 0:
                    336:         if (val & SYS_RESET) {
                    337:             s->sysctrl = SYS_RESETSTAT;
                    338:             qemu_system_reset_request();
                    339:         }
                    340:         break;
                    341:     default:
                    342:         break;
                    343:     }
                    344: }
                    345: 
1.1.1.7 ! root      346: static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
1.1.1.4   root      347:     NULL,
                    348:     NULL,
                    349:     slavio_sysctrl_mem_readl,
                    350: };
                    351: 
1.1.1.7 ! root      352: static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
1.1.1.4   root      353:     NULL,
                    354:     NULL,
                    355:     slavio_sysctrl_mem_writel,
                    356: };
                    357: 
                    358: static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
                    359: {
                    360:     MiscState *s = opaque;
1.1.1.5   root      361:     uint32_t ret = 0;
1.1.1.4   root      362: 
1.1.1.5   root      363:     switch (addr) {
1.1.1.4   root      364:     case 0:
                    365:         ret = s->leds;
                    366:         break;
                    367:     default:
                    368:         break;
                    369:     }
1.1.1.5   root      370:     MISC_DPRINTF("Read diagnostic LED %04x\n", ret);
1.1.1.4   root      371:     return ret;
                    372: }
                    373: 
                    374: static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
                    375:                                   uint32_t val)
                    376: {
                    377:     MiscState *s = opaque;
                    378: 
1.1.1.5   root      379:     MISC_DPRINTF("Write diagnostic LED %04x\n", val & 0xffff);
                    380:     switch (addr) {
1.1.1.4   root      381:     case 0:
                    382:         s->leds = val;
                    383:         break;
                    384:     default:
                    385:         break;
                    386:     }
                    387: }
                    388: 
1.1.1.7 ! root      389: static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
1.1.1.4   root      390:     NULL,
                    391:     slavio_led_mem_readw,
                    392:     NULL,
                    393: };
                    394: 
1.1.1.7 ! root      395: static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
1.1.1.4   root      396:     NULL,
                    397:     slavio_led_mem_writew,
                    398:     NULL,
1.1       root      399: };
                    400: 
1.1.1.7 ! root      401: static const VMStateDescription vmstate_misc = {
        !           402:     .name ="slavio_misc",
        !           403:     .version_id = 1,
        !           404:     .minimum_version_id = 1,
        !           405:     .minimum_version_id_old = 1,
        !           406:     .fields      = (VMStateField []) {
        !           407:         VMSTATE_UINT32(dummy, MiscState),
        !           408:         VMSTATE_UINT8(config, MiscState),
        !           409:         VMSTATE_UINT8(aux1, MiscState),
        !           410:         VMSTATE_UINT8(aux2, MiscState),
        !           411:         VMSTATE_UINT8(diag, MiscState),
        !           412:         VMSTATE_UINT8(mctrl, MiscState),
        !           413:         VMSTATE_UINT8(sysctrl, MiscState),
        !           414:         VMSTATE_END_OF_LIST()
1.1.1.5   root      415:     }
1.1.1.7 ! root      416: };
1.1.1.6   root      417: 
1.1.1.7 ! root      418: static int apc_init1(SysBusDevice *dev)
1.1.1.6   root      419: {
                    420:     APCState *s = FROM_SYSBUS(APCState, dev);
                    421:     int io;
1.1       root      422: 
1.1.1.6   root      423:     sysbus_init_irq(dev, &s->cpu_halt);
1.1       root      424: 
1.1.1.6   root      425:     /* Power management (APC) XXX: not a Slavio device */
                    426:     io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s);
                    427:     sysbus_init_mmio(dev, MISC_SIZE, io);
1.1.1.7 ! root      428:     return 0;
1.1.1.6   root      429: }
                    430: 
1.1.1.7 ! root      431: static int slavio_misc_init1(SysBusDevice *dev)
1.1.1.6   root      432: {
                    433:     MiscState *s = FROM_SYSBUS(MiscState, dev);
                    434:     int io;
                    435: 
                    436:     sysbus_init_irq(dev, &s->irq);
                    437:     sysbus_init_irq(dev, &s->fdc_tc);
                    438: 
                    439:     /* 8 bit registers */
                    440:     /* Slavio control */
                    441:     io = cpu_register_io_memory(slavio_cfg_mem_read,
                    442:                                 slavio_cfg_mem_write, s);
                    443:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    444: 
                    445:     /* Diagnostics */
                    446:     io = cpu_register_io_memory(slavio_diag_mem_read,
                    447:                                 slavio_diag_mem_write, s);
                    448:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    449: 
                    450:     /* Modem control */
                    451:     io = cpu_register_io_memory(slavio_mdm_mem_read,
                    452:                                 slavio_mdm_mem_write, s);
                    453:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    454: 
                    455:     /* 16 bit registers */
                    456:     /* ss600mp diag LEDs */
                    457:     io = cpu_register_io_memory(slavio_led_mem_read,
                    458:                                 slavio_led_mem_write, s);
                    459:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    460: 
                    461:     /* 32 bit registers */
                    462:     /* System control */
                    463:     io = cpu_register_io_memory(slavio_sysctrl_mem_read,
                    464:                                 slavio_sysctrl_mem_write, s);
                    465:     sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
                    466: 
                    467:     /* AUX 1 (Misc System Functions) */
                    468:     io = cpu_register_io_memory(slavio_aux1_mem_read,
                    469:                                 slavio_aux1_mem_write, s);
                    470:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    471: 
                    472:     /* AUX 2 (Software Powerdown Control) */
                    473:     io = cpu_register_io_memory(slavio_aux2_mem_read,
                    474:                                 slavio_aux2_mem_write, s);
                    475:     sysbus_init_mmio(dev, MISC_SIZE, io);
                    476: 
1.1.1.7 ! root      477:     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
        !           478: 
        !           479:     return 0;
1.1.1.6   root      480: }
                    481: 
                    482: static SysBusDeviceInfo slavio_misc_info = {
                    483:     .init = slavio_misc_init1,
                    484:     .qdev.name  = "slavio_misc",
                    485:     .qdev.size  = sizeof(MiscState),
1.1.1.7 ! root      486:     .qdev.vmsd  = &vmstate_misc,
        !           487:     .qdev.reset  = slavio_misc_reset,
1.1.1.6   root      488: };
1.1.1.5   root      489: 
1.1.1.6   root      490: static SysBusDeviceInfo apc_info = {
                    491:     .init = apc_init1,
                    492:     .qdev.name  = "apc",
                    493:     .qdev.size  = sizeof(MiscState),
                    494: };
                    495: 
                    496: static void slavio_misc_register_devices(void)
                    497: {
                    498:     sysbus_register_withprop(&slavio_misc_info);
                    499:     sysbus_register_withprop(&apc_info);
1.1       root      500: }
1.1.1.6   root      501: 
                    502: device_init(slavio_misc_register_devices)

unix.superglobalmegacorp.com

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