📄 etherdev.c
字号:
/* etherdev.c: This code supports some basic ethernet device-specific stuff. This is a hack from Motorola dbug code, primarily fec.c. General notice: This code is part of a boot-monitor package developed as a generic base platform for embedded system designs. As such, it is likely to be distributed to various projects beyond the control of the original author. Please notify the author of any enhancements made or bugs found so that all may benefit from the changes. In addition, notification back to the author will allow the new user to pick up changes that may have been made by other users after this version of the code was distributed. Author: Ed Sutter email: esutter@lucent.com (home: lesutter@worldnet.att.net) phone: 908-582-2351 (home: 908-889-5161)*/#include "config.h"#if INCLUDE_ETHERNET#include "cpuio.h"#include "ether.h"#include "genlib.h"#include "stddefs.h"#include "mcf5272.h"#include "nbuf.h"int EtherPollActive;extern char *Etheradd, *IPadd; /* Pointer to ascii addresses */extern uchar BinIpAddr[]; /* Space for binary addresses */extern uchar BinEnetAddr[]; /* Only 6 bytes used. */extern int EtherVerbose; /* Verbosity flag. */extern int EtherIsActive; /* Non-zero if ethernet is up. */int eninit(void);voidShowEtherdevStats(){ printf("EtherIsActive = %d\n",EtherIsActive);}intEtherdevStartup(int verbose){ /* Initialize device-specific error counters... */ /* Initialize descriptors and their buffers */ nbuf_init(); /* Put ethernet controller in reset: */ enreset(); /* Initialize controller: */ eninit(); return(0);}/* DisableEtherdev(): * Put the ethernet chip in powerdown state. */voidDisableEtherdev(){ MCF5272_IMM *imm = mcf5272_get_immp(); enreset(); /* Set the Graceful Transmit Stop bit */ MCF5272_WR_FEC_TCR(imm, MCF5272_RD_FEC_TCR(imm) | MCF5272_FEC_TCR_GTS); /* Wait for the current transmission to complete */ while ( !(MCF5272_RD_FEC_EIR(imm) & MCF5272_FEC_EIR_GRA)) ; /* Clear the GRA event */ MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_EIR_GRA); /* Disable the FEC */ MCF5272_WR_FEC_ECR(imm,0); /* Disable all FEC interrupts by clearing the IMR register */ MCF5272_WR_FEC_IMR(imm,0); /* Clear the GTS bit so frames can be tranmitted when restarted */ MCF5272_WR_FEC_TCR(imm, MCF5272_RD_FEC_TCR(imm) & ~MCF5272_FEC_TCR_GTS);}/* pollethernet(): * If the interface is active, poll for incoming packets. Return * the number of packets processed. * Hacked from fec_receive(). */intpolletherdev(){ int pcnt = 0; NBUF *pNbuf; struct ether_header *ethrhdr;#if 0 MCF5272_IMM *imm = mcf5272_get_immp(); if (MCF5272_RD_FEC_EIR(imm) & MCF5272_FEC_EIR_RXF) { MCF5272_WR_FEC_EIR(imm,MCF5272_FEC_EIR_RXF);#endif while(nbuf_rx_next_ready()) { /* Get the next buffer received by the FEC */ pNbuf = nbuf_rx_allocate(); if (pNbuf == NULL) { printf("rx_allocate1 failed\n"); return(pcnt); } /************************************************************ The size of the Rx Buffers is set so that every frame addressed to me should fit in one buffer. Therefore, the L bit should be set on every buffer received. *************************************************************/ if (!(pNbuf->status & RX_BD_L)) { do { /* Free the current buffer */ nbuf_rx_release(pNbuf); /* Get the next buffer of this frame */ pNbuf = nbuf_rx_allocate(); if (pNbuf == NULL) { printf("rx_allocate2 failed\n"); return(pcnt); } /* Keep going until we find the last one */ } while (!(pNbuf->status & RX_BD_L)); /* Free the last buffer of this frame */ nbuf_rx_release(pNbuf); return(pcnt); } /* Point to the ethernet header of this packet */ ethrhdr = (struct ether_header *)pNbuf->data; /* Adjust the length by the ethernet header size */ pNbuf->length -= (4 + 6 + 6 + 2); /* Call the appriopriate handler */ processPACKET(ethrhdr, pNbuf->length); /************************************************************ Higher level protocols must save off the data if they need to keep it around for processing. The buffers are freed here to ensure that the circular buffer descriptor ring is maintained properly. *************************************************************/ nbuf_rx_release(pNbuf); pcnt++; }#if 0 } /* Clear interrupt from EIR register */ MCF5272_WR_FEC_EIR(imm,MCF5272_FEC_EIR_RXF);#endif return(pcnt);}/* reset the ethernet chip and associated data structures. * In the original fec.c source file, this was fec_reset() */voidenreset(){ MCF5272_IMM *imm = mcf5272_get_immp(); /* Reset the FEC - equivalent to a hard reset */ MCF5272_WR_FEC_ECR(imm,MCF5272_FEC_ECR_RESET); /* Wait for the reset sequence to complete */ while (MCF5272_RD_FEC_ECR(imm) & MCF5272_FEC_ECR_RESET); /* Disable all FEC interrupts by clearing the IMR register */ MCF5272_WR_FEC_IMR(imm,0); /* Clear any interrupts by setting all bits in the EIR register */ MCF5272_WR_FEC_EIR(imm,0xFFFFFFFF);}/* eninit(): * Init ethernet... * And enable xmit/receive. * If self-test fails, return -1. */inteninit(void){ MCF5272_IMM *imm = mcf5272_get_immp(); /* Set the source address for the controller */ MCF5272_WR_FEC_MALR(imm,0 | (BinEnetAddr[0] <<24) | (BinEnetAddr[1] <<16) | (BinEnetAddr[2] <<8) | (BinEnetAddr[3] <<0)); MCF5272_WR_FEC_MAUR(imm,0 | (BinEnetAddr[4] <<24) | (BinEnetAddr[5] <<16)); /* Initialize the hash table registers */ MCF5272_WR_FEC_HTUR(imm,0); MCF5272_WR_FEC_HTLR(imm,0); /* Set Receive Buffer Size */ MCF5272_WR_FEC_EMRBR(imm, (uint16)RX_BUFFER_SIZE); /* Point to the start of the circular Rx buffer descriptor queue */ MCF5272_WR_FEC_ERDSR(imm, nbuf_get_start(Rx)); /* Point to the start of the circular Tx buffer descriptor queue */ MCF5272_WR_FEC_ETDSR(imm, nbuf_get_start(Tx)); /* Set the tranceiver interface to MII mode */ MCF5272_WR_FEC_RCR(imm, 0 | MCF5272_FEC_RCR_MII_MODE); /* | MCF5272_FEC_RCR_DRT); half duplex */ /* Only operate in half-duplex, no heart beat control */ MCF5272_WR_FEC_TCR(imm, 0); /* Enable FEC */ MCF5272_WR_FEC_ECR(imm, MCF5272_FEC_ECR_ETHER_EN); /* Allow interrupts by setting IMR register */ MCF5272_WR_FEC_IMR(imm, MCF5272_FEC_IMR_RXFEN); /* Indicate that there have been empty receive buffers produced */ MCF5272_WR_FEC_RDAR(imm,1); return(0);}/* enselftest(): * Return 1 if passed, else -1. */intenselftest(int verbose){ return(1);}/* enlbktest(): * Return 1 if passed, else -1. */intenlbktest(int verbose){ return(1);}/* geteinbuf(): * Get ethernet input buffer... * Pull packet out of device and call processPACKET(). * Increment EtherRFRAMECnt for each packet received. * * Note: Don't do anything that would cause geteinbuf() to * be called recursively (including printf) until the buffer * is passed back to the NIC, or strange things will happen. */intgeteinbuf(){ int cnt = 0; return(cnt);}NBUF *Xbuf;/* getXmitBuffer(): * Return to the caller a pointer of memory space that will ultimatley * be populated with a full ethernet packet.*/uchar *getXmitBuffer(){ Xbuf = nbuf_tx_allocate(); return(Xbuf->data);}intsendBuffer(int length){ MCF5272_IMM *imm = mcf5272_get_immp(); if (length < 64) length = 64; if (EtherVerbose & SHOW_OUTGOING) printPkt((struct ether_header *)Xbuf->data,length,ETHER_OUTGOING); Xbuf->length = length; /* Set Frame ready for transmit */ Xbuf->status |= TX_BD_R; /* Mark the buffer as not in use */ nbuf_tx_release(Xbuf); /* Indicate that there has been a transmit buffer produced */ MCF5272_WR_FEC_TDAR(imm,1); /* The hardware will mark the buffer as empty once it's transmitted */ EtherXFRAMECnt++; return(length);}voiddisableBroadcastReception(){}voidenableBroadcastReception(){}voidenablePromiscuousReception(){}voiddisablePromiscuousReception(){}char *extGetIpAdd(){ return((char *)0);}char *extGetEtherAdd(){ return((char *)0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -