📄 ne2000end.c
字号:
/* 3. clear Remote Byte Count Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00); /* 4. initialize Receive Configuration Register */ /* Always accept broadcast packets. */ rxFilter = RCON_BROAD; /* Set multicast mode if it's asked for. */ if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0) { rxFilter |= RCON_GROUP; } ENDLOGMSG (("\tMulticast mode %s\n", (rxFilter & RCON_GROUP) ? "on" : "off", 0, 0, 0, 0, 0)); /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC) { rxFilter |= RCON_PROM; } ENDLOGMSG (("\tPromiscuous mode %s\n", (rxFilter & RCON_PROM) ? "on" : "off", 0, 0, 0, 0, 0)); ENDLOGMSG (("\tsetting rxFilter = 0x%x\n", rxFilter,2,3,4,5,6)); SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter); /* 5. place the ENE in LOOPBACK mode 1 or 2 */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1); /* 6. initialize Receive Buffer Ring */ SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, NE2000_PSTART); SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, NE2000_PSTOP); SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, NE2000_PSTART); /* 7. clear Interrupt Status Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff); /* 8. initialize Interrupt Mask Register */ pDrvCtrl->imask = 0; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* 9. program Command Register for page 1 */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1 | CMD_STOP); /* i) initialize physical address registers */ SYS_OUT_CHAR (pDrvCtrl, ENE_STA0, pDrvCtrl->enetAddr[0]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA1, pDrvCtrl->enetAddr[1]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA2, pDrvCtrl->enetAddr[2]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA3, pDrvCtrl->enetAddr[3]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA4, pDrvCtrl->enetAddr[4]); SYS_OUT_CHAR (pDrvCtrl, ENE_STA5, pDrvCtrl->enetAddr[5]); ENDLOGMSG (("enet addr %02x:%02x:%02x:%02x:%02x:%02x\n", pDrvCtrl->enetAddr[0] & 0xff, pDrvCtrl->enetAddr[1] & 0xff, pDrvCtrl->enetAddr[2] & 0xff, pDrvCtrl->enetAddr[3] & 0xff, pDrvCtrl->enetAddr[4] & 0xff, pDrvCtrl->enetAddr[5] & 0xff)); /* ii) initialize multicast address registers */ ne2000AddrFilterSet (pDrvCtrl); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR0, pDrvCtrl->mcastFilter[0]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR1, pDrvCtrl->mcastFilter[1]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR2, pDrvCtrl->mcastFilter[2]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR3, pDrvCtrl->mcastFilter[3]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR4, pDrvCtrl->mcastFilter[4]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR5, pDrvCtrl->mcastFilter[5]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR6, pDrvCtrl->mcastFilter[6]); SYS_OUT_CHAR (pDrvCtrl, ENE_MAR7, pDrvCtrl->mcastFilter[7]);#ifdef DEBUG ENDLOGMSG ((("Setting multicast addresses to:\n"),1,2,3,4,5,6)); sprintf(buf, "enet mcast %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", pDrvCtrl->mcastFilter[0] & 0xff, pDrvCtrl->mcastFilter[1] & 0xff, pDrvCtrl->mcastFilter[2] & 0xff, pDrvCtrl->mcastFilter[3] & 0xff, pDrvCtrl->mcastFilter[4] & 0xff, pDrvCtrl->mcastFilter[5] & 0xff, pDrvCtrl->mcastFilter[6] & 0xff, pDrvCtrl->mcastFilter[7] & 0xff); ENDLOGMSG (((buf),1,2,3,4,5,6));#endif /* DEBUG */ /* iii) initialize current page pointer */ SYS_OUT_CHAR (pDrvCtrl, ENE_CURR, NE2000_PSTART + 1); pDrvCtrl->nextPacket = NE2000_PSTART + 1; /* set memory parameters */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE2 | CMD_STOP); /* * HELP: DP 83905 manual says thas ENE_ENH is address counter lower, * ENE_BLOCK is address counter upper. not wait states, or anything * else. What is with these comments? */ SYS_OUT_CHAR (pDrvCtrl, ENE_ENH, 0x00); /* 0 wait states */ SYS_OUT_CHAR (pDrvCtrl, ENE_BLOCK, 0x00); /* 0x00xxxx */ /* 10. put the ENE in START mode */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START); /* 11. initialize Transmit Configuration Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_NORMAL); ENDLOGMSG (("ne2000Config: done\n", 0, 0, 0, 0, 0, 0)); pDrvCtrl->imask = ((pDrvCtrl->flags & END_POLLING) ? 0 : NE2000_ALL_INTS); /* Only actually enable interrupts if not polling */ if (intEnable) SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); }/********************************************************************************* ne2000OverwriteRecover - recover from receive buffer ring overflow** This procedure is mandated by National Semiconductor as the only safe* way to recover from an Overwrite Warning Error. The first two steps* of their procedure, reading the Command Register and stopping the NIC,* were accomplished in the interrupt handler. The rest occurs here.** This routine is scheduled to run in the net task since it must delay* to allow the STOP command to take effect.*/LOCAL void ne2000OverwriteRecover ( NE2000END_DEVICE *pDrvCtrl, UCHAR cmdStatus ) { UCHAR stat; BOOL reSend; ENDLOGMSG (("ne2000OverwriteRecover: enter (flags=%x, imask=%x)\n", pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0)); /* We shouldn't get here without the OVERWRITE flags set */ if (!(pDrvCtrl->flags & END_OVERWRITE2)) { ENDLOGMSG (("ne2000OverwriteRecover: bad flags\n", 0,0,0,0,0,0));#ifdef DEBUG SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0); taskSuspend (0);#else return;#endif } /* 1. read the TXP bit in the command register (already in cmdStatus) */ /* 2. issue the STOP command (done in the interrupt handler) */ /* 3. delay at least 1.6 milliseconds (1/625 second) */ taskDelay ((sysClkRateGet() + 624)/ 625); /* we are now supposedly sure the NIC is stopped */ /* 4. clear Remote Byte Count Register */ SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00); /* 5. read the stored value of the TXP bit (in cmdStatus) */ if ((cmdStatus & CMD_TXP) == 0) reSend = FALSE; else { SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat); if ((stat & (ISTAT_PTX | ISTAT_TXE)) == 0) { /* transmit was in progress but probably deferring */ reSend = TRUE; } else { /* transmit was completed (probably), don't repeat it */ reSend = FALSE; } } /* 6. place the NIC in loopback mode */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1); /* 7. issue the START command to the NIC */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START); /* 8. remove one or more packets from the receive buffer ring */ /* clear overwrite flag */ pDrvCtrl->flags &= ~END_OVERWRITE; pDrvCtrl->current = ne2000GetCurr (pDrvCtrl); ne2000HandleRcvInt (pDrvCtrl); /* 9. reset the overwrite warning bit in the ISR */ /* reset all active interrupt conditions */ SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat); SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, stat); /* 10. take the NIC out of loopback */ SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, 0x00); /* 10a. re-enable all device interrupts */ pDrvCtrl->imask = NE2000_ALL_INTS; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* 11. if need to resend, do so, otherwise if anything queued, send that */ pDrvCtrl->flags &= ~END_OVERWRITE2; if (reSend) SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP); else muxTxRestart (&pDrvCtrl->endObj); ENDLOGMSG (("ne2000OverwriteRecover: done (flags=%x, imask=%x)\n", pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0)); }/********************************************************************************* ne2000Int - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void ne2000Int ( NE2000END_DEVICE *pDrvCtrl ) { UCHAR val; UCHAR intStat; UCHAR txStat; UCHAR rxStat; pDrvCtrl->stats.interrupts++; /* Read status and Acknowlegde interrupt */ SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &intStat); intStat &= pDrvCtrl->imask; SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, intStat); /* Get TX and RX status */ SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &txStat); SYS_IN_CHAR (pDrvCtrl, ENE_RSTAT, &rxStat); ENDLOGMSG (("ne2000Int: intStat=%02x imask=%02x txStat=%02x rxStat=%02x\n", intStat, pDrvCtrl->imask, txStat, rxStat, 0, 0)); /* Update count registers */ SYS_IN_CHAR (pDrvCtrl, ENE_COLCNT, &val); pDrvCtrl->stats.collisions += val; SYS_IN_CHAR (pDrvCtrl, ENE_ALICNT, &val); pDrvCtrl->stats.aligns += val; SYS_IN_CHAR (pDrvCtrl, ENE_CRCCNT, &val); pDrvCtrl->stats.crcs += val; SYS_IN_CHAR (pDrvCtrl, ENE_MPCNT, &val); pDrvCtrl->stats.missed += val; /* * enable interrupts, clear receive and/or transmit interrupts, and clear * any errors that may be set. */ /* Check for errors */ if (intStat & ISTAT_OVW) /* Overwrite */ { UCHAR cmdStat; END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); if (!(pDrvCtrl->flags & END_OVERWRITE2)) { pDrvCtrl->flags |= (END_OVERWRITE | END_OVERWRITE2); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Overwrite"; netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj, (int) &pDrvCtrl->lastError, 0, 0, 0); pDrvCtrl->stats.overwrite++; SYS_IN_CHAR (pDrvCtrl, ENE_COLCNT, &cmdStat); SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP); ENDLOGMSG (("ne2000Int: overwrite detected\n", 0, 0, 0, 0, 0, 0)); netJobAdd ((FUNCPTR) ne2000OverwriteRecover, (int) pDrvCtrl, cmdStat, 0, 0, 0); } /* no further interrupt processing */ pDrvCtrl->imask = 0; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); return; } /* Receive handling */ if (intStat & ISTAT_RXE) /* Receive-error */ { if (!pDrvCtrl->lastIntError) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "receive error"; netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj, (int) &pDrvCtrl->lastError, 0, 0, 0); } ++pDrvCtrl->lastIntError; pDrvCtrl->stats.rerror++; if (rxStat & RSTAT_OVER) pDrvCtrl->stats.overruns++; if (rxStat & RSTAT_DIS) pDrvCtrl->stats.disabled++; if (rxStat & RSTAT_DFR) pDrvCtrl->stats.deferring++; } if (intStat & ISTAT_TXE) /* Transmit error-packet not sent */ { if (!pDrvCtrl->lastIntError) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "transmit error"; netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj, (int) &pDrvCtrl->lastError, 0, 0, 0); } ++pDrvCtrl->lastIntError; pDrvCtrl->stats.terror++; if (txStat & TSTAT_ABORT) { pDrvCtrl->stats.aborts++; pDrvCtrl->stats.collisions += 16; } if (txStat & TSTAT_UNDER) pDrvCtrl->stats.underruns++; } /* Transmit handling */ if (intStat & ISTAT_PTX) /* Transmit-packet sent */ { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); if (txStat & TSTAT_CDH) pDrvCtrl->stats.heartbeats++; if (txStat & TSTAT_OWC) pDrvCtrl->stats.outofwindow++; if (txStat & TSTAT_PTX) pDrvCtrl->stats.tnoerror++; } /* Check for lack of errors */ if (!(intStat & (ISTAT_RXE | ISTAT_TXE))) pDrvCtrl->lastIntError = 0; /* Have netTask handle any input packets */ if (intStat & ISTAT_PRX) { pDrvCtrl->current = ne2000GetCurr (pDrvCtrl); ENDLOGMSG(("ne2000Int: input packet (flags=%x, current=%d)\n", pDrvCtrl->flags, pDrvCtrl->current, 0, 0, 0, 0)); if (!(pDrvCtrl->flags & END_RECV_HANDLING_FLAG)) { /* Disable RX int */ pDrvCtrl->imask &= ~IM_PRXE; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); pDrvCtrl->flags |= END_RECV_HANDLING_FLAG; (void)netJobAdd ((FUNCPTR)ne2000HandleRcvInt, (int)pDrvCtrl, 0,0,0,0); } } /* Check for transmit complete */ if ((intStat & (ISTAT_TXE | ISTAT_PTX)) != 0) { pDrvCtrl->flags &= ~END_TX_IN_PROGRESS; ENDLOGMSG (("ne2000Int: Tx complete, blocked=%d\n", (pDrvCtrl->flags & END_TX_BLOCKED) ? 1 : 0,0,0,0,0,0)); if (pDrvCtrl->flags & END_TX_BLOCKED) { /* Disable TX ints */ pDrvCtrl->imask &= ~(IM_TXEE | IM_PTXE); SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); pDrvCtrl->flags &= ~END_TX_BLOCKED; netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0); } } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); }/********************************************************************************* ne2000HandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void ne2000HandleRcvInt ( NE2000END_DEVICE *pDrvCtrl ) { int oldLevel; char *pBuf; /* END_RECV_HANDLING_FLAG set by ISR */ ENDLOGMSG (("ne2000HandleRcvInt(%x): enter (flags=%x)\n", pDrvCtrl,pDrvCtrl->flags,0,0,0,0)); pBuf = NULL; while (pDrvCtrl->flags & END_RECV_HANDLING_FLAG) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -