blob: e9443cda8e17151e4a2381a2113c29fa31eea298 [file] [log] [blame]
/*
* 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>
#include "Zynq/x_emacpsif.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
///* FreeRTOS+TCP includes. */
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
extern TaskHandle_t xEMACTaskHandle;
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
*** to run it on a PEEP board
***/
unsigned int link_speed = 100;
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;
}
BaseType_t xNetworkInterfaceInitialise( void );
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( );
}