Statistics
| Branch: | Revision:

root / hw / alpha_typhoon.c @ 3871481c

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