Statistics
| Branch: | Revision:

root / hw / alpha / typhoon.c @ a8aec295

History | View | Annotate | Download (23.7 kB)

1 80bb2ff7 Richard Henderson
/*
2 80bb2ff7 Richard Henderson
 * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation.
3 80bb2ff7 Richard Henderson
 *
4 80bb2ff7 Richard Henderson
 * Written by Richard Henderson.
5 80bb2ff7 Richard Henderson
 *
6 80bb2ff7 Richard Henderson
 * This work is licensed under the GNU GPL license version 2 or later.
7 80bb2ff7 Richard Henderson
 */
8 80bb2ff7 Richard Henderson
9 80bb2ff7 Richard Henderson
#include "cpu.h"
10 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
11 bd2be150 Peter Maydell
#include "hw/devices.h"
12 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
13 47b43a1f Paolo Bonzini
#include "alpha_sys.h"
14 022c62cb Paolo Bonzini
#include "exec/address-spaces.h"
15 80bb2ff7 Richard Henderson
16 80bb2ff7 Richard Henderson
17 94dd91d6 Andreas Färber
#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
18 94dd91d6 Andreas Färber
19 80bb2ff7 Richard Henderson
typedef struct TyphoonCchip {
20 80bb2ff7 Richard Henderson
    MemoryRegion region;
21 80bb2ff7 Richard Henderson
    uint64_t misc;
22 80bb2ff7 Richard Henderson
    uint64_t drir;
23 80bb2ff7 Richard Henderson
    uint64_t dim[4];
24 80bb2ff7 Richard Henderson
    uint32_t iic[4];
25 ad601177 Andreas Färber
    AlphaCPU *cpu[4];
26 80bb2ff7 Richard Henderson
} TyphoonCchip;
27 80bb2ff7 Richard Henderson
28 80bb2ff7 Richard Henderson
typedef struct TyphoonWindow {
29 80bb2ff7 Richard Henderson
    uint32_t base_addr;
30 80bb2ff7 Richard Henderson
    uint32_t mask;
31 80bb2ff7 Richard Henderson
    uint32_t translated_base_pfn;
32 80bb2ff7 Richard Henderson
} TyphoonWindow;
33 80bb2ff7 Richard Henderson
 
34 80bb2ff7 Richard Henderson
typedef struct TyphoonPchip {
35 80bb2ff7 Richard Henderson
    MemoryRegion region;
36 80bb2ff7 Richard Henderson
    MemoryRegion reg_iack;
37 80bb2ff7 Richard Henderson
    MemoryRegion reg_mem;
38 80bb2ff7 Richard Henderson
    MemoryRegion reg_io;
39 80bb2ff7 Richard Henderson
    MemoryRegion reg_conf;
40 80bb2ff7 Richard Henderson
    uint64_t ctl;
41 80bb2ff7 Richard Henderson
    TyphoonWindow win[4];
42 80bb2ff7 Richard Henderson
} TyphoonPchip;
43 80bb2ff7 Richard Henderson
44 94dd91d6 Andreas Färber
#define TYPHOON_PCI_HOST_BRIDGE(obj) \
45 94dd91d6 Andreas Färber
    OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
