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

📄 ln97xend.c

📁 vxWorks下AMD973芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /***** Establish a region of shared memory *****/

    /* OK. We now know how much shared memory we need.  If the caller
     * provides a specific memory region, we check to see if the provided
     * region is large enough for our needs.  If the caller did not
     * provide a specific region, then we attempt to allocate the memory
     * from the system, using the cache aware allocation system call.
     */

    switch ((int) pDrvCtrl->memAdrs)
	{
	default :       /* caller provided memory */
	    if (pDrvCtrl->memSize < sz)     /* not enough space */
		{
		DRV_LOG (DRV_DEBUG_LOAD, "ln97x: not enough memory provided\n"
			 "ln97x: need %ul got %d\n",
			 sz, pDrvCtrl->memSize, 3, 4, 5, 6);
		return (NULL);
                }

	    /* set the beginning of pool */

	    pDrvCtrl->pShMem = pDrvCtrl->memAdrs;

	    /* assume pool is cache coherent, copy null structure */

	    pDrvCtrl->cacheFuncs = cacheNullFuncs;
	    DRV_LOG (DRV_DEBUG_LOAD, "Memory checks out\n", 1, 2, 3, 4, 5, 6);
	    break;

        case NONE :     /* get our own memory */

	    /* Because the structures that are shared between the device
	     * and the driver may share cache lines, the possibility exists
	     * that the driver could flush a cache line for a structure and
	     * wipe out an asynchronous change by the device to a neighboring
	     * structure. Therefore, this driver cannot operate with memory
	     * that is not write coherent.  We check for the availability of
	     * such memory here, and abort if the system did not give us what
	     * we need.
	     */

	    if (!CACHE_DMA_IS_WRITE_COHERENT ())
		{
		printf ( "ln97x: device requires cache coherent memory\n" );
		return (ERROR);
		}

	    pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz);

	    if ((int)pDrvCtrl->pShMem == NULL)
		{
		printf ( "ln97x: system memory unavailable\n" );
		return (ERROR);
		}

	    /* copy the DMA structure */

	    pDrvCtrl->cacheFuncs = cacheDmaFuncs;

            break;
        }

    /*                        Turkey Carving
     *                        --------------
     *
     *                          LOW MEMORY
     *
     *             |-------------------------------------|
     *             |       The initialization block      |
     *             |         (sizeof (LN_IB))            |
     *             |-------------------------------------|
     *             |         The Rx descriptors          |
     *             | (1 << lnRsize) * sizeof (LN_RMD)|
     *             |-------------------------------------|
     *             |         The Tx descriptors          |
     *             | (1 << lnTsize) * sizeof (LN_TMD)|
     *             |-------------------------------------|
     */

    /* Save some things */

    pDrvCtrl->memBase  = (char *)((UINT32)pDrvCtrl->pShMem & 0xff000000);

    if ((int) pDrvCtrl->memAdrs == NONE)
        pDrvCtrl->flags |= LS_MEM_ALLOC_FLAG;

    /* first let's clear memory */

    bzero ( (char *) pDrvCtrl->pShMem, (int) sz );

    /* setup Rx memory pointers */

    pDrvCtrl->pRring    = (LN_RMD *) ((int)pDrvCtrl->pShMem + IB_SIZ);
    pDrvCtrl->rringLen  = lnRsize;
    pDrvCtrl->rringSize = 1 << lnRsize;
    pDrvCtrl->rmdIndex  = 0;

    /* setup Tx memory pointers. */

    /* Note: +2 is to round up to alignment. */

    pDrvCtrl->pTring = (LN_TMD *) (int)(pDrvCtrl->pShMem + IB_SIZ +
                        ((1 << lnRsize) + 1) * RMD_SIZ + 0xf);
    pDrvCtrl->pTring = (LN_TMD *) (((int)pDrvCtrl->pTring + 0xf) & ~0xf);

    pDrvCtrl->tringSize = 1 << lnTsize;
    pDrvCtrl->tringLen  = lnTsize;
    pDrvCtrl->tmdIndex  = 0;
    pDrvCtrl->tmdIndexC = 0;

    /* Set up the structures to allow us to free data after sending it. */

    for (ix = 0; ix < pDrvCtrl->rringSize; ix++)
	{
	pDrvCtrl->freeRtn[ix] = NULL;
	pDrvCtrl->freeData[ix].arg1 = NULL;
	pDrvCtrl->freeData[ix].arg2 = NULL;
	}

    /* allocate pool structure for mblks, clBlk, and clusters */

    if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
	return (ERROR);

