ethermii.c 4.4 KB

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