/[gxemul]/upstream/0.4.0.1/src/devices/dev_sgi_ip22.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.0.1/src/devices/dev_sgi_ip22.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show annotations)
Mon Oct 8 16:20:18 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 12559 byte(s)
0.4.0.1
1 /*
2 * Copyright (C) 2004-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: dev_sgi_ip22.c,v 1.28 2006/03/04 12:38:48 debug Exp $
29 *
30 * SGI IP22 stuff.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "cpu.h"
38 #include "devices.h"
39 #include "machine.h"
40 #include "memory.h"
41 #include "misc.h"
42
43 #include "imcreg.h"
44
45
46 #define SGI_IP22_TICK_SHIFT 14
47
48
49 /*
50 * dev_sgi_ip22_tick():
51 */
52 void dev_sgi_ip22_tick(struct cpu *cpu, void *extra)
53 {
54 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
55
56 if (d->reg[0x38 / 4] != 0)
57 d->reg[0x38 / 4] --;
58 }
59
60
61 /*
62 * dev_sgi_ip22_imc_access():
63 *
64 * The memory controller (?).
65 */
66 DEVICE_ACCESS(sgi_ip22_imc)
67 {
68 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
69 uint64_t idata = 0, odata = 0;
70 int regnr;
71
72 if (writeflag == MEM_WRITE)
73 idata = memory_readmax64(cpu, data, len);
74
75 regnr = relative_addr / sizeof(uint32_t);
76
77 if (writeflag == MEM_WRITE)
78 d->imc_reg[regnr] = idata;
79 else
80 odata = d->imc_reg[regnr];
81
82 switch (relative_addr) {
83 case (IMC_CPUCTRL0 - IP22_IMC_BASE):
84 if (writeflag == MEM_WRITE) {
85 /* debug("[ sgi_ip22_imc: write to "
86 "IMC_CPUCTRL0, data=0x%08x ]\n", (int)idata); */
87 } else {
88 /* debug("[ sgi_ip22_imc: read from IMC_CPUCTRL0, "
89 "data=0x%08x ]\n", (int)odata); */
90 }
91 break;
92 case (IMC_SYSID - IP22_IMC_BASE):
93 if (writeflag == MEM_WRITE) {
94 debug("[ sgi_ip22_imc: unimplemented write "
95 "IMC_SYSID, data=0x%08x ]\n", (int)idata);
96 } else {
97 /* Lowest 4 bits are the revision bits. */
98 odata = 3; /* + IMC_SYSID_HAVEISA; */
99 /* debug("[ sgi_ip22_imc: read from IMC_SYSID, "
100 "data=0x%08x ]\n", (int)odata); */
101 }
102 break;
103 case (IMC_WDOG - IP22_IMC_BASE):
104 if (writeflag == MEM_WRITE) {
105 /* debug("[ sgi_ip22_imc: write to IMC_WDOG, "
106 "data=0x%08x ]\n", (int)idata); */
107 } else {
108 /* debug("[ sgi_ip22_imc: read from IMC_WDOG, "
109 "data=0x%08x ]\n", (int)odata); */
110 }
111 break;
112 case (IMC_MEMCFG0 - IP22_IMC_BASE):
113 if (writeflag == MEM_WRITE) {
114 debug("[ sgi_ip22_imc: unimplemented write "
115 "IMC_MEMCFG0, data=0x%08x ]\n", (int)idata);
116 } else {
117 odata = 0x3100 + (0x8000000 >> 22); /* ? TODO */
118 /* debug("[ sgi_ip22_imc: read from IMC_MEMCFG0,"
119 " data=0x%08x ]\n", (int)odata); */
120 }
121 break;
122 case (IMC_MEMCFG1 - IP22_IMC_BASE):
123 if (writeflag == MEM_WRITE) {
124 debug("[ sgi_ip22_imc: unimplemented write "
125 "IMC_MEMCFG1, data=0x%08x ]\n", (int)idata);
126 } else {
127 odata = 0;
128 /* debug("[ sgi_ip22_imc: read from IMC_MEMCFG1, "
129 "data=0x%08x ]\n", (int)odata); */
130 }
131 break;
132 case (IMC_EEPROM - IP22_IMC_BASE):
133 /*
134 * The IP22 prom tries to access this during bootup,
135 * but I have no idea how it works.
136 */
137 if (writeflag == MEM_WRITE) {
138 debug("[ sgi_ip22_imc: write to IMC_EEPROM, data="
139 "0x%08x ]\n", (int)idata);
140 } else {
141 odata = random() & 0x1e;
142 debug("[ sgi_ip22_imc: read from IMC_WDOG, "
143 "data=0x%08x ]\n", (int)odata);
144 }
145 break;
146 default:
147 if (writeflag == MEM_WRITE) {
148 debug("[ sgi_ip22_imc: unimplemented write to "
149 "address 0x%x, data=0x%08x ]\n",
150 (int)relative_addr, (int)idata);
151 } else {
152 debug("[ sgi_ip22_imc: unimplemented read from "
153 "address 0x%x, data=0x%08x ]\n",
154 (int)relative_addr, (int)odata);
155 }
156 }
157
158 if (writeflag == MEM_READ)
159 memory_writemax64(cpu, data, len, odata);
160
161 return 1;
162 }
163
164
165 /*
166 * dev_sgi_ip22_unknown_access():
167 *
168 * A so far unknown device, used by the IP22 prom during startup.
169 */
170 DEVICE_ACCESS(sgi_ip22_unknown)
171 {
172 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
173 uint64_t idata = 0, odata = 0;
174
175 idata = memory_readmax64(cpu, data, len);
176
177 switch (relative_addr) {
178 case 0x04:
179 if (writeflag == MEM_WRITE) {
180 debug("[ sgi_ip22_unknown: write to address 0x%x,"
181 " data=0x%08x ]\n", (int)relative_addr, (int)idata);
182 } else {
183 odata = d->unknown_timer;
184 d->unknown_timer += 100;
185 debug("[ sgi_ip22_unknown: read from address 0x%x, "
186 "data=0x%08x ]\n", (int)relative_addr, (int)odata);
187 }
188 break;
189 default:
190 if (writeflag == MEM_WRITE) {
191 debug("[ sgi_ip22_unknown: unimplemented write to "
192 "address 0x%x, data=0x%08x ]\n",
193 (int)relative_addr, (int)idata);
194 } else {
195 debug("[ sgi_ip22_unknown: unimplemented read from "
196 "address 0x%x, data=0x%08x ]\n",
197 (int)relative_addr, (int)odata);
198 }
199 }
200
201 if (writeflag == MEM_READ)
202 memory_writemax64(cpu, data, len, odata);
203
204 return 1;
205 }
206
207
208 /*
209 * dev_sgi_ip22_unknown2_access():
210 *
211 * A so far unknown device, used by the IP22 prom during startup.
212 */
213 DEVICE_ACCESS(sgi_ip22_unknown2)
214 {
215 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
216 uint64_t idata = 0, odata = 0;
217 int regnr;
218
219 idata = memory_readmax64(cpu, data, len);
220 regnr = relative_addr / sizeof(uint32_t);
221
222 if (writeflag == MEM_WRITE)
223 d->unknown2_reg[regnr] = idata;
224 else
225 odata = d->unknown2_reg[regnr];
226
227 switch (relative_addr) {
228 default:
229 if (writeflag == MEM_WRITE) {
230 debug("[ sgi_ip22_unknown2: unimplemented write "
231 "to address 0x%x, data=0x%08x ]\n",
232 (int)relative_addr, (int)idata);
233 } else {
234 debug("[ sgi_ip22_unknown2: unimplemented read from "
235 "address 0x%x, data=0x%08x ]\n",
236 (int)relative_addr, (int)odata);
237 }
238 }
239
240 if (writeflag == MEM_READ)
241 memory_writemax64(cpu, data, len, odata);
242
243 return 1;
244 }
245
246
247 /*
248 * dev_sgi_ip22_sysid_access():
249 */
250 DEVICE_ACCESS(sgi_ip22_sysid)
251 {
252 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
253 uint64_t idata = 0, odata = 0;
254
255 idata = memory_readmax64(cpu, data, len);
256
257 if (writeflag == MEM_WRITE) {
258 debug("[ sgi_ip22_sysid: write to address 0x%x, "
259 "data=0x%08x ]\n", (int)relative_addr, (int)idata);
260 } else {
261 /*
262 * According to NetBSD's sgimips/ip22.c:
263 *
264 * printf("IOC rev %d, machine %s, board rev %d\n",
265 * (sysid >> 5) & 0x07,
266 * (sysid & 1) ? "Indigo2 (Fullhouse)" : "Indy (Guiness)",
267 * (sysid >> 1) & 0x0f);
268 */
269
270 /* IOC rev 1, Guiness, board rev 3: */
271 odata = (1 << 5) + (3 << 1) + (d->guiness_flag? 0 : 1);
272
273 debug("[ sgi_ip22_sysid: read from address 0x%x, data="
274 "0x%08x ]\n", (int)relative_addr, (int)odata);
275 }
276
277 if (writeflag == MEM_READ)
278 memory_writemax64(cpu, data, len, odata);
279
280 return 1;
281 }
282
283
284 /*
285 * dev_sgi_ip22_access():
286 */
287 DEVICE_ACCESS(sgi_ip22)
288 {
289 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
290 uint64_t idata = 0, odata = 0;
291 int regnr;
292
293 idata = memory_readmax64(cpu, data, len);
294 regnr = relative_addr / sizeof(uint32_t);
295
296 if (writeflag == MEM_WRITE)
297 d->reg[regnr] = idata;
298 else
299 odata = d->reg[regnr];
300
301 /* Read from/write to the sgi_ip22: */
302 switch (relative_addr) {
303 case 0x00: /* local0 irq stat */
304 if (writeflag == MEM_WRITE) {
305 debug("[ sgi_ip22: write to local0 IRQ STAT, "
306 "data=0x%llx ]\n", (long long)idata);
307 } else {
308 debug("[ sgi_ip22: read from local0 IRQ STAT, "
309 "data=0x%llx ]\n", (long long)odata);
310 }
311 break;
312 case 0x04: /* local0 irq mask */
313 if (writeflag == MEM_WRITE) {
314 /*
315 * Ugly hack: if an interrupt is asserted, and someone
316 * writes to this mask register, the interrupt should
317 * be masked. That is, sgi_ip22_interrupt() in
318 * src/machine.c has to be called to deal with this.
319 * The ugly solution I choose here is to deassert
320 * some interrupt which should never be used anyway.
321 * (TODO: Fix this.)
322 */
323 cpu_interrupt_ack(cpu, 8 + 63);
324 debug("[ sgi_ip22: write to local0 IRQ MASK, "
325 "data=0x%llx ]\n", (long long)idata);
326 } else {
327 debug("[ sgi_ip22: read from local0 IRQ MASK, "
328 "data=0x%llx ]\n", (long long)odata);
329 }
330 break;
331 case 0x08: /* local1 irq stat */
332 if (writeflag == MEM_WRITE) {
333 debug("[ sgi_ip22: write to local1 IRQ STAT, "
334 "data=0x%llx ]\n", (long long)idata);
335 } else {
336 debug("[ sgi_ip22: read from local1 IRQ STAT, "
337 "data=0x%llx ]\n", (long long)odata);
338 }
339 break;
340 case 0x0c: /* local1 irq mask */
341 if (writeflag == MEM_WRITE) {
342 /* See commen above, about local0 irq mask. */
343 cpu_interrupt_ack(cpu, 8 + 63);
344 debug("[ sgi_ip22: write to local1 IRQ MASK, "
345 "data=0x%llx ]\n", (long long)idata);
346 } else {
347 debug("[ sgi_ip22: read from local1 IRQ MASK, "
348 "data=0x%llx ]\n", (long long)odata);
349 }
350 break;
351 case 0x10:
352 if (writeflag == MEM_WRITE) {
353 debug("[ sgi_ip22: write to mappable IRQ STAT, "
354 "data=0x%llx ]\n", (long long)idata);
355 } else {
356 debug("[ sgi_ip22: read from mappable IRQ STAT, "
357 "data=0x%llx ]\n", (long long)odata);
358 }
359 break;
360 case 0x14:
361 if (writeflag == MEM_WRITE) {
362 debug("[ sgi_ip22: write to mappable local0 IRQ "
363 "MASK, data=0x%llx ]\n", (long long)idata);
364 } else {
365 debug("[ sgi_ip22: read from mappable local0 IRQ "
366 "MASK, data=0x%llx ]\n", (long long)odata);
367 }
368 break;
369 case 0x18:
370 if (writeflag == MEM_WRITE) {
371 debug("[ sgi_ip22: write to mappable local1 IRQ "
372 "MASK, data=0x%llx ]\n", (long long)idata);
373 } else {
374 debug("[ sgi_ip22: read from mappable local1 IRQ "
375 "MASK, data=0x%llx ]\n", (long long)odata);
376 }
377 break;
378 case 0x38: /* timer count */
379 if (writeflag == MEM_WRITE) {
380 /* Two byte values are written to this address,
381 sequentially... TODO */
382 } else {
383 /* The timer is decreased by the tick function. */
384 }
385 break;
386 case 0x3b: /* ? */
387 odata = random();
388 break;
389 case 0x3c: /* timer control */
390 break;
391 case 0x3f: /* ? */
392 odata = random();
393 break;
394 default:
395 if (writeflag == MEM_WRITE) {
396 debug("[ sgi_ip22: unimplemented write to address "
397 "0x%x, data=0x%02x ]\n", (int)relative_addr,
398 (int)idata);
399 } else {
400 debug("[ sgi_ip22: unimplemented read from address "
401 "0x%llx ]\n", (long long)relative_addr);
402 }
403 }
404
405 if (writeflag == MEM_READ)
406 memory_writemax64(cpu, data, len, odata);
407
408 return 1;
409 }
410
411
412 /*
413 * dev_sgi_ip22_init():
414 */
415 struct sgi_ip22_data *dev_sgi_ip22_init(struct machine *machine,
416 struct memory *mem, uint64_t baseaddr, int guiness_flag)
417 {
418 struct sgi_ip22_data *d = malloc(sizeof(struct sgi_ip22_data));
419 if (d == NULL) {
420 fprintf(stderr, "out of memory\n");
421 exit(1);
422 }
423 memset(d, 0, sizeof(struct sgi_ip22_data));
424 d->guiness_flag = guiness_flag;
425
426 memory_device_register(mem, "sgi_ip22", baseaddr, DEV_SGI_IP22_LENGTH,
427 dev_sgi_ip22_access, (void *)d, DM_DEFAULT, NULL);
428 memory_device_register(mem, "sgi_ip22_sysid", 0x1fbd9858, 0x8,
429 dev_sgi_ip22_sysid_access, (void *)d, DM_DEFAULT, NULL);
430 memory_device_register(mem, "sgi_ip22_imc", IP22_IMC_BASE,
431 DEV_SGI_IP22_IMC_LENGTH, dev_sgi_ip22_imc_access, (void *)d,
432 DM_DEFAULT, NULL);
433 memory_device_register(mem, "sgi_ip22_unknown", 0x1fa01000, 0x10,
434 dev_sgi_ip22_unknown_access, (void *)d, DM_DEFAULT, NULL);
435 memory_device_register(mem, "sgi_ip22_unknown2", IP22_UNKNOWN2_BASE,
436 DEV_SGI_IP22_UNKNOWN2_LENGTH, dev_sgi_ip22_unknown2_access,
437 (void *)d, DM_DEFAULT, NULL);
438
439 machine_add_tickfunction(machine, dev_sgi_ip22_tick, d,
440 SGI_IP22_TICK_SHIFT, 0.0);
441
442 return d;
443 }
444

  ViewVC Help
Powered by ViewVC 1.1.26