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

📄 ln97xend.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
LOCAL void ln97xHandleError    (    LN_97X_DRV_CTRL * pDrvCtrl,   /* pointer to DRV_CTRL structure */    UINT32            csr0Errors  /* holds error bits read from CSR0 */    )    {    pDrvCtrl->errorHandling = FALSE;    if (csr0Errors & CSR0_MERR)        {        pDrvCtrl->lastError.errCode = END_ERR_WARN;        pDrvCtrl->lastError.pMesg   = "Bus master REQ timeout";        muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);        }    if (csr0Errors & CSR0_BABL)        {        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);        pDrvCtrl->lastError.errCode = END_ERR_WARN;        pDrvCtrl->lastError.pMesg   = "Babbling";        muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);        }    if (csr0Errors & CSR0_MISS)        {        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);        pDrvCtrl->lastError.errCode = END_ERR_WARN;        pDrvCtrl->lastError.pMesg   = "Missing";        muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);        }    }/********************************************************************************* ln97xInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A*/LOCAL void ln97xInt    (    LN_97X_DRV_CTRL * pDrvCtrl  /* pointer to DRV_CTRL structure */    )    {    /* assume no errors */    UINT32 errs = 0;    /* Read the device status register */    UINT32 stat = csrLockedRead (pDrvCtrl, CSR(0));    /* If false interrupt, return. */    if (! (stat & CSR0_INTR))        {        return;        }    /* clear interrupt status, error status, and interrupt enable bits */    csrLockedWrite (pDrvCtrl, CSR(0), stat & (~CSR0_INEA));    /* check for any one, or a combination, of (3) error types */    errs = (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR));    if ((errs) && !(pDrvCtrl->errorHandling))        {        /* put a task level error handler on the netTask job queue */        if (netJobAdd ((FUNCPTR) ln97xHandleError,           (int) pDrvCtrl, (int) errs, 0, 0, 0) == OK)            {            pDrvCtrl->errorHandling = TRUE;            }        }    /* process received frame descriptors */    if ((stat & CSR0_RINT) && !(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG))        {        /* put a task level input packet handler on the netTask job queue */        if (netJobAdd ((FUNCPTR) ln97xHandleRecvInt,           (int) pDrvCtrl, 0,0,0,0) == OK)            {            pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;            }        }    /* process transmitted frame descriptors */    if ((stat & CSR0_TINT) && !(pDrvCtrl->txCleaning))        {        if (netJobAdd ((FUNCPTR) ln97xTRingScrub,           (int) pDrvCtrl, 0, 0, 0, 0) == OK)            {            pDrvCtrl->txCleaning = TRUE;            }        }    if (pDrvCtrl->txBlocked)    /* cause a MUX restart */        {        if (netJobAdd ((FUNCPTR) muxTxRestart,           (int) &pDrvCtrl->endObj, 0, 0, 0, 0) == OK)            {            pDrvCtrl->txBlocked = FALSE;            }        }    /* reenable device-side interrupts */    csrWrite (pDrvCtrl, CSR(0), CSR0_INEA);    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    }/********************************************************************************* ln97xHandleRecvInt - 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 ln97xHandleRecvInt    (    LN_97X_DRV_CTRL * pDrvCtrl  /* points to DRV_CTRL structure */    )    {    LN_RMD *          pRmd = (LN_RMD *) NULL;    do        {        pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;        while ((pRmd = ln97xFullRMDGet (pDrvCtrl)) != (LN_RMD *) NULL)             {            ln97xRecv (pDrvCtrl, pRmd);            }        /*         * 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 &= ~LS_RCV_HANDLING_FLAG;        }    while (ln97xFullRMDGet (pDrvCtrl) != NULL);    /* this double check solves the RACE */    }/********************************************************************************* ln97xRecv - process the next incoming packet** RETURNS: OK or ERROR.*/LOCAL STATUS ln97xRecv    (    LN_97X_DRV_CTRL * pDrvCtrl,  /* points to device control structure */    LN_RMD *          pRmd    )    {    int               len;    CL_BLK_ID         pClBlk;    M_BLK_ID          pMblk;    char *            pCluster;    char *            pNewCluster;    /* alias frequently referenced device control fields */    const int         offset   = pDrvCtrl->offset;    END_OBJ * const   pEndObj  = &(pDrvCtrl->endObj);    NET_POOL_ID const pNetPool = pEndObj->pNetPool;    DRV_LOG (DRV_DEBUG_RX, "Recv : index %d rmd = 0x%X\n",             pDrvCtrl->rmdIndex, (int) pRmd, 3, 4, 5, 6);    /* If error flag OR if packet is not completely in one buffer */    if  (rmdHasErrors (pRmd))        {        END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);        goto cleanRXD;        }    /* If we cannot get a buffer to loan then bail out */    if ((pNewCluster = netClusterGet (pNetPool, pDrvCtrl->pClPoolId)) == NULL)        {#if defined(END_ERR_NO_BUF)        pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;        muxError (pEndObj, &pDrvCtrl->lastError);#endif  /* defined(END_ERR_NO_BUF) */        END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);        goto cleanRXD;        }    if ((pClBlk = netClBlkGet (pNetPool, M_DONTWAIT)) == NULL)        {        netClFree (pNetPool, (UCHAR *) pNewCluster);        END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);        goto cleanRXD;        }    /* get an <mBlk> and join it to the cluster from the RMD */    if ((pMblk = mBlkGet (pNetPool, M_DONTWAIT, MT_DATA)) == NULL)        {        netClBlkFree (pNetPool, pClBlk);        netClFree (pNetPool, (UCHAR *) pNewCluster);        END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);        goto cleanRXD;        }    /* get the packet length & a pointer to the packet */    len = LN_PKT_LEN_GET (pRmd);    pCluster  = rmdBuffAddrGet (pDrvCtrl, pRmd);    pCluster -= offset;    END_ERR_ADD (pEndObj, MIB2_IN_UCAST, +1);    /* 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  += offset;    pMblk->mBlkHdr.mLen    = len;    pMblk->mBlkHdr.mFlags |= M_PKTHDR;    pMblk->mBlkPktHdr.len  = len;    /* Give receiver a new buffer */    pNewCluster += offset;    rmdBuffAddrSet (pDrvCtrl, pRmd, pNewCluster);    /* Call the upper layer's receive routine */    END_RCV_RTN_CALL (pEndObj, pMblk);cleanRXD:    /* return a clean descriptor to the controller */    rxDescClean (pRmd);    CACHE_PIPE_FLUSH ();    /* increment index to RMD ring */    pDrvCtrl->rmdIndex = ((pDrvCtrl->rmdIndex + 1) % (pDrvCtrl->rringSize));    return (OK);    }/********************************************************************************* ln97xSend - 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.** CAVEATS* Assumes that the TMD returned from ln97xTMDGet() has been "cleaned".* Assumes that the TMD will not be inadvertently cleaned while the* TMD is being constructed and before the controller has been given* ownersip of the TMD.** RETURNS: OK or ERROR.*/LOCAL STATUS ln97xSend    (    LN_97X_DRV_CTRL * pDrvCtrl,  /* device to be initialized */    M_BLK_ID          pMblk      /* data to send */    )    {    volatile LN_TMD * pTmd;    UINT32            ltmd1;    char *            pBuf;    int               len = 0;    /* check device mode */    if (pDrvCtrl->flags & LS_POLLING)        {        netMblkClChainFree (pMblk);        errno = EINVAL;        return (ERROR);        }    /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */    END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);    pTmd = ln97xTMDGet (pDrvCtrl);    DRV_LOG (DRV_DEBUG_TX, "Send : index %d tmd = 0x%X\n",             pDrvCtrl->tmdIndex, (int) pTmd, 3, 4, 5, 6);    if (pTmd == NULL)        {        pDrvCtrl->txBlocked = TRUE;        END_TX_SEM_GIVE (&pDrvCtrl->endObj);        return (END_ERR_BLOCK);        }    if ((pBuf = netClusterGet        (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL)        {        pDrvCtrl->txBlocked = TRUE;        END_TX_SEM_GIVE (&pDrvCtrl->endObj);        return (END_ERR_BLOCK);        }    pBuf += pDrvCtrl->offset;    len = netMblkToBufCopy (pMblk, pBuf, NULL);    /* increment the unicast output counter */    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);    netMblkClChainFree (pMblk);    tmdBuffAddrSet (pDrvCtrl, pTmd, pBuf);    ltmd1 = (TMD1_BCNT_MSK & -(max (len, ETHERSMALL))) |            (TMD1_OWN | TMD1_CNST | TMD1_STP | TMD1_ENP);    /* increment index to TMD ring */    pDrvCtrl->tmdIndex = ((pDrvCtrl->tmdIndex + 1) % (pDrvCtrl->tringSize));    /* write transmit descriptor (with OWN-bit set) to actual register */    pTmd->lnTMD1 = PCI_SWAP (ltmd1);    CACHE_PIPE_FLUSH ();    if (lnKickStartTx)        {        csrLockedWrite (pDrvCtrl, CSR(0), (CSR0_INEA | CSR0_TDMD));        }    END_TX_SEM_GIVE (&pDrvCtrl->endObj);    return (OK);    }/********************************************************************************* ln97xIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS OK or ERROR value*/LOCAL int ln97xIoctl    (    LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */    int               cmd,      /* ioctl command to execute */    caddr_t           data      /* data to get or set */    )    {    int    error = 0;    switch ((UINT)cmd)        {        case EIOCSADDR:            if (data == NULL)                return (EINVAL);            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),                   END_HADDR_LEN (&pDrvCtrl->endObj));            break;        case EIOCGADDR:            if (data == NULL)                return (EINVAL);            bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data,                   END_HADDR_LEN (&pDrvCtrl->endObj));            break;        case EIOCSFLAGS:       

⌨️ 快捷键说明

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