📄 if_esmc.c
字号:
sc->interrupt++; bank = sysInWord (ioaddr + ESMC_BANK_SELECT); /* save bank */ ESMC_SWITCH_BANK (2); mask = sysInByte (ioaddr + ESMC_INT_MASK); /* save mask */ while ((status = sysInByte (ioaddr + ESMC_INT_STAT) & mask) && (timeout--)) { if (status & ESMC_INT_RCV) /* RX done */ { sc->intRcv++; if (sc->mode == RX_MODE_INTERRUPT) /* RX in int */ { esmcGetInt (unit); if ((sc->flags & ESMC_RXING) == 0) { sc->flags |= ESMC_RXING; (void) netJobAdd ((FUNCPTR)esmcGetTask, unit, 0, 0, 0, 0); } } else if ((sc->flags & ESMC_RXING) == 0) /* RX in task */ { sc->flags |= ESMC_RXING; (void) netJobAdd ((FUNCPTR)esmcGet, unit, 0, 0, 0, 0); } } if (status & ESMC_INT_TX) /* TX error */ { sc->es_if.if_oerrors++; sc->es_if.if_opackets--; sc->intTx++; pointerSave = sysInWord (ioaddr + ESMC_PTR); /* save pointer */ packetSave = sysInByte (ioaddr + ESMC_PNR); /* save packet */ packetFail = sysInWord (ioaddr + ESMC_FIFO) & 0x7f; sysOutByte (ioaddr + ESMC_PNR, packetFail); sysOutWord (ioaddr + ESMC_PTR, ESMC_PTR_AUTOINC | ESMC_PTR_READ); statusTx = sysInWord (ioaddr + ESMC_DATA_1); if (statusTx & ESMC_TS_LOST_CARR) sc->lostCarr++; if (statusTx & ESMC_TS_LATCOL) sc->es_if.if_collisions++; sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_TX_RELEASE); /* release */ sysOutByte (ioaddr + ESMC_INT_ACK, ESMC_INT_TX); /* int ack */ ESMC_SWITCH_BANK (0); sysOutWord (ioaddr + ESMC_TCR, sysInWord (ioaddr + ESMC_TCR) | ESMC_TCR_TXEN); ESMC_SWITCH_BANK (2); sysOutByte (ioaddr + ESMC_PNR, packetSave); /* restore packet */ sysOutWord (ioaddr + ESMC_PTR, pointerSave); /* restore pointer */ } if (status & ESMC_INT_TX_EMPTY) /* TX done */ { sc->intTxempty++; sysOutByte (ioaddr + ESMC_INT_ACK, ESMC_INT_TX_EMPTY); /* int ack */ ESMC_SWITCH_BANK (0); statusCard = sysInWord (ioaddr + ESMC_COUNTER); ESMC_SWITCH_BANK (2); sc->es_if.if_collisions += statusCard & 0x0f; statusCard >>= 4; sc->es_if.if_collisions += statusCard & 0x0f; mask &= ~ESMC_INT_TX_EMPTY; if (sc->es_if.if_snd.ifq_head != NULL)#ifdef BSD43_DRIVER (void) netJobAdd ((FUNCPTR)esmcPut, unit, 0, 0, 0, 0);#else (void) netJobAdd ((FUNCPTR)esmcPut, (int)sc, 0, 0, 0, 0);#endif } if (status & ESMC_INT_ALLOC) /* ALLOC done */ { sc->intAlloc++; mask &= ~ESMC_INT_ALLOC; semGive (&sc->esmcSyncSem); } if (status & ESMC_INT_RX_OVRN) /* RX over run */ { sc->es_if.if_ierrors++; sc->intOverrun++; sysOutByte (ioaddr + ESMC_INT_ACK, ESMC_INT_RX_OVRN); /* int ack */ if (sc->mode == RX_MODE_INTERRUPT) /* RX in int */ { esmcGetInt (unit); if ((sc->flags & ESMC_RXING) == 0) { sc->flags |= ESMC_RXING; (void) netJobAdd ((FUNCPTR)esmcGetTask, unit, 0, 0, 0, 0); } } else if ((sc->flags & ESMC_RXING) == 0) /* RX in task */ { sc->flags |= ESMC_RXING; (void) netJobAdd ((FUNCPTR)esmcGet, unit, 0, 0, 0, 0); } } if (status & ESMC_INT_EPH) /* EPH */ sc->intEph++; if (status & ESMC_INT_ERCV) /* early receive */ sc->intErcv++; } sysOutByte (ioaddr + ESMC_INT_MASK, mask); /* restore the mask */ ESMC_SWITCH_BANK (bank); /* restore the bank */ return; }/********************************************************************************* esmcGet - read a packet off the interface(Task Level: netTask)** Copy packets from a RING into an mbuf and hand it to the next higher layer.** RETURNS: N/A*/LOCAL void esmcGet ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST int ioaddr = sc->ioAddr; FAST struct ether_header *eh; FAST struct mbuf *m; int off; int len; u_short packetNo; u_short statusRx; u_char * pData; u_char mask; ESMC_SWITCH_BANK (2); mask = sysInByte (ioaddr + ESMC_INT_MASK); /* save mask */unlucky: while (((packetNo = sysInWord (ioaddr + ESMC_FIFO)) & ESMC_FP_RXEMPTY) == 0) { sysOutByte (ioaddr + ESMC_INT_MASK, 0); /* lock INT */ sysOutWord (ioaddr + ESMC_PTR, ESMC_PTR_READ | ESMC_PTR_RCV | ESMC_PTR_AUTOINC); statusRx = sysInWord (ioaddr + ESMC_DATA_1); /* status */ len = sysInWord (ioaddr + ESMC_DATA_1); /* byte count */ len = (len & 0x07ff) - 6; /* subtract extra */ if (statusRx & ESMC_RS_ERROR_MASK) { ++sc->es_if.if_ierrors; while (sysInWord (ioaddr + ESMC_MMU) & 0x0001) /* check busy bit */ ; sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ sysOutByte (ioaddr + ESMC_INT_MASK, mask); /* unlock INT */ } else {#if ESMC_USE_LONG sysInLongString (ioaddr + ESMC_DATA_1, (long *)sc->pBuft, len >> 2); if (len & 0x02) *(short *)&sc->pBuft[len & ~0x03] = sysInWord (ioaddr + ESMC_DATA_1); *(short *)&sc->pBuft[len & ~0x01] = sysInWord (ioaddr + ESMC_DATA_1);#else sysInWordString (ioaddr + ESMC_DATA_1, (short *)sc->pBuft, (len>>1) + 1);#endif /* ESMC_USE_LONG */ if (statusRx & ESMC_RS_ODDFRM) len++; while (sysInWord (ioaddr + ESMC_MMU) & 0x0001) /* check busy bit */ ; sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ sysOutByte (ioaddr + ESMC_INT_MASK, mask); /* unlock INT */#ifdef ESMC_DEBUG { int ix; int iy; printf ("packet=0x%x, status=0x%x, len=%d\n", (packetNo >> 8) & 0x1f, statusRx, len); for (iy = 0; iy < 8; iy++) { for (ix = 0; ix < 16; ix++) printf ("%2.2x ", (u_char)sc->pBuft[iy * 16 + ix]); printf ("\n"); } }#endif /* ESMC_DEBUG */ sc->es_if.if_ipackets++; /* bump statistic */ eh = (struct ether_header *)(sc->pBuft); /* call input hook if any */ if ((etherInputHookRtn != NULL) && (* etherInputHookRtn) (&sc->es_if, (char *) eh, len)) { continue; } if (len >= SIZEOF_ETHERHEADER) len -= SIZEOF_ETHERHEADER; else { sc->es_if.if_ierrors++; /* bump error statistic */ continue; } pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER check_trailer (eh, pData, &len, &off, &sc->es_if); /* copy data from the ring buffer to mbuf a long-word at a time */ m = bcopy_to_mbufs (pData, len, off, (struct ifnet *)&sc->es_if, 2); if (m == NULL) { sc->es_if.if_ierrors++; /* bump error statistic */ continue; } do_protocol_with_type (eh->ether_type, m, &sc->es_ac, len);#else /* copy data from the ring buffer to mbuf */ m = bcopy_to_mbufs (pData, len, off, (struct ifnet *)&sc->es_if, 2); if (m == NULL) { sc->es_if.if_ierrors++; /* bump error statistic */ continue; } do_protocol (eh, m, &sc->es_ac, len);#endif } } sc->flags &= ~ESMC_RXING; /* go back if we got an interrupt and a new packet */ if ((sysInByte (ioaddr + ESMC_INT_STAT) & (ESMC_INT_RCV | ESMC_INT_RX_OVRN)) || (((sysInWord (ioaddr + ESMC_FIFO)) & ESMC_FP_RXEMPTY) == 0)) goto unlucky; }/********************************************************************************* esmcGetInt - read a packet off the interface(Interrupt Level)** Copy packets from a RING into an mbuf and hand it to the next higher layer.** RETURNS: N/A*/LOCAL void esmcGetInt ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST int ioaddr = sc->ioAddr; int len; int bufLen; u_short statusRx; u_short packetNo; if ((sc->pIn > sc->pOut) && ((sc->pEnd - sc->pIn) < ESMC_BUFSIZE)) sc->pIn = sc->pStart; if (((sc->pOut > sc->pIn) && ((sc->pOut - sc->pIn) < ESMC_BUFSIZE)) || (sc->packetLen[sc->indexIn] != 0)) return; while (((packetNo = sysInWord (ioaddr + ESMC_FIFO)) & ESMC_FP_RXEMPTY) == 0) { sysOutWord (ioaddr + ESMC_PTR, ESMC_PTR_READ | ESMC_PTR_RCV | ESMC_PTR_AUTOINC); statusRx = sysInWord (ioaddr + ESMC_DATA_1); /* status */ len = sysInWord (ioaddr + ESMC_DATA_1); /* byte count */ len = (len & 0x07ff) - 6; /* subtract extra */ if (statusRx & ESMC_RS_ERROR_MASK) { ++sc->es_if.if_ierrors; while (sysInWord (ioaddr + ESMC_MMU) & 0x0001) /* check busy bit */ ; sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ } else {#if ESMC_USE_LONG sysInLongString (ioaddr + ESMC_DATA_1, (long *)sc->pIn, len >> 2); if (len & 0x02) *(short *)&sc->pIn[len & ~0x03] = sysInWord (ioaddr + ESMC_DATA_1); *(short *)&sc->pIn[len & ~0x01] = sysInWord (ioaddr + ESMC_DATA_1);#else sysInWordString (ioaddr + ESMC_DATA_1, (short *)sc->pIn, (len>>1) + 1);#endif /* ESMC_USE_LONG */ if (statusRx & ESMC_RS_ODDFRM) len++; while (sysInWord (ioaddr + ESMC_MMU) & 0x0001) /* check busy bit */ ; sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ if (len & 0x01) /* buffer length */ bufLen = len + 1; else bufLen = len + 2; sc->packetAddr[sc->indexIn] = sc->pIn; /* packet address */ sc->packetLen[sc->indexIn] = len; /* packet length */ sc->pIn += bufLen; /* increment */ sc->indexIn = (sc->indexIn + 1) % sc->nIndex; if ((sc->pIn > sc->pOut) && ((sc->pEnd - sc->pIn) < ESMC_BUFSIZE)) sc->pIn = sc->pStart; /* wrap around */ if (((sc->pOut > sc->pIn) && ((sc->pOut - sc->pIn) < ESMC_BUFSIZE)) || (sc->packetLen[sc->indexIn] != 0)) /* no space */ break; } } }/********************************************************************************* esmcGetTask - read a packet off the interface(Task Level)** Copy packets from a RING into an mbuf and hand it to the next higher layer.** RETURNS: N/A*/LOCAL void esmcGetTask ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST struct ether_header *eh; FAST struct mbuf *m; int off; int len; int bufLen; u_char * pData; while ((len = sc->packetLen[sc->indexOut]) != 0) { eh = (struct ether_header *)(sc->packetAddr[sc->indexOut]); sc->es_if.if_ipackets++; /* bump statistic */ /* call input hook if any */ if ((etherInputHookRtn != NULL) && (* etherInputHookRtn) (&sc->es_if, (char *) eh, len)) continue; if (len >= SIZEOF_ETHERHEADER) len -= SIZEOF_ETHERHEADER; else { sc->es_if.if_ierrors++; /* bump error statistic */ continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -