⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne64driver.c

📁 用于以太网开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 *                      (c) Freescale  Inc. 2004 All rights reserved
 *
 * File Name     : ne64driver.c
 *
 * PURPOSE: NE64 Ethernet API
 *
 * DESCRIPTION: Defines higher level routines for the EMAC module
 *
 * Version : 3.0
 * Date    : 06/07/04
 *
 *****************************************************************************/
#include "MOTTYPES.h"
#include "address.h"
#include "ne64config.h"
#include "ne64driver.h"
#include "ne64debug.h"          /* diagnostics - enabled when SCI_DEBUG defined */
#include "IO_Map.h"

/* CALLBACK function from EMAC ISR */
extern UINT16 NE64Receive (void *PktBuffer, UINT16 len, UINT16 flags);

/* These structures/unions should NOT be exported! */
typedef union uMCHASHUnion
  {
  tU16 Word[4];         /* Multicast Hash Table bits 63 to 0 */
  tU08 Byte[8];
  }tMCHASHStr;

typedef union uMACADUnion
{
  tU16 Word[3];         /* MAC Address bits 47 to 0 */
  tU08 Byte[6];
} tMACADStr;

typedef struct
  {
   tU08 da[6]; /**< destination address */
   tU08 sa[6]; /**< source address */
   tU16 ft;    /**< frame type */
  }tFRHEAD;
  
typedef tFRHEAD * pFRHEAD;



#define RAM_START 0x2000    /**< RAM block starting address */

#if WORD_ACCESS
  tREG16 emacFIFOa[EMAC_RX_SZ/2] @ RAM_START;                     /**< Emac RX buffer A definition */
  tREG16 emacFIFOb[EMAC_RX_SZ/2] @ (RAM_START + EMAC_RX_SZ);      /**< Emac RX buffer B definition */
  tREG16 emacFIFOtx[EMAC_TX_SZ/2] @ (RAM_START + 2*EMAC_RX_SZ);   /**< Emac TX buffer definition */
#else
  tU08 emacFIFOa[EMAC_RX_SZ] @ RAM_START;                         /**< Emac RX buffer A definition */
  tU08 emacFIFOb[EMAC_RX_SZ] @ (RAM_START + EMAC_RX_SZ);          /**< Emac RX buffer B definition */
  tU08 emacFIFOtx[EMAC_TX_SZ] @ (RAM_START + 2*EMAC_RX_SZ);       /**< Emac TX buffer definition */
#endif


//extern section
  extern   tU08    activebuffer;
  extern   tU08    gotlink;

#if WORD_ACCESS
  extern   tREG16    *rxa_pointer;
  extern   tREG16    *rxb_pointer;
  extern   tREG16    *tx_pointer;
#else
  extern   tU08    *rxa_pointer;
  extern   tU08    *rxb_pointer;
  extern   tU08    *tx_pointer;
#endif		//WORD_ACCESS
#if USE_SWLED
extern tU16 LEDcounter;
#endif	 //USE_SWLED


tU16 gotxflowc;			/**<Global Variable For Determination of
                                      * Flow Control Packets are sent in Full Duplex
                                      * defined in "main.c" */

tU08	gotlink;   						/**<Global Variable For Determination if
                                      * link is active (1=active)
                                      * defined in "main.c" */
                                      

                                     //Intialize Ethernet Module