46 94dd91d6 Andreas Färber
47 80bb2ff7 Richard Henderson
typedef struct TyphoonState {
48 67c332fd Andreas Färber
    PCIHostState parent_obj;
49 94dd91d6 Andreas Färber
50 80bb2ff7 Richard Henderson
    TyphoonCchip cchip;
51 80bb2ff7 Richard Henderson
    TyphoonPchip pchip;
52 80bb2ff7 Richard Henderson
    MemoryRegion dchip_region;
53 80bb2ff7 Richard Henderson
    MemoryRegion ram_region;
54 80bb2ff7 Richard Henderson
55 80bb2ff7 Richard Henderson
    /* QEMU emulation state.  */
56 80bb2ff7 Richard Henderson
    uint32_t latch_tmp;
57 80bb2ff7 Richard Henderson
} TyphoonState;
58 80bb2ff7 Richard Henderson
59 80bb2ff7 Richard Henderson
/* Called when one of DRIR or DIM changes.  */
60 ad601177 Andreas Färber
static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
61 80bb2ff7 Richard Henderson
{
62 80bb2ff7 Richard Henderson
    /* If there are any non-masked interrupts, tell the cpu.  */
63 ad601177 Andreas Färber
    if (cpu != NULL) {
64 d8ed887b Andreas Färber
        CPUState *cs = CPU(cpu);
65 80bb2ff7 Richard Henderson
        if (req) {
66 c3affe56 Andreas Färber
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
67 80bb2ff7 Richard Henderson
        } else {
68 d8ed887b Andreas Färber
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
69 80bb2ff7 Richard Henderson
        }
70 80bb2ff7 Richard Henderson
    }
71 80bb2ff7 Richard Henderson
}
72 80bb2ff7 Richard Henderson
73 a8170e5e Avi Kivity
static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
74 80bb2ff7 Richard Henderson
{
75 8b2aee29 Andreas Färber
    CPUAlphaState *env = cpu_single_env;
76 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
77 55e5c285 Andreas Färber
    CPUState *cpu;
78 80bb2ff7 Richard Henderson
    uint64_t ret = 0;
79 80bb2ff7 Richard Henderson
80 80bb2ff7 Richard Henderson
    if (addr & 4) {
81 80bb2ff7 Richard Henderson
        return s->latch_tmp;
82 80bb2ff7 Richard Henderson
    }
83 80bb2ff7 Richard Henderson
84 80bb2ff7 Richard Henderson
    switch (addr) {
85 80bb2ff7 Richard Henderson
    case 0x0000:
86 80bb2ff7 Richard Henderson
        /* CSC: Cchip System Configuration Register.  */
87 80bb2ff7 Richard Henderson
        /* All sorts of data here; probably the only thing relevant is
88 80bb2ff7 Richard Henderson
           PIP<14> Pchip 1 Present = 0.  */
89 80bb2ff7 Richard Henderson
        break;
90 80bb2ff7 Richard Henderson
91 80bb2ff7 Richard Henderson
    case 0x0040:
92 80bb2ff7 Richard Henderson
        /* MTR: Memory Timing Register.  */
93 80bb2ff7 Richard Henderson
        /* All sorts of stuff related to real DRAM.  */
94 80bb2ff7 Richard Henderson
        break;
95 80bb2ff7 Richard Henderson
96 80bb2ff7 Richard Henderson
    case 0x0080:
97 80bb2ff7 Richard Henderson
        /* MISC: Miscellaneous Register.  */
98 55e5c285 Andreas Färber
        cpu = ENV_GET_CPU(env);
99 55e5c285 Andreas Färber
        ret = s->cchip.misc | (cpu->cpu_index & 3);
100 80bb2ff7 Richard Henderson
        break;
101 80bb2ff7 Richard Henderson
102 80bb2ff7 Richard Henderson
    case 0x00c0:
103 80bb2ff7 Richard Henderson
        /* MPD: Memory Presence Detect Register.  */
104 80bb2ff7 Richard Henderson
        break;
105 80bb2ff7 Richard Henderson
106 80bb2ff7 Richard Henderson
    case 0x0100: /* AAR0 */
107 80bb2ff7 Richard Henderson
    case 0x0140: /* AAR1 */
108 80bb2ff7 Richard Henderson
    case 0x0180: /* AAR2 */
109 80bb2ff7 Richard Henderson
    case 0x01c0: /* AAR3 */
110 80bb2ff7 Richard Henderson
        /* AAR: Array Address Register.  */
111 80bb2ff7 Richard Henderson
        /* All sorts of information about DRAM.  */
112 80bb2ff7 Richard Henderson
        break;
113 80bb2ff7 Richard Henderson
114 80bb2ff7 Richard Henderson
    case 0x0200:
115 80bb2ff7 Richard Henderson
        /* DIM0: Device Interrupt Mask Register, CPU0.  */
116 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[0];
117 80bb2ff7 Richard Henderson
        break;
118 80bb2ff7 Richard Henderson
    case 0x0240:
119 80bb2ff7 Richard Henderson
        /* DIM1: Device Interrupt Mask Register, CPU1.  */
120 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[1];
121 80bb2ff7 Richard Henderson
        break;
122 80bb2ff7 Richard Henderson
    case 0x0280:
123 80bb2ff7 Richard Henderson
        /* DIR0: Device Interrupt Request Register, CPU0.  */
124 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[0] & s->cchip.drir;
125 80bb2ff7 Richard Henderson
        break;
126 80bb2ff7 Richard Henderson
    case 0x02c0:
127 80bb2ff7 Richard Henderson
        /* DIR1: Device Interrupt Request Register, CPU1.  */
128 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[1] & s->cchip.drir;
129 80bb2ff7 Richard Henderson
        break;
130 80bb2ff7 Richard Henderson
    case 0x0300:
131 80bb2ff7 Richard Henderson
        /* DRIR: Device Raw Interrupt Request Register.  */
132 80bb2ff7 Richard Henderson
        ret = s->cchip.drir;
133 80bb2ff7 Richard Henderson
        break;
134 80bb2ff7 Richard Henderson
135 80bb2ff7 Richard Henderson
    case 0x0340:
136 80bb2ff7 Richard Henderson
        /* PRBEN: Probe Enable Register.  */
137 80bb2ff7 Richard Henderson
        break;
138 80bb2ff7 Richard Henderson
139 80bb2ff7 Richard Henderson
    case 0x0380:
140 80bb2ff7 Richard Henderson
        /* IIC0: Interval Ignore Count Register, CPU0.  */
141 80bb2ff7 Richard Henderson
        ret = s->cchip.iic[0];
142 80bb2ff7 Richard Henderson
        break;
143 80bb2ff7 Richard Henderson
    case 0x03c0:
144 80bb2ff7 Richard Henderson
        /* IIC1: Interval Ignore Count Register, CPU1.  */
145 80bb2ff7 Richard Henderson
        ret = s->cchip.iic[1];
146 80bb2ff7 Richard Henderson
        break;
147 80bb2ff7 Richard Henderson
148 80bb2ff7 Richard Henderson
    case 0x0400: /* MPR0 */
149 80bb2ff7 Richard Henderson
    case 0x0440: /* MPR1 */
150 80bb2ff7 Richard Henderson
    case 0x0480: /* MPR2 */
151 80bb2ff7 Richard Henderson
    case 0x04c0: /* MPR3 */
152 80bb2ff7 Richard Henderson
        /* MPR: Memory Programming Register.  */
153 80bb2ff7 Richard Henderson
        break;
154 80bb2ff7 Richard Henderson
155 80bb2ff7 Richard Henderson
    case 0x0580:
156 80bb2ff7 Richard Henderson
        /* TTR: TIGbus Timing Register.  */
157 80bb2ff7 Richard Henderson
        /* All sorts of stuff related to interrupt delivery timings.  */
158 80bb2ff7 Richard Henderson
        break;
159 80bb2ff7 Richard Henderson
    case 0x05c0:
160 80bb2ff7 Richard Henderson
        /* TDR: TIGbug Device Timing Register.  */
161 80bb2ff7 Richard Henderson
        break;
162 80bb2ff7 Richard Henderson
163 80bb2ff7 Richard Henderson
    case 0x0600:
164 80bb2ff7 Richard Henderson
        /* DIM2: Device Interrupt Mask Register, CPU2.  */
165 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[2];
166 80bb2ff7 Richard Henderson
        break;
167 80bb2ff7 Richard Henderson
    case 0x0640:
168 80bb2ff7 Richard Henderson
        /* DIM3: Device Interrupt Mask Register, CPU3.  */
169 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[3];
170 80bb2ff7 Richard Henderson
        break;
171 80bb2ff7 Richard Henderson
    case 0x0680:
172 80bb2ff7 Richard Henderson
        /* DIR2: Device Interrupt Request Register, CPU2.  */
173 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[2] & s->cchip.drir;
174 80bb2ff7 Richard Henderson
        break;
175 80bb2ff7 Richard Henderson
    case 0x06c0:
176 80bb2ff7 Richard Henderson
        /* DIR3: Device Interrupt Request Register, CPU3.  */
177 80bb2ff7 Richard Henderson
        ret = s->cchip.dim[3] & s->cchip.drir;
178 80bb2ff7 Richard Henderson
        break;
179 80bb2ff7 Richard Henderson
180 80bb2ff7 Richard Henderson
    case 0x0700:
181 80bb2ff7 Richard Henderson
        /* IIC2: Interval Ignore Count Register, CPU2.  */
182 80bb2ff7 Richard Henderson
        ret = s->cchip.iic[2];
183 80bb2ff7 Richard Henderson
        break;
184 80bb2ff7 Richard Henderson
    case 0x0740:
185 80bb2ff7 Richard Henderson
        /* IIC3: Interval Ignore Count Register, CPU3.  */
186 80bb2ff7 Richard Henderson
        ret = s->cchip.iic[3];
187 80bb2ff7 Richard Henderson
        break;
188 80bb2ff7 Richard Henderson
189 80bb2ff7 Richard Henderson
    case 0x0780:
190 80bb2ff7 Richard Henderson
        /* PWR: Power Management Control.   */
191 80bb2ff7 Richard Henderson
        break;
192 80bb2ff7 Richard Henderson
    
193 80bb2ff7 Richard Henderson
    case 0x0c00: /* CMONCTLA */
194 80bb2ff7 Richard Henderson
    case 0x0c40: /* CMONCTLB */
195 80bb2ff7 Richard Henderson
    case 0x0c80: /* CMONCNT01 */
196 80bb2ff7 Richard Henderson
    case 0x0cc0: /* CMONCNT23 */
197 80bb2ff7 Richard Henderson
        break;
198 80bb2ff7 Richard Henderson
199 80bb2ff7 Richard Henderson
    default:
200 c658b94f Andreas Färber
        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
201 c658b94f Andreas Färber
        cpu_unassigned_access(cpu, addr, false, false, 0, size);
202 80bb2ff7 Richard Henderson
        return -1;
203 80bb2ff7 Richard Henderson
    }
204 80bb2ff7 Richard Henderson
205 80bb2ff7 Richard Henderson
    s->latch_tmp = ret >> 32;
206 80bb2ff7 Richard Henderson
    return ret;
207 80bb2ff7 Richard Henderson
}
208 80bb2ff7 Richard Henderson
209 a8170e5e Avi Kivity
static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
210 80bb2ff7 Richard Henderson
{
211 80bb2ff7 Richard Henderson
    /* Skip this.  It's all related to DRAM timing and setup.  */
212 80bb2ff7 Richard Henderson
    return 0;
213 80bb2ff7 Richard Henderson
}
214 80bb2ff7 Richard Henderson
215 a8170e5e Avi Kivity
static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
216 80bb2ff7 Richard Henderson
{
217 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
218 c658b94f Andreas Färber
    CPUState *cs;
219 80bb2ff7 Richard Henderson
    uint64_t ret = 0;
220 80bb2ff7 Richard Henderson
221 80bb2ff7 Richard Henderson
    if (addr & 4) {
222 80bb2ff7 Richard Henderson
        return s->latch_tmp;
223 80bb2ff7 Richard Henderson
    }
224 80bb2ff7 Richard Henderson
225 80bb2ff7 Richard Henderson
    switch (addr) {
226 80bb2ff7 Richard Henderson
    case 0x0000:
227 80bb2ff7 Richard Henderson
        /* WSBA0: Window Space Base Address Register.  */
228 80bb2ff7 Richard Henderson
        ret = s->pchip.win[0].base_addr;
229 80bb2ff7 Richard Henderson
        break;
230 80bb2ff7 Richard Henderson
    case 0x0040:
231 80bb2ff7 Richard Henderson
        /* WSBA1 */
232 80bb2ff7 Richard Henderson
        ret = s->pchip.win[1].base_addr;
233 80bb2ff7 Richard Henderson
        break;
234 80bb2ff7 Richard Henderson
    case 0x0080:
235 80bb2ff7 Richard Henderson
        /* WSBA2 */
236 80bb2ff7 Richard Henderson
        ret = s->pchip.win[2].base_addr;
237 80bb2ff7 Richard Henderson
        break;
238 80bb2ff7 Richard Henderson
    case 0x00c0:
239 80bb2ff7 Richard Henderson
        /* WSBA3 */
240 80bb2ff7 Richard Henderson
        ret = s->pchip.win[3].base_addr;
241 80bb2ff7 Richard Henderson
        break;
242 80bb2ff7 Richard Henderson
243 80bb2ff7 Richard Henderson
    case 0x0100:
244 80bb2ff7 Richard Henderson
        /* WSM0: Window Space Mask Register.  */
245 80bb2ff7 Richard Henderson
        ret = s->pchip.win[0].mask;
246 80bb2ff7 Richard Henderson
        break;
247 80bb2ff7 Richard Henderson
    case 0x0140:
248 80bb2ff7 Richard Henderson
        /* WSM1 */
249 80bb2ff7 Richard Henderson
        ret = s->pchip.win[1].mask;
250 80bb2ff7 Richard Henderson
        break;
251 80bb2ff7 Richard Henderson
    case 0x0180:
252 80bb2ff7 Richard Henderson
        /* WSM2 */
253 80bb2ff7 Richard Henderson
        ret = s->pchip.win[2].mask;
254 80bb2ff7 Richard Henderson
        break;
255 80bb2ff7 Richard Henderson
    case 0x01c0:
256 80bb2ff7 Richard Henderson
        /* WSM3 */
257 80bb2ff7 Richard Henderson
        ret = s->pchip.win[3].mask;
258 80bb2ff7 Richard Henderson
        break;
259 80bb2ff7 Richard Henderson
260 80bb2ff7 Richard Henderson
    case 0x0200:
261 80bb2ff7 Richard Henderson
        /* TBA0: Translated Base Address Register.  */
262 80bb2ff7 Richard Henderson
        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
263 80bb2ff7 Richard Henderson
        break;
264 80bb2ff7 Richard Henderson
    case 0x0240:
265 80bb2ff7 Richard Henderson
        /* TBA1 */
266 80bb2ff7 Richard Henderson
        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
267 80bb2ff7 Richard Henderson
        break;
268 80bb2ff7 Richard Henderson
    case 0x0280:
269 80bb2ff7 Richard Henderson
        /* TBA2 */
270 80bb2ff7 Richard Henderson
        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
271 80bb2ff7 Richard Henderson
        break;
272 80bb2ff7 Richard Henderson
    case 0x02c0:
273 80bb2ff7 Richard Henderson
        /* TBA3 */
274 80bb2ff7 Richard Henderson
        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
275 80bb2ff7 Richard Henderson
        break;
276 80bb2ff7 Richard Henderson
277 80bb2ff7 Richard Henderson
    case 0x0300:
278 80bb2ff7 Richard Henderson
        /* PCTL: Pchip Control Register.  */
279 80bb2ff7 Richard Henderson
        ret = s->pchip.ctl;
280 80bb2ff7 Richard Henderson
        break;
281 80bb2ff7 Richard Henderson
    case 0x0340:
282 80bb2ff7 Richard Henderson
        /* PLAT: Pchip Master Latency Register.  */
283 80bb2ff7 Richard Henderson
        break;
284 80bb2ff7 Richard Henderson
    case 0x03c0:
285 80bb2ff7 Richard Henderson
        /* PERROR: Pchip Error Register.  */
286 80bb2ff7 Richard Henderson
        break;
287 80bb2ff7 Richard Henderson
    case 0x0400:
288 80bb2ff7 Richard Henderson
        /* PERRMASK: Pchip Error Mask Register.  */
289 80bb2ff7 Richard Henderson
        break;
290 80bb2ff7 Richard Henderson
    case 0x0440:
291 80bb2ff7 Richard Henderson
        /* PERRSET: Pchip Error Set Register.  */
292 80bb2ff7 Richard Henderson
        break;
293 80bb2ff7 Richard Henderson
    case 0x0480:
294 80bb2ff7 Richard Henderson
        /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
295 80bb2ff7 Richard Henderson
        break;
296 80bb2ff7 Richard Henderson
    case 0x04c0:
297 80bb2ff7 Richard Henderson
        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
298 80bb2ff7 Richard Henderson
        break;
299 80bb2ff7 Richard Henderson
    case 0x0500: /* PMONCTL */
300 80bb2ff7 Richard Henderson
    case 0x0540: /* PMONCNT */
301 80bb2ff7 Richard Henderson
    case 0x0800: /* SPRST */
302 80bb2ff7 Richard Henderson
        break;
303 80bb2ff7 Richard Henderson
304 80bb2ff7 Richard Henderson
    default:
305 c658b94f Andreas Färber
        cs = CPU(alpha_env_get_cpu(cpu_single_env));
306 c658b94f Andreas Färber
        cpu_unassigned_access(cs, addr, false, false, 0, size);
307 80bb2ff7 Richard Henderson
        return -1;
308 80bb2ff7 Richard Henderson
    }
309 80bb2ff7 Richard Henderson
310 80bb2ff7 Richard Henderson
    s->latch_tmp = ret >> 32;
311 80bb2ff7 Richard Henderson
    return ret;
312 80bb2ff7 Richard Henderson
}
313 80bb2ff7 Richard Henderson
314 a8170e5e Avi Kivity
static void cchip_write(void *opaque, hwaddr addr,
315 80bb2ff7 Richard Henderson
                        uint64_t v32, unsigned size)