#ifdef DRV_DEBUG
    pLan97xNetPool = pDrvCtrl->endObj.pNetPool;
#endif
    
    pDrvCtrl->clDesc.clNum    = pDrvCtrl->rringSize * 2;
    pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum;
    pDrvCtrl->mClCfg.mBlkNum  = pDrvCtrl->mClCfg.clBlkNum * 2;

    /* total memory size for mBlks and clBlks */
    
    pDrvCtrl->mClCfg.memSize =
        (pDrvCtrl->mClCfg.mBlkNum  *  (MSIZE + sizeof (long))) +
        (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long)));

    /* total memory for mBlks and clBlks */

    if ((pDrvCtrl->mClCfg.memArea =
         (char *) memalign (sizeof(long), pDrvCtrl->mClCfg.memSize)) == NULL)
        return (ERROR);

    /* total memory size for all clusters */

    pDrvCtrl->clDesc.clSize  = LN_BUFSIZ;
    pDrvCtrl->clDesc.memSize =
        (pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + 8)) + sizeof(int);

    /* Do we hand over our own memory? */

    if (pDrvCtrl->memAdrs != (char *)NONE)
        {
        pDrvCtrl->clDesc.memArea =
            (char *)(pDrvCtrl->pTring + pDrvCtrl->tringSize);
        }
    else
        {
        pDrvCtrl->clDesc.memArea = cacheDmaMalloc (pDrvCtrl->clDesc.memSize);
            
        if ((int)pDrvCtrl->clDesc.memArea == NULL)
            {
            DRV_LOG(DRV_DEBUG_LOAD,
                    "system memory unavailable\n", 1, 2, 3, 4, 5, 6);
            return (ERROR);
            }
        }

    /* initialize the device net pool */
    
    if (netPoolInit (pDrvCtrl->endObj.pNetPool, &pDrvCtrl->mClCfg,
                     &pDrvCtrl->clDesc, 1, NULL) == ERROR)
        {
        DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n",
                 1, 2, 3, 4, 5, 6);
        return (ERROR);
        }
    
    /* Store the cluster pool id as others need it later. */

    pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
                                       LN_BUFSIZ, FALSE);

    /* Longword align rmd ring */

    pDrvCtrl->pRring = (LN_RMD *) (((int)pDrvCtrl->pRring + 0xf) & ~0xf);
    pDrvCtrl->pRring = (LN_RMD *) (((int)pDrvCtrl->pRring + 0xf) & ~0xf);
    pRmd = pDrvCtrl->pRring;

    DRV_LOG (DRV_DEBUG_LOAD, "Using %d RX buffers from 0x%X\n",
             pDrvCtrl->rringSize, (int)pRmd, 3, 4, 5, 6);

    for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++)
        {
        if ((pTempBuf = (char *)netClusterGet (pDrvCtrl->endObj.pNetPool,
                                               pDrvCtrl->pClPoolId)) == NULL)
            {
            DRV_LOG (DRV_DEBUG_LOAD, "Could not get a buffer\n",
                     1, 2, 3, 4, 5, 6);
            return (ERROR);
            }
        pTempBuf += pDrvCtrl->offset;
        LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pTempBuf);
        }

    return OK;
    }

/*******************************************************************************
*
* ln97xStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*/

LOCAL STATUS ln97xStart
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl /* device to be initialized */
    )
    {
	int tValue;
	
	tValue = pDrvCtrl->ilevel;
	if(tValue == 0)
		tValue = pDrvCtrl->ivec; 

    pDrvCtrl->txCleaning = FALSE;
    pDrvCtrl->txBlocked  = FALSE;

	(void) intConnect (INUM_TO_IVEC ((int)tValue), ln97xInt, (int)pDrvCtrl);
    /* SYS_INT_CONNECT (pDrvCtrl, ln97xInt, (int)pDrvCtrl, &result); */

    /*if (result == ERROR)
        return ERROR;*/

    DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6);
    
    SYS_INT_ENABLE (); 

    DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6);

    return (OK);
    }

/*******************************************************************************
*
* ln97xInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*/

