Example #1
0
void LPC24XX_EMAC_lwip_recv( struct netif *pNetIf )
{
    UINT32 idx, bytes_in;
    struct pbuf *pPBuf;
    void *dst, *src;
    
    LPC24XX_EMAC & ENET = *(LPC24XX_EMAC *)LPC24XX_EMAC::c_EMAC_Base;

    /* Disable intrrupts */
    GLOBAL_LOCK(irq);
    
    while ( ENET.MAC_RXCONSUMEINDEX != ENET.MAC_RXPRODUCEINDEX )
    {
        /* Get the index of the received ethernet frame */
        idx = ENET.MAC_RXCONSUMEINDEX;
        if ( RX_STAT_INFO(idx) & RX_FRAME_ERROR )
        {
            /* Received ethernet frame has an error */
            //lpc24xx_emac_stats.errors_in++;
        }
        else
        {
            /* Ethernet Frame FCS is not part of the data and the frame size is - 1 encoded */
            bytes_in = ( RX_STAT_INFO(idx) & RX_DESC_STATUS_SIZE ) - 3;
            
            pPBuf = pbuf_alloc(PBUF_RAW, bytes_in, PBUF_RAM);

            if( pPBuf )
            {
                src = (void*)RX_DESC_PACKET(idx);
                dst = pPBuf->payload;
                memcpy(dst, src, bytes_in);
                /* Tell IP layer that a packet has arrived */
                pNetIf->input( pPBuf, pNetIf );
                /* Update statistics */
                //lpc24xx_emac_stats.packets_in++;
                //lpc24xx_emac_stats.bytes_in += bytes_in;
            }
            else
            {
                debug_printf("LPC24XX_EMAC_recv: pbuf_alloc failed");
                //lpc24xx_emac_stats.packets_lost++;
            }    
        }
        idx++;
        /* Reset the index if last descriptor */
        if (idx == NUM_RX_FRAG) 
        {    
             idx = 0;
        }
        /* Mark RX descriptor as available */
        ENET.MAC_RXCONSUMEINDEX = idx;
    }
}
Example #2
0
File: emac.c Project: wugsh/wgs
unsigned long ulGetEMACRxData( void )
{
unsigned long ulLen = 0;
long lIndex;

	if( EMAC->RxProduceIndex != EMAC->RxConsumeIndex )
	{
		/* Mark the current buffer as free as uip_buf is going to be set to
		the buffer that contains the received data. */
		prvReturnBuffer( uip_buf );

		ulLen = ( RX_STAT_INFO( EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3;
		uip_buf = ( unsigned char * ) RX_DESC_PACKET( EMAC->RxConsumeIndex );

		/* Allocate a new buffer to the descriptor. */
        RX_DESC_PACKET( EMAC->RxConsumeIndex ) = ( unsigned long ) prvGetNextBuffer();

		/* Move the consume index onto the next position, ensuring it wraps to
		the beginning at the appropriate place. */
		lIndex = EMAC->RxConsumeIndex;

		lIndex++;
		if( lIndex >= NUM_RX_FRAG )
		{
			lIndex = 0;
		}

		EMAC->RxConsumeIndex = lIndex;
	}

	return ulLen;
}
// Reads the length of the received ethernet frame and checks if the 
// destination address is a broadcast message or not
// returns the frame length
unsigned short StartReadFrame(void) {
  unsigned short RxLen;
  unsigned int idx;

  idx = RxConsumeIndex;
  RxLen = (RX_STAT_INFO(idx) & RINFO_SIZE) - 3;
  rptr = (unsigned short *)RX_DESC_PACKET(idx);
  return(RxLen);
}
// Reads the length of the received ethernet frame and checks if the 
// destination address is a broadcast message or not
// returns the frame length
unsigned short StartReadFrame(void) {
  unsigned short RxLen;
  unsigned int idx;

  idx = MAC_RXCONSUMEINDEX;
  RxLen = (RX_STAT_INFO(idx) & RINFO_SIZE) - 3;
  rptr = (unsigned short *)RX_DESC_PACKET(idx);
  return(RxLen);
}
Example #5
0
// Reads  length of received ethernet frame and checks
// if destination address is a broadcast message or not.
// Then returns the frame length
unsigned short StartReadingFrame(void)
{
  unsigned short ReceiveLength;
  unsigned int index;

  index = LPC_EMAC->RxConsumeIndex;
  ReceiveLength = (RX_STAT_INFO(index) & RINFO_SIZE) - 3;
  rxptr = (unsigned short *)RX_DESC_PACKET(index);
  return(ReceiveLength);
}
Example #6
0
/**
 * 受信キューの先頭にあるRXフレームのポインタを返します。
 * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。
 * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)
 * @return
 * 成功した場合、受信データを格納したバッファポインターです。
 * 次回nextRxEthFrameを呼び出すまで有効です。
 */
static void* getRxEthFrame(unsigned short* o_len_of_data)
{
	if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )
	{
		//受信データを返却する。
		*o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);
		return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );
	}
	return NULL;
}
Example #7
0
/* reception packet. */
struct pbuf *lpc17xx_emac_rx(rt_device_t dev)
{
	struct pbuf* p;
	rt_uint32_t size;
	rt_uint32_t Index;

