/[gxemul]/trunk/src/devices/dev_dec21143.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_dec21143.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_dec21143.c,v 1.16 2005/11/25 03:52:55 debug Exp $   *  $Id: dev_dec21143.c,v 1.24 2006/02/09 20:02:59 debug Exp $
29   *   *
30   *  DEC 21143 ("Tulip") ethernet controller. Implemented from Intel document   *  DEC 21143 ("Tulip") ethernet controller. Implemented from Intel document
31   *  278074-001 ("21143 PC/CardBus 10/100Mb/s Ethernet LAN Controller") and by   *  278074-001 ("21143 PC/CardBus 10/100Mb/s Ethernet LAN Controller") and by
32   *  reverse-engineering OpenBSD and NetBSD sources.   *  reverse-engineering OpenBSD and NetBSD 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   *   *
  *  TODO:  
43   *   *
44   *      o)  Endianness for descriptors...   *  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>  #include <stdio.h>
# Line 117  struct dec21143_data { Line 130  struct dec21143_data {
130    
131  /*  /*
132   *  dec21143_rx():   *  dec21143_rx():
133     *
134     *  Receive a packet. (If there is no current packet, then check for newly
135     *  arrived ones. If the current packet couldn't be fully transfered the
136     *  last time, then continue on that packet.)
137   */   */
138  int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)  int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)
139  {  {
# Line 135  int dec21143_rx(struct cpu *cpu, struct Line 152  int dec21143_rx(struct cpu *cpu, struct
152                  net_ethernet_rx(d->net, d, &d->cur_rx_buf,                  net_ethernet_rx(d->net, d, &d->cur_rx_buf,
153                      &d->cur_rx_buf_len);                      &d->cur_rx_buf_len);
154    
155                    /*  Append a 4 byte CRC:  */
156                    d->cur_rx_buf_len += 4;
157                    d->cur_rx_buf = realloc(d->cur_rx_buf, d->cur_rx_buf_len);
158                    if (d->cur_rx_buf == NULL) {
159                            fatal("dec21143_rx(): out of memory\n");
160                            exit(1);
161                    }
162                    /*  Well... the CRC is just zeros, for now.  */
163                    memset(d->cur_rx_buf + d->cur_rx_buf_len - 4, 0, 4);
164    
165                  d->cur_rx_offset = 0;                  d->cur_rx_offset = 0;
166          }          }
167    
168          /*  fatal("{ dec21143_rx: base = 0x%08x }\n", (int)addr);  */          /*  fatal("{ dec21143_rx: base = 0x%08x }\n", (int)addr);  */
169            addr &= 0x7fffffff;
170    
171          if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),          if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
172              MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {              MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
# Line 181  int dec21143_rx(struct cpu *cpu, struct Line 209  int dec21143_rx(struct cpu *cpu, struct
209                          d->cur_rx_addr += 4 * sizeof(uint32_t);                          d->cur_rx_addr += 4 * sizeof(uint32_t);
210          }          }
211    
212          /*  fatal("{ RX (%llx): %08x %08x %x %x: buf %i bytes at 0x%x }\n",          debug("{ RX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
213              (long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize,              (long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize, (int)bufaddr);
214              (int)bufaddr);  */          bufaddr &= 0x7fffffff;
215    
216          /*  Turn off all status bits, and give up ownership:  */          /*  Turn off all status bits, and give up ownership:  */
217          rdes0 = 0x00000000;          rdes0 = 0x00000000;
# Line 210  int dec21143_rx(struct cpu *cpu, struct Line 238  int dec21143_rx(struct cpu *cpu, struct
238          if (d->cur_rx_offset >= d->cur_rx_buf_len) {          if (d->cur_rx_offset >= d->cur_rx_buf_len) {
239                  rdes0 |= TDSTAT_Rx_LS;                  rdes0 |= TDSTAT_Rx_LS;
240    
241                  /*  Frame len, which includes the size of a 4-byte CRC:  */                  /*  Set the frame length:  */
242                  rdes0 |= ((d->cur_rx_buf_len + 4) << 16) & TDSTAT_Rx_FL;                  rdes0 |= (d->cur_rx_buf_len << 16) & TDSTAT_Rx_FL;
243    
244                  /*  Frame too long? (1518 is max ethernet frame length)  */                  /*  Frame too long? (1518 is max ethernet frame length)  */
245                  if (d->cur_rx_buf_len > 1518)                  if (d->cur_rx_buf_len > 1518)
# Line 249  int dec21143_rx(struct cpu *cpu, struct Line 277  int dec21143_rx(struct cpu *cpu, struct
277    
278  /*  /*
279   *  dec21143_tx():   *  dec21143_tx():
280     *
281     *  Transmit a packet, if the guest OS has marked a descriptor as containing
282     *  data to transmit.
283   */   */
284  int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)  int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)
285  {  {
# Line 257  int dec21143_tx(struct cpu *cpu, struct Line 288  int dec21143_tx(struct cpu *cpu, struct
288          uint32_t tdes0, tdes1, tdes2, tdes3;          uint32_t tdes0, tdes1, tdes2, tdes3;
289          int bufsize, buf1_size, buf2_size, i, writeback_len = 4;          int bufsize, buf1_size, buf2_size, i, writeback_len = 4;
290    
291          /*  fatal("{ dec21143_tx: base = 0x%08x }\n", (int)addr);  */          addr &= 0x7fffffff;
292    
293          if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),          if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
294              MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {              MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
# Line 267  int dec21143_tx(struct cpu *cpu, struct Line 298  int dec21143_tx(struct cpu *cpu, struct
298    
299          tdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);          tdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
300    
301            /*  fatal("{ dec21143_tx: base=0x%08x, tdes0=0x%08x }\n",
302                (int)addr, (int)tdes0);  */
303    
304          /*  Only process packets owned by the 21143:  */          /*  Only process packets owned by the 21143:  */
305          if (!(tdes0 & TDSTAT_OWN)) {          if (!(tdes0 & TDSTAT_OWN)) {
306                  if (d->tx_idling > d->tx_idling_threshold) {                  if (d->tx_idling > d->tx_idling_threshold) {
# Line 304  int dec21143_tx(struct cpu *cpu, struct Line 338  int dec21143_tx(struct cpu *cpu, struct
338                          d->cur_tx_addr += 4 * sizeof(uint32_t);                          d->cur_tx_addr += 4 * sizeof(uint32_t);
339          }          }
340    
341          /*  fatal("{ TX (%llx): %08x %08x %x %x: buf %i bytes at 0x%x }\n",          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,              (long long)addr, tdes0, tdes1, tdes2, tdes3, bufsize, (int)bufaddr);
343              (int)bufaddr); */          bufaddr &= 0x7fffffff;
344    
345          /*  Assume no error:  */          /*  Assume no error:  */
346          tdes0 &= ~ (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC          tdes0 &= ~ (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
# Line 379  int dec21143_tx(struct cpu *cpu, struct Line 413  int dec21143_tx(struct cpu *cpu, struct
413                          d->cur_tx_buf = NULL;                          d->cur_tx_buf = NULL;
414                          d->cur_tx_buf_len = 0;                          d->cur_tx_buf_len = 0;
415    
416                            /*  TODO: Shouldn't the OWN bit be cleared on all
417                                kinds of segments, not just the Last?  */
418    
419                          /*  We are done.  */                          /*  We are done.  */
420                          tdes0 &= ~TDSTAT_OWN;                          tdes0 &= ~TDSTAT_OWN;
421                          writeback_len = 1;                          writeback_len = 1;
# Line 621  static void mii_access(struct cpu *cpu, Line 658  static void mii_access(struct cpu *cpu,
658   *   *
659   *  This function handles reads from the Ethernet Address ROM. This is not a   *  This function handles reads from the Ethernet Address ROM. This is not a
660   *  100% correct implementation, as it was reverse-engineered from OpenBSD   *  100% correct implementation, as it was reverse-engineered from OpenBSD
661   *  sources; it seems to work with OpenBSD, NetBSD, and Linux.   *  sources; it seems to work with OpenBSD, NetBSD, and Linux, though.
662   *   *
663   *  Each transfer (if I understood this correctly) is of the following format:   *  Each transfer (if I understood this correctly) is of the following format:
664   *   *
# Line 785  static void dec21143_reset(struct cpu *c Line 822  static void dec21143_reset(struct cpu *c
822  /*  /*
823   *  dev_dec21143_access():   *  dev_dec21143_access():
824   */   */
825  int dev_dec21143_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(dec21143)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
826  {  {
827          struct dec21143_data *d = extra;          struct dec21143_data *d = extra;
828          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
# Line 893  int dev_dec21143_access(struct cpu *cpu, Line 928  int dev_dec21143_access(struct cpu *cpu,
928                                  d->reg[CSR_STATUS/8] &= ~STATUS_RS;                                  d->reg[CSR_STATUS/8] &= ~STATUS_RS;
929                          }                          }
930                          idata &= ~(OPMODE_HBD | OPMODE_SCR | OPMODE_PCS                          idata &= ~(OPMODE_HBD | OPMODE_SCR | OPMODE_PCS
931                              | OPMODE_PS | OPMODE_SF | OPMODE_TTM);                              | OPMODE_PS | OPMODE_SF | OPMODE_TTM | OPMODE_FD);
932                          if (idata & OPMODE_PNIC_IT) {                          if (idata & OPMODE_PNIC_IT) {
933                                  idata &= ~OPMODE_PNIC_IT;                                  idata &= ~OPMODE_PNIC_IT;
934                                  d->tx_idling = d->tx_idling_threshold;                                  d->tx_idling = d->tx_idling_threshold;
# Line 948  int dev_dec21143_access(struct cpu *cpu, Line 983  int dev_dec21143_access(struct cpu *cpu,
983  }  }
984    
985    
986  /*  DEVINIT(dec21143)
  *  devinit_dec21143():  
  */  
 int devinit_dec21143(struct devinit *devinit)  
987  {  {
988          struct dec21143_data *d;          struct dec21143_data *d;
989          char name2[100];          char name2[100];

Legend:
Removed from v.20  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26