316 80bb2ff7 Richard Henderson
{
317 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
318 c658b94f Andreas Färber
    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
319 80bb2ff7 Richard Henderson
    uint64_t val, oldval, newval;
320 80bb2ff7 Richard Henderson
321 80bb2ff7 Richard Henderson
    if (addr & 4) {
322 80bb2ff7 Richard Henderson
        val = v32 << 32 | s->latch_tmp;
323 80bb2ff7 Richard Henderson
        addr ^= 4;
324 80bb2ff7 Richard Henderson
    } else {
325 80bb2ff7 Richard Henderson
        s->latch_tmp = v32;
326 80bb2ff7 Richard Henderson
        return;
327 80bb2ff7 Richard Henderson
    }
328 80bb2ff7 Richard Henderson
329 80bb2ff7 Richard Henderson
    switch (addr) {
330 80bb2ff7 Richard Henderson
    case 0x0000:
331 80bb2ff7 Richard Henderson
        /* CSC: Cchip System Configuration Register.  */
332 80bb2ff7 Richard Henderson
        /* All sorts of data here; nothing relevant RW.  */
333 80bb2ff7 Richard Henderson
        break;
334 80bb2ff7 Richard Henderson
335 80bb2ff7 Richard Henderson
    case 0x0040:
336 80bb2ff7 Richard Henderson
        /* MTR: Memory Timing Register.  */
337 80bb2ff7 Richard Henderson
        /* All sorts of stuff related to real DRAM.  */
338 80bb2ff7 Richard Henderson
        break;
339 80bb2ff7 Richard Henderson
340 80bb2ff7 Richard Henderson
    case 0x0080:
341 80bb2ff7 Richard Henderson
        /* MISC: Miscellaneous Register.  */
342 80bb2ff7 Richard Henderson
        newval = oldval = s->cchip.misc;
343 80bb2ff7 Richard Henderson
        newval &= ~(val & 0x10000ff0);     /* W1C fields */
344 80bb2ff7 Richard Henderson
        if (val & 0x100000) {
345 80bb2ff7 Richard Henderson
            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
346 80bb2ff7 Richard Henderson
        } else {
347 80bb2ff7 Richard Henderson
            newval |= val & 0x00f00000;    /* ABT field is W1S */
348 80bb2ff7 Richard Henderson
            if ((newval & 0xf0000) == 0) {
349 80bb2ff7 Richard Henderson
                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
350 80bb2ff7 Richard Henderson
            }
351 80bb2ff7 Richard Henderson
        }
352 80bb2ff7 Richard Henderson
        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
353 80bb2ff7 Richard Henderson
354 80bb2ff7 Richard Henderson
        newval &= ~0xf0000000000ull;       /* WO and RW fields */
355 80bb2ff7 Richard Henderson
        newval |= val & 0xf0000000000ull;
356 80bb2ff7 Richard Henderson
        s->cchip.misc = newval;
357 80bb2ff7 Richard Henderson
358 80bb2ff7 Richard Henderson
        /* Pass on changes to IPI and ITI state.  */
359 80bb2ff7 Richard Henderson
        if ((newval ^ oldval) & 0xff0) {
360 80bb2ff7 Richard Henderson
            int i;
361 80bb2ff7 Richard Henderson
            for (i = 0; i < 4; ++i) {
362 ad601177 Andreas Färber
                AlphaCPU *cpu = s->cchip.cpu[i];
363 ad601177 Andreas Färber
                if (cpu != NULL) {
364 d8ed887b Andreas Färber
                    CPUState *cs = CPU(cpu);
365 80bb2ff7 Richard Henderson
                    /* IPI can be either cleared or set by the write.  */
366 80bb2ff7 Richard Henderson
                    if (newval & (1 << (i + 8))) {
367 c3affe56 Andreas Färber
                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
368 80bb2ff7 Richard Henderson
                    } else {
369 d8ed887b Andreas Färber
                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
370 80bb2ff7 Richard Henderson
                    }
371 80bb2ff7 Richard Henderson
372 80bb2ff7 Richard Henderson
                    /* ITI can only be cleared by the write.  */
373 80bb2ff7 Richard Henderson
                    if ((newval & (1 << (i + 4))) == 0) {
374 d8ed887b Andreas Färber
                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
375 80bb2ff7 Richard Henderson
                    }
376 80bb2ff7 Richard Henderson
                }
377 80bb2ff7 Richard Henderson
            }
378 80bb2ff7 Richard Henderson
        }
379 80bb2ff7 Richard Henderson
        break;
380 80bb2ff7 Richard Henderson
381 80bb2ff7 Richard Henderson
    case 0x00c0:
382 80bb2ff7 Richard Henderson
        /* MPD: Memory Presence Detect Register.  */
383 80bb2ff7 Richard Henderson
        break;
384 80bb2ff7 Richard Henderson
385 80bb2ff7 Richard Henderson
    case 0x0100: /* AAR0 */
386 80bb2ff7 Richard Henderson
    case 0x0140: /* AAR1 */
387 80bb2ff7 Richard Henderson
    case 0x0180: /* AAR2 */
388 80bb2ff7 Richard Henderson
    case 0x01c0: /* AAR3 */
389 80bb2ff7 Richard Henderson
        /* AAR: Array Address Register.  */
390 80bb2ff7 Richard Henderson
        /* All sorts of information about DRAM.  */
391 80bb2ff7 Richard Henderson
        break;
392 80bb2ff7 Richard Henderson
393 80bb2ff7 Richard Henderson
    case 0x0200: /* DIM0 */
394 80bb2ff7 Richard Henderson
        /* DIM: Device Interrupt Mask Register, CPU0.  */
395 80bb2ff7 Richard Henderson
        s->cchip.dim[0] = val;
396 80bb2ff7 Richard Henderson
        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
397 80bb2ff7 Richard Henderson
        break;
398 80bb2ff7 Richard Henderson
    case 0x0240: /* DIM1 */
399 80bb2ff7 Richard Henderson
        /* DIM: Device Interrupt Mask Register, CPU1.  */
400 80bb2ff7 Richard Henderson
        s->cchip.dim[0] = val;
401 80bb2ff7 Richard Henderson
        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
402 80bb2ff7 Richard Henderson
        break;
403 80bb2ff7 Richard Henderson
404 80bb2ff7 Richard Henderson
    case 0x0280: /* DIR0 (RO) */
405 80bb2ff7 Richard Henderson
    case 0x02c0: /* DIR1 (RO) */
406 80bb2ff7 Richard Henderson
    case 0x0300: /* DRIR (RO) */
407 80bb2ff7 Richard Henderson
        break;
408 80bb2ff7 Richard Henderson
409 80bb2ff7 Richard Henderson
    case 0x0340:
410 80bb2ff7 Richard Henderson
        /* PRBEN: Probe Enable Register.  */
411 80bb2ff7 Richard Henderson
        break;
412 80bb2ff7 Richard Henderson
413 80bb2ff7 Richard Henderson
    case 0x0380: /* IIC0 */
414 80bb2ff7 Richard Henderson
        s->cchip.iic[0] = val & 0xffffff;
415 80bb2ff7 Richard Henderson
        break;
416 80bb2ff7 Richard Henderson
    case 0x03c0: /* IIC1 */
417 80bb2ff7 Richard Henderson
        s->cchip.iic[1] = val & 0xffffff;
418 80bb2ff7 Richard Henderson
        break;
419 80bb2ff7 Richard Henderson
420 80bb2ff7 Richard Henderson
    case 0x0400: /* MPR0 */
421 80bb2ff7 Richard Henderson
    case 0x0440: /* MPR1 */
422 80bb2ff7 Richard Henderson
    case 0x0480: /* MPR2 */
423 80bb2ff7 Richard Henderson
    case 0x04c0: /* MPR3 */
424 80bb2ff7 Richard Henderson
        /* MPR: Memory Programming Register.  */
425 80bb2ff7 Richard Henderson
        break;
426 80bb2ff7 Richard Henderson
427 80bb2ff7 Richard Henderson
    case 0x0580:
428 80bb2ff7 Richard Henderson
        /* TTR: TIGbus Timing Register.  */
429 80bb2ff7 Richard Henderson
        /* All sorts of stuff related to interrupt delivery timings.  */
430 80bb2ff7 Richard Henderson
        break;
431 80bb2ff7 Richard Henderson
    case 0x05c0:
432 80bb2ff7 Richard Henderson
        /* TDR: TIGbug Device Timing Register.  */
433 80bb2ff7 Richard Henderson
        break;
434 80bb2ff7 Richard Henderson
435 80bb2ff7 Richard Henderson
    case 0x0600:
436 80bb2ff7 Richard Henderson
        /* DIM2: Device Interrupt Mask Register, CPU2.  */
437 80bb2ff7 Richard Henderson
        s->cchip.dim[2] = val;
438 80bb2ff7 Richard Henderson
        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
439 80bb2ff7 Richard Henderson
        break;
440 80bb2ff7 Richard Henderson
    case 0x0640:
441 80bb2ff7 Richard Henderson
        /* DIM3: Device Interrupt Mask Register, CPU3.  */
442 80bb2ff7 Richard Henderson
        s->cchip.dim[3] = val;
443 80bb2ff7 Richard Henderson
        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
444 80bb2ff7 Richard Henderson
        break;
445 80bb2ff7 Richard Henderson
446 80bb2ff7 Richard Henderson
    case 0x0680: /* DIR2 (RO) */
447 80bb2ff7 Richard Henderson
    case 0x06c0: /* DIR3 (RO) */
448 80bb2ff7 Richard Henderson
        break;
449 80bb2ff7 Richard Henderson
450 80bb2ff7 Richard Henderson
    case 0x0700: /* IIC2 */
451 80bb2ff7 Richard Henderson
        s->cchip.iic[2] = val & 0xffffff;
452 80bb2ff7 Richard Henderson
        break;
453 80bb2ff7 Richard Henderson
    case 0x0740: /* IIC3 */
454 80bb2ff7 Richard Henderson
        s->cchip.iic[3] = val & 0xffffff;
455 80bb2ff7 Richard Henderson
        break;
456 80bb2ff7 Richard Henderson
457 80bb2ff7 Richard Henderson
    case 0x0780:
458 80bb2ff7 Richard Henderson
        /* PWR: Power Management Control.   */
459 80bb2ff7 Richard Henderson
        break;
460 80bb2ff7 Richard Henderson
    
461 80bb2ff7 Richard Henderson
    case 0x0c00: /* CMONCTLA */
462 80bb2ff7 Richard Henderson
    case 0x0c40: /* CMONCTLB */
463 80bb2ff7 Richard Henderson
    case 0x0c80: /* CMONCNT01 */
464 80bb2ff7 Richard Henderson
    case 0x0cc0: /* CMONCNT23 */
465 80bb2ff7 Richard Henderson
        break;
466 80bb2ff7 Richard Henderson
467 80bb2ff7 Richard Henderson
    default:
468 c658b94f Andreas Färber
        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
469 80bb2ff7 Richard Henderson
        return;
470 80bb2ff7 Richard Henderson
    }
471 80bb2ff7 Richard Henderson
}
472 80bb2ff7 Richard Henderson
473 a8170e5e Avi Kivity
static void dchip_write(void *opaque, hwaddr addr,
474 80bb2ff7 Richard Henderson
                        uint64_t val, unsigned size)
