IPC@CHIP® RTOS-PPC – API Documentation

Header image

Main page


Explanations and source code example

Ethernet PHY API functions

The SC2x3 ethernet MAC interface requires the connection of an external PHY transceiver via the MII-Interface.
By default the TCPIP ethernet device driver supports the PHY Intel LTX971A, in accordance to the following chip.ini settings at the section [IP]:

If the chip.ini section [IP] doesn't contain an entry ETH_ENABLE=0 , the driver tries to detect the existance of a LXT971A device by reading the standard PHY identifier registers 2 and 3.

If the detection of the LXT971A failed, the driver initializes the found PHY with a basic functionality by programming the standard PHY control register 0 in accordance with the Chip.ini setting ETH_MODE. This action is required to provide a running ethernet device at boottime of the RTOS, regardless of the connected PHY transceiver and an existing driver application (provided by the user).

The implementation of an own PHY driver application is required, if the user wants to connect a specific PHY transceiver to the SC2x3 ethernet MAC instead of the LXT971A.

Therefor the Ethernet API of the SC2x3-RTOS provides several functions:

ethMiiWrite( ) Write PHY register via MII interface
ethMiiRead( ) Read PHY register
ethPhyInstall( ) Installation of the PHY driver functions
ethReStart( ) Start of the ethernet device<br>

The PHY driver application has to provide the functions as listed below. The source code example is made for an LXT971A PHY transceiver. The used register constants are listed at the end of this document.

Note:
Normally a PHY driver application runs forever (recommended). If an application calls ethPhyInstall with parameter NULL and exits, the Ethernet device is stopped. A new start of the PHY driver application is required to use the Ethernet device again.
If an application exits without uninstalling the PHY driver functions, the Ethernet device restarts with a minimal set of basic PHY functions as described above.

int myPhyConfigure(WORD ethMode)
{
  int notimeout;
  WORD miidata;
  WORD status;
 
  // reset PHY first 
  ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_CNTL, MII_CNTL_RESET);
  RTX_Sleep_Time(1);
  ethMiiRead(ethPhyCtrl.phyAddr,MII_REG_CNTL,&miidata);
  if(miidata & MII_CNTL_RESET)
  {
         return -1; //Reset failed
  }
  if(ethMode==ETH_AUTO) //Autonegotiation
  {
      // write autoneg advertisement register
      ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_AN_ADV, 
                  MII_AN_100BTX_FDX | MII_AN_100BTX | MII_AN_10BT_FDX |
                  MII_AN_10BT | MII_AN_802_3);
     //Start autonegotiation
     ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_CNTL, MII_CNTL_AUTONEG_EN |
                 MII_CNTL_SPEED_100 | MII_CNTL_AUTONEG_EN | MII_CNTL_FDX);
     //wait for autonegotiation to complete
     notimeout = 5000; //in milliseconds == 5s
     do {
          RTX_Sleep_Time(1);
          if(ethMiiRead(ethPhyCtrl.phyAddr, MII_REG_STAT, &miidata))
          {
             miidata = 0;
          }
     } while(!(miidata & MII_STAT_AUTO_NEG) && (--notimeout));
  }
  else //Fixed mode
  {
     switch(ethMode)
     {
        case  ETH_10_HD:   miidata=MII_CNTL_SPEED_10;
                           break;
        case  ETH_10_FD:   miidata=MII_CNTL_SPEED_10 | MII_CNTL_FDX;
                           break;
        case  ETH_100_HD:  miidata=MII_CNTL_SPEED_100;
                           break;
        case  ETH_100_FD:  miidata=MII_CNTL_SPEED_100 | MII_CNTL_FDX;
                           break;
     }
     ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_CNTL, miidata);
     //Now poll max. 4 seconds for link up
     notimeout = 4000; //in milliseconds == 4s
     do {
         RTX_Sleep_Time(1);
         if(ethMiiRead(ethPhyCtrl.phyAddr, MII_REG_XSTAT, &miidata))
         {
           miidata = 0;
         }
    } while(!(miidata & MII_XSTAT_LINK) && (--notimeout));
  }
  //Enable the PHY interrupt events
  if(ethPhyCtrl.phyIRQ!=-1)
  {
     ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_IEN,
                  MII_INTEN_INTEN | MII_INTEN_LINKMSK | MII_INTEN_DPLXMSK
                  | MII_INTEN_SPEEDMSK  | MII_INTEN_ANMSK);
  }
  return 0;
}
 WORD  myPhyEventCb(void)
 {
   WORD phyIntStatus,phyStatus;
   //Ack PHY interrupt by reading interrupt status register 19
   if(0==ethMiiRead(ethPhyCtrl.phyAddr,MII_REG_ISTAT, &phyIntStatus))
   {
     phyStatus = myPhyGetStatus();
     //Check, if the duplex mode has changed
     if(phyIntStatus & MII_INTSTAT_DPLXCHG)
     {
         phyStatus |= ETH_PHYSTAT_DPLXCHG;
     }
   }
   return phyStatus;
}
 WORD  myPhyGetStatus(void)
 {
   WORD phyStatusLXT91A,phyStatus=0;
   if(0==ethMiiRead(ethPhyCtrl.phyAddr, MII_REG_XSTAT, &phyStatusLXT91A))
   {
       if(phyStatusLXT91A & MII_XSTAT_LINK)    phyStatus|=ETH_PHYSTAT_LINKUP;
       if(phyStatusLXT91A & MII_XSTAT_100MB)   phyStatus|=ETH_PHYSTAT_100MB;
       if(phyStatusLXT91A & MII_XSTAT_DPLX)    phyStatus|=ETH_PHYSTAT_FDPLX;
       if(phyStatusLXT91A & MII_XSTAT_ERR)     phyStatus|=ETH_PHYSTAT_ERR;
       if(phyStatusLXT91A & MII_XSTAT_AUTONEG) phyStatus|=ETH_PHYSTAT_AUTONEG;
   }
   return phyStatus;
 }
 int myPhyStop(void)
 {
    return ethMiiWrite(ethPhyCtrl.phyAddr, MII_REG_CNTL, MII_CNTL_ISOLATE);
 }
 int main(void)
 {
    //Setup the parameters
    EthPhyCtrl ethPhyCtrl={0,  //Hardware address
                           2, //IRQ (0-3, -1 none)
                           myPhyConfigure, //Function pointers
                           myPhyEventCb,
                           myPhyGetStatus,
                           myPhyStop);
    
    if(ethPhyInstall(&ethPhyCtrl)==0)
    {
       ethReStart();
    }
    else
    {
        return -1;
    }
    //Exit, but program's image remains in memory
    BIOS_Tsr_Exit (0);
 }
