⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etherdev.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -