📄 etherdev.c
字号:
/* etherdev.c: This file, along with common/ethernet.c supports the ethernet interface. It is the lowest layer of code supporting the monitor's IP, ICMP & UDP services. This file is specific to one particular ethernet device and provides the hooks needed by common/ethernet.c to initialize, and transmit/receive packets in a polled environment. The common vs device-specific code is generally noted by a naming convention where ...Ethernet... is common and ...Etherdev... is device- specific. 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 "smc91c94.h"#include "cpuio.h"#include "ether.h"#include "stddefs.h"#include "genlib.h"#define INCLUDE_FDUMP 0#define USE_AUTORELEASE 1static int EtherRXOVRNCnt;static int EtherALGNERRCnt, EtherBADCRCCnt, EtherTOOLONGCnt;static int EtherTOOSHORTCnt, EtherWFATMTCnt, EtherWFTTMTCnt;ushort smcBank;static ulong Ercvbuf[400]; /* Ethernet receive buffer word aligned */static ulong Exmtbuf[400]; /* Ethernet transmit buffer word aligned *//* 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(){ showSmcRevision(); printf("Receiver overrun errors: %d\n",EtherRXOVRNCnt); printf("Alignment errors: %d\n",EtherALGNERRCnt); printf("Bad CRC errors: %d\n",EtherBADCRCCnt); printf("Packet too long errors: %d\n",EtherTOOLONGCnt); printf("Packet too short errors: %d\n",EtherTOOSHORTCnt); printf("Wait-for-alloc timeouts: %d\n",EtherWFATMTCnt); printf("Wait-for-xmit timeouts: %d\n",EtherWFTTMTCnt);}/* smcRead() & smcWrite(): Interface functions used to access the SMC chip. Note that the function is wrapped around a critical section because the bank selection and register read/modification should be atomic.*/ushortsmcRead(int smcreg){ ushort reg; /* Set up the appropriate bank: */ if (smcBank != (smcreg & SMCBANKMASK)) { *(vushort *)(SMCADDR + SMCBSR) &= ~SMCBANKMASK; *(vushort *)(SMCADDR + SMCBSR) |= ((ushort)smcreg & SMCBANKMASK); smcBank = smcreg & SMCBANKMASK; } /* Retrieve the register value: */ reg = (*(vushort *)(SMCADDR + (smcreg & ~SMCBANKMASK))); return(reg);}ucharsmcReadByte(int smcreg){ uchar reg; /* Set up the appropriate bank: */ if (smcBank != (smcreg & SMCBANKMASK)) { *(vushort *)(SMCADDR + SMCBSR) &= ~SMCBANKMASK; *(vushort *)(SMCADDR + SMCBSR) |= ((ushort)smcreg & SMCBANKMASK); smcBank = smcreg & SMCBANKMASK; } if (!(smcreg & 1)) smcreg |= 0x10000; /* For even byte access, set a17 */ /* Retrieve the register value: */ reg = (*(vuchar *)(SMCADDR + (smcreg & ~SMCBANKMASK))); return(reg);}voidsmcWrite(int smcreg, ushort value){ /* Set up the appropriate bank: */ if (smcBank != (smcreg & SMCBANKMASK)) { *(vushort *)(SMCADDR + SMCBSR) &= ~SMCBANKMASK; *(vushort *)(SMCADDR + SMCBSR) |= ((ushort)smcreg & SMCBANKMASK); smcBank = smcreg & SMCBANKMASK; } /* Put value to the register: */ *(vushort *)(SMCADDR + (smcreg & ~SMCBANKMASK)) = value;}voidsmcWriteByte(int smcreg, uchar value){ /* Set up the appropriate bank: */ if (smcBank != (smcreg & SMCBANKMASK)) { *(vushort *)(SMCADDR + SMCBSR) &= ~SMCBANKMASK; *(vushort *)(SMCADDR + SMCBSR) |= ((ushort)smcreg & SMCBANKMASK); smcBank = smcreg & SMCBANKMASK; } if (!(smcreg & 1)) smcreg |= 0x10000; /* Put value to the register: */ *(vuchar *)(SMCADDR + (smcreg & ~SMCBANKMASK)) = value;}/* BankSelect(): Establish the active register bank, and return the old active register bank.*/intbankSelect(int bank){ int oldbank; oldbank = (int)((*(vushort *)(SMCBSR) >> 8) & 7); *(vushort *)(SMCBSR) &= ~0x0700; *(vushort *)(SMCBSR) |= (ushort)((bank & 7) << 8); return(oldbank);}voidshowSmcRevision(void){ ushort revid; char *chip; revid = smcRead(SMCREV); switch(revid & 0xf000) { case LAN91C90_92: chip = "91C90/92"; break; case LAN91C94_96: if ((revid & 0x0f00) < 0x0600) chip = "91C94"; else chip = "91C96"; break; case LAN91C95: chip = "91C95"; break; case LAN91C100: chip = "91C100"; break; case LAN91C100FD: chip = "91C100FD"; break; default: chip = 0; break; } if (chip) printf("SMC Part: %s, rev %d\n",chip,(revid & 0x0f00) >> 8); else printf("SMC RevID: %04x\n",revid & 0x0f00);}/* EtherdevStartup(): Called by EthernetStartup(). Initialize all device-specific counters, reset and initialized the ethernet device.*/intEtherdevStartup(int verbose){ int eninit(); /* Initialize device-driver counters: */ EtherRXOVRNCnt = 0; EtherALGNERRCnt = 0; EtherBADCRCCnt = 0; EtherTOOLONGCnt = 0; EtherTOOSHORTCnt = 0; EtherWFATMTCnt = 0; /* Put ethernet controller in reset: */ enreset(); /* Initialize controller: */ eninit(); /* Enable transceiver: */ smcWrite(SMCTCR,smcRead(SMCTCR) | TXENA); smcWrite(SMCRCR,smcRead(SMCRCR) | RXEN); return(0);}/* enselftest(): Return 1 if passed, else -1.*/intenselftest(int verbose){ if (verbose) printf("Self test not available\n"); return(1);}/* DisableEtherdev(): Called by DisableEthernet() to do the device-specific portion of the turn-down.*/voidDisableEtherdev(){ enreset();}voidDisableErcv(){ smcWrite(SMCRCR,smcRead(SMCRCR) & ~RXEN);}voidEnableErcv(){ smcWrite(SMCRCR,smcRead(SMCRCR) | RXEN);}voidenresetmmu(){ smcWrite(SMCMMUCMD,MMUCMD_RESETMMU);}voidenreset(){ /* Reset the device: */ smcWrite(SMCRCR,SOFT_RST); smcWrite(SMCRCR,0); /* Reset MMU and TX fifos: */ smcWrite(SMCMMUCMD,MMUCMD_RESETMMU); smcWrite(SMCMMUCMD,MMUCMD_RESETTXFIFOS);}inteninit(){ smcBank = SMCBANKNULL; smcWrite(SMCTCR,PAD_EN|FDUPLX); smcWrite(SMCRCR,FILT_CAR|STRIP_CRC); smcWrite(SMCCONFIG,0); /* Reserve 1.5K for Xmit... */ smcWrite(SMCMCR,0x0600); /* Store the ethernet address. */ smcWrite(SMCIA01,*(ushort *)BinEnetAddr); smcWrite(SMCIA23,*(ushort *)&BinEnetAddr[2]); smcWrite(SMCIA45,*(ushort *)&BinEnetAddr[4]);#if USE_AUTORELEASE smcWrite(SMCCTRL,smcRead(SMCCTRL) | AUTO_REL);#else smcWrite(SMCCTRL,smcRead(SMCCTRL));#endif return(0);}/* geteinbuf(): Retrieve the incoming ethernet packet. The first word of the packet is receive frame status word, the second is the byte count of the incoming frame. Incoming data format: WORD1: Receive Frame Status Word (RFSW). WORD2: Byte count (includes RFSW, bytecount, data and control).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -