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

📄 at91emacend.c

📁 VxWorks BSP for AT91RM92
💻 C
📖 第 1 页 / 共 5 页
字号:

    pDrvCtrl->txHdrs = (volatile TXBUF_HDR *) malloc(pDrvCtrl->txNum * sizeof(TXBUF_HDR)); 

    if (pDrvCtrl->txHdrs == NULL)
        {
        EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate TX descriptors\n", 1, 2, 3, 4, 5, 6);
        return (ERROR);
        }

    for (i = 0; i < pDrvCtrl->txNum; i++)
        {
        pDrvCtrl->txHdrs[i].pAdrs = (char *) cacheDmaMalloc(EMAC_END_MAX_CL_LEN);

        if (pDrvCtrl->txHdrs[i].pAdrs == NULL)
            {
            EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate TX buffer %i\n", i, 2, 3, 4, 5, 6);
            return (ERROR);
            }
        }

    /* Allocate a TX buffer for polling mode */
    pDrvCtrl->pTxPollBuf = (char *) cacheDmaMalloc(EMAC_END_MAX_CL_LEN);
    
    if (pDrvCtrl->pTxPollBuf == NULL)
        {
        EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate TX poll buffer\n", 1, 2, 3, 4, 5, 6);
        return (ERROR);
        }

    /*
     * Rx buffer and descriptors (EMAC use the descriptor for receiving data)
     */

#ifdef EMAC_RX_BUFFER_IN_SRAM
    
    /*
     * use internal SRAM for RX buffers and descriptors
     * ensures that the receive descriptors start on a 64byte boundary
     * (errata #11)
     * NOTE: Start at offset 0x200 because the area below is used
     * by vxWorks for the vectors and exceptions pointer.
     */
    
    pDrvCtrl->rxHdrs = (volatile RXBUF_HDR *) (AT91C_ISRAM + 0x200);
    pDrvCtrl->rxBuff = (volatile UCHAR *)     (AT91C_ISRAM + 0x300);

    for (i = 0; i < pDrvCtrl->rxNum; i++)
        {
		pDrvCtrl->rxHdrs[i].adrs   = (UINT32)(&pDrvCtrl->rxBuff[i * RX_BUFFER_SIZE]);
		pDrvCtrl->rxHdrs[i].status = 0;

		EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: RX Buffer %i at 0x%08x.\n", i, (int) pDrvCtrl->rxHdrs[i].adrs,0,0,0,0);		
        }

#else
    
    /*
     * This variant lets the descriptor in SRAM (not cached)
     * but allows to create more RX buffers.
     * NOTE: Start at offset 0x200 because the area below is used
     * by vxWorks for the vectors and exceptions pointer.
     */
    
    pDrvCtrl->rxHdrs    = (volatile RXBUF_HDR *) (AT91C_ISRAM + 0x200);
    pDrvCtrl->rxBuff    = NULL;
    pDrvCtrl->rxCluster = (UINT32 *) malloc(pDrvCtrl->rxNum * sizeof(UINT32));

    if (pDrvCtrl->rxCluster == NULL)
        {
        EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate RX Clusters pointer\n", 1, 2, 3, 4, 5, 6);
        return (ERROR);
        }

    for (i = 0; i < pDrvCtrl->rxNum; i++)
        {
        char *	pBuf  = NULL;	/* a rx data pointer */
        char *  pData = NULL;
            
        /* allocate aligned buffer */

        if ((pBuf = cacheDmaMalloc(EMAC_END_MAX_CL_LEN)) == NULL)
            {
            EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate RX buffer %i\n", i, 2, 3, 4, 5, 6);
            return (ERROR);
            }

        pData = (char *) NET_TO_EMAC_END_BUF(pBuf); /* align buffer according to errata #11 */ 
        
        pDrvCtrl->rxHdrs[i].adrs   = (UINT32) pData;
        pDrvCtrl->rxCluster[i]     = (UINT32) pBuf; /* save pointer for releasing in unload() routine */
		pDrvCtrl->rxHdrs[i].status = 0;
        }

#endif /* EMAC_RX_BUFFER_IN_SRAM */

    EMAC_END_LOG (EMAC_END_DBG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6);

    return OK;
    }


/*******************************************************************************
*
* at91EmacEndPhyRead - Read from MII register
*
* This routine reads the register specified by <phyReg> in the PHY device
* whose address is <phyAddr>. The value read is returned in the location
* pointed to by <retVal>.
*
* SEE ALSO: at91EmacEndPhyWrite()
*
* RETURNS: value read
*/

UINT32 at91EmacEndPhyRead
    (
    UINT8 phyReg
    )
    {
    UINT32	phyVal;     /* value written/read to/from the MII register */

    phyVal = ((0x01 << 30)	    /* Start of Frame Delimiter */
			 |(0x02 << 28)	    /* Operation, 0x01 = Write, 0x02 = Read */
			 |(0x00 << 23)	    /* Phy Number, 0 as we only have one */
			 |(phyReg << 18)	/* Phy Register */
			 |(0x02 << 16));	/* must be 0x02 for turn around field */

    EMAC_REG(EMAC_MAN) = phyVal;

	/* wait for phy read to complete */
	sysDelay();

    phyVal = EMAC_REG(EMAC_MAN) & 0xFFFF; 

	EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndPhyRead: Phy 0, Reg %i, Read 0x%x.\n", phyReg, phyVal, 0,0,0,0);
	

	return (phyVal);
}

/**************************************************************************
*
* at91EmacEndPhyWrite - write to the MII register
*
* This routine writes the register specified by <phyReg> in the PHY device,
* whose address is <phyAddr>, with the 16-bit value included in <data>.
*
* SEE ALSO: at91EmacEndPhyRead()
*
* RETURNS: N/A.
*/

void at91EmacEndPhyWrite
    (
    UINT8   phyReg,
    UINT16  data
    )
    {
    UINT32	phyVal;         /* value written/read to/from the MII register */

    phyVal = ((0x01 << 30)	    /* Start of Frame Delimiter */
              |(0x01 << 28)	    /* Operation, 0x01 = Write, 0x02 = Read */
              |(0x00 << 23)	    /* Phy Number, 0 as we only have one */
              |(phyReg << 18)	/* Phy Register */
              |(0x02 << 16)	    /* must be 0x02 for turn around field */
              | data);

    EMAC_REG(EMAC_MAN) = phyVal;
	
    EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: Phy 0, Reg %i, Write 0x%x.\n", phyReg, data, 0,0,0,0);
	
	/* wait for phy write to complete */
	sysDelay();
    }


/*******************************************************************************
*
* at91EmacEndStart - 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 at91EmacEndStart
    (
    EMAC_END_DEVICE * pDrvCtrl	/* device ID */
    )
    {
    STATUS  result;
    int     i;
    int     timeout;
    UINT32  emacLinkStatus = 0;
    
    /*
     * RX buffers and descriptors initialisation
     */

    /* initialize the receive buffer descriptors */
    EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: RX Buffer Header at 0x%08x.\n", (int) pDrvCtrl->rxHdrs, 2, 3, 4, 5, 6);
	
    for (i = 0; i < pDrvCtrl->rxNum; i++)
        {
		pDrvCtrl->rxHdrs[i].adrs   &= ~RXBUF_ADD_OWNED; /* ensure that buffer is owned by the DMA engine */
		pDrvCtrl->rxHdrs[i].status = 0;
        }

	/* set the wrap bit on the last buffer */
	pDrvCtrl->rxHdrs[pDrvCtrl->rxNum-1].adrs |= RXBUF_ADD_WRAP;
	
	/* point to the receive buffer queue */
	EMAC_REG(EMAC_RBQP) = (UINT32) pDrvCtrl->rxHdrs;

    pDrvCtrl->rxIndex = 0;
    
    /* clear Rx status bits */
	EMAC_REG(EMAC_RSR)  &= ~(EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA);

    /*
     * TX buffers and descriptors initialisation
     */

    for (i = 0; i < pDrvCtrl->txNum; i++)
        {
		pDrvCtrl->txHdrs[i].inUse = FALSE;   /* buffer not used to transmit */
        }

    pDrvCtrl->txIndexRd = 0;
    pDrvCtrl->txIndexWr = 0;

    /* initialize the transmit control register */
    EMAC_REG(EMAC_TCR) = 0;
    EMAC_REG(EMAC_TAR) = 0;

    /* clear Tx status bits */
	EMAC_REG(EMAC_TSR)  &= ~(EMAC_TSR_UND | EMAC_TSR_COMP | EMAC_TSR_BNQ 
                             | EMAC_TSR_TXIDLE | EMAC_TSR_RLE | EMAC_TSR_COL | EMAC_TSR_OVR);

    /*
     * PHY configuration
     */

	/* set the MII clock divider to MCK/64 */
	EMAC_REG(EMAC_CFG) = (EMAC_CFG_CLK_64 | EMAC_CFG_BIG | EMAC_CFG_FD);

	/* enable the MII interface */
	EMAC_REG(EMAC_CTL) = EMAC_CTL_MPE;

	EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: Getting Link Status.\n", 0,0,0,0,0,0);

	/* Get the link status - wait for done with a timeout */
    timeout = 1000;

	while (timeout > 0)
        {
		emacLinkStatus = at91EmacEndPhyRead(MII_STAT_REG);
		
        if (!(emacLinkStatus & MII_SR_AUTO_SEL))
            {
			EMAC_END_PRINT(EMAC_END_DBG_ERR, ("at91EmacEndStart: PHY is unable to Auto-Negotiate!\n"));
			timeout = 0;
			break;
            }

		if (emacLinkStatus & MII_SR_AUTO_NEG)
            {
			EMAC_END_PRINT(EMAC_END_DBG_LOAD, ("at91EmacEndStart: Auto-Negotiate Complete, Link = "));
			break;
            }
		
        timeout-- ;
        }

	if (!(timeout))
        {
		EMAC_END_PRINT(EMAC_END_DBG_ERR, ("at91EmacEndStart: Auto-Negotatiate Failed, Status = 0x%x!\n", emacLinkStatus));
		return ERROR; 
        }

	/* Set SPD and FD based on the return link status */
	if (emacLinkStatus & (MII_SR_TX_HALF_DPX | MII_SR_TX_FULL_DPX))
        {
		EMAC_REG(EMAC_CFG) |= EMAC_CFG_SPD;
		EMAC_END_PRINT(EMAC_END_DBG_LOAD, ("100MBIT, "));
        }
	else
        {
		EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_SPD;
		EMAC_END_PRINT(EMAC_END_DBG_LOAD, ("10MBIT, "));
        }		
			
	if (emacLinkStatus & (MII_SR_TX_FULL_DPX | MII_SR_10T_FULL_DPX))
        {
		EMAC_REG(EMAC_CFG) |= EMAC_CFG_FD;
		EMAC_END_PRINT(EMAC_END_DBG_LOAD, ("Full Duplex.\n"));
        }
	else
        {
		EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_FD;
		EMAC_END_PRINT(EMAC_END_DBG_LOAD, ("Half Duplex.\n"));
        }		

#ifdef TARGET_CSB337
	/* Set PHY LED1 to Speed, PHY LED2 to combined Link/Activity and enable pulse stretching */
	at91EmacEndPhyWrite(0x14, (LXT971_LED1(LXT971_LED_SPEED)
				 | LXT971_LED2(LXT971_LED_LINK_RX_TX)
				 | LXT971_LED_STRETCH_30MS
				 | LXT971_LED_STRETCH_ON)); 
#endif /* TARGET_CSB337 */
    
	/* disable the MII interface */
	EMAC_REG(EMAC_CTL) &= ~EMAC_CTL_MPE;

    SYS_INT_CONNECT (pDrvCtrl, at91EmacEndInt, (int)pDrvCtrl, &result);
    
    if (result == ERROR)
        {
        return ERROR;
        }

    EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: Interrupt connected.\n", 1, 2, 3, 4, 5, 6);

    SYS_INT_ENABLE (pDrvCtrl);

    EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: interrupt enabled.\n", 1, 2, 3, 4, 5, 6);

    END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);

	EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndStart: Enable TX and RX.\n", 0,0,0,0,0,0);

	/* Enable interrupts */
	EMAC_REG(EMAC_IER) = EMAC_INT_RCOM | EMAC_INT_RBNA
			| EMAC_INT_TUND | EMAC_INT_RTRY | EMAC_INT_TCOM
			| EMAC_INT_ROVR | EMAC_INT_ABT;
	
    /* Enable TX/RX and clear the statistics counters */
	EMAC_REG(EMAC_CTL) = (EMAC_CTL_TE | EMAC_CTL_RE | EMAC_CTL_CSR);

    return (OK);
    }

