📄 etherdev.c
字号:
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 + -