/*****************************************************************************
* Copyright (c) 2005 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/

#ifndef _ETH_H_H 
#define _ETH_H_H 

#include "Npttypes.h"
#include "eth_arch.h" 
#ifdef NET_OS_SPECIFIC
#include "bsp_net.h" 
#endif
#include "dma.h"
#include "regs.h"

#ifdef NDS_SPECIFIC
#include "fwtypes.h"
#endif

#include "trsocket.h"

#define ETH0_IFNAME     "eth0"

#ifdef __cplusplus
extern "C" {
#endif

#ifndef BSP_ENABLE_ETHERNET_BYPASS
#define BSP_ENABLE_ETHERNET_BYPASS          FALSE
#define BSP_ETHERNET_BYPASS_SEND_BUFFERS    0
#endif
#ifndef BSP_USE_ETHERNET_RECV_QUEUE
#define BSP_USE_ETHERNET_RECV_QUEUE         FALSE
#endif
#ifndef BSP_WANT_2ND_ETHERNET_CHECKSUM
#define BSP_WANT_2ND_ETHERNET_CHECKSUM      FALSE
#endif
#ifndef BSP_ENABLE_ETHERNET_INTERRUPT_FILTER
#define BSP_ENABLE_ETHERNET_INTERRUPT_FILTER	FALSE
#endif
/*
 * Hardware delays for r amount of time where r is a random number of slot times where 0 <= r <= 2**k, 
 * and 0 <= k <= 10 (see 802.3 paragraph 4.2.3.2.5), and a slot time is 512 bit times (paragraphs 
 * 4.4.2.1 and 4.4.2.3). At 10M bps, worse case is that the delay after a collision is about 52 mills.
 * 
 */
#define ETH_MAX_DELAY_AFTER_1_COLLISION     (52)

/*
 * Up to 16 collisions before hardware gives up.
 */
#define ETH_MAX_COLLISIONS_DELAY            (16 * ETH_MAX_DELAY_AFTER_1_COLLISION)

/*
 * How often the transmitter check routine should check for a lockup condition.
 */
#define ETH_TRANSMITTER_CHECK_FREQUENCY     (NS_MILLISECONDS_TO_TICKS(ETH_MAX_COLLISIONS_DELAY))

/*
 * How often should check Ethernet link.
 */
#define ETH_LINK_CHECK_FREQUENCY            (NS_MILLISECONDS_TO_TICKS(20))

/*
 * Ethernet connector types
 */

#define ETH_THINNET     0
#define ETH_10BASET     1
#define ETH_MII_10      2
#define ETH_MII_100     3

/* 
 * The following defines can be changed on a target system. In thiscase BSP library 
 * should be recompiled.
 */

#define ETH_RX_DMA_STATS    0
#define ETH_LOG_ENABLED     0
/* 
 * Maximum value of MII Management Clock rate, which IEEE 802.3u defines 
 * to be no faster than 2.5 Mhz. Your PHY might support a higher clock rate.
 */
#define ETH_MAX_PHY_CLK             2500000

/*
 * Number of receive DMA channels (A, B, C, and D) used
 * Channels A, B, C, and D are indexed into driver's tables as 0, 1, 2, and 3
 */
#define ETH_RX_CHANNELS             1

/* 
 * Number of DMA buffer descriptors in receive DMA buffer descriptor rings for 
 * channels A, B, C, and D. 
 */
#if ETH_RX_CHANNELS == 1
#define ETH_MAX_RXA_DESCRIPTORS     64
#define ETH_MAX_RXB_DESCRIPTORS     0
#define ETH_MAX_RXC_DESCRIPTORS     0 
#define ETH_MAX_RXD_DESCRIPTORS     0 
#else
#define ETH_MAX_RXA_DESCRIPTORS     64
#define ETH_MAX_RXB_DESCRIPTORS     16
#define ETH_MAX_RXC_DESCRIPTORS     16
#define ETH_MAX_RXD_DESCRIPTORS     64
#endif

/* 
 * Number of DMA buffer descriptors in the transmit DMA buffer descriptor ring
 */
