Statistics
| Branch: | Revision:

root / hw / alpha_typhoon.c @ f8f48b69

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