/*
 * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */


/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"

#include "Zynq/x_emacpsif.h"

extern TaskHandle_t xEMACTaskHandle;

/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
 *** to run it on a PEEP board
 ***/

void setup_isr( xemacpsif_s *xemacpsif )
{
	/*
	 * Setup callbacks
	 */
	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
		(void *) emacps_send_handler,
		(void *) xemacpsif);

	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
		(void *) emacps_recv_handler,
		(void *) xemacpsif);

	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
		(void *) emacps_error_handler,
		(void *) xemacpsif);
}

void start_emacps (xemacpsif_s *xemacps)
{
	/* start the temac */
	XEmacPs_Start(&xemacps->emacps);
}

extern struct xtopology_t xXTopology;

volatile int error_msg_count = 0;
volatile const char *last_err_msg = "";

struct xERROR_MSG {
	void *arg;
	u8 Direction;
	u32 ErrorWord;
};

static struct xERROR_MSG xErrorList[ 8 ];
static BaseType_t xErrorHead, xErrorTail;

void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xemacpsif_s *xemacpsif;
	BaseType_t xNextHead = xErrorHead;

	xemacpsif = (xemacpsif_s *)(arg);

	if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
	{
		if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
			xNextHead = 0;
		if( xNextHead != xErrorTail )
		{

			xErrorList[ xErrorHead ].arg = arg;
			xErrorList[ xErrorHead ].Direction = Direction;
			xErrorList[ xErrorHead ].ErrorWord = ErrorWord;

			xErrorHead = xNextHead;

			xemacpsif = (xemacpsif_s *)(arg);
			xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
		}

		if( xEMACTaskHandle != NULL )
		{
			vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
		}

	}

	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);

int emacps_check_errors( xemacpsif_s *xemacps )
{
int xResult;

	( void ) xemacps;

	if( xErrorHead == xErrorTail )
	{
		xResult = 0;
	}
	else
	{
		xResult = 1;
		emacps_handle_error(
			xErrorList[ xErrorTail ].arg,
			xErrorList[ xErrorTail ].Direction,
			xErrorList[ xErrorTail ].ErrorWord );
	}

	return xResult;
}

static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
{
	xemacpsif_s   *xemacpsif;
	struct xtopology_t *xtopologyp;
	XEmacPs *xemacps;

	xemacpsif = (xemacpsif_s *)(arg);

	xtopologyp = &xXTopology;

	xemacps = &xemacpsif->emacps;

	/* Do not appear to be used. */
	( void ) xemacps;
	( void ) xtopologyp;

	last_err_msg = NULL;

	if( ErrorWord != 0 )
	{
		switch (Direction) {
		case XEMACPS_RECV:
			if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
			{
				last_err_msg = "Receive DMA error";
				xNetworkInterfaceInitialise( );
			}
			if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
			{
				last_err_msg = "Receive over run";
				emacps_recv_handler(arg);
			}
			if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
			{
				last_err_msg = "Receive buffer not available";
				emacps_recv_handler(arg);
			}
			break;
		case XEMACPS_SEND:
			if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
			{
				last_err_msg = "Transmit DMA error";
				xNetworkInterfaceInitialise( );
			}
			if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
			{
				last_err_msg = "Transmit under run";
				HandleTxErrors( xemacpsif );
			}
			if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
			{
				last_err_msg = "Transmit buffer exhausted";
				HandleTxErrors( xemacpsif );
			}
			if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
			{
				last_err_msg = "Transmit retry excessed limits";
				HandleTxErrors( xemacpsif );
			}
			if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
			{
				last_err_msg = "Transmit collision";
				emacps_check_tx( xemacpsif );
			}
			break;
		}
	}
	// Break on this statement and inspect error_msg if you like
	if( last_err_msg != NULL )
	{
		error_msg_count++;
		FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
	}
}

extern XEmacPs_Config mac_config;

void HandleTxErrors(xemacpsif_s *xemacpsif)
{
	u32 netctrlreg;

	//taskENTER_CRITICAL()
	{
		netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
													XEMACPS_NWCTRL_OFFSET);
		netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
										XEMACPS_NWCTRL_OFFSET, netctrlreg);

		clean_dma_txdescs( xemacpsif );
		netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
														XEMACPS_NWCTRL_OFFSET);
		netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
											XEMACPS_NWCTRL_OFFSET, netctrlreg);
	}
	//taskEXIT_CRITICAL( );
}