475 80bb2ff7 Richard Henderson
{
476 80bb2ff7 Richard Henderson
    /* Skip this.  It's all related to DRAM timing and setup.  */
477 80bb2ff7 Richard Henderson
}
478 80bb2ff7 Richard Henderson
479 a8170e5e Avi Kivity
static void pchip_write(void *opaque, hwaddr addr,
480 80bb2ff7 Richard Henderson
                        uint64_t v32, unsigned size)
481 80bb2ff7 Richard Henderson
{
482 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
483 c658b94f Andreas Färber
    CPUState *cs;
484 80bb2ff7 Richard Henderson
    uint64_t val, oldval;
485 80bb2ff7 Richard Henderson
486 80bb2ff7 Richard Henderson
    if (addr & 4) {
487 80bb2ff7 Richard Henderson
        val = v32 << 32 | s->latch_tmp;
488 80bb2ff7 Richard Henderson
        addr ^= 4;
489 80bb2ff7 Richard Henderson
    } else {
490 80bb2ff7 Richard Henderson
        s->latch_tmp = v32;
491 80bb2ff7 Richard Henderson
        return;
492 80bb2ff7 Richard Henderson
    }
493 80bb2ff7 Richard Henderson
494 80bb2ff7 Richard Henderson
    switch (addr) {
495 80bb2ff7 Richard Henderson
    case 0x0000:
496 80bb2ff7 Richard Henderson
        /* WSBA0: Window Space Base Address Register.  */
497 80bb2ff7 Richard Henderson
        s->pchip.win[0].base_addr = val;
498 80bb2ff7 Richard Henderson
        break;
499 80bb2ff7 Richard Henderson
    case 0x0040:
500 80bb2ff7 Richard Henderson
        /* WSBA1 */
501 80bb2ff7 Richard Henderson
        s->pchip.win[1].base_addr = val;
502 80bb2ff7 Richard Henderson
        break;
503 80bb2ff7 Richard Henderson
    case 0x0080:
504 80bb2ff7 Richard Henderson
        /* WSBA2 */
505 80bb2ff7 Richard Henderson
        s->pchip.win[2].base_addr = val;
506 80bb2ff7 Richard Henderson
        break;
507 80bb2ff7 Richard Henderson
    case 0x00c0:
508 80bb2ff7 Richard Henderson
        /* WSBA3 */
509 80bb2ff7 Richard Henderson
        s->pchip.win[3].base_addr = val;
510 80bb2ff7 Richard Henderson
        break;
511 80bb2ff7 Richard Henderson
512 80bb2ff7 Richard Henderson
    case 0x0100:
513 80bb2ff7 Richard Henderson
        /* WSM0: Window Space Mask Register.  */
514 80bb2ff7 Richard Henderson
        s->pchip.win[0].mask = val;
515 80bb2ff7 Richard Henderson
        break;
516 80bb2ff7 Richard Henderson
    case 0x0140:
517 80bb2ff7 Richard Henderson
        /* WSM1 */
518 80bb2ff7 Richard Henderson
        s->pchip.win[1].mask = val;
519 80bb2ff7 Richard Henderson
        break;
520 80bb2ff7 Richard Henderson
    case 0x0180:
521 80bb2ff7 Richard Henderson
        /* WSM2 */
522 80bb2ff7 Richard Henderson
        s->pchip.win[2].mask = val;
523 80bb2ff7 Richard Henderson
        break;
524 80bb2ff7 Richard Henderson
    case 0x01c0:
525 80bb2ff7 Richard Henderson
        /* WSM3 */
526 80bb2ff7 Richard Henderson
        s->pchip.win[3].mask = val;
527 80bb2ff7 Richard Henderson
        break;
528 80bb2ff7 Richard Henderson
529 80bb2ff7 Richard Henderson
    case 0x0200:
530 80bb2ff7 Richard Henderson
        /* TBA0: Translated Base Address Register.  */
531 80bb2ff7 Richard Henderson
        s->pchip.win[0].translated_base_pfn = val >> 10;
532 80bb2ff7 Richard Henderson
        break;
533 80bb2ff7 Richard Henderson
    case 0x0240:
534 80bb2ff7 Richard Henderson
        /* TBA1 */
535 80bb2ff7 Richard Henderson
        s->pchip.win[1].translated_base_pfn = val >> 10;
536 80bb2ff7 Richard Henderson
        break;
537 80bb2ff7 Richard Henderson
    case 0x0280:
538 80bb2ff7 Richard Henderson
        /* TBA2 */
539 80bb2ff7 Richard Henderson
        s->pchip.win[2].translated_base_pfn = val >> 10;
540 80bb2ff7 Richard Henderson
        break;
541 80bb2ff7 Richard Henderson
    case 0x02c0:
542 80bb2ff7 Richard Henderson
        /* TBA3 */
543 80bb2ff7 Richard Henderson
        s->pchip.win[3].translated_base_pfn = val >> 10;
544 80bb2ff7 Richard Henderson
        break;
545 80bb2ff7 Richard Henderson
546 80bb2ff7 Richard Henderson
    case 0x0300:
547 80bb2ff7 Richard Henderson
        /* PCTL: Pchip Control Register.  */
548 80bb2ff7 Richard Henderson
        oldval = s->pchip.ctl;
549 80bb2ff7 Richard Henderson
        oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
550 80bb2ff7 Richard Henderson
        oldval |= val & 0x00001cff0fc7ffull;
551 80bb2ff7 Richard Henderson
552 80bb2ff7 Richard Henderson
        s->pchip.ctl = oldval;
553 80bb2ff7 Richard Henderson
        break;
554 80bb2ff7 Richard Henderson
555 80bb2ff7 Richard Henderson
    case 0x0340:
556 80bb2ff7 Richard Henderson
        /* PLAT: Pchip Master Latency Register.  */
557 80bb2ff7 Richard Henderson
        break;
558 80bb2ff7 Richard Henderson
    case 0x03c0:
559 80bb2ff7 Richard Henderson
        /* PERROR: Pchip Error Register.  */
560 80bb2ff7 Richard Henderson
        break;
561 80bb2ff7 Richard Henderson
    case 0x0400:
562 80bb2ff7 Richard Henderson
        /* PERRMASK: Pchip Error Mask Register.  */
563 80bb2ff7 Richard Henderson
        break;
564 80bb2ff7 Richard Henderson
    case 0x0440:
565 80bb2ff7 Richard Henderson
        /* PERRSET: Pchip Error Set Register.  */
566 80bb2ff7 Richard Henderson
        break;
567 80bb2ff7 Richard Henderson
568 80bb2ff7 Richard Henderson
    case 0x0480:
569 80bb2ff7 Richard Henderson
        /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
570 80bb2ff7 Richard Henderson
        break;
571 80bb2ff7 Richard Henderson
572 80bb2ff7 Richard Henderson
    case 0x04c0:
573 80bb2ff7 Richard Henderson
        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
574 80bb2ff7 Richard Henderson
        break;
575 80bb2ff7 Richard Henderson
576 80bb2ff7 Richard Henderson
    case 0x0500:
577 80bb2ff7 Richard Henderson
        /* PMONCTL */
578 80bb2ff7 Richard Henderson
    case 0x0540:
579 80bb2ff7 Richard Henderson
        /* PMONCNT */
580 80bb2ff7 Richard Henderson
    case 0x0800:
581 80bb2ff7 Richard Henderson
        /* SPRST */
582 80bb2ff7 Richard Henderson
        break;
583 80bb2ff7 Richard Henderson
584 80bb2ff7 Richard Henderson
    default:
585 c658b94f Andreas Färber
        cs = CPU(alpha_env_get_cpu(cpu_single_env));
586 c658b94f Andreas Färber
        cpu_unassigned_access(cs, addr, true, false, 0, size);
587 80bb2ff7 Richard Henderson
        return;
588 80bb2ff7 Richard Henderson
    }
589 80bb2ff7 Richard Henderson
}
590 80bb2ff7 Richard Henderson
591 80bb2ff7 Richard Henderson
static const MemoryRegionOps cchip_ops = {
592 80bb2ff7 Richard Henderson
    .read = cchip_read,
593 80bb2ff7 Richard Henderson
    .write = cchip_write,
594 80bb2ff7 Richard Henderson
    .endianness = DEVICE_LITTLE_ENDIAN,
595 80bb2ff7 Richard Henderson
    .valid = {
596 80bb2ff7 Richard Henderson
        .min_access_size = 4,  /* ??? Should be 8.  */
597 80bb2ff7 Richard Henderson
        .max_access_size = 8,
598 80bb2ff7 Richard Henderson
    },
599 80bb2ff7 Richard Henderson
    .impl = {
600 80bb2ff7 Richard Henderson
        .min_access_size = 4,
601 80bb2ff7 Richard Henderson
        .max_access_size = 4,
602 80bb2ff7 Richard Henderson
    },
603 80bb2ff7 Richard Henderson
};
604 80bb2ff7 Richard Henderson
605 80bb2ff7 Richard Henderson
static const MemoryRegionOps dchip_ops = {
606 80bb2ff7 Richard Henderson
    .read = dchip_read,
607 80bb2ff7 Richard Henderson
    .write = dchip_write,
608 80bb2ff7 Richard Henderson
    .endianness = DEVICE_LITTLE_ENDIAN,
609 80bb2ff7 Richard Henderson
    .valid = {
610 80bb2ff7 Richard Henderson
        .min_access_size = 4,  /* ??? Should be 8.  */
611 80bb2ff7 Richard Henderson
        .max_access_size = 8,
612 80bb2ff7 Richard Henderson
    },
613 80bb2ff7 Richard Henderson
    .impl = {
614 80bb2ff7 Richard Henderson
        .min_access_size = 4,
615 80bb2ff7 Richard Henderson
        .max_access_size = 8,
616 80bb2ff7 Richard Henderson
    },
617 80bb2ff7 Richard Henderson
};
618 80bb2ff7 Richard Henderson
619 80bb2ff7 Richard Henderson
static const MemoryRegionOps pchip_ops = {
620 80bb2ff7 Richard Henderson
    .read = pchip_read,
621 80bb2ff7 Richard Henderson
    .write = pchip_write,
622 80bb2ff7 Richard Henderson
    .endianness = DEVICE_LITTLE_ENDIAN,
623 80bb2ff7 Richard Henderson
    .valid = {
624 80bb2ff7 Richard Henderson
        .min_access_size = 4,  /* ??? Should be 8.  */
625 80bb2ff7 Richard Henderson
        .max_access_size = 8,
626 80bb2ff7 Richard Henderson
    },
627 80bb2ff7 Richard Henderson
    .impl = {
628 80bb2ff7 Richard Henderson
        .min_access_size = 4,
629 80bb2ff7 Richard Henderson
        .max_access_size = 4,
630 80bb2ff7 Richard Henderson
    },
631 80bb2ff7 Richard Henderson
};
632 80bb2ff7 Richard Henderson
633 80bb2ff7 Richard Henderson
static void typhoon_set_irq(void *opaque, int irq, int level)
634 80bb2ff7 Richard Henderson
{
635 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
636 80bb2ff7 Richard Henderson
    uint64_t drir;
637 80bb2ff7 Richard Henderson
    int i;
638 80bb2ff7 Richard Henderson
639 80bb2ff7 Richard Henderson
    /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
640 80bb2ff7 Richard Henderson
    drir = s->cchip.drir;
641 80bb2ff7 Richard Henderson
    if (level) {
642 80bb2ff7 Richard Henderson
        drir |= 1ull << irq;
643 80bb2ff7 Richard Henderson
    } else {
644 80bb2ff7 Richard Henderson
        drir &= ~(1ull << irq);
645 80bb2ff7 Richard Henderson
    }
646 80bb2ff7 Richard Henderson
    s->cchip.drir = drir;
647 80bb2ff7 Richard Henderson
648 80bb2ff7 Richard Henderson
    for (i = 0; i < 4; ++i) {
649 80bb2ff7 Richard Henderson
        cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
650 80bb2ff7 Richard Henderson
    }
651 80bb2ff7 Richard Henderson
}
652 80bb2ff7 Richard Henderson
653 80bb2ff7 Richard Henderson
static void typhoon_set_isa_irq(void *opaque, int irq, int level)
654 80bb2ff7 Richard Henderson
{
655 80bb2ff7 Richard Henderson
    typhoon_set_irq(opaque, 55, level);
656 80bb2ff7 Richard Henderson
}
657 80bb2ff7 Richard Henderson
658 80bb2ff7 Richard Henderson
static void typhoon_set_timer_irq(void *opaque, int irq, int level)
659 80bb2ff7 Richard Henderson
{
660 80bb2ff7 Richard Henderson
    TyphoonState *s = opaque;
661 80bb2ff7 Richard Henderson
    int i;
662 80bb2ff7 Richard Henderson
663 80bb2ff7 Richard Henderson
    /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
664 80bb2ff7 Richard Henderson
       and so we don't have to worry about missing interrupts just
665 80bb2ff7 Richard Henderson
       because we never actually ACK the interrupt.  Just ignore any
666 80bb2ff7 Richard Henderson
       case of the interrupt level going low.  */
667 80bb2ff7 Richard Henderson
    if (level == 0) {
668 80bb2ff7 Richard Henderson
        return;
669 80bb2ff7 Richard Henderson
    }
670 80bb2ff7 Richard Henderson
671 80bb2ff7 Richard Henderson
    /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
672 80bb2ff7 Richard Henderson
    for (i = 0; i < 4; ++i) {
673 ad601177 Andreas Färber
        AlphaCPU *cpu = s->cchip.cpu[i];
674 ad601177 Andreas Färber
        if (cpu != NULL) {
675 80bb2ff7 Richard Henderson
            uint32_t iic = s->cchip.iic[i];
676 80bb2ff7 Richard Henderson
677 80bb2ff7 Richard Henderson
            /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
678 80bb2ff7 Richard Henderson
               Bit 24 is the OverFlow bit, RO, and set when the count
679 80bb2ff7 Richard Henderson
               decrements past 0.  When is OF cleared?  My guess is that
680 80bb2ff7 Richard Henderson
               OF is actually cleared when the IIC is written, and that
681 80bb2ff7 Richard Henderson
               the ICNT field always decrements.  At least, that's an
682 80bb2ff7 Richard Henderson
               interpretation that makes sense, and "allows the CPU to
683 80bb2ff7 Richard Henderson
               determine exactly how mant interval timer ticks were
684 80bb2ff7 Richard Henderson
               skipped".  At least within the next 4M ticks...  */
685 80bb2ff7 Richard Henderson
686 80bb2ff7 Richard Henderson
            iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
687 80bb2ff7 Richard Henderson
            s->cchip.iic[i] = iic;
688 80bb2ff7 Richard Henderson
689 80bb2ff7 Richard Henderson
            if (iic & 0x1000000) {
690 80bb2ff7 Richard Henderson
                /* Set the ITI bit for this cpu.  */
691 80bb2ff7 Richard Henderson
                s->cchip.misc |= 1 << (i + 4);
692 80bb2ff7 Richard Henderson
                /* And signal the interrupt.  */
693 c3affe56 Andreas Färber
                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
694 80bb2ff7 Richard Henderson
            }
695 80bb2ff7 Richard Henderson
        }
696 80bb2ff7 Richard Henderson
    }
697 80bb2ff7 Richard Henderson
}
698 80bb2ff7 Richard Henderson
699 c781cf96 Richard Henderson
static void typhoon_alarm_timer(void *opaque)
700 c781cf96 Richard Henderson
{
701 c781cf96 Richard Henderson
    TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
702 c781cf96 Richard Henderson
    int cpu = (uintptr_t)opaque & 3;
703 c781cf96 Richard Henderson
704 c781cf96 Richard Henderson
    /* Set the ITI bit for this cpu.  */
705 c781cf96 Richard Henderson
    s->cchip.misc |= 1 << (cpu + 4);
706 c3affe56 Andreas Färber
    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
707 c781cf96 Richard Henderson
}
708 c781cf96 Richard Henderson
709 71baa303 Hervé Poussineau
PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
710 71baa303 Hervé Poussineau
                     qemu_irq *p_rtc_irq,
