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

📄 ln97xend.c

📁 vxWorks下AMD973芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    else
        return ((LN_RMD *) NULL);
    }

/*******************************************************************************
*
* ln97xRecv - process the next incoming packet
*
* RETURNS: OK/ERROR
*/

LOCAL STATUS ln97xRecv
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl, /* device to be initialized */
    LN_RMD *		pRmd
    )
    {
    int         	len;
    M_BLK_ID    	pMblk;
    char *       	pCluster;
    char *       	pNewCluster;
    char *       	pTemp;
    CL_BLK_ID   	pClBlk;
    UINT32		rmd1Tmp;

    /* Packet must be checked for errors, Read rmd1 once only */

    rmd1Tmp = PCI_SWAP (pRmd->rBufRmd1);

    DRV_LOG (DRV_DEBUG_TX, "Recv : rmd1 = %X index = %d\n", rmd1Tmp,
             pDrvCtrl->rmdIndex, 3, 4, 5, 6);

    /* If error flag OR if packet is not completely in one buffer */

    if  ((rmd1Tmp & RMD1_ERR) ||
          (rmd1Tmp & (RMD1_STP | RMD1_ENP)) != (RMD1_STP | RMD1_ENP))
	{
        DRV_LOG (DRV_DEBUG_RX, "RMD error!\n", 1, 2, 3, 4, 5, 6);
        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
        goto cleanRXD;                          /* skip to clean up */
	}

    /* If we cannot get a buffer to loan then bail out. */

    pNewCluster = netClusterGet (pDrvCtrl->endObj.pNetPool,
                                 pDrvCtrl->pClPoolId);

    if (pNewCluster == NULL)
        {
        DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6);
        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
        goto cleanRXD;
        }

    if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
        {
        netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster);
        DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6);
        END_ERR_ADD (&pDrvCtrl->endObj, 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->endObj.pNetPool, M_DONTWAIT, MT_DATA))
        == NULL)
        {
        netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
        netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster);
        DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6);
        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
        goto cleanRXD;
        }

    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);

    len = LN_PKT_LEN_GET (pRmd);	/* get packet length */

    LN_RMD_TO_ADDR (pRmd, pCluster);	/* Get pointer to packet */

    pCluster -= pDrvCtrl->offset;
    
    DRV_LOG (DRV_DEBUG_RX, "Packet @ 0x%X for %d bytes!\n", pCluster,
             len, 3, 4, 5, 6);

    /* 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;

    /* Give receiver a new buffer */

    LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pNewCluster);

    /* Call the upper layer's receive routine. */

    END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);

cleanRXD:
    /* clear status bits */

    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);
    }

