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

📄 ln7990end.c

📁 7990驱动编程
💻 C
📖 第 1 页 / 共 5 页
字号:
*/LOCAL STATUS ln7990Recv    (    LN7990END_DEVICE *pDrvCtrl,    ln_rmd   *pRmd    )    {    int         len;    u_long	phys;    M_BLK_ID 	pMblk;    char*       pCluster;    char*       pNewCluster;    char*       pTemp;    CL_BLK_ID	pClBlk;    /* Packet must be checked for errors. */    /* If error flag */    /* OR if packet is not completely in one buffer */    if  (LN_RMD_ERR (pRmd))        {	DRV_LOG (DRV_DEBUG_RX, "RMD error!\n", 1, 2, 3, 4, 5, 6);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }    /* If we cannot get a buffer to loan then bail out. */    pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);    if (pNewCluster == NULL)        {	DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }    if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)        {        netClFree (pDrvCtrl->end.pNetPool, pNewCluster);	DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }        /*     * OK we've got a spare, let's get an M_BLK_ID and marry it to the     * one in the ring.     */    if ((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)        {        netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);	DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }    END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);    len = LN_PKT_LEN_GET (pRmd);           		/* get packet length */    /* Get pointer to packet */    LN_RMD_TO_ADDR (pDrvCtrl->memBase , pRmd, phys);    pCluster = LN_CACHE_PHYS_TO_VIRT (phys);    pCluster -= pDrvCtrl->offset;        /* Join the cluster to the MBlock */    netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);    netMblkClJoin (pMblk, pClBlk);    /* make the packet data coherent */    LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);    pMblk->mBlkHdr.mData += pDrvCtrl->offset;    pMblk->mBlkHdr.mLen = len;    pMblk->mBlkHdr.mFlags |= M_PKTHDR;    pMblk->mBlkPktHdr.len = len;    DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6);    /* Deal with memory alignment. */    pNewCluster += pDrvCtrl->offset;    LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pNewCluster);    LN_CLEAN_RXD (pRmd);    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    /* Advance our management index */    pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);    /* Call the upper layer's receive routine. */    END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);    return (OK);cleanRXD:    LN_CLEAN_RXD (pRmd);    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    /* Advance our management index */    pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);    return (OK);    }/********************************************************************************* ln7990Send - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it.  This is done by a higher layer.  The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine.  ** RETURNS: OK or ERROR.*/LOCAL STATUS ln7990Send    (    LN7990END_DEVICE *pDrvCtrl,	/* device ptr */    M_BLK_ID pMblk	/* data to send */    )    {    ln_tmd*	pTmd;    int         len = 0;    void*       pTemp;    char*       pBuf;    char*       pOrig;    int         s;    /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */    if (!(pDrvCtrl->flags & LS_POLLING))	END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);    /*     * Here we handle both simple and vector transmit in the same place.     *     */#if 0    {    M_BLK_ID    pChunk;    int         count;    pChunk = pMblk;    for (count = 0; pChunk != NULL && (pChunk->mBlkHdr.mData != 0);         pChunk = pChunk->m_next, count++)        {        if (pChunk->mBlkHdr.mLen <= 0)            {            netMblkClFree(pChunk);            continue;            }        pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;                LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);                if ((pTmd->tbuf_stat & lntmd1_OWN) ||            (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))             == pDrvCtrl->tmdIndexC))            {            if (!(pDrvCtrl->flags & LS_POLLING))                END_TX_SEM_GIVE (&pDrvCtrl->end);            /* Are we still on the first chunk? */            if (count == 0)                netMblkClChainFree(pMblk);            else /* Have to iteratively clean up. */                {                                }            DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!\n", 1, 2, 3, 4, 5, 6);            return (END_ERR_BLOCK);            }        len = pChunk->mBlkHdr.mLen;        LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pChunk->mBlkHdr.mData);        pTmd->tbuf_err = 0;         /* clear buffer error status */        pTmd->tbuf_bcnt = -len;     /* negative message byte count */                if (count == 0)            pTmd->tbuf_stat |=  lntmd1_STP;                pTmd->tbuf_stat |= lntmd1_OWN;        pDrvCtrl->freeRtn[pDrvCtrl->tmdIndex] = (FUNCPTR)netMblkClFree;        pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg1 = pChunk;        pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg2 = NULL;        /* Advance our management index */        pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);                }        /* On the final tmd we set the END bit as well as OWN. */    pTmd->tbuf_stat |= lntmd1_OWN | lntmd1_ENP;    /* If we only have one TMD for the packet then make sure of size. */    if (count == 1)        {        len = max (len, ETHERSMALL);        pTmd->tbuf_bcnt = -len;        }        }#else    pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;        LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);        if ((pTmd->tbuf_stat & lntmd1_OWN) ||        (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))         == pDrvCtrl->tmdIndexC))        {        if (!(pDrvCtrl->flags & LS_POLLING))            END_TX_SEM_GIVE (&pDrvCtrl->end);        /* Are we still on the first chunk? */        DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!\n", 1, 2, 3, 4, 5, 6);        s = intLock();	pDrvCtrl->txBlocked = TRUE;        intUnlock(s);        return (END_ERR_BLOCK);        }    DRV_LOG (DRV_DEBUG_TX, "before cluster get %d %d\n",             (int) pDrvCtrl->end.pNetPool,             (int) pDrvCtrl->pClPoolId, 3, 4, 5, 6);    pOrig = pBuf = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);    DRV_LOG (DRV_DEBUG_TX, "after cluster get\n", 1, 2, 3, 4, 5, 6);    if (pBuf == NULL)        {	if (!(pDrvCtrl->flags & LS_POLLING))	    END_TX_SEM_GIVE (&pDrvCtrl->end);        netMblkClChainFree(pMblk);        return (ERROR);        }    pBuf += pDrvCtrl->offset;        len = netMblkToBufCopy (pMblk, pBuf, NULL);    netMblkClChainFree(pMblk);     LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf);    len = max (len, ETHERSMALL);    pTmd->tbuf_err = 0;         /* clear buffer error status */    pTmd->tbuf_bcnt = -len;     /* negative message byte count */            pTmd->tbuf_stat |=  lntmd1_STP | lntmd1_OWN | lntmd1_ENP;        pDrvCtrl->freeRtn[pDrvCtrl->tmdIndex] = (FUNCPTR)netClFree;    pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg1 = pDrvCtrl->end.pNetPool;    pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg2 = pOrig;    /* Advance our management index */    pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);#endif    /* Flush the write pipe */        CACHE_PIPE_FLUSH ();        if (lnKickStartTx)        {        if (!(pDrvCtrl->flags & LS_POLLING))	    ln7990CsrWrite (pDrvCtrl, 0, (lncsr_INEA | lncsr_TDMD));	else	    ln7990CsrWrite (pDrvCtrl, 0, lncsr_TDMD);	}        if (!(pDrvCtrl->flags & LS_POLLING))	END_TX_SEM_GIVE (&pDrvCtrl->end);        /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);    return (OK);    }/********************************************************************************* ln7990Ioctl - the driver I/O control routine** Process an ioctl request.*/LOCAL int ln7990Ioctl    (    LN7990END_DEVICE *pDrvCtrl,    int cmd,    caddr_t data    )    {    int error = 0;    long value;    switch (cmd)        {        case EIOCSADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),		   END_HADDR_LEN(&pDrvCtrl->end));            break;        case EIOCGADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,		    END_HADDR_LEN(&pDrvCtrl->end));            break;        case EIOCSFLAGS:	    value = (long)data;	    if (value < 0)		{		value = -value;		value--;		/* HELP: WHY ??? */		END_FLAGS_CLR (&pDrvCtrl->end, value);		}	    else		{		END_FLAGS_SET (&pDrvCtrl->end, value);		}	    ln7990Config (pDrvCtrl);            break;        case EIOCGFLAGS:	    *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);            break;	case EIOCPOLLSTART:	    error = ln7990PollStart (pDrvCtrl);	    break;	case EIOCPOLLSTOP:	    error = ln7990PollStop (pDrvCtrl);	    break;        case EIOCGMIB2:            if (data == NULL)                return (EINVAL);            bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,                  sizeof(pDrvCtrl->end.mib2Tbl));            break;        case EIOCGFBUF:            if (data == NULL)                return (EINVAL);            *(int *)data = LN_MIN_FBUF;            break;        case EIOCGMWIDTH:            if (data == NULL)                return (EINVAL);            *(int *)data = pDrvCtrl->memWidth;            break;        case EIOCGHDRLEN:            if (data == NULL)                return (EINVAL);            *(int *)data = 14;            break;        default:            error = EINVAL;        }    return (error);    }/********************************************************************************* ln7990Reset - hardware reset of chip (stop it)*/LOCAL void ln7990Reset    (    LN7990END_DEVICE  *pDrvCtrl    )    {    ln7990CsrWrite (pDrvCtrl, 0, lncsr_STOP);    }/********************************************************************************* ln7990Csr0Read - read CSR 0 register** Assumes normal operation, where the RAP register has been left selecting* CSR0.*/LOCAL u_short ln7990Csr0Read    (    LN7990END_DEVICE * pDrvCtrl		/* driver control */    )    {    USHORT result;    SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->pCsr, &result);    return (result);		/* get contents of CSR */    }/********************************************************************************* ln7990CsrWrite - select and write a CSR register**/LOCAL void ln7990CsrWrite    (    LN7990END_DEVICE * pDrvCtrl,	/* driver control */    int reg,				/* register to select */    u_short value			/* value to write */    )    {    int level;    level = intLock ();    SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->pRap, (u_short)reg);    SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->pCsr, value);    intUnlock (level);    }

⌨️ 快捷键说明

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