#if (PROCESSOR == ns9750) || (PROCESSOR == ns9360) || (PROCESSOR == ns9210) || (PROCESSOR == ns9215)
/* NOTE: There are only 64 available in the hardware DMA memory area in these processors. */
#define ETH_MAX_TX_DESCRIPTORS      64
#elif (PROCESSOR == ns7520) || (PROCESSOR == net50)
#define ETH_MAX_TX_DESCRIPTORS      128
#else
    #error Unsupported processor
#endif

#if BSP_ENABLE_ETHERNET_BYPASS
#define ETH_TCPIP_SEND_BUFFERS       (ETH_MAX_TX_DESCRIPTORS - BSP_ETHERNET_BYPASS_SEND_BUFFERS)
#else
#define ETH_TCPIP_SEND_BUFFERS       ETH_MAX_TX_DESCRIPTORS
#endif


/* The following defines should not be changed. */

/* 
 * Ethernet physical address size in bytes.
 */
#define ETH_MAC_ADDR_SIZE           6

/*
 * Ethernet driver state. The initial state is 0. If the driver is disabled,
 * it goes to ETH_INITIALIZED state.
 */
#define ETH_NOT_INITIALIZED         0
#define ETH_INITIALIZED             1
#define ETH_ENABLED                 2

#define ETH_MAX_PACKET_LENGTH          1536

#define ETH_RX_MAX_PACKET_LEN	       1538	/* 1536 + 2 for RX-Align mode */
#define ETH_RXA_MAX_PACKET_LEN         66   /* 64 + 2 for RX-Align mode */
#define ETH_RXB_MAX_PACKET_LEN         128
#define ETH_RXC_MAX_PACKET_LEN         256
#define ETH_RXD_MAX_PACKET_LEN         ETH_RX_MAX_PACKET_LEN

#ifndef	NET_OS_SPECIFIC
#if BSP_WANT_ETHERNET_ACTIVITY_LED
/*
 * If this hardware requires a software controlled ethernet activity LED,
 * establish the minimum "on" time for the activity LED.  The implementation
 * forces on the LED when activity is detected in either the transmit or
 * receive direction.  When doing so, it also resets a "time-to-live" timer
 * which continues to count down as long as there is inactivity, dimming
 * the light when it expires.  We add one to the number of ticks in the
 * "time-to-live" count in order to require that "at least" the requested
 * interval has passed.  The units are in BSP ticks (not Fusion ticks).
 */
#define ETH_ACTIVITY_TTL_MS         20
#define ETH_ACTIVITY_TTL            (((ETH_ACTIVITY_TTL_MS * BSP_TICKS_PER_SECOND)/1000) + 1)
#endif
#endif


/*
 * Ethernet statistics structure definition
 */
