/************************************************************************/
/**	\file	bfphy_generic.c
 *	\brief	LwIP network interface for generic PHY
 *
 *	\date	2011/10/06
 *	\author	Stephane Lesage for LwIP
 *
 */
/************************************************************************/

/* Includes */
#include <blackfin.h>
#include <sys/exception.h>
#include "bfphy.h"
#include "lwip/sys.h"

/* Macros */

/* Types */

/* Externals */
extern volatile u8_t bfphy_event;

/* Variables */

/* Functions */

void bfphy_init_vendor()
{
}

void bfphy_interrupt_callback(void* ctx)
{
	static u16_t prev_mctl = 0;
	static u16_t prev_mstat = 0;
	SYS_ARCH_DECL_PROTECT(old_level);

	// Read Registers
	u16_t mctl = bfphy_read(PHYREG_MODECTL);
	u16_t mstat = bfphy_read(PHYREG_MODESTAT);
	bfphy_event = 0;

	// Mode Change
	if (mctl != prev_mctl)
	{
		prev_mctl = mctl;

		// Speed/Duplex Mode
		SYS_ARCH_PROTECT(old_level);
		u32_t opmode = *pEMAC_OPMODE;
		if (mctl & PHY_MODECTL_DUPLEX_MODE)
		{
			bfphy_fd = 1;
			opmode |= FDMODE;
		}
		else
		{
			bfphy_fd = 0;
			opmode &= ~FDMODE;
		}
		if (mctl & PHY_MODECTL_SPEED_SELECT)
		{
			bfphy_100M = 1;
			opmode &= ~RMII_10;
		}
		else
		{
			bfphy_100M = 0;
			opmode |= RMII_10;
		}
		*pEMAC_OPMODE = opmode;
		SYS_ARCH_UNPROTECT(old_level);
	}

	// Link state
	if ((mstat ^ prev_mstat) & PHY_MODESTAT_LINK_STATUS)
	{
		struct netif* netif = (struct netif*) ctx;
		if (mstat & PHY_MODESTAT_LINK_STATUS)	netif_set_link_up(netif);
		else									netif_set_link_down(netif);
		prev_mstat = mstat;
	}
}