711 ad601177 Andreas Färber
                     AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
712 80bb2ff7 Richard Henderson
{
713 80bb2ff7 Richard Henderson
    const uint64_t MB = 1024 * 1024;
714 80bb2ff7 Richard Henderson
    const uint64_t GB = 1024 * MB;
715 80bb2ff7 Richard Henderson
    MemoryRegion *addr_space = get_system_memory();
716 80bb2ff7 Richard Henderson
    MemoryRegion *addr_space_io = get_system_io();
717 80bb2ff7 Richard Henderson
    DeviceState *dev;
718 80bb2ff7 Richard Henderson
    TyphoonState *s;
719 94dd91d6 Andreas Färber
    PCIHostState *phb;
720 80bb2ff7 Richard Henderson
    PCIBus *b;
721 c781cf96 Richard Henderson
    int i;
722 80bb2ff7 Richard Henderson
723 94dd91d6 Andreas Färber
    dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
724 80bb2ff7 Richard Henderson
    qdev_init_nofail(dev);
725 80bb2ff7 Richard Henderson
726 94dd91d6 Andreas Färber
    s = TYPHOON_PCI_HOST_BRIDGE(dev);
727 8558d942 Andreas Färber
    phb = PCI_HOST_BRIDGE(dev);
728 80bb2ff7 Richard Henderson
729 80bb2ff7 Richard Henderson
    /* Remember the CPUs so that we can deliver interrupts to them.  */
730 c781cf96 Richard Henderson
    for (i = 0; i < 4; i++) {
731 ad601177 Andreas Färber
        AlphaCPU *cpu = cpus[i];
732 ad601177 Andreas Färber
        s->cchip.cpu[i] = cpu;
733 ad601177 Andreas Färber
        if (cpu != NULL) {
734 c9245853 Andreas Färber
            cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
735 c781cf96 Richard Henderson
                                                 typhoon_alarm_timer,
736 c781cf96 Richard Henderson
                                                 (void *)((uintptr_t)s + i));
737 c781cf96 Richard Henderson
        }
738 c781cf96 Richard Henderson
    }
