Commit 0bb3602c44b73c647b8a478d7077192a576b5781
1 parent
963262de
Implement hw/eccmemctl.c version differences (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6124 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
10 deletions
hw/eccmemctl.c
| ... | ... | @@ -40,6 +40,10 @@ |
| 40 | 40 | * SMC (version 0, implementation 2) SS-10SX and SS-20 |
| 41 | 41 | */ |
| 42 | 42 | |
| 43 | +#define ECC_MCC 0x00000000 | |
| 44 | +#define ECC_EMC 0x10000000 | |
| 45 | +#define ECC_SMC 0x20000000 | |
| 46 | + | |
| 43 | 47 | /* Register indexes */ |
| 44 | 48 | #define ECC_MER 0 /* Memory Enable Register */ |
| 45 | 49 | #define ECC_MDR 1 /* Memory Delay Register */ |
| ... | ... | @@ -63,12 +67,15 @@ |
| 63 | 67 | #define ECC_MER_MRR5 0x00000080 /* SIMM 5 */ |
| 64 | 68 | #define ECC_MER_MRR6 0x00000100 /* SIMM 6 */ |
| 65 | 69 | #define ECC_MER_MRR7 0x00000200 /* SIMM 7 */ |
| 66 | -#define ECC_MER_REU 0x00000200 /* Memory Refresh Enable (600MP) */ | |
| 70 | +#define ECC_MER_REU 0x00000100 /* Memory Refresh Enable (600MP) */ | |
| 67 | 71 | #define ECC_MER_MRR 0x000003fc /* MRR mask */ |
| 68 | -#define ECC_MEM_A 0x00000400 /* Memory controller addr map select */ | |
| 72 | +#define ECC_MER_A 0x00000400 /* Memory controller addr map select */ | |
| 69 | 73 | #define ECC_MER_DCI 0x00000800 /* Disables Coherent Invalidate ACK */ |
| 70 | 74 | #define ECC_MER_VER 0x0f000000 /* Version */ |
| 71 | 75 | #define ECC_MER_IMPL 0xf0000000 /* Implementation */ |
| 76 | +#define ECC_MER_MASK_0 0x00000103 /* Version 0 (MCC) mask */ | |
| 77 | +#define ECC_MER_MASK_1 0x00000bff /* Version 1 (EMC) mask */ | |
| 78 | +#define ECC_MER_MASK_2 0x00000bff /* Version 2 (SMC) mask */ | |
| 72 | 79 | |
| 73 | 80 | /* ECC memory delay register */ |
| 74 | 81 | #define ECC_MDR_RRI 0x000003ff /* Refresh Request Interval */ |
| ... | ... | @@ -122,6 +129,7 @@ typedef struct ECCState { |
| 122 | 129 | qemu_irq irq; |
| 123 | 130 | uint32_t regs[ECC_NREGS]; |
| 124 | 131 | uint8_t diag[ECC_DIAG_SIZE]; |
| 132 | + uint32_t version; | |
| 125 | 133 | } ECCState; |
| 126 | 134 | |
| 127 | 135 | static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
| ... | ... | @@ -130,8 +138,12 @@ static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 130 | 138 | |
| 131 | 139 | switch (addr >> 2) { |
| 132 | 140 | case ECC_MER: |
| 133 | - s->regs[ECC_MER] = (s->regs[ECC_MER] & (ECC_MER_VER | ECC_MER_IMPL)) | | |
| 134 | - (val & ~(ECC_MER_VER | ECC_MER_IMPL)); | |
| 141 | + if (s->version == ECC_MCC) | |
| 142 | + s->regs[ECC_MER] = (val & ECC_MER_MASK_0); | |
| 143 | + else if (s->version == ECC_EMC) | |
| 144 | + s->regs[ECC_MER] = s->version | (val & ECC_MER_MASK_1); | |
| 145 | + else if (s->version == ECC_SMC) | |
| 146 | + s->regs[ECC_MER] = s->version | (val & ECC_MER_MASK_2); | |
| 135 | 147 | DPRINTF("Write memory enable %08x\n", val); |
| 136 | 148 | break; |
| 137 | 149 | case ECC_MDR: |
| ... | ... | @@ -140,6 +152,7 @@ static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 140 | 152 | break; |
| 141 | 153 | case ECC_MFSR: |
| 142 | 154 | s->regs[ECC_MFSR] = val; |
| 155 | + qemu_irq_lower(s->irq); | |
| 143 | 156 | DPRINTF("Write memory fault status %08x\n", val); |
| 144 | 157 | break; |
| 145 | 158 | case ECC_VCR: |
| ... | ... | @@ -148,7 +161,7 @@ static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 148 | 161 | break; |
| 149 | 162 | case ECC_DR: |
| 150 | 163 | s->regs[ECC_DR] = val; |
| 151 | - DPRINTF("Write diagnosiic %08x\n", val); | |
| 164 | + DPRINTF("Write diagnostic %08x\n", val); | |
| 152 | 165 | break; |
| 153 | 166 | case ECC_ECR0: |
| 154 | 167 | s->regs[ECC_ECR0] = val; |
| ... | ... | @@ -254,7 +267,7 @@ static int ecc_load(QEMUFile *f, void *opaque, int version_id) |
| 254 | 267 | ECCState *s = opaque; |
| 255 | 268 | int i; |
| 256 | 269 | |
| 257 | - if (version_id != 2) | |
| 270 | + if (version_id != 3) | |
| 258 | 271 | return -EINVAL; |
| 259 | 272 | |
| 260 | 273 | for (i = 0; i < ECC_NREGS; i++) |
| ... | ... | @@ -263,6 +276,8 @@ static int ecc_load(QEMUFile *f, void *opaque, int version_id) |
| 263 | 276 | for (i = 0; i < ECC_DIAG_SIZE; i++) |
| 264 | 277 | qemu_get_8s(f, &s->diag[i]); |
| 265 | 278 | |
| 279 | + qemu_get_be32s(f, &s->version); | |
| 280 | + | |
| 266 | 281 | return 0; |
| 267 | 282 | } |
| 268 | 283 | |
| ... | ... | @@ -276,14 +291,19 @@ static void ecc_save(QEMUFile *f, void *opaque) |
| 276 | 291 | |
| 277 | 292 | for (i = 0; i < ECC_DIAG_SIZE; i++) |
| 278 | 293 | qemu_put_8s(f, &s->diag[i]); |
| 294 | + | |
| 295 | + qemu_put_be32s(f, &s->version); | |
| 279 | 296 | } |
| 280 | 297 | |
| 281 | 298 | static void ecc_reset(void *opaque) |
| 282 | 299 | { |
| 283 | 300 | ECCState *s = opaque; |
| 284 | 301 | |
| 285 | - s->regs[ECC_MER] &= (ECC_MER_VER | ECC_MER_IMPL); | |
| 286 | - s->regs[ECC_MER] |= ECC_MER_MRR; | |
| 302 | + if (s->version == ECC_MCC) | |
| 303 | + s->regs[ECC_MER] &= ECC_MER_REU; | |
| 304 | + else | |
| 305 | + s->regs[ECC_MER] &= (ECC_MER_VER | ECC_MER_IMPL | ECC_MER_MRR | | |
| 306 | + ECC_MER_DCI); | |
| 287 | 307 | s->regs[ECC_MDR] = 0x20; |
| 288 | 308 | s->regs[ECC_MFSR] = 0; |
| 289 | 309 | s->regs[ECC_VCR] = 0; |
| ... | ... | @@ -303,18 +323,19 @@ void * ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) |
| 303 | 323 | if (!s) |
| 304 | 324 | return NULL; |
| 305 | 325 | |
| 326 | + s->version = version; | |
| 306 | 327 | s->regs[0] = version; |
| 307 | 328 | s->irq = irq; |
| 308 | 329 | |
| 309 | 330 | ecc_io_memory = cpu_register_io_memory(0, ecc_mem_read, ecc_mem_write, s); |
| 310 | 331 | cpu_register_physical_memory(base, ECC_SIZE, ecc_io_memory); |
| 311 | - if (version == 0) { // SS-600MP only | |
| 332 | + if (version == ECC_MCC) { // SS-600MP only | |
| 312 | 333 | ecc_io_memory = cpu_register_io_memory(0, ecc_diag_mem_read, |
| 313 | 334 | ecc_diag_mem_write, s); |
| 314 | 335 | cpu_register_physical_memory(base + 0x1000, ECC_DIAG_SIZE, |
| 315 | 336 | ecc_io_memory); |
| 316 | 337 | } |
| 317 | - register_savevm("ECC", base, 2, ecc_save, ecc_load, s); | |
| 338 | + register_savevm("ECC", base, 3, ecc_save, ecc_load, s); | |
| 318 | 339 | qemu_register_reset(ecc_reset, s); |
| 319 | 340 | ecc_reset(s); |
| 320 | 341 | return s; | ... | ... |