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

📄 if_ln.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        }    while (pDrvCtrl->tmdIndexC != pDrvCtrl->tmdIndex)        {        /* disposal has not caught up */         tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndexC;         /* if the buffer is still owned by LANCE, don't touch it */         LN_CACHE_INVALIDATE (tmd, TMD_SIZ);        if (tmd->tbuf_stat & TMD_OWN)            break;        /*         * lntmd1_ERR is an "OR" of LCOL, LCAR, UFLO or RTRY.         * Note that BUFF is not indicated in lntmd1_ERR.         * We should therefore check both lntmd1_ERR and lntmd3_BUFF         * here for error conditions.         */        if ((tmd->tbuf_stat & lntmd1_ERR) || (tmd->tbuf_err & lntmd3_BUFF))            {            pDrvCtrl->idr.ac_if.if_oerrors++;     /* output error */            pDrvCtrl->idr.ac_if.if_opackets--;            /*              * If error was due to excess collisions, bump the collision             * counter.  The LANCE does not keep an individual counter of             * collisions, so in this driver, the collision statistic is not             * an accurate count of total collisions.             */            if (tmd->tbuf_err & lntmd3_RTRY)	/* assume DRTY bit not set */                pDrvCtrl->idr.ac_if.if_collisions += 16;            /* check for no carrier */            if (tmd->tbuf_err & TMD_LCAR)                logMsg ("ln%d: no carrier\n", pDrvCtrl->idr.ac_if.if_unit,                         0, 0, 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             * refresh or slow memory could influence this.  Many             * implementations 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->tbuf_err & lntmd3_BUFF) || (tmd->tbuf_err & TMD_UFLO))                {                pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);                logMsg ("lnInt: transmitter underflow\n", 0, 0, 0, 0, 0, 0);                (void) netJobAdd ((FUNCPTR) lnRestart,	        		   pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0);                /* Flush the write pipe */                CACHE_PIPE_FLUSH ();                /* allow interrupt line to go inactive */                i = 3;                while (i-- && (lnCsr0Read (pDrvCtrl) & lncsr_INTR))                    ;                return;                }            }        tmd->tbuf_stat &= 0x00ff; 	/* reset status bits */        tmd->tbuf_err = 0; 		/* clear error bits */       /* now bump the tmd disposal index pointer around the ring */        pDrvCtrl->tmdIndexC = (pDrvCtrl->tmdIndexC + 1) &                              (pDrvCtrl->tringSize - 1);        }    CACHE_PIPE_FLUSH ();		/* flush the write pipe */    /* allow interrupt line to go inactive */    i = 3;    while (i-- && (lnCsr0Read (pDrvCtrl) & lncsr_INTR))        ;    }/********************************************************************************* 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    (    DRV_CTRL *pDrvCtrl    )    {    do {        pDrvCtrl->flags |= LN_RX_HANDLING_FLAG;        while (lnGetFullRMD (pDrvCtrl))            lnRecv (pDrvCtrl);        /*         * 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.         */        pDrvCtrl->flags &= ~LN_RX_HANDLING_FLAG;        }    while (lnGetFullRMD (pDrvCtrl)); /* double check for RACE */    }/********************************************************************************* lnGetFullRMD - check next RMD for ownership**/LOCAL BOOL lnGetFullRMD    (    DRV_CTRL *pDrvCtrl    )    {    int status = FALSE;    ln_rmd *rmd;    if  ((pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) ==        (IFF_UP | IFF_RUNNING))	{        rmd = pDrvCtrl->rring + pDrvCtrl->rmdIndex;        LN_CACHE_INVALIDATE (rmd, RMD_SIZ);        if ((rmd->rbuf_stat & lnrmd1_OWN) == 0)            status = TRUE;	}    return (status);    }/********************************************************************************* lnRecv - process the next incoming packet**/LOCAL STATUS lnRecv    (    DRV_CTRL *pDrvCtrl    )    {    ETH_HDR	*pEnetHdr;    MBUF	*pMbuf = NULL;    ln_rmd	*rmd = pDrvCtrl->rring + pDrvCtrl->rmdIndex;    u_char	*pData;    u_long	pPhys;    int		len;    u_short	type;    /* packet must be checked for errors or possible data chaining */    if ((rmd->rbuf_stat & lnrmd1_ERR) || ((rmd->rbuf_stat &	(lnrmd1_STP | lnrmd1_ENP)) != (lnrmd1_STP | lnrmd1_ENP)))        {        ++pDrvCtrl->idr.ac_if.if_ierrors;	/* bump error stat */        goto cleanRXD;				/* skip to clean up */        }    len = rmd->rbuf_mcnt;			/* get packet length */    len = len - 4; 				/* omit frame check sequence */    /* get pointer to the receive buffer */    pPhys = ((ULONG)pDrvCtrl->pMemPool & 0xff000000) |            ((rmd->rbuf_ladr | (rmd->rbuf_hadr << 16)) & 0x00ffffff);    pEnetHdr = (ETH_HDR *) LN_CACHE_PHYS_TO_VIRT (pPhys);    LN_CACHE_INVALIDATE (pEnetHdr, len);	/* make the pkt data coherent */    /* call input hook if any */    if ((etherInputHookRtn == NULL) || ((*etherInputHookRtn)       (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)) == 0)        {        len -= SIZEOF_ETHERHEADER;	/* adjust length to size of data only */        type = ntohs (pEnetHdr->ether_type);	/* save type field */        pData = ((u_char *) pEnetHdr) + SIZEOF_ETHERHEADER;        /* OK to loan out buffer ? -> build an mbuf cluster */#ifdef BSD43_DRIVER    	if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)))	    pMbuf = build_cluster (pData, len, & pDrvCtrl->idr, MC_LANCE,	        pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)], lnLoanFree,		(int) pDrvCtrl, (int) pEnetHdr,		(int) pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)]);        /* if buffer was successfully turned into mbuf cluster */        if (pMbuf != NULL)	    {            pPhys = (u_long) LN_CACHE_VIRT_TO_PHYS		    (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]);            rmd->rbuf_ladr = pPhys;            rmd->rbuf_hadr = (pPhys >> 16) & lnrmd1_HADR;	    }        else            {            if ((pMbuf = bcopy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if,                pDrvCtrl->memWidth)) == NULL)		{                ++pDrvCtrl->idr.ac_if.if_ierrors;	/* bump error stat */                goto cleanRXD;		}            }        /* send on up... */        do_protocol_with_type (type, pMbuf, & pDrvCtrl->idr, len);#else 	/* BSD43_DRIVER */	if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)) &&	    ((pMbuf = build_cluster (pData, len, &pDrvCtrl->idr.ac_if, MC_LANCE,                                    pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)],                                    (FUNCPTR)lnLoanFree, (int)pDrvCtrl,                                     (int)pEnetHdr,                     (int)pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRx - 1)])) != NULL))	    {            pPhys = (u_long) LN_CACHE_VIRT_TO_PHYS		    (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]);            rmd->rbuf_ladr = pPhys;            rmd->rbuf_hadr = (pPhys >> 16) & lnrmd1_HADR;	    }	else 	    pMbuf = bcopy_to_mbufs (pData, len, 0, &pDrvCtrl->idr.ac_if,                                     pDrvCtrl->memWidth);	if (pMbuf != NULL)	    do_protocol (pEnetHdr, pMbuf, &pDrvCtrl->idr, len);#endif	/* BSD43_DRIVER */         ++pDrvCtrl->idr.ac_if.if_ipackets;	/* bump statistic */        }    /* Done with descriptor, clean up and give it to the device. */cleanRXD:    rmd->rbuf_mcnt = 0;			/* reset count */    rmd->rbuf_stat &= 0xff; 		/* reset status bits */    rmd->rbuf_stat |= lnrmd1_OWN;	/* give device ownership */    CACHE_PIPE_FLUSH ();		/* flush the write pipe */    /* advance our management index */    pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* lnOutput - the driver output routine**/LOCAL int lnOutput    (    IDR  *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    DRV_CTRL	*pDrvCtrl;    char	destEnetAddr [6];	/* space for enet addr */    u_short	packetType;		/* type field for the packet */    ln_tmd	*tmd;    char	*buf;    int		len;    /* check ifnet flags - return error if incorrect. */    if ((pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=	(IFF_UP | IFF_RUNNING))        return (ENETDOWN);    /*     * Attempt to convert socket addr into enet addr and packet type.     * Note that if ARP resolution of the address is required, the ARP     * module will call our routine again to transmit the ARP request     * packet.  This means we may actually call ourselves recursively!     */    if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == FALSE)        return (OK);    /* I KNOW returning OK is stupid, but it is correct */    /* get driver control pointer */    pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];    /*     * Obtain exclusive access to transmitter.  This is necessary because     * certain events can cause netTask to run a job that attempts to transmit     * a packet.  We can only allow one task here at a time.     */    semTake (pDrvCtrl->TxSem, WAIT_FOREVER);    tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndex;    LN_CACHE_INVALIDATE (tmd, TMD_SIZ);    if ((tmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) &        (pDrvCtrl->tringSize - 1)) == pDrvCtrl->tmdIndexC))        {        m_freem (pMbuf);			/* discard data */        pDrvCtrl->idr.ac_if.if_oerrors++;	/* output error */        goto outputDone;        }    buf = pDrvCtrl->tBufBase + (pDrvCtrl->tmdIndex * LN_BUFSIZ);    bcopy_from_mbufs ((buf + SIZEOF_ETHERHEADER), pMbuf, len,		      pDrvCtrl->memWidth);    bcopy (destEnetAddr, buf, 6);    bcopy ((char *) pIDR->ac_enaddr, (buf + 6), 6);    ((ETH_HDR *) buf)->ether_type = packetType;    len += SIZEOF_ETHERHEADER;    len = max (ETHERSMALL, len);    if ((etherOutputHookRtn != NULL) &&        (* etherOutputHookRtn) (&pDrvCtrl->idr.ac_if,buf,len))        {        CACHE_PIPE_FLUSH ();    /* done as a safety */        goto outputDone;        /* goto the end */        }    tmd->tbuf_bcnt = -len;    tmd->tbuf_err = 0;    /* advance our management index */    pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);    tmd->tbuf_stat |= lntmd1_OWN | lntmd1_STP | lntmd1_ENP;    tmd->tbuf_stat &= ~lntmd1_DEF & ~lntmd1_MORE & ~lntmd1_ERR;    CACHE_PIPE_FLUSH ();		/* flush the write pipe */    /* kick start the transmitter, if selected */    if (lnKickStartTx)        lnCsr0Write (pDrvCtrl, (lncsr_INEA | lncsr_TDMD));    pIDR->ac_if.if_opackets++;		/* bump the statistic counter. */outputDone:    semGive (pDrvCtrl->TxSem);		/* release exclusive access. */    return (OK);    }#else	/* BSD43_DRIVER *//********************************************************************************* lnStartOutput - the driver output routine**/LOCAL void lnStartOutput    (    DRV_CTRL *	pDrvCtrl	/* pointer to driver control structure */    )    {    struct mbuf * 	pMbuf = NULL;    ln_tmd *		tmd;    char *		buf;    int			len;    while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)        {	/* dequeue a packet from the transmit queue */        IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);  	tmd = pDrvCtrl->tring + pDrvCtrl->tmdIndex;	LN_CACHE_INVALIDATE (tmd, TMD_SIZ);	if ((tmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) &					       (pDrvCtrl->tringSize - 1)) == 					      pDrvCtrl->tmdIndexC))	    {	    pDrvCtrl->idr.ac_if.if_oerrors++;	/* output error */	    if (pMbuf != NULL)		m_freem (pMbuf); 	/* drop the packet */	    break;	    }	buf = pDrvCtrl->tBufBase + (pDrvCtrl->tmdIndex * LN_BUFSIZ);

⌨️ 快捷键说明

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