/*
 * ianENC28J60.h
 *
 *  Created on: Jan 2, 2021
 *      Author: ianst
 */

#ifndef IANENC28J60_H_
#define IANENC28J60_H_

/*********************************************************************
 *
 *            ENC28J60 registers/bits - Mostly from Microchip file
 *
 *********************************************************************
 */

#include "main.h"
#include "armbits.h"
#include "TCPIPConfig.h"
#include "config.h"
#include "registry.h"



typedef struct
{
  __IO uint32_t ISR;   /*!< DMA interrupt status register */
  __IO uint32_t Reserved0;
  __IO uint32_t IFCR;  /*!< DMA interrupt flag clear register */
} DMA_Base_Registers;



typedef enum _BOOL { FALSE = 0, TRUE } BOOL;	// Undefined size



#define LSB(a)          ((a).v[0])
#define MSB(a)          ((a).v[1])

#define LOWER_LSB(a)    ((a).v[0])
#define LOWER_MSB(a)    ((a).v[1])
#define UPPER_LSB(a)    ((a).v[2])
#define UPPER_MSB(a)    ((a).v[3])



/******************************************************************************
* Register locations
******************************************************************************/
// Bank 0 registers --------
#define ERDPTL		0x00
#define ERDPTH		0x01
#define EWRPTL		0x02
#define EWRPTH		0x03
#define ETXSTL		0x04
#define ETXSTH		0x05
#define ETXNDL		0x06
#define ETXNDH		0x07
#define ERXSTL		0x08
#define ERXSTH		0x09
#define ERXNDL		0x0A
#define ERXNDH		0x0B
#define ERXRDPTL	0x0C
#define ERXRDPTH	0x0D
#define ERXWRPTL	0x0E
#define ERXWRPTH	0x0F
#define EDMASTL		0x10
#define EDMASTH		0x11
#define EDMANDL		0x12
#define EDMANDH		0x13
#define EDMADSTL	0x14
#define EDMADSTH	0x15
#define EDMACSL		0x16
#define EDMACSH		0x17

#define EIE			0x1B
#define EIR			0x1C
#define ESTAT		0x1D
#define ECON2		0x1E
#define ECON1		0x1F

// Bank 1 registers -----
#define EHT0		0x100
#define EHT1		0x101
#define EHT2		0x102
#define EHT3		0x103
#define EHT4		0x104
#define EHT5		0x105
#define EHT6		0x106
#define EHT7		0x107
#define EPMM0		0x108
#define EPMM1		0x109
#define EPMM2		0x10A
#define EPMM3		0x10B
#define EPMM4		0x10C
#define EPMM5		0x10D
#define EPMM6		0x10E
#define EPMM7		0x10F
#define EPMCSL		0x110
#define EPMCSH		0x111

#define EPMOL		0x114
#define EPMOH		0x115

#define ERXFCON		0x118
#define EPKTCNT		0x119

// Bank 2 registers -----
#define MACON1		0x200
#define MACON2		0x201
#define MACON3		0x202
#define MACON4		0x203
#define MABBIPG		0x204
#define MAIPGL		0x206
#define MAIPGH		0x207
#define MACLCON1	0x208
#define MACLCON2	0x209
#define MAMXFLL		0x20A
#define MAMXFLH		0x20B
#define MICON		0x211
#define MICMD		0x212
#define MIREGADR	0x214
#define MIWRL		0x216
#define MIWRH		0x217
#define MIRDL		0x218
#define MIRDH		0x219

// Bank 3 registers -----
#define MAADR5		0x300
#define MAADR6		0x301
#define MAADR3		0x302
#define MAADR4		0x303
#define MAADR1		0x304
#define MAADR2		0x305
#define EBSTSD		0x306
#define EBSTCON		0x307
#define EBSTCSL		0x308
#define EBSTCSH		0x309
#define MISTAT		0x30A
#define EREVID		0x312
#define ECOCON		0x315
#define EFLOCON		0x317
#define EPAUSL		0x318
#define EPAUSH		0x319




typedef union _REG
{
	uint8_t Val;

	// EIE bits ----------
	struct {
		uint8_t RXERIE:1;
		uint8_t TXERIE:1;
		uint8_t :1;
		uint8_t TXIE:1;
		uint8_t LINKIE:1;
		uint8_t DMAIE:1;
		uint8_t PKTIE:1;
		uint8_t INTIE:1;
	} EIEbits;

	// EIR bits ----------
	struct {
		uint8_t RXERIF:1;
		uint8_t TXERIF:1;
		uint8_t :1;
		uint8_t TXIF:1;
		uint8_t LINKIF:1;
		uint8_t DMAIF:1;
		uint8_t PKTIF:1;
		uint8_t :1;
	} EIRbits;

	// ESTAT bits ---------
	struct {
		uint8_t CLKRDY:1;
		uint8_t TXABRT:1;
		uint8_t RXBUSY:1;
		uint8_t :1;
		uint8_t LATECOL:1;
		uint8_t :1;
		uint8_t BUFER:1;
		uint8_t INT:1;
	} ESTATbits;

	// ECON2 bits --------
	struct {
		uint8_t :3;
		uint8_t VRPS:1;
		uint8_t :1;
		uint8_t PWRSV:1;
		uint8_t PKTDEC:1;
		uint8_t AUTOINC:1;
	} ECON2bits;

	// ECON1 bits --------
	struct {
		uint8_t BSEL0:1;
		uint8_t BSEL1:1;
		uint8_t RXEN:1;
		uint8_t TXRTS:1;
		uint8_t CSUMEN:1;
		uint8_t DMAST:1;
		uint8_t RXRST:1;
		uint8_t TXRST:1;
	} ECON1bits;

	// ERXFCON bits ------
	struct {
		uint8_t BCEN:1;
		uint8_t MCEN:1;
		uint8_t HTEN:1;
		uint8_t MPEN:1;
		uint8_t PMEN:1;
		uint8_t CRCEN:1;
		uint8_t ANDOR:1;
		uint8_t UCEN:1;
	} ERXFCONbits;

	// MACON1 bits --------
	struct {
		uint8_t MARXEN:1;
		uint8_t PASSALL:1;
		uint8_t RXPAUS:1;
		uint8_t TXPAUS:1;
		uint8_t :4;
	} MACON1bits;


	// MACON3 bits --------
	struct {
		uint8_t FULDPX:1;
		uint8_t FRMLNEN:1;
		uint8_t HFRMEN:1;
		uint8_t PHDREN:1;
		uint8_t TXCRCEN:1;
		uint8_t PADCFG0:1;
		uint8_t PADCFG1:1;
		uint8_t PADCFG2:1;
	} MACON3bits;
	struct {
		uint8_t FULDPX:1;
		uint8_t FRMLNEN:1;
		uint8_t HFRMEN:1;
		uint8_t PHDREN:1;
		uint8_t TXCRCEN:1;
		uint8_t PADCFG:3;
	} MACON3bits2;

	// MACON4 bits --------
	struct {
		uint8_t :4;
		uint8_t NOBKOFF:1;
		uint8_t BPEN:1;
		uint8_t DEFER:1;
		uint8_t :1;
	} MACON4bits;

	// MICMD bits ---------
	struct {
		uint8_t MIIRD:1;
		uint8_t MIISCAN:1;
		uint8_t :6;
	} MICMDbits;

	// EBSTCON bits -----
	struct {
		uint8_t BISTST:1;
		uint8_t TME:1;
		uint8_t TMSEL0:1;
		uint8_t TMSEL1:1;
		uint8_t PSEL:1;
		uint8_t PSV0:1;
		uint8_t PSV1:1;
		uint8_t PSV2:1;
	} EBSTCONbits;
	struct {
		uint8_t BISTST:1;
		uint8_t TME:1;
		uint8_t TMSEL:2;
		uint8_t PSEL:1;
		uint8_t PSV:3;
	} EBSTCONbits2;

	// MISTAT bits --------
	struct {
		uint8_t BUSY:1;
		uint8_t SCAN:1;
		uint8_t NVALID:1;
		uint8_t :5;
	} MISTATbits;

	// ECOCON bits -------
	struct {
		uint8_t COCON0:1;
		uint8_t COCON1:1;
		uint8_t COCON2:1;
		uint8_t :5;
	} ECOCONbits;
	struct {
		uint8_t COCON:3;
		uint8_t :5;
	} ECOCONbits2;

	// EFLOCON bits -----
	struct {
		uint8_t FCEN0:1;
		uint8_t FCEN1:1;
		uint8_t FULDPXS:1;
		uint8_t :5;
	} EFLOCONbits;
	struct {
		uint8_t FCEN:2;
		uint8_t FULDPXS:1;
		uint8_t :5;
	} EFLOCONbits2;
} REG;