/*******************************************************************************
*
* lnSend - 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 ln97xSend
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl,  /* device to be initialized */
    M_BLK_ID 		pMblk      /* data to send */
    )
    {
    LN_TMD *		pTmd;
    UINT32		ltmd1;
    void *       	pTemp;
    char *       	pBuf;
    char *       	pOrig;
    int         	level;
    int         	len = 0;

    /*
     * 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->endObj, WAIT_FOREVER);

    pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;

    DRV_LOG (DRV_DEBUG_TX, "Send : index %d tmd = 0x%X\n",
             pDrvCtrl->tmdIndex, (int)pTmd, 3, 4, 5, 6);

    LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);

    ltmd1 = PCI_SWAP (pTmd->tBufTmd1);
    
    if ((ltmd1 & TMD1_OWN) ||
	(((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))
         == pDrvCtrl->tmdIndexC))
        {
        if (!(pDrvCtrl->flags & LS_POLLING))
            END_TX_SEM_GIVE (&pDrvCtrl->endObj);

        /* Are we still on the first chunk? */

        DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!\n", 1, 2, 3, 4, 5, 6);

        level = intLock ();

        pDrvCtrl->txBlocked = TRUE;

        intUnlock (level);
        return (END_ERR_BLOCK);
        }

    DRV_LOG (DRV_DEBUG_TX, "before cluster get %d %d\n",
             pDrvCtrl->endObj.pNetPool,
             pDrvCtrl->pClPoolId, 3, 4, 5, 6);

    pOrig = pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool,
                                  pDrvCtrl->pClPoolId);

    DRV_LOG (DRV_DEBUG_TX, "after cluster get pBuf = 0x%X\n",
             (int)pBuf, 2, 3, 4, 5, 6);

    if (pBuf == NULL)
        {
        netMblkClChainFree(pMblk);
        return (ERROR);
        }

    pBuf += pDrvCtrl->offset;	/* take care of the alignment */

    len = netMblkToBufCopy (pMblk, pBuf, NULL);
    netMblkClChainFree(pMblk);
    LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf);
    len = max (len, ETHERSMALL);
    pTmd->tBufTmd2 = 0;         /* clear buffer error status */

    ltmd1 = TMD1_STP | TMD1_ENP | TMD1_CNST;
    ltmd1 |= (TMD1_BCNT_MSK & -len);
    pTmd->tBufTmd1 = PCI_SWAP (ltmd1);

    CACHE_PIPE_FLUSH ();
    LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);

    ltmd1 |= TMD1_OWN;

    DRV_LOG (DRV_DEBUG_TX, "TMD1 = 0x%X\n", ltmd1, 2, 3, 4, 5, 6);
    
    /* write to actual register */

    pTmd->tBufTmd1 = PCI_SWAP (ltmd1);

    pDrvCtrl->freeRtn [pDrvCtrl->tmdIndex] = (FUNCPTR)netClFree;
    pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg1 = pDrvCtrl->endObj.pNetPool;
    pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg2 = pOrig;

    /* Advance our management index */

    pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);

    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();

    if (lnKickStartTx)
        {
        if (!(pDrvCtrl->flags & LS_POLLING))
            ln97xCsrWrite (pDrvCtrl, 0, (CSR0_INTMASK | CSR0_TDMD));
        else
            ln97xCsrWrite (pDrvCtrl, 0, CSR0_TDMD);
        }

    if (!(pDrvCtrl->flags & LS_POLLING))
        END_TX_SEM_GIVE (&pDrvCtrl->endObj);

    /* Bump the statistic counter. */

    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);

    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	 /* date to get or set */
    )
    {
    long 		value;
    int 		error = 0;

    switch (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:
	    value = (long)data;
            
	    if (value < 0)
		{
		value = -value;
		value--;		/* HELP: WHY ??? */
		END_FLAGS_CLR (&pDrvCtrl->endObj, value);
		}
	    else
		{
		END_FLAGS_SET (&pDrvCtrl->endObj, value);
		}
	    ln97xConfig (pDrvCtrl);
            break;
        case EIOCGFLAGS:
	    *(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj);
            break;

	case EIOCPOLLSTART:
	    error = ln97xPollStart (pDrvCtrl);
	    break;

	case EIOCPOLLSTOP:
	    error = ln97xPollStop (pDrvCtrl);
	    break;

        case EIOCGMIB2:
            if (data == NULL)
                return (EINVAL);
            bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
                  sizeof(pDrvCtrl->endObj.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);
    }

/*******************************************************************************
*
* ln97xReset - hardware reset of chip (stop it)
*
* This routine is responsible for resetting the device and switching into
* 32 bit mode.
*
* RETURNS: OK/ERROR
*/

LOCAL int ln97xReset
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl /* device to be initialized */
    )
    {
    UINT32 		resetTmp;

    /* Enable 32 bit access by doing a 32 bit write */

    SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRdp, 0);

    ln97xCsrWrite (pDrvCtrl, CSR(0), CSR0_STOP);
    
    /* Generate a soft-reset of the controller */

    SYS_IN_LONG(pDrvCtrl, pDrvCtrl->pReset, resetTmp);

    /* This isn't a real test - it just stops the compiler ignoring the read */

    if (resetTmp == 0x12345678)
	return (ERROR);

    ln97xBcrWrite (pDrvCtrl, BCR(20), BCR20_SWSTYLE_PCNET);

    /* autoselect port tye - 10BT or AUI */
    ln97xBcrWrite (pDrvCtrl, BCR(2), BCR2_AUTO_SELECT); 

    /* read BCR */
    resetTmp = ln97xBcrRead (pDrvCtrl, BCR(20));

    return (OK);
    }

/*******************************************************************************
*
* ln97xCsrWrite - select and write a CSR register
*
* This routine selects a register to write, through the RAP register and
* then writes the CSR value to the RDP register.
*
* RETURNS: N/A
*/

LOCAL void ln97xCsrWrite
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl, /* device to be initialized */
    int 		reg,	 /* CSR register to select */
    UINT32 		value	 /* CSR value to write */
    )
    {
    int 		level;

    level = intLock ();

    /* select CSR */

    reg &= 0xff;

    SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP (reg));

    CACHE_PIPE_FLUSH ();

    value &=0xffff;

⌨️ 快捷键说明

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