#define MII_REG_CNTL       0     // control
#define MII_REG_STAT       1     // status
#define MII_REG_ID1        2     // PHY identification register 1
#define MII_REG_ID2        3     // PHY identification register 2
#define MII_REG_AN_ADV     4     // auto-negotiation advertisement
#define MII_REG_XSTAT      17    // extended status
#define MII_REG_IEN        18    // Interrupt enable
#define MII_REG_ISTAT      19    // Interrupt status

// MII control register bits
#define MII_CNTL_RESET        0x8000   // PHY reset
#define MII_CNTL_LOOPBACK     0x4000   // enable loopback mode
#define MII_CNTL_SPEED_100    0x2000   // set speed 100 Mbps
#define MII_CNTL_AUTONEG_EN   0x1000   // enable auto-negotiation
#define MII_CNTL_POWER_DOWN   0x0800   // power down
#define MII_CNTL_ISOLATE      0x0400   // electrically isolate PHY from MII
#define MII_CNTL_RESTART_AN   0x0200   // restart auto-negotiation
#define MII_CNTL_FDX          0x0100   // full duplex mode
#define MII_CNTL_COL_TEST     0x0080   // enable collision signal test
#define MII_CNTL_SPEED_10     0x0000   // set speed 10 Mbps

// MII status register bits
#define MII_STAT_100BT4       0x8000   // supports 100Base-T4
#define MII_STAT_100BX_FDX    0x4000   // supports 100Base-X full duplex
#define MII_STAT_100BX_HDX    0x2000   // supports 100Base-X half duplex
#define MII_STAT_10_FDX       0x1000   // supports 10 Mbps full duplex
#define MII_STAT_10_HDX       0x0800   // supports 10 Mbps half duplex
#define MII_STAT_100BT2_FDX   0x0400   // supports 100Base-T2 full duplex
#define MII_STAT_100BT2_HDX   0x0200   // supports 100Base-T2 half duplex
#define MII_STAT_EXT          0x0100   // extended status in reg 15
#define MII_STAT_MFP_SUPR     0x0040   // mgmt frames w/ preamble suppressed
#define MII_STAT_AUTO_NEG     0x0020   // auto-negotiation complete
#define MII_STAT_REM_FAULT    0x0010   // remote fault condition detected
#define MII_STAT_AN_CAP       0x0008   // PHY able to perform auto-negotiation
#define MII_STAT_LINK         0x0004   // link status, 1=up
#define MII_STAT_JABBER       0x0002   // jabber condition detected
#define MII_STAT_EXT_CAP      0x0001   // extended register capable