739 80bb2ff7 Richard Henderson
740 80bb2ff7 Richard Henderson
    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
741 80bb2ff7 Richard Henderson
742 80bb2ff7 Richard Henderson
    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
743 80bb2ff7 Richard Henderson
       but the address space hole reserved at this point is 8TB.  */
744 c5705a77 Avi Kivity
    memory_region_init_ram(&s->ram_region, "ram", ram_size);
745 c5705a77 Avi Kivity
    vmstate_register_ram_global(&s->ram_region);
746 80bb2ff7 Richard Henderson
    memory_region_add_subregion(addr_space, 0, &s->ram_region);
747 80bb2ff7 Richard Henderson
748 80bb2ff7 Richard Henderson
    /* TIGbus, 0x801.0000.0000, 1GB.  */
749 80bb2ff7 Richard Henderson
    /* ??? The TIGbus is used for delivering interrupts, and access to
750 80bb2ff7 Richard Henderson
       the flash ROM.  I'm not sure that we need to implement it at all.  */
751 80bb2ff7 Richard Henderson
752 80bb2ff7 Richard Henderson
    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
753 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
754 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x80180000000ULL,
755 02d6516c Stefan Weil
                                &s->pchip.region);
756 80bb2ff7 Richard Henderson
757 80bb2ff7 Richard Henderson
    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
