ethermii.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "etherif.h"
  16. #include "ethermii.h"
  17. int
  18. mii(Mii* mii, int mask)
  19. {
  20. MiiPhy *miiphy;
  21. int bit, phyno, r, rmask;
  22. /*
  23. * Probe through mii for PHYs in mask;
  24. * return the mask of those found in the current probe.
  25. * If the PHY has not already been probed, update
  26. * the Mii information.
  27. */
  28. rmask = 0;
  29. for(phyno = 0; phyno < NMiiPhy; phyno++){
  30. bit = 1<<phyno;
  31. if(!(mask & bit))
  32. continue;
  33. if(mii->mask & bit){
  34. rmask |= bit;
  35. continue;
  36. }
  37. if(mii->mir(mii, phyno, Bmsr) == -1)
  38. continue;
  39. if((miiphy = malloc(sizeof(MiiPhy))) == nil)
  40. continue;
  41. miiphy->mii = mii;
  42. r = mii->mir(mii, phyno, Phyidr1);
  43. miiphy->oui = (r & 0x3FFF)<<6;
  44. r = mii->mir(mii, phyno, Phyidr2);
  45. miiphy->oui |= r>>10;
  46. miiphy->phyno = phyno;
  47. miiphy->anar = ~0;
  48. miiphy->fc = ~0;
  49. miiphy->mscr = ~0;
  50. mii->phy[phyno] = miiphy;
  51. if(mii->curphy == nil)
  52. mii->curphy = miiphy;
  53. mii->mask |= bit;
  54. mii->nphy++;
  55. rmask |= bit;
  56. }
  57. return rmask;
  58. }
  59. int
  60. miimir(Mii* mii, int r)
  61. {
  62. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  63. return -1;
  64. return mii->mir(mii, mii->curphy->phyno, r);
  65. }
  66. int
  67. miimiw(Mii* mii, int r, int data)
  68. {
  69. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  70. return -1;
  71. return mii->miw(mii, mii->curphy->phyno, r, data);
  72. }
  73. int
  74. miireset(Mii* mii)
  75. {
  76. int bmcr;
  77. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  78. return -1;
  79. bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
  80. bmcr |= BmcrR;
  81. mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
  82. microdelay(1);
  83. return 0;
  84. }
  85. int
  86. miiane(Mii* mii, int a, int p, int e)
  87. {
  88. int anar, bmsr, mscr, r, phyno;
  89. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  90. return -1;
  91. phyno = mii->curphy->phyno;
  92. bmsr = mii->mir(mii, phyno, Bmsr);
  93. if(!(bmsr & BmsrAna))
  94. return -1;
  95. if(a != ~0)
  96. anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
  97. else if(mii->curphy->anar != ~0)
  98. anar = mii->curphy->anar;
  99. else{
  100. anar = mii->mir(mii, phyno, Anar);
  101. anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
  102. if(bmsr & Bmsr10THD)
  103. anar |= Ana10HD;
  104. if(bmsr & Bmsr10TFD)
  105. anar |= Ana10FD;
  106. if(bmsr & Bmsr100TXHD)
  107. anar |= AnaTXHD;
  108. if(bmsr & Bmsr100TXFD)
  109. anar |= AnaTXFD;
  110. }
  111. mii->curphy->anar = anar;
  112. if(p != ~0)
  113. anar |= (AnaAP|AnaP) & p;
  114. else if(mii->curphy->fc != ~0)
  115. anar |= mii->curphy->fc;
  116. mii->curphy->fc = (AnaAP|AnaP) & anar;
  117. if(bmsr & BmsrEs){
  118. mscr = mii->mir(mii, phyno, Mscr);
  119. mscr &= ~(Mscr1000TFD|Mscr1000THD);
  120. if(e != ~0)
  121. mscr |= (Mscr1000TFD|Mscr1000THD) & e;
  122. else if(mii->curphy->mscr != ~0)
  123. mscr = mii->curphy->mscr;
  124. else{
  125. r = mii->mir(mii, phyno, Esr);
  126. if(r & Esr1000THD)
  127. mscr |= Mscr1000THD;
  128. if(r & Esr1000TFD)
  129. mscr |= Mscr1000TFD;
  130. }
  131. mii->curphy->mscr = mscr;
  132. mii->miw(mii, phyno, Mscr, mscr);
  133. }
  134. mii->miw(mii, phyno, Anar, anar);
  135. r = mii->mir(mii, phyno, Bmcr);
  136. if(!(r & BmcrR)){
  137. r |= BmcrAne|BmcrRan;
  138. mii->miw(mii, phyno, Bmcr, r);
  139. }
  140. return 0;
  141. }
  142. int
  143. miistatus(Mii* mii)
  144. {
  145. MiiPhy *phy;
  146. int anlpar, bmsr, p, r, phyno;
  147. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  148. return -1;
  149. phy = mii->curphy;
  150. phyno = phy->phyno;
  151. /*
  152. * Check Auto-Negotiation is complete and link is up.
  153. * (Read status twice as the Ls bit is sticky).
  154. */
  155. bmsr = mii->mir(mii, phyno, Bmsr);
  156. if(!(bmsr & (BmsrAnc|BmsrAna)))
  157. return -1;
  158. bmsr = mii->mir(mii, phyno, Bmsr);
  159. if(!(bmsr & BmsrLs)){
  160. phy->link = 0;
  161. return -1;
  162. }
  163. phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
  164. if(phy->mscr){
  165. r = mii->mir(mii, phyno, Mssr);
  166. if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
  167. phy->speed = 1000;
  168. phy->fd = 1;
  169. }
  170. else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
  171. phy->speed = 1000;
  172. }
  173. anlpar = mii->mir(mii, phyno, Anlpar);
  174. if(phy->speed == 0){
  175. r = phy->anar & anlpar;
  176. if(r & AnaTXFD){
  177. phy->speed = 100;
  178. phy->fd = 1;
  179. }
  180. else if(r & AnaTXHD)
  181. phy->speed = 100;
  182. else if(r & Ana10FD){
  183. phy->speed = 10;
  184. phy->fd = 1;
  185. }
  186. else if(r & Ana10HD)
  187. phy->speed = 10;
  188. }
  189. if(phy->speed == 0)
  190. return -1;
  191. if(phy->fd){
  192. p = phy->fc;
  193. r = anlpar & (AnaAP|AnaP);
  194. if(p == AnaAP && r == (AnaAP|AnaP))
  195. phy->tfc = 1;
  196. else if(p == (AnaAP|AnaP) && r == AnaAP)
  197. phy->rfc = 1;
  198. else if((p & AnaP) && (r & AnaP))
  199. phy->rfc = phy->tfc = 1;
  200. }
  201. phy->link = 1;
  202. return 0;
  203. }