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