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-2009 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, mec, ust, mte)
29  *
30  * o) CRIME
31  * o) MACE
32  * o) MACE PCI bus
33  * o) mec (ethernet)
34  * o) ust (unknown device)
35  * o) mte (memory transfer engine? details unknown)
36  */
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "bus_pci.h"
43 #include "console.h"
44 #include "cpu.h"
45 #include "device.h"
46 #include "devices.h"
47 #include "emul.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51 #include "net.h"
52 
53 #include "thirdparty/crimereg.h"
54 #include "thirdparty/if_mecreg.h"
55 #include "thirdparty/sgi_macereg.h"
56 
57 
58 #define CRIME_TICKSHIFT 14
59 #define CRIME_SPEED_MUL_FACTOR 1
60 #define CRIME_SPEED_DIV_FACTOR 1
61 
62 struct macepci_data {
63  struct pci_data *pci_data;
64  uint32_t reg[DEV_MACEPCI_LENGTH / 4];
65 };
66 
67 #define DEV_CRIME_LENGTH 0x1000
68 struct crime_data {
69  unsigned char reg[DEV_CRIME_LENGTH];
70  struct interrupt irq;
71  int use_fb;
72 };
73 
74 
75 /*
76  * crime_interrupt_assert():
77  * crime_interrupt_deassert():
78  */
80 {
81  struct crime_data *d = (struct crime_data *) interrupt->extra;
82  uint32_t line = interrupt->line, asserted;
83 
84  d->reg[CRIME_INTSTAT + 4] |= ((line >> 24) & 255);
85  d->reg[CRIME_INTSTAT + 5] |= ((line >> 16) & 255);
86  d->reg[CRIME_INTSTAT + 6] |= ((line >> 8) & 255);
87  d->reg[CRIME_INTSTAT + 7] |= (line & 255);
88 
89  asserted =
90  (d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) |
91  (d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) |
92  (d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) |
93  (d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]);
94 
95  if (asserted)
97 }
99 {
100  struct crime_data *d = (struct crime_data *) interrupt->extra;
101  uint32_t line = interrupt->line, asserted;
102 
103  d->reg[CRIME_INTSTAT + 4] &= ~((line >> 24) & 255);
104  d->reg[CRIME_INTSTAT + 5] &= ~((line >> 16) & 255);
105  d->reg[CRIME_INTSTAT + 6] &= ~((line >> 8) & 255);
106  d->reg[CRIME_INTSTAT + 7] &= ~(line & 255);
107 
108  asserted =
109  (d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) |
110  (d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) |
111  (d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) |
112  (d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]);
113 
114  if (!asserted)
116 }
117 
118 
119 /*
120  * dev_crime_tick():
121  *
122  * This function simply updates CRIME_TIME each tick.
123  *
124  * The names DIV and MUL may be a bit confusing. Increasing the
125  * MUL factor will result in an OS running on the emulated machine
126  * detecting a faster CPU. Increasing the DIV factor will result
127  * in a slower detected CPU.
128  *
129  * A R10000 is detected as running at
130  * CRIME_SPEED_FACTOR * 66 MHz. (TODO: this is not correct anymore)
131  */
133 {
134  int j, carry, old, new_, add_byte;
135  uint64_t what_to_add = (1<<CRIME_TICKSHIFT)
137  struct crime_data *d = (struct crime_data *) extra;
138 
139  j = 0;
140  carry = 0;
141  while (j < 8) {
142  old = d->reg[CRIME_TIME + 7 - j];
143  add_byte = what_to_add >> ((int64_t)j * 8);
144  add_byte &= 255;
145  new_ = old + add_byte + carry;
146  d->reg[CRIME_TIME + 7 - j] = new_ & 255;
147  if (new_ >= 256)
148  carry = 1;
149  else
150  carry = 0;
151  j++;
152  }
153 }
154 
155 
157 {
158  struct crime_data *d = (struct crime_data *) extra;
159  uint64_t idata = 0;
160  size_t i;
161 
162  if (writeflag == MEM_WRITE)
163  idata = memory_readmax64(cpu, data, len);
164 
165  /*
166  * Set crime version/revision:
167  *
168  * This might not be the most elegant or correct solution, but it
169  * seems that the IP32 PROM likes 0x11 for machines without graphics,
170  * and 0xa1 for machines with graphics.
171  *
172  * NetBSD 2.0 complains about "unknown" crime for 0x11, but I guess
173  * that's something one has to live with. (TODO?)
174  */
175  d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00;
176  d->reg[7] = d->use_fb? 0xa1 : 0x11;
177 
178  /*
179  * Amount of memory. Bit 8 of bank control set ==> 128MB instead
180  * of 32MB per bank (?)
181  *
182  * When the bank control registers contain the same value as the
183  * previous one, that bank is not valid. (?)
184  */
185  d->reg[CRM_MEM_BANK_CTRL0 + 6] = 0; /* lowbit set=128MB, clear=32MB */
186  d->reg[CRM_MEM_BANK_CTRL0 + 7] = 0; /* address * 32MB */
187  d->reg[CRM_MEM_BANK_CTRL1 + 6] = 0; /* lowbit set=128MB, clear=32MB */
188  d->reg[CRM_MEM_BANK_CTRL1 + 7] = 1; /* address * 32MB */
189 
190  if (relative_addr >= CRIME_TIME && relative_addr < CRIME_TIME+8) {
191  if (writeflag == MEM_READ)
192  memcpy(data, &d->reg[relative_addr], len);
193  return 1;
194  }
195 
196  if (writeflag == MEM_WRITE)
197  memcpy(&d->reg[relative_addr], data, len);
198  else
199  memcpy(data, &d->reg[relative_addr], len);
200 
201  switch (relative_addr) {
202  case CRIME_CONTROL: /* 0x008 */
203  /* TODO: 64-bit write to CRIME_CONTROL, but some things
204  (such as NetBSD 1.6.2) write to 0x00c! */
205  if (writeflag == MEM_WRITE) {
206  /*
207  * 0x200 = watchdog timer (according to NetBSD)
208  * 0x800 = "reboot" used by the IP32 PROM
209  */
210  if (idata & 0x200) {
211  idata &= ~0x200;
212  }
213  if (idata & 0x800) {
214  int j;
215 
216  /* This is used by the IP32 PROM's
217  "reboot" command: */
218  for (j=0; j<cpu->machine->ncpus; j++)
219  cpu->machine->cpus[j]->running = 0;
220  cpu->machine->
221  exit_without_entering_debugger = 1;
222  idata &= ~0x800;
223  }
224  if (idata != 0)
225  fatal("[ CRIME_CONTROL: unimplemented "
226  "control 0x%016llx ]\n", (long long)idata);
227  }
228  break;
229 
230  case CRIME_INTSTAT: /* 0x010, Current interrupt status */
231  case CRIME_INTSTAT + 4:
232  case CRIME_INTMASK: /* 0x018, Current interrupt mask */
233  case CRIME_INTMASK + 4:
234  if ((d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) |
235  (d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) |
236  (d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) |
237  (d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]) )
238  INTERRUPT_ASSERT(d->irq);
239  else
241  break;
242  case 0x34:
243  /* don't dump debug info for these */
244  break;
245 
246  default:
247  if (writeflag==MEM_READ) {
248  debug("[ crime: read from 0x%x, len=%i:",
249  (int)relative_addr, len);
250  for (i=0; i<len; i++)
251  debug(" %02x", data[i]);
252  debug(" ]\n");
253  } else {
254  debug("[ crime: write to 0x%x:", (int)relative_addr);
255  for (i=0; i<len; i++)
256  debug(" %02x", data[i]);
257  debug(" (len=%i) ]\n", len);
258  }
259  }
260 
261  return 1;
262 }
263 
264 
265 /*
266  * dev_crime_init():
267  */
268 void dev_crime_init(struct machine *machine, struct memory *mem,
269  uint64_t baseaddr, char *irq_path, int use_fb)
270 {
271  struct crime_data *d;
272  char tmpstr[200];
273  int i;
274 
275  CHECK_ALLOCATION(d = (struct crime_data *) malloc(sizeof(struct crime_data)));
276  memset(d, 0, sizeof(struct crime_data));
277 
278  d->use_fb = use_fb;
279 
280  INTERRUPT_CONNECT(irq_path, d->irq);
281 
282  /* Register 32 crime interrupts (hexadecimal names): */
283  for (i=0; i<32; i++) {
284  struct interrupt templ;
285  char name[400];
286  snprintf(name, sizeof(name), "%s.crime.0x%x", irq_path, 1 << i);
287  memset(&templ, 0, sizeof(templ));
288  templ.line = 1 << i;
289  templ.name = name;
290  templ.extra = d;
294  }
295 
296  memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH,
297  dev_crime_access, d, DM_DEFAULT, NULL);
298 
299  snprintf(tmpstr, sizeof(tmpstr), "mace addr=0x1f310000 irq=%s.crime",
300  irq_path);
301  device_add(machine, tmpstr);
302 
303  machine_add_tickfunction(machine, dev_crime_tick, d,
305 }
306 
307 
308 /****************************************************************************/
309 
310 
311 #define DEV_MACE_LENGTH 0x100
312 struct mace_data {
313  unsigned char reg[DEV_MACE_LENGTH];
314  struct interrupt irq_periph;
315  struct interrupt irq_misc;
316 };
317 
318 
319 /*
320  * mace_interrupt_assert():
321  * mace_interrupt_deassert():
322  */
324 {
325  struct mace_data *d = (struct mace_data *) interrupt->extra;
326  uint32_t line = 1 << interrupt->line;
327 
328  d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255);
329  d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255);
330  d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255);
331  d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255);
332 
333  /* High bits = PERIPH */
334  if ((d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4]) |
337 
338  /* Low bits = MISC */
339  if ((d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6]) |
342 }
344 {
345  struct mace_data *d = (struct mace_data *) interrupt->extra;
346  uint32_t line = 1 << interrupt->line;
347 
348  d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255);
349  d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255);
350  d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255);
351  d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255);
352 
353  /* High bits = PERIPH */
354  if (!((d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4]) |
355  (d->reg[MACE_ISA_INT_STATUS+5] & d->reg[MACE_ISA_INT_MASK+5])))
357 
358  /* Low bits = MISC */
359  if (!((d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6]) |
360  (d->reg[MACE_ISA_INT_STATUS+7] & d->reg[MACE_ISA_INT_MASK+7])))
362 }
363 
364 
366 {
367  size_t i;
368  struct mace_data *d = (struct mace_data *) extra;
369 
370  if (writeflag == MEM_WRITE)
371  memcpy(&d->reg[relative_addr], data, len);
372  else
373  memcpy(data, &d->reg[relative_addr], len);
374 
375  switch (relative_addr) {
376 
377  case MACE_ISA_INT_STATUS: /* Current interrupt assertions */
378  case MACE_ISA_INT_STATUS + 4:
379  /* don't dump debug info for these */
380  if (writeflag == MEM_WRITE) {
381  fatal("[ NOTE/TODO: WRITE to mace intr: "
382  "reladdr=0x%x data=", (int)relative_addr);
383  for (i=0; i<len; i++)
384  fatal(" %02x", data[i]);
385  fatal(" (len=%i) ]\n", len);
386  }
387  break;
388  case MACE_ISA_INT_MASK: /* Current interrupt mask */
389  case MACE_ISA_INT_MASK + 4:
390  if ((d->reg[MACE_ISA_INT_STATUS+4]&d->reg[MACE_ISA_INT_MASK+4])|
393  else
395 
396  if ((d->reg[MACE_ISA_INT_STATUS+6]&d->reg[MACE_ISA_INT_MASK+6])|
399  else
401  break;
402 
403  default:
404  if (writeflag == MEM_READ) {
405  debug("[ mace: read from 0x%x:", (int)relative_addr);
406  for (i=0; i<len; i++)
407  debug(" %02x", data[i]);
408  debug(" (len=%i) ]\n", len);
409  } else {
410  debug("[ mace: write to 0x%x:", (int)relative_addr);
411  for (i=0; i<len; i++)
412  debug(" %02x", data[i]);
413  debug(" (len=%i) ]\n", len);
414  }
415  }
416 
417  return 1;
418 }
419 
420 
421 DEVINIT(mace)
422 {
423  struct mace_data *d;
424  char tmpstr[300];
425  int i;
426 
427  CHECK_ALLOCATION(d = (struct mace_data *) malloc(sizeof(struct mace_data)));
428  memset(d, 0, sizeof(struct mace_data));
429 
430  snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
432  INTERRUPT_CONNECT(tmpstr, d->irq_periph);
433 
434  snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x",
436  INTERRUPT_CONNECT(tmpstr, d->irq_misc);
437 
438  /*
439  * For Mace interrupts MACE_PERIPH_SERIAL and MACE_PERIPH_MISC,
440  * register 32 mace interrupts each.
441  */
442  /* Register 32 crime interrupts (hexadecimal names): */
443  for (i=0; i<32; i++) {
444  struct interrupt templ;
445  char name[400];
446  snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
448  memset(&templ, 0, sizeof(templ));
449  templ.line = i;
450  templ.name = name;
451  templ.extra = d;
455 
456  snprintf(name, sizeof(name), "%s.0x%x.mace.%i",
458  memset(&templ, 0, sizeof(templ));
459  templ.line = i;
460  templ.name = name;
461  templ.extra = d;
465  }
466 
468  devinit->addr, DEV_MACE_LENGTH, dev_mace_access, d,
469  DM_DEFAULT, NULL);
470 
471  devinit->return_ptr = d;
472  return 1;
473 }
474 
475 
476 /****************************************************************************/
477 
478 
480 {
481  struct macepci_data *d = (struct macepci_data *) extra;
482  uint64_t idata = 0, odata=0;
483  int regnr, res = 1, bus, dev, func, pcireg;
484 
485  if (writeflag == MEM_WRITE)
486  idata = memory_readmax64(cpu, data, len);
487 
488  regnr = relative_addr / sizeof(uint32_t);
489 
490  /* Read from/write to the macepci: */
491  switch (relative_addr) {
492 
493  case 0x00: /* Error address */
494  if (writeflag == MEM_WRITE) {
495  } else {
496  odata = 0;
497  }
498  break;
499 
500  case 0x04: /* Error flags */
501  if (writeflag == MEM_WRITE) {
502  } else {
503  odata = 0x06;
504  }
505  break;
506 
507  case 0x0c: /* Revision number */
508  if (writeflag == MEM_WRITE) {
509  } else {
510  odata = 0x01;
511  }
512  break;
513 
514  case 0xcf8: /* PCI ADDR */
515  bus_pci_decompose_1(idata, &bus, &dev, &func, &pcireg);
516  bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, pcireg);
517  break;
518 
519  case 0xcfc: /* PCI DATA */
520  bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
521  &odata : &idata, len, writeflag);
522  break;
523 
524  default:
525  if (writeflag == MEM_WRITE) {
526  debug("[ macepci: unimplemented write to address "
527  "0x%x, data=0x%02x ]\n",
528  (int)relative_addr, (int)idata);
529  } else {
530  debug("[ macepci: unimplemented read from address "
531  "0x%x ]\n", (int)relative_addr);
532  }
533  }
534 
535  if (writeflag == MEM_READ)
536  memory_writemax64(cpu, data, len, odata);
537 
538  return res;
539 }
540 
541 
542 /*
543  * dev_macepci_init():
544  */
546  struct memory *mem, uint64_t baseaddr, char *irq_path)
547 {
548  struct macepci_data *d;
549 
550  CHECK_ALLOCATION(d = (struct macepci_data *) malloc(sizeof(struct macepci_data)));
551  memset(d, 0, sizeof(struct macepci_data));
552 
553  /* TODO: PCI vs ISA interrupt? */
554 
555  d->pci_data = bus_pci_init(machine,
556  irq_path,
557  0,
558  0,
559  0,
560  0,
561  "TODO: pci irq path",
562  0x18000003, /* ISA portbase */
563  0,
564  irq_path);
565 
566  memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH,
567  dev_macepci_access, (void *)d, DM_DEFAULT, NULL);
568 
569  return d->pci_data;
570 }
571 
572 
573 /****************************************************************************/
574 
575 
576 /*
577  * SGI "mec" ethernet. Used in SGI-IP32.
578  *
579  * Study http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/sgi/dev/if_mec.c
580  * and/or NetBSD. TODO:
581  *
582  * x) tx and rx interrupts/ring/slot stuff
583  */
584 
585 #define MEC_TICK_SHIFT 14
586 
587 #define MAX_TX_PACKET_LEN 1700
588 #define N_RX_ADDRESSES 16
589 
590 struct sgi_mec_data {
591  uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)];
592 
593  struct interrupt irq;
594  unsigned char macaddr[6];
595 
596  unsigned char cur_tx_packet[MAX_TX_PACKET_LEN];
598 
599  unsigned char *cur_rx_packet;
601 
602  uint64_t rx_addr[N_RX_ADDRESSES];
605 };
606 
607 
608 /*
609  * mec_reset():
610  */
611 static void mec_reset(struct sgi_mec_data *d)
612 {
613  if (d->cur_rx_packet != NULL)
614  free(d->cur_rx_packet);
615 
616  memset(d->reg, 0, sizeof(d->reg));
617 }
618 
619 
620 /*
621  * mec_control_write():
622  */
623 static void mec_control_write(struct cpu *cpu, struct sgi_mec_data *d,
624  uint64_t x)
625 {
626  if (x & MEC_MAC_CORE_RESET) {
627  debug("[ sgi_mec: CORE RESET ]\n");
628  mec_reset(d);
629  }
630 }
631 
632 
633 /*
634  * mec_try_rx():
635  */
636 static int mec_try_rx(struct cpu *cpu, struct sgi_mec_data *d)
637 {
638  uint64_t base;
639  unsigned char data[8];
640  int i, res, retval = 0;
641 
642  base = d->rx_addr[d->cur_rx_addr_index];
643  if (base & 0xfff)
644  fatal("[ mec_try_rx(): WARNING! lowest bits of base are "
645  "non-zero (0x%3x). TODO ]\n", (int)(base & 0xfff));
646  base &= 0xfffff000ULL;
647  if (base == 0)
648  goto skip;
649 
650  /* printf("rx base = 0x%016llx\n", (long long)base); */
651 
652  /* Read an rx descriptor from memory: */
653  res = cpu->memory_rw(cpu, cpu->mem, base,
654  &data[0], sizeof(data), MEM_READ, PHYSICAL);
655  if (!res)
656  return 0;
657 
658 #if 0
659  printf("{ mec: rxdesc %i: ", d->cur_rx_addr_index);
660  for (i=0; i<sizeof(data); i++) {
661  if ((i & 3) == 0)
662  printf(" ");
663  printf("%02x", data[i]);
664  }
665  printf(" }\n");
666 #endif
667 
668  /* Is this descriptor already in use? */
669  if (data[0] & 0x80) {
670  /* printf("INTERRUPT for base = 0x%x\n", (int)base); */
671  goto skip_and_advance;
672  }
673 
674  if (d->cur_rx_packet == NULL &&
676  net_ethernet_rx(cpu->machine->emul->net, d,
678 
679  if (d->cur_rx_packet == NULL)
680  goto skip;
681 
682  /* Copy the packet data: */
683  /* printf("RX: "); */
684  for (i=0; i<d->cur_rx_packet_len; i++) {
685  res = cpu->memory_rw(cpu, cpu->mem, base + 32 + i + 2,
686  d->cur_rx_packet + i, 1, MEM_WRITE, PHYSICAL);
687  /* printf(" %02x", d->cur_rx_packet[i]); */
688  }
689  /* printf("\n"); */
690 
691 #if 0
692  printf("RX: %i bytes, index %i, base = 0x%x\n",
693  d->cur_rx_packet_len, d->cur_rx_addr_index, (int)base);
694 #endif
695 
696  /* 4 bytes of CRC at the end. Hm. TODO */
697  d->cur_rx_packet_len += 4;
698 
699  memset(data, 0, sizeof(data));
700  data[6] = (d->cur_rx_packet_len >> 8) & 255;
701  data[7] = d->cur_rx_packet_len & 255;
702  /* TODO: lots of bits :-) */
703  data[4] = 0x04; /* match MAC */
704  data[0] = 0x80; /* 0x80 = received. */
705  res = cpu->memory_rw(cpu, cpu->mem, base,
706  &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
707 
708  /* Free the packet from memory: */
709  free(d->cur_rx_packet);
710  d->cur_rx_packet = NULL;
711 
712  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_RX_THRESHOLD;
713 skip_and_advance:
714  d->cur_rx_addr_index ++;
716  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &= ~MEC_INT_RX_MCL_FIFO_ALIAS;
717  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
718  (d->cur_rx_addr_index & 0x1f) << 8;
719  retval = 1;
720 
721 skip:
722  return retval;
723 }
724 
725 
726 /*
727  * mec_try_tx():
728  */
729 static int mec_try_tx(struct cpu *cpu, struct sgi_mec_data *d)
730 {
731  uint64_t base, addr, dma_base;
732  int tx_ring_ptr, ringread, ringwrite, res, i, j;
733  unsigned char data[32];
734  int len, start_offset, dma_ptr_nr, dma_len;
735 
736  base = d->reg[MEC_TX_RING_BASE / sizeof(uint64_t)];
737  tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
738 
739  if (base == 0)
740  return 0;
741 
742  /* printf("base = 0x%016llx\n", base); */
743 
744  ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
745  ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
746  ringread >>= 16;
747  /* All done? Then abort. */
748  if (ringread == ringwrite)
749  return 0;
750 
751  tx_ring_ptr &= MEC_TX_RING_READ_PTR;
752  tx_ring_ptr >>= 16;
753 
754  /* Each tx descriptor (+ buffer) is 128 bytes: */
755  addr = base + tx_ring_ptr*128;
756  res = cpu->memory_rw(cpu, cpu->mem, addr,
757  &data[0], sizeof(data), MEM_READ, PHYSICAL);
758  if (!res)
759  return 0;
760 
761  /* Is this packet transmitted already? */
762  if (data[0] & 0x80) {
763  fatal("[ mec_try_tx: tx_ring_ptr = %i, already"
764  " transmitted? ]\n", tx_ring_ptr);
765  goto advance_tx;
766  }
767 
768  len = data[6] * 256 + data[7];
769  start_offset = data[5] & 0x7f;
770 
771  /* Is this packet empty? Then don't transmit. */
772  if (len == 0)
773  return 0;
774 
775  /* Hm. Is len one too little? TODO */
776  len ++;
777 
778 #if 0
779  printf("{ mec: txdesc %i: ", tx_ring_ptr);
780  for (i=0; i<sizeof(data); i++) {
781  if ((i & 3) == 0)
782  printf(" ");
783  printf("%02x", data[i]);
784  }
785  printf(" }\n");
786 #endif
787  dma_ptr_nr = 0;
788 
789  j = 0;
790  d->cur_tx_packet_len = len;
791 
792  for (i=start_offset; i<start_offset+len; i++) {
793  unsigned char ch;
794 
795  if ((i & 0x7f) == 0x00)
796  break;
797 
798  res = cpu->memory_rw(cpu, cpu->mem, addr + i,
799  &ch, sizeof(ch), MEM_READ, PHYSICAL);
800  /* printf(" %02x", ch); */
801 
802  d->cur_tx_packet[j++] = ch;
803  if (j >= MAX_TX_PACKET_LEN) {
804  fatal("[ mec_try_tx: packet too large? ]\n");
805  break;
806  }
807  }
808  /* printf("\n"); */
809 
810  if (j < len) {
811  /* Continue with DMA: */
812  for (;;) {
813  dma_ptr_nr ++;
814  if (dma_ptr_nr >= 4)
815  break;
816  if (!(data[4] & (0x01 << dma_ptr_nr)))
817  break;
818  dma_base = (data[dma_ptr_nr * 8 + 4] << 24)
819  + (data[dma_ptr_nr * 8 + 5] << 16)
820  + (data[dma_ptr_nr * 8 + 6] << 8)
821  + (data[dma_ptr_nr * 8 + 7]);
822  dma_base &= 0xfffffff8ULL;
823  dma_len = (data[dma_ptr_nr * 8 + 2] << 8)
824  + (data[dma_ptr_nr * 8 + 3]) + 1;
825 
826  /* printf("dma_base = %08x, dma_len = %i\n",
827  (int)dma_base, dma_len); */
828 
829  while (dma_len > 0) {
830  unsigned char ch;
831  res = cpu->memory_rw(cpu, cpu->mem, dma_base,
832  &ch, sizeof(ch), MEM_READ, PHYSICAL);
833  /* printf(" %02x", ch); */
834 
835  d->cur_tx_packet[j++] = ch;
836  if (j >= MAX_TX_PACKET_LEN) {
837  fatal("[ mec_try_tx: packet too large?"
838  " ]\n");
839  break;
840  }
841  dma_base ++;
842  dma_len --;
843  }
844  }
845  }
846 
847  if (j < len)
848  fatal("[ mec_try_tx: not enough data? ]\n");
849 
850  net_ethernet_tx(cpu->machine->emul->net, d,
852 
853  /* see openbsd's if_mec.c for details */
854  if (data[4] & 0x01) {
855  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
857  }
858  memset(data, 0, 6); /* last 2 bytes are len */
859  data[0] = 0x80;
860  data[5] = 0x80;
861 
862  res = cpu->memory_rw(cpu, cpu->mem, addr,
863  &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
864 
865  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_EMPTY;
866  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_PACKET_SENT;
867 
868 advance_tx:
869  /* Advance the ring Read ptr. */
870  tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
871  ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
872  ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
873 
874  ringread = (ringread >> 16) + 1;
875  ringread &= 63;
876  ringread <<= 16;
877 
878  d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] =
879  (ringwrite & MEC_TX_RING_WRITE_PTR) |
880  (ringread & MEC_TX_RING_READ_PTR);
881 
882  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
884  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
885  (d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] &
887 
888  return 1;
889 }
890 
891 
892 DEVICE_TICK(sgi_mec)
893 {
894  struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
895  int n = 0;
896 
897  while (mec_try_tx(cpu, d))
898  ;
899 
900  while (mec_try_rx(cpu, d) && n < 16)
901  n++;
902 
903  /* Interrupts: (TODO: only when enabled) */
904  if (d->reg[MEC_INT_STATUS / sizeof(uint64_t)] & MEC_INT_STATUS_MASK) {
905 #if 0
906  printf("[%02x]", (int)(d->reg[MEC_INT_STATUS /
907  sizeof(uint64_t)] & MEC_INT_STATUS_MASK));
908  fflush(stdout);
909 #endif
910  INTERRUPT_ASSERT(d->irq);
911  } else
913 }
914 
915 
917 {
918  struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
919  uint64_t idata = 0, odata = 0;
920  int regnr;
921 
922  if (writeflag == MEM_WRITE)
923  idata = memory_readmax64(cpu, data, len);
924 
925  regnr = relative_addr / sizeof(uint64_t);
926 
927  /* Treat most registers as read/write, by default. */
928  if (writeflag == MEM_WRITE) {
929  switch (relative_addr) {
930  case MEC_INT_STATUS: /* 0x08 */
931  /* Clear bits on write: (This is just a guess) */
932  d->reg[regnr] = (d->reg[regnr] & ~0xff)
933  | ((d->reg[regnr] & ~idata) & 0xff);
934  break;
935  case MEC_TX_RING_PTR: /* 0x30 */
936  idata &= MEC_TX_RING_WRITE_PTR;
937  d->reg[regnr] = (d->reg[regnr] &
938  ~MEC_TX_RING_WRITE_PTR) | idata;
939  /* TODO */
940  break;
941  default:
942  d->reg[regnr] = idata;
943  }
944  } else
945  odata = d->reg[regnr];
946 
947  switch (relative_addr) {
948  case MEC_MAC_CONTROL: /* 0x00 */
949  if (writeflag)
950  mec_control_write(cpu, d, idata);
951  else {
952  /* Fake "revision 1": */
953  odata &= ~MEC_MAC_REVISION;
954  odata |= 1 << MEC_MAC_REVISION_SHIFT;
955  }
956  break;
957  case MEC_INT_STATUS: /* 0x08 */
958  if (writeflag)
959  debug("[ sgi_mec: write to MEC_INT_STATUS: "
960  "0x%016llx ]\n", (long long)idata);
961  break;
962  case MEC_DMA_CONTROL: /* 0x10 */
963  if (writeflag) {
964  debug("[ sgi_mec: write to MEC_DMA_CONTROL: "
965  "0x%016llx ]\n", (long long)idata);
966  if (!(idata & MEC_DMA_TX_INT_ENABLE)) {
967  /* This should apparently stop the
968  TX Empty interrupt. */
969  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
971  }
972  }
973  break;
974  case MEC_TX_ALIAS: /* 0x20 */
975  if (writeflag) {
976  debug("[ sgi_mec: write to MEC_TX_ALIAS: "
977  "0x%016llx ]\n", (long long)idata);
978  } else {
979  debug("[ sgi_mec: read from MEC_TX_ALIAS: "
980  "0x%016llx ]\n", (long long)idata);
981  odata = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
982  }
983  break;
984  case MEC_RX_ALIAS: /* 0x28 */
985  if (writeflag)
986  debug("[ sgi_mec: write to MEC_RX_ALIAS: "
987  "0x%016llx ]\n", (long long)idata);
988  break;
989  case MEC_TX_RING_PTR: /* 0x30 */
990  if (writeflag)
991  debug("[ sgi_mec: write to MEC_TX_RING_PTR: "
992  "0x%016llx ]\n", (long long)idata);
993  break;
994  case MEC_PHY_DATA: /* 0x64 */
995  if (writeflag)
996  fatal("[ sgi_mec: write to MEC_PHY_DATA: "
997  "0x%016llx ]\n", (long long)idata);
998  else
999  odata = 0; /* ? */
1000  break;
1001  case MEC_PHY_ADDRESS: /* 0x6c */
1002  if (writeflag)
1003  debug("[ sgi_mec: write to MEC_PHY_ADDRESS: "
1004  "0x%016llx ]\n", (long long)idata);
1005  break;
1006  case MEC_PHY_READ_INITIATE: /* 0x70 */
1007  if (writeflag)
1008  debug("[ sgi_mec: write to MEC_PHY_READ_INITIATE: "
1009  "0x%016llx ]\n", (long long)idata);
1010  break;
1011  case 0x74:
1012  if (writeflag)
1013  debug("[ sgi_mec: write to 0x74: 0x%016llx ]\n",
1014  (long long)idata);
1015  else
1016  debug("[ sgi_mec: read from 0x74 ]\n");
1017  break;
1018  case MEC_STATION: /* 0xa0 */
1019  if (writeflag)
1020  debug("[ sgi_mec: setting the MAC address to "
1021  "%02x:%02x:%02x:%02x:%02x:%02x ]\n",
1022  (idata >> 40) & 255, (idata >> 32) & 255,
1023  (idata >> 24) & 255, (idata >> 16) & 255,
1024  (idata >> 8) & 255, (idata >> 0) & 255);
1025  break;
1026  case MEC_STATION_ALT: /* 0xa8 */
1027  if (writeflag)
1028  debug("[ sgi_mec: setting the ALTERNATIVE MAC address"
1029  " to %02x:%02x:%02x:%02x:%02x:%02x ]\n",
1030  (idata >> 40) & 255, (idata >> 32) & 255,
1031  (idata >> 24) & 255, (idata >> 16) & 255,
1032  (idata >> 8) & 255, (idata >> 0) & 255);
1033  break;
1034  case MEC_MULTICAST: /* 0xb0 */
1035  if (writeflag)
1036  debug("[ sgi_mec: write to MEC_MULTICAST: "
1037  "0x%016llx ]\n", (long long)idata);
1038  break;
1039  case MEC_TX_RING_BASE: /* 0xb8 */
1040  if (writeflag)
1041  debug("[ sgi_mec: write to MEC_TX_RING_BASE: "
1042  "0x%016llx ]\n", (long long)idata);
1043  break;
1044  case MEC_MCL_RX_FIFO: /* 0x100 */
1045  if (writeflag) {
1046  debug("[ sgi_mec: write to MEC_MCL_RX_FIFO: 0x"
1047  "%016llx ]\n", (long long)idata);
1048  d->rx_addr[d->cur_rx_addr_index_write] = idata;
1051  }
1052  break;
1053  default:
1054  if (writeflag == MEM_WRITE)
1055  fatal("[ sgi_mec: unimplemented write to address"
1056  " 0x%llx, data=0x%016llx ]\n",
1057  (long long)relative_addr, (long long)idata);
1058  else
1059  fatal("[ sgi_mec: unimplemented read from address"
1060  " 0x%llx ]\n", (long long)relative_addr);
1061  }
1062 
1063  if (writeflag == MEM_READ)
1064  memory_writemax64(cpu, data, len, odata);
1065 
1066  dev_sgi_mec_tick(cpu, extra);
1067 
1068  return 1;
1069 }
1070 
1071 
1072 /*
1073  * dev_sgi_mec_init():
1074  */
1075 void dev_sgi_mec_init(struct machine *machine, struct memory *mem,
1076  uint64_t baseaddr, char *irq_path, unsigned char *macaddr)
1077 {
1078  char *name2;
1079  size_t nlen = 55;
1080  struct sgi_mec_data *d;
1081 
1082  CHECK_ALLOCATION(d = (struct sgi_mec_data *) malloc(sizeof(struct sgi_mec_data)));
1083  memset(d, 0, sizeof(struct sgi_mec_data));
1084 
1085  INTERRUPT_CONNECT(irq_path, d->irq);
1086  memcpy(d->macaddr, macaddr, 6);
1087  mec_reset(d);
1088 
1089  CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
1090  snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]",
1091  d->macaddr[0], d->macaddr[1], d->macaddr[2],
1092  d->macaddr[3], d->macaddr[4], d->macaddr[5]);
1093 
1094  memory_device_register(mem, name2, baseaddr,
1096  DM_DEFAULT, NULL);
1097 
1098  machine_add_tickfunction(machine, dev_sgi_mec_tick, d,
1099  MEC_TICK_SHIFT);
1100 
1101  net_add_nic(machine->emul->net, d, macaddr);
1102 }
1103 
1104 
1105 /****************************************************************************/
1106 
1107 
1109  uint64_t reg[DEV_SGI_UST_LENGTH / sizeof(uint64_t)];
1110 };
1111 
1112 
1114 {
1115  struct sgi_ust_data *d = (struct sgi_ust_data *) extra;
1116  uint64_t idata = 0, odata = 0;
1117  int regnr;
1118 
1119  idata = memory_readmax64(cpu, data, len);
1120  regnr = relative_addr / sizeof(uint64_t);
1121 
1122  /* Treat all registers as read/write, by default. */
1123  if (writeflag == MEM_WRITE)
1124  d->reg[regnr] = idata;
1125  else
1126  odata = d->reg[regnr];
1127 
1128  switch (relative_addr) {
1129  case 0:
1130  d->reg[regnr] += 0x2710; // HUH?
1131  break;
1132  default:
1133  if (writeflag == MEM_WRITE)
1134  debug("[ sgi_ust: unimplemented write to "
1135  "address 0x%llx, data=0x%016llx ]\n",
1136  (long long)relative_addr, (long long)idata);
1137  else
1138  debug("[ sgi_ust: unimplemented read from address"
1139  " 0x%llx ]\n", (long long)relative_addr);
1140  }
1141 
1142  if (writeflag == MEM_READ)
1143  memory_writemax64(cpu, data, len, odata);
1144 
1145  return 1;
1146 }
1147 
1148 
1149 /*
1150  * dev_sgi_ust_init():
1151  */
1152 void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
1153 {
1154  struct sgi_ust_data *d;
1155 
1156  CHECK_ALLOCATION(d = (struct sgi_ust_data *) malloc(sizeof(struct sgi_ust_data)));
1157  memset(d, 0, sizeof(struct sgi_ust_data));
1158 
1159  memory_device_register(mem, "sgi_ust", baseaddr,
1161  DM_DEFAULT, NULL);
1162 }
1163 
1164 
1165 /****************************************************************************/
1166 
1167 
1168 /*
1169  * SGI "mte". This device seems to be an accelerator for copying/clearing
1170  * memory. Used by (at least) the SGI O2 PROM.
1171  *
1172  * Actually, it seems to be used for graphics output as well. (?)
1173  * The O2's PROM uses it to output graphics.
1174  */
1175 /* #define debug fatal */
1176 /* #define MTE_DEBUG */
1177 #define ZERO_CHUNK_LEN 4096
1178 
1180  uint32_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)];
1181 };
1182 
1183 
1185 {
1186  struct sgi_mte_data *d = (struct sgi_mte_data *) extra;
1187  uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len;
1188  unsigned char zerobuf[ZERO_CHUNK_LEN];
1189  uint64_t idata = 0, odata = 0;
1190  int regnr;
1191 
1192  idata = memory_readmax64(cpu, data, len);
1193  regnr = relative_addr / sizeof(uint32_t);
1194 
1195  /*
1196  * Treat all registers as read/write, by default. Sometimes these
1197  * are accessed as 32-bit words, sometimes as 64-bit words.
1198  */
1199  if (len != 4) {
1200  if (writeflag == MEM_WRITE) {
1201  d->reg[regnr] = idata >> 32;
1202  d->reg[regnr+1] = idata;
1203  } else
1204  odata = ((uint64_t)d->reg[regnr] << 32) +
1205  d->reg[regnr+1];
1206  }
1207 
1208  if (writeflag == MEM_WRITE)
1209  d->reg[regnr] = idata;
1210  else
1211  odata = d->reg[regnr];
1212 
1213 #ifdef MTE_DEBUG
1214  if (writeflag == MEM_WRITE && relative_addr >= 0x2000 &&
1215  relative_addr < 0x3000)
1216  fatal("[ MTE: 0x%08x: 0x%016llx ]\n", (int)relative_addr,
1217  (long long)idata);
1218 #endif
1219 
1220  /*
1221  * I've not found any docs about this 'mte' device at all, so this is
1222  * just a guess. The mte seems to be used for copying and zeroing
1223  * chunks of memory.
1224  *
1225  * write to 0x3030, data=0x00000000003da000 ] <-- first address
1226  * write to 0x3038, data=0x00000000003f9fff ] <-- last address
1227  * write to 0x3018, data=0x0000000000000000 ] <-- what to fill?
1228  * write to 0x3008, data=0x00000000ffffffff ] <-- ?
1229  * write to 0x3800, data=0x0000000000000011 ] <-- operation
1230  * (0x11 = zerofill)
1231  *
1232  * write to 0x1700, data=0x80001ea080001ea1 <-- also containing the
1233  * write to 0x1708, data=0x80001ea280001ea3 address to fill (?)
1234  * write to 0x1710, data=0x80001ea480001ea5
1235  * ...
1236  * write to 0x1770, data=0x80001e9c80001e9d
1237  * write to 0x1778, data=0x80001e9e80001e9f
1238  */
1239  switch (relative_addr) {
1240 
1241  /* No warnings for these: */
1242  case 0x3030:
1243  case 0x3038:
1244  break;
1245 
1246  /* Unknown, but no warning: */
1247  case 0x4000:
1248  case 0x3018:
1249  case 0x3008:
1250  case 0x1700:
1251  case 0x1708:
1252  case 0x1710:
1253  case 0x1718:
1254  case 0x1720:
1255  case 0x1728:
1256  case 0x1730:
1257  case 0x1738:
1258  case 0x1740:
1259  case 0x1748:
1260  case 0x1750:
1261  case 0x1758:
1262  case 0x1760:
1263  case 0x1768:
1264  case 0x1770:
1265  case 0x1778:
1266  break;
1267 
1268  /* Graphics stuff? No warning: */
1269  case 0x2018:
1270  case 0x2060:
1271  case 0x2070:
1272  case 0x2074:
1273  case 0x20c0:
1274  case 0x20c4:
1275  case 0x20d0:
1276  case 0x21b0:
1277  case 0x21b8:
1278  break;
1279 
1280  /* Perform graphics operation: */
1281  case 0x21f8:
1282  {
1283  uint32_t op = d->reg[0x2060 / sizeof(uint32_t)];
1284  uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1285  uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1286  >> 16) & 0xfff;
1287  uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1288  uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1289  >> 16) & 0xfff;
1290  uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1291  uint32_t y;
1292 
1293  op >>= 24;
1294 
1295  switch (op) {
1296  case 1: /* Unknown. Used after drawing bitmaps? */
1297  break;
1298  case 3: /* Fill: */
1299  if (x2 < x1) {
1300  int tmp = x1; x1 = x2; x2 = tmp;
1301  }
1302  if (y2 < y1) {
1303  int tmp = y1; y1 = y2; y2 = tmp;
1304  }
1305  for (y=y1; y<=y2; y++) {
1306  unsigned char buf[1280];
1307  int length = x2-x1+1;
1308  int addr = (x1 + y*1280);
1309  if (length < 1)
1310  length = 1;
1311  memset(buf, color, length);
1312  if (x1 < 1280 && y < 1024)
1313  cpu->memory_rw(cpu, cpu->mem,
1314  0x38000000 + addr, buf,
1315  length, MEM_WRITE,
1317  }
1318  break;
1319 
1320  default:fatal("\n--- MTE OP %i color 0x%02x: %i,%i - "
1321  "%i,%i\n\n", op, color, x1,y1, x2,y2);
1322  }
1323  }
1324  break;
1325 
1326  case 0x29f0:
1327  /* Pixel output: */
1328  {
1329  uint32_t pixeldata = d->reg[0x20c4 / sizeof(uint32_t)];
1330  uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1331  uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1332  >> 16) & 0xfff;
1333  uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1334  uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1335  >> 16) & 0xfff;
1336  uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1337  size_t x, y;
1338 
1339  if (x2 < x1) {
1340  int tmp = x1; x1 = x2; x2 = tmp;
1341  }
1342  if (y2 < y1) {
1343  int tmp = y1; y1 = y2; y2 = tmp;
1344  }
1345  if (x2-x1 <= 15)
1346  pixeldata <<= 16;
1347 
1348  x=x1; y=y1;
1349  while (x <= x2 && y <= y2) {
1350  unsigned char buf = color;
1351  int addr = x + y*1280;
1352  int bit_set = pixeldata & 0x80000000UL;
1353  pixeldata <<= 1;
1354  if (x < 1280 && y < 1024 && bit_set)
1355  cpu->memory_rw(cpu, cpu->mem,
1356  0x38000000 + addr, &buf,1,MEM_WRITE,
1358  x++;
1359  if (x > x2) {
1360  x = x1;
1361  y++;
1362  }
1363  }
1364  }
1365  break;
1366 
1367 
1368  /* Operations: */
1369  case 0x3800:
1370  if (writeflag == MEM_WRITE) {
1371  switch (idata) {
1372  case 0x11: /* zerofill */
1373  first_addr = d->reg[0x3030 / sizeof(uint32_t)];
1374  last_addr = d->reg[0x3038 / sizeof(uint32_t)];
1375  zerobuflen = last_addr - first_addr + 1;
1376  debug("[ sgi_mte: zerofill: first = 0x%016llx,"
1377  " last = 0x%016llx, length = 0x%llx ]\n",
1378  (long long)first_addr, (long long)
1379  last_addr, (long long)zerobuflen);
1380 
1381  /* TODO: is there a better way to
1382  implement this? */
1383  memset(zerobuf, 0, sizeof(zerobuf));
1384  fill_addr = first_addr;
1385  while (zerobuflen != 0) {
1386  if (zerobuflen > sizeof(zerobuf))
1387  fill_len = sizeof(zerobuf);
1388  else
1389  fill_len = zerobuflen;
1390  cpu->memory_rw(cpu, mem, fill_addr,
1391  zerobuf, fill_len, MEM_WRITE,
1393  fill_addr += fill_len;
1394  zerobuflen -= sizeof(zerobuf);
1395  }
1396 
1397  break;
1398  default:
1399  fatal("[ sgi_mte: UNKNOWN operation "
1400  "0x%x ]\n", idata);
1401  }
1402  }
1403  break;
1404  default:
1405  if (writeflag == MEM_WRITE)
1406  debug("[ sgi_mte: unimplemented write to "
1407  "address 0x%llx, data=0x%016llx ]\n",
1408  (long long)relative_addr, (long long)idata);
1409  else
1410  debug("[ sgi_mte: unimplemented read from address"
1411  " 0x%llx ]\n", (long long)relative_addr);
1412  }
1413 
1414  if (writeflag == MEM_READ)
1415  memory_writemax64(cpu, data, len, odata);
1416 
1417  return 1;
1418 }
1419 
1420 
1421 /*
1422  * dev_sgi_mte_init():
1423  */
1424 void dev_sgi_mte_init(struct memory *mem, uint64_t baseaddr)
1425 {
1426  struct sgi_mte_data *d;
1427 
1428  CHECK_ALLOCATION(d = (struct sgi_mte_data *) malloc(sizeof(struct sgi_mte_data)));
1429  memset(d, 0, sizeof(struct sgi_mte_data));
1430 
1431  memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH,
1432  dev_sgi_mte_access, (void *)d, DM_DEFAULT, NULL);
1433 }
1434 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
#define MEC_INT_RX_MCL_FIFO_ALIAS
Definition: if_mecreg.h:80
void net_ethernet_tx(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net.cc:371
void fatal(const char *fmt,...)
Definition: main.cc:152
#define MEC_INT_STATUS_MASK
Definition: if_mecreg.h:71
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define DM_DEFAULT
Definition: memory.h:130
#define CRM_MEM_BANK_CTRL0
Definition: crimereg.h:54
unsigned char reg[DEV_MACE_LENGTH]
#define MEC_DMA_CONTROL
Definition: if_mecreg.h:85
struct interrupt irq
#define MEC_MCL_RX_FIFO
Definition: if_mecreg.h:152
#define MACE_ISA_INT_STATUS
Definition: sgi_macereg.h:153
char * name
Definition: device.h:43
struct memory * mem
Definition: cpu.h:362
void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
struct machine * machine
Definition: cpu.h:328
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
#define MEC_MULTICAST
Definition: if_mecreg.h:141
#define MEM_READ
Definition: memory.h:116
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
#define MEC_INT_TX_RING_BUFFER_ALIAS
Definition: if_mecreg.h:81
struct memory * memory
Definition: machine.h:126
#define CRIME_INTMASK
Definition: crimereg.h:43
void crime_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:98
struct pci_data * dev_macepci_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path)
#define ZERO_CHUNK_LEN
#define DEV_SGI_UST_LENGTH
Definition: devices.h:437
uint32_t reg[DEV_MACEPCI_LENGTH/4]
Definition: dev_sgi_ip32.cc:64
uint32_t reg[DEV_SGI_MTE_LENGTH/sizeof(uint32_t)]
int cur_rx_addr_index_write
void * return_ptr
Definition: device.h:56
#define MEC_PHY_DATA
Definition: if_mecreg.h:124
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
uint64_t rx_addr[N_RX_ADDRESSES]
struct cpu ** cpus
Definition: machine.h:140
#define DEV_SGI_MEC_LENGTH
Definition: devices.h:431
#define MAX_TX_PACKET_LEN
#define CRIME_SPEED_DIV_FACTOR
Definition: dev_sgi_ip32.cc:60
#define MEC_INT_TX_EMPTY
Definition: if_mecreg.h:72
int ncpus
Definition: machine.h:139
int net_ethernet_rx(struct net *net, void *extra, unsigned char **packetp, int *lenp)
Definition: net.cc:316
#define CRIME_TIME
Definition: crimereg.h:48
struct pci_data * pci_data
Definition: dev_sgi_ip32.cc:63
struct emul * emul
Definition: machine.h:99
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
#define MEC_STATION_ALT
Definition: if_mecreg.h:138
void mace_interrupt_assert(struct interrupt *interrupt)
#define DEV_MACE_LENGTH
void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
Definition: net.cc:598
int dev_sgi_mec_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
#define PHYSICAL
Definition: memory.h:126
#define MEC_TX_RING_WRITE_PTR
Definition: if_mecreg.h:107
#define MACE_PERIPH_MISC
Definition: crimereg.h:96
void crime_interrupt_assert(struct interrupt *interrupt)
Definition: dev_sgi_ip32.cc:79
void dev_sgi_mec_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path, unsigned char *macaddr)
#define MEC_MAC_CORE_RESET
Definition: if_mecreg.h:45
void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data, int bus, int device, int function, int reg)
Definition: bus_pci.cc:197
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:365
void dev_sgi_mte_init(struct memory *mem, uint64_t baseaddr)
u_short data
Definition: siireg.h:79
#define MEC_INT_RX_THRESHOLD
Definition: if_mecreg.h:77
#define MEC_TICK_SHIFT
uint64_t reg[DEV_SGI_MEC_LENGTH/sizeof(uint64_t)]
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
uint8_t running
Definition: cpu.h:353
#define CRIME_TICKSHIFT
Definition: dev_sgi_ip32.cc:58
#define MEM_WRITE
Definition: memory.h:117
#define MEC_STATION
Definition: if_mecreg.h:137
#define MEC_DMA_TX_INT_ENABLE
Definition: if_mecreg.h:86
#define DEV_MACEPCI_LENGTH
Definition: devices.h:425
int dev_sgi_mte_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
#define CRM_MEM_BANK_CTRL1
Definition: crimereg.h:55
#define MEC_MAC_REVISION_SHIFT
Definition: if_mecreg.h:63
Definition: device.h:40
#define MEC_MAC_REVISION
Definition: if_mecreg.h:62
struct interrupt irq_periph
#define MEC_PHY_READ_INITIATE
Definition: if_mecreg.h:134
uint64_t reg[DEV_SGI_UST_LENGTH/sizeof(uint64_t)]
unsigned char reg[DEV_CRIME_LENGTH]
Definition: dev_sgi_ip32.cc:69
int net_ethernet_rx_avail(struct net *net, void *extra)
Definition: net.cc:253
#define MEC_TX_RING_BASE
Definition: if_mecreg.h:142
uint32_t addr
DEVICE_ACCESS(crime)
#define debug
Definition: dev_adb.cc:57
int dev_sgi_ust_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
uint32_t line
Definition: interrupt.h:51
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
struct machine * machine
Definition: device.h:41
#define NO_EXCEPTIONS
Definition: memory.h:125
char * name
Definition: interrupt.h:66
struct interrupt irq
Definition: dev_sgi_ip32.cc:70
#define MACE_ISA_INT_MASK
Definition: sgi_macereg.h:154
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
#define MEC_TX_RING_PTR
Definition: if_mecreg.h:106
#define DEV_CRIME_LENGTH
Definition: dev_sgi_ip32.cc:67
void dev_crime_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path, int use_fb)
DEVINIT(mace)
int dev_macepci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
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
#define CRIME_CONTROL
Definition: crimereg.h:41
#define MACE_PERIPH_SERIAL
Definition: crimereg.h:97
struct net * net
Definition: emul.h:43
#define MEC_INT_STATUS
Definition: if_mecreg.h:70
unsigned char * cur_rx_packet
void bus_pci_decompose_1(uint32_t t, int *bus, int *dev, int *func, int *reg)
Definition: bus_pci.cc:77
#define CRIME_INTSTAT
Definition: crimereg.h:42
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:356
Definition: memory.h:75
uint64_t addr
Definition: device.h:46
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
#define CRIME_SPEED_MUL_FACTOR
Definition: dev_sgi_ip32.cc:59
struct interrupt irq_misc
void * extra
Definition: interrupt.h:59
#define N_RX_ADDRESSES
void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data, uint64_t *data, int len, int writeflag)
Definition: bus_pci.cc:96
unsigned char cur_tx_packet[MAX_TX_PACKET_LEN]
DEVICE_TICK(crime)
#define MEC_TX_RING_READ_PTR
Definition: if_mecreg.h:108
char * op[16]
#define MEC_PHY_ADDRESS
Definition: if_mecreg.h:129
#define MEC_INT_TX_PACKET_SENT
Definition: if_mecreg.h:73
void mace_interrupt_deassert(struct interrupt *interrupt)
unsigned char macaddr[6]
#define DEV_SGI_MTE_LENGTH
Definition: devices.h:442
#define MEC_RX_ALIAS
Definition: if_mecreg.h:102
char * interrupt_path
Definition: device.h:50
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
#define MEC_TX_ALIAS
Definition: if_mecreg.h:99
#define MEC_MAC_CONTROL
Definition: if_mecreg.h:44

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13