dev_sgi_ip32.cc Source File

Back to the index.

dev_sgi_ip32.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2018 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 
80 
81  struct interrupt irq;
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 
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)
116 
117  d->prev_asserted = asserted;
118 }
119 
120 /*
121  * crime_interrupt_assert():
122  * crime_interrupt_deassert():
123  */
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);
130 }
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);
137 }
138 
139 
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  */
179 {
180  struct crime_data *d = (struct crime_data *) extra;
181 
184 }
185 
186 
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  * When the bank control registers contain the same value as the
236  * previous one, that bank is not valid. (?)
237  *
238  * TODO: Make this work reliably with other sizes than 128 or 256 MB.
239  * 128 MB is what I have in my machine. Theoretically, up to 1 GB
240  * could be supported in the O2, of which the first 256 MB is
241  * accessible at low physical addresses (below 0x10000000).
242  */
243  if (cpu->machine->physical_ram_in_mb >= 1024) {
244  fatal("[ sgi_crime: SGI O2 can not have more than 1024 MB RAM ]\n");
245  exit(1);
246  }
247 
248  int mb_per_bank;
249  if (cpu->machine->physical_ram_in_mb <= 256)
250  mb_per_bank = 32;
251  else
252  mb_per_bank = 128;
253 
254  if (cpu->machine->physical_ram_in_mb % mb_per_bank) {
255  fatal("[ sgi_crime: for up to 256 MB RAM, RAM size needs to be divisible "
256  "by 32 MB. for larger RAM sizes (up to 1024 MB), it needs to be "
257  "divisible by 128 MB. ]\n");
258  exit(1);
259  }
260 
261  int flag_for_128MB = mb_per_bank == 128 ? 0x100 : 0x000;
262  int total_mb = 0;
263  for (int bank = 0; bank < 8; ++bank) {
264  int b = mb_per_bank == 128 ? (bank << 2) : bank;
265  if (total_mb >= cpu->machine->physical_ram_in_mb)
266  d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + bank] =
267  d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + 0];
268  else
269  d->reg[CRIME_MEM_BANK_CTRL0 / sizeof(uint64_t) + bank] = flag_for_128MB | b;
270  total_mb += mb_per_bank;
271  }
272 
273  if (len == 8) {
274  if (writeflag == MEM_WRITE)
275  d->reg[relative_addr / 8] = idata;
276  else
277  odata = d->reg[relative_addr / 8];
278  } else if (len == 4) {
279  if (writeflag == MEM_WRITE) {
280  if (relative_addr & 4) {
281  d->reg[relative_addr / 8] &= ~0xffffffffULL;
282  d->reg[relative_addr / 8] |= (uint32_t)idata;
283  } else {
284  d->reg[relative_addr / 8] &= 0xffffffffULL;
285  d->reg[relative_addr / 8] |= (uint64_t)(idata << 32ULL);
286  }
287  } else {
288  odata = d->reg[relative_addr / 8];
289  if (relative_addr & 4)
290  odata = (int32_t)odata;
291  else
292  odata = (int32_t)(odata >> 32);
293  }
294  } else {
295  fatal("crime access len = %i!\n", len);
296  exit(1);
297  }
298 
299  switch (relative_addr) {
300 
301  case CRIME_REV: /* 0x000 */
302  /*
303  * A contender for winning a prize for the worst hack
304  * in history: the IP32 PROM probes the CPU caches during
305  * bootup, but they are not really emulated, so it fails.
306  * During the probe, the CRIME_REV is read a lot. By
307  * "returning" from the probe function, i.e. jumping to ra,
308  * when this register is read the second time, the probe
309  * can be skipped, and the PROM thus runs further.
310  *
311  * The address where this happens is:
312  * 0xbfc0517c PROM v2.3
313  * 0xbfc051ac PROM v4.13
314  *
315  * 4.18 works too.
316  *
317  * By extrapolating a bit (allowing for variations for other
318  * versions of the PROM), let's return if the read of the
319  * CRIME_REV register occurs anywhere near 0xbfc051XX.
320  */
321  if (((uint32_t)cpu->pc & 0xffffff00) == (uint32_t)0xbfc05100) {
322  cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
323  if (cpu->is_32bit)
325  else
327  }
328  break;
329 
330  case CRIME_CONTROL: /* 0x008 */
331  /* TODO: 64-bit write to CRIME_CONTROL, but some things
332  (such as NetBSD 1.6.2) write to 0x00c! */
333  if (writeflag == MEM_WRITE) {
334  /*
335  * 0x200 = watchdog timer (according to NetBSD)
336  * 0x800 = "reboot" used by the IP32 PROM
337  */
338  if (idata & CRIME_CONTROL_DOG_ENABLE) {
339  idata &= ~CRIME_CONTROL_DOG_ENABLE;
340  }
341  if (idata & CRIME_CONTROL_HARD_RESET) {
342  int j;
343 
344  /* This is used by the IP32 PROM's
345  "reboot" command: */
346  for (j=0; j<cpu->machine->ncpus; j++)
347  cpu->machine->cpus[j]->running = 0;
348  cpu->machine->
349  exit_without_entering_debugger = 1;
350  idata &= ~CRIME_CONTROL_HARD_RESET;
351  }
352 
353  idata &= ~CRIME_CONTROL_ENDIANESS;
354 
355  if (idata != 0)
356  fatal("[ CRIME_CONTROL: unimplemented "
357  "control 0x%016llx ]\n", (long long)idata);
358  }
359  break;
360 
361  case CRIME_INTSTAT: /* 0x010, Current interrupt status */
362  case CRIME_INTMASK: /* 0x018, Current interrupt mask */
364  break;
365 
366  case CRIME_DOG: /* 0x030 */
367  // No warning.
368  break;
369 
370  case CRIME_TIME: /* 0x038 */
372  break;
373 
374  default:
375  if (writeflag==MEM_READ) {
376  debug("[ crime: read from 0x%x, len=%i:",
377  (int)relative_addr, len);
378  for (i=0; i<len; i++)
379  debug(" %02x", data[i]);
380  debug(" ]\n");
381  } else {
382  debug("[ crime: write to 0x%x:", (int)relative_addr);
383  for (i=0; i<len; i++)
384  debug(" %02x", data[i]);
385  debug(" (len=%i) ]\n", len);
386  }
387  }
388 
389  d->reg[CRIME_HARDINT / sizeof(uint64_t)] = preserved_CRIME_HARDINT;
390  d->reg[CRIME_INTSTAT / sizeof(uint64_t)] =
391  (d->reg[CRIME_SOFTINT / sizeof(uint64_t)] |
392  d->reg[CRIME_HARDINT / sizeof(uint64_t)]);
393 
394  if (writeflag == MEM_READ)
395  memory_writemax64(cpu, data, len, odata);
396 
397  return 1;
398 }
399 
400 
401 /*
402  * dev_crime_init():
403  */
404 void dev_crime_init(struct machine *machine, struct memory *mem,
405  uint64_t baseaddr, char *irq_path, int use_fb)
406 {
407  struct crime_data *d;
408  char tmpstr[200];
409  int i;
410 
411  CHECK_ALLOCATION(d = (struct crime_data *) malloc(sizeof(struct crime_data)));
412  memset(d, 0, sizeof(struct crime_data));
413 
414  d->use_fb = use_fb;
415 
416  INTERRUPT_CONNECT(irq_path, d->irq);
417 
418  /* Register 32 crime interrupts (hexadecimal names): */
419  for (i=0; i<32; i++) {
420  struct interrupt templ;
421  char name[400];
422  snprintf(name, sizeof(name), "%s.crime.0x%x", irq_path, 1 << i);
423  memset(&templ, 0, sizeof(templ));
424  templ.line = 1 << i;
425  templ.name = name;
426  templ.extra = d;
430  }
431 
432  memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH,
433  dev_crime_access, d, DM_DEFAULT, NULL);
434 
435  snprintf(tmpstr, sizeof(tmpstr), "mace addr=0x1f310000 irq=%s.crime",
436  irq_path);
437  device_add(machine, tmpstr);
438 
439  machine_add_tickfunction(machine, dev_crime_tick, d,
441 }
442 
443 
444 /****************************************************************************/
445 
446 
447 #define DEV_MACE_LENGTH 0x100
448 struct mace_data {
449  unsigned char reg[DEV_MACE_LENGTH];
454 };
455 
456 
458 {
459  uint8_t s4 = d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4];
460  uint8_t s5 = d->reg[MACE_ISA_INT_STATUS+5] & d->reg[MACE_ISA_INT_MASK+5];
461  uint8_t s6 = d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6];
462  uint8_t s7 = d->reg[MACE_ISA_INT_STATUS+7] & d->reg[MACE_ISA_INT_MASK+7];
463 
464  int assert_periph = s4 | s5 ? 1 : 0;
465  int assert_misc = s6 | s7 ? 1 : 0;
466 
467 /*
468 printf("status=%02x%02x%02x%02x mask=%02x%02x%02x%02x => periph = %i misc = %i\n",
469 d->reg[MACE_ISA_INT_STATUS+4],
470 d->reg[MACE_ISA_INT_STATUS+5],
471 d->reg[MACE_ISA_INT_STATUS+6],
472 d->reg[MACE_ISA_INT_STATUS+7],
473 d->reg[MACE_ISA_INT_MASK+4],
474 d->reg[MACE_ISA_INT_MASK+5],
475 d->reg[MACE_ISA_INT_MASK+6],
476 d->reg[MACE_ISA_INT_MASK+7],
477  assert_periph, assert_misc);
478 */
479 
480  if (assert_periph != d->prev_assert_periph) {
481  d->prev_assert_periph = assert_periph;
482  if (assert_periph)
484  else
486  }
487 
488  if (assert_misc != d->prev_assert_misc) {
489  d->prev_assert_misc = assert_misc;
490  if (assert_misc)
492  else
494  }
495 }
496 
497 
498 
499 /*
500  * mace_interrupt_assert():
501  * mace_interrupt_deassert():
502  */
504 {
505  struct mace_data *d = (struct mace_data *) interrupt->extra;
506  uint32_t line = 1 << interrupt->line;
507 
508  d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255);
509  d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255);
510  d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255);
511  d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255);
512 
514 }
516 {
517  struct mace_data *d = (struct mace_data *) interrupt->extra;
518  uint32_t line = 1 << interrupt->line;
519 
520  d->reg[MACE_ISA_INT_STATUS + 4] &= ~((line >> 24) & 255);
521  d->reg[MACE_ISA_INT_STATUS + 5] &= ~((line >> 16) & 255);
522  d->reg[MACE_ISA_INT_STATUS + 6] &= ~((line >> 8) & 255);
523  d->reg[MACE_ISA_INT_STATUS + 7] &= ~(line & 255);
524 
526 }
527 
528 
530 {
531  size_t i;
532  struct mace_data *d = (struct mace_data *) extra;
533 
534  /*
535  * My O2 returns the following when dumping 0xbf310000 and forward:
536  *
537  * +0x00: 0x0000000000000010 0x000000000000001e
538  * +0x10: 0x0000000000000000 0x0000000000000000
539  *
540  * and then the following addresses result in the same data as
541  * 0xbf310000.
542  */
543  d->reg[MACE_ISA_RINGBASE + 7] = 0x10;
545 
546  uint8_t old_mace_isa_flash_nic_reg =
547  d->reg[MACE_ISA_FLASH_NIC_REG + 7];
548 
549  if (writeflag == MEM_WRITE)
550  memcpy(&d->reg[relative_addr], data, len);
551  else
552  memcpy(data, &d->reg[relative_addr], len);
553 
554  switch (relative_addr & ~7) {
555 
556  case MACE_ISA_RINGBASE:
557  break;
558 
560  // I think the PROM attempts to read the machine's ethernet
561  // address from a DS2502 EPROM, by writing MACE_ISA_NIC_DEASSERT
562  // to this register in various patterns, and looking at the
563  // resulting MACE_ISA_NIC_DATA (or does it write data as well?)
564  // In any case, onewire is too complicated to implement right
565  // now. TODO.
566  if (writeflag)
567  {
568  /*
569  * The NetBSD defines are called "RED" and "GREEN",
570  * and are documented like this:
571  *
572  * 1=> Illuminate RED LED
573  *
574  * (and similarly for GREEN). But on my O2, it feels
575  * like the other way around (i.e. 1 = do NOT illuminate
576  * that LED color). Also, having it this way is more
577  * compatible with how NetBSD, OpenBSD, and the PROM
578  * actually use the LED.
579  */
580  uint8_t change = (d->reg[MACE_ISA_FLASH_NIC_REG + 7]
581  ^ old_mace_isa_flash_nic_reg) &
583  if (change) {
585  case 0: debug("[ mace: turning LED WHITE/ORANGE ]\n");
586  break;
587  case MACE_ISA_LED_RED:
588  debug("[ mace: turning LED GREEN ]\n");
589  break;
590  case MACE_ISA_LED_GREEN:
591  debug("[ mace: turning LED RED ]\n");
592  break;
593  default:fatal("[ mace: turning LED OFF ]\n");
594  break;
595  }
596  }
597 
598 //printf("%02x: MACE_ISA_NIC_DEASSERT = %i, DATA = %i\n",
599  //d->reg[MACE_ISA_FLASH_NIC_REG + 7],
600 //d->reg[MACE_ISA_FLASH_NIC_REG + 7] & MACE_ISA_NIC_DEASSERT,
601  //d->reg[MACE_ISA_FLASH_NIC_REG + 7] & MACE_ISA_NIC_DATA);
602  } else {
603 // data[len-1] ^= (random() & MACE_ISA_NIC_DATA);
604 // data[len-1] |= MACE_ISA_NIC_DEASSERT;
605  }
606  break;
607 
608  case MACE_ISA_INT_STATUS: /* Current interrupt assertions */
609  /* don't dump debug info for these */
610  if (writeflag == MEM_WRITE) {
611  fatal("[ NOTE/TODO: WRITE to mace intr: "
612  "reladdr=0x%x data=", (int)relative_addr);
613  for (i=0; i<len; i++)
614  fatal(" %02x", data[i]);
615  fatal(" (len=%i) ]\n", len);
616  }
617  break;
618  case MACE_ISA_INT_MASK: /* Current interrupt mask */
620  break;
621 
622  default:
623  if (writeflag == MEM_READ) {
624  debug("[ mace: read from 0x%x:", (int)relative_addr);
625  for (i=0; i<len; i++)
626  debug(" %02x", data[i]);
627  debug(" (len=%i) ]\n", len);
628  } else {
629  debug("[ mace: write to 0x%x:", (int)relative_addr);
630  for (i=0; i<len; i++)
631  debug(" %02x", data[i]);
632  debug(" (len=%i) ]\n", len);
633  }
634  }
635 
636  return 1;
637 }
638 
639 
640 DEVINIT(mace)
641 {
642  struct mace_data *d;
643  char tmpstr[300];
644  int i;
645 
646  CHECK_ALLOCATION(d = (struct mace_data *) malloc(sizeof(struct mace_data)));
647  memset(d, 0, sizeof(struct mace_data));
648 
649  snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
651  INTERRUPT_CONNECT(tmpstr, d->irq_periph);
652 
653  snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
655  INTERRUPT_CONNECT(tmpstr, d->irq_misc);
656 
657  /*
658  * For CRIME interrupts PERIPH_SERIAL and PERIPH_MISC,
659  * register 32 mace interrupts each.
660  */
661  for (i=0; i<32; i++) {
662  struct interrupt templ;
663  char name[400];
664  snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
666  memset(&templ, 0, sizeof(templ));
667  templ.line = i;
668  templ.name = name;
669  templ.extra = d;
673 
674  snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
676  memset(&templ, 0, sizeof(templ));
677  templ.line = i;
678  templ.name = name;
679  templ.extra = d;
683  }
684 
686  devinit->addr, DEV_MACE_LENGTH, dev_mace_access, d,
687  DM_DEFAULT, NULL);
688 
689  devinit->return_ptr = d;
690  return 1;
691 }
692 
693 
694 /****************************************************************************/
695 
696 
698 {
699  struct macepci_data *d = (struct macepci_data *) extra;
700  uint64_t idata = 0, odata=0;
701  int res = 1, bus, dev, func, pcireg;
702 
703  if (len != 4)
704  fatal("[ macepci: unimplemented len %i ]\n", len);
705 
706  if (writeflag == MEM_WRITE) {
707  idata = memory_readmax64(cpu, data, len);
708 #ifdef MACEPCI_DEBUG
709  fatal("[ macepci: write to address 0x%x, data=0x%02x (len %i) ]\n",
710  (int)relative_addr, (int)idata, len);
711 #endif
712  }
713 
714  /* Read from/write to the macepci: */
715  switch (relative_addr) {
716 
717  case 0x00: /* Error address */
718  if (writeflag == MEM_WRITE) {
719  } else {
720  /* My real O2 returns 0x4000. */
721  odata = 0x4000;
722  }
723  break;
724 
725  case 0x04: /* Error flags */
726  if (writeflag == MEM_WRITE) {
727  } else {
728  /* My real O2 returns 0x00100006. */
729  odata = 0x00100006;
730  }
731  break;
732 
733  case 0x08: /* TODO: Unknown? */
734  if (writeflag == MEM_WRITE) {
735  } else {
736  /* My real O2 returns 0xff000500. */
737  odata = 0xff000500;
738  }
739  break;
740 
741  case 0x0c: /* Revision number */
742  if (writeflag == MEM_WRITE) {
743  } else {
744  /* My real O2 returns 0x00000001. */
745  odata = 0x00000001;
746  }
747  break;
748 
749  case 0xcf8: /* PCI ADDR */
750  bus_pci_decompose_1(idata, &bus, &dev, &func, &pcireg);
751  bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, pcireg);
752  break;
753 
754  case 0xcfc: /* PCI DATA */
755  bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
756  &odata : &idata, len, writeflag);
757  break;
758 
759  default:
760  if (writeflag == MEM_WRITE) {
761  fatal("[ macepci: unimplemented write to address "
762  "0x%x, data=0x%02x ]\n",
763  (int)relative_addr, (int)idata);
764  } else {
765  fatal("[ macepci: unimplemented read from address "
766  "0x%x ]\n", (int)relative_addr);
767 
768  /* My real O2 returns 0xffffffff for all unimplemented
769  registers. */
770  odata = 0xffffffff;
771  }
772  }
773 
774  if (writeflag == MEM_READ) {
775  memory_writemax64(cpu, data, len, odata);
776 #ifdef MACEPCI_DEBUG
777  fatal("[ macepci: read from address 0x%x, data=0x%02x (len %i) ]\n",
778  (int)relative_addr, (int)odata, len);
779 #endif
780  }
781 
782  return res;
783 }
784 
785 
786 /*
787  * dev_macepci_init():
788  */
789 struct pci_data *dev_macepci_init(struct machine *machine,
790  struct memory *mem, uint64_t baseaddr, char *irq_path)
791 {
792  struct macepci_data *d;
793 
794  CHECK_ALLOCATION(d = (struct macepci_data *) malloc(sizeof(struct macepci_data)));
795  memset(d, 0, sizeof(struct macepci_data));
796 
797  /* TODO: PCI vs ISA interrupt? */
798 
800  irq_path,
801  0,
802  0,
803  0,
804  0,
805  "TODO: pci irq path",
806  0x18000003, /* ISA portbase */
807  0,
808  irq_path);
809 
810  memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH,
811  dev_macepci_access, (void *)d, DM_DEFAULT, NULL);
812 
813  return d->pci_data;
814 }
815 
816 
817 /****************************************************************************/
818 
819 
820 struct sgi_ust_data {
821  uint64_t reg[DEV_SGI_UST_LENGTH / sizeof(uint64_t)];
822 };
823 
824 
826 {
827  struct sgi_ust_data *d = (struct sgi_ust_data *) extra;
828  uint64_t idata = 0, odata = 0;
829  int regnr;
830 
831  idata = memory_readmax64(cpu, data, len);
832  regnr = relative_addr / sizeof(uint64_t);
833 
834  /* Treat all registers as read/write, by default. */
835  if (writeflag == MEM_WRITE)
836  d->reg[regnr] = idata;
837  else
838  odata = d->reg[regnr];
839 
840  switch (relative_addr) {
841  case 0:
842  d->reg[regnr] += 0x2710; // HUH?
843  break;
844  default:
845  if (writeflag == MEM_WRITE)
846  debug("[ sgi_ust: unimplemented write to "
847  "address 0x%llx, data=0x%016llx ]\n",
848  (long long)relative_addr, (long long)idata);
849  else
850  debug("[ sgi_ust: unimplemented read from address"
851  " 0x%llx ]\n", (long long)relative_addr);
852  }
853 
854  if (writeflag == MEM_READ)
855  memory_writemax64(cpu, data, len, odata);
856 
857  return 1;
858 }
859 
860 
861 /*
862  * dev_sgi_ust_init():
863  */
864 void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
865 {
866  struct sgi_ust_data *d;
867 
868  CHECK_ALLOCATION(d = (struct sgi_ust_data *) malloc(sizeof(struct sgi_ust_data)));
869  memset(d, 0, sizeof(struct sgi_ust_data));
870 
871  memory_device_register(mem, "sgi_ust", baseaddr,
873  DM_DEFAULT, NULL);
874 }
875 
876 
crime_data::use_fb
int use_fb
Definition: dev_sgi_ip32.cc:84
CRIME_SOFTINT
#define CRIME_SOFTINT
Definition: crimereg.h:122
data
u_short data
Definition: siireg.h:79
dev_crime_init
void dev_crime_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path, int use_fb)
Definition: dev_sgi_ip32.cc:404
mace_data::irq_misc
struct interrupt irq_misc
Definition: dev_sgi_ip32.cc:451
DEV_CRIME_LENGTH
#define DEV_CRIME_LENGTH
Definition: dev_sgi_ip32.cc:75
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
mace_data::reg
unsigned char reg[DEV_MACE_LENGTH]
Definition: dev_sgi_ip32.cc:449
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
cpu::running
uint8_t running
Definition: cpu.h:353
interrupt::interrupt_deassert
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
DEVICE_ACCESS
DEVICE_ACCESS(crime)
Definition: dev_sgi_ip32.cc:187
DEV_SGI_UST_LENGTH
#define DEV_SGI_UST_LENGTH
Definition: devices.h:464
memory
Definition: memory.h:75
debug
#define debug
Definition: dev_adb.cc:57
MACE_ISA_INT_MASK
#define MACE_ISA_INT_MASK
Definition: sgi_macereg.h:154
machine::cpus
struct cpu ** cpus
Definition: machine.h:140
bus_pci_setaddr
void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data, int bus, int device, int function, int reg)
Definition: bus_pci.cc:196
machine::physical_ram_in_mb
int physical_ram_in_mb
Definition: machine.h:147
CRIME_INT_PERIPH_SERIAL
#define CRIME_INT_PERIPH_SERIAL
Definition: crimereg.h:114
devinit::addr
uint64_t addr
Definition: device.h:46
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
mips32_pc_to_pointers
void mips32_pc_to_pointers(struct cpu *)
bus_pci_data_access
void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data, uint64_t *data, int len, int writeflag)
Definition: bus_pci.cc:95
DEVINIT
DEVINIT(mace)
Definition: dev_sgi_ip32.cc:640
MEM_READ
#define MEM_READ
Definition: memory.h:116
CRIME_TICKSHIFT
#define CRIME_TICKSHIFT
Definition: dev_sgi_ip32.cc:68
CRIME_CONTROL
#define CRIME_CONTROL
Definition: crimereg.h:52
MACE_ISA_RINGBASE
#define MACE_ISA_RINGBASE
Definition: sgi_macereg.h:138
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
interrupt::extra
void * extra
Definition: interrupt.h:59
devinit::machine
struct machine * machine
Definition: device.h:41
crime_data::prev_asserted
int prev_asserted
Definition: dev_sgi_ip32.cc:82
CRIME_TIME
#define CRIME_TIME
Definition: crimereg.h:134
console.h
cpu::mips
struct mips_cpu mips
Definition: cpu.h:443
device.h
CRIME_CONTROL_DOG_ENABLE
#define CRIME_CONTROL_DOG_ENABLE
Definition: crimereg.h:57
bus_pci_decompose_1
void bus_pci_decompose_1(uint32_t t, int *bus, int *dev, int *func, int *reg)
Definition: bus_pci.cc:76
bus_pci_init
struct pci_data * bus_pci_init(struct machine *machine, const char *irq_path, uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset, uint64_t pci_portbase, uint64_t pci_membase, const char *pci_irqbase, uint64_t isa_portbase, uint64_t isa_membase, const char *isa_irqbase)
Definition: bus_pci.cc:355
crime_data::irq
struct interrupt irq
Definition: dev_sgi_ip32.cc:81
crime_interrupt_assert
void crime_interrupt_assert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:124
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
crime_interrupt_deassert
void crime_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:131
CRIME_INTMASK
#define CRIME_INTMASK
Definition: crimereg.h:121
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
crime_data::last_microseconds
uint64_t last_microseconds
Definition: dev_sgi_ip32.cc:79
devinit::interrupt_path
char * interrupt_path
Definition: device.h:50
sgi_ust_data::reg
uint64_t reg[DEV_SGI_UST_LENGTH/sizeof(uint64_t)]
Definition: dev_sgi_ip32.cc:821
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
CRIME_REV
#define CRIME_REV
Definition: crimereg.h:42
misc.h
mace_interrupt_reassert
void mace_interrupt_reassert(struct mace_data *d)
Definition: dev_sgi_ip32.cc:457
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
CRIME_HARDINT
#define CRIME_HARDINT
Definition: crimereg.h:123
cpu::cd
union cpu::@1 cd
device_add
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
machine.h
machine
Definition: machine.h:97
dev_sgi_ust_access
int dev_sgi_ust_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
CRIME_CONTROL_HARD_RESET
#define CRIME_CONTROL_HARD_RESET
Definition: crimereg.h:55
devinit::name
char * name
Definition: device.h:43
emul.h
mace_interrupt_assert
void mace_interrupt_assert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:503
devinit
Definition: device.h:40
cpu::is_32bit
uint8_t is_32bit
Definition: cpu.h:350
mace_data::irq_periph
struct interrupt irq_periph
Definition: dev_sgi_ip32.cc:450
cpu.h
MACE_ISA_INT_STATUS
#define MACE_ISA_INT_STATUS
Definition: sgi_macereg.h:153
DEV_MACEPCI_LENGTH
#define DEV_MACEPCI_LENGTH
Definition: devices.h:452
machine::memory
struct memory * memory
Definition: machine.h:126
bus_pci.h
crime_data::reg
uint64_t reg[DEV_CRIME_LENGTH/sizeof(uint64_t)]
Definition: dev_sgi_ip32.cc:77
cpu::machine
struct machine * machine
Definition: cpu.h:328
mips_pc_to_pointers
void mips_pc_to_pointers(struct cpu *)
devinit::return_ptr
void * return_ptr
Definition: device.h:56
macepci_data
Definition: dev_sgi_ip32.cc:71
MACE_ISA_FLASH_NIC_REG
#define MACE_ISA_FLASH_NIC_REG
Definition: sgi_macereg.h:142
MACE_ISA_LED_GREEN
#define MACE_ISA_LED_GREEN
Definition: sgi_macereg.h:148
crime_interrupt_reassert
void crime_interrupt_reassert(struct crime_data *d)
Definition: dev_sgi_ip32.cc:92
macepci_data::pci_data
struct pci_data * pci_data
Definition: dev_sgi_ip32.cc:72
dev_macepci_init
struct pci_data * dev_macepci_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path)
Definition: dev_sgi_ip32.cc:789
CRIME_CONTROL_ENDIANESS
#define CRIME_CONTROL_ENDIANESS
Definition: crimereg.h:58
MIPS_GPR_RA
#define MIPS_GPR_RA
Definition: MIPS_CPUComponent.h:104
sgi_macereg.h
mips_cpu::gpr
uint64_t gpr[N_MIPS_GPRS]
Definition: cpu_mips.h:209
CRIME_MEM_BANK_CTRL0
#define CRIME_MEM_BANK_CTRL0
Definition: crimereg.h:141
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
mace_data::prev_assert_misc
int prev_assert_misc
Definition: dev_sgi_ip32.cc:453
interrupt::line
uint32_t line
Definition: interrupt.h:51
DEVICE_TICK
DEVICE_TICK(crime)
Definition: dev_sgi_ip32.cc:178
interrupt::interrupt_assert
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
dev_macepci_access
int dev_macepci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
interrupt_handler_register
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
interrupt::name
char * name
Definition: interrupt.h:66
interrupt
Definition: interrupt.h:36
MACE_ISA_PWD_CLEAR
#define MACE_ISA_PWD_CLEAR
Definition: sgi_macereg.h:144
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
mace_interrupt_deassert
void mace_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:515
devices.h
dev_sgi_ust_init
void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
Definition: dev_sgi_ip32.cc:864
cpu
Definition: cpu.h:326
CRIME_INTSTAT
#define CRIME_INTSTAT
Definition: crimereg.h:86
net.h
sgi_ust_data
Definition: dev_sgi_ip32.cc:820
CRIME_INT_PERIPH_MISC
#define CRIME_INT_PERIPH_MISC
Definition: crimereg.h:113
cpu::pc
uint64_t pc
Definition: cpu.h:383
DEV_MACE_LENGTH
#define DEV_MACE_LENGTH
Definition: dev_sgi_ip32.cc:447
mace_data
Definition: dev_sgi_ip32.cc:448
memory.h
mace_data::prev_assert_periph
int prev_assert_periph
Definition: dev_sgi_ip32.cc:452
crimereg.h
crime_update_crime_time
void crime_update_crime_time(struct crime_data *d)
Definition: dev_sgi_ip32.cc:140
MACE_ISA_LED_RED
#define MACE_ISA_LED_RED
Definition: sgi_macereg.h:147
crime_data
Definition: dev_sgi_ip32.cc:76
CRIME_DOG
#define CRIME_DOG
Definition: crimereg.h:132
machine::ncpus
int ncpus
Definition: machine.h:139
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17