typedef struct
{
    WORD32  tx_ints;		        /* Number of tx interrupts */
    WORD32  bytes_transmitted;      /* # of bytes transmitted*/
    WORD32  transmitted;            /* total packets successfully transmitted*/
    WORD32  tx_frames;		        /* Number of frames transmitted. */
    WORD32  multicast_transmitted;  /* # of multicast packets transmitted*/
    WORD32  tx_full;		        /* # of packets delayed because TX ring is full. */
    WORD32  tx_transmit;	        /* # of calls to naEthOneScatSend. */
    WORD32  tx_reset;		        /* # of calls to naEthTxReset. */
    WORD32  transmitterResets;      /* number of times receiver had to be reset*/

    WORD32  rx_ints;		        /* Number of rx interrupts */
    WORD32  bytes_received;         /* # of bytes received*/
    WORD32  rx_frames;		        /* # of frames indicating receive. */
    WORD32  rec_passed_up;          /* # of packets passed up to protocol stack*/
    WORD32  rx_drop;		        /* # of packets dropped by driver. */
    WORD32  rec_bytes_passed_up;    /* # of bytes passed up to protocol stack */
    WORD32  multicast_passed_up;    /* # of multicast packets passed up to protocol stack*/
    WORD32  rx_carrierevent;	    /* # of carrier events. */
    WORD32  rx_dataevent;	    /* # of data events. */
    WORD32  rx_broadcast;	    /* # of broadcast frames received. */
    WORD32  rx_multicast;	    /* # of multicast frames received. */
    WORD32  rx_crcerror;	    /* # of frames indicating CRC error. */
    WORD32  rx_dribble;		    /* # of frames indicating dribble error. */
    WORD32  rx_codeviolation;	/* # of frames indicating code violation. */
    WORD32  rx_long;		    /* # of frames that are too long. */
    WORD32  rx_short;		    /* # of frames that are too short. */
    WORD32  rx_really_short;    /* < 30 bytes on ARM7 */
    WORD32  rx_overrun;		    /* # of frames indicating overrun. */

#if ETH_RX_DMA_STATS
    WORD32  rx_not_full[4];	    /* # of times packet was not available. */
    WORD32  dma_skipped[4];     /* # of times DMA has skipped some buffer descriptors */
    WORD32  rx_all_full[4];	    /* # of times ring was entirely full. */
    WORD32  rx_isr_empty[4];    /* buffer closed, but DMA ring is empty */
    WORD32  rx_wrap;		    /* # of times rx ring has been wrapped. */
	WORD32  rx_isr_full;
	WORD32  rx_isr_nobuf;
	WORD32  rx_isr_notified;
#endif

    WORD32  rx_receive;		    /* # of calls to naEthReceive. */
    WORD32  rx_check;		    /* # of calls to naEthCheckReceive. */
    WORD32  rx_nrip;            /* # of NRIP occured */
    WORD32  rx_no_buffer;       /* # of times RXNOBUF | RXBUFFUL on arm9 */
    WORD32  rx_reset;		        /* # of calls to naEthRxReset. */
    WORD32  rec_no_proto_buffer;    /* protocol stack had no buffer for packet*/
    WORD32  tr_colc;                /* collision count */
    WORD32  tr_late_collisions;     /* # of collisions w/ at least 64 bytes sent */
    WORD32  tr_excess_deferrals;    /* # of excessive deferrals */
    WORD32  tr_excess_collisions;   /* # of frames aborted by too many collisions */
    WORD32  tr_under_run;           /* # of frames aborted by under run */
} ETH_STATS;


/*
 *  Ethernet data structure definition
 */ 
typedef struct 
{   
    ttUserInterface interfaceHandle;
    char  mac_addr[ETH_MAC_ADDR_SIZE];              /* MAC adddress */
    char  state;                                    /* drive state  */
    char  link_state;				                /* Link state:  */

    fb_buffer_desc_t *tx_in;	    /* Where packets to be transmitted are placed. */
    fb_buffer_desc_t *rx_out[ETH_RX_CHANNELS];	    /* Where packets are removed. */
    fb_buffer_desc_t *rx_isr_out[ETH_RX_CHANNELS];   /* Position of last notification to receive thread. */
    
    volatile WORD32 rx_service_count[ETH_RX_CHANNELS];
    int rx_reset_scheduled;
    int rx_channel_cnt;
    WORD32 rx_present_channel;

    ttUserBuffer rx_bypass;

    struct 
    {
        ttUserBuffer handle;
        char         *buffer;
    } rxPackets[ETH_RX_CHANNELS][ETH_MAX_RXA_DESCRIPTORS];
 
    INT16   connector_type;         /* type of connector selected*/
    INT16   connector_autosense;    /* TRUE if connector selected automatically*/
    char  efe_mii_100;                             /* 1 = 100Mb, 0 = 10 Mb  */
    char  fulld;                                   /* MAC & EFE full duplex */

    unsigned long offload;	        /* Offload flags enabled by Treck stack. */

    WORD32  tx_submitted;
    WORD32  txIsrSavedIdx;         /* position of Eth DMA module in ring from last tx interrupt */
    WORD32  txIsrCompleted;        /* ISR's count of transmit complete buffers */
    WORD32  txIsrBytesSent;        /* ISR's count of bytes transmitted */

    struct 
    {
       unsigned size;
       WORD32   flags;
    } txPackets[ETH_MAX_TX_DESCRIPTORS];

#if (PROCESSOR == ns7520) || (PROCESSOR == net50) || (PROCESSOR == net40)
     WORD32  ethTxPacketStart[ETH_MAX_TX_DESCRIPTORS];
     WORD32  ethTxPacketEnd[ETH_MAX_TX_DESCRIPTORS];
     WORD32  ethTxPacketFixHead;
     WORD32  ethTxPacketFixTail;
#endif

     ETH_STATS  eth_stats;
} ethData;


