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

📄 c6455_emac.c

📁 ti的TMS320C64XEMAC应用源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
uint EMAC_getStatistics( Handle hEMAC, EMAC_Statistics *pStatistics )
{
    EMAC_Device  *pd = (EMAC_Device *)hEMAC;

    /* Validate our handle */
    if( !pd || pd->DevMagic != EMAC_DEVMAGIC || !pStatistics )
        return( EMAC_ERROR_INVALID );

    /* Update the stats */
    emacUpdateStats( pd );

    /* Copy the updated stats to the application */
    *pStatistics = pd->Stats;

    /* Clear our copy */
    memset( &pd->Stats, 0, sizeof(EMAC_Statistics) );

    return(0);
}


/*-----------------------------------------------------------------------*\
* EMAC_setMulticast()
*
* This function is called to install a list of multicast addresses for
* use in multicast address filtering. Each time this function is called,
* any current multicast configuration is discarded in favor of the new
* list. Thus a set with a list size of zero will remove all multicast
* addresses from the device.
*
* Note that the multicast list configuration is stateless in that the
* list of multicast addresses used to build the configuration is not
* retained. Thus it is impossible to examine a list of currently installed
* addresses.
*
* The addresses to install are pointed to by pMCastList. The length of
* this list in bytes is 6 times the value of AddrCnt. When AddrCnt is
* zero, the pMCastList parameter can be NULL.
*
* The function returns zero on success, or an error code on failure.
* The multicast list settings are not altered in the event of a failure
* code.
*
* Possible error code include:
*   EMAC_ERROR_INVALID   - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_setMulticast( Handle hEMAC, uint AddrCnt, Uint8 *pMCastList )
{
    EMAC_Device  *pd = (EMAC_Device *)hEMAC;
    uint        tmp1,tmp2;
    Uint8       HashVal,tmpval;
    Uint32		temp,temp1;
	int 		i;

    /* Validate our handle */
    if( !pd || pd->DevMagic != EMAC_DEVMAGIC || (AddrCnt && !pMCastList) )
        return( EMAC_ERROR_INVALID );

#if RAM_MCAST

	if (AddrCnt > 31)
		return ( EMAC_ERROR_INVALID );

		// Clear the multicast list
	for (i = 1; i < 32; i++)
	{
		EMAC_REGS->MACINDEX = i;
		EMAC_REGS->MACADDRHI = 0;
		EMAC_REGS->MACADDRLO = 0;
	}

	// For each address in the list, add it to the RAM
	for( tmp1=0; tmp1<AddrCnt; tmp1++ )
	{
		EMAC_REGS->MACINDEX = tmp1+1;

		temp = 0;

		for( i=3; i>=0; i-- )
			temp = (temp<<8) | *(pMCastList+i);

		EMAC_REGS->MACADDRHI = temp;

		temp = *(pMCastList+4);
		temp1 = *(pMCastList+5);
		EMAC_REGS->MACADDRLO = CSL_FMKT( EMAC_MACADDRLO_VALID, VALID ) |
							   CSL_FMKT( EMAC_MACADDRLO_MATCHFILT, MATCH ) |
							   CSL_FMK( EMAC_MACADDRLO_CHANNEL, 0 ) |
							   (temp1<<8) | temp ;
		pMCastList+=6;
	}

#else

    /* Clear the hash bits */
    pd->MacHash1 = 0;
    pd->MacHash2 = 0;

    /* For each address in the list, hash and set the bit */
    for( tmp1=0; tmp1<AddrCnt; tmp1++ )
    {
        HashVal=0;

        for( tmp2=0; tmp2<2; tmp2++ )
        {
            tmpval = *pMCastList++;
            HashVal ^= (tmpval>>2)^(tmpval<<4);
            tmpval = *pMCastList++;
            HashVal ^= (tmpval>>4)^(tmpval<<2);
            tmpval = *pMCastList++;
            HashVal ^= (tmpval>>6)^(tmpval);
        }

        if( HashVal & 0x20 )
            pd->MacHash2 |= (1<<(HashVal&0x1f));
        else
            pd->MacHash1 |= (1<<(HashVal&0x1f));
    }

    /* We only write the hash table if the filter setting allows */
    if( pd->RxFilter < EMAC_RXFILTER_ALLMULTICAST )
    {
        EMAC_REGS->MACHASH1 = pd->MacHash1;
        EMAC_REGS->MACHASH2 = pd->MacHash2;
    }

#endif

    return(0);
}


