mdio-tool.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/sockios.h>
#ifndef __GLIBC__
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#endif
#include "mii.h"
#define MDIO_TOOL_VERSION "v1.0"
#define PHY_SLECT_PAGE 31
#define PHY_BASE_PAGE 0
//you can find kernel/driver/net/phy/phy.c : phy_mii_ioctl
#define MII_ADDR_C45 (1 << 30)
#define PHY_IS_C45 0x8000
#define PHY_C45_MASK 0x03e0
static struct ifreq ifr;
static int skfd = -1;
static int mdio_read(int location)
{
struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
mii->reg_num = location;
if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) {
fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
strerror(errno));
return -1;
}
return mii->val_out;
}
static int mdio_write(int location, int value)
{
struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
mii->reg_num = location;
mii->val_in = value;
if (ioctl(skfd, SIOCSMIIREG, &ifr) < 0) {
fprintf(stderr, "SIOCSMIIREG on %s failed: %s\n", ifr.ifr_name,
strerror(errno));
return -1;
}
return 0;
}
static int mdio_mmd_read(int devad, int reg)
{
mdio_write(13, (devad | 0x0000));
mdio_write(14, reg);
mdio_write(13, (devad | 0x4000));
return mdio_read(14);
}
static int mdio_mmd_write(int devad, int reg, int val)
{
mdio_write(13, (devad | 0x0000));
mdio_write(14, reg);
mdio_write(13, (devad | 0x4000));
return mdio_write(14, val);
}
static int mdio_c45_read(int devad, int reg)
{
struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
// mii->reg_num = (MII_ADDR_C45 | (devad << 16) | (reg & 0xffff));
mii->reg_num = reg;
if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) {
fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
strerror(errno));
return -1;
}
return mii->val_out;
}
static int mdio_c45_write(int devad, int reg, int val)
{
struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
// mii->reg_num = (MII_ADDR_C45 | (devad << 16) | (reg & 0xffff));
mii->reg_num = reg;
mii->val_in = val;
if (ioctl(skfd, SIOCSMIIREG, &ifr) < 0) {
fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
strerror(errno));
return -1;
}
return 0;
}
static void help(void *op)
{
if (((char *)op)[0] == 'w') {
printf("Usage: mdio-tool [w] [dev] [reg] [val]\n");
printf("or\n");
printf("Usage: mdio-tool [w] [dev] [page] [reg] [val]\n");
printf("or\n");
printf("Usage: mdio-tool [w] [dev] [phyaddr] [page] [reg] [val]\n");
} else if (((char*)op)[0] == 'r') {
printf("Usage: mdio-tool [r] [dev] [reg]\n");
printf("or\n");
printf("Usage: mdio-tool [r] [dev] [page] [reg]\n");
printf("or\n");
printf("Usage: mdio-tool [r] [dev] [phyaddr] [page] [reg]\n");
}else if (((char*)op)[0] == 'm'){
if (((char*)op)[1] == 'w') {
printf("Usage: mdio-tool [mw] [dev] [devad] [reg] [val]\n");
printf("or\n");
printf("Usage: mdio-tool [mw] [dev] [phyaddr] [devad] [reg] [val]\n");
} else if (((char*)op)[1] == 'r'){
printf("Usage: mdio-tool [mr] [dev] [devad] [reg]\n");
printf("or\n");
printf("Usage: mdio-tool [mr] [dev] [phyaddr] [devad] [reg]\n");
}
}else if (((char*)op)[0] == 'd'){
if (((char*)op)[1] == 'w') {
printf("Usage: mdio-tool [dw] [dev] [devad] [reg] [val]\n");
printf("or\n");
printf("Usage: mdio-tool [dw] [dev] [phyaddr] [devad] [reg] [val]\n");
} else if (((char*)op)[1] == 'r'){
printf("Usage: mdio-tool [dr] [dev] [devad] [reg]\n");
printf("or\n");
printf("Usage: mdio-tool [dr] [dev] [phyaddr] [devad] [reg]\n");
}
} else {
printf("==========================