mii.h 8.5 KB

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