static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) { CPUAlphaState *env = cpu_single_env; TyphoonState *s = opaque; CPUState *cpu; uint64_t ret = 0; if (addr & 4) { return s->latch_tmp; } switch (addr) { case 0x0000: /* CSC: Cchip System Configuration Register. */ /* All sorts of data here; probably the only thing relevant is PIP<14> Pchip 1 Present = 0. */ break; case 0x0040: /* MTR: Memory Timing Register. */ /* All sorts of stuff related to real DRAM. */ break; case 0x0080: /* MISC: Miscellaneous Register. */ cpu = ENV_GET_CPU(env); ret = s->cchip.misc | (cpu->cpu_index & 3); break; case 0x00c0: /* MPD: Memory Presence Detect Register. */ break; case 0x0100: /* AAR0 */ case 0x0140: /* AAR1 */ case 0x0180: /* AAR2 */ case 0x01c0: /* AAR3 */ /* AAR: Array Address Register. */ /* All sorts of information about DRAM. */ break; case 0x0200: /* DIM0: Device Interrupt Mask Register, CPU0. */ ret = s->cchip.dim[0]; break; case 0x0240: /* DIM1: Device Interrupt Mask Register, CPU1. */ ret = s->cchip.dim[1]; break; case 0x0280: /* DIR0: Device Interrupt Request Register, CPU0. */ ret = s->cchip.dim[0] & s->cchip.drir; break; case 0x02c0: /* DIR1: Device Interrupt Request Register, CPU1. */ ret = s->cchip.dim[1] & s->cchip.drir; break; case 0x0300: /* DRIR: Device Raw Interrupt Request Register. */ ret = s->cchip.drir; break; case 0x0340: /* PRBEN: Probe Enable Register. */ break; case 0x0380: /* IIC0: Interval Ignore Count Register, CPU0. */ ret = s->cchip.iic[0]; break; case 0x03c0: /* IIC1: Interval Ignore Count Register, CPU1. */ ret = s->cchip.iic[1]; break; case 0x0400: /* MPR0 */ case 0x0440: /* MPR1 */ case 0x0480: /* MPR2 */ case 0x04c0: /* MPR3 */ /* MPR: Memory Programming Register. */ break; case 0x0580: /* TTR: TIGbus Timing Register. */ /* All sorts of stuff related to interrupt delivery timings. */ break; case 0x05c0: /* TDR: TIGbug Device Timing Register. */ break; case 0x0600: /* DIM2: Device Interrupt Mask Register, CPU2. */ ret = s->cchip.dim[2]; break; case 0x0640: /* DIM3: Device Interrupt Mask Register, CPU3. */ ret = s->cchip.dim[3]; break; case 0x0680: /* DIR2: Device Interrupt Request Register, CPU2. */ ret = s->cchip.dim[2] & s->cchip.drir; break; case 0x06c0: /* DIR3: Device Interrupt Request Register, CPU3. */ ret = s->cchip.dim[3] & s->cchip.drir; break; case 0x0700: /* IIC2: Interval Ignore Count Register, CPU2. */ ret = s->cchip.iic[2]; break; case 0x0740: /* IIC3: Interval Ignore Count Register, CPU3. */ ret = s->cchip.iic[3]; break; case 0x0780: /* PWR: Power Management Control. */ break; case 0x0c00: /* CMONCTLA */ case 0x0c40: /* CMONCTLB */ case 0x0c80: /* CMONCNT01 */ case 0x0cc0: /* CMONCNT23 */ break; default: cpu = CPU(alpha_env_get_cpu(cpu_single_env)); cpu_unassigned_access(cpu, addr, false, false, 0, size); return -1; } s->latch_tmp = ret >> 32; return ret; }
static void pchip_write(void *opaque, hwaddr addr, uint64_t v32, unsigned size) { TyphoonState *s = opaque; CPUState *cs; uint64_t val, oldval; if (addr & 4) { val = v32 << 32 | s->latch_tmp; addr ^= 4; } else { s->latch_tmp = v32; return; } switch (addr) { case 0x0000: /* WSBA0: Window Space Base Address Register. */ s->pchip.win[0].base_addr = val; break; case 0x0040: /* WSBA1 */ s->pchip.win[1].base_addr = val; break; case 0x0080: /* WSBA2 */ s->pchip.win[2].base_addr = val; break; case 0x00c0: /* WSBA3 */ s->pchip.win[3].base_addr = val; break; case 0x0100: /* WSM0: Window Space Mask Register. */ s->pchip.win[0].mask = val; break; case 0x0140: /* WSM1 */ s->pchip.win[1].mask = val; break; case 0x0180: /* WSM2 */ s->pchip.win[2].mask = val; break; case 0x01c0: /* WSM3 */ s->pchip.win[3].mask = val; break; case 0x0200: /* TBA0: Translated Base Address Register. */ s->pchip.win[0].translated_base_pfn = val >> 10; break; case 0x0240: /* TBA1 */ s->pchip.win[1].translated_base_pfn = val >> 10; break; case 0x0280: /* TBA2 */ s->pchip.win[2].translated_base_pfn = val >> 10; break; case 0x02c0: /* TBA3 */ s->pchip.win[3].translated_base_pfn = val >> 10; break; case 0x0300: /* PCTL: Pchip Control Register. */ oldval = s->pchip.ctl; oldval &= ~0x00001cff0fc7ffull; /* RW fields */ oldval |= val & 0x00001cff0fc7ffull; s->pchip.ctl = oldval; break; case 0x0340: /* PLAT: Pchip Master Latency Register. */ break; case 0x03c0: /* PERROR: Pchip Error Register. */ break; case 0x0400: /* PERRMASK: Pchip Error Mask Register. */ break; case 0x0440: /* PERRSET: Pchip Error Set Register. */ break; case 0x0480: /* TLBIV: Translation Buffer Invalidate Virtual Register. */ break; case 0x04c0: /* TLBIA: Translation Buffer Invalidate All Register (WO). */ break; case 0x0500: /* PMONCTL */ case 0x0540: /* PMONCNT */ case 0x0800: /* SPRST */ break; default: cs = CPU(alpha_env_get_cpu(cpu_single_env)); cpu_unassigned_access(cs, addr, true, false, 0, size); return; } }
static void cchip_write(void *opaque, hwaddr addr, uint64_t v32, unsigned size) { TyphoonState *s = opaque; CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env)); uint64_t val, oldval, newval; if (addr & 4) { val = v32 << 32 | s->latch_tmp; addr ^= 4; } else { s->latch_tmp = v32; return; } switch (addr) { case 0x0000: /* CSC: Cchip System Configuration Register. */ /* All sorts of data here; nothing relevant RW. */ break; case 0x0040: /* MTR: Memory Timing Register. */ /* All sorts of stuff related to real DRAM. */ break; case 0x0080: /* MISC: Miscellaneous Register. */ newval = oldval = s->cchip.misc; newval &= ~(val & 0x10000ff0); /* W1C fields */ if (val & 0x100000) { newval &= ~0xff0000ull; /* ACL clears ABT and ABW */ } else { newval |= val & 0x00f00000; /* ABT field is W1S */ if ((newval & 0xf0000) == 0) { newval |= val & 0xf0000; /* ABW field is W1S iff zero */ } } newval |= (val & 0xf000) >> 4; /* IPREQ field sets IPINTR. */ newval &= ~0xf0000000000ull; /* WO and RW fields */ newval |= val & 0xf0000000000ull; s->cchip.misc = newval; /* Pass on changes to IPI and ITI state. */ if ((newval ^ oldval) & 0xff0) { int i; for (i = 0; i < 4; ++i) { AlphaCPU *cpu = s->cchip.cpu[i]; if (cpu != NULL) { CPUState *cs = CPU(cpu); /* IPI can be either cleared or set by the write. */ if (newval & (1 << (i + 8))) { cpu_interrupt(cs, CPU_INTERRUPT_SMP); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP); } /* ITI can only be cleared by the write. */ if ((newval & (1 << (i + 4))) == 0) { cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER); } } } } break; case 0x00c0: /* MPD: Memory Presence Detect Register. */ break; case 0x0100: /* AAR0 */ case 0x0140: /* AAR1 */ case 0x0180: /* AAR2 */ case 0x01c0: /* AAR3 */ /* AAR: Array Address Register. */ /* All sorts of information about DRAM. */ break; case 0x0200: /* DIM0 */ /* DIM: Device Interrupt Mask Register, CPU0. */ s->cchip.dim[0] = val; cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir); break; case 0x0240: /* DIM1 */ /* DIM: Device Interrupt Mask Register, CPU1. */ s->cchip.dim[0] = val; cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir); break; case 0x0280: /* DIR0 (RO) */ case 0x02c0: /* DIR1 (RO) */ case 0x0300: /* DRIR (RO) */ break; case 0x0340: /* PRBEN: Probe Enable Register. */ break; case 0x0380: /* IIC0 */ s->cchip.iic[0] = val & 0xffffff; break; case 0x03c0: /* IIC1 */ s->cchip.iic[1] = val & 0xffffff; break; case 0x0400: /* MPR0 */ case 0x0440: /* MPR1 */ case 0x0480: /* MPR2 */ case 0x04c0: /* MPR3 */ /* MPR: Memory Programming Register. */ break; case 0x0580: /* TTR: TIGbus Timing Register. */ /* All sorts of stuff related to interrupt delivery timings. */ break; case 0x05c0: /* TDR: TIGbug Device Timing Register. */ break; case 0x0600: /* DIM2: Device Interrupt Mask Register, CPU2. */ s->cchip.dim[2] = val; cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir); break; case 0x0640: /* DIM3: Device Interrupt Mask Register, CPU3. */ s->cchip.dim[3] = val; cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir); break; case 0x0680: /* DIR2 (RO) */ case 0x06c0: /* DIR3 (RO) */ break; case 0x0700: /* IIC2 */ s->cchip.iic[2] = val & 0xffffff; break; case 0x0740: /* IIC3 */ s->cchip.iic[3] = val & 0xffffff; break; case 0x0780: /* PWR: Power Management Control. */ break; case 0x0c00: /* CMONCTLA */ case 0x0c40: /* CMONCTLB */ case 0x0c80: /* CMONCNT01 */ case 0x0cc0: /* CMONCNT23 */ break; default: cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size); return; } }
static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) { TyphoonState *s = opaque; CPUState *cs; uint64_t ret = 0; if (addr & 4) { return s->latch_tmp; } switch (addr) { case 0x0000: /* WSBA0: Window Space Base Address Register. */ ret = s->pchip.win[0].base_addr; break; case 0x0040: /* WSBA1 */ ret = s->pchip.win[1].base_addr; break; case 0x0080: /* WSBA2 */ ret = s->pchip.win[2].base_addr; break; case 0x00c0: /* WSBA3 */ ret = s->pchip.win[3].base_addr; break; case 0x0100: /* WSM0: Window Space Mask Register. */ ret = s->pchip.win[0].mask; break; case 0x0140: /* WSM1 */ ret = s->pchip.win[1].mask; break; case 0x0180: /* WSM2 */ ret = s->pchip.win[2].mask; break; case 0x01c0: /* WSM3 */ ret = s->pchip.win[3].mask; break; case 0x0200: /* TBA0: Translated Base Address Register. */ ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10; break; case 0x0240: /* TBA1 */ ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10; break; case 0x0280: /* TBA2 */ ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10; break; case 0x02c0: /* TBA3 */ ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10; break; case 0x0300: /* PCTL: Pchip Control Register. */ ret = s->pchip.ctl; break; case 0x0340: /* PLAT: Pchip Master Latency Register. */ break; case 0x03c0: /* PERROR: Pchip Error Register. */ break; case 0x0400: /* PERRMASK: Pchip Error Mask Register. */ break; case 0x0440: /* PERRSET: Pchip Error Set Register. */ break; case 0x0480: /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */ break; case 0x04c0: /* TLBIA: Translation Buffer Invalidate All Register (WO). */ break; case 0x0500: /* PMONCTL */ case 0x0540: /* PMONCNT */ case 0x0800: /* SPRST */ break; default: cs = CPU(alpha_env_get_cpu(cpu_single_env)); cpu_unassigned_access(cs, addr, false, false, 0, size); return -1; } s->latch_tmp = ret >> 32; return ret; }
static void pchip_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { TyphoonState *s = opaque; uint64_t oldval; switch (addr) { case 0x0000: /* WSBA0: Window Space Base Address Register. */ s->pchip.win[0].wba = val & 0xfff00003u; break; case 0x0040: /* WSBA1 */ s->pchip.win[1].wba = val & 0xfff00003u; break; case 0x0080: /* WSBA2 */ s->pchip.win[2].wba = val & 0xfff00003u; break; case 0x00c0: /* WSBA3 */ s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2; break; case 0x0100: /* WSM0: Window Space Mask Register. */ s->pchip.win[0].wsm = val & 0xfff00000u; break; case 0x0140: /* WSM1 */ s->pchip.win[1].wsm = val & 0xfff00000u; break; case 0x0180: /* WSM2 */ s->pchip.win[2].wsm = val & 0xfff00000u; break; case 0x01c0: /* WSM3 */ s->pchip.win[3].wsm = val & 0xfff00000u; break; case 0x0200: /* TBA0: Translated Base Address Register. */ s->pchip.win[0].tba = val & 0x7fffffc00ull; break; case 0x0240: /* TBA1 */ s->pchip.win[1].tba = val & 0x7fffffc00ull; break; case 0x0280: /* TBA2 */ s->pchip.win[2].tba = val & 0x7fffffc00ull; break; case 0x02c0: /* TBA3 */ s->pchip.win[3].tba = val & 0x7fffffc00ull; break; case 0x0300: /* PCTL: Pchip Control Register. */ oldval = s->pchip.ctl; oldval &= ~0x00001cff0fc7ffull; /* RW fields */ oldval |= val & 0x00001cff0fc7ffull; s->pchip.ctl = oldval; break; case 0x0340: /* PLAT: Pchip Master Latency Register. */ break; case 0x03c0: /* PERROR: Pchip Error Register. */ break; case 0x0400: /* PERRMASK: Pchip Error Mask Register. */ break; case 0x0440: /* PERRSET: Pchip Error Set Register. */ break; case 0x0480: /* TLBIV: Translation Buffer Invalidate Virtual Register. */ break; case 0x04c0: /* TLBIA: Translation Buffer Invalidate All Register (WO). */ break; case 0x0500: /* PMONCTL */ case 0x0540: /* PMONCNT */ case 0x0800: /* SPRST */ break; default: cpu_unassigned_access(current_cpu, addr, true, false, 0, size); return; } }
static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) { TyphoonState *s = opaque; uint64_t ret = 0; switch (addr) { case 0x0000: /* WSBA0: Window Space Base Address Register. */ ret = s->pchip.win[0].wba; break; case 0x0040: /* WSBA1 */ ret = s->pchip.win[1].wba; break; case 0x0080: /* WSBA2 */ ret = s->pchip.win[2].wba; break; case 0x00c0: /* WSBA3 */ ret = s->pchip.win[3].wba; break; case 0x0100: /* WSM0: Window Space Mask Register. */ ret = s->pchip.win[0].wsm; break; case 0x0140: /* WSM1 */ ret = s->pchip.win[1].wsm; break; case 0x0180: /* WSM2 */ ret = s->pchip.win[2].wsm; break; case 0x01c0: /* WSM3 */ ret = s->pchip.win[3].wsm; break; case 0x0200: /* TBA0: Translated Base Address Register. */ ret = s->pchip.win[0].tba; break; case 0x0240: /* TBA1 */ ret = s->pchip.win[1].tba; break; case 0x0280: /* TBA2 */ ret = s->pchip.win[2].tba; break; case 0x02c0: /* TBA3 */ ret = s->pchip.win[3].tba; break; case 0x0300: /* PCTL: Pchip Control Register. */ ret = s->pchip.ctl; break; case 0x0340: /* PLAT: Pchip Master Latency Register. */ break; case 0x03c0: /* PERROR: Pchip Error Register. */ break; case 0x0400: /* PERRMASK: Pchip Error Mask Register. */ break; case 0x0440: /* PERRSET: Pchip Error Set Register. */ break; case 0x0480: /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */ break; case 0x04c0: /* TLBIA: Translation Buffer Invalidate All Register (WO). */ break; case 0x0500: /* PMONCTL */ case 0x0540: /* PMONCNT */ case 0x0800: /* SPRST */ break; default: cpu_unassigned_access(current_cpu, addr, false, false, 0, size); return -1; } return ret; }