	/* init p pointer */
	p = RT_NULL;

	/* lock EMAC device */
	rt_sem_take(&sem_lock, RT_WAITING_FOREVER);

	Index = LPC_EMAC->RxConsumeIndex;
	if(Index != LPC_EMAC->RxProduceIndex)
	{
		size = (RX_STAT_INFO(Index) & 0x7ff)+1;
		if (size > ETH_FRAG_SIZE) size = ETH_FRAG_SIZE;

		/* allocate buffer */
		p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM);
		if (p != RT_NULL)
		{
			struct pbuf* q;
			rt_uint8_t *ptr;

			ptr = (rt_uint8_t*)RX_BUF(Index);
			for (q = p; q != RT_NULL; q= q->next)
			{
				memcpy(q->payload, ptr, q->len);
				ptr += q->len;
			}
		}
		
		/* move Index to the next */
		if(++Index > LPC_EMAC->RxDescriptorNumber)
			Index = 0;

		/* set consume index */
		LPC_EMAC->RxConsumeIndex = Index;
	}
	else
	{
		/* Enable RxDone interrupt */
		LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
	}

	/* unlock EMAC device */
	rt_sem_release(&sem_lock);

	return p;
}
Example #8
0
static void prevRxDescriptor(void)
{
	int x;
	//デスクリプタの設定
	for( x = 0; x < NUM_RX_FRAG; x++ )
	{
		/* Allocate the next Ethernet buffer to this descriptor. */
		RX_DESC_PACKET(x) = ETH_BUF(x);
		RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );
		RX_STAT_INFO(x) = 0;
		RX_STAT_HASHCRC(x) = 0;
	}

	/* Set LPC_EMAC Receive Descriptor Registers. */
	LPC_EMAC->RxDescriptor = RX_DESC_BASE;
	LPC_EMAC->RxStatus = RX_STAT_BASE;
	LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;

}
// Keil: function added to initialize Rx Descriptors
void rx_descr_init (void)
{
  unsigned int i;

  for (i = 0; i < NUM_RX_FRAG; i++) {
    RX_DESC_PACKET(i)  = RX_BUF(i);
    RX_DESC_CTRL(i)    = RCTRL_INT | (ETH_FRAG_SIZE-1);
    RX_STAT_INFO(i)    = 0;
    RX_STAT_HASHCRC(i) = 0;
  }

  /* Set EMAC Receive Descriptor Registers. */
  RxDescriptor    = RX_DESC_BASE;
  RxStatus        = RX_STAT_BASE;
  RxDescriptorNumber = NUM_RX_FRAG-1;

  /* Rx Descriptors Point to 0 */
  RxConsumeIndex  = 0;
}
		// Keil: function added to initialize Rx Descriptors
		void rx_descr_init (void)
		{
		  unsigned int i;
		
		  for (i = 0; i < NUM_RX_FRAG; i++) {
		    RX_DESC_PACKET(i)  = RX_BUF(i);
		    RX_DESC_CTRL(i)    = RCTRL_INT | (ETH_FRAG_SIZE-1);
		    RX_STAT_INFO(i)    = 0;
		    RX_STAT_HASHCRC(i) = 0;
		  }
		
		  /* Set EMAC Receive Descriptor Registers. */
		  MAC_RXDESCRIPTOR    = RX_DESC_BASE;
		  MAC_RXSTATUS        = RX_STAT_BASE;
		  MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1;//Minus 1 Encoding
		
		  /* Rx Descriptors Point to 0 */
		  MAC_RXCONSUMEINDEX  = 0;
		}
