📄 if_es.c
字号:
esChipReset (ls); /* reset ESTAR */ (void) intConnect (INUM_TO_IVEC (ivec), esInt, (int)ls);#ifdef BSD43_DRIVER ether_attach (ifp, unit, "es", (FUNCPTR) esInit, (FUNCPTR) esIoctl, (FUNCPTR) esOutput, (FUNCPTR) esReset);#else ether_attach ( &ls->ls_ac.ac_if, unit, "es", (FUNCPTR) esInit, (FUNCPTR) esIoctl, (FUNCPTR) ether_output, (FUNCPTR) esReset ); ifp->if_start = (FUNCPTR)esStartOutput;#endif sysIntEnable (ilevel); esInit (unit); return (OK); }/********************************************************************************* esReset - reset the interface** Mark interface as inactive & reset the chip*/LOCAL VOID esReset ( int unit ) { FAST struct ls_softc *ls = ls_softc [unit]; ls->ls_if.if_flags &= ~IFF_RUNNING; esChipReset (ls); /* reset ESTAR */ }/********************************************************************************* esInit - initializes EtherStar connection** Initialization of interface; clear recorded pending operations.* Called at boot time (with interrupts disabled?),* and at ifconfig time via esIoctl, with interrupts disabled.*/LOCAL int esInit ( int unit ) { FAST struct ls_softc *ls = ls_softc [unit]; FAST struct ifnet *ifp = &ls->ls_if; ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_PROMISC); esChipReset (ls); /* disable chip during init */ esConfig (ls); /* reset all ring structures */ ifp->if_flags |= (IFF_UP | IFF_RUNNING); if (ls->ls_flags & LS_PROMISCUOUS_FLAG) ifp->if_flags |= (IFF_PROMISC); esChipInit (ls); /* on return ESTAR is running */#ifdef BSD43_DRIVER esStartOutput (ls->ls_if.if_unit); /* tell chip about any pending output */#else esStartOutput (ls);#endif return (0); }/********************************************************************************* esConfig - fill in initialization block with mode information.** Fill in all fields in the Initialization Block with relevant values.* In addition, fill in all fields in Transmit Message Descriptor ring* and Receive Message Descriptor ring.*/LOCAL VOID esConfig ( FAST struct ls_softc *ls ) { FAST es_rmd *rmd; FAST es_tmd *tmd; FAST char *buf; FAST es_ib *ib; int i; rmd = ls->ls_rring; /* receive message descriptor ring */ rmd = (es_rmd *)(((int)rmd + 7) & ~7); /* low 3 bits must be 000 */ ls->ls_rring = rmd; /* fix softc as well */ buf = ls->rmd_ring.r_bufs; for (i = 0; i < ls->ls_rsize; i++) { rmd->rbuf_ladr = (u_short)((int)buf); /* bits 15:00 of buffer address */ rmd->rbuf_rmd1 = (u_short)((int)buf >> 16) & 0xff; /* bits 23:16 of buffer address */ rmd->rbuf_bcnt = -(ls->bufSize);/* neg of buffer byte count */ rmd->rbuf_mcnt = 0; /* no message byte count yet */ rmd->es_rmd1.es_rmd1b |= esrmd1_OWN; /* buffer now owned by ESTAR */ rmd++; /* step to next message descriptor */ buf += (ls->bufSize); /* step to start of next buffer */ ls->loanRefCnt [i] = (u_char) 0; } ls->ls_rindex = 0; /* ESTAR will use at start of ring */ tmd = ls->ls_tring; /* transmit message descriptor ring */ tmd = (es_tmd *)(((int)tmd + 7) & ~7); /* low 3 bits must be 000 */ ls->ls_tring = tmd; /* fix softc as well */ buf = ls->tmd_ring.t_bufs; for (i = 0; i < ls->ls_tsize; i++) { tmd->tbuf_ladr = (u_short)((int)buf); /* bits 15:00 of buffer address */ tmd->tbuf_tmd1 = (u_short)((int)buf >> 16) & 0xff; /* bits 23:16 of buffer address */ tmd->tbuf_bcnt = 0; /* no message byte count yet */ tmd->tbuf_tmd3 = 0; /* no error status yet */ tmd->es_tmd1.es_tmd1b |= estmd1_ENP; /* buffer is end of packet */ tmd->es_tmd1.es_tmd1b |= estmd1_STP; /* buffer is start of packet */ tmd++; /* step to next message descriptor */ buf += (ls->bufSize); /* step to start of next buffer */ } ls->ls_tindex = 0; /* ESTAR */ ls->ls_dindex = 0; /* buffer disposal will lag tindex */ ib = ls->ib; if (ls->ls_flags & LS_PROMISCUOUS_FLAG) ib->esIBMode = 0x8000; /* chip will be in promiscuous receive mode */ else ib->esIBMode = 0; /* chip will be in normal receive mode */ swab ((char *)ls->ls_enaddr, ib->esIBPadr, 6); ib->esIBRdraLow = (u_short)((int)ls->ls_rring); ib->esIBRdraHigh = (u_short)(((int)ls->ls_rring >> 16) & 0xff) | (ls->ls_rpo2 << 13); ib->esIBTdraLow = (u_short)((int)ls->ls_tring); ib->esIBTdraHigh = (u_short)(((int)ls->ls_tring >> 16) & 0xff) | (ls->ls_tpo2 << 13); }/********************************************************************************* esInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/LOCAL VOID esInt ( FAST struct ls_softc *ls ) { FAST ES_DEVICE *dv; FAST es_rmd *rmd; FAST es_tmd *tmd; FAST int *pDindex; FAST int *pTindex; FAST int *pTsize; FAST es_tmd *pTring; FAST u_short w, temp; FAST int i; FAST char *buf; dv = ls->devAdrs; *dlan.dlcr1 = 0x00; /* clear transmit masks */ *dlan.dlcr3 = 0x00; /* clear receive masks */ /* read any receive packets */ while (!(*dlan.dlcr5 & 0x40)) { *dlan.dlcr2 = 0x80; /* clear pkt_rdy */ rmd = ls->ls_rring + recIndex; recIndex = (recIndex + 1) & (ls->ls_rsize - 1); rmd->es_rmd1.es_rmd1b &= ~esrmd1_OWN; /* rbuf_own = 0; */ buf = (char *) ((u_int) ls->rmd_ring.r_bufs + (u_int) ((((u_int)rmd - (u_int)ls->ls_rring) / sizeof(es_rmd)) * ls->bufSize)); temp = esReadBmpr0 (dv); /* read status */ if (newdlan == TRUE) { temp = esReadBmpr0 (dv); /* and count */ i = (temp>>8 | temp<<8) & 0xffff; rmd->rbuf_mcnt = i; /* save count */ rmd->es_rmd1.es_rmd1b |= esrmd1_STP; /* rbuf_stp = 1; */ rmd->es_rmd1.es_rmd1b |= esrmd1_ENP; /* rbuf_enp = 1; */ while (i > 0) { w = esReadBmpr0 (dv); *(u_short *)buf = w; buf +=2; i -= 2; /* count down */ } } else { i = esReadBmpr0 (dv); /* and count */ rmd->rbuf_mcnt = i; /* save count */ rmd->es_rmd1.es_rmd1b |= esrmd1_STP; /* rbuf_stp = 1; */ rmd->es_rmd1.es_rmd1b |= esrmd1_ENP; /* rbuf_enp = 1; */ while (i > 0) { w = esReadBmpr0 (dv); *(u_short *)buf = (w>>8 | w<<8); buf +=2; i -= 2; /* count down */ } } } if (*dlan.dlcr2 & es_bus_rd_err) *dlan.dlcr2 = es_bus_rd_err; if ((rmd = esGetFullRMD (ls)) != NULL) { if ((ls->ls_flags & LS_RCV_HANDLING_FLAG) == 0) { ls->ls_flags |= LS_RCV_HANDLING_FLAG; (void) netJobAdd ((FUNCPTR) esHandleRecvInt, (int) ls, 0, 0, 0, 0); } } /* Did etherstar update any of the TMD's? */ if (!(*dlan.dlcr0 & ES_TMT_MASK)) { *dlan.dlcr3 = ES_RCV_MASK; return; } *dlan.dlcr1 = 0x00; /* clear transmit mask */ *dlan.dlcr0 = 0x0f; /* reset error conditions */ *dlan.dlcr2 = 0x4f; /* reset packet ready */ pDindex = &ls->ls_dindex; pTindex = &ls->ls_tindex; pTsize = &ls->ls_tsize; pTring = ls->ls_tring; while (*pDindex != *pTindex) { /* disposal has not caught up */ tmd = pTring + *pDindex; /* if the buffer is still owned by ESTAR, don't touch it */ if (tmd->tbuf_tmd1 & TMD_OWN) { break; } /* * tbuf_err (TMD1.ERR) is an "OR" of LCOL, LCAR, UFLO or RTRY. * Note that BUFF is not indicated in TMD1.ERR. * We should therefore check both tbuf_err and tbuf_buff * here for error conditions. */ if ((tmd->tbuf_tmd1 & TMD_ERR) || (tmd->tbuf_tmd3 & TMD_BUFF)) { ls->ls_if.if_oerrors++; /* output error */ ls->ls_if.if_opackets--; /* check for no carrier */ if (tmd->tbuf_tmd3 & TMD_LCAR) logMsg ("es%d: no carrier\n", ls->ls_if.if_unit, 0, 0, 0, 0, 0); /* every esLogCount errors show other interesting bits of tmd3 */ if ((tmd->tbuf_tmd3 & 0xfc00) && esLogCount && (ls->ls_if.if_oerrors % esLogCount) == 0) logMsg ("es%d: xmit error, status(tmd3)=0x%x, err count=%d\n", ls->ls_if.if_unit, tmd->tbuf_tmd3 & 0xfc00, ls->ls_if.if_oerrors, 0, 0, 0); /* restart chip on fatal errors */ if ((tmd->tbuf_tmd3 & TMD_BUFF) || (tmd->tbuf_tmd3 & TMD_UFLO)) { (void) netJobAdd ((FUNCPTR) esInit, ls->ls_if.if_unit, 0, 0, 0, 0); break; } } tmd->tbuf_tmd1 &= 0xff; /* clear high byte */ tmd->tbuf_tmd3 = 0; /* clear all error & stat stuff */ /* now bump the tmd disposal index pointer around the ring */ *pDindex = (*pDindex + 1) & (*pTsize - 1); } if (ls->ls_if.if_snd.ifq_head != NULL && (ls->ls_flags & LS_START_OUTPUT_FLAG) == 0) { ls->ls_flags |= LS_START_OUTPUT_FLAG;#ifdef BSD43_DRIVER (void) netJobAdd ( (FUNCPTR) esStartOutput, ls->ls_if.if_unit, 0, 0, 0, 0);#else (void) netJobAdd ( (FUNCPTR) esStartOutput, (int)ls, 0, 0, 0, 0);#endif } *dlan.dlcr3 = ES_RCV_MASK; }/********************************************************************************* esReadBmpr0 - prevents optimizer from stripping required accesses to device** prevents optimizer from stripping required accesses to the device*/LOCAL u_short esReadBmpr0 ( FAST ES_DEVICE *dv ) { return ( dv->bmpr0); }/********************************************************************************* esHandleRecvInt - 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.*/LOCAL VOID esHandleRecvInt ( FAST struct ls_softc *ls ) { FAST es_rmd *rmd; FAST int oldIndex; do { ls->ls_flags |= LS_RCV_HANDLING_FLAG; while ((rmd = esGetFullRMD (ls)) != NULL) { /* RMD available */ oldIndex = ls->ls_rindex; if (esRecv (ls, rmd) == OK) for (; oldIndex != ls->ls_rindex; oldIndex = (oldIndex + 1) & (ls->ls_rsize - 1)) { rmd = ls->ls_rring + oldIndex; ES_RMD_GIVE_TO_ESTAR (rmd); } else break; } /* * There is a RACE right here. The ISR could add a receive packet * and check the boolean below, and decide to exit. Thus the * packet could be dropped if we don't double check before we * return. */ ls->ls_flags &= ~LS_RCV_HANDLING_FLAG; } while (esGetFullRMD (ls) != NULL); /* this double check solves the RACE */ { } *dlan.dlcr3 = ES_RCV_MASK; }/********************************************************************************* esRecv - process Ethernet receive completion** Process Ethernet receive completion:* If input error just drop packet.* Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length* from type, then have to drop packet. Otherwise decapsulate* packet based on type and pass to type-specific higher-level* input routine.** RETURNS: ERROR if RMD shouldn't be returned back to ESTAR yet.* Otherwise, returns OK to return the RMD back to ESTAR.*/LOCAL STATUS esRecv ( struct ls_softc *ls, FAST es_rmd *rmd ) { FAST struct ether_header *eh; FAST struct mbuf *m; FAST u_char *pData; int len; int off;#ifdef BSD43_DRIVER u_short ether_type;#endif /* * If both STP and ENP are set, ESTAR didn't try to * use data chaining. */ if (((rmd->es_rmd1.es_rmd1b & esrmd1_STP) == esrmd1_STP) && ((rmd->es_rmd1.es_rmd1b & esrmd1_ENP) == esrmd1_ENP)) { len = rmd->rbuf_mcnt; ls->ls_rindex = (ls->ls_rindex + 1) & (ls->ls_rsize - 1); } else { ls->ls_rindex = (ls->ls_rindex + 1) & (ls->ls_rsize - 1); ++ls->ls_if.if_ierrors; if (esLogCount && (ls->ls_if.if_ierrors % esLogCount) == 0) logMsg ("es%d: receive error, stp %d enp %d\n", ls->ls_if.if_unit, (rmd->es_rmd1.es_rmd1b & esrmd1_STP) >> 9, (rmd->es_rmd1.es_rmd1b & esrmd1_ENP) >> 8, 0, 0, 0); return (OK); /* intentional */ } /* eh = (struct ether_header *)(rmd->rbuf_ladr | (rmd->rbuf_hadr << 16)); ItoK (eh, struct ether_header *, ls->memBase); */ ++ls->ls_if.if_ipackets; /* bump statistic */ eh =(struct ether_header *) ((u_int) ls->rmd_ring.r_bufs + (u_int) ((((u_int)rmd - (u_int)ls->ls_rring) / sizeof(es_rmd)) * ls->bufSize));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -