⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_lnsgi.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * 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->lnTMD1 & TMD_ERR) || (tmd->lnTMD3 & TMD_BUFF))	    {	    ls->ls_if.if_oerrors++;	/* output error */	    ls->ls_if.if_opackets--;	    /* check for no carrier */	    if (tmd->lnTMD3 & TMD_LCAR)		logMsg ("ln%d lnInt: no carrier\n", ls->ls_if.if_unit, 0, 0, 0, 0, 0);	    /* every lnsgiLogCount errors show other interesting bits of tmd3 */	    if ((tmd->lnTMD3 & 0xfc00) && lnsgiLogCount &&		(ls->ls_if.if_oerrors % lnsgiLogCount) == 0)		logMsg ("ln%d lnInt: xmit error, status(tmd3)=0x%x, err count=%d\n",			ls->ls_if.if_unit, tmd->lnTMD3 & 0xfc00,			ls->ls_if.if_oerrors, 0, 0, 0);	    /* restart chip on fatal errors */	    /*	     * The following code handles the situation where the transmitter 	     * shuts down due to an underflow error.  This is a situation that 	     * will occur if the DMA cannot keep up with the transmitter.	     * It will occur if the LANCE is being held off from DMA access 	     * for too long or due to significant memory latency.  DRAM fresh	     * or slow memory could influence this.  Many implementation use a 	     * dedicated LANCE buffer.  This can be static RAM to eliminate 	     * refresh conflicts or dual-port RAM so that the LANCE can have 	     * free run of this memory during its DMA transfers.	     */	    if ((tmd->lnTMD3 & TMD_BUFF) || (tmd->lnTMD3 & TMD_UFLO))		{/*		logMsg ("ln%d lnInt: xmit error, tmd3=0x%x. (%s/%d)\n", *			ls->ls_if.if_unit, tmd->tbuf_tmd3 & 0xffff, *                        __FILE__, __LINE__); */ 		lnCsrIntWrite (ls, 0, lncsr_STOP);	/* stop the LANCE */		(void) netJobAdd ((FUNCPTR) lnInit, ls->ls_if.if_unit, 				  0, 0, 0, 0);		return;		}	    }	tmd->lnTMD1 &= 0xff;		/* clear high byte */	tmd->lnTMD3 = 0;		/* clear all error & stat stuff */	sysWbFlush ();		/* 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)lnStartOutput, ls->ls_if.if_unit, 			  0, 0, 0, 0);#else        (void) netJobAdd ( (FUNCPTR)lnStartOutput, (int)ls, 0, 0, 0, 0);#endif	}    }/********************************************************************************* lnHandleCsr0Err - task level interrupt service for csr0 errors*/LOCAL void lnHandleCsr0Err    (    FAST struct ls_softc	*ls,    u_short			status     )    {    if (status & lncsr_CERR)	/* collision error */	ls->ls_if.if_collisions++;    if (status & (lncsr_BABL | lncsr_MISS | lncsr_MERR))	{	++ls->csr0Errs;	++ls->ls_if.if_ierrors;	/* every lnsgiLogCount errors show interesting bits of csr0 */	if (lnsgiLogCount && (ls->csr0Errs % lnsgiLogCount) == 0)	    logMsg ("ln%d lnInt: csr0 error, csr0=0x%x, err count=%d\n",		    ls->ls_if.if_unit, status, ls->csr0Errs, 0, 0, 0);	/*	 * restart chip on fatal error 	 */	if (status & lncsr_MERR)	/* memory error */	    (void) netJobAdd ((FUNCPTR) lnInit, ls->ls_if.if_unit, 0, 0, 0, 0);	}    }/********************************************************************************* lnHandleRecvInt - 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 lnHandleRecvInt    (    FAST struct ls_softc *ls     )    {    FAST ln_rmd         *rmd;    FAST int oldIndex;    do	{	ls->ls_flags |= LS_RCV_HANDLING_FLAG;	while ((rmd = lnGetFullRMD (ls)) != NULL)	    {					    /* RMD available */	    oldIndex = ls->ls_rindex;	    if (lnRecv (ls, rmd) == OK)		{		for (; oldIndex != ls->ls_rindex; 		     oldIndex = (oldIndex + 1) & (ls->ls_rsize - 1))		    {		    rmd = ls->ls_rring + oldIndex;    		    cacheClearEntry (rmd, sizeof(ln_rmd));		    LN_RMD_GIVE_TO_LANCE (rmd); sysWbFlush ();		    }		}	    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 (lnGetFullRMD (ls) != NULL);	/* this double check solves the RACE */    }/********************************************************************************* lnRecv -** 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 LANCE yet.*          Otherwise, returns OK to return the RMD back to LANCE.*/LOCAL STATUS lnRecv    (    struct ls_softc	   *ls,    FAST ln_rmd		   *rmd     )    {    FAST struct ether_header	*eh;    FAST struct mbuf		*m;    FAST u_char			*pData;    FAST ln_rmd			*nextRmd;    int				ix, len;    int off = 0;#ifdef BSD43_DRIVER    u_short			ether_type;#endif    /*     * If both STP and ENP are set, LANCE didn't try to     * use data chaining.     */    if (((rmd->lnRMD1 & lnrmd1_STP) == lnrmd1_STP) &&	((rmd->lnRMD1 & lnrmd1_ENP) == lnrmd1_ENP))	{	len = rmd->rbuf_mcnt;	ls->ls_rindex = (ls->ls_rindex + 1) & (ls->ls_rsize - 1);    	sysWbFlush ();	}    else if (((rmd->lnRMD1 & lnrmd1_STP) == lnrmd1_STP) &&	     ((rmd->lnRMD1 & lnrmd1_ENP) == 0))	{	/* STP is set but ENP is not set, so LANCE is trying	 * to use data chaining.  We scan the following sequence of	 * RMD's to find the last buffer in this data chain.	 */	ix = (ls->ls_rindex + 1) & (ls->ls_rsize - 1);	do	    {	    nextRmd = ls->ls_rring + ix;		/* next rmd */	    /* Return if the next rmd is not ready.  Try later. */   	    cacheClearEntry(rmd, sizeof(ln_rmd));	    if ((nextRmd->lnRMD1 & lnrmd1_OWN) != 0)	        return (ERROR);	    ix = (ix + 1) & (ls->ls_rsize - 1);	    }	/* end of packet? */	while ((nextRmd->lnRMD1 & lnrmd1_ENP) == 0);		/* This last RMD contains the valid MCNT. */	ls->ls_rindex = ix;        sysWbFlush ();	len = nextRmd->rbuf_mcnt;	}    else	{	ls->ls_rindex = (ls->ls_rindex + 1) & (ls->ls_rsize - 1);        sysWbFlush ();	++ls->ls_if.if_ierrors;	if (lnsgiLogCount && (ls->ls_if.if_ierrors % lnsgiLogCount) == 0)	    logMsg ("ln%d lnRecv: receive error, stp %d enp %d\n",		    ls->ls_if.if_unit,	            (rmd->lnRMD1 & lnrmd1_STP) >> 9,	            (rmd->lnRMD1 & lnrmd1_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(ln_rmd)) 	* ls->bufSize));    cacheClearEntry (eh, len);    /* call input hook if any */    if ((etherInputHookRtn != NULL) &&	(* etherInputHookRtn) (&ls->ls_if, (char *)eh, len))	return (OK);#ifdef BSD43_DRIVER    /* This legacy code is not correct for the BSD 4.4 stack. It would     * also treat multicast addresses like alien packets, and not send     * them up the stack. The higher-level protocols in the new stack     * can handle these addresses, and will discard them if they do not     * match an existing multicast group.     */    /* do software filter if controller is in promiscuous mode */    if (ls->ls_flags & LS_PROMISCUOUS_FLAG)        if ( (bcmp ( (char *)eh->ether_dhost,	/* not our adrs? */                     (char *)ls->ls_enaddr,                    sizeof (eh->ether_dhost)) != 0) &&             (bcmp ( (char *)eh->ether_dhost,	/* not broadcast? */                     (char *)etherbroadcastaddr,                    sizeof (eh->ether_dhost)) != 0))            return (OK);#endif    if (len >= sizeof (struct ether_header))        len -= sizeof (struct ether_header);    else        len = 0;    pData = ( (u_char *)eh) + (sizeof (struct ether_header)); #ifdef BSD43_DRIVER    check_trailer (eh, pData, &len, &off, &ls->ls_if);    if (len == 0)	return (OK);    ether_type = eh->ether_type;#endif    m = NULL;    /*     * we can loan out receive buffers from LANCE receive ring if:     *     * 1) canLoanRmd is TRUE.  canLoanRmd is set to TRUE if memWidth     *    is NONE (no special restriction in copying data in terms of     *    size and boundary conditions) and each of the buffers in the     *    LANCE ring is big enough to hold the maximum sized ethernet     *    frame (data-chaining is not being used for the input).     * 2) trailer protocol is not being used for the given input ethernet frame.     * 3) there is available free buffers that can be used to replace the     *    rbuf to be loaned out in the free list 'freeBufs'.     * 4) size of the input ethernet frame is large enough to be used with     *    clustering.     */        if (ls->canLoanRmds && off == 0 && ls->nFree > 0 && USE_CLUSTER (len))	{        m = build_cluster (pData, len, &ls->ls_if, MC_LANCE,                           &(ls->loanRefCnt [ls->ls_rindex]),                           lnRmdFree, (int) ls, (int) eh, NULL);        if (m != NULL)            {            FAST char *pBuf;            /* get a free buffer from the free list to replace the             * rbuf loaned out.  replace the rbuf pointers in the RMD             * to point to the new buffer.	     */	                pBuf = ls->freeBufs [--ls->nFree];	                rmd->rbuf_ladr = (int) pBuf;            rmd->lnRMD1 = (rmd->lnRMD1 & ~lnrmd1_HADR)	                    | (((int) pBuf >> 16) & lnrmd1_HADR);            sysWbFlush ();            }        }    if (m == NULL)#ifdef BSD43_DRIVER        /*         * Instead of calling copy_to_mbufs (), we call bcopy_to_mbufs ()         * with ls->memWidth as an addtional argument to specify unit of a         * copy op.         *         * Most drivers would use macro copy_to_mbufs (), which will in turn         * call bcopy_to_mbufs () telling it to use the normal bcopy ().  Some         * of the on-board LANCE hardware implementations require that you         * copy the data by certain number of bytes from dedicated memory         * to system memory, so LANCE driver has a ln_bcopy () routine that         * conforms to this requirement.         */        m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &ls->ls_if,                            ls->memWidth);#else        m = copy_to_mbufs (pData, len, 0, &ls->ls_if);#endif    if (m == NULL)        ls->ls_if.if_ierrors++;    else#ifdef BSD43_DRIVER        do_protocol_with_type (ether_type, m, &ls->ls_ac, len);#else        do_protocol (eh, m, &ls->ls_ac, len);#endif            return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* lnOutput -** 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.*/LOCAL int lnOutput    (    FAST struct ifnet	*ifp,    FAST struct mbuf	*m0,    struct sockaddr	*dst     )    {    return (ether_output (ifp, m0, dst, (FUNCPTR) lnStartOutput, 			  &ls_softc [ifp->if_unit]->ls_ac));    }#endif/********************************************************************************* lnStartOutput - start pending output** Start output to LANCE.* Queue up all pending datagrams for which transmit buffers are available.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -