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