758 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
759 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
760 02d6516c Stefan Weil
                                &s->cchip.region);
761 80bb2ff7 Richard Henderson
762 80bb2ff7 Richard Henderson
    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
763 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
764 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
765 02d6516c Stefan Weil
                                &s->dchip_region);
766 80bb2ff7 Richard Henderson
767 80bb2ff7 Richard Henderson
    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
768 80bb2ff7 Richard Henderson
    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
769 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x80000000000ULL,
770 02d6516c Stefan Weil
                                &s->pchip.reg_mem);
771 80bb2ff7 Richard Henderson
772 80bb2ff7 Richard Henderson
    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
773 80bb2ff7 Richard Henderson
    /* ??? Ideally we drop the "system" i/o space on the floor and give the
774 80bb2ff7 Richard Henderson
       PCI subsystem the full address space reserved by the chipset.
775 80bb2ff7 Richard Henderson
       We can't do that until the MEM and IO paths in memory.c are unified.  */
776 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
777 80bb2ff7 Richard Henderson
                          "pci0-io", 32*MB);
778 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
779 02d6516c Stefan Weil
                                &s->pchip.reg_io);
780 80bb2ff7 Richard Henderson
781 94dd91d6 Andreas Färber
    b = pci_register_bus(dev, "pci",
782 80bb2ff7 Richard Henderson
                         typhoon_set_irq, sys_map_irq, s,
783 60a0e443 Alex Williamson
                         &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
784 94dd91d6 Andreas Färber
    phb->bus = b;
785 80bb2ff7 Richard Henderson
786 80bb2ff7 Richard Henderson
    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
787 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
788 80bb2ff7 Richard Henderson
                          "pci0-iack", 64*MB);
