[ixp1200] l3fwdr

Botham, Mick mick.botham at intel.com
Tue Jun 3 06:10:52 EDT 2003


Vikram

You are welcome to try this code (below) I've used it on the IXP1200
dev board, I don't know how much different this is to your board.

Rgds

Mick



/***************************************************************************
***

*

* PHY.C

* 

* Access MII and symbol PHYs.

*

* Revision history : Created March 1997
                     Updated October 2001
                     Updated April 2003

*
WARRANTY DISCLAIMER.  INTEL AND ITS SUPPLIERS MAKE NO WARRANTIES WITH
RESPECT TO TECHNOLOGY, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED
WARRANTIES OF SATISFACTORY QUALITY OR FITNESS FOR A PARTICULAR PURPOSE OR
ANY IMPLIED WARRANTY OF NONINFRINGEMENT.  TECHNOLOGY IS PROVIDED AS IS,
WITHOUT WARRANTY OF ANY KIND.

LIMITATION OF LIABILITY.  INTEL AND ITS SUPPLIERS SHALL NOT BE LIABLE FOR
ANY PROPERTY DAMAGE, PERSONAL INJURY, LOSS OF PROFITS, LOSS OR CORRUPTION OF
DATA OR USE, INTERRUPTION OF BUSINESS OR ANY SPECIAL, DIRECT, INDIRECT,
CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED, WHETHER FOR
BREACH OF WARRANTY, CONTRACT, STRICT LIABILITY OR OTHERWISE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE OR LOSS.  INTEL AND ITS SUPPLIERS DISCLAIM
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY INTELLECTUAL
PROPERTY RIGHTS RELATING TO THE TECHNOLOGY PROVIDED.   IT IS THE RECIPIENTS
OBLIGATION TO BACK-UP OR SAVE ANY STORED DATA.


****************************************************************************
**/



#include <stdio.h>


typedef unsigned char BYTE;

typedef unsigned short WORD;

typedef unsigned long DWORD;


/* functions' prototypes*/



int PHYread_reg (int port, int phyadd, int reg_offset);

int PHYwrite_reg (int port, int phyadd, int reg_offset, unsigned short
value);

void LED_FLASH ();

/* static functions*/

static void PHYgen_tristate (int base_port);

static void PHYwrite_mii (int base_port, DWORD mii_data, int size);

static int SERCOMread_reg (int port);

static void SERCOMwrite_reg (int port, DWORD value);



/*--------------------------------------------------------------------------
--

| MII management : |

| |

| The MII management interface consists of two pins : MDIO and MDC. |

| When reading or writing a bit from/to the PHY, its value should be |

| read or written to MDIO and MDC should be rotated (once high and once|

| low). |

| |

|---------------------------------------------------------------------------
--

| Accessing MII management through the dec21440: |

| |

| SER_COM register has 3 relevant bits: |

| |

| MDM : Mii Data Mode : setting this bit sets the MDIO pin to output mode, |

| resetting it sets the pin to input mode. |

| MDC : writing this bit sets the MDC pin |

| MDIO : writing this bit sets the MDIO pin, reading this bit reads the|

| value from the MDIO pin. | 

| |

----------------------------------------------------------------------------
*/

/*==========================================================================
======

= Accessing MII PHY registers :

=

= The management should write the following frame to the MII PHY :

=

= +----------------------------------------------------------------+

= | Management frame fields |

= +------+-------+----+----+-------+-------+----+------------------+-----+

= | | PRE | ST | OP | PHYAD | REGAD | TA | DATA |IDLE |

= +------+-------+----+----+-------+-------+----+------------------+-----+

= |Read | 1...1 | 01 | 10 | AAAAA | RRRRR | Z0 | DDDDDDDDDDDDDDDD | Z |

= +------+-------+----+----+-------+-------+----+------------------+-----+

= |Write | 1...1 | 01 | 01 | AAAAA | RRRRR | 10 | DDDDDDDDDDDDDDDD | Z |

= +------+-------+----+----+-------+-------+----+------------------+-----+

=

= PRE : preamble (32 bits of '1' on MDIO)

= ST : Start frame

= OP : operation mode (read or write)

= PHYADD : Phy address

= REGADD : Register's internal address

= TA : turnaround - in 'read' operation - tristate on the MII's IO pin, the
phy 

= should write '0' on the next MCLK cycle.

= in 'write' operation - write 10 on the IO pin.

= DATA : register's contents (16 bits) on MDIO 

=

============================================================================
====*/

#define MII_ACS_PREAMBLE 0xFFFFFFFF

#define MII_ACS_PREAMBLE_LEN 32

#define MII_ACS_READ_MASK 0x60000000

#define MII_ACS_WRITE_MASK 0x50020000 

#define MII_ACS_PHYADD_ALIGN 23

#define MII_ACS_REGADD_ALIGN 18

#define SER_COM (0x8 * 0x4) 

#define MDM 0x20

#define MDIO 0x10

#define MDC 0x8

#define MDIO_BIT_POSITION 4

#define PASS 0

#define FAIL 0xFFFF





/***************************************************************************
**

PHYread_reg

This function reads an MII PHY registers.

Input parameters:

int port - the IXF440 port number

int phyadd - the PHY address

int reg_offset - the PHY's register offset

Output parameters:

none

Return value:

Data from PHY if the reading succeded (the PHY responded), FAIL otherwise.

****************************************************************************
/

int PHYread_reg (int port, int phyadd, int reg_offset) {

int base_port, frame, value, retval, i;

BYTE ser_val, dbit;


/* write preamble*/

