1 /*
2 * Copyright (C) 2003-2020 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 * COMMENT: SGI IP32 stuff (CRIME, MACE, MACEPCI, ust)
29 *
30 * o) CRIME (interrupt controller)
31 * o) MACE (Multimedia, Audio and Communications Engine)
32 * o) MACE PCI bus
33 * o) ust (unknown device)
34 *
35 * TODO:
36 * o) VICE (Video and Image Compression Engine)
37 * (perhaps best to place in the Graphics Back End?)
38 *
39 * The GBE graphics (Graphics Back End) is in dev_sgi_gbe.cc.
40 *
41 * Some info here: http://bukosek.si/hardware/collection/sgi-o2.html
42 * but mostly based on how NetBSD, OpenBSD, and Linux use the hardware.
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/time.h>
49
50 #include "bus_pci.h"
51 #include "console.h"
52 #include "cpu.h"
53 #include "device.h"
54 #include "devices.h"
55 #include "emul.h"
56 #include "machine.h"
57 #include "memory.h"
58 #include "misc.h"
59 #include "net.h"
60
61 #include "thirdparty/crimereg.h"
62 #include "thirdparty/sgi_macereg.h"
63
64 // #define debug fatal
65
66 // #define MACEPCI_DEBUG
67
68 #define CRIME_TICKSHIFT 14
69
70
71 struct macepci_data {
72 struct pci_data *pci_data;
73 };
74
75 #define DEV_CRIME_LENGTH 0x280
76 struct crime_data {
77 uint64_t reg[DEV_CRIME_LENGTH / sizeof(uint64_t)];
78
79 uint64_t last_microseconds;
80
81 struct interrupt irq;
82 int prev_asserted;
83
84 int use_fb;
85 };
86
87
88 void mips_pc_to_pointers(struct cpu *);
89 void mips32_pc_to_pointers(struct cpu *);
90
91
crime_interrupt_reassert(struct crime_data * d)92 void crime_interrupt_reassert(struct crime_data *d)
93 {
94 uint64_t status =
95 d->reg[CRIME_SOFTINT / sizeof(uint64_t)] |
96 d->reg[CRIME_HARDINT / sizeof(uint64_t)];
97
98 d->reg[CRIME_INTSTAT / sizeof(uint64_t)] = status;
99
100 status &= d->reg[CRIME_INTMASK / sizeof(uint64_t)];
101
102 #if 0
103 printf("CRIME SOFTINT=0x%08x HARDINT=0x%08x => 0x%08x, INTMASK=0x%08x\n",
104 (uint32_t)d->reg[CRIME_SOFTINT / sizeof(uint64_t)],
105 (uint32_t)d->reg[CRIME_HARDINT / sizeof(uint64_t)],
106 (uint32_t)status,
107 (uint32_t)d->reg[CRIME_INTMASK / sizeof(uint64_t)]);
108 #endif
109
110 int asserted = !!status;
111
112 if (asserted && !d->prev_asserted)
113 INTERRUPT_ASSERT(d->irq);
114 else if (!asserted && d->prev_asserted)
115 INTERRUPT_DEASSERT(d->irq);
116
117 d->prev_asserted = asserted;
118 }
119
120 /*
121 * crime_interrupt_assert():
122 * crime_interrupt_deassert():
123 */
crime_interrupt_assert(struct interrupt * interrupt)124 void crime_interrupt_assert(struct interrupt *interrupt)
125 {
126 struct crime_data *d = (struct crime_data *) interrupt->extra;
127 d->reg[CRIME_HARDINT / sizeof(uint64_t)] |= interrupt->line;
128 //printf("CRIME asserting 0x%08x\n", interrupt->line);
129 crime_interrupt_reassert(d);
130 }
crime_interrupt_deassert(struct interrupt * interrupt)131 void crime_interrupt_deassert(struct interrupt *interrupt)
132 {
133 struct crime_data *d = (struct crime_data *) interrupt->extra;
134 d->reg[CRIME_HARDINT / sizeof(uint64_t)] &= ~interrupt->line;
135 //printf("CRIME deasserting 0x%08x\n", interrupt->line);
136 crime_interrupt_reassert(d);
137 }
138
139
crime_update_crime_time(struct crime_data * d)140 void crime_update_crime_time(struct crime_data* d)
141 {
142 struct timeval tv;
143
144 gettimeofday(&tv, NULL);
145
146 uint64_t microseconds = tv.tv_sec * 1000000 + tv.tv_usec;
147 if (d->last_microseconds == 0)
148 d->last_microseconds = microseconds;
149
150 int64_t delta = microseconds - d->last_microseconds;
151
152 if (delta < 0) {
153 fatal("[ crime_update_crime_time: host system time went backwards? ]\n");
154 d->last_microseconds = microseconds;
155 delta = 0;
156 }
157
158 // The delta to add is 66 per microsecond.
159 int64_t to_add = delta * 66;
160
161 if (to_add >= 1) {
162 // NetBSD says CRIME_TIME_MASK = 0x0000ffffffffffffULL
163 // but my O2 seems to use only the lower 32 bits as an
164 // _unsigned_ value. (TODO: Double-check this again.)
165 d->reg[CRIME_TIME / sizeof(uint64_t)] =
166 (uint32_t)(d->reg[CRIME_TIME / sizeof(uint64_t)] + to_add);
167
168 d->last_microseconds = microseconds;
169 }
170 }
171
172
173 /*
174 * dev_crime_tick():
175 *
176 * Updates CRIME_TIME (at 66 MHz) and reassert CRIME interrupts.
177 */
DEVICE_TICK(crime)178 DEVICE_TICK(crime)
179 {
180 struct crime_data *d = (struct crime_data *) extra;
181
182 crime_update_crime_time(d);
183 crime_interrupt_reassert(d);
184 }
185
186
DEVICE_ACCESS(crime)187 DEVICE_ACCESS(crime)
188 {
189 /*
190 * The CRIME is memory mapped as 0x80 bytes, starting at
191 * physical 0x14000000.
192 *
193 * On my real O2:
194 *
195 * 0x14000080..0x140000ff is the same as 0x14000000..0x1400007f.
196 * 0x14000100..0x1400017f is the same as 0x14000000..0x1400007f.
197 * 0x14000180..0x140001ff is the same as 0x14000000..0x1400007f.
198 *
199 * (I assume that real code will never access the above "mirrors",
200 * but it would be trivial to add redirection so that such code
201 * would work too.)
202 *
203 * Memory control then starts at 0x14000200.
204 */
205 struct crime_data *d = (struct crime_data *) extra;
206 uint64_t idata = 0, odata = 0;
207 uint64_t preserved_CRIME_HARDINT = d->reg[CRIME_HARDINT / sizeof(uint64_t)];
208 size_t i;
209
210 if (writeflag == MEM_WRITE)
211 idata = memory_readmax64(cpu, data, len);
212
213 /*
214 * Set crime version/revision:
215 *
216 * This might not be the most elegant or correct solution, but it
217 * seems that the IP32 PROM likes 0x11 for machines without graphics,
218 * and 0xa1 for machines with graphics.
219 *
220 * NetBSD 2.0 complains about "unknown" crime for 0x11, but I guess
221 * that's something one has to live with. (TODO?)
222 */
223 d->reg[CRIME_REV / sizeof(uint64_t)] = d->use_fb? 0xa1 : 0x11;
224
225 d->reg[CRIME_CONTROL / sizeof(uint64_t)] = CRIME_CONTROL_ENDIANESS;
226
227 d->reg[CRIME_INTSTAT / sizeof(uint64_t)] =
228 (d->reg[CRIME_SOFTINT / sizeof(uint64_t)] |
229 d->reg[CRIME_HARDINT / sizeof(uint64_t)]);
230
231 /*
232 * Amount of memory. Bit 8 of bank control set ==> 128MB instead
233 * of 32MB per bank (?)
234 *
235 * According to OpenBSD, "Empty banks are reported as duplicates of
236 * bank #0."
237 */
238 if (cpu->machine->physical_ram_in_mb > 1024) {
239 fatal("[ sgi_crime: SGI O2 can not have more than 1024 MB RAM ]\n");
240 exit(1);
241 }
242
243 int mb_per_bank;
244 if (cpu->machine->physical_ram_in_mb <= 256)
245 mb_per_bank = 32;
246 else
247 mb_per_bank = 128;
248
249 if (cpu->machine->physical_ram_in_mb % mb_per_bank) {
250 fatal("[ sgi_crime: for up to 256 MB RAM, RAM size needs to be divisible "
251 "by 32 MB. for larger RAM sizes (up to 1024 MB), it needs to be "
252 "divisible by 128 MB. ]\n");
253 exit(1);
254 }
255
256 int flag_for_128MB = mb_per_bank == 128 ? 0x100 : 0x000;
257 size_t total_mb = 0;
258 for (int bank = 0; bank < 8; ++bank) {
259 int b = mb_per_bank == 128 ? (bank << 2) : bank;
260 if (total_mb >= cpu->machine->physical_ram_in_mb)
261 d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + bank] =
262 d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + 0];
263 else
264 d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + bank] = flag_for_128MB | b;
265
266 total_mb += mb_per_bank;
267 }
268
269 if (len == 8) {
270 if (writeflag == MEM_WRITE)
271 d->reg[relative_addr / 8] = idata;
272 else
273 odata = d->reg[relative_addr / 8];
274 } else if (len == 4) {
275 if (writeflag == MEM_WRITE) {
276 if (relative_addr & 4) {
277 d->reg[relative_addr / 8] &= ~0xffffffffULL;
278 d->reg[relative_addr / 8] |= (uint32_t)idata;
279 } else {
280 d->reg[relative_addr / 8] &= 0xffffffffULL;
281 d->reg[relative_addr / 8] |= (uint64_t)(idata << 32ULL);
282 }
283 } else {
284 odata = d->reg[relative_addr / 8];
285 if (relative_addr & 4)
286 odata = (int32_t)odata;
287 else
288 odata = (int32_t)(odata >> 32);
289 }
290 } else {
291 fatal("crime access len = %i!\n", len);
292 exit(1);
293 }
294
295 switch (relative_addr) {
296
297 case CRIME_REV: /* 0x000 */
298 /*
299 * A contender for winning a prize for the worst hack
300 * in history: the IP32 PROM probes the CPU caches during
301 * bootup, but they are not really emulated, so it fails.
302 * During the probe, the CRIME_REV is read a lot. By
303 * "returning" from the probe function, i.e. jumping to ra,
304 * when this register is read the second time, the probe
305 * can be skipped, and the PROM thus runs further.
306 *
307 * The address where this happens is:
308 * 0xbfc0517c PROM v2.3
309 * 0xbfc051ac PROM v4.13
310 *
311 * 4.18 works too.
312 *
313 * By extrapolating a bit (allowing for variations for other
314 * versions of the PROM), let's return if the read of the
315 * CRIME_REV register occurs anywhere near 0xbfc051XX.
316 */
317 if (((uint32_t)cpu->pc & 0xffffff00) == (uint32_t)0xbfc05100) {
318 cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
319 if (cpu->is_32bit)
320 mips32_pc_to_pointers(cpu);
321 else
322 mips_pc_to_pointers(cpu);
323 }
324 break;
325
326 case CRIME_CONTROL: /* 0x008 */
327 /* TODO: 64-bit write to CRIME_CONTROL, but some things
328 (such as NetBSD 1.6.2) write to 0x00c! */
329 if (writeflag == MEM_WRITE) {
330 /*
331 * 0x200 = watchdog timer (according to NetBSD)
332 * 0x800 = "reboot" used by the IP32 PROM
333 */
334 if (idata & CRIME_CONTROL_DOG_ENABLE) {
335 idata &= ~CRIME_CONTROL_DOG_ENABLE;
336 }
337 if (idata & CRIME_CONTROL_HARD_RESET) {
338 int j;
339
340 /* This is used by the IP32 PROM's
341 "reboot" command: */
342 for (j=0; j<cpu->machine->ncpus; j++)
343 cpu->machine->cpus[j]->running = 0;
344 cpu->machine->
345 exit_without_entering_debugger = 1;
346 idata &= ~CRIME_CONTROL_HARD_RESET;
347 }
348
349 idata &= ~CRIME_CONTROL_ENDIANESS;
350
351 if (idata != 0)
352 fatal("[ CRIME_CONTROL: unimplemented "
353 "control 0x%016llx ]\n", (long long)idata);
354 }
355 break;
356
357 case CRIME_INTSTAT: /* 0x010, Current interrupt status */
358 case CRIME_INTMASK: /* 0x018, Current interrupt mask */
359 crime_interrupt_reassert(d);
360 break;
361
362 case CRIME_DOG: /* 0x030 */
363 // No warning.
364 break;
365
366 case CRIME_TIME: /* 0x038 */
367 crime_update_crime_time(d);
368 break;
369
370 default:
371 if (writeflag==MEM_READ) {
372 debug("[ crime: read from 0x%x, len=%i:",
373 (int)relative_addr, len);
374 for (i=0; i<len; i++)
375 debug(" %02x", data[i]);
376 debug(" ]\n");
377 } else {
378 debug("[ crime: write to 0x%x:", (int)relative_addr);
379 for (i=0; i<len; i++)
380 debug(" %02x", data[i]);
381 debug(" (len=%i) ]\n", len);
382 }
383 }
384
385 d->reg[CRIME_HARDINT / sizeof(uint64_t)] = preserved_CRIME_HARDINT;
386 d->reg[CRIME_INTSTAT / sizeof(uint64_t)] =
387 (d->reg[CRIME_SOFTINT / sizeof(uint64_t)] |
388 d->reg[CRIME_HARDINT / sizeof(uint64_t)]);
389
390 if (writeflag == MEM_READ)
391 memory_writemax64(cpu, data, len, odata);
392
393 return 1;
394 }
395
396
397 /*
398 * dev_crime_init():
399 */
dev_crime_init(struct machine * machine,struct memory * mem,uint64_t baseaddr,char * irq_path,int use_fb)400 void dev_crime_init(struct machine *machine, struct memory *mem,
401 uint64_t baseaddr, char *irq_path, int use_fb)
402 {
403 struct crime_data *d;
404 char tmpstr[200];
405 int i;
406
407 CHECK_ALLOCATION(d = (struct crime_data *) malloc(sizeof(struct crime_data)));
408 memset(d, 0, sizeof(struct crime_data));
409
410 d->use_fb = use_fb;
411
412 INTERRUPT_CONNECT(irq_path, d->irq);
413
414 /* Register 32 crime interrupts (hexadecimal names): */
415 for (i=0; i<32; i++) {
416 struct interrupt templ;
417 char name[400];
418 snprintf(name, sizeof(name), "%s.crime.0x%x", irq_path, 1 << i);
419 memset(&templ, 0, sizeof(templ));
420 templ.line = 1 << i;
421 templ.name = name;
422 templ.extra = d;
423 templ.interrupt_assert = crime_interrupt_assert;
424 templ.interrupt_deassert = crime_interrupt_deassert;
425 interrupt_handler_register(&templ);
426 }
427
428 memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH,
429 dev_crime_access, d, DM_DEFAULT, NULL);
430
431 snprintf(tmpstr, sizeof(tmpstr), "mace addr=0x1f310000 irq=%s.crime",
432 irq_path);
433 device_add(machine, tmpstr);
434
435 machine_add_tickfunction(machine, dev_crime_tick, d,
436 CRIME_TICKSHIFT);
437 }
438
439
440 /****************************************************************************/
441
442
443 #define DEV_MACE_LENGTH 0x100
444 struct mace_data {
445 unsigned char reg[DEV_MACE_LENGTH];
446 struct interrupt irq_periph;
447 struct interrupt irq_misc;
448 int prev_assert_periph;
449 int prev_assert_misc;
450 };
451
452
mace_interrupt_reassert(struct mace_data * d)453 void mace_interrupt_reassert(struct mace_data *d)
454 {
455 uint8_t s4 = d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4];
456 uint8_t s5 = d->reg[MACE_ISA_INT_STATUS+5] & d->reg[MACE_ISA_INT_MASK+5];
457 uint8_t s6 = d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6];
458 uint8_t s7 = d->reg[MACE_ISA_INT_STATUS+7] & d->reg[MACE_ISA_INT_MASK+7];
459
460 int assert_periph = s4 | s5 ? 1 : 0;
461 int assert_misc = s6 | s7 ? 1 : 0;
462
463 /*
464 printf("status=%02x%02x%02x%02x mask=%02x%02x%02x%02x => periph = %i misc = %i\n",
465 d->reg[MACE_ISA_INT_STATUS+4],
466 d->reg[MACE_ISA_INT_STATUS+5],
467 d->reg[MACE_ISA_INT_STATUS+6],
468 d->reg[MACE_ISA_INT_STATUS+7],
469 d->reg[MACE_ISA_INT_MASK+4],
470 d->reg[MACE_ISA_INT_MASK+5],
471 d->reg[MACE_ISA_INT_MASK+6],
472 d->reg[MACE_ISA_INT_MASK+7],
473 assert_periph, assert_misc);
474 */
475
476 if (assert_periph != d->prev_assert_periph) {
477 d->prev_assert_periph = assert_periph;
478 if (assert_periph)
479 INTERRUPT_ASSERT(d->irq_periph);
480 else
481 INTERRUPT_DEASSERT(d->irq_periph);
482 }
483
484 if (assert_misc != d->prev_assert_misc) {
485 d->prev_assert_misc = assert_misc;
486 if (assert_misc)
487 INTERRUPT_ASSERT(d->irq_misc);
488 else
489 INTERRUPT_DEASSERT(d->irq_misc);
490 }
491 }
492
493
494
495 /*
496 * mace_interrupt_assert():
497 * mace_interrupt_deassert():
498 */
mace_interrupt_assert(struct interrupt * interrupt)499 void mace_interrupt_assert(struct interrupt *interrupt)
500 {
501 struct mace_data *d = (struct mace_data *) interrupt->extra;
502 uint32_t line = 1 << interrupt->line;
503
504 d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255);
505 d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255);
506 d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255);
507 d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255);
508
509 mace_interrupt_reassert(d);
510 }
mace_interrupt_deassert(struct interrupt * interrupt)511 void mace_interrupt_deassert(struct interrupt *interrupt)
512 {
513 struct mace_data *d = (struct mace_data *) interrupt->extra;
514 uint32_t line = 1 << interrupt->line;
515
516 d->reg[MACE_ISA_INT_STATUS + 4] &= ~((line >> 24) & 255);
517 d->reg[MACE_ISA_INT_STATUS + 5] &= ~((line >> 16) & 255);
518 d->reg[MACE_ISA_INT_STATUS + 6] &= ~((line >> 8) & 255);
519 d->reg[MACE_ISA_INT_STATUS + 7] &= ~(line & 255);
520
521 mace_interrupt_reassert(d);
522 }
523
524
DEVICE_ACCESS(mace)525 DEVICE_ACCESS(mace)
526 {
527 size_t i;
528 struct mace_data *d = (struct mace_data *) extra;
529
530 /*
531 * My O2 returns the following when dumping 0xbf310000 and forward:
532 *
533 * +0x00: 0x0000000000000010 0x000000000000001e
534 * +0x10: 0x0000000000000000 0x0000000000000000
535 *
536 * and then the following addresses result in the same data as
537 * 0xbf310000.
538 */
539 d->reg[MACE_ISA_RINGBASE + 7] = 0x10;
540 d->reg[MACE_ISA_FLASH_NIC_REG + 7] |= MACE_ISA_PWD_CLEAR;
541
542 uint8_t old_mace_isa_flash_nic_reg =
543 d->reg[MACE_ISA_FLASH_NIC_REG + 7];
544
545 if (writeflag == MEM_WRITE)
546 memcpy(&d->reg[relative_addr], data, len);
547 else
548 memcpy(data, &d->reg[relative_addr], len);
549
550 switch (relative_addr & ~7) {
551
552 case MACE_ISA_RINGBASE:
553 break;
554
555 case MACE_ISA_FLASH_NIC_REG:
556 // I think the PROM attempts to read the machine's ethernet
557 // address from a DS2502 EPROM, by writing MACE_ISA_NIC_DEASSERT
558 // to this register in various patterns, and looking at the
559 // resulting MACE_ISA_NIC_DATA (or does it write data as well?)
560 // In any case, onewire is too complicated to implement right
561 // now. TODO.
562 if (writeflag)
563 {
564 /*
565 * The NetBSD defines are called "RED" and "GREEN",
566 * and are documented like this:
567 *
568 * 1=> Illuminate RED LED
569 *
570 * (and similarly for GREEN). But on my O2, it feels
571 * like the other way around (i.e. 1 = do NOT illuminate
572 * that LED color). Also, having it this way is more
573 * compatible with how NetBSD, OpenBSD, and the PROM
574 * actually use the LED.
575 */
576 uint8_t change = (d->reg[MACE_ISA_FLASH_NIC_REG + 7]
577 ^ old_mace_isa_flash_nic_reg) &
578 (MACE_ISA_LED_RED | MACE_ISA_LED_GREEN);
579 if (change) {
580 switch (d->reg[MACE_ISA_FLASH_NIC_REG + 7] & (MACE_ISA_LED_RED | MACE_ISA_LED_GREEN)) {
581 case 0: debug("[ mace: turning LED WHITE/ORANGE ]\n");
582 break;
583 case MACE_ISA_LED_RED:
584 debug("[ mace: turning LED GREEN ]\n");
585 break;
586 case MACE_ISA_LED_GREEN:
587 debug("[ mace: turning LED RED ]\n");
588 break;
589 default:fatal("[ mace: turning LED OFF ]\n");
590 break;
591 }
592 }
593
594 //printf("%02x: MACE_ISA_NIC_DEASSERT = %i, DATA = %i\n",
595 //d->reg[MACE_ISA_FLASH_NIC_REG + 7],
596 //d->reg[MACE_ISA_FLASH_NIC_REG + 7] & MACE_ISA_NIC_DEASSERT,
597 //d->reg[MACE_ISA_FLASH_NIC_REG + 7] & MACE_ISA_NIC_DATA);
598 } else {
599 // data[len-1] ^= (random() & MACE_ISA_NIC_DATA);
600 // data[len-1] |= MACE_ISA_NIC_DEASSERT;
601 }
602 break;
603
604 case MACE_ISA_INT_STATUS: /* Current interrupt assertions */
605 /* don't dump debug info for these */
606 if (writeflag == MEM_WRITE) {
607 fatal("[ NOTE/TODO: WRITE to mace intr: "
608 "reladdr=0x%x data=", (int)relative_addr);
609 for (i=0; i<len; i++)
610 fatal(" %02x", data[i]);
611 fatal(" (len=%i) ]\n", len);
612 }
613 break;
614 case MACE_ISA_INT_MASK: /* Current interrupt mask */
615 mace_interrupt_reassert(d);
616 break;
617
618 default:
619 if (writeflag == MEM_READ) {
620 debug("[ mace: read from 0x%x:", (int)relative_addr);
621 for (i=0; i<len; i++)
622 debug(" %02x", data[i]);
623 debug(" (len=%i) ]\n", len);
624 } else {
625 debug("[ mace: write to 0x%x:", (int)relative_addr);
626 for (i=0; i<len; i++)
627 debug(" %02x", data[i]);
628 debug(" (len=%i) ]\n", len);
629 }
630 }
631
632 return 1;
633 }
634
635
DEVINIT(mace)636 DEVINIT(mace)
637 {
638 struct mace_data *d;
639 char tmpstr[300];
640 int i;
641
642 CHECK_ALLOCATION(d = (struct mace_data *) malloc(sizeof(struct mace_data)));
643 memset(d, 0, sizeof(struct mace_data));
644
645 snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
646 devinit->interrupt_path, CRIME_INT_PERIPH_SERIAL);
647 INTERRUPT_CONNECT(tmpstr, d->irq_periph);
648
649 snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
650 devinit->interrupt_path, CRIME_INT_PERIPH_MISC);
651 INTERRUPT_CONNECT(tmpstr, d->irq_misc);
652
653 /*
654 * For CRIME interrupts PERIPH_SERIAL and PERIPH_MISC,
655 * register 32 mace interrupts each.
656 */
657 for (i=0; i<32; i++) {
658 struct interrupt templ;
659 char name[400];
660 snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
661 devinit->interrupt_path, CRIME_INT_PERIPH_SERIAL, i);
662 memset(&templ, 0, sizeof(templ));
663 templ.line = i;
664 templ.name = name;
665 templ.extra = d;
666 templ.interrupt_assert = mace_interrupt_assert;
667 templ.interrupt_deassert = mace_interrupt_deassert;
668 interrupt_handler_register(&templ);
669
670 snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
671 devinit->interrupt_path, CRIME_INT_PERIPH_MISC, i);
672 memset(&templ, 0, sizeof(templ));
673 templ.line = i;
674 templ.name = name;
675 templ.extra = d;
676 templ.interrupt_assert = mace_interrupt_assert;
677 templ.interrupt_deassert = mace_interrupt_deassert;
678 interrupt_handler_register(&templ);
679 }
680
681 memory_device_register(devinit->machine->memory, devinit->name,
682 devinit->addr, DEV_MACE_LENGTH, dev_mace_access, d,
683 DM_DEFAULT, NULL);
684
685 devinit->return_ptr = d;
686 return 1;
687 }
688
689
690 /****************************************************************************/
691
692
DEVICE_ACCESS(macepci)693 DEVICE_ACCESS(macepci)
694 {
695 struct macepci_data *d = (struct macepci_data *) extra;
696 uint64_t idata = 0, odata=0;
697 int res = 1, bus, dev, func, pcireg;
698
699 if (len != 4)
700 fatal("[ macepci: unimplemented len %i ]\n", len);
701
702 if (writeflag == MEM_WRITE) {
703 idata = memory_readmax64(cpu, data, len);
704 #ifdef MACEPCI_DEBUG
705 fatal("[ macepci: write to address 0x%x, data=0x%02x (len %i) ]\n",
706 (int)relative_addr, (int)idata, len);
707 #endif
708 }
709
710 /* Read from/write to the macepci: */
711 switch (relative_addr) {
712
713 case 0x00: /* Error address */
714 if (writeflag == MEM_WRITE) {
715 } else {
716 /* My real O2 returns 0x4000. */
717 odata = 0x4000;
718 }
719 break;
720
721 case 0x04: /* Error flags */
722 if (writeflag == MEM_WRITE) {
723 } else {
724 /* My real O2 returns 0x00100006. */
725 odata = 0x00100006;
726 }
727 break;
728
729 case 0x08: /* TODO: Unknown? */
730 if (writeflag == MEM_WRITE) {
731 } else {
732 /* My real O2 returns 0xff000500. */
733 odata = 0xff000500;
734 }
735 break;
736
737 case 0x0c: /* Revision number */
738 if (writeflag == MEM_WRITE) {
739 } else {
740 /* My real O2 returns 0x00000001. */
741 odata = 0x00000001;
742 }
743 break;
744
745 case 0xcf8: /* PCI ADDR */
746 bus_pci_decompose_1(idata, &bus, &dev, &func, &pcireg);
747 bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, pcireg);
748 break;
749
750 case 0xcfc: /* PCI DATA */
751 bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
752 &odata : &idata, len, writeflag);
753 break;
754
755 default:
756 if (writeflag == MEM_WRITE) {
757 fatal("[ macepci: unimplemented write to address "
758 "0x%x, data=0x%02x ]\n",
759 (int)relative_addr, (int)idata);
760 } else {
761 fatal("[ macepci: unimplemented read from address "
762 "0x%x ]\n", (int)relative_addr);
763
764 /* My real O2 returns 0xffffffff for all unimplemented
765 registers. */
766 odata = 0xffffffff;
767 }
768 }
769
770 if (writeflag == MEM_READ) {
771 memory_writemax64(cpu, data, len, odata);
772 #ifdef MACEPCI_DEBUG
773 fatal("[ macepci: read from address 0x%x, data=0x%02x (len %i) ]\n",
774 (int)relative_addr, (int)odata, len);
775 #endif
776 }
777
778 return res;
779 }
780
781
782 /*
783 * dev_macepci_init():
784 */
dev_macepci_init(struct machine * machine,struct memory * mem,uint64_t baseaddr,char * irq_path)785 struct pci_data *dev_macepci_init(struct machine *machine,
786 struct memory *mem, uint64_t baseaddr, char *irq_path)
787 {
788 struct macepci_data *d;
789
790 CHECK_ALLOCATION(d = (struct macepci_data *) malloc(sizeof(struct macepci_data)));
791 memset(d, 0, sizeof(struct macepci_data));
792
793 /* TODO: PCI vs ISA interrupt? */
794
795 d->pci_data = bus_pci_init(machine,
796 irq_path,
797 0,
798 0,
799 0,
800 0,
801 "TODO: pci irq path",
802 0x18000003, /* ISA portbase */
803 0,
804 irq_path);
805
806 memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH,
807 dev_macepci_access, (void *)d, DM_DEFAULT, NULL);
808
809 return d->pci_data;
810 }
811
812
813 /****************************************************************************/
814
815
816 struct sgi_ust_data {
817 uint64_t reg[DEV_SGI_UST_LENGTH / sizeof(uint64_t)];
818 };
819
820
DEVICE_ACCESS(sgi_ust)821 DEVICE_ACCESS(sgi_ust)
822 {
823 struct sgi_ust_data *d = (struct sgi_ust_data *) extra;
824 uint64_t idata = 0, odata = 0;
825 int regnr;
826
827 idata = memory_readmax64(cpu, data, len);
828 regnr = relative_addr / sizeof(uint64_t);
829
830 /* Treat all registers as read/write, by default. */
831 if (writeflag == MEM_WRITE)
832 d->reg[regnr] = idata;
833 else
834 odata = d->reg[regnr];
835
836 switch (relative_addr) {
837 case 0:
838 d->reg[regnr] += 0x2710; // HUH?
839 break;
840 default:
841 if (writeflag == MEM_WRITE)
842 debug("[ sgi_ust: unimplemented write to "
843 "address 0x%llx, data=0x%016llx ]\n",
844 (long long)relative_addr, (long long)idata);
845 else
846 debug("[ sgi_ust: unimplemented read from address"
847 " 0x%llx ]\n", (long long)relative_addr);
848 }
849
850 if (writeflag == MEM_READ)
851 memory_writemax64(cpu, data, len, odata);
852
853 return 1;
854 }
855
856
857 /*
858 * dev_sgi_ust_init():
859 */
dev_sgi_ust_init(struct memory * mem,uint64_t baseaddr)860 void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
861 {
862 struct sgi_ust_data *d;
863
864 CHECK_ALLOCATION(d = (struct sgi_ust_data *) malloc(sizeof(struct sgi_ust_data)));
865 memset(d, 0, sizeof(struct sgi_ust_data));
866
867 memory_device_register(mem, "sgi_ust", baseaddr,
868 DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d,
869 DM_DEFAULT, NULL);
870 }
871
872
873