/******************************************************************************
* PH Register Locations
******************************************************************************/
#define PHCON1	0x00
#define PHSTAT1	0x01
#define PHID1	0x02
#define PHID2	0x03
#define PHCON2	0x10
#define PHSTAT2	0x11
#define PHIE	0x12
#define PHIR	0x13
#define PHLCON	0x14


typedef union {
	uint16_t Val;
	uint16_t_VAL VAL;

	// PHCON1 bits ----------
	struct {
		unsigned :8;
		unsigned PDPXMD:1;
		unsigned :2;
		unsigned PPWRSV:1;
		unsigned :2;
		unsigned PLOOPBK:1;
		unsigned PRST:1;
	} PHCON1bits;

	// PHSTAT1 bits --------
	struct {
		unsigned :1;
		unsigned JBSTAT:1;
		unsigned LLSTAT:1;
		unsigned :5;
		unsigned :3;
		unsigned PHDPX:1;
		unsigned PFDPX:1;
		unsigned :3;
	} PHSTAT1bits;

	// PHID2 bits ----------
	struct {
		unsigned PREV0:1;
		unsigned PREV1:1;
		unsigned PREV2:1;
		unsigned PREV3:1;
		unsigned PPN0:1;
		unsigned PPN1:1;
		unsigned PPN2:1;
		unsigned PPN3:1;
		unsigned PPN4:1;
		unsigned PPN5:1;
		unsigned PID19:1;
		unsigned PID20:1;
		unsigned PID21:1;
		unsigned PID22:1;
		unsigned PID23:1;
		unsigned PID24:1;
	} PHID2bits;
	struct {
		unsigned PREV:4;
		unsigned PPNL:4;
		unsigned PPNH:2;
		unsigned PID:6;
	} PHID2bits2;

	// PHCON2 bits ----------
	struct {
		unsigned :8;
		unsigned HDLDIS:1;
		unsigned :1;
		unsigned JABBER:1;
		unsigned :2;
		unsigned TXDIS:1;
		unsigned FRCLNK:1;
		unsigned :1;
	} PHCON2bits;

	// PHSTAT2 bits --------
	struct {
		unsigned :5;
		unsigned PLRITY:1;
		unsigned :2;
		unsigned :1;
		unsigned DPXSTAT:1;
		unsigned LSTAT:1;
		unsigned COLSTAT:1;
		unsigned RXSTAT:1;
		unsigned TXSTAT:1;
		unsigned :2;
	} PHSTAT2bits;

	// PHIE bits -----------
	struct {
		unsigned :1;
		unsigned PGEIE:1;
		unsigned :2;
		unsigned PLNKIE:1;
		unsigned :3;
		unsigned :8;
	} PHIEbits;

	// PHIR bits -----------
	struct {
		unsigned :2;
		unsigned PGIF:1;
		unsigned :1;
		unsigned PLNKIF:1;
		unsigned :3;
		unsigned :8;
	} PHIRbits;

	// PHLCON bits -------
	struct {
		unsigned :1;
		unsigned STRCH:1;
		unsigned LFRQ0:1;
		unsigned LFRQ1:1;
		unsigned LBCFG0:1;
		unsigned LBCFG1:1;
		unsigned LBCFG2:1;
		unsigned LBCFG3:1;
		unsigned LACFG0:1;
		unsigned LACFG1:1;
		unsigned LACFG2:1;
		unsigned LACFG3:1;
		unsigned :4;
	} PHLCONbits;
	struct {
		unsigned :1;
		unsigned STRCH:1;
		unsigned LFRQ:2;
		unsigned LBCFG:4;
		unsigned LACFG:4;
		unsigned :4;
	} PHLCONbits2;
} PHYREG;


/******************************************************************************
* Individual Register Bits
******************************************************************************/
// ETH/MAC/MII bits

// EIE bits ----------
#define	EIE_INTIE		(1<<7)
#define	EIE_PKTIE		(1<<6)
#define	EIE_DMAIE		(1<<5)
#define	EIE_LINKIE		(1<<4)
#define	EIE_TXIE		(1<<3)
#define	EIE_TXERIE		(1<<1)
#define	EIE_RXERIE		(1)

// EIR bits ----------
#define	EIR_PKTIF		(1<<6)
#define	EIR_DMAIF		(1<<5)
#define	EIR_LINKIF		(1<<4)
#define	EIR_TXIF		(1<<3)
#define	EIR_TXERIF		(1<<1)
#define	EIR_RXERIF		(1)

// ESTAT bits ---------
#define	ESTAT_INT		(1<<7)
#define ESTAT_BUFER		(1<<6)
#define	ESTAT_LATECOL	(1<<4)
#define	ESTAT_RXBUSY	(1<<2)
#define	ESTAT_TXABRT	(1<<1)
#define	ESTAT_CLKRDY	(1)

// ECON2 bits --------
#define	ECON2_AUTOINC	(1<<7)
#define	ECON2_PKTDEC	(1<<6)
#define	ECON2_PWRSV		(1<<5)
#define	ECON2_VRPS		(1<<3)

// ECON1 bits --------
#define	ECON1_TXRST		(1<<7)
#define	ECON1_RXRST		(1<<6)
#define	ECON1_DMAST		(1<<5)
#define	ECON1_CSUMEN	(1<<4)
#define	ECON1_TXRTS		(1<<3)
#define	ECON1_RXEN		(1<<2)
#define	ECON1_BSEL1		(1<<1)
#define	ECON1_BSEL0		(1)

// ERXFCON bits ------
#define	ERXFCON_UCEN	(1<<7)
#define	ERXFCON_ANDOR	(1<<6)
#define	ERXFCON_CRCEN	(1<<5)
#define	ERXFCON_PMEN	(1<<4)
#define	ERXFCON_MPEN	(1<<3)
#define	ERXFCON_HTEN	(1<<2)
#define	ERXFCON_MCEN	(1<<1)
#define	ERXFCON_BCEN	(1)

// MACON1 bits --------
#define	MACON1_TXPAUS	(1<<3)
#define	MACON1_RXPAUS	(1<<2)
#define	MACON1_PASSALL	(1<<1)
#define	MACON1_MARXEN	(1)

// MACON3 bits --------
#define	MACON3_PADCFG2	(1<<7)
#define	MACON3_PADCFG1	(1<<6)
#define	MACON3_PADCFG0	(1<<5)
#define	MACON3_TXCRCEN	(1<<4)
#define	MACON3_PHDREN	(1<<3)
#define	MACON3_HFRMEN	(1<<2)
#define	MACON3_FRMLNEN	(1<<1)
#define	MACON3_FULDPX	(1)

// MACON4 bits --------
#define	MACON4_DEFER	(1<<6)
#define	MACON4_BPEN		(1<<5)
#define	MACON4_NOBKOFF	(1<<4)

// MICMD bits ---------
#define	MICMD_MIISCAN	(1<<1)
#define	MICMD_MIIRD		(1)

// EBSTCON bits -----
#define	EBSTCON_PSV2	(1<<7)
#define	EBSTCON_PSV1	(1<<6)
#define	EBSTCON_PSV0	(1<<5)
#define	EBSTCON_PSEL	(1<<4)
#define	EBSTCON_TMSEL1	(1<<3)
#define	EBSTCON_TMSEL0	(1<<2)
#define	EBSTCON_TME		(1<<1)
#define	EBSTCON_BISTST	(1)

// MISTAT bits --------
#define	MISTAT_NVALID	(1<<2)
#define	MISTAT_SCAN		(1<<1)
#define	MISTAT_BUSY		(1)

// ECOCON bits -------
#define	ECOCON_COCON2	(1<<2)
#define	ECOCON_COCON1	(1<<1)
#define	ECOCON_COCON0	(1)