PHYwrite_mii (port, MII_ACS_PREAMBLE, MII_ACS_PREAMBLE_LEN);


/* prepare command word*/

frame = phyadd << MII_ACS_PHYADD_ALIGN; 

frame |= reg_offset << MII_ACS_REGADD_ALIGN;

frame |= MII_ACS_READ_MASK;

PHYwrite_mii (port, frame, 14);


/* tristate*/


PHYgen_tristate (port);


/* check that the PHY responded with zero bit*/

ser_val = SERCOMread_reg (port);

if ((ser_val & MDIO) != 0)

retval = FAIL;


/* read data from PHY*/



ser_val &= ~MDM & ~MDC ; /* change to input mode*/

for (i=0; i< 16; i++) { 


SERCOMwrite_reg (port, ser_val);


SERCOMwrite_reg (port, ser_val | MDC);


;

dbit = ((BYTE)(SERCOMread_reg (port)) & MDIO) >> MDIO_BIT_POSITION;

(value) = ((value) << 1) | dbit;

}

PHYgen_tristate (base_port);

return (value);

} 



/***************************************************************************
**

PHYwrite_reg

This function writes an MII PHY register.


Input parameters:

int port - the IXF440 port number

int phyadd - the PHY address

int reg_offset - the PHY's register offset

unsigned short value - the value to be written to the register.

Return value:

none.

****************************************************************************
/


int PHYwrite_reg (int port, int phyadd, int reg_offset, unsigned short
value) {

int base_port;

DWORD frame;


/* write preamble */

PHYwrite_mii (port, MII_ACS_PREAMBLE, MII_ACS_PREAMBLE_LEN);

/* prepare command word */

frame = phyadd << MII_ACS_PHYADD_ALIGN; 

frame |= reg_offset << MII_ACS_REGADD_ALIGN;

frame |= MII_ACS_WRITE_MASK;

PHYwrite_mii (port, frame, 16);


/* write data */

PHYwrite_mii (port, (DWORD)value << 16, 16);


PHYgen_tristate (port);

return(PASS);


} 


/***************************************************************************
**

PHYwrite_mii

This function writes a buffer of data to the MII phy.

Input parameters:

int base_port - the IXF440 port to which we should write SER_COM (port

0 of the chip on which our port is)

DWORD mii_data - the data buffer to write to the PHY. The data will

be written with MSB first.

int size - the size of data (in bits) we wish to write.

Return value:

none

****************************************************************************
/

static void PHYwrite_mii (int port, DWORD mii_data, int size) {

BYTE dbit, /* data bit */

ser_val;

int i,j;


ser_val = (BYTE)(SERCOMread_reg (port)) & (~MDC & ~MDIO & MDM); /* leave
only the bits not related

to PHY access*/


for (i=size; i>0; i--) {

dbit = (BYTE)(mii_data >> (31 - MDIO_BIT_POSITION)) & MDIO;

SERCOMwrite_reg (port, ser_val | MDM | dbit );

j++; /*slow the loop down*/

SERCOMwrite_reg (port, ser_val | dbit | MDM | MDC);

mii_data = mii_data << 1;

} 

} 



/***************************************************************************
**

PHYgen_tristate

This function generates tristate on the phy's MDIO pin.

Input parameters:

int base_port - the IXF440 port to which we should write SER_COM (port

0 of the chip on which our port is)

Return value:

PASS if the reading succeded (the PHY responded), FAIL otherwise.

****************************************************************************
/

#define MII_WRITE_TS 0

static void PHYgen_tristate (int port){



BYTE ser_val;




ser_val = (BYTE)(SERCOMread_reg (port)) & (~MDIO & ~MDC & ~MDM);


SERCOMwrite_reg (port, ser_val | MII_WRITE_TS);

SERCOMwrite_reg (port, ser_val | MII_WRITE_TS | MDC);

}


/***************************************************************************
**

SERCOMread_reg

This function reads data from the MAC ser_com port.

Input parameters:

int base_port - the IXF440 port to which we should read from SER_COM (port

0 of the chip on which our port is)

Return value:

data from PHY if the reading succeded (the PHY responded), FAIL otherwise.

****************************************************************************
/



static int SERCOMread_reg (int base_port)

{

int *p_SER_COM, value;

p_SER_COM=0x38400020;

value = *p_SER_COM;

return (value);


}

/***************************************************************************
**

SERCOMwrite_reg

This function writes data to the MAC ser_com port.

Input parameters:

int base_port - the IXF440 port to which we should read from SER_COM (port

0 of the chip on which our port is)

Return value:

none

****************************************************************************
/



static void SERCOMwrite_reg (int port, DWORD value)

{

int *p_SER_COM;

p_SER_COM=0x38400020;

*p_SER_COM = value;

}


void LED_FLASH ()

{

int *p_GMII_MNG_ACC;
int value;

/*turn off the gigabit MDIO,MDC as these lines are shared*/

p_GMII_MNG_ACC=0x038408128; 
*p_GMII_MNG_ACC=0x0;

/*flash the leds on port0 phy*/

PHYwrite_reg(0x0,0x0,0x14,0xBBB2);



}




More information about the ixp1200 mailing list