//===============================================
void EtherInit (void)
{

  //Variable
  tU16 myctr; 								//generic counter variable
  tU16 mymrdata, mymwdata;    //temp variable for MII read/write data
  tU16 angotduplex, 					//Auto negotiation control variable
       etypecontrol, 				  //Ethertype filter control variable
       addressfiltercontrol;	//address filter control variable


  //No link present
  gotlink = 0;

  //=========================
  //PHY Inits	 - enable EPHY module	and EPHY Interrupt
  //=========================

  //Write PHY address before EPHYEN is set; this will latch EPHY register 14 on reset
  //address PHY 0 (default address of internal PHY); PHYADD0 | PHYADD1 | PHYADD2 | PHYADD3| PHYADD4
  EPHYCTL1 = PHY_ADDRESS;	 //Modify in "ne64config.h"

  //Enable EPHY module with PHY clocks disabled
  //Do not trun on PHY clocks untill both EMAC and EPHY are completely setup (see Below)
  EPHYCTL0 = EPHYCTL0_DIS100_MASK | EPHYCTL0_DIS10_MASK;
#if  AUTO_NEG
  //Enable auto_neg at start-up
  EPHYCTL0 = EPHYCTL0 & (~EPHYCTL0_ANDIS_MASK);
#else				//ELSE AUTO_NEG
  //Disable auto_neg at start-up
  EPHYCTL0 = EPHYCTL0 | EPHYCTL0_ANDIS_MASK;
#endif	    //AUTO_NEG

  //Enable EPHY module
  EPHYCTL0 = EPHYCTL0_EPHYEN_MASK | EPHYCTL0;      //Enable PHY

  //Enable EPHY LEDs and Interrupts
#if USE_SWLED  

  EPHYCTL0 = EPHYCTL0 | (EPHYCTL0_EPHYIEN_MASK );
#if   ACTLED
  DDRL_DDRL0 = 1;
  PTL_PTL0 = 1; //turn off LED
#endif
#if   LNKLED
  DDRL_DDRL1 = 1;
  PTL_PTL1 = 1; //turn off LED
#endif
#if   SPDLED
  DDRL_DDRL2 = 1;
  PTL_PTL3 = 1; //turn off LED
#endif
#if   DUPLED
  DDRL_DDRL3 = 1;
  PTL_PTL3 = 1; //turn off LED
#endif
#if   COLLED
  DDRL_DDRL4 = 1;
  PTL_PTL4 = 1; //turn off LED
#endif

#else
  EPHYCTL0 = EPHYCTL0 | (EPHYCTL0_LEDEN_MASK | EPHYCTL0_EPHYIEN_MASK );
#endif

  //DELAY, Delay staret-up
  for (myctr=18000; myctr >0; myctr--);


  //=========================
  //EMAC Inits
  //========================

  //We do not duplex yet since auto_neg is not complete so use half as default
  angotduplex = 0; 				 //Auto negotiation control variable

  //Configure RX mode based on EtherInit() define settings
  addressfiltercontrol = 0;		 //address filter control variable
#if (BRODC_REJ)
    addressfiltercontrol = addressfiltercontrol | BCREJ;
#endif
#if (CON_MULTIC)
    addressfiltercontrol = addressfiltercontrol | CONMC;
#endif
#if (PROM_MODE)
    addressfiltercontrol = addressfiltercontrol | PROM;
#endif

  //Configure Ethertype based on EtherInit() define settings
  etypecontrol = 0;				 //Ethertype filter control variable
#if (ETYPE_PET)
    etypecontrol = etypecontrol | T_PET;
#endif
#if (ETYPE_EMW)
    etypecontrol = etypecontrol | T_EMW;
#endif
#if (ETYPE_IPV6)
    etypecontrol = etypecontrol | T_IPV6;
#endif
#if (ETYPE_ARP)
    etypecontrol = etypecontrol | T_ARP;
#endif
#if (ETYPE_IPV4)
    etypecontrol = etypecontrol | T_IPV4;
#endif
#if (ETYPE_IEEE)
    etypecontrol = etypecontrol | T_IEEE;
#endif
#if (ETYPE_ALL)
    etypecontrol = etypecontrol & T_ALL;
#endif

  //Initialize EMAC including MII management Interface
  EtherOpen(MII_MDCSEL(BUS_CLOCK),
            BUFMAP,                   // defined in 'emacfifocfg.h'
            RX_MAX_FL,                // RX max packet lenght
            (void *)hard_addr,        // defined in 'address.h'
            etypecontrol,                // program ethertype fixed filter target */
            ETYPE_PRG,                // program prgramable ethertype value related to T_PET */
#if XFLOWC	 //this should be only enabled in auto negotiation if pause resolution confirms this (full duplex only)
            RFCE | addressfiltercontrol,
#else             //ELSE XFLOWC
            addressfiltercontrol,
#endif						//XFLOWC

#if  AUTO_NEG
            //Configure Net Control: Duplex, external PHY, loopback, wait
            angotduplex		        //Half Duplex operation default until auto_neg is complete
#else			//ELSE AUTO_NEG (manual speed duplex settings)
#if FULL_DUPLEX
            NETCT_FDX           // full duplex operation */
#else     //ELSE FULL_DUPLEX
            angotduplex           //Half Duplex operation */
#endif	  //FULL_DUPLEX
#endif		//AUTO_NEG
            );

  //Enable Select EMAC interrrupt: 
  IMASK = IMASK_TXCIE_MASK | IMASK_ECIE_MASK | IMASK_LCIE_MASK;
#if (!RX_POLL_MODE)    //USE RX INTERRUPTS
  IMASK = IMASK | IMASK_RXACIE_MASK |  IMASK_RXBCIE_MASK;
#endif  // RX_POLL_MODE
  IMASK = IMASK | IMASK_RXAOIE_MASK|IMASK_RXBOIE_MASK | IMASK_RXEIE_MASK;				//Buffer Overruns & RX error
  IMASK = IMASK | IMASK_BREIE_MASK;             //Babbling Error		
  IMASK = IMASK | IMASK_RFCIE_MASK;							//RX flow Control								  


  //Transmit pause initialization: set bit and pause time  duration
#if XFLOWC

#if AUTO_NEG
//   EtherPause(1,PAUSE_TIME);			 // PAUSE_TIME defined in "ne64config.h"
#endif	  //AUTO_NEG

#if FULL_DUPLEX
   gotxflowc = 1;
//   EtherPause(1,PAUSE_TIME);
#endif	  //FULL_DUPLEX

#endif		//XFLOWC

//===============================================
// Configure PHY through EMAC MII Serial Management now that MII clock is set (address PHY is 0x00)
//===============================================
   //READ  PHY_REG_IDX: PHY idenfitication which is composed from OUI and make/model/revision of PHY
#if READ_PHY_ID
   //read PHY_REG_ID1
   while ( !(MIIread(PHY_ADDRESS, PHY_REG_ID1 , &mymrdata)) );

   //read PHY_REG_ID2 - should be:
   while ( !(MIIread(PHY_ADDRESS, PHY_REG_ID2 , &mymrdata))  );

   //read PHY_REG_ADDR - should be: 0x00
   while ( !(MIIread(PHY_ADDRESS, PHY_REG_ADDR , &mymrdata)) );
#endif


//Read PHY_REG_ANAR then configure the PHY Link abilities for auto_negoigation
#if AUTO_NEG
   while ( !(MIIread(PHY_ADDRESS, PHY_REG_ANAR, &mymrdata)) );

//Configure Flow Control PHY Link abilities advertisement
    mymwdata = mymrdata;
#if XFLOWC
   mymwdata = mymwdata | PHY_R4_FC;
#endif //#if XFLOWC

//Configure Speed and Duplex PHY Link abilities advertisement
#if (~FULL10  & 1)
    mymwdata = mymwdata & ~PHY_R4_10F;
#endif
#if (~HALF10  & 1)
    mymwdata = mymwdata & ~PHY_R4_10H;
#endif
#if (~HALF100 & 1)  || (USE_EXTBUS)
    mymwdata = mymwdata & ~PHY_R4_100H;
#endif
#if (~FULL100  & 1)	 || (USE_EXTBUS)
    mymwdata = mymwdata & ~PHY_R4_100F;
#endif

   //Write PHY_REG_ANAR to configure PHY Link abilities advertisement
   while ( !(MIIwrite(PHY_ADDRESS, PHY_REG_ANAR, mymwdata  ))    );

#endif //#if AUTO_NEG

   //Enable PHY interrupts in Reg 16 (PHY Interrupt Control Register)
	 //Set PHY Interrupt Control Register
   mymwdata = PHY_R16_ACKIE | PHY_R16_PRIE | PHY_R16_LCIE | PHY_R16_ANIE;
   mymwdata = mymwdata | PHY_R16_PDFIE | PHY_R16_RFIE | PHY_R16_JABIE;
   while ( ! (MIIwrite(PHY_ADDRESS, PHY_REG_IR, mymwdata))   );

//===============================================
// Start up EPHY clocks (PLLs)
//===============================================

   //Read PHY Control Register 0
   while ( !(MIIread(PHY_ADDRESS, PHY_REG_CR, &mymrdata)) );


//Start up EPHY in auto negotiation
#if  AUTO_NEG

	 //Start PHY PLLs
     EPHYCTL0 = EPHYCTL0  & ~(EPHYCTL0_DIS100_MASK | EPHYCTL0_DIS10_MASK); //Let PHY PLLs be determined by PHY

//Start up EPHY without auto negotiation (CONFIGURE MANUALLY- SPEED AND DUPLEX)
#else	 //NO AUTO_NEG

//Set Duplex MANUALLY
#if FULL_DUPLEX
   mymwdata = mymrdata | PHY_R0_DPLX;		  //Set Full Duplex
#else                   //ELSE FULL_DUPLEX
   mymwdata = mymrdata & ~PHY_R0_DPLX;    //Set Half Duplex
#endif	                //FULL_DUPLEX

//Set Speed MANUALLY
#if SPEED100
#if USE_EXTBUS	 //OVERRIDE USER: Set SPEED10 since with Extbus&Ethernet speed limit is 10 Mbps
   mymwdata = mymwdata & ~PHY_R0_DR;
   //add warning		
#else
   mymwdata = mymwdata | PHY_R0_DR;		//Set SPEED100
#endif   
#else                   //ELSE SPEED100
   mymwdata = mymwdata & ~PHY_R0_DR;		//Set SPEED10
#endif	                //SPEED100

   //Write Config Register to set manually configure speed and duplex
   while ( !(MIIwrite(PHY_ADDRESS, PHY_REG_CR, mymwdata ))    );

	 //Start EPHY PLLs
   EPHYCTL0 = EPHYCTL0  & ~(EPHYCTL0_DIS100_MASK | EPHYCTL0_DIS10_MASK); //Let PHY PLLs be determined by PHY


#endif			      //AUTO_NEG

}

  
//===============================================
tU08 MIIwrite(tU08 _mpadr, tU08 _mradr, tU16 _mwdata) {
 
  tU16 temprdata;

  _DEBUGNL;_DEBUGT("-MIIWRITE-");
  if (MCMST_BUSY)
  {
   _DEBUGT("-MII_BUSY ");
   return 0; /* MII busy -> return with error  */
  }
  MPADR=_mpadr;
  MRADR=_mradr;
  MWDATA=_mwdata;
  MCMST_OP=MII_WRITE;

  //Wait for MII write
  while (!IEVENT_MMCIF); /* wait for transfer completed */
  IEVENT = IEVENT_MMCIF_MASK; /* Clear the flag in Emac */
  
  while ( ! (MIIread(PHY_ADDRESS, PHY_REG_IR, &temprdata))   );
    
  return 0xff; /* operation completed OK */
}

//===============================================
 tU08 MIIread(tU08 _mpadr, tU08 _mradr, tU16 * _mrdata)  {
 
  _DEBUGNL;_DEBUGT("-MIIREAD-");  
  if (MCMST_BUSY)
  {
   _DEBUGT("-MII_BUSY ");
   return 0; /* MII busy -> return with error */
  }

  MPADR=_mpadr;
  MRADR=_mradr;
  MCMST_OP=MII_READ;

  //Wait for MII read
  while (!IEVENT_MMCIF); /* wait for transfer completed */
  *_mrdata = MRDATA;
  IEVENT = IEVENT_MMCIF_MASK; /* Clear the flag in Emac */

  _DEBUGT("DATA= "); _DEBUGI(*_mrdata);	 _DEBUGNL;
  return 0xff; /* operation completed OK */
}



//===============================================
#if RX_POLL_MODE
tU16 EtherReceive(void * buffer)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -