?? ne64driver.c
字號:
/*****************************************************************************
* (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 + -