Statistics
| Branch: | Revision:

root / hw / alpha_typhoon.c @ 4be403c8

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