📄 if_ene.c
字号:
pSoftc->eneStat.collisions += 16; } if (txStat & TSTAT_UNDER) pSoftc->eneStat.underruns++; } if ( (intStat & ISTAT_PTX) != 0) /* Transmit-packet sent */ { if (txStat & TSTAT_CDH) pSoftc->eneStat.heartbeats++; if (txStat & TSTAT_OWC) pSoftc->eneStat.outofwindow++; if (txStat & TSTAT_PTX) pSoftc->eneStat.tnoerror++; } if ( (intStat & (ISTAT_TXE | ISTAT_PTX)) != 0) /* Transmit complete */ if (pSoftc->es_if.if_snd.ifq_head != NULL)#ifdef BSD43_DRIVER (void) netJobAdd ((FUNCPTR)enePut, unit, 0,0,0,0);#else (void) netJobAdd ((FUNCPTR)enePut, (int)pSoftc, 0,0,0,0);#endif }/********************************************************************************* eneGet - read a packet off the interface** Copy packets from the buffer ring into mbufs and hand them to the next* higher layer.*/static void eneGet ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; FAST struct ether_header * eh; FAST MBUF * m;#ifdef BSD43_DRIVER int off;#endif UINT packetSize; UCHAR * pData; static UCHAR uppByteCnt; UINT8 tempPage; /* used in buffer validation */ UINT8 pageCount; /* used in buffer validation */ ENE_HEADER h;unlucky: while (TRUE) { if (pSoftc->nextPacket == pSoftc->current) break; /* done all complete frames */ eneDataIn (unit, (((UINT)pSoftc->nextPacket << 8) & 0x0000ffff), sizeof (ENE_HEADER), (char *) &h);#ifdef ENE_DEBUGprintf ("ene: Get: next=%02x, uppByteCnt=%02x, lowByteCnt=%02x\n", h.next, h.uppByteCnt, h.lowByteCnt);#endif /* Calculate upper byte count in case it's corrupted, * though this supposedly happens only in StarLAN applications * with bus clock frequence greater than 4 mHz. */ if (h.next > pSoftc->nextPacket) uppByteCnt = h.next - pSoftc->nextPacket; else uppByteCnt = (NE2000_PSTOP - pSoftc->nextPacket) + (h.next - NE2000_PSTART); if (h.lowByteCnt > 0xfc) uppByteCnt -= 2; else uppByteCnt -= 1; h.uppByteCnt = uppByteCnt; /* compute packet size excluding Ethernet checksum bytes */ packetSize = ( ( (UINT)h.uppByteCnt << 8) + h.lowByteCnt) - 4; /* Check for packet (and header) shifted in memory (by heavy load). * The method and solution are recommended by 3Com in their * EtherLink II Adapter Technical Manual, with the addition of * a reasonableness check on the next-page link. */ pageCount = (packetSize + 4 + sizeof (ENE_HEADER) + (ENE_PAGESIZE - 1)) / ENE_PAGESIZE; tempPage = pSoftc->nextPacket + pageCount; if (tempPage >= NE2000_PSTOP) tempPage -= (NE2000_PSTOP - NE2000_PSTART); if ((h.next != tempPage) || (h.next < NE2000_PSTART) || (h.next >= NE2000_PSTOP)) { pSoftc->eneStat.badPacket++; /* can't trust anything now */ pSoftc->eneStat.rerror++; eneInit (unit); /* stop and restart the interface */ pSoftc->flags &= ~RXING; eneIntEnable (unit); return; } /* reject runts, although we are configured to reject them */ if (packetSize < 60) { pSoftc->eneStat.shortPacket++; goto doneGet; } /* reject packets larger than our scratch buffer */ if (packetSize > MAX_FRAME_SIZE) goto doneGet; if (h.rstat & RSTAT_PRX) { /* 3Com says this status marks a packet bit-shifted in memory; * the data cannot be trusted but the NIC header is OK. */ if ( (h.rstat & (RSTAT_DFR | RSTAT_DIS)) != 0) { pSoftc->eneStat.badPacket++; pSoftc->eneStat.rerror++; goto doneGet; } pSoftc->eneStat.rnoerror++; } else { if ( (h.rstat & RSTAT_DFR) != 0) pSoftc->eneStat.jabber++; pSoftc->eneStat.rerror++; goto doneGet; } /* copy separated frame to a temporary buffer */ eneDataIn (unit, ((UINT)pSoftc->nextPacket << 8) + sizeof (ENE_HEADER), packetSize, pSoftc->packetBuf); eh = (struct ether_header *)(pSoftc->packetBuf); pSoftc->es_if.if_ipackets++; /* bump statistic. */ /* call input hook if any */ if ((etherInputHookRtn != NULL) && (* etherInputHookRtn) (&pSoftc->es_if, (char *) eh, packetSize)) { goto doneGet; } if (packetSize >= SIZEOF_ETHERHEADER) packetSize -= SIZEOF_ETHERHEADER; else goto doneGet; pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER check_trailer (eh, pData, (int *) &packetSize, &off, &pSoftc->es_if); /* copy data from the scratch buffer to mbuf a long-word at a time */ m = bcopy_to_mbufs (pData, packetSize, off, (IFNET *) &pSoftc->es_if, 2); if (m == NULL) { pSoftc->es_if.if_ierrors++; /* bump error statistic. */ goto doneGet; } do_protocol_with_type (eh->ether_type, m, &pSoftc->es_ac, packetSize);#else m = bcopy_to_mbufs (pData, packetSize, 0, (IFNET *)&pSoftc->es_if, 2); if (m == NULL) { pSoftc->es_if.if_ierrors++; /* bump error statistic. */ goto doneGet; } do_protocol (eh, m, &pSoftc->es_ac, packetSize);#endifdoneGet: pSoftc->nextPacket = h.next; sysOutByte (ENE_BOUND (pSoftc->eneAddr), (pSoftc->nextPacket != NE2000_PSTART ? pSoftc->nextPacket - 1 : NE2000_PSTOP - 1)); } pSoftc->flags &= ~RXING; /* go back if we received an interrupt and a new packet */ if (pSoftc->nextPacket != pSoftc->current) goto unlucky; }#ifdef BSD43_DRIVER/********************************************************************************* eneoutput - ethernet output routine** Encapsulate a packet of type family for the local net.* Use trailer local net encapsulation if enough data in first* packet leaves a multiple of 512 bytes of data in remainder.* If destination is this address or broadcast, send packet to* loop device to kludge around the fact that 3com interfaces can't* talk to themselves.** RETURNS: ?*/static int eneoutput ( IFNET * ifp, MBUF * m0, SOCK * dst ) { return (ether_output (ifp, m0, dst, (FUNCPTR)enePut, & pEneSoftc [ifp->if_unit]->es_ac)); }#endif/********************************************************************************* enePut - copy a packet to the interface.** Copy from mbuf chain to transmitter buffer in shared memory.**/#ifdef BSD43_DRIVERstatic void enePut ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit];#elsestatic void enePut ( ENE_SOFTC * pSoftc ) { int unit = pSoftc->es_if.if_unit;#endif FAST MBUF * m; FAST int len; long qdtimer; int s = splnet (); if (pSoftc->es_if.if_snd.ifq_head != NULL) { qdtimer = 10000L; while ( ( (sysInByte (ENE_CMD (pSoftc->eneAddr)) & CMD_TXP) != 0) && (--qdtimer > 0)) ; if (qdtimer == 0) eneInit (unit); IF_DEQUEUE (&pSoftc->es_if.if_snd, m); /* we assume no packet will be larger than MAX_FRAME_SIZE, * based on our advertised MTU. */ copy_from_mbufs (pSoftc->packetBuf, m, len); len = max (ETHERSMALL, len); /* call output hook if there is one, else send the packet */ if ( (etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&pSoftc->es_if, pSoftc->packetBuf, len)) { } else { /* put packet in board's output buffer */ eneDataOut (unit, pSoftc->packetBuf, len, (NE2000_TSTART << 8)); /* kick Transmitter */ sysOutByte (ENE_INTMASK (pSoftc->eneAddr), 0x00); sysOutByte (ENE_TSTART (pSoftc->eneAddr), NE2000_TSTART); sysOutByte (ENE_TCNTH (pSoftc->eneAddr), len >> 8); sysOutByte (ENE_TCNTL (pSoftc->eneAddr), len & 0xff); sysOutByte (ENE_CMD (pSoftc->eneAddr), CMD_TXP); eneIntEnable (unit); } } splx (s); }/********************************************************************************* eneBoardReset - reset the whole board** The NE2000 has an I/O port dedicated to hardware reset; you READ the port* to initiate the reset then WRITE 0 to the port.*/static void eneBoardReset ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; (void) sysInByte (ENE_RESET (pSoftc->eneAddr)); taskDelay (sysClkRateGet () >> 1); sysOutByte (ENE_RESET (pSoftc->eneAddr), 0x00); taskDelay (sysClkRateGet () >> 1); sysOutByte (ENE_CMD (pSoftc->eneAddr), CMD_NODMA | CMD_PAGE0 | CMD_STOP); while ((sysInByte (ENE_INTSTAT (pSoftc->eneAddr)) & ISTAT_RST) != ISTAT_RST) ; }/********************************************************************************* eneReset - reset the chip** Reset the chip.**/static void eneReset ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; int s = splnet (); /* mask interrupt */ sysOutByte (ENE_INTMASK (pSoftc->eneAddr), 0x00); eneInit (unit); eneIntEnable (unit); pSoftc->eneStat.reset++; splx (s); }/********************************************************************************* eneioctl - ioctl for interface** RETURNS: ?*/static int eneioctl ( FAST IFNET * ifp, int cmd, caddr_t data ) { int unit; ENE_SOFTC * pSoftc; int error = 0; int s; unit = ifp->if_unit; pSoftc = pEneSoftc [unit]; s = splimp(); switch (cmd) { case SIOCSIFADDR: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (ifp, &IA_SIN (data)->sin_addr); break; case SIOCSIFFLAGS: /* Set promiscuous mode according to current interface flags */ pSoftc->rxFilter = ( (ifp->if_flags & IFF_PROMISC) != 0) ? RCON_BROAD | RCON_PROM : RCON_BROAD; sysOutByte (ENE_RCON (pSoftc->eneAddr), pSoftc->rxFilter); break; default: error = EINVAL; } splx (s); return (error); }/********************************************************************************* eneInit - initialize SMC8390 ENE (Ethernet LAN Controller)** RETURNS: N/A** NOMANUAL*/static void eneInit ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; UCHAR * pAddr = (UCHAR *)pSoftc->es_enaddr; /* 1. program Command Register for page 0 and for no DMA */ sysOutByte (ENE_CMD (pSoftc->eneAddr), CMD_NODMA | CMD_PAGE0 | CMD_STOP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -