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