789 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
790 02d6516c Stefan Weil
                                &s->pchip.reg_iack);
791 80bb2ff7 Richard Henderson
792 80bb2ff7 Richard Henderson
    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
793 80bb2ff7 Richard Henderson
    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
794 80bb2ff7 Richard Henderson
                          "pci0-conf", 16*MB);
795 02d6516c Stefan Weil
    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
796 02d6516c Stefan Weil
                                &s->pchip.reg_conf);
797 80bb2ff7 Richard Henderson
798 80bb2ff7 Richard Henderson
    /* For the record, these are the mappings for the second PCI bus.
799 80bb2ff7 Richard Henderson
       We can get away with not implementing them because we indicate
800 80bb2ff7 Richard Henderson
       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
801 80bb2ff7 Richard Henderson
    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
802 80bb2ff7 Richard Henderson
    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
803 80bb2ff7 Richard Henderson
    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
804 80bb2ff7 Richard Henderson
    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
805 80bb2ff7 Richard Henderson
    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
806 80bb2ff7 Richard Henderson
807 80bb2ff7 Richard Henderson
    /* Init the ISA bus.  */
808 80bb2ff7 Richard Henderson
    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
809 80bb2ff7 Richard Henderson
    {
810 80bb2ff7 Richard Henderson
        qemu_irq isa_pci_irq, *isa_irqs;
811 80bb2ff7 Richard Henderson
812 71baa303 Hervé Poussineau
        *isa_bus = isa_bus_new(NULL, addr_space_io);
813 80bb2ff7 Richard Henderson
        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
814 71baa303 Hervé Poussineau
        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
815 71baa303 Hervé Poussineau
        isa_bus_irqs(*isa_bus, isa_irqs);
816 80bb2ff7 Richard Henderson
    }
817 80bb2ff7 Richard Henderson
818 80bb2ff7 Richard Henderson
    return b;
819 80bb2ff7 Richard Henderson
}
820 80bb2ff7 Richard Henderson
821 80bb2ff7 Richard Henderson
static int typhoon_pcihost_init(SysBusDevice *dev)
822 80bb2ff7 Richard Henderson
{
823 80bb2ff7 Richard Henderson
    return 0;
824 80bb2ff7 Richard Henderson
}
825 80bb2ff7 Richard Henderson
826 999e12bb Anthony Liguori
static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
827 999e12bb Anthony Liguori
{
828 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
829 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
830 999e12bb Anthony Liguori
831 999e12bb Anthony Liguori
    k->init = typhoon_pcihost_init;
832 39bffca2 Anthony Liguori
    dc->no_user = 1;
833 999e12bb Anthony Liguori
}
834 999e12bb Anthony Liguori
835 4240abff Andreas Färber
static const TypeInfo typhoon_pcihost_info = {
836 94dd91d6 Andreas Färber
    .name          = TYPE_TYPHOON_PCI_HOST_BRIDGE,
837 8558d942 Andreas Färber
    .parent        = TYPE_PCI_HOST_BRIDGE,
838 39bffca2 Anthony Liguori
    .instance_size = sizeof(TyphoonState),
839 39bffca2 Anthony Liguori
    .class_init    = typhoon_pcihost_class_init,
840 80bb2ff7 Richard Henderson
};
841 80bb2ff7 Richard Henderson
842 83f7d43a Andreas Färber
static void typhoon_register_types(void)
843 80bb2ff7 Richard Henderson
{
844 39bffca2 Anthony Liguori
    type_register_static(&typhoon_pcihost_info);
845 80bb2ff7 Richard Henderson
}
846 83f7d43a Andreas Färber
847 83f7d43a Andreas Färber
type_init(typhoon_register_types)