/*-----------------------------------------------------------------------*\
* EMAC_sendPacket()
*
* Sends a Ethernet data packet out the EMAC device. On a non-error return,
* the EMAC device takes ownership of the packet. The packet is returned
* to the application's free pool once it has been transmitted.
*
* The function returns zero on success, or an error code on failure.
* When an error code is returned, the EMAC device has not taken ownership
* of the packet.
*
* Possible error codes include:
*   EMAC_ERROR_INVALID   - A calling parameter is invalid
*   EMAC_ERROR_BADPACKET - The packet structure is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_sendPacket( Handle hEMAC, EMAC_Pkt *pPkt )
{
    EMAC_Device  *pd = (EMAC_Device *)hEMAC;
    uint        fragcnt,pktlen;
    EMAC_Pkt     *pPktLast;
    EMAC_DescCh  *pdc;

    /* Validate our handle */
    if( !pd || pd->DevMagic != EMAC_DEVMAGIC || !pPkt )
        return( EMAC_ERROR_INVALID );

    /* Do some packet validation */
    if( !(pPkt->Flags & EMAC_PKT_FLAGS_SOP) )
        return( EMAC_ERROR_BADPACKET );

    if( pPkt->PktChannel >= pd->Config.TxChannels )
        return( EMAC_ERROR_BADPACKET );

    if( pPkt->PktLength < 14 || pPkt->PktLength > pd->PktMTU )
        return( EMAC_ERROR_BADPACKET );

    /* Count the number of frags in this packet */
    fragcnt = 1;
    pktlen  = pPkt->PktLength;
    pPktLast = pPkt;
    while( !(pPktLast->Flags & EMAC_PKT_FLAGS_EOP) )
    {
        if( !pPktLast->pNext )
            return( EMAC_ERROR_INVALID );
        pktlen -= pPktLast->ValidLen;
        pPktLast = pPktLast->pNext;
        fragcnt++;

        /* At this point we can't have another SOP */
        if( pPktLast->Flags & EMAC_PKT_FLAGS_SOP )
            return( EMAC_ERROR_INVALID );
    }

    /* Make sure PktLength and ValidLen agree */
    if( pktlen != pPkt->ValidLen )
        return( EMAC_ERROR_BADPACKET );

    /* The final packet frag must be the last in the list */
    if( pPktLast->pNext )
        return( EMAC_ERROR_BADPACKET );

    /* The frag count must be correct */
    if( fragcnt != pPkt->PktFrags )
        return( EMAC_ERROR_BADPACKET );

    /* Now pad for 60 byte min size. We only pad the last fragment */
    if( pPkt->PktLength < 60 )
    {
        pktlen = 60 - pPkt->PktLength;
        pPkt->PktLength = 60;
        pPktLast->ValidLen += pktlen;
    }

    /* Get a local pointer to the descriptor channel */
    pdc = &(pd->TxCh[pPkt->PktChannel]);

    /* Make sure this packet does not have too many frags to fit */
    if( fragcnt > pdc->DescMax )
        return( EMAC_ERROR_BADPACKET );

    /*
    // Queue and packet and service transmitter
    */
    pqPushChain( &pdc->WaitQueue, pPkt, pPktLast, fragcnt );
    emacEnqueueTx( pdc );

    return(0);
}


/*-----------------------------------------------------------------------*\
* EMAC_serviceCheck()
*
* This function should be called every time there is an EMAC device
* interrupt. It maintains the status the EMAC.
*
* Note that the application has the responsibility for mapping the
* physical device index to the correct EMAC_serviceCheck() function. If
* more than one EMAC device is on the same interrupt, the function must be
* called for each device.
*
* Possible error codes include:
*   EMAC_ERROR_INVALID   - A calling parameter is invalid
*   EMAC_ERROR_MACFATAL  - Fatal error in the MAC - Call EMAC_close()
*
\*-----------------------------------------------------------------------*/
uint EMAC_serviceCheck( Handle hEMAC )
{
    EMAC_Device		*pd = (EMAC_Device *)hEMAC;
    Uint32			intflags,Desc,mask;
    uint			tmp;
    volatile Uint32	*pRegAddr;

    /* Validate our handle */
    if( !pd || pd->DevMagic != EMAC_DEVMAGIC )
        return( EMAC_ERROR_INVALID );

    /* Disable EMAC/MDIO interrupts in wrapper */
    CSL_FINST(ECTL_REGS->EWCTL, ECTL_EWCTL_INTEN, DISABLE );

    /* Read the interrupt cause */
    intflags = EMAC_REGS->MACINVECTOR;

    /* Look for fatal errors first */
    if( intflags & CSL_FMK( EMAC_MACINVECTOR_HOSTPEND, 1 ) )
    {
        /* Read the error status - we'll decode it by hand */
        pd->FatalError = EMAC_REGS->MACSTATUS;

        /* Tell the application */
        (*localDev.Config.pfcbStatus)(pd->hApplication);

        /* return with interrupt disabled in the wrapper */
        return( EMAC_ERROR_MACFATAL );
    }

    /* Look for statistics interrupt */
    if( intflags & CSL_FMK( EMAC_MACINVECTOR_STATPEND, 1 ) )
    {
        /* Read the stats and reset to zero         */
        /* This is necessary to clear the interrupt */
        emacUpdateStats( pd );

        /* Tell the application */
        (*localDev.Config.pfcbStatistics)(pd->hApplication);
    }

    pRegAddr = &EMAC_REGS->TX0CP;

    /* Look for TX interrupt (channel 0-max) */
    for( tmp=0; tmp<pd->Config.TxChannels; tmp++ )
    {
        mask = CSL_FMK( EMAC_MACINVECTOR_TXPEND, 1<<tmp );
        if( intflags & mask )
        {
            Desc = *(pRegAddr + tmp);
            *(pRegAddr + tmp) = Desc;
            emacDequeueTx( &pd->TxCh[tmp], (EMAC_Desc *)Desc );
        }
    }

    /* Look for RX interrupt (channel 0) */
    if( intflags & CSL_FMK( EMAC_MACINVECTOR_RXPEND, 1<<0 ) )
    {
        /*
        // For multichannel operation, we need to apply the
        // same errata workaround as TX. However this driver
        // example only supports one RX channel.
        */
        Desc = EMAC_REGS->RX0CP ;
        EMAC_REGS->RX0CP = Desc;

        emacDequeueRx( &pd->RxCh, (EMAC_Desc *)Desc );
    }

    /* Enable EMAC/MDIO interrupts in wrapper */
    CSL_FINST(ECTL_REGS->EWCTL, ECTL_EWCTL_INTEN, ENABLE );

    return(0);
}

