dev_dec21143.cc Source File

Back to the index.

dev_dec21143.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-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: DEC 21143 "Tulip" ethernet controller
29  *
30  * Implemented from Intel document 278074-001 ("21143 PC/CardBus 10/100Mb/s
31  * Ethernet LAN Controller") and by reverse-engineering OpenBSD and NetBSD
32  * sources.
33  *
34  * This device emulates several sub-components:
35  *
36  * 21143: This is the actual ethernet controller.
37  *
38  * MII: The "physical" network interface.
39  *
40  * SROM: A ROM area containing setting such as which MAC address to
41  * use, and info about the MII.
42  *
43  *
44  * TODO:
45  * o) Handle _writes_ to MII registers.
46  * o) Make it work with modern Linux kernels (as a guest OS).
47  * o) Endianness for descriptors? If necessary.
48  * o) Actually handle the "Setup" packet.
49  * o) MAC filtering on incoming packets.
50  * o) Don't hardcode as many values.
51  */
52 
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 
57 #include "cpu.h"
58 #include "device.h"
59 #include "devices.h"
60 #include "emul.h"
61 #include "interrupt.h"
62 #include "machine.h"
63 #include "memory.h"
64 #include "misc.h"
65 #include "net.h"
66 
67 #include "thirdparty/mii.h"
68 #include "thirdparty/tulipreg.h"
69 
70 
71 /* #define debug fatal */
72 
73 #define DEC21143_TICK_SHIFT 16
74 
75 #define N_REGS 32
76 #define ROM_WIDTH 6
77 
78 struct dec21143_data {
79  struct interrupt irq;
81 
82  /* PCI: */
84 
85  /* Ethernet address, and a network which we are connected to: */
86  uint8_t mac[6];
87  struct net *net;
88 
89  /* SROM emulation: */
90  uint8_t srom[1 << (ROM_WIDTH + 1)];
94  int srom_addr;
95 
96  /* MII PHY emulation: */
97  uint16_t mii_phy_reg[MII_NPHY * 32];
98  int mii_state;
99  int mii_bit;
103 
104  /* 21143 registers: */
105  uint32_t reg[N_REGS];
106 
107  /* Internal TX state: */
108  uint64_t cur_tx_addr;
109  unsigned char *cur_tx_buf;
113 
114  /* Internal RX state: */
115  uint64_t cur_rx_addr;
116  unsigned char *cur_rx_buf;
119 };
120 
121 
122 /* Internal states during MII data stream decode: */
123 #define MII_STATE_RESET 0
124 #define MII_STATE_START_WAIT 1
125 #define MII_STATE_READ_OP 2
126 #define MII_STATE_READ_PHYADDR_REGADDR 3
127 #define MII_STATE_A 4
128 #define MII_STATE_D 5
129 #define MII_STATE_IDLE 6
130 
131 
132 /*
133  * dec21143_rx():
134  *
135  * Receive a packet. (If there is no current packet, then check for newly
136  * arrived ones. If the current packet couldn't be fully transfered the
137  * last time, then continue on that packet.)
138  */
139 int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)
140 {
141  uint64_t addr = d->cur_rx_addr, bufaddr;
142  unsigned char descr[16];
143  uint32_t rdes0, rdes1, rdes2, rdes3;
144  int bufsize, buf1_size, buf2_size, i, writeback_len = 4, to_xfer;
145 
146  /* No current packet? Then check for new ones. */
147  if (d->cur_rx_buf == NULL) {
148  /* Nothing available? Then abort. */
149  if (!net_ethernet_rx_avail(d->net, d))
150  return 0;
151 
152  /* Get the next packet into our buffer: */
153  net_ethernet_rx(d->net, d, &d->cur_rx_buf,
154  &d->cur_rx_buf_len);
155 
156  /* Append a 4 byte CRC: */
157  d->cur_rx_buf_len += 4;
158  CHECK_ALLOCATION(d->cur_rx_buf = (unsigned char *) realloc(d->cur_rx_buf,
159  d->cur_rx_buf_len));
160 
161  /* Well... the CRC is just zeros, for now. */
162  memset(d->cur_rx_buf + d->cur_rx_buf_len - 4, 0, 4);
163 
164  d->cur_rx_offset = 0;
165  }
166 
167  /* fatal("{ dec21143_rx: base = 0x%08x }\n", (int)addr); */
168  addr &= 0x7fffffff;
169 
170  if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
172  fatal("[ dec21143_rx: memory_rw failed! ]\n");
173  return 0;
174  }
175 
176  rdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
177 
178  /* Only use descriptors owned by the 21143: */
179  if (!(rdes0 & TDSTAT_OWN)) {
180  d->reg[CSR_STATUS/8] |= STATUS_RU;
181  return 0;
182  }
183 
184  if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
185  sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
186  NO_EXCEPTIONS)) {
187  fatal("[ dec21143_rx: memory_rw failed! ]\n");
188  return 0;
189  }
190 
191  rdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
192  rdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
193  rdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
194 
195  buf1_size = rdes1 & TDCTL_SIZE1;
196  buf2_size = (rdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
197  bufaddr = buf1_size? rdes2 : rdes3;
198  bufsize = buf1_size? buf1_size : buf2_size;
199 
200  d->reg[CSR_STATUS/8] &= ~STATUS_RS;
201 
202  if (rdes1 & TDCTL_ER)
203  d->cur_rx_addr = d->reg[CSR_RXLIST / 8];
204  else {
205  if (rdes1 & TDCTL_CH)
206  d->cur_rx_addr = rdes3;
207  else
208  d->cur_rx_addr += 4 * sizeof(uint32_t);
209  }
210 
211  debug("{ RX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
212  (long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize, (int)bufaddr);
213  bufaddr &= 0x7fffffff;
214 
215  /* Turn off all status bits, and give up ownership: */
216  rdes0 = 0x00000000;
217 
218  to_xfer = d->cur_rx_buf_len - d->cur_rx_offset;
219  if (to_xfer > bufsize)
220  to_xfer = bufsize;
221 
222  /* DMA bytes from the packet into emulated physical memory: */
223  for (i=0; i<to_xfer; i++) {
224  cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
225  d->cur_rx_buf + d->cur_rx_offset + i, 1, MEM_WRITE,
227  /* fatal(" %02x", d->cur_rx_buf[d->cur_rx_offset + i]); */
228  }
229 
230  /* Was this the first buffer in a frame? Then mark it as such. */
231  if (d->cur_rx_offset == 0)
232  rdes0 |= TDSTAT_Rx_FS;
233 
234  d->cur_rx_offset += to_xfer;
235 
236  /* Frame completed? */
237  if (d->cur_rx_offset >= d->cur_rx_buf_len) {
238  rdes0 |= TDSTAT_Rx_LS;
239 
240  /* Set the frame length: */
241  rdes0 |= (d->cur_rx_buf_len << 16) & TDSTAT_Rx_FL;
242 
243  /* Frame too long? (1518 is max ethernet frame length) */
244  if (d->cur_rx_buf_len > 1518)
245  rdes0 |= TDSTAT_Rx_TL;
246 
247  /* Cause a receiver interrupt: */
248  d->reg[CSR_STATUS/8] |= STATUS_RI;
249 
250  free(d->cur_rx_buf);
251  d->cur_rx_buf = NULL;
252  d->cur_rx_buf_len = 0;
253  }
254 
255  /* Descriptor writeback: */
256  descr[ 0] = rdes0; descr[ 1] = rdes0 >> 8;
257  descr[ 2] = rdes0 >> 16; descr[ 3] = rdes0 >> 24;
258  if (writeback_len > 1) {
259  descr[ 4] = rdes1; descr[ 5] = rdes1 >> 8;
260  descr[ 6] = rdes1 >> 16; descr[ 7] = rdes1 >> 24;
261  descr[ 8] = rdes2; descr[ 9] = rdes2 >> 8;
262  descr[10] = rdes2 >> 16; descr[11] = rdes2 >> 24;
263  descr[12] = rdes3; descr[13] = rdes3 >> 8;
264  descr[14] = rdes3 >> 16; descr[15] = rdes3 >> 24;
265  }
266 
267  if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
268  * writeback_len, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
269  fatal("[ dec21143_rx: memory_rw failed! ]\n");
270  return 0;
271  }
272 
273  return 1;
274 }
275 
276 
277 /*
278  * dec21143_tx():
279  *
280  * Transmit a packet, if the guest OS has marked a descriptor as containing
281  * data to transmit.
282  */
283 int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)
284 {
285  uint64_t addr = d->cur_tx_addr, bufaddr;
286  unsigned char descr[16];
287  uint32_t tdes0, tdes1, tdes2, tdes3;
288  int bufsize, buf1_size, buf2_size, i;
289 
290  addr &= 0x7fffffff;
291 
292  if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
294  fatal("[ dec21143_tx: memory_rw failed! ]\n");
295  return 0;
296  }
297 
298  tdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
299 
300  /* fatal("{ dec21143_tx: base=0x%08x, tdes0=0x%08x }\n",
301  (int)addr, (int)tdes0); */
302 
303  /* Only process packets owned by the 21143: */
304  if (!(tdes0 & TDSTAT_OWN)) {
305  if (d->tx_idling > d->tx_idling_threshold) {
306  d->reg[CSR_STATUS/8] |= STATUS_TU;
307  d->tx_idling = 0;
308  } else
309  d->tx_idling ++;
310  return 0;
311  }
312 
313  if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
314  sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
315  NO_EXCEPTIONS)) {
316  fatal("[ dec21143_tx: memory_rw failed! ]\n");
317  return 0;
318  }
319 
320  tdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
321  tdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
322  tdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
323 
324  buf1_size = tdes1 & TDCTL_SIZE1;
325  buf2_size = (tdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
326  bufaddr = buf1_size? tdes2 : tdes3;
327  bufsize = buf1_size? buf1_size : buf2_size;
328 
329  d->reg[CSR_STATUS/8] &= ~STATUS_TS;
330 
331  if (tdes1 & TDCTL_ER)
332  d->cur_tx_addr = d->reg[CSR_TXLIST / 8];
333  else {
334  if (tdes1 & TDCTL_CH)
335  d->cur_tx_addr = tdes3;
336  else
337  d->cur_tx_addr += 4 * sizeof(uint32_t);
338  }
339 
340  /*
341  fatal("{ TX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
342  (long long)addr, tdes0, tdes1, tdes2, tdes3, bufsize, (int)bufaddr);
343  */
344  bufaddr &= 0x7fffffff;
345 
346  /* Assume no error: */
347  tdes0 &= ~ (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
349 
350  if (tdes1 & TDCTL_Tx_SET) {
351  /*
352  * Setup Packet.
353  *
354  * TODO. For now, just ignore it, and pretend it worked.
355  */
356  /* fatal("{ TX: setup packet }\n"); */
357  if (bufsize != 192)
358  fatal("[ dec21143: setup packet len = %i, should be"
359  " 192! ]\n", (int)bufsize);
360  if (tdes1 & TDCTL_Tx_IC)
361  d->reg[CSR_STATUS/8] |= STATUS_TI;
362  /* New descriptor values, according to the docs: */
363  tdes0 = 0x7fffffff; tdes1 = 0xffffffff;
364  tdes2 = 0xffffffff; tdes3 = 0xffffffff;
365  } else {
366  /*
367  * Data Packet.
368  */
369  /* fatal("{ TX: data packet: "); */
370  if (tdes1 & TDCTL_Tx_FS) {
371  /* First segment. Let's allocate a new buffer: */
372  /* fatal("new frame }\n"); */
373 
374  CHECK_ALLOCATION(d->cur_tx_buf = (unsigned char *) malloc(bufsize));
375  d->cur_tx_buf_len = 0;
376  } else {
377  /* Not first segment. Increase the length of
378  the current buffer: */
379  /* fatal("continuing last frame }\n"); */
380 
381  if (d->cur_tx_buf == NULL)
382  fatal("[ dec21143: WARNING! tx: middle "
383  "segment, but no first segment?! ]\n");
384 
385  CHECK_ALLOCATION(d->cur_tx_buf = (unsigned char *) realloc(d->cur_tx_buf,
386  d->cur_tx_buf_len + bufsize));
387  }
388 
389  /* "DMA" data from emulated physical memory into the buf: */
390  for (i=0; i<bufsize; i++) {
391  cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
392  d->cur_tx_buf + d->cur_tx_buf_len + i, 1, MEM_READ,
394  /* fatal(" %02x", d->cur_tx_buf[
395  d->cur_tx_buf_len + i]); */
396  }
397 
398  d->cur_tx_buf_len += bufsize;
399 
400  /* Last segment? Then actually transmit it: */
401  if (tdes1 & TDCTL_Tx_LS) {
402  /* fatal("{ TX: data frame complete. }\n"); */
403  if (d->net != NULL) {
404  net_ethernet_tx(d->net, d, d->cur_tx_buf,
405  d->cur_tx_buf_len);
406  } else {
407  static int warn = 0;
408  if (!warn)
409  fatal("[ dec21143: WARNING! Not "
410  "connected to a network! ]\n");
411  warn = 1;
412  }
413 
414  free(d->cur_tx_buf);
415  d->cur_tx_buf = NULL;
416  d->cur_tx_buf_len = 0;
417 
418  /* Interrupt, if Tx_IC is set: */
419  if (tdes1 & TDCTL_Tx_IC)
420  d->reg[CSR_STATUS/8] |= STATUS_TI;
421  }
422 
423  /* We are done with this segment. */
424  tdes0 &= ~TDSTAT_OWN;
425  }
426 
427  /* Error summary: */
428  if (tdes0 & (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
430  tdes0 |= TDSTAT_ES;
431 
432  /* Descriptor writeback: */
433  descr[ 0] = tdes0; descr[ 1] = tdes0 >> 8;
434  descr[ 2] = tdes0 >> 16; descr[ 3] = tdes0 >> 24;
435  descr[ 4] = tdes1; descr[ 5] = tdes1 >> 8;
436  descr[ 6] = tdes1 >> 16; descr[ 7] = tdes1 >> 24;
437  descr[ 8] = tdes2; descr[ 9] = tdes2 >> 8;
438  descr[10] = tdes2 >> 16; descr[11] = tdes2 >> 24;
439  descr[12] = tdes3; descr[13] = tdes3 >> 8;
440  descr[14] = tdes3 >> 16; descr[15] = tdes3 >> 24;
441 
442  if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
443  * 4, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
444  fatal("[ dec21143_tx: memory_rw failed! ]\n");
445  return 0;
446  }
447 
448  return 1;
449 }
450 
451 
452 DEVICE_TICK(dec21143)
453 {
454  struct dec21143_data *d = (struct dec21143_data *) extra;
455  int asserted;
456 
457  if (d->reg[CSR_OPMODE / 8] & OPMODE_ST)
458  while (dec21143_tx(cpu, d))
459  ;
460 
461  if (d->reg[CSR_OPMODE / 8] & OPMODE_SR)
462  while (dec21143_rx(cpu, d))
463  ;
464 
465  /* Normal and Abnormal interrupt summary: */
466  d->reg[CSR_STATUS / 8] &= ~(STATUS_NIS | STATUS_AIS);
467  if (d->reg[CSR_STATUS / 8] & 0x00004845)
468  d->reg[CSR_STATUS / 8] |= STATUS_NIS;
469  if (d->reg[CSR_STATUS / 8] & 0x0c0037ba)
470  d->reg[CSR_STATUS / 8] |= STATUS_AIS;
471 
472  asserted = d->reg[CSR_STATUS / 8] & d->reg[CSR_INTEN / 8] & 0x0c01ffff;
473 
474  if (asserted)
475  INTERRUPT_ASSERT(d->irq);
476  if (!asserted && d->irq_was_asserted)
478 
479  /* Remember assertion flag: */
480  d->irq_was_asserted = asserted;
481 }
482 
483 
484 /*
485  * mii_access():
486  *
487  * This function handles accesses to the MII. Data streams seem to be of the
488  * following format:
489  *
490  * vv---- starting delimiter
491  * ... 01 xx yyyyy zzzzz a[a] dddddddddddddddd
492  * ^---- I am starting with mii_bit = 0 here
493  *
494  * where x = opcode (10 = read, 01 = write)
495  * y = PHY address
496  * z = register address
497  * a = on Reads: ACK bit (returned, should be 0)
498  * on Writes: _TWO_ dummy bits (10)
499  * d = 16 bits of data (MSB first)
500  */
501 static void mii_access(struct cpu *cpu, struct dec21143_data *d,
502  uint32_t oldreg, uint32_t idata)
503 {
504  int obit, ibit = 0;
505  uint16_t tmp;
506 
507  /* Only care about data during clock cycles: */
508  if (!(idata & MIIROM_MDC))
509  return;
510 
511  if (idata & MIIROM_MDC && oldreg & MIIROM_MDC)
512  return;
513 
514  /* fatal("[ mii_access(): 0x%08x ]\n", (int)idata); */
515 
516  if (idata & MIIROM_BR) {
517  fatal("[ mii_access(): MIIROM_BR: TODO ]\n");
518  return;
519  }
520 
521  obit = idata & MIIROM_MDO? 1 : 0;
522 
523  if (d->mii_state >= MII_STATE_START_WAIT &&
525  idata & MIIROM_MIIDIR)
526  fatal("[ mii_access(): bad dir? ]\n");
527 
528  switch (d->mii_state) {
529 
530  case MII_STATE_RESET:
531  /* Wait for a starting delimiter (0 followed by 1). */
532  if (obit)
533  return;
534  if (idata & MIIROM_MIIDIR)
535  return;
536  /* fatal("[ mii_access(): got a 0 delimiter ]\n"); */
538  d->mii_opcode = 0;
539  d->mii_phyaddr = 0;
540  d->mii_regaddr = 0;
541  break;
542 
544  /* Wait for a starting delimiter (0 followed by 1). */
545  if (!obit)
546  return;
547  if (idata & MIIROM_MIIDIR) {
549  return;
550  }
551  /* fatal("[ mii_access(): got a 1 delimiter ]\n"); */
553  d->mii_bit = 0;
554  break;
555 
556  case MII_STATE_READ_OP:
557  if (d->mii_bit == 0) {
558  d->mii_opcode = obit << 1;
559  /* fatal("[ mii_access(): got first opcode bit "
560  "(%i) ]\n", obit); */
561  } else {
562  d->mii_opcode |= obit;
563  /* fatal("[ mii_access(): got opcode = %i ]\n",
564  d->mii_opcode); */
566  }
567  d->mii_bit ++;
568  break;
569 
571  /* fatal("[ mii_access(): got phy/reg addr bit nr %i (%i)"
572  " ]\n", d->mii_bit - 2, obit); */
573  if (d->mii_bit <= 6)
574  d->mii_phyaddr |= obit << (6-d->mii_bit);
575  else
576  d->mii_regaddr |= obit << (11-d->mii_bit);
577  d->mii_bit ++;
578  if (d->mii_bit >= 12) {
579  /* fatal("[ mii_access(): phyaddr=0x%x regaddr=0x"
580  "%x ]\n", d->mii_phyaddr, d->mii_regaddr); */
581  d->mii_state = MII_STATE_A;
582  }
583  break;
584 
585  case MII_STATE_A:
586  switch (d->mii_opcode) {
587  case MII_COMMAND_WRITE:
588  if (d->mii_bit >= 13)
589  d->mii_state = MII_STATE_D;
590  break;
591  case MII_COMMAND_READ:
592  ibit = 0;
593  d->mii_state = MII_STATE_D;
594  break;
595  default:debug("[ mii_access(): UNIMPLEMENTED MII opcode "
596  "%i (probably just a bug in GXemul's "
597  "MII data stream handling) ]\n", d->mii_opcode);
599  }
600  d->mii_bit ++;
601  break;
602 
603  case MII_STATE_D:
604  switch (d->mii_opcode) {
605  case MII_COMMAND_WRITE:
606  if (idata & MIIROM_MIIDIR)
607  fatal("[ mii_access(): write: bad dir? ]\n");
608  obit = obit? (0x8000 >> (d->mii_bit - 14)) : 0;
609  tmp = d->mii_phy_reg[(d->mii_phyaddr << 5) +
610  d->mii_regaddr] | obit;
611  if (d->mii_bit >= 29) {
613  debug("[ mii_access(): WRITE to phyaddr=0x%x "
614  "regaddr=0x%x: 0x%04x ]\n", d->mii_phyaddr,
615  d->mii_regaddr, tmp);
616  }
617  break;
618  case MII_COMMAND_READ:
619  if (!(idata & MIIROM_MIIDIR))
620  break;
621  tmp = d->mii_phy_reg[(d->mii_phyaddr << 5) +
622  d->mii_regaddr];
623  if (d->mii_bit == 13)
624  debug("[ mii_access(): READ phyaddr=0x%x "
625  "regaddr=0x%x: 0x%04x ]\n", d->mii_phyaddr,
626  d->mii_regaddr, tmp);
627  ibit = tmp & (0x8000 >> (d->mii_bit - 13));
628  if (d->mii_bit >= 28)
630  break;
631  }
632  d->mii_bit ++;
633  break;
634 
635  case MII_STATE_IDLE:
636  d->mii_bit ++;
637  if (d->mii_bit >= 31)
639  break;
640  }
641 
642  d->reg[CSR_MIIROM / 8] &= ~MIIROM_MDI;
643  if (ibit)
644  d->reg[CSR_MIIROM / 8] |= MIIROM_MDI;
645 }
646 
647 
648 /*
649  * srom_access():
650  *
651  * This function handles reads from the Ethernet Address ROM. This is not a
652  * 100% correct implementation, as it was reverse-engineered from OpenBSD
653  * sources; it seems to work with OpenBSD, NetBSD, and Linux, though.
654  *
655  * Each transfer (if I understood this correctly) is of the following format:
656  *
657  * 1xx yyyyyy zzzzzzzzzzzzzzzz
658  *
659  * where 1xx = operation (6 means a Read),
660  * yyyyyy = ROM address
661  * zz...z = data
662  *
663  * y and z are _both_ read and written to at the same time; this enables the
664  * operating system to sense the number of bits in y (when reading, all y bits
665  * are 1 except the last one).
666  */
667 static void srom_access(struct cpu *cpu, struct dec21143_data *d,
668  uint32_t oldreg, uint32_t idata)
669 {
670  int obit, ibit;
671 
672  /* debug("CSR9 WRITE! 0x%08x\n", (int)idata); */
673 
674  /* New selection? Then reset internal state. */
675  if (idata & MIIROM_SR && !(oldreg & MIIROM_SR)) {
676  d->srom_curbit = 0;
677  d->srom_opcode = 0;
679  d->srom_addr = 0;
680  }
681 
682  /* Only care about data during clock cycles: */
683  if (!(idata & MIIROM_SROMSK))
684  return;
685 
686  obit = 0;
687  ibit = idata & MIIROM_SROMDI? 1 : 0;
688  /* debug("CLOCK CYCLE! (bit %i): ", d->srom_curbit); */
689 
690  /*
691  * Linux sends more zeroes before starting the actual opcode, than
692  * OpenBSD and NetBSD. Hopefully this is correct. (I'm just guessing
693  * that all opcodes should start with a 1, perhaps that's not really
694  * the case.)
695  */
696  if (!ibit && !d->srom_opcode_has_started)
697  return;
698 
699  if (d->srom_curbit < 3) {
701  d->srom_opcode <<= 1;
702  d->srom_opcode |= ibit;
703  /* debug("opcode input '%i'\n", ibit); */
704  } else {
705  switch (d->srom_opcode) {
706  case TULIP_SROM_OPC_READ:
707  if (d->srom_curbit < ROM_WIDTH + 3) {
708  obit = d->srom_curbit < ROM_WIDTH + 2;
709  d->srom_addr <<= 1;
710  d->srom_addr |= ibit;
711  } else {
712  uint16_t romword = d->srom[d->srom_addr*2]
713  + (d->srom[d->srom_addr*2+1] << 8);
714  if (d->srom_curbit == ROM_WIDTH + 3)
715  debug("[ dec21143: ROM read from offset"
716  " 0x%03x: 0x%04x ]\n",
717  d->srom_addr, romword);
718  obit = romword & (0x8000 >>
719  (d->srom_curbit - ROM_WIDTH - 3))? 1 : 0;
720  }
721  break;
722  default:fatal("[ dec21243: unimplemented SROM/EEPROM "
723  "opcode %i ]\n", d->srom_opcode);
724  }
725  d->reg[CSR_MIIROM / 8] &= ~MIIROM_SROMDO;
726  if (obit)
727  d->reg[CSR_MIIROM / 8] |= MIIROM_SROMDO;
728  /* debug("input '%i', output '%i'\n", ibit, obit); */
729  }
730 
731  d->srom_curbit ++;
732 
733  /*
734  * Done opcode + addr + data? Then restart. (At least NetBSD does
735  * sequential reads without turning selection off and then on.)
736  */
737  if (d->srom_curbit >= 3 + ROM_WIDTH + 16) {
738  d->srom_curbit = 0;
739  d->srom_opcode = 0;
741  d->srom_addr = 0;
742  }
743 }
744 
745 
746 /*
747  * dec21143_reset():
748  *
749  * Set the 21143 registers, SROM, and MII data to reasonable values.
750  */
751 static void dec21143_reset(struct cpu *cpu, struct dec21143_data *d)
752 {
753  int leaf;
754 
755  if (d->cur_rx_buf != NULL)
756  free(d->cur_rx_buf);
757  if (d->cur_tx_buf != NULL)
758  free(d->cur_tx_buf);
759  d->cur_rx_buf = d->cur_tx_buf = NULL;
760 
761  memset(d->reg, 0, sizeof(uint32_t) * N_REGS);
762  memset(d->srom, 0, sizeof(d->srom));
763  memset(d->mii_phy_reg, 0, sizeof(d->mii_phy_reg));
764 
765  /* Register values at reset, according to the manual: */
766  d->reg[CSR_BUSMODE / 8] = 0xfe000000; /* csr0 */
767  d->reg[CSR_MIIROM / 8] = 0xfff483ff; /* csr9 */
768  d->reg[CSR_SIACONN / 8] = 0xffff0000; /* csr13 */
769  d->reg[CSR_SIATXRX / 8] = 0xffffffff; /* csr14 */
770  d->reg[CSR_SIAGEN / 8] = 0x8ff00000; /* csr15 */
771 
772  d->tx_idling_threshold = 10;
773  d->cur_rx_addr = d->cur_tx_addr = 0;
774 
775  /* Version (= 1) and Chip count (= 1): */
777  d->srom[TULIP_ROM_CHIP_COUNT] = 1;
778 
779  /* Set the MAC address: */
780  memcpy(d->srom + TULIP_ROM_IEEE_NETWORK_ADDRESS, d->mac, 6);
781 
782  leaf = 30;
784  d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)] = leaf & 255;
785  d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)+1] = leaf >> 8;
786 
787  d->srom[leaf+TULIP_ROM_IL_SELECT_CONN_TYPE] = 0; /* Not used? */
788  d->srom[leaf+TULIP_ROM_IL_MEDIA_COUNT] = 2;
790 
791  d->srom[leaf] = 7; /* descriptor length */
792  d->srom[leaf+1] = TULIP_ROM_MB_21142_SIA;
793  d->srom[leaf+2] = TULIP_ROM_MB_MEDIA_100TX;
794  /* here comes 4 bytes of GPIO control/data settings */
795  leaf += d->srom[leaf];
796 
797  d->srom[leaf] = 15; /* descriptor length */
798  d->srom[leaf+1] = TULIP_ROM_MB_21142_MII;
799  d->srom[leaf+2] = 0; /* PHY nr */
800  d->srom[leaf+3] = 0; /* len of select sequence */
801  d->srom[leaf+4] = 0; /* len of reset sequence */
802  /* 5,6, 7,8, 9,10, 11,12, 13,14 = unused by GXemul */
803  leaf += d->srom[leaf];
804 
805  /* MII PHY initial state: */
807 
808  /* PHY #0: */
811 }
812 
813 
814 DEVICE_ACCESS(dec21143)
815 {
816  struct dec21143_data *d = (struct dec21143_data *) extra;
817  uint64_t idata = 0, odata = 0;
818  uint32_t oldreg = 0;
819  int regnr = relative_addr >> 3;
820 
821  if (writeflag == MEM_WRITE)
822  idata = memory_readmax64(cpu, data, len | d->pci_little_endian);
823 
824  if ((relative_addr & 7) == 0 && regnr < N_REGS) {
825  if (writeflag == MEM_READ) {
826  odata = d->reg[regnr];
827  } else {
828  oldreg = d->reg[regnr];
829  switch (regnr) {
830  case CSR_STATUS / 8: /* Zero-on-write */
831  d->reg[regnr] &= ~(idata & 0x0c01ffff);
832  break;
833  case CSR_MISSED / 8: /* Read only */
834  break;
835  default:d->reg[regnr] = idata;
836  }
837  }
838  } else
839  fatal("[ dec21143: WARNING! unaligned access (0x%x) ]\n",
840  (int)relative_addr);
841 
842  switch (relative_addr) {
843 
844  case CSR_BUSMODE: /* csr0 */
845  if (writeflag == MEM_WRITE) {
846  /* Software reset takes effect immediately. */
847  if (idata & BUSMODE_SWR) {
848  dec21143_reset(cpu, d);
849  idata &= ~BUSMODE_SWR;
850  }
851  }
852  break;
853 
854  case CSR_TXPOLL: /* csr1 */
855  if (writeflag == MEM_READ)
856  fatal("[ dec21143: UNIMPLEMENTED READ from "
857  "txpoll ]\n");
859  dev_dec21143_tick(cpu, extra);
860  break;
861 
862  case CSR_RXPOLL: /* csr2 */
863  if (writeflag == MEM_READ)
864  fatal("[ dec21143: UNIMPLEMENTED READ from "
865  "rxpoll ]\n");
866  dev_dec21143_tick(cpu, extra);
867  break;
868 
869  case CSR_RXLIST: /* csr3 */
870  if (writeflag == MEM_WRITE) {
871  debug("[ dec21143: setting RXLIST to 0x%x ]\n",
872  (int)idata);
873  if (idata & 0x3)
874  fatal("[ dec21143: WARNING! RXLIST not aligned"
875  "? (0x%llx) ]\n", (long long)idata);
876  idata &= ~0x3;
877  d->cur_rx_addr = idata;
878  }
879  break;
880 
881  case CSR_TXLIST: /* csr4 */
882  if (writeflag == MEM_WRITE) {
883  debug("[ dec21143: setting TXLIST to 0x%x ]\n",
884  (int)idata);
885  if (idata & 0x3)
886  fatal("[ dec21143: WARNING! TXLIST not aligned"
887  "? (0x%llx) ]\n", (long long)idata);
888  idata &= ~0x3;
889  d->cur_tx_addr = idata;
890  }
891  break;
892 
893  case CSR_STATUS: /* csr5 */
894  case CSR_INTEN: /* csr7 */
895  if (writeflag == MEM_WRITE) {
896  /* Recalculate interrupt assertion. */
897  dev_dec21143_tick(cpu, extra);
898  }
899  break;
900 
901  case CSR_OPMODE: /* csr6: */
902  if (writeflag == MEM_WRITE) {
903  if (idata & 0x02000000) {
904  /* A must-be-one bit. */
905  idata &= ~0x02000000;
906  }
907  if (idata & OPMODE_ST) {
908  idata &= ~OPMODE_ST;
909  } else {
910  /* Turned off TX? Then idle: */
911  d->reg[CSR_STATUS/8] |= STATUS_TPS;
912  }
913  if (idata & OPMODE_SR) {
914  idata &= ~OPMODE_SR;
915  } else {
916  /* Turned off RX? Then go to stopped state: */
917  d->reg[CSR_STATUS/8] &= ~STATUS_RS;
918  }
919  idata &= ~(OPMODE_HBD | OPMODE_SCR | OPMODE_PCS
921  if (idata & OPMODE_PNIC_IT) {
922  idata &= ~OPMODE_PNIC_IT;
924  }
925  if (idata != 0) {
926  fatal("[ dec21143: UNIMPLEMENTED OPMODE bits"
927  ": 0x%08x ]\n", (int)idata);
928  }
929  dev_dec21143_tick(cpu, extra);
930  }
931  break;
932 
933  case CSR_MISSED: /* csr8 */
934  break;
935 
936  case CSR_MIIROM: /* csr9 */
937  if (writeflag == MEM_WRITE) {
938  if (idata & MIIROM_MDC)
939  mii_access(cpu, d, oldreg, idata);
940  else
941  srom_access(cpu, d, oldreg, idata);
942  }
943  break;
944 
945  case CSR_SIASTAT: /* csr12 */
946  /* Auto-negotiation status = Good. */
947  odata = SIASTAT_ANS_FLPGOOD;
948  break;
949 
950  case CSR_SIATXRX: /* csr14 */
951  /* Auto-negotiation Enabled */
952  odata = SIATXRX_ANE;
953  break;
954 
955  case CSR_SIACONN: /* csr13 */
956  case CSR_SIAGEN: /* csr15 */
957  /* Don't print warnings for these, for now. */
958  break;
959 
960  default:if (writeflag == MEM_READ)
961  fatal("[ dec21143: read from unimplemented 0x%02x ]\n",
962  (int)relative_addr);
963  else
964  fatal("[ dec21143: write to unimplemented 0x%02x: "
965  "0x%02x ]\n", (int)relative_addr, (int)idata);
966  }
967 
968  if (writeflag == MEM_READ)
969  memory_writemax64(cpu, data, len | d->pci_little_endian, odata);
970 
971  return 1;
972 }
973 
974 
975 DEVINIT(dec21143)
976 {
977  struct dec21143_data *d;
978  char name2[100];
979 
980  CHECK_ALLOCATION(d = (struct dec21143_data *) malloc(sizeof(struct dec21143_data)));
981  memset(d, 0, sizeof(struct dec21143_data));
982 
985 
987  net_add_nic(devinit->machine->emul->net, d, d->mac);
988  d->net = devinit->machine->emul->net;
989 
990  dec21143_reset(devinit->machine->cpus[0], d);
991 
992  snprintf(name2, sizeof(name2), "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
993  devinit->name, d->mac[0], d->mac[1], d->mac[2], d->mac[3],
994  d->mac[4], d->mac[5]);
995 
997  devinit->addr, 0x100, dev_dec21143_access, d, DM_DEFAULT, NULL);
998 
1000  dev_dec21143_tick, d, DEC21143_TICK_SHIFT);
1001 
1002  /*
1003  * NetBSD/cats uses memory accesses, OpenBSD/cats uses I/O registers.
1004  * Let's make a mirror from the memory range to the I/O range:
1005  */
1008 
1009  return 1;
1010 }
1011 
uint64_t addr2
Definition: device.h:47
#define STATUS_TS
Definition: tulipreg.h:543
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
void net_ethernet_tx(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net.cc:371
#define OPMODE_PNIC_IT
Definition: tulipreg.h:632
void fatal(const char *fmt,...)
Definition: main.cc:152
#define MII_STATE_READ_OP
#define DM_DEFAULT
Definition: memory.h:130
uint8_t mac[6]
Definition: dev_dec21143.cc:86
#define TDCTL_SIZE1
Definition: tulipreg.h:228
#define TDCTL_Tx_IC
Definition: tulipreg.h:240
#define STATUS_TI
Definition: tulipreg.h:490
#define MIIROM_SR
Definition: tulipreg.h:690
#define TDSTAT_Tx_UF
Definition: tulipreg.h:220
#define TULIP_ROM_SROM_FORMAT_VERION
Definition: tulipreg.h:320
#define TDSTAT_Tx_EC
Definition: tulipreg.h:216
#define SIATXRX_ANE
Definition: tulipreg.h:830
#define TDSTAT_ES
Definition: tulipreg.h:178
char * name
Definition: device.h:43
int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)
#define TDCTL_SIZE2_SHIFT
Definition: tulipreg.h:232
struct memory * mem
Definition: cpu.h:362
#define TDSTAT_Rx_FL
Definition: tulipreg.h:185
#define MEM_READ
Definition: memory.h:116
#define CSR_RXPOLL
Definition: tulipreg.h:478
unsigned char * cur_tx_buf
#define CSR_RXLIST
Definition: tulipreg.h:483
struct memory * memory
Definition: machine.h:126
#define MII_NPHY
Definition: mii.h:42
#define MII_STATE_READ_PHYADDR_REGADDR
#define TDSTAT_Tx_NC
Definition: tulipreg.h:214
#define STATUS_RI
Definition: tulipreg.h:498
#define STATUS_RS
Definition: tulipreg.h:514
#define MII_STATE_D
int pci_little_endian
Definition: device.h:54
#define MIIROM_MDO
Definition: tulipreg.h:696
#define TDSTAT_OWN
Definition: tulipreg.h:177
struct net * net
Definition: dev_dec21143.cc:87
#define OPMODE_TTM
Definition: tulipreg.h:637
#define STATUS_NIS
Definition: tulipreg.h:513
struct interrupt irq
Definition: dev_dec21143.cc:79
struct cpu ** cpus
Definition: machine.h:140
#define TULIP_ROM_IL_SELECT_CONN_TYPE
Definition: tulipreg.h:328
#define DEV_RAM_MIRROR
Definition: devices.h:365
int srom_opcode_has_started
Definition: dev_dec21143.cc:93
#define OPMODE_PCS
Definition: tulipreg.h:640
#define TULIP_ROM_MB_21142_MII
Definition: tulipreg.h:380
#define MIIROM_BR
Definition: tulipreg.h:691
int net_ethernet_rx(struct net *net, void *extra, unsigned char **packetp, int *lenp)
Definition: net.cc:316
struct emul * emul
Definition: machine.h:99
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
Definition: net.cc:598
#define PHYSICAL
Definition: memory.h:126
#define CSR_STATUS
Definition: tulipreg.h:489
#define MIIROM_SROMSK
Definition: tulipreg.h:686
#define TDCTL_Tx_LS
Definition: tulipreg.h:241
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
#define OPMODE_HBD
Definition: tulipreg.h:627
unsigned char * cur_rx_buf
#define TDCTL_Tx_SET
Definition: tulipreg.h:244
#define BMSR_100TXFDX
Definition: mii.h:73
u_short data
Definition: siireg.h:79
#define OPMODE_SR
Definition: tulipreg.h:589
int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)
Definition: net.h:119
void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length, int mode, uint64_t otheraddress, const char *name)
Definition: dev_ram.cc:134
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
#define STATUS_TU
Definition: tulipreg.h:492
#define CSR_BUSMODE
Definition: tulipreg.h:427
#define MIIROM_SROMDI
Definition: tulipreg.h:687
#define STATUS_RU
Definition: tulipreg.h:499
void net_generate_unique_mac(struct machine *, unsigned char *macbuf)
Definition: net_misc.cc:88
#define MEM_WRITE
Definition: memory.h:117
uint64_t cur_tx_addr
#define BUSMODE_SWR
Definition: tulipreg.h:428
#define OPMODE_SCR
Definition: tulipreg.h:641
#define MIIROM_SROMDO
Definition: tulipreg.h:688
#define TDCTL_CH
Definition: tulipreg.h:235
#define TDCTL_ER
Definition: tulipreg.h:234
#define CSR_INTEN
Definition: tulipreg.h:661
#define CSR_MIIROM
Definition: tulipreg.h:680
Definition: device.h:40
#define TDSTAT_Tx_TO
Definition: tulipreg.h:212
#define CSR_SIATXRX
Definition: tulipreg.h:818
#define MIIROM_MIIDIR
Definition: tulipreg.h:697
#define TULIP_ROM_CHIP_COUNT
Definition: tulipreg.h:321
#define TDSTAT_Tx_LO
Definition: tulipreg.h:213
#define CSR_TXLIST
Definition: tulipreg.h:486
#define MII_BMSR
Definition: mii.h:71
int net_ethernet_rx_avail(struct net *net, void *extra)
Definition: net.cc:253
uint32_t addr
#define MIIROM_MDI
Definition: tulipreg.h:700
#define debug
Definition: dev_adb.cc:57
#define DEC21143_TICK_SHIFT
Definition: dev_dec21143.cc:73
#define STATUS_AIS
Definition: tulipreg.h:512
#define BMSR_LINK
Definition: mii.h:84
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
struct machine * machine
Definition: device.h:41
#define TDSTAT_Rx_TL
Definition: tulipreg.h:192
#define NO_EXCEPTIONS
Definition: memory.h:125
#define CSR_SIACONN
Definition: tulipreg.h:786
#define OPMODE_FD
Definition: tulipreg.h:603
DEVICE_TICK(dec21143)
#define TDCTL_SIZE2
Definition: tulipreg.h:231
#define MII_COMMAND_READ
Definition: mii.h:49
uint16_t mii_phy_reg[MII_NPHY *32]
Definition: dev_dec21143.cc:97
#define DEV_RAM_MIGHT_POINT_TO_DEVICES
Definition: devices.h:366
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
#define STATUS_TPS
Definition: tulipreg.h:491
#define BMSR_10TFDX
Definition: mii.h:75
#define TULIP_ROM_MB_MEDIA_100TX
Definition: tulipreg.h:356
#define N_REGS
Definition: dev_dec21143.cc:75
#define CSR_SIASTAT
Definition: tulipreg.h:740
DEVINIT(dec21143)
#define TULIP_ROM_CHIPn_DEVICE_NUMBER(n)
Definition: tulipreg.h:323
#define TDSTAT_Tx_LC
Definition: tulipreg.h:215
#define OPMODE_ST
Definition: tulipreg.h:609
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 MII_COMMAND_WRITE
Definition: mii.h:50
#define TDSTAT_Rx_LS
Definition: tulipreg.h:191
#define CSR_TXPOLL
Definition: tulipreg.h:473
struct net * net
Definition: emul.h:43
#define MII_STATE_A
#define TULIP_ROM_IL_MEDIAn_BLOCK_BASE
Definition: tulipreg.h:330
#define SIASTAT_ANS_FLPGOOD
Definition: tulipreg.h:776
#define MII_STATE_IDLE
DEVICE_ACCESS(dec21143)
#define OPMODE_PS
Definition: tulipreg.h:624
#define TULIP_ROM_MB_21142_SIA
Definition: tulipreg.h:379
#define BMSR_ACOMP
Definition: mii.h:81
#define TULIP_SROM_OPC_READ
Definition: tulipreg.h:715
addr & if(addr >=0x24 &&page !=NULL)
uint64_t addr
Definition: device.h:46
uint8_t srom[1<<(ROM_WIDTH+1)]
Definition: dev_dec21143.cc:90
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
#define CSR_MISSED
Definition: tulipreg.h:666
#define CSR_OPMODE
Definition: tulipreg.h:587
#define ROM_WIDTH
Definition: dev_dec21143.cc:76
uint64_t cur_rx_addr
#define BMSR_ANEG
Definition: mii.h:83
uint32_t reg[N_REGS]
#define MIIROM_MDC
Definition: tulipreg.h:695
#define MII_STATE_START_WAIT
#define TDCTL_Tx_FS
Definition: tulipreg.h:242
#define TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(n)
Definition: tulipreg.h:324
#define TULIP_ROM_IL_MEDIA_COUNT
Definition: tulipreg.h:329
#define TDSTAT_Rx_FS
Definition: tulipreg.h:190
#define TULIP_ROM_IEEE_NETWORK_ADDRESS
Definition: tulipreg.h:322
#define MII_STATE_RESET
#define CSR_SIAGEN
Definition: tulipreg.h:848
char * interrupt_path
Definition: device.h:50
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
#define OPMODE_SF
Definition: tulipreg.h:633

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