Annotation of qemu/hw/eccmemctl.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU Sparc Sun4m ECC memory controller emulation
        !             3:  *
        !             4:  * Copyright (c) 2007 Robert Reif
        !             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 "hw.h"
        !            25: #include "sun4m.h"
        !            26: #include "sysemu.h"
        !            27: 
        !            28: //#define DEBUG_ECC
        !            29: 
        !            30: #ifdef DEBUG_ECC
        !            31: #define DPRINTF(fmt, args...)                           \
        !            32:     do { printf("ECC: " fmt , ##args); } while (0)
        !            33: #else
        !            34: #define DPRINTF(fmt, args...)
        !            35: #endif
        !            36: 
        !            37: /* There are 3 versions of this chip used in SMP sun4m systems:
        !            38:  * MCC (version 0, implementation 0) SS-600MP
        !            39:  * EMC (version 0, implementation 1) SS-10
        !            40:  * SMC (version 0, implementation 2) SS-10SX and SS-20
        !            41:  */
        !            42: 
        !            43: /* Register offsets */
        !            44: #define ECC_FCR_REG    0
        !            45: #define ECC_FSR_REG    8
        !            46: #define ECC_FAR0_REG   16
        !            47: #define ECC_FAR1_REG   20
        !            48: #define ECC_DIAG_REG   24
        !            49: 
        !            50: /* ECC fault control register */
        !            51: #define ECC_FCR_EE     0x00000001      /* Enable ECC checking */
        !            52: #define ECC_FCR_EI     0x00000010      /* Enable Interrupts on correctable errors */
        !            53: #define ECC_FCR_VER    0x0f000000      /* Version */
        !            54: #define ECC_FCR_IMPL   0xf0000000      /* Implementation */
        !            55: 
        !            56: /* ECC fault status register */
        !            57: #define ECC_FSR_CE     0x00000001      /* Correctable error */
        !            58: #define ECC_FSR_BS     0x00000002      /* C2 graphics bad slot access */
        !            59: #define ECC_FSR_TO     0x00000004      /* Timeout on write */
        !            60: #define ECC_FSR_UE     0x00000008      /* Uncorrectable error */
        !            61: #define ECC_FSR_DW     0x000000f0      /* Index of double word in block */
        !            62: #define ECC_FSR_SYND   0x0000ff00      /* Syndrome for correctable error */
        !            63: #define ECC_FSR_ME     0x00010000      /* Multiple errors */
        !            64: #define ECC_FSR_C2ERR  0x00020000      /* C2 graphics error */
        !            65: 
        !            66: /* ECC fault address register 0 */
        !            67: #define ECC_FAR0_PADDR 0x0000000f      /* PA[32-35] */
        !            68: #define ECC_FAR0_TYPE  0x000000f0      /* Transaction type */
        !            69: #define ECC_FAR0_SIZE  0x00000700      /* Transaction size */
        !            70: #define ECC_FAR0_CACHE 0x00000800      /* Mapped cacheable */
        !            71: #define ECC_FAR0_LOCK  0x00001000      /* Error occurred in attomic cycle */
        !            72: #define ECC_FAR0_BMODE 0x00002000      /* Boot mode */
        !            73: #define ECC_FAR0_VADDR 0x003fc000      /* VA[12-19] (superset bits) */
        !            74: #define ECC_FAR0_S     0x08000000      /* Supervisor mode */
        !            75: #define ECC_FARO_MID   0xf0000000      /* Module ID */
        !            76: 
        !            77: /* ECC diagnostic register */
        !            78: #define ECC_DIAG_CBX   0x00000001
        !            79: #define ECC_DIAG_CB0   0x00000002
        !            80: #define ECC_DIAG_CB1   0x00000004
        !            81: #define ECC_DIAG_CB2   0x00000008
        !            82: #define ECC_DIAG_CB4   0x00000010
        !            83: #define ECC_DIAG_CB8   0x00000020
        !            84: #define ECC_DIAG_CB16  0x00000040
        !            85: #define ECC_DIAG_CB32  0x00000080
        !            86: #define ECC_DIAG_DMODE 0x00000c00
        !            87: 
        !            88: #define ECC_NREGS      8
        !            89: #define ECC_SIZE       (ECC_NREGS * sizeof(uint32_t))
        !            90: #define ECC_ADDR_MASK  (ECC_SIZE - 1)
        !            91: 
        !            92: typedef struct ECCState {
        !            93:     uint32_t regs[ECC_NREGS];
        !            94: } ECCState;
        !            95: 
        !            96: static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
        !            97: {
        !            98:     ECCState *s = opaque;
        !            99: 
        !           100:     switch (addr & ECC_ADDR_MASK) {
        !           101:     case ECC_FCR_REG:
        !           102:         s->regs[0] = (s->regs[0] & (ECC_FCR_VER | ECC_FCR_IMPL)) |
        !           103:                      (val & ~(ECC_FCR_VER | ECC_FCR_IMPL));
        !           104:         DPRINTF("Write fault control %08x\n", val);
        !           105:         break;
        !           106:     case 4:
        !           107:         s->regs[1] =  val;
        !           108:         DPRINTF("Write reg[1] %08x\n", val);
        !           109:         break;
        !           110:     case ECC_FSR_REG:
        !           111:         s->regs[2] =  val;
        !           112:         DPRINTF("Write fault status %08x\n", val);
        !           113:         break;
        !           114:     case 12:
        !           115:         s->regs[3] =  val;
        !           116:         DPRINTF("Write reg[3] %08x\n", val);
        !           117:         break;
        !           118:     case ECC_FAR0_REG:
        !           119:         s->regs[4] =  val;
        !           120:         DPRINTF("Write fault address 0 %08x\n", val);
        !           121:         break;
        !           122:     case ECC_FAR1_REG:
        !           123:         s->regs[5] =  val;
        !           124:         DPRINTF("Write fault address 1 %08x\n", val);
        !           125:         break;
        !           126:     case ECC_DIAG_REG:
        !           127:         s->regs[6] =  val;
        !           128:         DPRINTF("Write diag %08x\n", val);
        !           129:         break;
        !           130:     case 28:
        !           131:         s->regs[7] =  val;
        !           132:         DPRINTF("Write reg[7] %08x\n", val);
        !           133:         break;
        !           134:     }
        !           135: }
        !           136: 
        !           137: static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
        !           138: {
        !           139:     ECCState *s = opaque;
        !           140:     uint32_t ret = 0;
        !           141: 
        !           142:     switch (addr & ECC_ADDR_MASK) {
        !           143:     case ECC_FCR_REG:
        !           144:         ret = s->regs[0];
        !           145:         DPRINTF("Read enable %08x\n", ret);
        !           146:         break;
        !           147:     case 4:
        !           148:         ret = s->regs[1];
        !           149:         DPRINTF("Read register[1] %08x\n", ret);
        !           150:         break;
        !           151:     case ECC_FSR_REG:
        !           152:         ret = s->regs[2];
        !           153:         DPRINTF("Read fault status %08x\n", ret);
        !           154:         break;
        !           155:     case 12:
        !           156:         ret = s->regs[3];
        !           157:         DPRINTF("Read reg[3] %08x\n", ret);
        !           158:         break;
        !           159:     case ECC_FAR0_REG:
        !           160:         ret = s->regs[4];
        !           161:         DPRINTF("Read fault address 0 %08x\n", ret);
        !           162:         break;
        !           163:     case ECC_FAR1_REG:
        !           164:         ret = s->regs[5];
        !           165:         DPRINTF("Read fault address 1 %08x\n", ret);
        !           166:         break;
        !           167:     case ECC_DIAG_REG:
        !           168:         ret = s->regs[6];
        !           169:         DPRINTF("Read diag %08x\n", ret);
        !           170:         break;
        !           171:     case 28:
        !           172:         ret = s->regs[7];
        !           173:         DPRINTF("Read reg[7] %08x\n", ret);
        !           174:         break;
        !           175:     }
        !           176:     return ret;
        !           177: }
        !           178: 
        !           179: static CPUReadMemoryFunc *ecc_mem_read[3] = {
        !           180:     NULL,
        !           181:     NULL,
        !           182:     ecc_mem_readl,
        !           183: };
        !           184: 
        !           185: static CPUWriteMemoryFunc *ecc_mem_write[3] = {
        !           186:     NULL,
        !           187:     NULL,
        !           188:     ecc_mem_writel,
        !           189: };
        !           190: 
        !           191: static int ecc_load(QEMUFile *f, void *opaque, int version_id)
        !           192: {
        !           193:     ECCState *s = opaque;
        !           194:     int i;
        !           195: 
        !           196:     if (version_id != 1)
        !           197:         return -EINVAL;
        !           198: 
        !           199:     for (i = 0; i < ECC_NREGS; i++)
        !           200:         qemu_get_be32s(f, &s->regs[i]);
        !           201: 
        !           202:     return 0;
        !           203: }
        !           204: 
        !           205: static void ecc_save(QEMUFile *f, void *opaque)
        !           206: {
        !           207:     ECCState *s = opaque;
        !           208:     int i;
        !           209: 
        !           210:     for (i = 0; i < ECC_NREGS; i++)
        !           211:         qemu_put_be32s(f, &s->regs[i]);
        !           212: }
        !           213: 
        !           214: static void ecc_reset(void *opaque)
        !           215: {
        !           216:     ECCState *s = opaque;
        !           217:     int i;
        !           218: 
        !           219:     s->regs[ECC_FCR_REG] &= (ECC_FCR_VER | ECC_FCR_IMPL);
        !           220: 
        !           221:     for (i = 1; i < ECC_NREGS; i++)
        !           222:         s->regs[i] = 0;
        !           223: }
        !           224: 
        !           225: void * ecc_init(target_phys_addr_t base, uint32_t version)
        !           226: {
        !           227:     int ecc_io_memory;
        !           228:     ECCState *s;
        !           229: 
        !           230:     s = qemu_mallocz(sizeof(ECCState));
        !           231:     if (!s)
        !           232:         return NULL;
        !           233: 
        !           234:     s->regs[0] = version;
        !           235: 
        !           236:     ecc_io_memory = cpu_register_io_memory(0, ecc_mem_read, ecc_mem_write, s);
        !           237:     cpu_register_physical_memory(base, ECC_SIZE, ecc_io_memory);
        !           238:     register_savevm("ECC", base, 1, ecc_save, ecc_load, s);
        !           239:     qemu_register_reset(ecc_reset, s);
        !           240:     ecc_reset(s);
        !           241:     return s;
        !           242: }

unix.superglobalmegacorp.com

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