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