linux/include/linux/mii.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * linux/mii.h: definitions for MII-compatible transceivers
   4 * Originally drivers/net/sunhme.h.
   5 *
   6 * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
   7 */
   8#ifndef __LINUX_MII_H__
   9#define __LINUX_MII_H__
  10
  11
  12#include <linux/if.h>
  13#include <uapi/linux/mii.h>
  14
  15struct ethtool_cmd;
  16
  17struct mii_if_info {
  18        int phy_id;
  19        int advertising;
  20        int phy_id_mask;
  21        int reg_num_mask;
  22
  23        unsigned int full_duplex : 1;   /* is full duplex? */
  24        unsigned int force_media : 1;   /* is autoneg. disabled? */
  25        unsigned int supports_gmii : 1; /* are GMII registers supported? */
  26
  27        struct net_device *dev;
  28        int (*mdio_read) (struct net_device *dev, int phy_id, int location);
  29        void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
  30};
  31
  32extern int mii_link_ok (struct mii_if_info *mii);
  33extern int mii_nway_restart (struct mii_if_info *mii);
  34extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
  35extern void mii_ethtool_get_link_ksettings(
  36        struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
  37extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
  38extern int mii_ethtool_set_link_ksettings(
  39        struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
  40extern int mii_check_gmii_support(struct mii_if_info *mii);
  41extern void mii_check_link (struct mii_if_info *mii);
  42extern unsigned int mii_check_media (struct mii_if_info *mii,
  43                                     unsigned int ok_to_print,
  44                                     unsigned int init_media);
  45extern int generic_mii_ioctl(struct mii_if_info *mii_if,
  46                             struct mii_ioctl_data *mii_data, int cmd,
  47                             unsigned int *duplex_changed);
  48
  49
  50static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
  51{
  52        return (struct mii_ioctl_data *) &rq->ifr_ifru;
  53}
  54
  55/**
  56 * mii_nway_result
  57 * @negotiated: value of MII ANAR and'd with ANLPAR
  58 *
  59 * Given a set of MII abilities, check each bit and returns the
  60 * currently supported media, in the priority order defined by
  61 * IEEE 802.3u.  We use LPA_xxx constants but note this is not the
  62 * value of LPA solely, as described above.
  63 *
  64 * The one exception to IEEE 802.3u is that 100baseT4 is placed
  65 * between 100T-full and 100T-half.  If your phy does not support
  66 * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
  67 * priority order, you will need to roll your own function.
  68 */
  69static inline unsigned int mii_nway_result (unsigned int negotiated)
  70{
  71        unsigned int ret;
  72
  73        if (negotiated & LPA_100FULL)
  74                ret = LPA_100FULL;
  75        else if (negotiated & LPA_100BASE4)
  76                ret = LPA_100BASE4;
  77        else if (negotiated & LPA_100HALF)
  78                ret = LPA_100HALF;
  79        else if (negotiated & LPA_10FULL)
  80                ret = LPA_10FULL;
  81        else
  82                ret = LPA_10HALF;
  83
  84        return ret;
  85}
  86
  87/**
  88 * mii_duplex
  89 * @duplex_lock: Non-zero if duplex is locked at full
  90 * @negotiated: value of MII ANAR and'd with ANLPAR
  91 *
  92 * A small helper function for a common case.  Returns one
  93 * if the media is operating or locked at full duplex, and
  94 * returns zero otherwise.
  95 */
  96static inline unsigned int mii_duplex (unsigned int duplex_lock,
  97                                       unsigned int negotiated)
  98{
  99        if (duplex_lock)
 100                return 1;
 101        if (mii_nway_result(negotiated) & LPA_DUPLEX)
 102                return 1;
 103        return 0;
 104}
 105
 106/**
 107 * ethtool_adv_to_mii_adv_t
 108 * @ethadv: the ethtool advertisement settings
 109 *
 110 * A small helper function that translates ethtool advertisement
 111 * settings to phy autonegotiation advertisements for the
 112 * MII_ADVERTISE register.
 113 */
 114static inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
 115{
 116        u32 result = 0;
 117
 118        if (ethadv & ADVERTISED_10baseT_Half)
 119                result |= ADVERTISE_10HALF;
 120        if (ethadv & ADVERTISED_10baseT_Full)
 121                result |= ADVERTISE_10FULL;
 122        if (ethadv & ADVERTISED_100baseT_Half)
 123                result |= ADVERTISE_100HALF;
 124        if (ethadv & ADVERTISED_100baseT_Full)
 125                result |= ADVERTISE_100FULL;
 126        if (ethadv & ADVERTISED_Pause)
 127                result |= ADVERTISE_PAUSE_CAP;
 128        if (ethadv & ADVERTISED_Asym_Pause)
 129                result |= ADVERTISE_PAUSE_ASYM;
 130
 131        return result;
 132}
 133
 134/**
 135 * mii_adv_to_ethtool_adv_t
 136 * @adv: value of the MII_ADVERTISE register
 137 *
 138 * A small helper function that translates MII_ADVERTISE bits
 139 * to ethtool advertisement settings.
 140 */
 141static inline u32 mii_adv_to_ethtool_adv_t(u32 adv)
 142{
 143        u32 result = 0;
 144
 145        if (adv & ADVERTISE_10HALF)
 146                result |= ADVERTISED_10baseT_Half;
 147        if (adv & ADVERTISE_10FULL)
 148                result |= ADVERTISED_10baseT_Full;
 149        if (adv & ADVERTISE_100HALF)
 150                result |= ADVERTISED_100baseT_Half;
 151        if (adv & ADVERTISE_100FULL)
 152                result |= ADVERTISED_100baseT_Full;
 153        if (adv & ADVERTISE_PAUSE_CAP)
 154                result |= ADVERTISED_Pause;
 155        if (adv & ADVERTISE_PAUSE_ASYM)
 156                result |= ADVERTISED_Asym_Pause;
 157
 158        return result;
 159}
 160
 161/**
 162 * ethtool_adv_to_mii_ctrl1000_t
 163 * @ethadv: the ethtool advertisement settings
 164 *
 165 * A small helper function that translates ethtool advertisement
 166 * settings to phy autonegotiation advertisements for the
 167 * MII_CTRL1000 register when in 1000T mode.
 168 */
 169static inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
 170{
 171        u32 result = 0;
 172
 173        if (ethadv & ADVERTISED_1000baseT_Half)
 174                result |= ADVERTISE_1000HALF;
 175        if (ethadv & ADVERTISED_1000baseT_Full)
 176                result |= ADVERTISE_1000FULL;
 177
 178        return result;
 179}
 180
 181/**
 182 * mii_ctrl1000_to_ethtool_adv_t
 183 * @adv: value of the MII_CTRL1000 register
 184 *
 185 * A small helper function that translates MII_CTRL1000
 186 * bits, when in 1000Base-T mode, to ethtool
 187 * advertisement settings.
 188 */
 189static inline u32 mii_ctrl1000_to_ethtool_adv_t(u32 adv)
 190{
 191        u32 result = 0;
 192
 193        if (adv & ADVERTISE_1000HALF)
 194                result |= ADVERTISED_1000baseT_Half;
 195        if (adv & ADVERTISE_1000FULL)
 196                result |= ADVERTISED_1000baseT_Full;
 197
 198        return result;
 199}
 200
 201/**
 202 * mii_lpa_to_ethtool_lpa_t
 203 * @adv: value of the MII_LPA register
 204 *
 205 * A small helper function that translates MII_LPA
 206 * bits, when in 1000Base-T mode, to ethtool
 207 * LP advertisement settings.
 208 */
 209static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa)
 210{
 211        u32 result = 0;
 212
 213        if (lpa & LPA_LPACK)
 214                result |= ADVERTISED_Autoneg;
 215
 216        return result | mii_adv_to_ethtool_adv_t(lpa);
 217}
 218
 219/**
 220 * mii_stat1000_to_ethtool_lpa_t
 221 * @adv: value of the MII_STAT1000 register
 222 *
 223 * A small helper function that translates MII_STAT1000
 224 * bits, when in 1000Base-T mode, to ethtool
 225 * advertisement settings.
 226 */
 227static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
 228{
 229        u32 result = 0;
 230
 231        if (lpa & LPA_1000HALF)
 232                result |= ADVERTISED_1000baseT_Half;
 233        if (lpa & LPA_1000FULL)
 234                result |= ADVERTISED_1000baseT_Full;
 235
 236        return result;
 237}
 238
 239/**
 240 * ethtool_adv_to_mii_adv_x
 241 * @ethadv: the ethtool advertisement settings
 242 *
 243 * A small helper function that translates ethtool advertisement
 244 * settings to phy autonegotiation advertisements for the
 245 * MII_CTRL1000 register when in 1000Base-X mode.
 246 */
 247static inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
 248{
 249        u32 result = 0;
 250
 251        if (ethadv & ADVERTISED_1000baseT_Half)
 252                result |= ADVERTISE_1000XHALF;
 253        if (ethadv & ADVERTISED_1000baseT_Full)
 254                result |= ADVERTISE_1000XFULL;
 255        if (ethadv & ADVERTISED_Pause)
 256                result |= ADVERTISE_1000XPAUSE;
 257        if (ethadv & ADVERTISED_Asym_Pause)
 258                result |= ADVERTISE_1000XPSE_ASYM;
 259
 260        return result;
 261}
 262
 263/**
 264 * mii_adv_to_ethtool_adv_x
 265 * @adv: value of the MII_CTRL1000 register
 266 *
 267 * A small helper function that translates MII_CTRL1000
 268 * bits, when in 1000Base-X mode, to ethtool
 269 * advertisement settings.
 270 */
 271static inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
 272{
 273        u32 result = 0;
 274
 275        if (adv & ADVERTISE_1000XHALF)
 276                result |= ADVERTISED_1000baseT_Half;
 277        if (adv & ADVERTISE_1000XFULL)
 278                result |= ADVERTISED_1000baseT_Full;
 279        if (adv & ADVERTISE_1000XPAUSE)
 280                result |= ADVERTISED_Pause;
 281        if (adv & ADVERTISE_1000XPSE_ASYM)
 282                result |= ADVERTISED_Asym_Pause;
 283
 284        return result;
 285}
 286
 287/**
 288 * mii_lpa_to_ethtool_lpa_x
 289 * @adv: value of the MII_LPA register
 290 *
 291 * A small helper function that translates MII_LPA
 292 * bits, when in 1000Base-X mode, to ethtool
 293 * LP advertisement settings.
 294 */
 295static inline u32 mii_lpa_to_ethtool_lpa_x(u32 lpa)
 296{
 297        u32 result = 0;
 298
 299        if (lpa & LPA_LPACK)
 300                result |= ADVERTISED_Autoneg;
 301
 302        return result | mii_adv_to_ethtool_adv_x(lpa);
 303}
 304
 305/**
 306 * mii_advertise_flowctrl - get flow control advertisement flags
 307 * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
 308 */
 309static inline u16 mii_advertise_flowctrl(int cap)
 310{
 311        u16 adv = 0;
 312
 313        if (cap & FLOW_CTRL_RX)
 314                adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 315        if (cap & FLOW_CTRL_TX)
 316                adv ^= ADVERTISE_PAUSE_ASYM;
 317
 318        return adv;
 319}
 320
 321/**
 322 * mii_resolve_flowctrl_fdx
 323 * @lcladv: value of MII ADVERTISE register
 324 * @rmtadv: value of MII LPA register
 325 *
 326 * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
 327 */
 328static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
 329{
 330        u8 cap = 0;
 331
 332        if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
 333                cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
 334        } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
 335                if (lcladv & ADVERTISE_PAUSE_CAP)
 336                        cap = FLOW_CTRL_RX;
 337                else if (rmtadv & ADVERTISE_PAUSE_CAP)
 338                        cap = FLOW_CTRL_TX;
 339        }
 340
 341        return cap;
 342}
 343
 344#endif /* __LINUX_MII_H__ */
 345