#define ETH_TX_LAST_FLAG            0x10000000
#define ETH_TX_BYPASS_FLAG          0x20000000
#define ETH_TX_BUFFER_CNT_MASK      0x0000ffff

/* 
 * Ethernet driver Function prototypes
 * These are routines, internal to the driver, 
 * and routines that interface FAST IP, the TCP/IP stack, etc.
 */

/*
 * Ethernet hardware address type;
 */

typedef BYTE ETH_ADDRESS[ETH_MAC_ADDR_SIZE];
  
/* Multicast routines */
extern void  eth_load_multicast_table (int num, const ETH_ADDRESS *multicast_table);

/* Hardware initialization */
extern int  eth_reset(ethData *eth_datap);
extern void eth_init_clk(void);
extern void eth_enable_efe(void);
extern void eth_disable_efe(void);
extern void eth_read_autosense (ethData *eth_datap, INT16 *connector_type, INT16 *connector_autosense);

/* DMA routines */
extern int naEthInitRxBufferDescriptors(ethData *eth_datap);
extern void naEthResetRxBufferDescriptors(ethData *eth_datap);

extern void eth_link_changed(ethData *eth_datap);


#ifdef ETH_API_ENABLED
extern ethFilterActionType naEthKeepThisPacket(char *pktBuffer, unsigned pktlen, WORD32 dma_status);
extern void naEthBypassReceive(ttUserInterface interfaceHandle);
extern void naEthIsrFilter(fb_buffer_desc_t *desc);
#else
typedef int ethFilterActionType;
#define  ethFilterActionDiscard  0
#define  ethFilterActionForward  1
#define naEthKeepThisPacket(a,b,c) ethFilterActionForward
#endif

/* eth_recv.c */
extern void naEthResetRxBufferDescriptors(ethData *eth_datap);
extern void naEthResetTxBufferDescriptors(ethData *eth_datap);
extern void naEthRxIsr(void *context);
extern void naEthTxIsr(void *context);
extern void naEthCheckLink(ethData *eth_datap);
extern void naEthCheckTransmit(ethData *eth_datap);
extern int  naEthRecvPacket(ttUserInterface      * interfaceHandle,
                                    char TM_FAR * TM_FAR * dataPtr,
	                                int TM_FAR *           dataLength,
	                                ttUserBufferPtr        bufHandlePtr);

extern int naEthPassToTreck(ttUserInterface interfaceHandle,
	                        char TM_FAR * TM_FAR * dataPtr,
	                        int TM_FAR *           dataLength,
	                        ttUserBufferPtr        bufHandlePtr
                            );


extern void naEthTransmitPacketBuffer(ethData *eth_datap, 
                               fb_buffer_desc_t *desc, 
							   fb_buffer_desc_t *first_descr, 
                               unsigned char *buffer, 
                               unsigned size, 
                               WORD32 flags);

extern fb_buffer_desc_t * ethNextTxDescr(fb_buffer_desc_t *);

extern int naEthIsLinkUp(void);


/* eth_os.c - no services yet. */
#define naEthInitOsServices(a)	    TM_DEV_OKAY
#define naEthStartOsServices(a)	    TM_DEV_OKAY
#define naEthStopOsServices(a)

#if ETH_LOG_ENABLED
extern void EthLogRx(ethData *eth_datap, DWord operation, DWord status, DWord channel);
extern void EthLogTx(ethData *eth_datap, DWord operation, DWord status);
#else
#define EthLogTx(a,b,c)
#define EthLogRx(a,b,c,d)
#endif

extern void GetFullEth0Stats(ETH_STATS*);

#ifdef __cplusplus
}
#endif
#endif /*_ETH_H_H */

