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) |