Ethernet Compliance Test를 위해 Ethernet PHY 에서 특정 신호를 출력할 수 있게 설정해 주어야 한다.

Ethernet PHY(Broadcom B50612E)의 datasheet를 참조한다. 




testmode.c

 /*

 * Test Mode 

 *

 * The BCM5461 can be placed in one of four transmit test mode by writing bits [15:13] of the 1000BASE-T control register.

 * The transmit test modes are defined in IEEE802.3ab. When read, these bits return the last value written. For test modes 1,

 * 2, and 4 the PHY must have auto-negotiation disabled, forced to 1000BASE-T mode and auto-MDIX disabled.

 *

 * Disable auto-neg and force to 1000BASE-T mode (write to register 00h = 0x0040)

 * Disable auto-MDIX (write to register 18h, shadow value 111, bit 9 = 0)

 * Enter test mode s (write to register 09h, bits[15:13] = the test mode you want)

 *

 */


#include <linux/mii.h>

#include <net/if.h>

#include <linux/sockios.h>

#include <sys/types.h>          

#include <sys/socket.h>

#include <sys/ioctl.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>


/* Ethernet dev */

#define NET_DEV "eth1"


/* PHY id */

#define PHY_ADDR   (0)


/* Register Map (Broadcom B50612E) */

#define PHY_MII_CTRL_REG (0x00) /* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register */

#define PHY_CTRL_REG (0x09) /* 1000BASE-T Control Register */

#define PHY_MISC_CTRL_REG (0x18) /* 1000BASE-T/100BASE-TX/10BASE-T Miscellaneous Control Register */


int main(int argc, char *argv[])

{

struct ifreq ifr; 

struct mii_ioctl_data *mii;

int nSockFD;

int mode;


if (argc < 2)

{

printf("* Usage : ./testmode [mode] \n");

printf("* mode : \n");

printf(" 0 - Normal operation\n");

printf(" 1 - Test mode 1 (Transmit waveform test) \n");

printf(" 2 - Test mode 2 (Master transmit jitter test) \n");

printf(" 3 - Test mode 3 (Slave transmit jitter test) \n");

printf(" 4 - Test mode 4 (Transmitter distortion test) \n");

return -1;

}


printf("\n==== 1000BASE-T Control Test ====\n\n");


nSockFD = socket(AF_INET, SOCK_DGRAM, 0);

if( nSockFD < 0) 

{    

printf("Failed to create socket (errno: %d)", errno);

return -1;

}   

memset(&ifr, 0, sizeof(ifr));

strcpy(ifr.ifr_name, NET_DEV);

mii             = (struct mii_ioctl_data *)&ifr.ifr_data;

mii->phy_id     = PHY_ADDR;


/*

* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register

*   Bits [6,13]: 10 = 1000 Mbps

*   Bits [12] : 0 = Auto-negotiation Disabled

*/


mii->reg_num = PHY_MII_CTRL_REG;

mii->val_in = 0x0040; 

printf("STEP 1. Disable auto-neg and force to 1000BASE-T mode. (Address : %02Xh) \n", mii->reg_num);

if (ioctl(nSockFD, SIOCSMIIREG, &ifr) < 0) 

{    

perror("Failed to write register value");

close (nSockFD);

return -1;

}



/*

* 1000BASE-T/100BASE-TX/10BASE-T Miscellaneous Control Register

*     Bits [9] : 0 = Auto-MDIX is disabled when autonegotiation is disabled

*/


mii->reg_num   = PHY_MISC_CTRL_REG;

mii->val_in = 0x01E7;


printf("STEP 2. Disable auto-MDIX (Address : %02Xh) \n", mii->reg_num);

if (ioctl(nSockFD, SIOCSMIIREG, &ifr) < 0) 

{    

perror("Failed to write register value");

close (nSockFD);

return -1;

}


/*

* 1000BASE-T Control

*     Bits[15:13] : 1 X X = Test mode 4—Transmitter distortion test

* 0 1 1 = Test mode 3—Slave transmit jitter test

* 0 1 0 = Test mode 2—Master transmit jitter test

* 0 0 1 = Test mode 1—Transmit waveform test

* 0 0 0 = Normal operation

*/


mii->reg_num   = PHY_CTRL_REG;

mode = atoi(argv[1]);

printf("STEP 3. Enter test mode (Address : %02Xh) (Test Mode : %d)\n", mii->reg_num, mode);

switch (mode)

{

case 0 :

mii->val_in = 0x0200; /* Normal operation */

break;

case 1 :

mii->val_in = 0x2200; /* Test Mode 1 */

break;

case 2 :

mii->val_in = 0x5A00; /* Test Mode 2 */

break;

case 3 :

mii->val_in = 0x7A00; /* Test Mode 3 */

break;

case 4 :

mii->val_in = 0x8200; /* Test Mode 4 */

break;

default : 

printf("Invalid mode (mode : %d)!!", mode);

close (nSockFD);

return -1;

break;

}


if (ioctl(nSockFD, SIOCSMIIREG, &ifr) < 0) 

{    

perror("Failed to write register value");

close (nSockFD);

return -1;

}


mii->reg_num   = PHY_CTRL_REG;

if (ioctl(nSockFD, SIOCGMIIREG, &ifr) < 0) 

{    

perror("Failed to get register value");

close (nSockFD);

return -1;

}   

printf("1000BASE-T Control Register(Address : %02XH), (Value : %04XH)\n",mii->reg_num, mii->val_out);



close (nSockFD);



return 0;

}


Makefile

CC = mipsel-linux-gcc

INC =

LIBS = 

CFLAGS = -g -Wall

OBJS = testmode.o

SRCS = testmode.c

TARGET = testmode 

all : $(TARGET)


$(TARGET) : $(OBJS)

$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)

clean :

rm -rf $(OBJS) $(TARGET)



참 고 : 

Tektronix TDSET3 Ethernet Compliance Test Software

TDSET3.pdf






Posted by eoseontaek