// EFLOCON bits -----
#define	EFLOCON_FULDPXS	(1<<2)
#define	EFLOCON_FCEN1	(1<<1)
#define	EFLOCON_FCEN0	(1)

typedef union {
	uint8_t v[4];
	struct {
		uint16_t	 		ByteCount;
		uint8_t	PreviouslyIgnored:1;
		uint8_t	RXDCPreviouslySeen:1;
		uint8_t	CarrierPreviouslySeen:1;
		uint8_t	CodeViolation:1;
		uint8_t	CRCError:1;
		uint8_t	LengthCheckError:1;
		uint8_t	LengthOutOfRange:1;
		uint8_t	ReceiveOk:1;
		uint8_t	Multicast:1;
		uint8_t	Broadcast:1;
		uint8_t	DribbleNibble:1;
		uint8_t	ControlFrame:1;
		uint8_t	PauseControlFrame:1;
		uint8_t	UnsupportedOpcode:1;
		uint8_t	VLANType:1;
		uint8_t	Zero:1;
	} bits;
} RXSTATUS;


// PHY bits

// PHCON1 bits ----------
#define	PHCON1_PRST		(1ul<<15)
#define	PHCON1_PLOOPBK	(1ul<<14)
#define	PHCON1_PPWRSV	(1ul<<11)
#define	PHCON1_PDPXMD	(1ul<<8)

// PHSTAT1 bits --------
#define	PHSTAT1_PFDPX	(1ul<<12)
#define	PHSTAT1_PHDPX	(1ul<<11)
#define	PHSTAT1_LLSTAT	(1ul<<2)
#define	PHSTAT1_JBSTAT	(1ul<<1)

// PHID2 bits --------
#define	PHID2_PID24		(1ul<<15)
#define	PHID2_PID23		(1ul<<14)
#define	PHID2_PID22		(1ul<<13)
#define	PHID2_PID21		(1ul<<12)
#define	PHID2_PID20		(1ul<<11)
#define	PHID2_PID19		(1ul<<10)
#define	PHID2_PPN5		(1ul<<9)
#define	PHID2_PPN4		(1ul<<8)
#define	PHID2_PPN3		(1ul<<7)
#define	PHID2_PPN2		(1ul<<6)
#define	PHID2_PPN1		(1ul<<5)
#define	PHID2_PPN0		(1ul<<4)
#define	PHID2_PREV3		(1ul<<3)
#define	PHID2_PREV2		(1ul<<2)
#define	PHID2_PREV1		(1ul<<1)
#define	PHID2_PREV0		(1ul)

// PHCON2 bits ----------
#define	PHCON2_FRCLNK	(1ul<<14)
#define	PHCON2_TXDIS	(1ul<<13)
#define	PHCON2_JABBER	(1ul<<10)
#define	PHCON2_HDLDIS	(1ul<<8)

// PHSTAT2 bits --------
#define	PHSTAT2_TXSTAT	(1ul<<13)
#define	PHSTAT2_RXSTAT	(1ul<<12)
#define	PHSTAT2_COLSTAT	(1ul<<11)
#define	PHSTAT2_LSTAT	(1ul<<10)
#define	PHSTAT2_DPXSTAT	(1ul<<9)
#define	PHSTAT2_PLRITY	(1ul<<5)

// PHIE bits -----------
#define	PHIE_PLNKIE		(1ul<<4)
#define	PHIE_PGEIE		(1ul<<1)

// PHIR bits -----------
#define	PHIR_PLNKIF		(1ul<<4)
#define	PHIR_PGIF		(1ul<<2)

// PHLCON bits -------
#define	PHLCON_LACFG3	(1ul<<11)
#define	PHLCON_LACFG2	(1ul<<10)
#define	PHLCON_LACFG1	(1ul<<9)
#define	PHLCON_LACFG0	(1ul<<8)
#define	PHLCON_LBCFG3	(1ul<<7)
#define	PHLCON_LBCFG2	(1ul<<6)
#define	PHLCON_LBCFG1	(1ul<<5)
#define	PHLCON_LBCFG0	(1ul<<4)
#define	PHLCON_LFRQ1	(1ul<<3)
#define	PHLCON_LFRQ0	(1ul<<2)
#define	PHLCON_STRCH	(1ul<<1)




// This is left shifted by 4.  Actual value is 0x04.
#define IPv4                (0x40u)
#define IP_VERSION          IPv4

// IHL (Internet Header Length) is # of uint32_ts in a header.
// Since, we do not support options, our IP header length will be
// minimum i.e. 20 bytes : IHL = 20 / 4 = 5.
#define IP_IHL              (0x05)

#define IP_SERVICE_NW_CTRL  (0x07)
#define IP_SERVICE_IN_CTRL  (0x06)
#define IP_SERVICE_ECP      (0x05)
#define IP_SERVICE_OVR      (0x04)
#define IP_SERVICE_FLASH    (0x03)
#define IP_SERVICE_IMM      (0x02)
#define IP_SERVICE_PRIOR    (0x01)
#define IP_SERVICE_ROUTINE  (0x00)

#define IP_SERVICE_N_DELAY  (0x00)
#define IP_SERCICE_L_DELAY  (0x08)
#define IP_SERVICE_N_THRPT  (0x00)
#define IP_SERVICE_H_THRPT  (0x10)
#define IP_SERVICE_N_RELIB  (0x00)
#define IP_SERVICE_H_RELIB  (0x20)

#define IP_SERVICE          (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY)

#define MY_IP_TTL           (100)  // Time-To-Live in hops



#define BE2LEINT16(a) ((((a)>>8)&0xff)|((a)<<8))
#define BE2LEINT32(a) ((((a)>>24)&0xff)|(((a)>>8)&0xff00)|((((a)&0xff00)<<8))|((a)<<24))
#define ARP_OPERATION_REQ_LE       BE2LEINT16(0x01u)		// Operation code indicating an ARP Request
#define ARP_OPERATION_RESP_LE      BE2LEINT16(0x02u)		// Operation code indicating an ARP Response
#define HW_ETHERNET_LE             BE2LEINT16(0x0001u)	// ARP Hardware type as defined by IEEE 802.3
//#define offsetof(s,memb) ((size_t)((char *)&((s *)0)->memb-(char *)0))
#define IP_PROT_ICMP    (1u)
#define IP_PROT_UDP     (17u)

#define MAC_IP      	(0x00u)
#define MAC_ARP     	(0x06u)
#define MAC_UNKNOWN 	(0xFFu)
#define MAC_NONE  	(0xFEu)



// MAC RAM definitions
#define RAMSIZE	8192ul
#define TXSTART (RAMSIZE - (1ul+MAX_ETHTX+7ul))

#define RXSTART	(0ul)						// Should be an even memory address; must be 0 for errata
#define	RXSTOP	((TXSTART-2ul) | 0x0001ul)	// Odd for errata workaround
#define RXSIZE	(RXSTOP-RXSTART+1ul)

#define BASE_TX_ADDR	(TXSTART + 1ul)

// A generic structure representing the Ethernet header starting all Ethernet
// frames


// Stores a UDP Port Number
typedef uint16_t UDP_PORT;


#define IP_ADDR		uint32_t_VAL

#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))

typedef struct __attribute__((__packed__)) _NODE_INFO
{
    IP_ADDR     IPAddr;
    MAC_ADDR    MACAddr;
} NODE_INFO;
// Stores information about a current UDP socket

typedef struct _UDP_SOCKET_INFO
{
    NODE_INFO   remoteNode;		// IP and MAC of remote node
    UDP_PORT    remotePort;		// Remote node's UDP port number
    UDP_PORT    localPort;		// Local UDP port number, or INVALID_UDP_PORT when free
} UDP_SOCKET_INFO;

typedef struct  __attribute__((aligned(2), packed))
{
	MAC_ADDR        DestMACAddr;
	MAC_ADDR        SourceMACAddr;
	uint16_t_VAL        Type;
} ETHER_HEADER;


// IP packet header definition
typedef struct _IP_HEADER
{
    uint8_t    	VersionIHL;
    uint8_t    	TypeOfService;
    uint16_t   	TotalLength;
    uint16_t   	Identification;
    uint16_t   	FragmentInfo;
    uint8_t    	TimeToLive;
    uint8_t    	Protocol;
    uint16_t   	HeaderChecksum;
    IP_ADDR 	SourceAddress;
    IP_ADDR 	DestAddress;
} IP_HEADER;

typedef struct __attribute__((aligned(2), packed))
{
    uint16_t	HardwareType;
    uint16_t	Protocol;
    uint8_t		MACAddrLen;
    uint8_t		ProtocolLen;
    uint16_t	Operation;
    MAC_ADDR	SenderMACAddr;
    IP_ADDR		SenderIPAddr;
    MAC_ADDR	TargetMACAddr;
    IP_ADDR		TargetIPAddr;
} ARP_PACKET;

// A header appended at the start of all RX frames by the hardware
typedef struct  __attribute__((aligned(2), packed))
{
    uint16_t		NextPacketPointer;
    RXSTATUS		StatusVector;
    MAC_ADDR        DestMACAddr;
    MAC_ADDR        SourceMACAddr;
    uint16_t_VAL	Type;
} ENC_PREAMBLE;
// Stores the header of a UDP packet

typedef struct _UDP_HEADER
{
    UDP_PORT    SourcePort;				// Source UDP port
    UDP_PORT    DestinationPort;		// Destination UDP port
    uint16_t    Length;					// Length of data
    uint16_t    Checksum;				// UDP checksum of the data
} UDP_HEADER;

// A header appended at the start of all RX frames by the hardware
typedef struct  __attribute__((aligned(4), packed))
{
	uint16_t		Packing; //debug to align payload to int32 boundary
    ENC_PREAMBLE	Pre;         //Sizeing
    ETHER_HEADER 	ETHH;
 	IP_HEADER		IPH;
    UDP_HEADER      UDPH;
    uint8_t   PL[MAX_UDP_PAYLOAD];
    uint32_t    IPCRC; // for enc chip crc receive
} ENC_PACKET;


// IP Pseudo header as defined by RFC 793 (needed for TCP and UDP
// checksum calculations/verification)
typedef struct _PSEUDO_HEADER
{
    IP_ADDR SourceAddress;
    IP_ADDR DestAddress;
    uint8_t Zero;
    uint8_t Protocol;
    uint16_t Length;
} PSEUDO_HEADER;

typedef struct _UDPPPH
{
    uint32_t cmd;
    uint32_t len;
} UDPPPH;

typedef struct _UDPPPL
{
    uint32_t add;
	uint8_t dat[];
} UDPPPL;

typedef struct _UDPPP
{
    UDPPPH hdr;
    UDPPPL pl;
} UDPPP;
typedef struct _UDPPPN
{
    UDPPPH hdr;
	uint8_t	name[REGNAMELEN];
    UDPPPL pl;
} UDPPPN;

typedef struct _PP_INFO
{
    uint32_t Cmd;
    uint32_t MaxLen;
    uint32_t RegAdr;
    uint32_t RegEntSize;
} PP_INFO;

typedef struct _SEND_BY_NAME_STRUCT
{
 uint8_t IP[4];
 void * Data;
 uint32_t Len;
 uint32_t Offset;
 void * Next;
 unsigned Busy;
 char Name[REGNAMELEN];
} SEND_BY_NAME_STRUCT;

/****************************************************************************
  Section:
	Function Prototypes
  ***************************************************************************/

void		WritePHYReg(uint8_t Register, uint16_t Data);
uint16_t	ReadPHYReg(uint8_t Register);
void 		GetPhy(void);

void 		MACInit(void);
uint16_t 	CalcIPChecksum(uint8_t* buffer, uint16_t count);
void    	EraseFlashSector(uint32_t Sector );

void 		IPDo(void);
void 		SendByName(SEND_BY_NAME_STRUCT * S);


extern volatile uint32_t ETH_Dropped_Packets;
extern volatile uint32_t ETH_ENC_Resets;
extern volatile uint32_t ETH_ENC_Tx_Resets;
extern volatile uint32_t ETH_UDP_Xmits;
extern volatile uint32_t ETH_ARP_Responses;
extern volatile uint32_t ETH_ICMP_Responses;


#endif /* IANENC28J60_H_ */
