diff --git a/Makefile b/Makefile index 66d0bbb4900c8ef3c32040b39ead18774c1b5512..545074d39e0a3e6c7b9d60bd9a8d83f7c730bb02 100644 --- a/Makefile +++ b/Makefile @@ -20,11 +20,12 @@ CFLAGS += -Itest_stub LIBETH_CFLAGS += $(DIAG_CFLAGS) -Werror objs_lib += econet/econet.o econet/ecnt_prvt.o LIBS += -lapi_lib_switchmgr +else ifeq ($(PLATFORM),IPQ95XX) +objs_lib += ipq95xx/ipq95xx.o else ifeq ($(PLATFORM),TEST) CFLAGS += -DIOPSYS_TEST -I/usr/include/libnl3 LIBETH_CFLAGS += $(DIAG_CFLAGS) -Werror objs_lib += test_stub/stub.o - endif all: libethernet.so diff --git a/ethernet.c b/ethernet.c index 451aa92db3edc426f4ff1b73be25f6a7697a7397..8a0b199b3eeee1493a6f53c5e721ddd10e711e58 100644 --- a/ethernet.c +++ b/ethernet.c @@ -46,6 +46,8 @@ extern const struct eth_ops test_eth_ops; extern const struct eth_ops econet_gen_eth_ops; extern const struct eth_ops econet_nas_wan_eth_ops; extern const struct eth_ops econet_ae_wan_eth_ops; +#elif defined(IPQ95XX) +extern const struct eth_ops ipq95xx_eth_ops; #else extern const struct eth_ops ethsw_ops; #endif @@ -59,6 +61,8 @@ const struct eth_ops *eth_ops[] = { &econet_gen_eth_ops, &econet_nas_wan_eth_ops, &econet_ae_wan_eth_ops, +#elif defined(IPQ95XX) + &ipq95xx_eth_ops, #else ðsw_ops, /* FIXME */ #endif diff --git a/ipq95xx/ipq95xx.c b/ipq95xx/ipq95xx.c new file mode 100644 index 0000000000000000000000000000000000000000..af71fd88c7ff841d4daea18f75ee1eb424100f3d --- /dev/null +++ b/ipq95xx/ipq95xx.c @@ -0,0 +1,139 @@ +/* + * ipq95xx.c + */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdint.h> +#include <errno.h> +#include <ctype.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <time.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/sockios.h> +#include "easy.h" +#include "if_utils.h" +#include "../ethernet.h" + +#include "ipq95xx.h" + +int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link) +{ + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * 32 * 127]; + } ecmd; + + memset(&ecmd, 0, sizeof(struct ethtool_link_settings)); + + if (ipq95xx_eth_get_link_settings(ifname, &link)) + return -1; + + ecmd.req.cmd = ETHTOOL_SLINKSETTINGS; + + ecmd.req.port = link.portid; + ecmd.req.speed = link.speed; + ecmd.req.autoneg = (link.autoneg == 0 ? false : true); + ecmd.req.duplex = (link.fullduplex == 1 ? false : true); + + if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings))) + return -1; + return 0; +} + +int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link) +{ + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * 32 * 127]; + } ecmd; + + memset(&ecmd, 0, sizeof(struct ethtool_link_settings)); + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings))) + return -1; + + if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + return -1; + + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings))) + return -1; + + if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + return -1; + + link->portid = ecmd.req.port; + link->speed = ecmd.req.speed; + link->autoneg = ecmd.req.autoneg == 0 ? false : true; + link->fullduplex = ecmd.req.duplex == 1 ? false : true; + + return 0; +} + +int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p) +{ + libethernet_err("%s(): TODO\n", __func__); + return 0; +} + +int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p) +{ + libethernet_err("%s(): TODO\n", __func__); + return 0; +} + +int ipq95xx_eth_reset_phy(const char *ifname, int phy_id) +{ + return eth_mii_reset_phy(ifname, phy_id); +} + +int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s) +{ + struct if_stats ifstats; + + memset(&ifstats, 0, sizeof(struct if_stats)); + + if (if_getstats(ifname, &ifstats) < 0) + return -1; + + s->rx_packets = ifstats.rx_packets; + s->tx_packets = ifstats.tx_packets; + s->rx_bytes = ifstats.rx_bytes; + s->tx_bytes = ifstats.tx_bytes; + s->rx_errors = ifstats.rx_errors; + s->tx_errors = ifstats.tx_errors; + s->rx_discard_packets = ifstats.rx_dropped; + s->tx_discard_packets = ifstats.tx_dropped; + + return 0; +} + +int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon) +{ + libethernet_err("%s(): TODO\n", __func__); + return 0; +} + +const struct eth_ops ipq95xx_eth_ops = { + .ifname = "eth", + .set_link_settings = ipq95xx_eth_set_link_settings, + .get_link_settings = ipq95xx_eth_get_link_settings, + .get_stats = ipq95xx_eth_get_stats, + .get_rmon_stats = ipq95xx_eth_get_rmon_stats, + .poweron_phy = ipq95xx_eth_poweron_phy, + .poweroff_phy = ipq95xx_eth_poweroff_phy, + .reset_phy = ipq95xx_eth_reset_phy, +}; diff --git a/ipq95xx/ipq95xx.h b/ipq95xx/ipq95xx.h new file mode 100644 index 0000000000000000000000000000000000000000..6017ae2e22c8d4825f458f9fcf3ed3662781b59b --- /dev/null +++ b/ipq95xx/ipq95xx.h @@ -0,0 +1,20 @@ +#ifndef IPQ95XX +#define IPQ95XX + +#ifdef __cplusplus +extern "C" { +#endif + +int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link); +int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link); +int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p); +int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p); +int ipq95xx_eth_reset_phy(const char *ifname, int phy_id); +int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s); +int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon); + +#ifdef __cplusplus +} +#endif + +#endif /* IPQ95XX */