Example #11
0
File: emac.c Project: wugsh/wgs
static void prvInitDescriptors( void )
{
long x, lNextBuffer = 0;

	for( x = 0; x < NUM_RX_FRAG; x++ )
	{
		/* Allocate the next Ethernet buffer to this descriptor. */
		RX_DESC_PACKET( x ) = ETH_BUF( lNextBuffer );
		RX_DESC_CTRL( x ) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );
		RX_STAT_INFO( x ) = 0;
		RX_STAT_HASHCRC( x ) = 0;

		/* The Ethernet buffer is now in use. */
		ucBufferInUse[ lNextBuffer ] = pdTRUE;
		lNextBuffer++;
	}

	/* Set EMAC Receive Descriptor Registers. */
	EMAC->RxDescriptor = RX_DESC_BASE;
	EMAC->RxStatus = RX_STAT_BASE;
	EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;

	/* Rx Descriptors Point to 0 */
	EMAC->RxConsumeIndex = 0;

	/* A buffer is not allocated to the Tx descriptors until they are actually
	used. */
	for( x = 0; x < NUM_TX_FRAG; x++ )
	{
		TX_DESC_PACKET( x ) = ( unsigned long ) NULL;
		TX_DESC_CTRL( x ) = 0;
		TX_STAT_INFO( x ) = 0;
	}

	/* Set EMAC Transmit Descriptor Registers. */
	EMAC->TxDescriptor = TX_DESC_BASE;
	EMAC->TxStatus = TX_STAT_BASE;
	EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;

	/* Tx Descriptors Point to 0 */
	EMAC->TxProduceIndex = 0;
}
UNS_32 EMAC_ReadPacket(void * pPacket)
{
	UNS_32 Index = LPC_EMAC->RxConsumeIndex;
	UNS_32 size;

	if(Index == LPC_EMAC->RxProduceIndex)
	{
		return(0);
	}

	size = (RX_STAT_INFO(Index) & 0x7ff)+1;
	if (size > ETH_FRAG_SIZE)	size = ETH_FRAG_SIZE;
  	
	memcpy(pPacket,(unsigned int *)RX_BUF(Index),size);

	if(++Index > LPC_EMAC->RxDescriptorNumber)
	{
		Index = 0;
	}
	LPC_EMAC->RxConsumeIndex = Index;

	return(size);
}
Example #13
0
void Init_EthMAC(void)
{
  unsigned int value, phyid1, phyid2;
  volatile unsigned int loop;
  unsigned phy_in_use = 0;
  unsigned phy_linkstatus_reg;
  unsigned phy_linkstatus_mask;  


  /* Power Up the EMAC controller. */
  LPC_SC->PCONP |= (0x1<<30);

#if RMII
  LPC_IOCON->P1_0  &= ~0x07;	/*  ENET I/O config */
  LPC_IOCON->P1_0  |= 0x01;		/* ENET_TXD0 */
  LPC_IOCON->P1_1  &= ~0x07;	
  LPC_IOCON->P1_1  |= 0x01;		/* ENET_TXD1 */
  LPC_IOCON->P1_4  &= ~0x07;
  LPC_IOCON->P1_4  |= 0x01;		/* ENET_TXEN */
  LPC_IOCON->P1_8  &= ~0x07;	
  LPC_IOCON->P1_8  |= 0x01;		/* ENET_CRS */
  LPC_IOCON->P1_9  &= ~0x07;	
  LPC_IOCON->P1_9  |= 0x01;		/* ENET_RXD0 */
  LPC_IOCON->P1_10 &= ~0x07;	
  LPC_IOCON->P1_10 |= 0x01;		/* ENET_RXD1 */
  LPC_IOCON->P1_14 &= ~0x07;	
  LPC_IOCON->P1_14 |= 0x01;		/* ENET_RX_ER */
  LPC_IOCON->P1_15 &= ~0x07;	
  LPC_IOCON->P1_15 |= 0x01;		/* ENET_REF_CLK */
#else
  LPC_IOCON->P1_0  &= ~0x07;	/*  ENET I/O config */
  LPC_IOCON->P1_0  |= 0x01;		/* ENET_TXD0 */
  LPC_IOCON->P1_1  &= ~0x07;	
  LPC_IOCON->P1_1  |= 0x01;		/* ENET_TXD1 */
  LPC_IOCON->P1_2  &= ~0x07;
  LPC_IOCON->P1_2  |= 0x01;		/* ENET_TXD2 */
  LPC_IOCON->P1_3  &= ~0x07;	
  LPC_IOCON->P1_3  |= 0x01;		/* ENET_TXD3 */
  LPC_IOCON->P1_4  &= ~0x07;
  LPC_IOCON->P1_4  |= 0x01;		/* ENET_TXEN */
  LPC_IOCON->P1_5  &= ~0x07;	
  LPC_IOCON->P1_5  |= 0x01;		/* ENET_TXER */
  LPC_IOCON->P1_6  &= ~0x07;	
  LPC_IOCON->P1_6  |= 0x01;		/* ENET_TX_CLK */
  LPC_IOCON->P1_7  &= ~0x07;	
  LPC_IOCON->P1_7  |= 0x01;		/* ENET_COL */
  LPC_IOCON->P1_8  &= ~0x07;	
  LPC_IOCON->P1_8  |= 0x01;		/* ENET_CRS */
  LPC_IOCON->P1_9  &= ~0x07;	
  LPC_IOCON->P1_9  |= 0x01;		/* ENET_RXD0 */
  LPC_IOCON->P1_10 &= ~0x07;	
  LPC_IOCON->P1_10 |= 0x01;		/* ENET_RXD1 */
  LPC_IOCON->P1_11 &= ~0x07;	
  LPC_IOCON->P1_11 |= 0x01;		/* ENET_RXD2 */
  LPC_IOCON->P1_12 &= ~0x07;	
  LPC_IOCON->P1_12 |= 0x01;		/* ENET_RXD3 */
  LPC_IOCON->P1_13 &= ~0x07;	
  LPC_IOCON->P1_13 |= 0x01;		/* ENET_RX_DV */
  LPC_IOCON->P1_14 &= ~0x07;	
  LPC_IOCON->P1_14 |= 0x01;		/* ENET_RX_ER */
  LPC_IOCON->P1_15 &= ~0x07;	
  LPC_IOCON->P1_15 |= 0x01;		/* ENET_RX_CLK/ENET_REF_CLK */
#endif

#if 1
  LPC_IOCON->P1_16 &= ~0x07;	/* ENET/PHY I/O config */
  LPC_IOCON->P1_16 |= 0x01;		/* ENET_MDC */
  LPC_IOCON->P1_17 &= ~0x07;	
  LPC_IOCON->P1_17 |= 0x01;		/* ENET_MDIO */
//  LPC_IOCON->LOC_ENET_MDIO = 0x01;
#endif
#if 0
  LPC_IOCON->P2_8 &= ~0x07;	/* ENET/PHY I/O config */
  LPC_IOCON->P2_8 |= 0x04;		/* ENET_MDC */
  LPC_IOCON->P2_9 &= ~0x07;	
  LPC_IOCON->P2_9 |= 0x04;		/* ENET_MDIO */
//  LPC_IOCON->LOC_ENET_MDIO = 0x00;
#endif

  // Set up MAC Configuration Register 1
  LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | 
         MAC1_RES_MCS_RX |MAC1_SIM_RES | MAC1_SOFT_RES;

  // Set up MAC Command Register
  LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
  
  // Short delay
  for (loop = 100; loop; loop--);

  // Set up MAC Configuration Register 1 to pass all receive frames
  LPC_EMAC->MAC1 = MAC1_PASS_ALL;
  // Set up MAC Configuration Register 2 to append CRC and pad out frames
  LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;

  // Set Ethernet Maximum Frame Register
  LPC_EMAC->MAXF = ETH_MAX_FLEN;
  // Set Collision Window / Retry Register
  LPC_EMAC->CLRT = CLRT_DEF;
  // Set Non Back-to-Back Inter-Packet-Gap Register
  LPC_EMAC->IPGR = IPGR_DEF;

  /* Enable Reduced MII interface. */
  LPC_EMAC->MCFG = MCFG_CLK_DIV64 | MCFG_RES_MII;
  for (loop = 100; loop; loop--);
  LPC_EMAC->MCFG = MCFG_CLK_DIV64;

  // Set MAC Command Register to enable Reduced MII interface
  // and prevent runt frames being filtered out
  LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;

  // Put PHY into reset mode
  WriteToPHY (PHY_REG_BMCR, 0x8000);

  // Loop until hardware reset completes
  for (loop = 0; loop < 0x100000; loop++) {
    value = ReadFromPHY (PHY_REG_BMCR);
    if (!(value & 0x8000)) {
      // Reset has completed
      break;
    }
  }

  // Just check this actually is a DP83848C PHY
  phyid1 = ReadFromPHY (PHY_REG_IDR1);
  phyid2 = ReadFromPHY (PHY_REG_IDR2);

  if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == DP83848C_ID) {
    phy_in_use =  DP83848C_ID;
  }
  else if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == LAN8720_ID) {
    phy_in_use = LAN8720_ID;
  }

  if (phy_in_use != 0) {	  
    // Safe to configure the PHY device

    // Set PHY to autonegotiation link speed
    WriteToPHY (PHY_REG_BMCR, PHY_AUTO_NEG);
    // loop until autonegotiation completes
    for (loop = 0; loop < 0x100000; loop++) {
      value = ReadFromPHY (PHY_REG_BMSR);
      if (value & 0x0020) {
        // Autonegotiation has completed
        break;
      }
    }
  }

  // Now check the link status
  for (loop = 0; loop < 0x10000; loop++) {
  	value = ReadFromPHY (PHY_REG_BMSR);
      if (value & 0x04) {						/* bit 2 of BSR = 1? Link Up  */
      // The link is on
      break;
    }
  }


  // Configure the EMAC with the established parameters
  switch (phy_in_use) {
  	  case DP83848C_ID:

  		  value = ReadFromPHY (PHY_REG_STS);	/* PHY Extended Status Register  */
  		  // Now configure for full/half duplex mode
  		  if (value & 0x0004) {
  		    // We are in full duplex is enabled mode
  			  LPC_EMAC->MAC2    |= MAC2_FULL_DUP;
  			  LPC_EMAC->Command |= CR_FULL_DUP;
  			  LPC_EMAC->IPGT     = IPGT_FULL_DUP;
  		  }
  		  else {
  		    // Otherwise we are in half duplex mode
  			  LPC_EMAC->IPGT = IPGT_HALF_DUP;
  		  }

  		  // Now configure 100MBit or 10MBit mode
  		  if (value & 0x0002) {
  		    // 10MBit mode
  			  LPC_EMAC->SUPP = 0;
  		  }
  		  else {
  		    // 100MBit mode
  			  LPC_EMAC->SUPP = SUPP_SPEED;
  		  }
  		  break;

  	  case LAN8720_ID:

  		  value = ReadFromPHY (PHY_REG_SCSR);	/* PHY Extended Status Register  */
  		  // Now configure for full/half duplex mode
  		  if (value & (1<<4)) {		/* bit 4: 1 = Full Duplex, 0 = Half Duplex  */
    		  // We are in full duplex is enabled mode
  			  LPC_EMAC->MAC2    |= MAC2_FULL_DUP;
  			  LPC_EMAC->Command |= CR_FULL_DUP;
  			  LPC_EMAC->IPGT     = IPGT_FULL_DUP;
  		  }else {
   		      // Otherwise we are in half duplex mode
    		  LPC_EMAC->IPGT = IPGT_HALF_DUP;
  		  }

  		  // Now configure 100MBit or 10MBit mode
  		  if (value & (1<<3)) {	/* bit 3: 1 = 100Mbps, 0 = 10Mbps  */
  			  // 100MBit mode
    		  LPC_EMAC->SUPP = SUPP_SPEED;
  		  }else {
    		  // 10MBit mode
    		  LPC_EMAC->SUPP = 0;
  		  }


  		  break;

  }

  // Now set the Ethernet MAC Address registers
  // NOTE - MAC address must be unique on the network!
  LPC_EMAC->SA0 = (MYMAC_1 << 8) | MYMAC_2; // Station address 0 Reg
  LPC_EMAC->SA1 = (MYMAC_3 << 8) | MYMAC_4; // Station address 1 Reg
  LPC_EMAC->SA2 = (MYMAC_5 << 8) | MYMAC_6; // Station address 2 Reg

  // Now initialise the Rx descriptors    
  for (loop = 0; loop < NUM_RX_FRAG; loop++) {
    RX_DESC_PACKET(loop)  = RX_BUF(loop);
    RX_DESC_CTRL(loop)    = RCTRL_INT | (ETH_FRAG_SIZE-1);
    RX_STAT_INFO(loop)    = 0;
    RX_STAT_HASHCRC(loop) = 0;
  }

  // Set up the Receive Descriptor Base address register
  LPC_EMAC->RxDescriptor    = RX_DESC_BASE;
  // Set up the Receive Status Base address register
  LPC_EMAC->RxStatus        = RX_STAT_BASE;
  // Setup the Receive Number of Descriptor register
  LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
  //  Set Receive Consume Index register to 0
  LPC_EMAC->RxConsumeIndex  = 0;

  // Now initialise the Tx descriptors 
  for (loop = 0; loop < NUM_TX_FRAG; loop++) {
    TX_DESC_PACKET(loop) = TX_BUF(loop);
    TX_DESC_CTRL(loop)   = 0;
    TX_STAT_INFO(loop)   = 0;
  }

  // Set up the Transmit Descriptor Base address register
  LPC_EMAC->TxDescriptor    = TX_DESC_BASE;
  // Set up the Transmit Status Base address register
  LPC_EMAC->TxStatus        = TX_STAT_BASE;
  // Setup the Transmit Number of Descriptor register
  LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
  //  Set Transmit Consume Index register to 0
  LPC_EMAC->TxProduceIndex  = 0;
 
  // Receive Broadcast and Perfect Match Packets



  LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN;					 
 
  // Enable interrupts MAC Module Control Interrupt Enable Register
  LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;

  // Reset all ethernet interrupts in MAC module
  LPC_EMAC->IntClear  = 0xFFFF;

  // Finally enable receive and transmit mode in ethernet core
  LPC_EMAC->Command  |= (CR_RX_EN | CR_TX_EN);
  LPC_EMAC->MAC1     |= MAC1_REC_EN;
}
Example #14
0
BOOL LPC24XX_EMAC_lwip_init ( struct netif *pNetIf )
{
    UINT32 i;
    LPC24XX_EMAC & ENET = *(LPC24XX_EMAC *)LPC24XX_EMAC::c_EMAC_Base;

    /* Power Up the EMAC controller. */
    LPC24XX::SYSCON().PCONP |= LPC24XX_SYSCON::ENABLE_ENET;
    
    /* Connect EMAC pins */
    LPC24XX_EMAC_lwip_setpins( ENET_PHY_lwip_get_MII_mode() );
    
    /* Reset EMAC */
    ENET.MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
                    MAC1_SIM_RES | MAC1_SOFT_RES;
    ENET.MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;
    HAL_Time_Sleep_MicroSeconds(1);
    
      /* Initialize MAC control registers. */
    ENET.MAC_MAC1 = 0;
    ENET.MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
    ENET.MAC_MAXF = ETH_MAX_FLEN;
    ENET.MAC_CLRT = CLRT_DEF;
    ENET.MAC_IPGR = IPGR_DEF;

    if ( !ENET_PHY_lwip_get_MII_mode() )
    {
        /* Enable RMII mode in MAC command register */
        ENET.MAC_COMMAND = ENET.MAC_COMMAND | CR_RMII;
    }

    /* Reset MII Management hardware */
    ENET.MAC_MCFG = MCFG_RES_MII;
    HAL_Time_Sleep_MicroSeconds(1);
    
    /* Set MDC Clock divider */
    ENET.MAC_MCFG = ENET_PHY_lwip_get_MDC_Clk_Div() & MCFG_CLK_SEL;

    /* Initialiaze external ethernet Phy */
    if ( !ENET_PHY_lwip_init() )
    {
        return FALSE;
    }

    /* Set the Ethernet MAC Address registers */
    ENET.MAC_SA2 = (pNetIf->hwaddr[1] << 8) | pNetIf->hwaddr[0];
    ENET.MAC_SA1 = (pNetIf->hwaddr[3] << 8) | pNetIf->hwaddr[2];
    ENET.MAC_SA0 = (pNetIf->hwaddr[5] << 8) | pNetIf->hwaddr[4];
    
    /* Setup the Rx DMA Descriptors */
    for (i = 0; i < NUM_RX_FRAG; i++)
    {
        RX_DESC_PACKET(i)  = RX_BUF(i);
        RX_DESC_CTRL(i)    = RCTRL_INT | (ETH_FRAG_SIZE-1);
        RX_STAT_INFO(i)    = 0;
        RX_STAT_HASHCRC(i) = 0;
    }

    /* Set the EMAC Rx Descriptor Registers. */
    ENET.MAC_RXDESCRIPTOR    = RX_DESC_BASE;
    ENET.MAC_RXSTATUS        = RX_STAT_BASE;
    ENET.MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1;
    ENET.MAC_RXCONSUMEINDEX  = 0;

    /* Setup the Tx DMA Descriptors */
    for (i = 0; i < NUM_TX_FRAG; i++) 
    {
        TX_DESC_PACKET(i) = TX_BUF(i);
        TX_DESC_CTRL(i)   = 0;
        TX_STAT_INFO(i)   = 0;
    }

    /* Set the EMAC Tx Descriptor Registers. */
    ENET.MAC_TXDESCRIPTOR    = TX_DESC_BASE;
    ENET.MAC_TXSTATUS        = TX_STAT_BASE;
    ENET.MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1;
    ENET.MAC_TXPRODUCEINDEX  = 0;
    
    /* Receive Broadcast and Perfect Match Packets */
    ENET.MAC_RXFILTERCTRL = RFC_PERFECT_EN | RFC_BCAST_EN;
    
    /* Enable EMAC interrupts. */
    ENET.MAC_INTENABLE = INT_RX_DONE | INT_TX_DONE | INT_TX_UNDERRUN | INT_RX_OVERRUN;

    /* Reset all interrupts */
    ENET.MAC_INTCLEAR  = 0xFFFF;

    /* Enable receive and transmit */
    ENET.MAC_COMMAND  |= (CR_RX_EN | CR_TX_EN);
    ENET.MAC_MAC1     |= MAC1_REC_EN;
    
    return TRUE;
}