📄 etherdev.c
字号:
/* etherdev.c: * This code supports some basic ethernet device-specific stuff for the * 68EN302 processor. * * 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"int EtherRLCnt, EtherDEFCnt, EtherLCCnt;int EtherXFRAMECnt, EtherRFRAMECnt, EtherDRVRETRYCnt;struct snoopinfo snoopInfo;ushort ArCtrl; /* Address recognition reg */static ulong xbuf[XBUFCNT][400]; /* Transmit & receive buffers pointed */static ulong rbuf[RBUFCNT][400]; /* to by the buffer descriptors. */int geteinbuf(void);/* struct ebd: * Structure used to overlay onto the ethernet buffer descriptors: */struct ebd { ushort flags; ushort length; ushort ptrhi; ushort ptrlo;} *rbptr, *xbptr;/* ShowEtherdevStats(): * Called by the command "ether stat" on the monitor's command line. * This function and a common ShowEthernetStats() are used to dump * generic as well as device-specific ethernet driver statistics. */voidShowEtherdevStats(){ printf("Driver retry count: %d\n",EtherDRVRETRYCnt); printf("Retry_count_exceeded: %d times\n",EtherRLCnt); printf("Late-collision count: %d\n",EtherLCCnt); printf("Defer-indication count: %d\n",EtherDEFCnt); printf("Transmitted frames: %d\n",EtherXFRAMECnt); printf("Received frames: %d\n",EtherRFRAMECnt); printf("IP hdr cksum errors: %d\n",EtherIPERRCnt); printf("UDP pkt cksum errors: %d\n",EtherUDPERRCnt); if (snoopInfo.on) { char smac[32]; EtherToString(snoopInfo.mac,smac); printf("Snoop MAC: %s\n",smac); }}intEtherdevStartup(int verbose){ int eninit(); EtherRLCnt = 0; EtherLCCnt = 0; EtherDEFCnt = 0; EtherXFRAMECnt = 0; EtherRFRAMECnt = 0; EtherDRVRETRYCnt = 0; snoopInfo.on = 0; /* Put ethernet controller in reset: */ enreset(); /* Initialize controller: */ eninit(); /* Enable all ethernet ctrlr interrupts: */ *(ushort *)INTR_MASK = 0x07ff; /* Enable the controller: */ *(ushort *)ECNTRL = 3; return(0);}voidDisableEtherdev(void){ enreset();}/* pollethernet(): * If the interface is active, poll for incoming packets. Return * the number of packets processed. */intpolletherdev(void){ ushort event; int pcnt=0; event = *(ushort *)INTR_EVENT; *(ushort *)INTR_EVENT = event; if (event & RFINT) { /* Received frame interrupt */ pcnt++; geteinbuf(); } return(pcnt);}voidenreset(void){ /* Reset the controller, but leave it disabled: */ *(ushort *)ECNTRL = 0; *(ushort *)ECNTRL = 1;#if SYSTEM_PPAFAXROUTER /* Reset the transceiver also: */ pioset('b',11); pioclr('b',11);#endif}inteninit(void){ uchar *cam; struct ebd *bdp; int i; /* Ethernet DMA config: */ /* BDSIZE=01 (16x & 112r) */ *(ushort *)EDMA = 0x000b | (BDSIZE); /* Maximum receive buffer length is 1518. */ *(ushort *)EMRBLR = 0x05ee; /* Use interrupt vector 224. */ *(ushort *)INTR_VECT = 0x00e0; *(ushort *)ECNFIG = 0x0000; /* Self test using ETHER_TEST... */ *(ushort *)ETHER_TEST = 0x0080; for(i=0;i<50000;i++) if ((*(ushort *)ETHER_TEST & 0x0080) == 0) break; if (i == 50000) { printf("Ethernet random number test failed\n"); return(-1); } /* Set address recognition control based on command line input. */ *(ushort *)AR_CNTRL = ArCtrl; /* Initialize Buffer Descriptors: */ bdp = (struct ebd *)EBD; xbptr = (struct ebd *)XBDBASE; rbptr = (struct ebd *)RBDBASE; /* Of the total 128 buffer descriptors available, only */ /* XBUFCNT + RBUFCNT are used here... */ for (bdp = xbptr,i=0;i<XBUFCNT;i++,bdp++) { bdp->flags = 0; bdp->length = 0; bdp->ptrhi = ((ushort)((ulong)(xbuf[i]) >> 16) & 0x00ff); bdp->ptrlo = (ushort)((ulong)xbuf[i] & 0xffff); if (i == (XBUFCNT-1)) bdp->flags |= WRAPBIT; /* Set WRAP bit on final BD */ } for(bdp = rbptr,i=0;i<RBUFCNT;i++,bdp++) { bdp->flags = 0x8000; bdp->length = 0; bdp->ptrhi = ((ushort)((ulong)(rbuf[i]) >> 16) & 0x00ff); bdp->ptrlo = (ushort)((ulong)rbuf[i] & 0xffff); if (i == (RBUFCNT-1)) bdp->flags |= WRAPBIT; /* Set WRAP bit on final BD */ } /* Load the CAM with this board's ethernet address. */ cam = (uchar *)CET; *cam++ = BinEnetAddr[0]; *cam++ = BinEnetAddr[1]; *cam++ = BinEnetAddr[2]; *cam++ = BinEnetAddr[3]; *cam++ = BinEnetAddr[4]; *cam++ = BinEnetAddr[5]; return(0);}intgeteinbuf(void){ int cnt, timeout; uchar *dp; struct ebd *rp; cnt = 0; /* Stay in this loop while there is an active receive buffer. */ /* If receive buffer is empty, just return. */ timeout = 100000; while(!(rbptr->flags & 0x8000)) { EtherRFRAMECnt++; /* Extract data ptr from buffer descriptor: */ dp = (uchar *)(((ulong)(rbptr->ptrhi)<<16) & (ulong)0xff0000); dp += (int)(rbptr->ptrlo); processPACKET((struct ether_header *)dp,rbptr->length); /* Make the buffer ready. */ rbptr->flags |= 0x8000; /* If WRAP, then back to top; else, increment to next BD. */ if (rbptr->flags & WRAPBIT) rbptr = (struct ebd *)RBDBASE; else rbptr++; cnt++; }#if 1 /* Make sure no other receive buffers are ready... */ rp = rbptr; timeout=100000; while(timeout > 0) { if (rp->flags & WRAPBIT) rp = (struct ebd *)RBDBASE; else rp++; if (rp == rbptr) break; if (!(rp->flags & 0x8000)) printf("rbptr buffer ready out of order!\n"); timeout--; } if (timeout <= 0) { printf("geteinbuf timeout2\n"); enreset(); EtherIsActive = 0; }#endif return(cnt);}uchar *getXmitBuffer(){ int timeout; uchar *dp; /* Wait for the next buffer descriptor to become available... */ timeout = 100000; while(xbptr->flags & 0x8000) { timeout--; if (timeout <= 0) { printf("getXmitBuffer timeout\n"); enreset(); EtherIsActive = 0; } } /* Extract the data pointer from the buffer descriptor: */ dp = (uchar *)(((ulong)(xbptr->ptrhi) << 16) & (ulong)0x00ff0000); dp += (int)(xbptr->ptrlo); return(dp);}/* sendBuffer(): Set the flag within the current transmit buffer descriptor indicating that it is ready to be transmitted. Then increment the BD pointer to the next buffer descriptor.*/intsendBuffer(int length){ if (EtherVerbose & SHOW_OUTGOING) { uchar *dp; dp = (uchar *)(((ulong)(xbptr->ptrhi) << 16) & (ulong)0xff0000); dp += (int)(xbptr->ptrlo); printPkt((struct ether_header *)dp,length,ETHER_OUTGOING); } /* Make the current transmit buffer ready and populate the length. */ xbptr->length = (ushort)length; xbptr->flags |= 0x8c00; /* If WRAP, then back to top; else, just increment to next BD. */ if (xbptr->flags & WRAPBIT) xbptr = (struct ebd *)XBDBASE; else xbptr++; return(0);}#if 0int_sendBuffer(int length){ int err; ushort flags; if (EtherVerbose & SHOW_OUTGOING) { uchar *dp; dp = (uchar *)(((ulong)(xbptr->ptrhi) << 16) & (ulong)0xff0000); dp += (int)(xbptr->ptrlo); printPkt((struct ether_header *)dp,length,ETHER_OUTGOING); } /* Make the current transmit buffer ready and populate the length. */ xbptr->length = (ushort)length; xbptr->flags |= 0x8c00; /* Wait for packet to be sent, if error, return -1. */ timeout = 100000; while(timeout > 0) { flags = xbptr->flags; if (!(flags & READY)) break; } it (timeout <= 0) { printf("_sendBuffer timeout\n"); enreset(); EtherIsActive = 0; return(-1); } err = 0; /* Keep stats: */ EtherXFRAMECnt++; if (flags & DEF) { EtherDEFCnt++; err = -1; } if (flags & LC) { EtherLCCnt++; err = -1; } if (flags & RL) { EtherRLCnt++; err = -1; } /* If WRAP, then back to top; else, just increment to next BD. */ if (xbptr->flags & WRAPBIT) xbptr = (struct ebd *)XBDBASE; else xbptr++; return(err);}voidsendBufferRetry(int length){ struct ebd *xptr; uchar *dp, *dp1; xptr = xbptr; while(_sendBuffer(length) == -1) { EtherDRVRETRYCnt++; dp = getXmitBuffer(); dp1 = (uchar *)(((ulong)(xptr->ptrhi) << 16) & (ulong)0xff0000); dp1 += (int)(xptr->ptrlo); memcpy(dp,dp1,length); }}#endif/* enselftest(): * Return 1 if passed, else -1. */intenselftest(int verbose){ if (verbose) printf("Self test not available\n"); return(1);}voidenresetmmu(void){}voiddisablePromiscuousReception(){}voidenablePromiscuousReception(){}voiddisableBroadcastReception(){ *(ushort *)AR_CNTRL = ArCtrl | 0x3000; /* Disable bcast rcv. */}voidenableBroadcastReception(){ *(ushort *)AR_CNTRL = ArCtrl; /* Re-enable bcast rcv. */}/* extGetEtherAdd() & extGetIpAdd(): These two functions return a char * to a string that represents an IP or MAC address. If they return NULL, then it is assumed by the calling function that there is no target specific hardware that contains the IP and/or MAC address.*/char *extGetEtherAdd(){ return((char *)0);}char *extGetIpAdd(){ return((char *)0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -