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

📄 etherdev.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 2 页
字号:
        WORDS3->N:  Actual ethernet packet (data).        WORDN+1:    Control byte and possibly last byte of data if odd length.   The length of the incoming packet must be adjusted prior to passing it to   any packet processing....  Deduct 2 for the size of the RFSW, 2 for the   size of the bytecount, 1 for the control byte and one more if the ODD   bit is not set.  If the ODD bit is set, then the byte in the lower half   of the final word is part of the actual packet.*/intgeteinbuf(){    ushort  rfsw, pktsize, count, *data, i;    smcWrite(SMCPOINTER,PTR_RCV|PTR_AUTOINC|PTR_READ);    for(i=0;i<10;i++);                  /* delay necessary between POINTER */                                        /* and DATA access. */    rfsw = smcRead(SMCDATA1);           /* Receive frame status word */    count = smcRead(SMCDATA2);          /* Byte count. */    count = SWAP16(count);    count &= 0x7ff;                     /* Upper 5 bits are reserved. */    count -= 4;                         /* Deduct for RFSW and ByteCount */    if (!(rfsw & RFSW_ODD_LEN))         /* Deduct for CTRL byte and possibly */        pktsize = count - 2;            /* one more because len != odd. */    else        pktsize = count - 1;    data = (ushort *)Ercvbuf;    if (count >= sizeof(Ercvbuf)) {        printf("\007geteinbuf() overflow (cnt=0x%04x)\n",count);        enreset();        eninit();        smcWrite(SMCTCR,smcRead(SMCTCR) | TXENA);        smcWrite(SMCRCR,smcRead(SMCRCR) | RXEN);        return(-1);    }    if (count & 1) count++;    while(count > 0) {        *data++ = smcRead(SMCDATA1);        count -= 2;    }    smcWrite(SMCMMUCMD,MMUCMD_RMRELRXFRAME);    if (rfsw & (ALGN_ERR | BADCRC | TOOLNG | TOOSHORT)) {        if (rfsw & ALGN_ERR) {            EtherALGNERRCnt++;            printf("Frame alignment error!\n");        }        if (rfsw & BADCRC) {            EtherBADCRCCnt++;            printf("Bad CRC!\n");        }        if (rfsw & TOOLNG) {            EtherTOOLONGCnt++;            printf("Frame too long!\n");        }        if (rfsw & TOOSHORT) {            EtherTOOSHORTCnt++;            printf("Frame too short!\n");        }        return(-1);    }    processPACKET((struct ether_header *)Ercvbuf,pktsize);    return(0);}/* polletherdev():    Called by pollethernet() to do the device-specific portion of the    ethernet polling.  This code is the first step in processing incoming    ethernet packets.  If a packet is available, the functino geteinbuf()    (get ethernet input buffer) is called to pass the packet to the higher    level processPACKET() function.    IMPORTANT NOTE:    This function MUST be re-entrant.  There is a possibility that the    processPACKET() function will ultimately call polletherdev() again.    This means that once the packet has been detected in the device, it     is important that this code do whatever is necessary to assure that    the same packet will not be seen as available to the nested caller.    In other words...    clear the packet from the device prior to calling processPACKET().*/intpolletherdev(){    ushort  istat;    int     pcnt;    pcnt = 0;    istat = smcRead(SMCINT);    if (istat & RXOVRN_INT) {        smcWrite(SMCMMUCMD,MMUCMD_RESETMMU);        smcWrite(SMCINT,RXOVRN_INT);        EtherRXOVRNCnt++;    }    else if (istat & RCV_INT) {        while((smcRead(SMCFIFOPORT) & RCVFIFO_EMPTY) == 0) {            EtherRFRAMECnt++;            pcnt++;            geteinbuf();        }    }    /* Enable transceiver: */    smcWrite(SMCTCR,smcRead(SMCTCR) | TXENA);    smcWrite(SMCRCR,smcRead(SMCRCR) | RXEN);    return(pcnt);}/* getXmitBuffer():    Called by various points in the IP/UDP/ICMP code for a buffer that    will ultimately be the next output packet.*/uchar *getXmitBuffer(){    return((uchar *)Exmtbuf);}/* 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 len){    ushort  pnrarr, nbits, *sptr, i;    int     origlen;    ulong   timeout;    if (EtherVerbose &  SHOW_OUTGOING)        printPkt((struct ether_header *)Exmtbuf,len,ETHER_OUTGOING);    origlen = len;    nbits = (ushort)(len >> 8);    if (nbits > 5) {        printf("sendBuffer(): len too long\n");        return(-1);    }    /* Allocate the space and wait for the allocation to succeed. */again:    smcWrite(SMCMMUCMD,MMUCMD_ALLOCTXMEM | SWAP16(nbits));    for(timeout=250000;timeout>0;timeout--) {#if 0        istat = smcRead(SMCINT);        if (istat & ALLOC_INT) {            pnrarr = smcRead(SMCPNRARR);            if (pnrarr & ALLOC_FAILED) {                printf("sendBuffer(%d) alloc failed 1\n",len);                EtherdevStartup(0);                return(-1);            }        }#else        pnrarr = (smcRead(SMCPNRARR) & ALLOC_FAILED);        if (!(pnrarr & ALLOC_FAILED))            break;#endif    }    if (!timeout) {        printf("sendBuffer(%d) wait-for-alloc timeout\n",len);        EtherWFATMTCnt++;        smcWrite(SMCMMUCMD,MMUCMD_RESETMMU);        goto again;//      EtherdevStartup(0);//      return(-1);    }    smcWrite(SMCPNRARR,ARRTOPNR(pnrarr));    smcWrite(SMCPOINTER,PTR_AUTOINC);    for(i=0;i<10;i++);                  /* delay necessary between POINTER */                                        /* and DATA access. */    smcWrite(SMCDATA1,0);                           /* control word */    smcWrite(SMCDATA2,SWAP16((ushort)(len+6)));     /* byte count */    sptr = (ushort *)Exmtbuf;    while(1) {        if (len > 1) {            smcWrite(SMCDATA1,*sptr++);            len -= 2;        }        else if (len == 1) {            smcWrite(SMCDATA1,(*sptr & 0xff00) | ODD_LENGTH);            break;        }        else {            smcWrite(SMCDATA1,0);            break;        }    }    smcWrite(SMCMMUCMD,MMUCMD_ENQUEUETXPKT);#ifndef USE_AUTORELEASE    for(timeout=250000;timeout>0;timeout--) {        istat = smcRead(SMCINT);        if (istat & TX_INT) {            smcWrite(SMCINT,TX_INT);            smcWrite(SMCPNRARR,smcRead(SMCFIFOPORT));            smcWrite(SMCMMUCMD,MMUCMD_RELEASEPKT);            break;        }    }    if (!timeout) {        printf("\007sendBuffer(%d) wait-for-tx_int timeout\n",origlen);        EtherWFTTMTCnt++;        EtherdevStartup(0);        return(-1);    }#endif    EtherXFRAMECnt++;    return(0);}#if INCLUDE_FDUMPintEtherStatToFile(char *prefix){    static  char buf[512];    int     i;    char    *bp, fname[32];    if (EtherIPERRCnt | EtherUDPERRCnt | EtherRXOVRNCnt | EtherALGNERRCnt |        EtherWFTTMTCnt |        EtherBADCRCCnt | EtherTOOLONGCnt | EtherTOOSHORTCnt | EtherWFATMTCnt)    {        bp = buf;        sprintf(bp,"%s\n",prefix);        bp += strlen(bp);        sprintf(bp,"Transmitted frames:      %d\n",EtherXFRAMECnt);        bp += strlen(bp);        sprintf(bp,"Received frames:         %d\n",EtherRFRAMECnt);        bp += strlen(bp);        sprintf(bp,"Receiver overrun errors: %d\n",EtherRXOVRNCnt);        bp += strlen(bp);        sprintf(bp,"IP hdr cksum errors:     %d\n",EtherIPERRCnt);        bp += strlen(bp);        sprintf(bp,"UDP pkt cksum errors:    %d\n",EtherUDPERRCnt);        bp += strlen(bp);        sprintf(bp,"Alignment errors:        %d\n",EtherALGNERRCnt);        bp += strlen(bp);        sprintf(bp,"Bad CRC errors:          %d\n",EtherBADCRCCnt);        bp += strlen(bp);        sprintf(bp,"Packet too long errors:  %d\n",EtherTOOLONGCnt);        bp += strlen(bp);        sprintf(bp,"Packet too short errors: %d\n",EtherTOOSHORTCnt);        bp += strlen(bp);        sprintf(bp,"Wait-for-xmit timeouts: %d\n",EtherWFTTMTCnt);        bp += strlen(bp);        sprintf(bp,"Wait-for-alloc timeouts: %d\n",EtherWFATMTCnt);        bp += strlen(bp);                for(i=0;i<10;i++) {            sprintf(fname,"estat%d",i);            if (!tfsstat(fname))                break;        }        if (i < 10)            tfsadd(fname,"estat",0,buf,bp - buf);    }    return(0);}#endif/* Disable/Enable either broadcast or promiscuous mode... */voidenablePromiscuousReception(){}voiddisablePromiscuousReception(){}voidenableBroadcastReception(){}voiddisableBroadcastReception(){}/* 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 + -