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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 13184 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


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