/[gxemul]/upstream/0.3.6.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.3.6.1/src/devices/dev_sgi_ip22.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (show annotations)
Mon Oct 8 16:19:05 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 13184 byte(s)
0.3.6.1
1 /*
2 * Copyright (C) 2004-2005 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.24 2005/02/22 05:52:58 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 int dev_sgi_ip22_imc_access(struct cpu *cpu, struct memory *mem,
67 uint64_t relative_addr, unsigned char *data, size_t len,
68 int writeflag, void *extra)
69 {
70 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
71 uint64_t idata = 0, odata = 0;
72 int regnr;
73
74 idata = memory_readmax64(cpu, data, len);
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 int dev_sgi_ip22_unknown_access(struct cpu *cpu, struct memory *mem,
171 uint64_t relative_addr, unsigned char *data, size_t len,
172 int writeflag, void *extra)
173 {
174 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
175 uint64_t idata = 0, odata = 0;
176
177 idata = memory_readmax64(cpu, data, len);
178
179 switch (relative_addr) {
180 case 0x04:
181 if (writeflag == MEM_WRITE) {
182 debug("[ sgi_ip22_unknown: write to address 0x%x,"
183 " data=0x%08x ]\n", (int)relative_addr, (int)idata);
184 } else {
185 odata = d->unknown_timer;
186 d->unknown_timer += 100;
187 debug("[ sgi_ip22_unknown: read from address 0x%x, "
188 "data=0x%08x ]\n", (int)relative_addr, (int)odata);
189 }
190 break;
191 default:
192 if (writeflag == MEM_WRITE) {
193 debug("[ sgi_ip22_unknown: unimplemented write to "
194 "address 0x%x, data=0x%08x ]\n",
195 (int)relative_addr, (int)idata);
196 } else {
197 debug("[ sgi_ip22_unknown: unimplemented read from "
198 "address 0x%x, data=0x%08x ]\n",
199 (int)relative_addr, (int)odata);
200 }
201 }
202
203 if (writeflag == MEM_READ)
204 memory_writemax64(cpu, data, len, odata);
205
206 return 1;
207 }
208
209
210 /*
211 * dev_sgi_ip22_unknown2_access():
212 *
213 * A so far unknown device, used by the IP22 prom during startup.
214 */
215 int dev_sgi_ip22_unknown2_access(struct cpu *cpu, struct memory *mem,
216 uint64_t relative_addr, unsigned char *data, size_t len,
217 int writeflag, void *extra)
218 {
219 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
220 uint64_t idata = 0, odata = 0;
221 int regnr;
222
223 idata = memory_readmax64(cpu, data, len);
224 regnr = relative_addr / sizeof(uint32_t);
225
226 if (writeflag == MEM_WRITE)
227 d->unknown2_reg[regnr] = idata;
228 else
229 odata = d->unknown2_reg[regnr];
230
231 switch (relative_addr) {
232 default:
233 if (writeflag == MEM_WRITE) {
234 debug("[ sgi_ip22_unknown2: unimplemented write "
235 "to address 0x%x, data=0x%08x ]\n",
236 (int)relative_addr, (int)idata);
237 } else {
238 debug("[ sgi_ip22_unknown2: unimplemented read from "
239 "address 0x%x, data=0x%08x ]\n",
240 (int)relative_addr, (int)odata);
241 }
242 }
243
244 if (writeflag == MEM_READ)
245 memory_writemax64(cpu, data, len, odata);
246
247 return 1;
248 }
249
250
251 /*
252 * dev_sgi_ip22_sysid_access():
253 */
254 int dev_sgi_ip22_sysid_access(struct cpu *cpu, struct memory *mem,
255 uint64_t relative_addr, unsigned char *data, size_t len,
256 int writeflag, void *extra)
257 {
258 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
259 uint64_t idata = 0, odata = 0;
260
261 idata = memory_readmax64(cpu, data, len);
262
263 if (writeflag == MEM_WRITE) {
264 debug("[ sgi_ip22_sysid: write to address 0x%x, "
265 "data=0x%08x ]\n", (int)relative_addr, (int)idata);
266 } else {
267 /*
268 * According to NetBSD's sgimips/ip22.c:
269 *
270 * printf("IOC rev %d, machine %s, board rev %d\n",
271 * (sysid >> 5) & 0x07,
272 * (sysid & 1) ? "Indigo2 (Fullhouse)" : "Indy (Guiness)",
273 * (sysid >> 1) & 0x0f);
274 */
275
276 /* IOC rev 1, Guiness, board rev 3: */
277 odata = (1 << 5) + (3 << 1) + (d->guiness_flag? 0 : 1);
278
279 debug("[ sgi_ip22_sysid: read from address 0x%x, data="
280 "0x%08x ]\n", (int)relative_addr, (int)odata);
281 }
282
283 if (writeflag == MEM_READ)
284 memory_writemax64(cpu, data, len, odata);
285
286 return 1;
287 }
288
289
290 /*
291 * dev_sgi_ip22_access():
292 *
293 * Returns 1 if ok, 0 on error.
294 */
295 int dev_sgi_ip22_access(struct cpu *cpu, struct memory *mem,
296 uint64_t relative_addr, unsigned char *data, size_t len,
297 int writeflag, void *extra)
298 {
299 struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
300 uint64_t idata = 0, odata = 0;
301 int regnr;
302
303 idata = memory_readmax64(cpu, data, len);
304 regnr = relative_addr / sizeof(uint32_t);
305
306 if (writeflag == MEM_WRITE)
307 d->reg[regnr] = idata;
308 else
309 odata = d->reg[regnr];
310
311 /* Read from/write to the sgi_ip22: */
312 switch (relative_addr) {
313 case 0x00: /* local0 irq stat */
314 if (writeflag == MEM_WRITE) {
315 debug("[ sgi_ip22: write to local0 IRQ STAT, "
316 "data=0x%llx ]\n", (long long)idata);
317 } else {
318 debug("[ sgi_ip22: read from local0 IRQ STAT, "
319 "data=0x%llx ]\n", (long long)odata);
320 }
321 break;
322 case 0x04: /* local0 irq mask */
323 if (writeflag == MEM_WRITE) {
324 /*
325 * Ugly hack: if an interrupt is asserted, and someone
326 * writes to this mask register, the interrupt should
327 * be masked. That is, sgi_ip22_interrupt() in
328 * src/machine.c has to be called to deal with this.
329 * The ugly solution I choose here is to deassert
330 * some interrupt which should never be used anyway.
331 * (TODO: Fix this.)
332 */
333 cpu_interrupt_ack(cpu, 8 + 63);
334 debug("[ sgi_ip22: write to local0 IRQ MASK, "
335 "data=0x%llx ]\n", (long long)idata);
336 } else {
337 debug("[ sgi_ip22: read from local0 IRQ MASK, "
338 "data=0x%llx ]\n", (long long)odata);
339 }
340 break;
341 case 0x08: /* local1 irq stat */
342 if (writeflag == MEM_WRITE) {
343 debug("[ sgi_ip22: write to local1 IRQ STAT, "
344 "data=0x%llx ]\n", (long long)idata);
345 } else {
346 debug("[ sgi_ip22: read from local1 IRQ STAT, "
347 "data=0x%llx ]\n", (long long)odata);
348 }
349 break;
350 case 0x0c: /* local1 irq mask */
351 if (writeflag == MEM_WRITE) {
352 /* See commen above, about local0 irq mask. */
353 cpu_interrupt_ack(cpu, 8 + 63);
354 debug("[ sgi_ip22: write to local1 IRQ MASK, "
355 "data=0x%llx ]\n", (long long)idata);
356 } else {
357 debug("[ sgi_ip22: read from local1 IRQ MASK, "
358 "data=0x%llx ]\n", (long long)odata);
359 }
360 break;
361 case 0x10:
362 if (writeflag == MEM_WRITE) {
363 debug("[ sgi_ip22: write to mappable IRQ STAT, "
364 "data=0x%llx ]\n", (long long)idata);
365 } else {
366 debug("[ sgi_ip22: read from mappable IRQ STAT, "
367 "data=0x%llx ]\n", (long long)odata);
368 }
369 break;
370 case 0x14:
371 if (writeflag == MEM_WRITE) {
372 debug("[ sgi_ip22: write to mappable local0 IRQ "
373 "MASK, data=0x%llx ]\n", (long long)idata);
374 } else {
375 debug("[ sgi_ip22: read from mappable local0 IRQ "
376 "MASK, data=0x%llx ]\n", (long long)odata);
377 }
378 break;
379 case 0x18:
380 if (writeflag == MEM_WRITE) {
381 debug("[ sgi_ip22: write to mappable local1 IRQ "
382 "MASK, data=0x%llx ]\n", (long long)idata);
383 } else {
384 debug("[ sgi_ip22: read from mappable local1 IRQ "
385 "MASK, data=0x%llx ]\n", (long long)odata);
386 }
387 break;
388 case 0x38: /* timer count */
389 if (writeflag == MEM_WRITE) {
390 /* Two byte values are written to this address,
391 sequentially... TODO */
392 } else {
393 /* The timer is decreased by the tick function. */
394 }
395 break;
396 case 0x3b: /* ? */
397 odata = random();
398 break;
399 case 0x3c: /* timer control */
400 break;
401 case 0x3f: /* ? */
402 odata = random();
403 break;
404 default:
405 if (writeflag == MEM_WRITE) {
406 debug("[ sgi_ip22: unimplemented write to address "
407 "0x%x, data=0x%02x ]\n", (int)relative_addr,
408 (int)idata);
409 } else {
410 debug("[ sgi_ip22: unimplemented read from address "
411 "0x%llx ]\n", (long long)relative_addr);
412 }
413 }
414
415 if (writeflag == MEM_READ)
416 memory_writemax64(cpu, data, len, odata);
417
418 return 1;
419 }
420
421
422 /*
423 * dev_sgi_ip22_init():
424 */
425 struct sgi_ip22_data *dev_sgi_ip22_init(struct machine *machine,
426 struct memory *mem, uint64_t baseaddr, int guiness_flag)
427 {
428 struct sgi_ip22_data *d = malloc(sizeof(struct sgi_ip22_data));
429 if (d == NULL) {
430 fprintf(stderr, "out of memory\n");
431 exit(1);
432 }
433 memset(d, 0, sizeof(struct sgi_ip22_data));
434 d->guiness_flag = guiness_flag;
435
436 memory_device_register(mem, "sgi_ip22", baseaddr, DEV_SGI_IP22_LENGTH,
437 dev_sgi_ip22_access, (void *)d, MEM_DEFAULT, NULL);
438 memory_device_register(mem, "sgi_ip22_sysid", 0x1fbd9858, 0x8,
439 dev_sgi_ip22_sysid_access, (void *)d, MEM_DEFAULT, NULL);
440 memory_device_register(mem, "sgi_ip22_imc", IP22_IMC_BASE,
441 DEV_SGI_IP22_IMC_LENGTH, dev_sgi_ip22_imc_access, (void *)d,
442 MEM_DEFAULT, NULL);
443 memory_device_register(mem, "sgi_ip22_unknown", 0x1fa01000, 0x10,
444 dev_sgi_ip22_unknown_access, (void *)d, MEM_DEFAULT, NULL);
445 memory_device_register(mem, "sgi_ip22_unknown2", IP22_UNKNOWN2_BASE,
446 DEV_SGI_IP22_UNKNOWN2_LENGTH, dev_sgi_ip22_unknown2_access,
447 (void *)d, MEM_DEFAULT, NULL);
448
449 machine_add_tickfunction(machine, dev_sgi_ip22_tick, d,
450 SGI_IP22_TICK_SHIFT);
451
452 return d;
453 }
454

  ViewVC Help
Powered by ViewVC 1.1.26