xref: /qemu/hw/alpha/typhoon.c (revision 19e0cbb82ffab7220cdbcc78ab2c1dac823ce4e3)
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 } TyphoonState;
5580bb2ff7SRichard Henderson 
5680bb2ff7SRichard Henderson /* Called when one of DRIR or DIM changes.  */
57ad601177SAndreas Färber static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
5880bb2ff7SRichard Henderson {
5980bb2ff7SRichard Henderson     /* If there are any non-masked interrupts, tell the cpu.  */
60ad601177SAndreas Färber     if (cpu != NULL) {
61d8ed887bSAndreas Färber         CPUState *cs = CPU(cpu);
6280bb2ff7SRichard Henderson         if (req) {
63c3affe56SAndreas Färber             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
6480bb2ff7SRichard Henderson         } else {
65d8ed887bSAndreas Färber             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
6680bb2ff7SRichard Henderson         }
6780bb2ff7SRichard Henderson     }
6880bb2ff7SRichard Henderson }
6980bb2ff7SRichard Henderson 
70a8170e5eSAvi Kivity static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
7180bb2ff7SRichard Henderson {
724917cf44SAndreas Färber     CPUState *cpu = current_cpu;
7380bb2ff7SRichard Henderson     TyphoonState *s = opaque;
7480bb2ff7SRichard Henderson     uint64_t ret = 0;
7580bb2ff7SRichard Henderson 
7680bb2ff7SRichard Henderson     switch (addr) {
7780bb2ff7SRichard Henderson     case 0x0000:
7880bb2ff7SRichard Henderson         /* CSC: Cchip System Configuration Register.  */
7980bb2ff7SRichard Henderson         /* All sorts of data here; probably the only thing relevant is
8080bb2ff7SRichard Henderson            PIP<14> Pchip 1 Present = 0.  */
8180bb2ff7SRichard Henderson         break;
8280bb2ff7SRichard Henderson 
8380bb2ff7SRichard Henderson     case 0x0040:
8480bb2ff7SRichard Henderson         /* MTR: Memory Timing Register.  */
8580bb2ff7SRichard Henderson         /* All sorts of stuff related to real DRAM.  */
8680bb2ff7SRichard Henderson         break;
8780bb2ff7SRichard Henderson 
8880bb2ff7SRichard Henderson     case 0x0080:
8980bb2ff7SRichard Henderson         /* MISC: Miscellaneous Register.  */
9055e5c285SAndreas Färber         ret = s->cchip.misc | (cpu->cpu_index & 3);
9180bb2ff7SRichard Henderson         break;
9280bb2ff7SRichard Henderson 
9380bb2ff7SRichard Henderson     case 0x00c0:
9480bb2ff7SRichard Henderson         /* MPD: Memory Presence Detect Register.  */
9580bb2ff7SRichard Henderson         break;
9680bb2ff7SRichard Henderson 
9780bb2ff7SRichard Henderson     case 0x0100: /* AAR0 */
9880bb2ff7SRichard Henderson     case 0x0140: /* AAR1 */
9980bb2ff7SRichard Henderson     case 0x0180: /* AAR2 */
10080bb2ff7SRichard Henderson     case 0x01c0: /* AAR3 */
10180bb2ff7SRichard Henderson         /* AAR: Array Address Register.  */
10280bb2ff7SRichard Henderson         /* All sorts of information about DRAM.  */
10380bb2ff7SRichard Henderson         break;
10480bb2ff7SRichard Henderson 
10580bb2ff7SRichard Henderson     case 0x0200:
10680bb2ff7SRichard Henderson         /* DIM0: Device Interrupt Mask Register, CPU0.  */
10780bb2ff7SRichard Henderson         ret = s->cchip.dim[0];
10880bb2ff7SRichard Henderson         break;
10980bb2ff7SRichard Henderson     case 0x0240:
11080bb2ff7SRichard Henderson         /* DIM1: Device Interrupt Mask Register, CPU1.  */
11180bb2ff7SRichard Henderson         ret = s->cchip.dim[1];
11280bb2ff7SRichard Henderson         break;
11380bb2ff7SRichard Henderson     case 0x0280:
11480bb2ff7SRichard Henderson         /* DIR0: Device Interrupt Request Register, CPU0.  */
11580bb2ff7SRichard Henderson         ret = s->cchip.dim[0] & s->cchip.drir;
11680bb2ff7SRichard Henderson         break;
11780bb2ff7SRichard Henderson     case 0x02c0:
11880bb2ff7SRichard Henderson         /* DIR1: Device Interrupt Request Register, CPU1.  */
11980bb2ff7SRichard Henderson         ret = s->cchip.dim[1] & s->cchip.drir;
12080bb2ff7SRichard Henderson         break;
12180bb2ff7SRichard Henderson     case 0x0300:
12280bb2ff7SRichard Henderson         /* DRIR: Device Raw Interrupt Request Register.  */
12380bb2ff7SRichard Henderson         ret = s->cchip.drir;
12480bb2ff7SRichard Henderson         break;
12580bb2ff7SRichard Henderson 
12680bb2ff7SRichard Henderson     case 0x0340:
12780bb2ff7SRichard Henderson         /* PRBEN: Probe Enable Register.  */
12880bb2ff7SRichard Henderson         break;
12980bb2ff7SRichard Henderson 
13080bb2ff7SRichard Henderson     case 0x0380:
13180bb2ff7SRichard Henderson         /* IIC0: Interval Ignore Count Register, CPU0.  */
13280bb2ff7SRichard Henderson         ret = s->cchip.iic[0];
13380bb2ff7SRichard Henderson         break;
13480bb2ff7SRichard Henderson     case 0x03c0:
13580bb2ff7SRichard Henderson         /* IIC1: Interval Ignore Count Register, CPU1.  */
13680bb2ff7SRichard Henderson         ret = s->cchip.iic[1];
13780bb2ff7SRichard Henderson         break;
13880bb2ff7SRichard Henderson 
13980bb2ff7SRichard Henderson     case 0x0400: /* MPR0 */
14080bb2ff7SRichard Henderson     case 0x0440: /* MPR1 */
14180bb2ff7SRichard Henderson     case 0x0480: /* MPR2 */
14280bb2ff7SRichard Henderson     case 0x04c0: /* MPR3 */
14380bb2ff7SRichard Henderson         /* MPR: Memory Programming Register.  */
14480bb2ff7SRichard Henderson         break;
14580bb2ff7SRichard Henderson 
14680bb2ff7SRichard Henderson     case 0x0580:
14780bb2ff7SRichard Henderson         /* TTR: TIGbus Timing Register.  */
14880bb2ff7SRichard Henderson         /* All sorts of stuff related to interrupt delivery timings.  */
14980bb2ff7SRichard Henderson         break;
15080bb2ff7SRichard Henderson     case 0x05c0:
15180bb2ff7SRichard Henderson         /* TDR: TIGbug Device Timing Register.  */
15280bb2ff7SRichard Henderson         break;
15380bb2ff7SRichard Henderson 
15480bb2ff7SRichard Henderson     case 0x0600:
15580bb2ff7SRichard Henderson         /* DIM2: Device Interrupt Mask Register, CPU2.  */
15680bb2ff7SRichard Henderson         ret = s->cchip.dim[2];
15780bb2ff7SRichard Henderson         break;
15880bb2ff7SRichard Henderson     case 0x0640:
15980bb2ff7SRichard Henderson         /* DIM3: Device Interrupt Mask Register, CPU3.  */
16080bb2ff7SRichard Henderson         ret = s->cchip.dim[3];
16180bb2ff7SRichard Henderson         break;
16280bb2ff7SRichard Henderson     case 0x0680:
16380bb2ff7SRichard Henderson         /* DIR2: Device Interrupt Request Register, CPU2.  */
16480bb2ff7SRichard Henderson         ret = s->cchip.dim[2] & s->cchip.drir;
16580bb2ff7SRichard Henderson         break;
16680bb2ff7SRichard Henderson     case 0x06c0:
16780bb2ff7SRichard Henderson         /* DIR3: Device Interrupt Request Register, CPU3.  */
16880bb2ff7SRichard Henderson         ret = s->cchip.dim[3] & s->cchip.drir;
16980bb2ff7SRichard Henderson         break;
17080bb2ff7SRichard Henderson 
17180bb2ff7SRichard Henderson     case 0x0700:
17280bb2ff7SRichard Henderson         /* IIC2: Interval Ignore Count Register, CPU2.  */
17380bb2ff7SRichard Henderson         ret = s->cchip.iic[2];
17480bb2ff7SRichard Henderson         break;
17580bb2ff7SRichard Henderson     case 0x0740:
17680bb2ff7SRichard Henderson         /* IIC3: Interval Ignore Count Register, CPU3.  */
17780bb2ff7SRichard Henderson         ret = s->cchip.iic[3];
17880bb2ff7SRichard Henderson         break;
17980bb2ff7SRichard Henderson 
18080bb2ff7SRichard Henderson     case 0x0780:
18180bb2ff7SRichard Henderson         /* PWR: Power Management Control.   */
18280bb2ff7SRichard Henderson         break;
18380bb2ff7SRichard Henderson 
18480bb2ff7SRichard Henderson     case 0x0c00: /* CMONCTLA */
18580bb2ff7SRichard Henderson     case 0x0c40: /* CMONCTLB */
18680bb2ff7SRichard Henderson     case 0x0c80: /* CMONCNT01 */
18780bb2ff7SRichard Henderson     case 0x0cc0: /* CMONCNT23 */
18880bb2ff7SRichard Henderson         break;
18980bb2ff7SRichard Henderson 
19080bb2ff7SRichard Henderson     default:
191c658b94fSAndreas Färber         cpu_unassigned_access(cpu, addr, false, false, 0, size);
19280bb2ff7SRichard Henderson         return -1;
19380bb2ff7SRichard Henderson     }
19480bb2ff7SRichard Henderson 
19580bb2ff7SRichard Henderson     return ret;
19680bb2ff7SRichard Henderson }
19780bb2ff7SRichard Henderson 
198a8170e5eSAvi Kivity static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
19980bb2ff7SRichard Henderson {
20080bb2ff7SRichard Henderson     /* Skip this.  It's all related to DRAM timing and setup.  */
20180bb2ff7SRichard Henderson     return 0;
20280bb2ff7SRichard Henderson }
20380bb2ff7SRichard Henderson 
204a8170e5eSAvi Kivity static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
20580bb2ff7SRichard Henderson {
20680bb2ff7SRichard Henderson     TyphoonState *s = opaque;
20780bb2ff7SRichard Henderson     uint64_t ret = 0;
20880bb2ff7SRichard Henderson 
20980bb2ff7SRichard Henderson     switch (addr) {
21080bb2ff7SRichard Henderson     case 0x0000:
21180bb2ff7SRichard Henderson         /* WSBA0: Window Space Base Address Register.  */
21280bb2ff7SRichard Henderson         ret = s->pchip.win[0].base_addr;
21380bb2ff7SRichard Henderson         break;
21480bb2ff7SRichard Henderson     case 0x0040:
21580bb2ff7SRichard Henderson         /* WSBA1 */
21680bb2ff7SRichard Henderson         ret = s->pchip.win[1].base_addr;
21780bb2ff7SRichard Henderson         break;
21880bb2ff7SRichard Henderson     case 0x0080:
21980bb2ff7SRichard Henderson         /* WSBA2 */
22080bb2ff7SRichard Henderson         ret = s->pchip.win[2].base_addr;
22180bb2ff7SRichard Henderson         break;
22280bb2ff7SRichard Henderson     case 0x00c0:
22380bb2ff7SRichard Henderson         /* WSBA3 */
22480bb2ff7SRichard Henderson         ret = s->pchip.win[3].base_addr;
22580bb2ff7SRichard Henderson         break;
22680bb2ff7SRichard Henderson 
22780bb2ff7SRichard Henderson     case 0x0100:
22880bb2ff7SRichard Henderson         /* WSM0: Window Space Mask Register.  */
22980bb2ff7SRichard Henderson         ret = s->pchip.win[0].mask;
23080bb2ff7SRichard Henderson         break;
23180bb2ff7SRichard Henderson     case 0x0140:
23280bb2ff7SRichard Henderson         /* WSM1 */
23380bb2ff7SRichard Henderson         ret = s->pchip.win[1].mask;
23480bb2ff7SRichard Henderson         break;
23580bb2ff7SRichard Henderson     case 0x0180:
23680bb2ff7SRichard Henderson         /* WSM2 */
23780bb2ff7SRichard Henderson         ret = s->pchip.win[2].mask;
23880bb2ff7SRichard Henderson         break;
23980bb2ff7SRichard Henderson     case 0x01c0:
24080bb2ff7SRichard Henderson         /* WSM3 */
24180bb2ff7SRichard Henderson         ret = s->pchip.win[3].mask;
24280bb2ff7SRichard Henderson         break;
24380bb2ff7SRichard Henderson 
24480bb2ff7SRichard Henderson     case 0x0200:
24580bb2ff7SRichard Henderson         /* TBA0: Translated Base Address Register.  */
24680bb2ff7SRichard Henderson         ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
24780bb2ff7SRichard Henderson         break;
24880bb2ff7SRichard Henderson     case 0x0240:
24980bb2ff7SRichard Henderson         /* TBA1 */
25080bb2ff7SRichard Henderson         ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
25180bb2ff7SRichard Henderson         break;
25280bb2ff7SRichard Henderson     case 0x0280:
25380bb2ff7SRichard Henderson         /* TBA2 */
25480bb2ff7SRichard Henderson         ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
25580bb2ff7SRichard Henderson         break;
25680bb2ff7SRichard Henderson     case 0x02c0:
25780bb2ff7SRichard Henderson         /* TBA3 */
25880bb2ff7SRichard Henderson         ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
25980bb2ff7SRichard Henderson         break;
26080bb2ff7SRichard Henderson 
26180bb2ff7SRichard Henderson     case 0x0300:
26280bb2ff7SRichard Henderson         /* PCTL: Pchip Control Register.  */
26380bb2ff7SRichard Henderson         ret = s->pchip.ctl;
26480bb2ff7SRichard Henderson         break;
26580bb2ff7SRichard Henderson     case 0x0340:
26680bb2ff7SRichard Henderson         /* PLAT: Pchip Master Latency Register.  */
26780bb2ff7SRichard Henderson         break;
26880bb2ff7SRichard Henderson     case 0x03c0:
26980bb2ff7SRichard Henderson         /* PERROR: Pchip Error Register.  */
27080bb2ff7SRichard Henderson         break;
27180bb2ff7SRichard Henderson     case 0x0400:
27280bb2ff7SRichard Henderson         /* PERRMASK: Pchip Error Mask Register.  */
27380bb2ff7SRichard Henderson         break;
27480bb2ff7SRichard Henderson     case 0x0440:
27580bb2ff7SRichard Henderson         /* PERRSET: Pchip Error Set Register.  */
27680bb2ff7SRichard Henderson         break;
27780bb2ff7SRichard Henderson     case 0x0480:
27880bb2ff7SRichard Henderson         /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
27980bb2ff7SRichard Henderson         break;
28080bb2ff7SRichard Henderson     case 0x04c0:
28180bb2ff7SRichard Henderson         /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
28280bb2ff7SRichard Henderson         break;
28380bb2ff7SRichard Henderson     case 0x0500: /* PMONCTL */
28480bb2ff7SRichard Henderson     case 0x0540: /* PMONCNT */
28580bb2ff7SRichard Henderson     case 0x0800: /* SPRST */
28680bb2ff7SRichard Henderson         break;
28780bb2ff7SRichard Henderson 
28880bb2ff7SRichard Henderson     default:
2894917cf44SAndreas Färber         cpu_unassigned_access(current_cpu, addr, false, false, 0, size);
29080bb2ff7SRichard Henderson         return -1;
29180bb2ff7SRichard Henderson     }
29280bb2ff7SRichard Henderson 
29380bb2ff7SRichard Henderson     return ret;
29480bb2ff7SRichard Henderson }
29580bb2ff7SRichard Henderson 
296a8170e5eSAvi Kivity static void cchip_write(void *opaque, hwaddr addr,
29767842165SRichard Henderson                         uint64_t val, unsigned size)
29880bb2ff7SRichard Henderson {
29980bb2ff7SRichard Henderson     TyphoonState *s = opaque;
30067842165SRichard Henderson     uint64_t oldval, newval;
30180bb2ff7SRichard Henderson 
30280bb2ff7SRichard Henderson     switch (addr) {
30380bb2ff7SRichard Henderson     case 0x0000:
30480bb2ff7SRichard Henderson         /* CSC: Cchip System Configuration Register.  */
30580bb2ff7SRichard Henderson         /* All sorts of data here; nothing relevant RW.  */
30680bb2ff7SRichard Henderson         break;
30780bb2ff7SRichard Henderson 
30880bb2ff7SRichard Henderson     case 0x0040:
30980bb2ff7SRichard Henderson         /* MTR: Memory Timing Register.  */
31080bb2ff7SRichard Henderson         /* All sorts of stuff related to real DRAM.  */
31180bb2ff7SRichard Henderson         break;
31280bb2ff7SRichard Henderson 
31380bb2ff7SRichard Henderson     case 0x0080:
31480bb2ff7SRichard Henderson         /* MISC: Miscellaneous Register.  */
31580bb2ff7SRichard Henderson         newval = oldval = s->cchip.misc;
31680bb2ff7SRichard Henderson         newval &= ~(val & 0x10000ff0);     /* W1C fields */
31780bb2ff7SRichard Henderson         if (val & 0x100000) {
31880bb2ff7SRichard Henderson             newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
31980bb2ff7SRichard Henderson         } else {
32080bb2ff7SRichard Henderson             newval |= val & 0x00f00000;    /* ABT field is W1S */
32180bb2ff7SRichard Henderson             if ((newval & 0xf0000) == 0) {
32280bb2ff7SRichard Henderson                 newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
32380bb2ff7SRichard Henderson             }
32480bb2ff7SRichard Henderson         }
32580bb2ff7SRichard Henderson         newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
32680bb2ff7SRichard Henderson 
32780bb2ff7SRichard Henderson         newval &= ~0xf0000000000ull;       /* WO and RW fields */
32880bb2ff7SRichard Henderson         newval |= val & 0xf0000000000ull;
32980bb2ff7SRichard Henderson         s->cchip.misc = newval;
33080bb2ff7SRichard Henderson 
33180bb2ff7SRichard Henderson         /* Pass on changes to IPI and ITI state.  */
33280bb2ff7SRichard Henderson         if ((newval ^ oldval) & 0xff0) {
33380bb2ff7SRichard Henderson             int i;
33480bb2ff7SRichard Henderson             for (i = 0; i < 4; ++i) {
335ad601177SAndreas Färber                 AlphaCPU *cpu = s->cchip.cpu[i];
336ad601177SAndreas Färber                 if (cpu != NULL) {
337d8ed887bSAndreas Färber                     CPUState *cs = CPU(cpu);
33880bb2ff7SRichard Henderson                     /* IPI can be either cleared or set by the write.  */
33980bb2ff7SRichard Henderson                     if (newval & (1 << (i + 8))) {
340c3affe56SAndreas Färber                         cpu_interrupt(cs, CPU_INTERRUPT_SMP);
34180bb2ff7SRichard Henderson                     } else {
342d8ed887bSAndreas Färber                         cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
34380bb2ff7SRichard Henderson                     }
34480bb2ff7SRichard Henderson 
34580bb2ff7SRichard Henderson                     /* ITI can only be cleared by the write.  */
34680bb2ff7SRichard Henderson                     if ((newval & (1 << (i + 4))) == 0) {
347d8ed887bSAndreas Färber                         cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
34880bb2ff7SRichard Henderson                     }
34980bb2ff7SRichard Henderson                 }
35080bb2ff7SRichard Henderson             }
35180bb2ff7SRichard Henderson         }
35280bb2ff7SRichard Henderson         break;
35380bb2ff7SRichard Henderson 
35480bb2ff7SRichard Henderson     case 0x00c0:
35580bb2ff7SRichard Henderson         /* MPD: Memory Presence Detect Register.  */
35680bb2ff7SRichard Henderson         break;
35780bb2ff7SRichard Henderson 
35880bb2ff7SRichard Henderson     case 0x0100: /* AAR0 */
35980bb2ff7SRichard Henderson     case 0x0140: /* AAR1 */
36080bb2ff7SRichard Henderson     case 0x0180: /* AAR2 */
36180bb2ff7SRichard Henderson     case 0x01c0: /* AAR3 */
36280bb2ff7SRichard Henderson         /* AAR: Array Address Register.  */
36380bb2ff7SRichard Henderson         /* All sorts of information about DRAM.  */
36480bb2ff7SRichard Henderson         break;
36580bb2ff7SRichard Henderson 
36680bb2ff7SRichard Henderson     case 0x0200: /* DIM0 */
36780bb2ff7SRichard Henderson         /* DIM: Device Interrupt Mask Register, CPU0.  */
36880bb2ff7SRichard Henderson         s->cchip.dim[0] = val;
36980bb2ff7SRichard Henderson         cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
37080bb2ff7SRichard Henderson         break;
37180bb2ff7SRichard Henderson     case 0x0240: /* DIM1 */
37280bb2ff7SRichard Henderson         /* DIM: Device Interrupt Mask Register, CPU1.  */
37380bb2ff7SRichard Henderson         s->cchip.dim[0] = val;
37480bb2ff7SRichard Henderson         cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
37580bb2ff7SRichard Henderson         break;
37680bb2ff7SRichard Henderson 
37780bb2ff7SRichard Henderson     case 0x0280: /* DIR0 (RO) */
37880bb2ff7SRichard Henderson     case 0x02c0: /* DIR1 (RO) */
37980bb2ff7SRichard Henderson     case 0x0300: /* DRIR (RO) */
38080bb2ff7SRichard Henderson         break;
38180bb2ff7SRichard Henderson 
38280bb2ff7SRichard Henderson     case 0x0340:
38380bb2ff7SRichard Henderson         /* PRBEN: Probe Enable Register.  */
38480bb2ff7SRichard Henderson         break;
38580bb2ff7SRichard Henderson 
38680bb2ff7SRichard Henderson     case 0x0380: /* IIC0 */
38780bb2ff7SRichard Henderson         s->cchip.iic[0] = val & 0xffffff;
38880bb2ff7SRichard Henderson         break;
38980bb2ff7SRichard Henderson     case 0x03c0: /* IIC1 */
39080bb2ff7SRichard Henderson         s->cchip.iic[1] = val & 0xffffff;
39180bb2ff7SRichard Henderson         break;
39280bb2ff7SRichard Henderson 
39380bb2ff7SRichard Henderson     case 0x0400: /* MPR0 */
39480bb2ff7SRichard Henderson     case 0x0440: /* MPR1 */
39580bb2ff7SRichard Henderson     case 0x0480: /* MPR2 */
39680bb2ff7SRichard Henderson     case 0x04c0: /* MPR3 */
39780bb2ff7SRichard Henderson         /* MPR: Memory Programming Register.  */
39880bb2ff7SRichard Henderson         break;
39980bb2ff7SRichard Henderson 
40080bb2ff7SRichard Henderson     case 0x0580:
40180bb2ff7SRichard Henderson         /* TTR: TIGbus Timing Register.  */
40280bb2ff7SRichard Henderson         /* All sorts of stuff related to interrupt delivery timings.  */
40380bb2ff7SRichard Henderson         break;
40480bb2ff7SRichard Henderson     case 0x05c0:
40580bb2ff7SRichard Henderson         /* TDR: TIGbug Device Timing Register.  */
40680bb2ff7SRichard Henderson         break;
40780bb2ff7SRichard Henderson 
40880bb2ff7SRichard Henderson     case 0x0600:
40980bb2ff7SRichard Henderson         /* DIM2: Device Interrupt Mask Register, CPU2.  */
41080bb2ff7SRichard Henderson         s->cchip.dim[2] = val;
41180bb2ff7SRichard Henderson         cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
41280bb2ff7SRichard Henderson         break;
41380bb2ff7SRichard Henderson     case 0x0640:
41480bb2ff7SRichard Henderson         /* DIM3: Device Interrupt Mask Register, CPU3.  */
41580bb2ff7SRichard Henderson         s->cchip.dim[3] = val;
41680bb2ff7SRichard Henderson         cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
41780bb2ff7SRichard Henderson         break;
41880bb2ff7SRichard Henderson 
41980bb2ff7SRichard Henderson     case 0x0680: /* DIR2 (RO) */
42080bb2ff7SRichard Henderson     case 0x06c0: /* DIR3 (RO) */
42180bb2ff7SRichard Henderson         break;
42280bb2ff7SRichard Henderson 
42380bb2ff7SRichard Henderson     case 0x0700: /* IIC2 */
42480bb2ff7SRichard Henderson         s->cchip.iic[2] = val & 0xffffff;
42580bb2ff7SRichard Henderson         break;
42680bb2ff7SRichard Henderson     case 0x0740: /* IIC3 */
42780bb2ff7SRichard Henderson         s->cchip.iic[3] = val & 0xffffff;
42880bb2ff7SRichard Henderson         break;
42980bb2ff7SRichard Henderson 
43080bb2ff7SRichard Henderson     case 0x0780:
43180bb2ff7SRichard Henderson         /* PWR: Power Management Control.   */
43280bb2ff7SRichard Henderson         break;
43380bb2ff7SRichard Henderson 
43480bb2ff7SRichard Henderson     case 0x0c00: /* CMONCTLA */
43580bb2ff7SRichard Henderson     case 0x0c40: /* CMONCTLB */
43680bb2ff7SRichard Henderson     case 0x0c80: /* CMONCNT01 */
43780bb2ff7SRichard Henderson     case 0x0cc0: /* CMONCNT23 */
43880bb2ff7SRichard Henderson         break;
43980bb2ff7SRichard Henderson 
44080bb2ff7SRichard Henderson     default:
4414917cf44SAndreas Färber         cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
44280bb2ff7SRichard Henderson         return;
44380bb2ff7SRichard Henderson     }
44480bb2ff7SRichard Henderson }
44580bb2ff7SRichard Henderson 
446a8170e5eSAvi Kivity static void dchip_write(void *opaque, hwaddr addr,
44780bb2ff7SRichard Henderson                         uint64_t val, unsigned size)
44880bb2ff7SRichard Henderson {
44980bb2ff7SRichard Henderson     /* Skip this.  It's all related to DRAM timing and setup.  */
45080bb2ff7SRichard Henderson }
45180bb2ff7SRichard Henderson 
452a8170e5eSAvi Kivity static void pchip_write(void *opaque, hwaddr addr,
45367842165SRichard Henderson                         uint64_t val, unsigned size)
45480bb2ff7SRichard Henderson {
45580bb2ff7SRichard Henderson     TyphoonState *s = opaque;
45667842165SRichard Henderson     uint64_t oldval;
45780bb2ff7SRichard Henderson 
45880bb2ff7SRichard Henderson     switch (addr) {
45980bb2ff7SRichard Henderson     case 0x0000:
46080bb2ff7SRichard Henderson         /* WSBA0: Window Space Base Address Register.  */
46180bb2ff7SRichard Henderson         s->pchip.win[0].base_addr = val;
46280bb2ff7SRichard Henderson         break;
46380bb2ff7SRichard Henderson     case 0x0040:
46480bb2ff7SRichard Henderson         /* WSBA1 */
46580bb2ff7SRichard Henderson         s->pchip.win[1].base_addr = val;
46680bb2ff7SRichard Henderson         break;
46780bb2ff7SRichard Henderson     case 0x0080:
46880bb2ff7SRichard Henderson         /* WSBA2 */
46980bb2ff7SRichard Henderson         s->pchip.win[2].base_addr = val;
47080bb2ff7SRichard Henderson         break;
47180bb2ff7SRichard Henderson     case 0x00c0:
47280bb2ff7SRichard Henderson         /* WSBA3 */
47380bb2ff7SRichard Henderson         s->pchip.win[3].base_addr = val;
47480bb2ff7SRichard Henderson         break;
47580bb2ff7SRichard Henderson 
47680bb2ff7SRichard Henderson     case 0x0100:
47780bb2ff7SRichard Henderson         /* WSM0: Window Space Mask Register.  */
47880bb2ff7SRichard Henderson         s->pchip.win[0].mask = val;
47980bb2ff7SRichard Henderson         break;
48080bb2ff7SRichard Henderson     case 0x0140:
48180bb2ff7SRichard Henderson         /* WSM1 */
48280bb2ff7SRichard Henderson         s->pchip.win[1].mask = val;
48380bb2ff7SRichard Henderson         break;
48480bb2ff7SRichard Henderson     case 0x0180:
48580bb2ff7SRichard Henderson         /* WSM2 */
48680bb2ff7SRichard Henderson         s->pchip.win[2].mask = val;
48780bb2ff7SRichard Henderson         break;
48880bb2ff7SRichard Henderson     case 0x01c0:
48980bb2ff7SRichard Henderson         /* WSM3 */
49080bb2ff7SRichard Henderson         s->pchip.win[3].mask = val;
49180bb2ff7SRichard Henderson         break;
49280bb2ff7SRichard Henderson 
49380bb2ff7SRichard Henderson     case 0x0200:
49480bb2ff7SRichard Henderson         /* TBA0: Translated Base Address Register.  */
49580bb2ff7SRichard Henderson         s->pchip.win[0].translated_base_pfn = val >> 10;
49680bb2ff7SRichard Henderson         break;
49780bb2ff7SRichard Henderson     case 0x0240:
49880bb2ff7SRichard Henderson         /* TBA1 */
49980bb2ff7SRichard Henderson         s->pchip.win[1].translated_base_pfn = val >> 10;
50080bb2ff7SRichard Henderson         break;
50180bb2ff7SRichard Henderson     case 0x0280:
50280bb2ff7SRichard Henderson         /* TBA2 */
50380bb2ff7SRichard Henderson         s->pchip.win[2].translated_base_pfn = val >> 10;
50480bb2ff7SRichard Henderson         break;
50580bb2ff7SRichard Henderson     case 0x02c0:
50680bb2ff7SRichard Henderson         /* TBA3 */
50780bb2ff7SRichard Henderson         s->pchip.win[3].translated_base_pfn = val >> 10;
50880bb2ff7SRichard Henderson         break;
50980bb2ff7SRichard Henderson 
51080bb2ff7SRichard Henderson     case 0x0300:
51180bb2ff7SRichard Henderson         /* PCTL: Pchip Control Register.  */
51280bb2ff7SRichard Henderson         oldval = s->pchip.ctl;
51380bb2ff7SRichard Henderson         oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
51480bb2ff7SRichard Henderson         oldval |= val & 0x00001cff0fc7ffull;
51580bb2ff7SRichard Henderson 
51680bb2ff7SRichard Henderson         s->pchip.ctl = oldval;
51780bb2ff7SRichard Henderson         break;
51880bb2ff7SRichard Henderson 
51980bb2ff7SRichard Henderson     case 0x0340:
52080bb2ff7SRichard Henderson         /* PLAT: Pchip Master Latency Register.  */
52180bb2ff7SRichard Henderson         break;
52280bb2ff7SRichard Henderson     case 0x03c0:
52380bb2ff7SRichard Henderson         /* PERROR: Pchip Error Register.  */
52480bb2ff7SRichard Henderson         break;
52580bb2ff7SRichard Henderson     case 0x0400:
52680bb2ff7SRichard Henderson         /* PERRMASK: Pchip Error Mask Register.  */
52780bb2ff7SRichard Henderson         break;
52880bb2ff7SRichard Henderson     case 0x0440:
52980bb2ff7SRichard Henderson         /* PERRSET: Pchip Error Set Register.  */
53080bb2ff7SRichard Henderson         break;
53180bb2ff7SRichard Henderson 
53280bb2ff7SRichard Henderson     case 0x0480:
53380bb2ff7SRichard Henderson         /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
53480bb2ff7SRichard Henderson         break;
53580bb2ff7SRichard Henderson 
53680bb2ff7SRichard Henderson     case 0x04c0:
53780bb2ff7SRichard Henderson         /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
53880bb2ff7SRichard Henderson         break;
53980bb2ff7SRichard Henderson 
54080bb2ff7SRichard Henderson     case 0x0500:
54180bb2ff7SRichard Henderson         /* PMONCTL */
54280bb2ff7SRichard Henderson     case 0x0540:
54380bb2ff7SRichard Henderson         /* PMONCNT */
54480bb2ff7SRichard Henderson     case 0x0800:
54580bb2ff7SRichard Henderson         /* SPRST */
54680bb2ff7SRichard Henderson         break;
54780bb2ff7SRichard Henderson 
54880bb2ff7SRichard Henderson     default:
5494917cf44SAndreas Färber         cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
55080bb2ff7SRichard Henderson         return;
55180bb2ff7SRichard Henderson     }
55280bb2ff7SRichard Henderson }
55380bb2ff7SRichard Henderson 
55480bb2ff7SRichard Henderson static const MemoryRegionOps cchip_ops = {
55580bb2ff7SRichard Henderson     .read = cchip_read,
55680bb2ff7SRichard Henderson     .write = cchip_write,
55780bb2ff7SRichard Henderson     .endianness = DEVICE_LITTLE_ENDIAN,
55880bb2ff7SRichard Henderson     .valid = {
55967842165SRichard Henderson         .min_access_size = 8,
56080bb2ff7SRichard Henderson         .max_access_size = 8,
56180bb2ff7SRichard Henderson     },
56280bb2ff7SRichard Henderson     .impl = {
56367842165SRichard Henderson         .min_access_size = 8,
56467842165SRichard Henderson         .max_access_size = 8,
56580bb2ff7SRichard Henderson     },
56680bb2ff7SRichard Henderson };
56780bb2ff7SRichard Henderson 
56880bb2ff7SRichard Henderson static const MemoryRegionOps dchip_ops = {
56980bb2ff7SRichard Henderson     .read = dchip_read,
57080bb2ff7SRichard Henderson     .write = dchip_write,
57180bb2ff7SRichard Henderson     .endianness = DEVICE_LITTLE_ENDIAN,
57280bb2ff7SRichard Henderson     .valid = {
57367842165SRichard Henderson         .min_access_size = 8,
57480bb2ff7SRichard Henderson         .max_access_size = 8,
57580bb2ff7SRichard Henderson     },
57680bb2ff7SRichard Henderson     .impl = {
57767842165SRichard Henderson         .min_access_size = 8,
57880bb2ff7SRichard Henderson         .max_access_size = 8,
57980bb2ff7SRichard Henderson     },
58080bb2ff7SRichard Henderson };
58180bb2ff7SRichard Henderson 
58280bb2ff7SRichard Henderson static const MemoryRegionOps pchip_ops = {
58380bb2ff7SRichard Henderson     .read = pchip_read,
58480bb2ff7SRichard Henderson     .write = pchip_write,
58580bb2ff7SRichard Henderson     .endianness = DEVICE_LITTLE_ENDIAN,
58680bb2ff7SRichard Henderson     .valid = {
58767842165SRichard Henderson         .min_access_size = 8,
58880bb2ff7SRichard Henderson         .max_access_size = 8,
58980bb2ff7SRichard Henderson     },
59080bb2ff7SRichard Henderson     .impl = {
59167842165SRichard Henderson         .min_access_size = 8,
59267842165SRichard Henderson         .max_access_size = 8,
59380bb2ff7SRichard Henderson     },
59480bb2ff7SRichard Henderson };
59580bb2ff7SRichard Henderson 
59680bb2ff7SRichard Henderson static void typhoon_set_irq(void *opaque, int irq, int level)
59780bb2ff7SRichard Henderson {
59880bb2ff7SRichard Henderson     TyphoonState *s = opaque;
59980bb2ff7SRichard Henderson     uint64_t drir;
60080bb2ff7SRichard Henderson     int i;
60180bb2ff7SRichard Henderson 
60280bb2ff7SRichard Henderson     /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
60380bb2ff7SRichard Henderson     drir = s->cchip.drir;
60480bb2ff7SRichard Henderson     if (level) {
60580bb2ff7SRichard Henderson         drir |= 1ull << irq;
60680bb2ff7SRichard Henderson     } else {
60780bb2ff7SRichard Henderson         drir &= ~(1ull << irq);
60880bb2ff7SRichard Henderson     }
60980bb2ff7SRichard Henderson     s->cchip.drir = drir;
61080bb2ff7SRichard Henderson 
61180bb2ff7SRichard Henderson     for (i = 0; i < 4; ++i) {
61280bb2ff7SRichard Henderson         cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
61380bb2ff7SRichard Henderson     }
61480bb2ff7SRichard Henderson }
61580bb2ff7SRichard Henderson 
61680bb2ff7SRichard Henderson static void typhoon_set_isa_irq(void *opaque, int irq, int level)
61780bb2ff7SRichard Henderson {
61880bb2ff7SRichard Henderson     typhoon_set_irq(opaque, 55, level);
61980bb2ff7SRichard Henderson }
62080bb2ff7SRichard Henderson 
62180bb2ff7SRichard Henderson static void typhoon_set_timer_irq(void *opaque, int irq, int level)
62280bb2ff7SRichard Henderson {
62380bb2ff7SRichard Henderson     TyphoonState *s = opaque;
62480bb2ff7SRichard Henderson     int i;
62580bb2ff7SRichard Henderson 
62680bb2ff7SRichard Henderson     /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
62780bb2ff7SRichard Henderson        and so we don't have to worry about missing interrupts just
62880bb2ff7SRichard Henderson        because we never actually ACK the interrupt.  Just ignore any
62980bb2ff7SRichard Henderson        case of the interrupt level going low.  */
63080bb2ff7SRichard Henderson     if (level == 0) {
63180bb2ff7SRichard Henderson         return;
63280bb2ff7SRichard Henderson     }
63380bb2ff7SRichard Henderson 
63480bb2ff7SRichard Henderson     /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
63580bb2ff7SRichard Henderson     for (i = 0; i < 4; ++i) {
636ad601177SAndreas Färber         AlphaCPU *cpu = s->cchip.cpu[i];
637ad601177SAndreas Färber         if (cpu != NULL) {
63880bb2ff7SRichard Henderson             uint32_t iic = s->cchip.iic[i];
63980bb2ff7SRichard Henderson 
64080bb2ff7SRichard Henderson             /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
64180bb2ff7SRichard Henderson                Bit 24 is the OverFlow bit, RO, and set when the count
64280bb2ff7SRichard Henderson                decrements past 0.  When is OF cleared?  My guess is that
64380bb2ff7SRichard Henderson                OF is actually cleared when the IIC is written, and that
64480bb2ff7SRichard Henderson                the ICNT field always decrements.  At least, that's an
64580bb2ff7SRichard Henderson                interpretation that makes sense, and "allows the CPU to
64680bb2ff7SRichard Henderson                determine exactly how mant interval timer ticks were
64780bb2ff7SRichard Henderson                skipped".  At least within the next 4M ticks...  */
64880bb2ff7SRichard Henderson 
64980bb2ff7SRichard Henderson             iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
65080bb2ff7SRichard Henderson             s->cchip.iic[i] = iic;
65180bb2ff7SRichard Henderson 
65280bb2ff7SRichard Henderson             if (iic & 0x1000000) {
65380bb2ff7SRichard Henderson                 /* Set the ITI bit for this cpu.  */
65480bb2ff7SRichard Henderson                 s->cchip.misc |= 1 << (i + 4);
65580bb2ff7SRichard Henderson                 /* And signal the interrupt.  */
656c3affe56SAndreas Färber                 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
65780bb2ff7SRichard Henderson             }
65880bb2ff7SRichard Henderson         }
65980bb2ff7SRichard Henderson     }
66080bb2ff7SRichard Henderson }
66180bb2ff7SRichard Henderson 
662c781cf96SRichard Henderson static void typhoon_alarm_timer(void *opaque)
663c781cf96SRichard Henderson {
664c781cf96SRichard Henderson     TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
665c781cf96SRichard Henderson     int cpu = (uintptr_t)opaque & 3;
666c781cf96SRichard Henderson 
667c781cf96SRichard Henderson     /* Set the ITI bit for this cpu.  */
668c781cf96SRichard Henderson     s->cchip.misc |= 1 << (cpu + 4);
669c3affe56SAndreas Färber     cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
670c781cf96SRichard Henderson }
671c781cf96SRichard Henderson 
67271baa303SHervé Poussineau PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
67371baa303SHervé Poussineau                      qemu_irq *p_rtc_irq,
674ad601177SAndreas Färber                      AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
67580bb2ff7SRichard Henderson {
67680bb2ff7SRichard Henderson     const uint64_t MB = 1024 * 1024;
67780bb2ff7SRichard Henderson     const uint64_t GB = 1024 * MB;
67880bb2ff7SRichard Henderson     MemoryRegion *addr_space = get_system_memory();
67980bb2ff7SRichard Henderson     DeviceState *dev;
68080bb2ff7SRichard Henderson     TyphoonState *s;
68194dd91d6SAndreas Färber     PCIHostState *phb;
68280bb2ff7SRichard Henderson     PCIBus *b;
683c781cf96SRichard Henderson     int i;
68480bb2ff7SRichard Henderson 
68594dd91d6SAndreas Färber     dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
68680bb2ff7SRichard Henderson     qdev_init_nofail(dev);
68780bb2ff7SRichard Henderson 
68894dd91d6SAndreas Färber     s = TYPHOON_PCI_HOST_BRIDGE(dev);
6898558d942SAndreas Färber     phb = PCI_HOST_BRIDGE(dev);
69080bb2ff7SRichard Henderson 
69180bb2ff7SRichard Henderson     /* Remember the CPUs so that we can deliver interrupts to them.  */
692c781cf96SRichard Henderson     for (i = 0; i < 4; i++) {
693ad601177SAndreas Färber         AlphaCPU *cpu = cpus[i];
694ad601177SAndreas Färber         s->cchip.cpu[i] = cpu;
695ad601177SAndreas Färber         if (cpu != NULL) {
696*19e0cbb8SRichard Henderson             cpu->alarm_timer = qemu_new_timer_ns(vm_clock,
697c781cf96SRichard Henderson                                                  typhoon_alarm_timer,
698c781cf96SRichard Henderson                                                  (void *)((uintptr_t)s + i));
699c781cf96SRichard Henderson         }
700c781cf96SRichard Henderson     }
70180bb2ff7SRichard Henderson 
70280bb2ff7SRichard Henderson     *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
70380bb2ff7SRichard Henderson 
70480bb2ff7SRichard Henderson     /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
70580bb2ff7SRichard Henderson        but the address space hole reserved at this point is 8TB.  */
70664bde0f3SPaolo Bonzini     memory_region_init_ram(&s->ram_region, OBJECT(s), "ram", ram_size);
707c5705a77SAvi Kivity     vmstate_register_ram_global(&s->ram_region);
70880bb2ff7SRichard Henderson     memory_region_add_subregion(addr_space, 0, &s->ram_region);
70980bb2ff7SRichard Henderson 
71080bb2ff7SRichard Henderson     /* TIGbus, 0x801.0000.0000, 1GB.  */
71180bb2ff7SRichard Henderson     /* ??? The TIGbus is used for delivering interrupts, and access to
71280bb2ff7SRichard Henderson        the flash ROM.  I'm not sure that we need to implement it at all.  */
71380bb2ff7SRichard Henderson 
71480bb2ff7SRichard Henderson     /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
71564bde0f3SPaolo Bonzini     memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0",
71664bde0f3SPaolo Bonzini                           256*MB);
71702d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x80180000000ULL,
71802d6516cSStefan Weil                                 &s->pchip.region);
71980bb2ff7SRichard Henderson 
72080bb2ff7SRichard Henderson     /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
72164bde0f3SPaolo Bonzini     memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0",
72264bde0f3SPaolo Bonzini                           256*MB);
72302d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x801a0000000ULL,
72402d6516cSStefan Weil                                 &s->cchip.region);
72580bb2ff7SRichard Henderson 
72680bb2ff7SRichard Henderson     /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
72764bde0f3SPaolo Bonzini     memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0",
72864bde0f3SPaolo Bonzini                           256*MB);
72902d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x801b0000000ULL,
73002d6516cSStefan Weil                                 &s->dchip_region);
73180bb2ff7SRichard Henderson 
73280bb2ff7SRichard Henderson     /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
73364bde0f3SPaolo Bonzini     memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB);
73402d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x80000000000ULL,
73502d6516cSStefan Weil                                 &s->pchip.reg_mem);
73680bb2ff7SRichard Henderson 
73780bb2ff7SRichard Henderson     /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
7383661049fSRichard Henderson     memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops,
7393661049fSRichard Henderson                           NULL, "pci0-io", 32*MB);
74002d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x801fc000000ULL,
74102d6516cSStefan Weil                                 &s->pchip.reg_io);
74280bb2ff7SRichard Henderson 
74394dd91d6SAndreas Färber     b = pci_register_bus(dev, "pci",
74480bb2ff7SRichard Henderson                          typhoon_set_irq, sys_map_irq, s,
745056e6baeSRichard Henderson                          &s->pchip.reg_mem, &s->pchip.reg_io,
746056e6baeSRichard Henderson                          0, 64, TYPE_PCI_BUS);
74794dd91d6SAndreas Färber     phb->bus = b;
74880bb2ff7SRichard Henderson 
74980bb2ff7SRichard Henderson     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
750056e6baeSRichard Henderson     memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
751056e6baeSRichard Henderson                           b, "pci0-iack", 64*MB);
75202d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x801f8000000ULL,
75302d6516cSStefan Weil                                 &s->pchip.reg_iack);
75480bb2ff7SRichard Henderson 
75580bb2ff7SRichard Henderson     /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
756056e6baeSRichard Henderson     memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops,
757056e6baeSRichard Henderson                           b, "pci0-conf", 16*MB);
75802d6516cSStefan Weil     memory_region_add_subregion(addr_space, 0x801fe000000ULL,
75902d6516cSStefan Weil                                 &s->pchip.reg_conf);
76080bb2ff7SRichard Henderson 
76180bb2ff7SRichard Henderson     /* For the record, these are the mappings for the second PCI bus.
76280bb2ff7SRichard Henderson        We can get away with not implementing them because we indicate
76380bb2ff7SRichard Henderson        via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
76480bb2ff7SRichard Henderson     /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
76580bb2ff7SRichard Henderson     /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
76680bb2ff7SRichard Henderson     /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
76780bb2ff7SRichard Henderson     /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
76880bb2ff7SRichard Henderson     /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
76980bb2ff7SRichard Henderson 
77080bb2ff7SRichard Henderson     /* Init the ISA bus.  */
77180bb2ff7SRichard Henderson     /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
77280bb2ff7SRichard Henderson     {
77380bb2ff7SRichard Henderson         qemu_irq isa_pci_irq, *isa_irqs;
77480bb2ff7SRichard Henderson 
775056e6baeSRichard Henderson         *isa_bus = isa_bus_new(NULL, &s->pchip.reg_io);
77680bb2ff7SRichard Henderson         isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
77771baa303SHervé Poussineau         isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
77871baa303SHervé Poussineau         isa_bus_irqs(*isa_bus, isa_irqs);
77980bb2ff7SRichard Henderson     }
78080bb2ff7SRichard Henderson 
78180bb2ff7SRichard Henderson     return b;
78280bb2ff7SRichard Henderson }
78380bb2ff7SRichard Henderson 
78480bb2ff7SRichard Henderson static int typhoon_pcihost_init(SysBusDevice *dev)
78580bb2ff7SRichard Henderson {
78680bb2ff7SRichard Henderson     return 0;
78780bb2ff7SRichard Henderson }
78880bb2ff7SRichard Henderson 
789999e12bbSAnthony Liguori static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
790999e12bbSAnthony Liguori {
79139bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
792999e12bbSAnthony Liguori     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
793999e12bbSAnthony Liguori 
794999e12bbSAnthony Liguori     k->init = typhoon_pcihost_init;
79539bffca2SAnthony Liguori     dc->no_user = 1;
796999e12bbSAnthony Liguori }
797999e12bbSAnthony Liguori 
7984240abffSAndreas Färber static const TypeInfo typhoon_pcihost_info = {
79994dd91d6SAndreas Färber     .name          = TYPE_TYPHOON_PCI_HOST_BRIDGE,
8008558d942SAndreas Färber     .parent        = TYPE_PCI_HOST_BRIDGE,
80139bffca2SAnthony Liguori     .instance_size = sizeof(TyphoonState),
802999e12bbSAnthony Liguori     .class_init    = typhoon_pcihost_class_init,
80380bb2ff7SRichard Henderson };
80480bb2ff7SRichard Henderson 
80583f7d43aSAndreas Färber static void typhoon_register_types(void)
80680bb2ff7SRichard Henderson {
80739bffca2SAnthony Liguori     type_register_static(&typhoon_pcihost_info);
80880bb2ff7SRichard Henderson }
80983f7d43aSAndreas Färber 
81083f7d43aSAndreas Färber type_init(typhoon_register_types)
811