LOCAL void ln97xInt
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl /* device to be initialized */
    )
    {
    UINT32	   	stat;

    /* Read the device status register */

    stat = ln97xCsrRead (pDrvCtrl, 0);

    DRV_LOG (DRV_DEBUG_INT, "i=0x%x:\n", stat, 2, 3, 4, 5, 6);

    /* If false interrupt, return. */

    if (! (stat & CSR0_INTR))
        {
        DRV_LOG (DRV_DEBUG_INT, "False interrupt.\n", 1, 2, 3, 4, 5, 6);
        return;
        }

    /*
     * enable interrupts, clear receive and/or transmit interrupts, and clear
     * any errors that may be set.
     * Writing back what was read clears all interrupts
     */

    ln97xCsrWrite (pDrvCtrl, 0, stat);

    /* Check for errors */

    if (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR))
	{
        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);

        if (stat & CSR0_BABL)
            {
            pDrvCtrl->lastError.errCode = END_ERR_WARN;
            pDrvCtrl->lastError.pMesg = "Babbling";
            netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
                       (int) &pDrvCtrl->lastError,
                       0, 0, 0);
            DRV_LOG (DRV_DEBUG_INT, "Babbling\n", 1, 2, 3, 4, 5, 6);
            }
        if (stat & CSR0_MISS)
            {
            pDrvCtrl->lastError.errCode = END_ERR_WARN;
            pDrvCtrl->lastError.pMesg = "Missing";
            netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
                       (int) &pDrvCtrl->lastError,
                       0, 0, 0);
            DRV_LOG (DRV_DEBUG_INT, "Missing\n", 1, 2, 3, 4, 5, 6);
            }

        /* restart chip on fatal error */

        if (stat & CSR0_MERR)        /* memory error */
	    {
            pDrvCtrl->lastError.errCode = END_ERR_RESET;
            pDrvCtrl->lastError.pMesg = "Memory error.";
            netJobAdd ((FUNCPTR)muxError, (int) &pDrvCtrl->endObj,
                       (int)&pDrvCtrl->lastError,
                       0, 0, 0);
            DRV_LOG (DRV_DEBUG_INT, "Memory error, restarting.\n",
                     1, 2, 3, 4, 5, 6);
            END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
            ln97xRestart (pDrvCtrl);
            return;
	    }
	}

    /* Have netTask handle any input packets */

    if ((stat & CSR0_RINT) && (stat & CSR0_RXON))
	{
        if (!(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG))
	    {
            pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
            (void) netJobAdd ((FUNCPTR)ln97xHandleRecvInt, (int)pDrvCtrl,
                              0,0,0,0);
	    }
	}

    /*
     * Did LANCE update any of the TMD's?
     * If not then don't bother continuing with transmitter stuff
     */

    if (!(stat & CSR0_TINT))
        return;

    DRV_LOG (DRV_DEBUG_INT, "t ", 1, 2, 3, 4, 5, 6);

    if (!pDrvCtrl->txCleaning)
        {
        pDrvCtrl->txCleaning = TRUE;
        netJobAdd ((FUNCPTR)ln97xTRingScrub, (int) pDrvCtrl, 0, 0, 0, 0);
        }

    if (pDrvCtrl->txBlocked)    /* cause a restart */
        {
        pDrvCtrl->txBlocked = FALSE;
        netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0);
        }

    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();

    return;
    }

/*******************************************************************************
*
* 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 /* device to be initialized */
    )
    {
    LN_RMD * 		pRmd = (LN_RMD *)NULL;

    do
        {
        pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;

        while ((pRmd = ln97xFullRMDGet (pDrvCtrl)) != (LN_RMD *)NULL) 
	    {
	    LN_CACHE_INVALIDATE (pRmd, RMD_SIZ);
            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 */
    }

/*******************************************************************************
*
* ln97xFullRMDGet - get next received message RMD
*
* Returns ptr to next Rx desc to process, or NULL if none ready.
*/

LOCAL LN_RMD * ln97xFullRMDGet
    (
    LN_97X_DRV_CTRL * 	pDrvCtrl /* device to be initialized */
    )
    {
    LN_RMD *		pRmd;

    pRmd = pDrvCtrl->pRring + pDrvCtrl->rmdIndex;  /* form ptr to Rx desc */

    /* If receive buffer has been released to us, return it */

    if ((PCI_SWAP (pRmd->rBufRmd1) & RMD1_OWN) == 0)
        return (pRmd);

⌨️ 快捷键说明

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