/*******************************************************************************
*
* at91EmacEndNextSend - send next packet
*
* This routine send the nex packet through the EMAC.
*
* RETURNS: current TX index.
*/

int at91EmacEndNextSend
    (
    EMAC_END_DEVICE  *pDrvCtrl	/* interrupting device */
    )
    {
    UINT32                  stat;
    volatile TXBUF_HDR *    pBufHdr;
    
    stat = EMAC_REG(EMAC_TSR);

    if ((stat & EMAC_TSR_BNQ) == EMAC_TSR_BNQ)
        {
        /* release packet from queue (should be the current index pointed) */
        if (EMAC_REG(EMAC_TAR) != 0)
            {
            pBufHdr = (volatile TXBUF_HDR *) &pDrvCtrl->txHdrs[pDrvCtrl->txIndexRd];
            pBufHdr->inUse = FALSE;

            /* next index to enqueue */
            if (pDrvCtrl->txIndexRd == (pDrvCtrl->txNum-1))
                {
                pDrvCtrl->txIndexRd = 0;
                }
            else
                {
                pDrvCtrl->txIndexRd++;
                }
            }

        /* enqueue packet */
        pBufHdr = (volatile TXBUF_HDR *) &pDrvCtrl->txHdrs[pDrvCtrl->txIndexRd];

        if (pBufHdr->inUse)
            {
            EMAC_REG(EMAC_TAR) = (UINT32) pBufHdr->pAdrs;
            EMAC_REG(EMAC_TCR) = EMAC_TCR_LEN((UINT32) pBufHdr->length);
	
            at91EmacEndNumSend++;

            EMAC_END_LOG (EMAC_END_DBG_TX, "at91EmacEndNextSend: send adrs=0x%x, length=%i (%i).\n",
                          (int) pBufHdr->pAdrs, pBufHdr->length, pDrvCtrl->txIndexRd,0,0,0);
            }
        else
            {
            EMAC_REG(EMAC_TCR) = 0;
            EMAC_REG(EMAC_TAR) = 0;
            
            EMAC_END_LOG (EMAC_END_DBG_TX, "at91EmacEndNextSend: Nothing more to send (%i).\n",
                          pDrvCtrl->txIndexRd, 0,0,0,0,0);
            }
        }

    return(pDrvCtrl->txIndexRd);
    }

/*******************************************************************************

⌨️ 快捷键说明

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