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