180bb2ff7SRichard Henderson /* 280bb2ff7SRichard Henderson * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation. 380bb2ff7SRichard Henderson * 480bb2ff7SRichard Henderson * Written by Richard Henderson. 580bb2ff7SRichard Henderson * 680bb2ff7SRichard Henderson * This work is licensed under the GNU GPL license version 2 or later. 780bb2ff7SRichard Henderson */ 880bb2ff7SRichard Henderson 980bb2ff7SRichard Henderson #include "cpu.h" 10022c62cbSPaolo Bonzini #include "exec/exec-all.h" 1183c9f4caSPaolo Bonzini #include "hw/hw.h" 12*bd2be150SPeter Maydell #include "hw/devices.h" 139c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 1447b43a1fSPaolo Bonzini #include "alpha_sys.h" 15022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 1680bb2ff7SRichard Henderson 1780bb2ff7SRichard Henderson 1894dd91d6SAndreas Färber #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" 1994dd91d6SAndreas Färber 2080bb2ff7SRichard Henderson typedef struct TyphoonCchip { 2180bb2ff7SRichard Henderson MemoryRegion region; 2280bb2ff7SRichard Henderson uint64_t misc; 2380bb2ff7SRichard Henderson uint64_t drir; 2480bb2ff7SRichard Henderson uint64_t dim[4]; 2580bb2ff7SRichard Henderson uint32_t iic[4]; 26ad601177SAndreas Färber AlphaCPU *cpu[4]; 2780bb2ff7SRichard Henderson } TyphoonCchip; 2880bb2ff7SRichard Henderson 2980bb2ff7SRichard Henderson typedef struct TyphoonWindow { 3080bb2ff7SRichard Henderson uint32_t base_addr; 3180bb2ff7SRichard Henderson uint32_t mask; 3280bb2ff7SRichard Henderson uint32_t translated_base_pfn; 3380bb2ff7SRichard Henderson } TyphoonWindow; 3480bb2ff7SRichard Henderson 3580bb2ff7SRichard Henderson typedef struct TyphoonPchip { 3680bb2ff7SRichard Henderson MemoryRegion region; 3780bb2ff7SRichard Henderson MemoryRegion reg_iack; 3880bb2ff7SRichard Henderson MemoryRegion reg_mem; 3980bb2ff7SRichard Henderson MemoryRegion reg_io; 4080bb2ff7SRichard Henderson MemoryRegion reg_conf; 4180bb2ff7SRichard Henderson uint64_t ctl; 4280bb2ff7SRichard Henderson TyphoonWindow win[4]; 4380bb2ff7SRichard Henderson } TyphoonPchip; 4480bb2ff7SRichard Henderson 4594dd91d6SAndreas Färber #define TYPHOON_PCI_HOST_BRIDGE(obj) \ 4694dd91d6SAndreas Färber OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE) 4794dd91d6SAndreas Färber 4880bb2ff7SRichard Henderson typedef struct TyphoonState { 4967c332fdSAndreas Färber PCIHostState parent_obj; 5094dd91d6SAndreas Färber 5180bb2ff7SRichard Henderson TyphoonCchip cchip; 5280bb2ff7SRichard Henderson TyphoonPchip pchip; 5380bb2ff7SRichard Henderson MemoryRegion dchip_region; 5480bb2ff7SRichard Henderson MemoryRegion ram_region; 5580bb2ff7SRichard Henderson 5680bb2ff7SRichard Henderson /* QEMU emulation state. */ 5780bb2ff7SRichard Henderson uint32_t latch_tmp; 5880bb2ff7SRichard Henderson } TyphoonState; 5980bb2ff7SRichard Henderson 6080bb2ff7SRichard Henderson /* Called when one of DRIR or DIM changes. */ 61ad601177SAndreas Färber static void cpu_irq_change(AlphaCPU *cpu, uint64_t req) 6280bb2ff7SRichard Henderson { 6380bb2ff7SRichard Henderson /* If there are any non-masked interrupts, tell the cpu. */ 64ad601177SAndreas Färber if (cpu != NULL) { 65d8ed887bSAndreas Färber CPUState *cs = CPU(cpu); 6680bb2ff7SRichard Henderson if (req) { 67c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_HARD); 6880bb2ff7SRichard Henderson } else { 69d8ed887bSAndreas Färber cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 7080bb2ff7SRichard Henderson } 7180bb2ff7SRichard Henderson } 7280bb2ff7SRichard Henderson } 7380bb2ff7SRichard Henderson 74a8170e5eSAvi Kivity static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) 7580bb2ff7SRichard Henderson { 768b2aee29SAndreas Färber CPUAlphaState *env = cpu_single_env; 7780bb2ff7SRichard Henderson TyphoonState *s = opaque; 7855e5c285SAndreas Färber CPUState *cpu; 7980bb2ff7SRichard Henderson uint64_t ret = 0; 8080bb2ff7SRichard Henderson 8180bb2ff7SRichard Henderson if (addr & 4) { 8280bb2ff7SRichard Henderson return s->latch_tmp; 8380bb2ff7SRichard Henderson } 8480bb2ff7SRichard Henderson 8580bb2ff7SRichard Henderson switch (addr) { 8680bb2ff7SRichard Henderson case 0x0000: 8780bb2ff7SRichard Henderson /* CSC: Cchip System Configuration Register. */ 8880bb2ff7SRichard Henderson /* All sorts of data here; probably the only thing relevant is 8980bb2ff7SRichard Henderson PIP<14> Pchip 1 Present = 0. */ 9080bb2ff7SRichard Henderson break; 9180bb2ff7SRichard Henderson 9280bb2ff7SRichard Henderson case 0x0040: 9380bb2ff7SRichard Henderson /* MTR: Memory Timing Register. */ 9480bb2ff7SRichard Henderson /* All sorts of stuff related to real DRAM. */ 9580bb2ff7SRichard Henderson break; 9680bb2ff7SRichard Henderson 9780bb2ff7SRichard Henderson case 0x0080: 9880bb2ff7SRichard Henderson /* MISC: Miscellaneous Register. */ 9955e5c285SAndreas Färber cpu = ENV_GET_CPU(env); 10055e5c285SAndreas Färber ret = s->cchip.misc | (cpu->cpu_index & 3); 10180bb2ff7SRichard Henderson break; 10280bb2ff7SRichard Henderson 10380bb2ff7SRichard Henderson case 0x00c0: 10480bb2ff7SRichard Henderson /* MPD: Memory Presence Detect Register. */ 10580bb2ff7SRichard Henderson break; 10680bb2ff7SRichard Henderson 10780bb2ff7SRichard Henderson case 0x0100: /* AAR0 */ 10880bb2ff7SRichard Henderson case 0x0140: /* AAR1 */ 10980bb2ff7SRichard Henderson case 0x0180: /* AAR2 */ 11080bb2ff7SRichard Henderson case 0x01c0: /* AAR3 */ 11180bb2ff7SRichard Henderson /* AAR: Array Address Register. */ 11280bb2ff7SRichard Henderson /* All sorts of information about DRAM. */ 11380bb2ff7SRichard Henderson break; 11480bb2ff7SRichard Henderson 11580bb2ff7SRichard Henderson case 0x0200: 11680bb2ff7SRichard Henderson /* DIM0: Device Interrupt Mask Register, CPU0. */ 11780bb2ff7SRichard Henderson ret = s->cchip.dim[0]; 11880bb2ff7SRichard Henderson break; 11980bb2ff7SRichard Henderson case 0x0240: 12080bb2ff7SRichard Henderson /* DIM1: Device Interrupt Mask Register, CPU1. */ 12180bb2ff7SRichard Henderson ret = s->cchip.dim[1]; 12280bb2ff7SRichard Henderson break; 12380bb2ff7SRichard Henderson case 0x0280: 12480bb2ff7SRichard Henderson /* DIR0: Device Interrupt Request Register, CPU0. */ 12580bb2ff7SRichard Henderson ret = s->cchip.dim[0] & s->cchip.drir; 12680bb2ff7SRichard Henderson break; 12780bb2ff7SRichard Henderson case 0x02c0: 12880bb2ff7SRichard Henderson /* DIR1: Device Interrupt Request Register, CPU1. */ 12980bb2ff7SRichard Henderson ret = s->cchip.dim[1] & s->cchip.drir; 13080bb2ff7SRichard Henderson break; 13180bb2ff7SRichard Henderson case 0x0300: 13280bb2ff7SRichard Henderson /* DRIR: Device Raw Interrupt Request Register. */ 13380bb2ff7SRichard Henderson ret = s->cchip.drir; 13480bb2ff7SRichard Henderson break; 13580bb2ff7SRichard Henderson 13680bb2ff7SRichard Henderson case 0x0340: 13780bb2ff7SRichard Henderson /* PRBEN: Probe Enable Register. */ 13880bb2ff7SRichard Henderson break; 13980bb2ff7SRichard Henderson 14080bb2ff7SRichard Henderson case 0x0380: 14180bb2ff7SRichard Henderson /* IIC0: Interval Ignore Count Register, CPU0. */ 14280bb2ff7SRichard Henderson ret = s->cchip.iic[0]; 14380bb2ff7SRichard Henderson break; 14480bb2ff7SRichard Henderson case 0x03c0: 14580bb2ff7SRichard Henderson /* IIC1: Interval Ignore Count Register, CPU1. */ 14680bb2ff7SRichard Henderson ret = s->cchip.iic[1]; 14780bb2ff7SRichard Henderson break; 14880bb2ff7SRichard Henderson 14980bb2ff7SRichard Henderson case 0x0400: /* MPR0 */ 15080bb2ff7SRichard Henderson case 0x0440: /* MPR1 */ 15180bb2ff7SRichard Henderson case 0x0480: /* MPR2 */ 15280bb2ff7SRichard Henderson case 0x04c0: /* MPR3 */ 15380bb2ff7SRichard Henderson /* MPR: Memory Programming Register. */ 15480bb2ff7SRichard Henderson break; 15580bb2ff7SRichard Henderson 15680bb2ff7SRichard Henderson case 0x0580: 15780bb2ff7SRichard Henderson /* TTR: TIGbus Timing Register. */ 15880bb2ff7SRichard Henderson /* All sorts of stuff related to interrupt delivery timings. */ 15980bb2ff7SRichard Henderson break; 16080bb2ff7SRichard Henderson case 0x05c0: 16180bb2ff7SRichard Henderson /* TDR: TIGbug Device Timing Register. */ 16280bb2ff7SRichard Henderson break; 16380bb2ff7SRichard Henderson 16480bb2ff7SRichard Henderson case 0x0600: 16580bb2ff7SRichard Henderson /* DIM2: Device Interrupt Mask Register, CPU2. */ 16680bb2ff7SRichard Henderson ret = s->cchip.dim[2]; 16780bb2ff7SRichard Henderson break; 16880bb2ff7SRichard Henderson case 0x0640: 16980bb2ff7SRichard Henderson /* DIM3: Device Interrupt Mask Register, CPU3. */ 17080bb2ff7SRichard Henderson ret = s->cchip.dim[3]; 17180bb2ff7SRichard Henderson break; 17280bb2ff7SRichard Henderson case 0x0680: 17380bb2ff7SRichard Henderson /* DIR2: Device Interrupt Request Register, CPU2. */ 17480bb2ff7SRichard Henderson ret = s->cchip.dim[2] & s->cchip.drir; 17580bb2ff7SRichard Henderson break; 17680bb2ff7SRichard Henderson case 0x06c0: 17780bb2ff7SRichard Henderson /* DIR3: Device Interrupt Request Register, CPU3. */ 17880bb2ff7SRichard Henderson ret = s->cchip.dim[3] & s->cchip.drir; 17980bb2ff7SRichard Henderson break; 18080bb2ff7SRichard Henderson 18180bb2ff7SRichard Henderson case 0x0700: 18280bb2ff7SRichard Henderson /* IIC2: Interval Ignore Count Register, CPU2. */ 18380bb2ff7SRichard Henderson ret = s->cchip.iic[2]; 18480bb2ff7SRichard Henderson break; 18580bb2ff7SRichard Henderson case 0x0740: 18680bb2ff7SRichard Henderson /* IIC3: Interval Ignore Count Register, CPU3. */ 18780bb2ff7SRichard Henderson ret = s->cchip.iic[3]; 18880bb2ff7SRichard Henderson break; 18980bb2ff7SRichard Henderson 19080bb2ff7SRichard Henderson case 0x0780: 19180bb2ff7SRichard Henderson /* PWR: Power Management Control. */ 19280bb2ff7SRichard Henderson break; 19380bb2ff7SRichard Henderson 19480bb2ff7SRichard Henderson case 0x0c00: /* CMONCTLA */ 19580bb2ff7SRichard Henderson case 0x0c40: /* CMONCTLB */ 19680bb2ff7SRichard Henderson case 0x0c80: /* CMONCNT01 */ 19780bb2ff7SRichard Henderson case 0x0cc0: /* CMONCNT23 */ 19880bb2ff7SRichard Henderson break; 19980bb2ff7SRichard Henderson 20080bb2ff7SRichard Henderson default: 20180bb2ff7SRichard Henderson cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size); 20280bb2ff7SRichard Henderson return -1; 20380bb2ff7SRichard Henderson } 20480bb2ff7SRichard Henderson 20580bb2ff7SRichard Henderson s->latch_tmp = ret >> 32; 20680bb2ff7SRichard Henderson return ret; 20780bb2ff7SRichard Henderson } 20880bb2ff7SRichard Henderson 209a8170e5eSAvi Kivity static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size) 21080bb2ff7SRichard Henderson { 21180bb2ff7SRichard Henderson /* Skip this. It's all related to DRAM timing and setup. */ 21280bb2ff7SRichard Henderson return 0; 21380bb2ff7SRichard Henderson } 21480bb2ff7SRichard Henderson 215a8170e5eSAvi Kivity static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) 21680bb2ff7SRichard Henderson { 21780bb2ff7SRichard Henderson TyphoonState *s = opaque; 21880bb2ff7SRichard Henderson uint64_t ret = 0; 21980bb2ff7SRichard Henderson 22080bb2ff7SRichard Henderson if (addr & 4) { 22180bb2ff7SRichard Henderson return s->latch_tmp; 22280bb2ff7SRichard Henderson } 22380bb2ff7SRichard Henderson 22480bb2ff7SRichard Henderson switch (addr) { 22580bb2ff7SRichard Henderson case 0x0000: 22680bb2ff7SRichard Henderson /* WSBA0: Window Space Base Address Register. */ 22780bb2ff7SRichard Henderson ret = s->pchip.win[0].base_addr; 22880bb2ff7SRichard Henderson break; 22980bb2ff7SRichard Henderson case 0x0040: 23080bb2ff7SRichard Henderson /* WSBA1 */ 23180bb2ff7SRichard Henderson ret = s->pchip.win[1].base_addr; 23280bb2ff7SRichard Henderson break; 23380bb2ff7SRichard Henderson case 0x0080: 23480bb2ff7SRichard Henderson /* WSBA2 */ 23580bb2ff7SRichard Henderson ret = s->pchip.win[2].base_addr; 23680bb2ff7SRichard Henderson break; 23780bb2ff7SRichard Henderson case 0x00c0: 23880bb2ff7SRichard Henderson /* WSBA3 */ 23980bb2ff7SRichard Henderson ret = s->pchip.win[3].base_addr; 24080bb2ff7SRichard Henderson break; 24180bb2ff7SRichard Henderson 24280bb2ff7SRichard Henderson case 0x0100: 24380bb2ff7SRichard Henderson /* WSM0: Window Space Mask Register. */ 24480bb2ff7SRichard Henderson ret = s->pchip.win[0].mask; 24580bb2ff7SRichard Henderson break; 24680bb2ff7SRichard Henderson case 0x0140: 24780bb2ff7SRichard Henderson /* WSM1 */ 24880bb2ff7SRichard Henderson ret = s->pchip.win[1].mask; 24980bb2ff7SRichard Henderson break; 25080bb2ff7SRichard Henderson case 0x0180: 25180bb2ff7SRichard Henderson /* WSM2 */ 25280bb2ff7SRichard Henderson ret = s->pchip.win[2].mask; 25380bb2ff7SRichard Henderson break; 25480bb2ff7SRichard Henderson case 0x01c0: 25580bb2ff7SRichard Henderson /* WSM3 */ 25680bb2ff7SRichard Henderson ret = s->pchip.win[3].mask; 25780bb2ff7SRichard Henderson break; 25880bb2ff7SRichard Henderson 25980bb2ff7SRichard Henderson case 0x0200: 26080bb2ff7SRichard Henderson /* TBA0: Translated Base Address Register. */ 26180bb2ff7SRichard Henderson ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10; 26280bb2ff7SRichard Henderson break; 26380bb2ff7SRichard Henderson case 0x0240: 26480bb2ff7SRichard Henderson /* TBA1 */ 26580bb2ff7SRichard Henderson ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10; 26680bb2ff7SRichard Henderson break; 26780bb2ff7SRichard Henderson case 0x0280: 26880bb2ff7SRichard Henderson /* TBA2 */ 26980bb2ff7SRichard Henderson ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10; 27080bb2ff7SRichard Henderson break; 27180bb2ff7SRichard Henderson case 0x02c0: 27280bb2ff7SRichard Henderson /* TBA3 */ 27380bb2ff7SRichard Henderson ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10; 27480bb2ff7SRichard Henderson break; 27580bb2ff7SRichard Henderson 27680bb2ff7SRichard Henderson case 0x0300: 27780bb2ff7SRichard Henderson /* PCTL: Pchip Control Register. */ 27880bb2ff7SRichard Henderson ret = s->pchip.ctl; 27980bb2ff7SRichard Henderson break; 28080bb2ff7SRichard Henderson case 0x0340: 28180bb2ff7SRichard Henderson /* PLAT: Pchip Master Latency Register. */ 28280bb2ff7SRichard Henderson break; 28380bb2ff7SRichard Henderson case 0x03c0: 28480bb2ff7SRichard Henderson /* PERROR: Pchip Error Register. */ 28580bb2ff7SRichard Henderson break; 28680bb2ff7SRichard Henderson case 0x0400: 28780bb2ff7SRichard Henderson /* PERRMASK: Pchip Error Mask Register. */ 28880bb2ff7SRichard Henderson break; 28980bb2ff7SRichard Henderson case 0x0440: 29080bb2ff7SRichard Henderson /* PERRSET: Pchip Error Set Register. */ 29180bb2ff7SRichard Henderson break; 29280bb2ff7SRichard Henderson case 0x0480: 29380bb2ff7SRichard Henderson /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */ 29480bb2ff7SRichard Henderson break; 29580bb2ff7SRichard Henderson case 0x04c0: 29680bb2ff7SRichard Henderson /* TLBIA: Translation Buffer Invalidate All Register (WO). */ 29780bb2ff7SRichard Henderson break; 29880bb2ff7SRichard Henderson case 0x0500: /* PMONCTL */ 29980bb2ff7SRichard Henderson case 0x0540: /* PMONCNT */ 30080bb2ff7SRichard Henderson case 0x0800: /* SPRST */ 30180bb2ff7SRichard Henderson break; 30280bb2ff7SRichard Henderson 30380bb2ff7SRichard Henderson default: 30480bb2ff7SRichard Henderson cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size); 30580bb2ff7SRichard Henderson return -1; 30680bb2ff7SRichard Henderson } 30780bb2ff7SRichard Henderson 30880bb2ff7SRichard Henderson s->latch_tmp = ret >> 32; 30980bb2ff7SRichard Henderson return ret; 31080bb2ff7SRichard Henderson } 31180bb2ff7SRichard Henderson 312a8170e5eSAvi Kivity static void cchip_write(void *opaque, hwaddr addr, 31380bb2ff7SRichard Henderson uint64_t v32, unsigned size) 31480bb2ff7SRichard Henderson { 31580bb2ff7SRichard Henderson TyphoonState *s = opaque; 31680bb2ff7SRichard Henderson uint64_t val, oldval, newval; 31780bb2ff7SRichard Henderson 31880bb2ff7SRichard Henderson if (addr & 4) { 31980bb2ff7SRichard Henderson val = v32 << 32 | s->latch_tmp; 32080bb2ff7SRichard Henderson addr ^= 4; 32180bb2ff7SRichard Henderson } else { 32280bb2ff7SRichard Henderson s->latch_tmp = v32; 32380bb2ff7SRichard Henderson return; 32480bb2ff7SRichard Henderson } 32580bb2ff7SRichard Henderson 32680bb2ff7SRichard Henderson switch (addr) { 32780bb2ff7SRichard Henderson case 0x0000: 32880bb2ff7SRichard Henderson /* CSC: Cchip System Configuration Register. */ 32980bb2ff7SRichard Henderson /* All sorts of data here; nothing relevant RW. */ 33080bb2ff7SRichard Henderson break; 33180bb2ff7SRichard Henderson 33280bb2ff7SRichard Henderson case 0x0040: 33380bb2ff7SRichard Henderson /* MTR: Memory Timing Register. */ 33480bb2ff7SRichard Henderson /* All sorts of stuff related to real DRAM. */ 33580bb2ff7SRichard Henderson break; 33680bb2ff7SRichard Henderson 33780bb2ff7SRichard Henderson case 0x0080: 33880bb2ff7SRichard Henderson /* MISC: Miscellaneous Register. */ 33980bb2ff7SRichard Henderson newval = oldval = s->cchip.misc; 34080bb2ff7SRichard Henderson newval &= ~(val & 0x10000ff0); /* W1C fields */ 34180bb2ff7SRichard Henderson if (val & 0x100000) { 34280bb2ff7SRichard Henderson newval &= ~0xff0000ull; /* ACL clears ABT and ABW */ 34380bb2ff7SRichard Henderson } else { 34480bb2ff7SRichard Henderson newval |= val & 0x00f00000; /* ABT field is W1S */ 34580bb2ff7SRichard Henderson if ((newval & 0xf0000) == 0) { 34680bb2ff7SRichard Henderson newval |= val & 0xf0000; /* ABW field is W1S iff zero */ 34780bb2ff7SRichard Henderson } 34880bb2ff7SRichard Henderson } 34980bb2ff7SRichard Henderson newval |= (val & 0xf000) >> 4; /* IPREQ field sets IPINTR. */ 35080bb2ff7SRichard Henderson 35180bb2ff7SRichard Henderson newval &= ~0xf0000000000ull; /* WO and RW fields */ 35280bb2ff7SRichard Henderson newval |= val & 0xf0000000000ull; 35380bb2ff7SRichard Henderson s->cchip.misc = newval; 35480bb2ff7SRichard Henderson 35580bb2ff7SRichard Henderson /* Pass on changes to IPI and ITI state. */ 35680bb2ff7SRichard Henderson if ((newval ^ oldval) & 0xff0) { 35780bb2ff7SRichard Henderson int i; 35880bb2ff7SRichard Henderson for (i = 0; i < 4; ++i) { 359ad601177SAndreas Färber AlphaCPU *cpu = s->cchip.cpu[i]; 360ad601177SAndreas Färber if (cpu != NULL) { 361d8ed887bSAndreas Färber CPUState *cs = CPU(cpu); 36280bb2ff7SRichard Henderson /* IPI can be either cleared or set by the write. */ 36380bb2ff7SRichard Henderson if (newval & (1 << (i + 8))) { 364c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_SMP); 36580bb2ff7SRichard Henderson } else { 366d8ed887bSAndreas Färber cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP); 36780bb2ff7SRichard Henderson } 36880bb2ff7SRichard Henderson 36980bb2ff7SRichard Henderson /* ITI can only be cleared by the write. */ 37080bb2ff7SRichard Henderson if ((newval & (1 << (i + 4))) == 0) { 371d8ed887bSAndreas Färber cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER); 37280bb2ff7SRichard Henderson } 37380bb2ff7SRichard Henderson } 37480bb2ff7SRichard Henderson } 37580bb2ff7SRichard Henderson } 37680bb2ff7SRichard Henderson break; 37780bb2ff7SRichard Henderson 37880bb2ff7SRichard Henderson case 0x00c0: 37980bb2ff7SRichard Henderson /* MPD: Memory Presence Detect Register. */ 38080bb2ff7SRichard Henderson break; 38180bb2ff7SRichard Henderson 38280bb2ff7SRichard Henderson case 0x0100: /* AAR0 */ 38380bb2ff7SRichard Henderson case 0x0140: /* AAR1 */ 38480bb2ff7SRichard Henderson case 0x0180: /* AAR2 */ 38580bb2ff7SRichard Henderson case 0x01c0: /* AAR3 */ 38680bb2ff7SRichard Henderson /* AAR: Array Address Register. */ 38780bb2ff7SRichard Henderson /* All sorts of information about DRAM. */ 38880bb2ff7SRichard Henderson break; 38980bb2ff7SRichard Henderson 39080bb2ff7SRichard Henderson case 0x0200: /* DIM0 */ 39180bb2ff7SRichard Henderson /* DIM: Device Interrupt Mask Register, CPU0. */ 39280bb2ff7SRichard Henderson s->cchip.dim[0] = val; 39380bb2ff7SRichard Henderson cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir); 39480bb2ff7SRichard Henderson break; 39580bb2ff7SRichard Henderson case 0x0240: /* DIM1 */ 39680bb2ff7SRichard Henderson /* DIM: Device Interrupt Mask Register, CPU1. */ 39780bb2ff7SRichard Henderson s->cchip.dim[0] = val; 39880bb2ff7SRichard Henderson cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir); 39980bb2ff7SRichard Henderson break; 40080bb2ff7SRichard Henderson 40180bb2ff7SRichard Henderson case 0x0280: /* DIR0 (RO) */ 40280bb2ff7SRichard Henderson case 0x02c0: /* DIR1 (RO) */ 40380bb2ff7SRichard Henderson case 0x0300: /* DRIR (RO) */ 40480bb2ff7SRichard Henderson break; 40580bb2ff7SRichard Henderson 40680bb2ff7SRichard Henderson case 0x0340: 40780bb2ff7SRichard Henderson /* PRBEN: Probe Enable Register. */ 40880bb2ff7SRichard Henderson break; 40980bb2ff7SRichard Henderson 41080bb2ff7SRichard Henderson case 0x0380: /* IIC0 */ 41180bb2ff7SRichard Henderson s->cchip.iic[0] = val & 0xffffff; 41280bb2ff7SRichard Henderson break; 41380bb2ff7SRichard Henderson case 0x03c0: /* IIC1 */ 41480bb2ff7SRichard Henderson s->cchip.iic[1] = val & 0xffffff; 41580bb2ff7SRichard Henderson break; 41680bb2ff7SRichard Henderson 41780bb2ff7SRichard Henderson case 0x0400: /* MPR0 */ 41880bb2ff7SRichard Henderson case 0x0440: /* MPR1 */ 41980bb2ff7SRichard Henderson case 0x0480: /* MPR2 */ 42080bb2ff7SRichard Henderson case 0x04c0: /* MPR3 */ 42180bb2ff7SRichard Henderson /* MPR: Memory Programming Register. */ 42280bb2ff7SRichard Henderson break; 42380bb2ff7SRichard Henderson 42480bb2ff7SRichard Henderson case 0x0580: 42580bb2ff7SRichard Henderson /* TTR: TIGbus Timing Register. */ 42680bb2ff7SRichard Henderson /* All sorts of stuff related to interrupt delivery timings. */ 42780bb2ff7SRichard Henderson break; 42880bb2ff7SRichard Henderson case 0x05c0: 42980bb2ff7SRichard Henderson /* TDR: TIGbug Device Timing Register. */ 43080bb2ff7SRichard Henderson break; 43180bb2ff7SRichard Henderson 43280bb2ff7SRichard Henderson case 0x0600: 43380bb2ff7SRichard Henderson /* DIM2: Device Interrupt Mask Register, CPU2. */ 43480bb2ff7SRichard Henderson s->cchip.dim[2] = val; 43580bb2ff7SRichard Henderson cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir); 43680bb2ff7SRichard Henderson break; 43780bb2ff7SRichard Henderson case 0x0640: 43880bb2ff7SRichard Henderson /* DIM3: Device Interrupt Mask Register, CPU3. */ 43980bb2ff7SRichard Henderson s->cchip.dim[3] = val; 44080bb2ff7SRichard Henderson cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir); 44180bb2ff7SRichard Henderson break; 44280bb2ff7SRichard Henderson 44380bb2ff7SRichard Henderson case 0x0680: /* DIR2 (RO) */ 44480bb2ff7SRichard Henderson case 0x06c0: /* DIR3 (RO) */ 44580bb2ff7SRichard Henderson break; 44680bb2ff7SRichard Henderson 44780bb2ff7SRichard Henderson case 0x0700: /* IIC2 */ 44880bb2ff7SRichard Henderson s->cchip.iic[2] = val & 0xffffff; 44980bb2ff7SRichard Henderson break; 45080bb2ff7SRichard Henderson case 0x0740: /* IIC3 */ 45180bb2ff7SRichard Henderson s->cchip.iic[3] = val & 0xffffff; 45280bb2ff7SRichard Henderson break; 45380bb2ff7SRichard Henderson 45480bb2ff7SRichard Henderson case 0x0780: 45580bb2ff7SRichard Henderson /* PWR: Power Management Control. */ 45680bb2ff7SRichard Henderson break; 45780bb2ff7SRichard Henderson 45880bb2ff7SRichard Henderson case 0x0c00: /* CMONCTLA */ 45980bb2ff7SRichard Henderson case 0x0c40: /* CMONCTLB */ 46080bb2ff7SRichard Henderson case 0x0c80: /* CMONCNT01 */ 46180bb2ff7SRichard Henderson case 0x0cc0: /* CMONCNT23 */ 46280bb2ff7SRichard Henderson break; 46380bb2ff7SRichard Henderson 46480bb2ff7SRichard Henderson default: 46580bb2ff7SRichard Henderson cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size); 46680bb2ff7SRichard Henderson return; 46780bb2ff7SRichard Henderson } 46880bb2ff7SRichard Henderson } 46980bb2ff7SRichard Henderson 470a8170e5eSAvi Kivity static void dchip_write(void *opaque, hwaddr addr, 47180bb2ff7SRichard Henderson uint64_t val, unsigned size) 47280bb2ff7SRichard Henderson { 47380bb2ff7SRichard Henderson /* Skip this. It's all related to DRAM timing and setup. */ 47480bb2ff7SRichard Henderson } 47580bb2ff7SRichard Henderson 476a8170e5eSAvi Kivity static void pchip_write(void *opaque, hwaddr addr, 47780bb2ff7SRichard Henderson uint64_t v32, unsigned size) 47880bb2ff7SRichard Henderson { 47980bb2ff7SRichard Henderson TyphoonState *s = opaque; 48080bb2ff7SRichard Henderson uint64_t val, oldval; 48180bb2ff7SRichard Henderson 48280bb2ff7SRichard Henderson if (addr & 4) { 48380bb2ff7SRichard Henderson val = v32 << 32 | s->latch_tmp; 48480bb2ff7SRichard Henderson addr ^= 4; 48580bb2ff7SRichard Henderson } else { 48680bb2ff7SRichard Henderson s->latch_tmp = v32; 48780bb2ff7SRichard Henderson return; 48880bb2ff7SRichard Henderson } 48980bb2ff7SRichard Henderson 49080bb2ff7SRichard Henderson switch (addr) { 49180bb2ff7SRichard Henderson case 0x0000: 49280bb2ff7SRichard Henderson /* WSBA0: Window Space Base Address Register. */ 49380bb2ff7SRichard Henderson s->pchip.win[0].base_addr = val; 49480bb2ff7SRichard Henderson break; 49580bb2ff7SRichard Henderson case 0x0040: 49680bb2ff7SRichard Henderson /* WSBA1 */ 49780bb2ff7SRichard Henderson s->pchip.win[1].base_addr = val; 49880bb2ff7SRichard Henderson break; 49980bb2ff7SRichard Henderson case 0x0080: 50080bb2ff7SRichard Henderson /* WSBA2 */ 50180bb2ff7SRichard Henderson s->pchip.win[2].base_addr = val; 50280bb2ff7SRichard Henderson break; 50380bb2ff7SRichard Henderson case 0x00c0: 50480bb2ff7SRichard Henderson /* WSBA3 */ 50580bb2ff7SRichard Henderson s->pchip.win[3].base_addr = val; 50680bb2ff7SRichard Henderson break; 50780bb2ff7SRichard Henderson 50880bb2ff7SRichard Henderson case 0x0100: 50980bb2ff7SRichard Henderson /* WSM0: Window Space Mask Register. */ 51080bb2ff7SRichard Henderson s->pchip.win[0].mask = val; 51180bb2ff7SRichard Henderson break; 51280bb2ff7SRichard Henderson case 0x0140: 51380bb2ff7SRichard Henderson /* WSM1 */ 51480bb2ff7SRichard Henderson s->pchip.win[1].mask = val; 51580bb2ff7SRichard Henderson break; 51680bb2ff7SRichard Henderson case 0x0180: 51780bb2ff7SRichard Henderson /* WSM2 */ 51880bb2ff7SRichard Henderson s->pchip.win[2].mask = val; 51980bb2ff7SRichard Henderson break; 52080bb2ff7SRichard Henderson case 0x01c0: 52180bb2ff7SRichard Henderson /* WSM3 */ 52280bb2ff7SRichard Henderson s->pchip.win[3].mask = val; 52380bb2ff7SRichard Henderson break; 52480bb2ff7SRichard Henderson 52580bb2ff7SRichard Henderson case 0x0200: 52680bb2ff7SRichard Henderson /* TBA0: Translated Base Address Register. */ 52780bb2ff7SRichard Henderson s->pchip.win[0].translated_base_pfn = val >> 10; 52880bb2ff7SRichard Henderson break; 52980bb2ff7SRichard Henderson case 0x0240: 53080bb2ff7SRichard Henderson /* TBA1 */ 53180bb2ff7SRichard Henderson s->pchip.win[1].translated_base_pfn = val >> 10; 53280bb2ff7SRichard Henderson break; 53380bb2ff7SRichard Henderson case 0x0280: 53480bb2ff7SRichard Henderson /* TBA2 */ 53580bb2ff7SRichard Henderson s->pchip.win[2].translated_base_pfn = val >> 10; 53680bb2ff7SRichard Henderson break; 53780bb2ff7SRichard Henderson case 0x02c0: 53880bb2ff7SRichard Henderson /* TBA3 */ 53980bb2ff7SRichard Henderson s->pchip.win[3].translated_base_pfn = val >> 10; 54080bb2ff7SRichard Henderson break; 54180bb2ff7SRichard Henderson 54280bb2ff7SRichard Henderson case 0x0300: 54380bb2ff7SRichard Henderson /* PCTL: Pchip Control Register. */ 54480bb2ff7SRichard Henderson oldval = s->pchip.ctl; 54580bb2ff7SRichard Henderson oldval &= ~0x00001cff0fc7ffull; /* RW fields */ 54680bb2ff7SRichard Henderson oldval |= val & 0x00001cff0fc7ffull; 54780bb2ff7SRichard Henderson 54880bb2ff7SRichard Henderson s->pchip.ctl = oldval; 54980bb2ff7SRichard Henderson break; 55080bb2ff7SRichard Henderson 55180bb2ff7SRichard Henderson case 0x0340: 55280bb2ff7SRichard Henderson /* PLAT: Pchip Master Latency Register. */ 55380bb2ff7SRichard Henderson break; 55480bb2ff7SRichard Henderson case 0x03c0: 55580bb2ff7SRichard Henderson /* PERROR: Pchip Error Register. */ 55680bb2ff7SRichard Henderson break; 55780bb2ff7SRichard Henderson case 0x0400: 55880bb2ff7SRichard Henderson /* PERRMASK: Pchip Error Mask Register. */ 55980bb2ff7SRichard Henderson break; 56080bb2ff7SRichard Henderson case 0x0440: 56180bb2ff7SRichard Henderson /* PERRSET: Pchip Error Set Register. */ 56280bb2ff7SRichard Henderson break; 56380bb2ff7SRichard Henderson 56480bb2ff7SRichard Henderson case 0x0480: 56580bb2ff7SRichard Henderson /* TLBIV: Translation Buffer Invalidate Virtual Register. */ 56680bb2ff7SRichard Henderson break; 56780bb2ff7SRichard Henderson 56880bb2ff7SRichard Henderson case 0x04c0: 56980bb2ff7SRichard Henderson /* TLBIA: Translation Buffer Invalidate All Register (WO). */ 57080bb2ff7SRichard Henderson break; 57180bb2ff7SRichard Henderson 57280bb2ff7SRichard Henderson case 0x0500: 57380bb2ff7SRichard Henderson /* PMONCTL */ 57480bb2ff7SRichard Henderson case 0x0540: 57580bb2ff7SRichard Henderson /* PMONCNT */ 57680bb2ff7SRichard Henderson case 0x0800: 57780bb2ff7SRichard Henderson /* SPRST */ 57880bb2ff7SRichard Henderson break; 57980bb2ff7SRichard Henderson 58080bb2ff7SRichard Henderson default: 58180bb2ff7SRichard Henderson cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size); 58280bb2ff7SRichard Henderson return; 58380bb2ff7SRichard Henderson } 58480bb2ff7SRichard Henderson } 58580bb2ff7SRichard Henderson 58680bb2ff7SRichard Henderson static const MemoryRegionOps cchip_ops = { 58780bb2ff7SRichard Henderson .read = cchip_read, 58880bb2ff7SRichard Henderson .write = cchip_write, 58980bb2ff7SRichard Henderson .endianness = DEVICE_LITTLE_ENDIAN, 59080bb2ff7SRichard Henderson .valid = { 59180bb2ff7SRichard Henderson .min_access_size = 4, /* ??? Should be 8. */ 59280bb2ff7SRichard Henderson .max_access_size = 8, 59380bb2ff7SRichard Henderson }, 59480bb2ff7SRichard Henderson .impl = { 59580bb2ff7SRichard Henderson .min_access_size = 4, 59680bb2ff7SRichard Henderson .max_access_size = 4, 59780bb2ff7SRichard Henderson }, 59880bb2ff7SRichard Henderson }; 59980bb2ff7SRichard Henderson 60080bb2ff7SRichard Henderson static const MemoryRegionOps dchip_ops = { 60180bb2ff7SRichard Henderson .read = dchip_read, 60280bb2ff7SRichard Henderson .write = dchip_write, 60380bb2ff7SRichard Henderson .endianness = DEVICE_LITTLE_ENDIAN, 60480bb2ff7SRichard Henderson .valid = { 60580bb2ff7SRichard Henderson .min_access_size = 4, /* ??? Should be 8. */ 60680bb2ff7SRichard Henderson .max_access_size = 8, 60780bb2ff7SRichard Henderson }, 60880bb2ff7SRichard Henderson .impl = { 60980bb2ff7SRichard Henderson .min_access_size = 4, 61080bb2ff7SRichard Henderson .max_access_size = 8, 61180bb2ff7SRichard Henderson }, 61280bb2ff7SRichard Henderson }; 61380bb2ff7SRichard Henderson 61480bb2ff7SRichard Henderson static const MemoryRegionOps pchip_ops = { 61580bb2ff7SRichard Henderson .read = pchip_read, 61680bb2ff7SRichard Henderson .write = pchip_write, 61780bb2ff7SRichard Henderson .endianness = DEVICE_LITTLE_ENDIAN, 61880bb2ff7SRichard Henderson .valid = { 61980bb2ff7SRichard Henderson .min_access_size = 4, /* ??? Should be 8. */ 62080bb2ff7SRichard Henderson .max_access_size = 8, 62180bb2ff7SRichard Henderson }, 62280bb2ff7SRichard Henderson .impl = { 62380bb2ff7SRichard Henderson .min_access_size = 4, 62480bb2ff7SRichard Henderson .max_access_size = 4, 62580bb2ff7SRichard Henderson }, 62680bb2ff7SRichard Henderson }; 62780bb2ff7SRichard Henderson 62880bb2ff7SRichard Henderson static void typhoon_set_irq(void *opaque, int irq, int level) 62980bb2ff7SRichard Henderson { 63080bb2ff7SRichard Henderson TyphoonState *s = opaque; 63180bb2ff7SRichard Henderson uint64_t drir; 63280bb2ff7SRichard Henderson int i; 63380bb2ff7SRichard Henderson 63480bb2ff7SRichard Henderson /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL. */ 63580bb2ff7SRichard Henderson drir = s->cchip.drir; 63680bb2ff7SRichard Henderson if (level) { 63780bb2ff7SRichard Henderson drir |= 1ull << irq; 63880bb2ff7SRichard Henderson } else { 63980bb2ff7SRichard Henderson drir &= ~(1ull << irq); 64080bb2ff7SRichard Henderson } 64180bb2ff7SRichard Henderson s->cchip.drir = drir; 64280bb2ff7SRichard Henderson 64380bb2ff7SRichard Henderson for (i = 0; i < 4; ++i) { 64480bb2ff7SRichard Henderson cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir); 64580bb2ff7SRichard Henderson } 64680bb2ff7SRichard Henderson } 64780bb2ff7SRichard Henderson 64880bb2ff7SRichard Henderson static void typhoon_set_isa_irq(void *opaque, int irq, int level) 64980bb2ff7SRichard Henderson { 65080bb2ff7SRichard Henderson typhoon_set_irq(opaque, 55, level); 65180bb2ff7SRichard Henderson } 65280bb2ff7SRichard Henderson 65380bb2ff7SRichard Henderson static void typhoon_set_timer_irq(void *opaque, int irq, int level) 65480bb2ff7SRichard Henderson { 65580bb2ff7SRichard Henderson TyphoonState *s = opaque; 65680bb2ff7SRichard Henderson int i; 65780bb2ff7SRichard Henderson 65880bb2ff7SRichard Henderson /* Thankfully, the mc146818rtc code doesn't track the IRQ state, 65980bb2ff7SRichard Henderson and so we don't have to worry about missing interrupts just 66080bb2ff7SRichard Henderson because we never actually ACK the interrupt. Just ignore any 66180bb2ff7SRichard Henderson case of the interrupt level going low. */ 66280bb2ff7SRichard Henderson if (level == 0) { 66380bb2ff7SRichard Henderson return; 66480bb2ff7SRichard Henderson } 66580bb2ff7SRichard Henderson 66680bb2ff7SRichard Henderson /* Deliver the interrupt to each CPU, considering each CPU's IIC. */ 66780bb2ff7SRichard Henderson for (i = 0; i < 4; ++i) { 668ad601177SAndreas Färber AlphaCPU *cpu = s->cchip.cpu[i]; 669ad601177SAndreas Färber if (cpu != NULL) { 67080bb2ff7SRichard Henderson uint32_t iic = s->cchip.iic[i]; 67180bb2ff7SRichard Henderson 67280bb2ff7SRichard Henderson /* ??? The verbage in Section 10.2.2.10 isn't 100% clear. 67380bb2ff7SRichard Henderson Bit 24 is the OverFlow bit, RO, and set when the count 67480bb2ff7SRichard Henderson decrements past 0. When is OF cleared? My guess is that 67580bb2ff7SRichard Henderson OF is actually cleared when the IIC is written, and that 67680bb2ff7SRichard Henderson the ICNT field always decrements. At least, that's an 67780bb2ff7SRichard Henderson interpretation that makes sense, and "allows the CPU to 67880bb2ff7SRichard Henderson determine exactly how mant interval timer ticks were 67980bb2ff7SRichard Henderson skipped". At least within the next 4M ticks... */ 68080bb2ff7SRichard Henderson 68180bb2ff7SRichard Henderson iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000); 68280bb2ff7SRichard Henderson s->cchip.iic[i] = iic; 68380bb2ff7SRichard Henderson 68480bb2ff7SRichard Henderson if (iic & 0x1000000) { 68580bb2ff7SRichard Henderson /* Set the ITI bit for this cpu. */ 68680bb2ff7SRichard Henderson s->cchip.misc |= 1 << (i + 4); 68780bb2ff7SRichard Henderson /* And signal the interrupt. */ 688c3affe56SAndreas Färber cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER); 68980bb2ff7SRichard Henderson } 69080bb2ff7SRichard Henderson } 69180bb2ff7SRichard Henderson } 69280bb2ff7SRichard Henderson } 69380bb2ff7SRichard Henderson 694c781cf96SRichard Henderson static void typhoon_alarm_timer(void *opaque) 695c781cf96SRichard Henderson { 696c781cf96SRichard Henderson TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3); 697c781cf96SRichard Henderson int cpu = (uintptr_t)opaque & 3; 698c781cf96SRichard Henderson 699c781cf96SRichard Henderson /* Set the ITI bit for this cpu. */ 700c781cf96SRichard Henderson s->cchip.misc |= 1 << (cpu + 4); 701c3affe56SAndreas Färber cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER); 702c781cf96SRichard Henderson } 703c781cf96SRichard Henderson 70471baa303SHervé Poussineau PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, 70571baa303SHervé Poussineau qemu_irq *p_rtc_irq, 706ad601177SAndreas Färber AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq) 70780bb2ff7SRichard Henderson { 70880bb2ff7SRichard Henderson const uint64_t MB = 1024 * 1024; 70980bb2ff7SRichard Henderson const uint64_t GB = 1024 * MB; 71080bb2ff7SRichard Henderson MemoryRegion *addr_space = get_system_memory(); 71180bb2ff7SRichard Henderson MemoryRegion *addr_space_io = get_system_io(); 71280bb2ff7SRichard Henderson DeviceState *dev; 71380bb2ff7SRichard Henderson TyphoonState *s; 71494dd91d6SAndreas Färber PCIHostState *phb; 71580bb2ff7SRichard Henderson PCIBus *b; 716c781cf96SRichard Henderson int i; 71780bb2ff7SRichard Henderson 71894dd91d6SAndreas Färber dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE); 71980bb2ff7SRichard Henderson qdev_init_nofail(dev); 72080bb2ff7SRichard Henderson 72194dd91d6SAndreas Färber s = TYPHOON_PCI_HOST_BRIDGE(dev); 7228558d942SAndreas Färber phb = PCI_HOST_BRIDGE(dev); 72380bb2ff7SRichard Henderson 72480bb2ff7SRichard Henderson /* Remember the CPUs so that we can deliver interrupts to them. */ 725c781cf96SRichard Henderson for (i = 0; i < 4; i++) { 726ad601177SAndreas Färber AlphaCPU *cpu = cpus[i]; 727ad601177SAndreas Färber s->cchip.cpu[i] = cpu; 728ad601177SAndreas Färber if (cpu != NULL) { 729c9245853SAndreas Färber cpu->alarm_timer = qemu_new_timer_ns(rtc_clock, 730c781cf96SRichard Henderson typhoon_alarm_timer, 731c781cf96SRichard Henderson (void *)((uintptr_t)s + i)); 732c781cf96SRichard Henderson } 733c781cf96SRichard Henderson } 73480bb2ff7SRichard Henderson 73580bb2ff7SRichard Henderson *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1); 73680bb2ff7SRichard Henderson 73780bb2ff7SRichard Henderson /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, 73880bb2ff7SRichard Henderson but the address space hole reserved at this point is 8TB. */ 739c5705a77SAvi Kivity memory_region_init_ram(&s->ram_region, "ram", ram_size); 740c5705a77SAvi Kivity vmstate_register_ram_global(&s->ram_region); 74180bb2ff7SRichard Henderson memory_region_add_subregion(addr_space, 0, &s->ram_region); 74280bb2ff7SRichard Henderson 74380bb2ff7SRichard Henderson /* TIGbus, 0x801.0000.0000, 1GB. */ 74480bb2ff7SRichard Henderson /* ??? The TIGbus is used for delivering interrupts, and access to 74580bb2ff7SRichard Henderson the flash ROM. I'm not sure that we need to implement it at all. */ 74680bb2ff7SRichard Henderson 74780bb2ff7SRichard Henderson /* Pchip0 CSRs, 0x801.8000.0000, 256MB. */ 74880bb2ff7SRichard Henderson memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB); 74902d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x80180000000ULL, 75002d6516cSStefan Weil &s->pchip.region); 75180bb2ff7SRichard Henderson 75280bb2ff7SRichard Henderson /* Cchip CSRs, 0x801.A000.0000, 256MB. */ 75380bb2ff7SRichard Henderson memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB); 75402d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x801a0000000ULL, 75502d6516cSStefan Weil &s->cchip.region); 75680bb2ff7SRichard Henderson 75780bb2ff7SRichard Henderson /* Dchip CSRs, 0x801.B000.0000, 256MB. */ 75880bb2ff7SRichard Henderson memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB); 75902d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x801b0000000ULL, 76002d6516cSStefan Weil &s->dchip_region); 76180bb2ff7SRichard Henderson 76280bb2ff7SRichard Henderson /* Pchip0 PCI memory, 0x800.0000.0000, 4GB. */ 76380bb2ff7SRichard Henderson memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB); 76402d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x80000000000ULL, 76502d6516cSStefan Weil &s->pchip.reg_mem); 76680bb2ff7SRichard Henderson 76780bb2ff7SRichard Henderson /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */ 76880bb2ff7SRichard Henderson /* ??? Ideally we drop the "system" i/o space on the floor and give the 76980bb2ff7SRichard Henderson PCI subsystem the full address space reserved by the chipset. 77080bb2ff7SRichard Henderson We can't do that until the MEM and IO paths in memory.c are unified. */ 77180bb2ff7SRichard Henderson memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL, 77280bb2ff7SRichard Henderson "pci0-io", 32*MB); 77302d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x801fc000000ULL, 77402d6516cSStefan Weil &s->pchip.reg_io); 77580bb2ff7SRichard Henderson 77694dd91d6SAndreas Färber b = pci_register_bus(dev, "pci", 77780bb2ff7SRichard Henderson typhoon_set_irq, sys_map_irq, s, 77860a0e443SAlex Williamson &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS); 77994dd91d6SAndreas Färber phb->bus = b; 78080bb2ff7SRichard Henderson 78180bb2ff7SRichard Henderson /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */ 78280bb2ff7SRichard Henderson memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b, 78380bb2ff7SRichard Henderson "pci0-iack", 64*MB); 78402d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x801f8000000ULL, 78502d6516cSStefan Weil &s->pchip.reg_iack); 78680bb2ff7SRichard Henderson 78780bb2ff7SRichard Henderson /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */ 78880bb2ff7SRichard Henderson memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b, 78980bb2ff7SRichard Henderson "pci0-conf", 16*MB); 79002d6516cSStefan Weil memory_region_add_subregion(addr_space, 0x801fe000000ULL, 79102d6516cSStefan Weil &s->pchip.reg_conf); 79280bb2ff7SRichard Henderson 79380bb2ff7SRichard Henderson /* For the record, these are the mappings for the second PCI bus. 79480bb2ff7SRichard Henderson We can get away with not implementing them because we indicate 79580bb2ff7SRichard Henderson via the Cchip.CSC<PIP> bit that Pchip1 is not present. */ 79680bb2ff7SRichard Henderson /* Pchip1 PCI memory, 0x802.0000.0000, 4GB. */ 79780bb2ff7SRichard Henderson /* Pchip1 CSRs, 0x802.8000.0000, 256MB. */ 79880bb2ff7SRichard Henderson /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB. */ 79980bb2ff7SRichard Henderson /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB. */ 80080bb2ff7SRichard Henderson /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */ 80180bb2ff7SRichard Henderson 80280bb2ff7SRichard Henderson /* Init the ISA bus. */ 80380bb2ff7SRichard Henderson /* ??? Technically there should be a cy82c693ub pci-isa bridge. */ 80480bb2ff7SRichard Henderson { 80580bb2ff7SRichard Henderson qemu_irq isa_pci_irq, *isa_irqs; 80680bb2ff7SRichard Henderson 80771baa303SHervé Poussineau *isa_bus = isa_bus_new(NULL, addr_space_io); 80880bb2ff7SRichard Henderson isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1); 80971baa303SHervé Poussineau isa_irqs = i8259_init(*isa_bus, isa_pci_irq); 81071baa303SHervé Poussineau isa_bus_irqs(*isa_bus, isa_irqs); 81180bb2ff7SRichard Henderson } 81280bb2ff7SRichard Henderson 81380bb2ff7SRichard Henderson return b; 81480bb2ff7SRichard Henderson } 81580bb2ff7SRichard Henderson 81680bb2ff7SRichard Henderson static int typhoon_pcihost_init(SysBusDevice *dev) 81780bb2ff7SRichard Henderson { 81880bb2ff7SRichard Henderson return 0; 81980bb2ff7SRichard Henderson } 82080bb2ff7SRichard Henderson 821999e12bbSAnthony Liguori static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) 822999e12bbSAnthony Liguori { 82339bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 824999e12bbSAnthony Liguori SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 825999e12bbSAnthony Liguori 826999e12bbSAnthony Liguori k->init = typhoon_pcihost_init; 82739bffca2SAnthony Liguori dc->no_user = 1; 828999e12bbSAnthony Liguori } 829999e12bbSAnthony Liguori 8304240abffSAndreas Färber static const TypeInfo typhoon_pcihost_info = { 83194dd91d6SAndreas Färber .name = TYPE_TYPHOON_PCI_HOST_BRIDGE, 8328558d942SAndreas Färber .parent = TYPE_PCI_HOST_BRIDGE, 83339bffca2SAnthony Liguori .instance_size = sizeof(TyphoonState), 834999e12bbSAnthony Liguori .class_init = typhoon_pcihost_class_init, 83580bb2ff7SRichard Henderson }; 83680bb2ff7SRichard Henderson 83783f7d43aSAndreas Färber static void typhoon_register_types(void) 83880bb2ff7SRichard Henderson { 83939bffca2SAnthony Liguori type_register_static(&typhoon_pcihost_info); 84080bb2ff7SRichard Henderson } 84183f7d43aSAndreas Färber 84283f7d43aSAndreas Färber type_init(typhoon_register_types) 843