/*-----------------------------------------------------------------------*\
* EMAC_timerTick()
*
* This function should be called for each device in the system on a
* periodic basis of 100mS (10 times a second). It is used to check the
* status of the EMAC and MDIO device, and to potentially recover from
* low Rx buffer conditions.
*
* Strict timing is not required, but the application should make a
* reasonable attempt to adhere to the 100mS mark. A missed call should
* not be "made up" by making multiple sequential calls.
*
* A "polling" driver (one that calls EMAC_serviceCheck() in a tight loop),
* must also adhere to the 100mS timing on this function.
*
* Possible error codes include:
*   EMAC_ERROR_INVALID   - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_timerTick( Handle hEMAC )
{
    EMAC_Device  *pd = (EMAC_Device *)hEMAC;
    uint         mdioStatus,linkStatus;

    /* Validate our handle */
    if( !pd || pd->DevMagic != EMAC_DEVMAGIC )
        return( EMAC_ERROR_INVALID );

    /* Signal the MDIO */
    mdioStatus = MDIO_timerTick( pd->hMDIO );

    /* On a new link, set the EMAC configuration appropriate for the interface used */
    if( mdioStatus == MDIO_EVENT_LINKUP )
    {
        MDIO_getStatus( pd->hMDIO, 0, &linkStatus );

        if( linkStatus == MDIO_LINKSTATUS_FD10  ||
            linkStatus == MDIO_LINKSTATUS_FD100 ||
            linkStatus == MDIO_LINKSTATUS_FD1000 )
        {
            CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, ENABLE );

			if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII )
				CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIIDUPLEXMODE, FULLDUPLEX );
		}
        else
        {
            CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, DISABLE );
			if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII )
				CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIIDUPLEXMODE, HALFDUPLEX );
        }

		if( linkStatus == MDIO_LINKSTATUS_FD1000 )
				CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_GIG, ENABLE );

		if(( (linkStatus == MDIO_LINKSTATUS_HD10 ) ||
			( linkStatus == MDIO_LINKSTATUS_FD10 )) &&
			( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII ))
				CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIISPEED, 2_5MHZ );

		if(( (linkStatus == MDIO_LINKSTATUS_HD100 ) ||
			( linkStatus == MDIO_LINKSTATUS_FD100 )) &&
			( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII ))
				CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIISPEED, 25MHZ );

		/* The following 2 settings apply only to PG 2.0 */
		if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII )		// Take RMII out of reset
			CSL_FINST(DEV_REGS->EMACCFG, DEV_EMACCFG_RMIIRST, RELEASE );

		if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII )		// Put RGMII in forced link mode
			CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RGMIIEN, DISABLE );

	}

    if( mdioStatus != MDIO_EVENT_NOCHANGE )
        (*localDev.Config.pfcbStatus)(pd->hApplication);

    /* Re-fill Rx buffer queue if needed */
    if( pd->RxCh.DescCount != pd->RxCh.DescMax )
        emacEnqueueRx( &pd->RxCh, 1 );

    return ( 0 );
}


/******************************************************************************\
* End of himalaya_emac.c
\******************************************************************************/

⌨️ 快捷键说明

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