dev_sgi_mec.cc Source File

Back to the index.

dev_sgi_mec.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 "mec" ethernet
29  *
30  * Used by the SGI O2 emulation mode.
31  * Based on how NetBSD and OpenBSD use the hardware, just about enough to let
32  * those OSes boot with root-on-nfs.
33  *
34  * http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/sgi/dev/if_mec.c
35  *
36  * TODO:
37  *
38  * x) tx and rx interrupts/ring/slot stuff
39  *
40  * A note about word length for reads/writes:
41  *
42  * NetBSD uses (at least) 64-bit reads/writes.
43  * OpenBSD uses both 32-bit and 64-bit reads/writes.
44  * The PROM uses (at least) 32-bit reads/writes and 16-bit reads (from
45  * offsets 0x34 and 0x36)!
46  *
47  * Random googling reveals this NetBSD dmesg about the PHYs:
48  *
49  * https://mail-index.netbsd.org/port-sgimips/2008/01/27/msg000043.html
50  *
51  * mec0 at mace0 offset 0x280000 intr 3 intrmask 0x0: MAC-110 Ethernet, rev 1
52  * mec0: Ethernet address 08:00:69:0e:85:21
53  * nsphy0 at mec0 phy 8: DP83840 10/100 media interface, rev. 1
54  * nsphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
55  */
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #include "bus_pci.h"
62 #include "console.h"
63 #include "cpu.h"
64 #include "device.h"
65 #include "devices.h"
66 #include "emul.h"
67 #include "machine.h"
68 #include "memory.h"
69 #include "misc.h"
70 #include "net.h"
71 
72 #include "thirdparty/if_mecreg.h"
73 #include "thirdparty/mii.h"
74 
75 // #define debug fatal
76 // #define MEC_DEBUG
77 
78 #define MEC_TICK_SHIFT 14
79 
80 #define MAX_TX_PACKET_LEN 1700
81 #define N_RX_ADDRESSES 16
82 
83 struct sgi_mec_data {
84  uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)];
85 
86  struct interrupt irq;
88 
89  unsigned char macaddr[6];
90 
93 
94  unsigned char *cur_rx_packet;
96 
100 };
101 
102 
103 /*
104  * mec_reset():
105  */
106 static void mec_reset(struct sgi_mec_data *d)
107 {
108  if (d->cur_rx_packet != NULL)
109  free(d->cur_rx_packet);
110 
111  memset(d->reg, 0, sizeof(d->reg));
112 }
113 
114 
115 /*
116  * mec_control_write():
117  */
118 static void mec_control_write(struct cpu *cpu, struct sgi_mec_data *d,
119  uint64_t x)
120 {
121  if (x & MEC_MAC_CORE_RESET) {
122  debug("[ sgi_mec: CORE RESET ]\n");
123  mec_reset(d);
124  }
125 }
126 
127 
128 /*
129  * mec_try_rx():
130  */
131 static int mec_try_rx(struct cpu *cpu, struct sgi_mec_data *d)
132 {
133  uint64_t base;
134  unsigned char data[8];
135  int i, res, retval = 0;
136 
137  base = d->rx_addr[d->cur_rx_addr_index];
138  if (base & 0xfff)
139  fatal("[ mec_try_rx(): WARNING! lowest bits of base are "
140  "non-zero (0x%3x). TODO ]\n", (int)(base & 0xfff));
141  base &= 0xfffff000ULL;
142  if (base == 0)
143  goto skip;
144 
145  /* printf("rx base = 0x%016llx\n", (long long)base); */
146 
147  /* Read an rx descriptor from memory: */
148  res = cpu->memory_rw(cpu, cpu->mem, base,
149  &data[0], sizeof(data), MEM_READ, PHYSICAL);
150  if (!res)
151  return 0;
152 
153  /* Is this descriptor already in use? */
154  if (data[0] & 0x80) {
155  /* printf("INTERRUPT for base = 0x%x\n", (int)base); */
156  goto skip_and_advance;
157  }
158 
159  if (d->cur_rx_packet == NULL &&
163 
164  if (d->cur_rx_packet == NULL)
165  goto skip;
166 
167 #if 0
168  printf("{ mec: rxdesc %i: ", d->cur_rx_addr_index);
169  for (i=0; i<sizeof(data); i++) {
170  if ((i & 3) == 0)
171  printf(" ");
172  printf("%02x", data[i]);
173  }
174  printf(" }\n");
175 #endif
176 
177  /* Copy the packet data: */
178  //printf("RX: ");
179  for (i=0; i<d->cur_rx_packet_len; i++) {
180  res = cpu->memory_rw(cpu, cpu->mem, base + 32 + i + 2,
181  d->cur_rx_packet + i, 1, MEM_WRITE, PHYSICAL);
182  //printf(" %02x", d->cur_rx_packet[i]);
183  }
184  //printf("\n");
185 
186 #if 0
187  printf("RX: %i bytes, index %i, base = 0x%x\n",
188  d->cur_rx_packet_len, d->cur_rx_addr_index, (int)base);
189 #endif
190 
191  /* 4 bytes of CRC at the end. Hm. TODO */
192  d->cur_rx_packet_len += 4;
193 
194  memset(data, 0, sizeof(data));
195  data[6] = (d->cur_rx_packet_len >> 8) & 255;
196  data[7] = d->cur_rx_packet_len & 255;
197  /* TODO: lots of bits :-) */
198  data[4] = 0x04; /* match MAC */
199  data[0] = 0x80; /* 0x80 = received. */
200  res = cpu->memory_rw(cpu, cpu->mem, base,
201  &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
202 
203  /* Free the packet from memory: */
204  free(d->cur_rx_packet);
205  d->cur_rx_packet = NULL;
206 
207  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_RX_THRESHOLD;
208 skip_and_advance:
209  d->cur_rx_addr_index ++;
211  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &= ~MEC_INT_RX_MCL_FIFO_ALIAS;
212  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
213  (d->cur_rx_addr_index & 0x1f) << 8;
214  retval = 1;
215 
216 skip:
217  return retval;
218 }
219 
220 
221 /*
222  * mec_try_tx():
223  */
224 static int mec_try_tx(struct cpu *cpu, struct sgi_mec_data *d)
225 {
226  uint64_t base, addr, dma_base;
227  int tx_ring_ptr, ringread, ringwrite, res, i, j;
228  unsigned char data[32];
229  int len, start_offset, dma_ptr_nr, dma_len;
230 
231  base = d->reg[MEC_TX_RING_BASE / sizeof(uint64_t)];
232  tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
233 
234  if (base == 0)
235  return 0;
236 
237  /* printf("base = 0x%016llx\n", base); */
238 
239  ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
240  ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
241  ringread >>= 16;
242  /* All done? Then abort. */
243  if (ringread == ringwrite)
244  return 0;
245 
246  tx_ring_ptr &= MEC_TX_RING_READ_PTR;
247  tx_ring_ptr >>= 16;
248 
249  /* Each tx descriptor (+ buffer) is 128 bytes: */
250  addr = base + tx_ring_ptr*128;
251  res = cpu->memory_rw(cpu, cpu->mem, addr,
252  &data[0], sizeof(data), MEM_READ, PHYSICAL);
253  if (!res)
254  return 0;
255 
256  /* Is this packet transmitted already? */
257  if (data[0] & 0x80) {
258  fatal("[ mec_try_tx: tx_ring_ptr = %i, already"
259  " transmitted? ]\n", tx_ring_ptr);
260  goto advance_tx;
261  }
262 
263  len = data[6] * 256 + data[7];
264  start_offset = data[5] & 0x7f;
265 
266  /* Is this packet empty? Then don't transmit. */
267  if (len == 0)
268  return 0;
269 
270  /* Hm. Is len one too little? TODO */
271  len ++;
272 
273 #if 0
274  printf("{ mec: txdesc %i: ", tx_ring_ptr);
275  for (i=0; i<sizeof(data); i++) {
276  if ((i & 3) == 0)
277  printf(" ");
278  printf("%02x", data[i]);
279  }
280  printf(" }\n");
281 #endif
282  dma_ptr_nr = 0;
283 
284  j = 0;
285  d->cur_tx_packet_len = len;
286 
287  //printf("TX: ");
288  for (i=start_offset; i<start_offset+len; i++) {
289  unsigned char ch;
290 
291  if ((i & 0x7f) == 0x00)
292  break;
293 
294  res = cpu->memory_rw(cpu, cpu->mem, addr + i,
295  &ch, sizeof(ch), MEM_READ, PHYSICAL);
296  //printf(" %02x", ch);
297 
298  d->cur_tx_packet[j++] = ch;
299  if (j >= MAX_TX_PACKET_LEN) {
300  fatal("[ mec_try_tx: packet too large? ]\n");
301  break;
302  }
303  }
304  //printf("\n");
305 
306  if (j < len) {
307  /* Continue with DMA: */
308  for (;;) {
309  dma_ptr_nr ++;
310  if (dma_ptr_nr >= 4)
311  break;
312  if (!(data[4] & (0x01 << dma_ptr_nr)))
313  break;
314  dma_base = (data[dma_ptr_nr * 8 + 4] << 24)
315  + (data[dma_ptr_nr * 8 + 5] << 16)
316  + (data[dma_ptr_nr * 8 + 6] << 8)
317  + (data[dma_ptr_nr * 8 + 7]);
318  dma_base &= 0xfffffff8ULL;
319  dma_len = (data[dma_ptr_nr * 8 + 2] << 8)
320  + (data[dma_ptr_nr * 8 + 3]) + 1;
321 
322  /* printf("dma_base = %08x, dma_len = %i\n",
323  (int)dma_base, dma_len); */
324 
325  while (dma_len > 0) {
326  unsigned char ch;
327  res = cpu->memory_rw(cpu, cpu->mem, dma_base,
328  &ch, sizeof(ch), MEM_READ, PHYSICAL);
329  /* printf(" %02x", ch); */
330 
331  d->cur_tx_packet[j++] = ch;
332  if (j >= MAX_TX_PACKET_LEN) {
333  fatal("[ mec_try_tx: packet too large?"
334  " ]\n");
335  break;
336  }
337  dma_base ++;
338  dma_len --;
339  }
340  }
341  }
342 
343  if (j < len)
344  fatal("[ mec_try_tx: not enough data? ]\n");
345 
348 
349  /* see openbsd's if_mec.c for details */
350  if (data[4] & 0x01) {
351  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
353  }
354  memset(data, 0, 6); /* last 2 bytes are len */
355  data[0] = 0x80;
356  data[5] = 0x80;
357 
358  res = cpu->memory_rw(cpu, cpu->mem, addr,
359  &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
360 
361  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_EMPTY;
362  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_PACKET_SENT;
363 
364 advance_tx:
365  /* Advance the ring Read ptr. */
366  tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
367  ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
368  ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
369 
370  ringread = (ringread >> 16) + 1;
371  ringread &= 63;
372  ringread <<= 16;
373 
374  d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] =
375  (ringwrite & MEC_TX_RING_WRITE_PTR) |
376  (ringread & MEC_TX_RING_READ_PTR);
377 
378  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
380  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
381  (d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] &
383 
384  return 1;
385 }
386 
387 
388 DEVICE_TICK(sgi_mec)
389 {
390  struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
391  int n = 0;
392 
393  while (mec_try_tx(cpu, d))
394  ;
395 
396  while (mec_try_rx(cpu, d) && n < 16)
397  n++;
398 
399  /* Interrupts: (TODO: only when enabled) */
400  int asserted = !!(d->reg[MEC_INT_STATUS / sizeof(uint64_t)] & MEC_INT_STATUS_MASK);
401 
402  if (asserted && !d->prev_asserted)
403  INTERRUPT_ASSERT(d->irq);
404  else if (!asserted && d->prev_asserted)
406 
407  d->prev_asserted = asserted;
408 }
409 
410 
412 {
413  struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
414  uint64_t idata = 0, odata = 0;
415  int regnr;
416 
417  uint64_t old_int_status = d->reg[MEC_INT_STATUS / sizeof(uint64_t)];
418  uint64_t old_tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
419 
420  if (writeflag == MEM_WRITE)
421  idata = memory_readmax64(cpu, data, len);
422 
423  regnr = relative_addr / sizeof(uint64_t);
424 
425  if ((relative_addr & ~7) == MEC_TX_RING_PTR_ALIAS)
426  relative_addr -= 8;
427 
428  // Support both 32-bit and 64-bit big-endian loads and stores...
429  if (len == sizeof(uint64_t)) {
430  if (writeflag == MEM_WRITE)
431  d->reg[regnr] = idata;
432  else
433  odata = d->reg[regnr];
434  } else if (len == sizeof(uint32_t)) {
435  if (writeflag == MEM_WRITE) {
436  if (relative_addr & 4)
437  d->reg[regnr] = (d->reg[regnr] & ~0xffffffffULL) | (uint32_t)idata;
438  else
439  d->reg[regnr] = (d->reg[regnr] & 0xffffffffULL) | ((uint64_t)idata << 32ULL);
440  } else {
441  odata = d->reg[regnr];
442  if (relative_addr & 4)
443  odata = (int32_t)odata;
444  else
445  odata = (odata >> 32ULL);
446  }
447  } else if (len == sizeof(uint16_t)) {
448  if (writeflag == MEM_WRITE) {
449  fatal("[ sgi_mec: unimplemented %s len %i (addr 0x%x) ]\n",
450  writeflag ? "write" : "read", len, (long long)relative_addr);
451  } else if ((relative_addr & 7) == 4) {
452  odata = d->reg[regnr];
453  odata = (uint16_t)(odata >> 16);
454  } else if ((relative_addr & 7) == 6) {
455  odata = d->reg[regnr];
456  odata = (uint16_t)odata;
457  } else {
458  fatal("[ sgi_mec: unimplemented %s len %i (addr 0x%x) ]\n",
459  writeflag ? "write" : "read", len, (long long)relative_addr);
460  }
461  } else {
462  fatal("[ sgi_mec: unimplemented %s len %i (addr 0x%x) ]\n",
463  writeflag ? "write" : "read", len, (long long)relative_addr);
464  }
465 
466 #ifdef MEC_DEBUG
467  if (writeflag == MEM_WRITE)
468  fatal("[ sgi_mec: write to address"
469  " 0x%llx, len %i, data=0x%016llx ]\n",
470  (long long)relative_addr, len, (long long)idata);
471 #endif
472 
473  // ... and then treat the registers as 64-bit aligned:
474  switch (relative_addr & ~7) {
475  case MEC_MAC_CONTROL: /* 0x00 */
476  if (writeflag)
477  mec_control_write(cpu, d, idata);
478  else {
479  /* 1 means "Revision 2" in hinv output, as per my O2. (1 + value?) */
480  odata &= ~MEC_MAC_REVISION;
481  odata |= 1 << MEC_MAC_REVISION_SHIFT;
482  }
483  break;
484  case MEC_INT_STATUS: /* 0x08 */
485  if (writeflag) {
486  /* Clear bits on write: (This is just a guess) */
487  uint64_t writtenvalue = d->reg[MEC_INT_STATUS / sizeof(uint64_t)];
488 
489  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] =
490  old_int_status
491  & ~(writtenvalue & MEC_INT_STATUS_MASK);
492  debug("[ sgi_mec: write to MEC_INT_STATUS: "
493  "0x%016llx ]\n", (long long)idata);
494  }
495  break;
496  case MEC_DMA_CONTROL: /* 0x10 */
497  if (writeflag) {
498  debug("[ sgi_mec: write to MEC_DMA_CONTROL: "
499  "0x%016llx ]\n", (long long)idata);
500  if (!(idata & MEC_DMA_TX_INT_ENABLE)) {
501  /* This should apparently stop the
502  TX Empty interrupt. */
503  d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
505  }
506  }
507  break;
508  case MEC_TX_ALIAS: /* 0x20 */
509  if (writeflag) {
510  debug("[ sgi_mec: write to MEC_TX_ALIAS: "
511  "0x%016llx ]\n", (long long)idata);
512  } else {
513  debug("[ sgi_mec: read from MEC_TX_ALIAS: "
514  "0x%016llx ]\n", (long long)idata);
515  odata = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
516  }
517  break;
518  case MEC_RX_ALIAS: /* 0x28 */
519  if (writeflag)
520  debug("[ sgi_mec: write to MEC_RX_ALIAS: "
521  "0x%016llx ]\n", (long long)idata);
522  break;
523  case MEC_TX_RING_PTR: /* 0x30 */
524  if (writeflag) {
525  uint64_t writtenvalue = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
526  writtenvalue &= MEC_TX_RING_WRITE_PTR;
527  d->reg[regnr] = (old_tx_ring_ptr & ~MEC_TX_RING_WRITE_PTR) | writtenvalue;
528 
529  debug("[ sgi_mec: write to MEC_TX_RING_PTR: "
530  "0x%016llx ]\n", (long long)idata);
531  }
532  break;
533  case MEC_PHY_DATA: /* 0x60 */
534  {
535  int dev = (d->reg[MEC_PHY_ADDRESS / sizeof(uint64_t)] & MEC_PHY_ADDR_DEVICE) >> MEC_PHY_ADDR_DEVSHIFT;
536  int reg = d->reg[MEC_PHY_ADDRESS / sizeof(uint64_t)] & MEC_PHY_ADDR_REGISTER;
537 
538  if (writeflag) {
539  debug("[ sgi_mec: write to MEC_PHY_DATA (dev %i, reg %i): "
540  "0x%016llx ]\n",
541  dev, reg, (long long)idata);
542  }
543 
544  odata = 0;
545 
546  if (dev == 8) {
547  // https://dmesgd.nycbug.org/index.cgi?do=view&id=2828 says:
548  // nsphy0 at mec0 phy 8: DP83840 10/100 media interface, rev. 0
549  // nsphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
550  switch (reg) {
551  case MII_BMCR: // 0
552  odata = BMCR_AUTOEN;
553  break;
554  case MII_BMSR: // 1
555  odata = BMSR_100TXFDX | BMSR_100TXHDX |
557  BMSR_ANEG | BMSR_LINK; // LINK means cable is connected
558  break;
559  case MII_PHYIDR1: // 2
560  odata = 0x2000; // To match NetBSD's "xxNATSEMI" value.
561  break;
562  case MII_PHYIDR2: // 3
563  odata = 0x5c00; // To match NetBSD's "xxNATSEMI" value.
564  break;
565  case 23: // MII_NSPHY_PCR
566  odata = 0x20; // PCR_CIMDIS
567  break;
568  default:
569  fatal("[ sgi_mec: unimplemented %s PHY register %i ]\n",
570  writeflag ? "write to" : "read from", reg);
571  }
572  }
573 
574  if (!writeflag) {
575  debug("[ sgi_mec: read from MEC_PHY_DATA (dev %i, reg %i): "
576  "0x%016llx ]\n",
577  dev, reg, (long long)odata);
578  }
579  }
580  break;
581  case MEC_PHY_ADDRESS: /* 0x68 */
582  if (writeflag)
583  debug("[ sgi_mec: write to MEC_PHY_ADDRESS: "
584  "0x%016llx ]\n", (long long)idata);
585  break;
586  case MEC_PHY_READ_INITIATE: /* 0x70 */
587  if (writeflag)
588  debug("[ sgi_mec: write to MEC_PHY_READ_INITIATE: "
589  "0x%016llx ]\n", (long long)idata);
590  break;
591  case MEC_STATION: /* 0xa0 */
592  if (writeflag)
593  debug("[ sgi_mec: setting the MAC address to "
594  "%02x:%02x:%02x:%02x:%02x:%02x ]\n",
595  (idata >> 40) & 255, (idata >> 32) & 255,
596  (idata >> 24) & 255, (idata >> 16) & 255,
597  (idata >> 8) & 255, (idata >> 0) & 255);
598  else
599  fatal("[ sgi_mec: reading the MAC address as "
600  "%02x:%02x:%02x:%02x:%02x:%02x ]\n",
601  (odata >> 40) & 255, (odata >> 32) & 255,
602  (odata >> 24) & 255, (odata >> 16) & 255,
603  (odata >> 8) & 255, (odata >> 0) & 255);
604  break;
605  case MEC_STATION_ALT: /* 0xa8 */
606  if (writeflag)
607  debug("[ sgi_mec: setting the ALTERNATIVE MAC address"
608  " to %02x:%02x:%02x:%02x:%02x:%02x ]\n",
609  (idata >> 40) & 255, (idata >> 32) & 255,
610  (idata >> 24) & 255, (idata >> 16) & 255,
611  (idata >> 8) & 255, (idata >> 0) & 255);
612  else
613  debug("[ sgi_mec: reading the ALTERNATIVE MAC address"
614  " as %02x:%02x:%02x:%02x:%02x:%02x ]\n",
615  (odata >> 40) & 255, (odata >> 32) & 255,
616  (odata >> 24) & 255, (odata >> 16) & 255,
617  (odata >> 8) & 255, (odata >> 0) & 255);
618  break;
619  case MEC_MULTICAST: /* 0xb0 */
620  if (writeflag)
621  debug("[ sgi_mec: write to MEC_MULTICAST: "
622  "0x%016llx ]\n", (long long)idata);
623  break;
624  case MEC_TX_RING_BASE: /* 0xb8 */
625  if (writeflag)
626  debug("[ sgi_mec: write to MEC_TX_RING_BASE: "
627  "0x%016llx ]\n", (long long)idata);
628  break;
629  case MEC_MCL_RX_FIFO: /* 0x100 */
630  if (writeflag) {
631  debug("[ sgi_mec: write to MEC_MCL_RX_FIFO: 0x"
632  "%016llx ]\n", (long long)idata);
633  d->rx_addr[d->cur_rx_addr_index_write] = idata;
636  }
637  break;
638  default:
639  if (writeflag == MEM_WRITE)
640  fatal("[ sgi_mec: unimplemented write to address"
641  " 0x%llx, data=0x%016llx ]\n",
642  (long long)relative_addr, (long long)idata);
643  else
644  fatal("[ sgi_mec: unimplemented read from address"
645  " 0x%llx ]\n", (long long)relative_addr);
646  }
647 
648  if (writeflag == MEM_READ)
649  memory_writemax64(cpu, data, len, odata);
650 
651 #ifdef MEC_DEBUG
652  if (writeflag == MEM_READ)
653  fatal("[ sgi_mec: read from address"
654  " 0x%llx, len %i, data=0x%llx ]\n", (long long)relative_addr,
655  len, (long long)odata);
656 #endif
657 
658  dev_sgi_mec_tick(cpu, extra);
659 
660  return 1;
661 }
662 
663 
664 /*
665  * dev_sgi_mec_init():
666  */
667 void dev_sgi_mec_init(struct machine *machine, struct memory *mem,
668  uint64_t baseaddr, char *irq_path, unsigned char *macaddr)
669 {
670  char *name2;
671  size_t nlen = 55;
672  struct sgi_mec_data *d;
673 
674  CHECK_ALLOCATION(d = (struct sgi_mec_data *) malloc(sizeof(struct sgi_mec_data)));
675  memset(d, 0, sizeof(struct sgi_mec_data));
676 
677  INTERRUPT_CONNECT(irq_path, d->irq);
678  memcpy(d->macaddr, macaddr, 6);
679  mec_reset(d);
680 
681  CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
682  snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]",
683  d->macaddr[0], d->macaddr[1], d->macaddr[2],
684  d->macaddr[3], d->macaddr[4], d->macaddr[5]);
685 
686  memory_device_register(mem, name2, baseaddr,
688  DM_DEFAULT, NULL);
689 
690  machine_add_tickfunction(machine, dev_sgi_mec_tick, d,
692 
694 }
695 
696 
sgi_mec_data::prev_asserted
int prev_asserted
Definition: dev_sgi_mec.cc:87
MII_BMSR
#define MII_BMSR
Definition: mii.h:68
data
u_short data
Definition: siireg.h:79
MEC_INT_RX_THRESHOLD
#define MEC_INT_RX_THRESHOLD
Definition: if_mecreg.h:77
MEC_INT_STATUS_MASK
#define MEC_INT_STATUS_MASK
Definition: if_mecreg.h:71
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
MEC_INT_TX_RING_BUFFER_ALIAS
#define MEC_INT_TX_RING_BUFFER_ALIAS
Definition: if_mecreg.h:82
MII_BMCR
#define MII_BMCR
Definition: mii.h:50
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
MEC_STATION
#define MEC_STATION
Definition: if_mecreg.h:137
sgi_mec_data::rx_addr
uint64_t rx_addr[N_RX_ADDRESSES]
Definition: dev_sgi_mec.cc:97
memory
Definition: memory.h:75
debug
#define debug
Definition: dev_adb.cc:57
machine::emul
struct emul * emul
Definition: machine.h:99
MEC_PHY_DATA
#define MEC_PHY_DATA
Definition: if_mecreg.h:125
DEV_SGI_MEC_LENGTH
#define DEV_SGI_MEC_LENGTH
Definition: devices.h:458
BMSR_ANEG
#define BMSR_ANEG
Definition: mii.h:80
if_mecreg.h
MEC_TICK_SHIFT
#define MEC_TICK_SHIFT
Definition: dev_sgi_mec.cc:78
MEC_TX_RING_READ_PTR
#define MEC_TX_RING_READ_PTR
Definition: if_mecreg.h:110
DEVICE_ACCESS
DEVICE_ACCESS(sgi_mec)
Definition: dev_sgi_mec.cc:411
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
MEC_INT_TX_EMPTY
#define MEC_INT_TX_EMPTY
Definition: if_mecreg.h:72
net_ethernet_rx
int net_ethernet_rx(struct net *net, void *extra, unsigned char **packetp, int *lenp)
Definition: net.cc:316
MEM_READ
#define MEM_READ
Definition: memory.h:116
sgi_mec_data::cur_tx_packet
unsigned char cur_tx_packet[MAX_TX_PACKET_LEN]
Definition: dev_sgi_mec.cc:91
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
console.h
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
N_RX_ADDRESSES
#define N_RX_ADDRESSES
Definition: dev_sgi_mec.cc:81
DEVICE_TICK
DEVICE_TICK(sgi_mec)
Definition: dev_sgi_mec.cc:388
device.h
MEC_MAC_REVISION
#define MEC_MAC_REVISION
Definition: if_mecreg.h:62
MEC_PHY_ADDR_DEVICE
#define MEC_PHY_ADDR_DEVICE
Definition: if_mecreg.h:131
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
MEC_MULTICAST
#define MEC_MULTICAST
Definition: if_mecreg.h:141
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
sgi_mec_data
Definition: dev_sgi_mec.cc:83
MEC_PHY_ADDR_DEVSHIFT
#define MEC_PHY_ADDR_DEVSHIFT
Definition: if_mecreg.h:132
MEC_PHY_ADDR_REGISTER
#define MEC_PHY_ADDR_REGISTER
Definition: if_mecreg.h:130
MII_PHYIDR2
#define MII_PHYIDR2
Definition: mii.h:102
MII_PHYIDR1
#define MII_PHYIDR1
Definition: mii.h:100
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
BMSR_10THDX
#define BMSR_10THDX
Definition: mii.h:73
MEC_STATION_ALT
#define MEC_STATION_ALT
Definition: if_mecreg.h:138
misc.h
MAX_TX_PACKET_LEN
#define MAX_TX_PACKET_LEN
Definition: dev_sgi_mec.cc:80
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
sgi_mec_data::reg
uint64_t reg[DEV_SGI_MEC_LENGTH/sizeof(uint64_t)]
Definition: dev_sgi_mec.cc:84
machine.h
machine
Definition: machine.h:97
MEC_PHY_ADDRESS
#define MEC_PHY_ADDRESS
Definition: if_mecreg.h:129
MEC_INT_STATUS
#define MEC_INT_STATUS
Definition: if_mecreg.h:70
MEC_TX_RING_BASE
#define MEC_TX_RING_BASE
Definition: if_mecreg.h:142
BMSR_100TXFDX
#define BMSR_100TXFDX
Definition: mii.h:70
sgi_mec_data::cur_rx_addr_index_write
int cur_rx_addr_index_write
Definition: dev_sgi_mec.cc:98
net_ethernet_tx
void net_ethernet_tx(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net.cc:371
MEC_TX_RING_PTR_ALIAS
#define MEC_TX_RING_PTR_ALIAS
Definition: if_mecreg.h:111
emul.h
sgi_mec_data::irq
struct interrupt irq
Definition: dev_sgi_mec.cc:86
MEC_DMA_TX_INT_ENABLE
#define MEC_DMA_TX_INT_ENABLE
Definition: if_mecreg.h:88
sgi_mec_data::cur_rx_packet
unsigned char * cur_rx_packet
Definition: dev_sgi_mec.cc:94
mii.h
net_add_nic
void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
Definition: net.cc:598
MEC_TX_RING_WRITE_PTR
#define MEC_TX_RING_WRITE_PTR
Definition: if_mecreg.h:109
cpu.h
dev_sgi_mec_access
int dev_sgi_mec_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
sgi_mec_data::cur_rx_addr_index
int cur_rx_addr_index
Definition: dev_sgi_mec.cc:99
net_ethernet_rx_avail
int net_ethernet_rx_avail(struct net *net, void *extra)
Definition: net.cc:253
emul::net
struct net * net
Definition: emul.h:43
sgi_mec_data::cur_tx_packet_len
int cur_tx_packet_len
Definition: dev_sgi_mec.cc:92
MEC_RX_ALIAS
#define MEC_RX_ALIAS
Definition: if_mecreg.h:104
cpu::mem
struct memory * mem
Definition: cpu.h:362
bus_pci.h
cpu::machine
struct machine * machine
Definition: cpu.h:328
reg
#define reg(x)
Definition: tmp_alpha_tail.cc:53
MEC_TX_RING_PTR
#define MEC_TX_RING_PTR
Definition: if_mecreg.h:108
MEC_INT_TX_PACKET_SENT
#define MEC_INT_TX_PACKET_SENT
Definition: if_mecreg.h:73
BMSR_LINK
#define BMSR_LINK
Definition: mii.h:81
MEC_INT_RX_MCL_FIFO_ALIAS
#define MEC_INT_RX_MCL_FIFO_ALIAS
Definition: if_mecreg.h:80
MEC_DMA_CONTROL
#define MEC_DMA_CONTROL
Definition: if_mecreg.h:87
BMSR_10TFDX
#define BMSR_10TFDX
Definition: mii.h:72
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
dev_sgi_mec_init
void dev_sgi_mec_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, char *irq_path, unsigned char *macaddr)
Definition: dev_sgi_mec.cc:667
interrupt
Definition: interrupt.h:36
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
MEC_MAC_REVISION_SHIFT
#define MEC_MAC_REVISION_SHIFT
Definition: if_mecreg.h:63
devices.h
MEC_MAC_CONTROL
#define MEC_MAC_CONTROL
Definition: if_mecreg.h:44
cpu
Definition: cpu.h:326
net.h
MEC_MAC_CORE_RESET
#define MEC_MAC_CORE_RESET
Definition: if_mecreg.h:45
cpu::memory_rw
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
MEC_PHY_READ_INITIATE
#define MEC_PHY_READ_INITIATE
Definition: if_mecreg.h:134
memory.h
sgi_mec_data::cur_rx_packet_len
int cur_rx_packet_len
Definition: dev_sgi_mec.cc:95
sgi_mec_data::macaddr
unsigned char macaddr[6]
Definition: dev_sgi_mec.cc:89
MEC_TX_ALIAS
#define MEC_TX_ALIAS
Definition: if_mecreg.h:101
BMCR_AUTOEN
#define BMCR_AUTOEN
Definition: mii.h:54
BMSR_100TXHDX
#define BMSR_100TXHDX
Definition: mii.h:71
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
MEC_MCL_RX_FIFO
#define MEC_MCL_RX_FIFO
Definition: if_mecreg.h:152

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