//MII auto-negotiation advertisement bits 
#define MII_AN_NEXT_PAGE      0x8000   // port has ability to send mult pages  
#define MII_AN_REM_FAULT      0x2000   // remote fault                         
#define MII_AN_ASYM_PAUSE     0x0800   // asymmetric pause                     
#define MII_AN_PAUSE          0x0400   // pause enabled for full duplex links  
#define MII_AN_100BT4         0x0200   // advertise 100Base-T4 capable         
#define MII_AN_100BTX_FDX     0x0100   // advertise 100Base-TX full duplex cap 
#define MII_AN_100BTX         0x0080   // advertise 100Base-TX capable         
#define MII_AN_10BT_FDX       0x0040   // advertise 10Base-T full duplex capab 
#define MII_AN_10BT           0x0020   // advertise 10Base-T capable           
#define MII_AN_802_9          0x0002   // IEEE 802.9 ISLAN-16T                 
#define MII_AN_802_3          0x0001   // IEEE 802.3

// Intel LXT971A: MII Interrupt Enable Register bits
#define MII_INTEN_ANMSK       0x0080   // Auto negotiation complete 
#define MII_INTEN_SPEEDMSK    0x0040   // Speed interrupt 
#define MII_INTEN_DPLXMSK     0x0020   // Duplex interrupt 
#define MII_INTEN_LINKMSK     0x0010   // Link status
#define MII_INTEN_INTEN       0x0002   // Interrupt enable
#define MII_INTEN_TINT        0x0001   // Force interrupt on ~MDINT 

// Intel LXT971A: MII Interrupt Status Bits 
#define MII_INTSTAT_ANDONE      0x0080   // 1: Auto negotiation done 
#define MII_INSTAT_SPEEDCHG     0x0040   // 1: Speed change status 
#define MII_INTSTAT_DPLXCHG     0x0020   // 1: Duplex mode changed 
#define MII_INTSTAT_LINKCHG     0x0010   // 1: Link  mode changed 


// Intel LXT971A: MII Operating mode bits (Status reg#2 17) 
#define MII_XSTAT_100MB        0x4000   //1: Phy operates in 100MB mode, else 10 
#define MII_XSTAT_TXSTAT       0x2000   //1: Phy transmits a packet 
#define MII_XSTAT_RXSTAT       0x1000   //1: Phy receives a packet 
#define MII_XSTAT_COL          0x0800   //1: Collision occuring 
#define MII_XSTAT_LINK         0x0400   //1: Link is up 
#define MII_XSTAT_DPLX         0x0200   //1: Full duplex mode 
#define MII_XSTAT_AUTONEG      0x0100   //1: Auto negotiation mode 
#define MII_XSTAT_AUTONEGCMPL  0x0080   //1: Auto negotiation complete 
#define MII_XSTAT_POL          0x0020   //1: Polarity reversed 
#define MII_XSTAT_ERR          0x0008   //1: Error remote fault 


//Ethernet API: Phy status bits (must be translated from LXT971A or user specific phy)
#define ETH_PHYSTAT_LINKUP  0x0001   //1: Link up 
#define ETH_PHYSTAT_100MB   0x0002   //1: Phy operates in 100MB mode, 0:10MB 
#define ETH_PHYSTAT_FDPLX   0x0008   //1: Full duplex mode, 0: Half Duplex
#define ETH_PHYSTAT_ERR     0x0020   //1: Remote fault detected 
#define ETH_PHYSTAT_AUTONEG 0x0040   //1: Auto negotiation mode 
#define ETH_PHYSTAT_DPLXCHG 0x0080   //1: Duplex mode has changed 
#define ETH_PHYSTAT_LINKCHG = 0x0100 //1: Link has changed
#define ETH_PHYSTAT_FAULT   = 0x8000 //1: Error: PHY not detected or faulty

//Ethernet operating modes (CHIP.INI)
#define ETH_AUTO         0x00   //Default: Autonegotiation mode
#define ETH_10_HD        0x01   //10 Mbps Half duplex
#define ETH_10_FD        0x02   //10 Mbps Full duplex
#define ETH_100_HD       0x03   //100 Mbps Half duplex
#define ETH_100_FD       0x04   //100 Mbps Full duplex





Top of page | Main page

Copyright © 2017 Beck IPC GmbH
Generated on Thu Jan 26 16:21:35 2017 by Doxygen 1.6.1