ethermii.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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, oui, 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. r = mii->mir(mii, phyno, Phyidr1);
  34. oui = (r & 0x3FFF)<<6;
  35. r = mii->mir(mii, phyno, Phyidr2);
  36. oui |= r>>10;
  37. if(oui == 0xFFFFF || oui == 0)
  38. continue;
  39. if((miiphy = malloc(sizeof(MiiPhy))) == nil)
  40. continue;
  41. miiphy->mii = mii;
  42. miiphy->oui = oui;
  43. miiphy->phyno = phyno;
  44. miiphy->anar = ~0;
  45. miiphy->fc = ~0;
  46. miiphy->mscr = ~0;
  47. mii->phy[phyno] = miiphy;
  48. if(mii->curphy == nil)
  49. mii->curphy = miiphy;
  50. mii->mask |= bit;
  51. mii->nphy++;
  52. rmask |= bit;
  53. }
  54. return rmask;
  55. }
  56. int
  57. miimir(Mii* mii, int r)
  58. {
  59. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  60. return -1;
  61. return mii->mir(mii, mii->curphy->phyno, r);
  62. }
  63. int
  64. miimiw(Mii* mii, int r, int data)
  65. {
  66. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  67. return -1;
  68. return mii->miw(mii, mii->curphy->phyno, r, data);
  69. }
  70. int
  71. miireset(Mii* mii)
  72. {
  73. int bmcr;
  74. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  75. return -1;
  76. bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
  77. bmcr |= BmcrR;
  78. mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
  79. microdelay(1);
  80. return 0;
  81. }
  82. int
  83. miiane(Mii* mii, int a, int p, int e)
  84. {
  85. int anar, bmsr, mscr, r, phyno;
  86. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  87. return -1;
  88. phyno = mii->curphy->phyno;
  89. bmsr = mii->mir(mii, phyno, Bmsr);
  90. if(!(bmsr & BmsrAna))
  91. return -1;
  92. if(a != ~0)
  93. anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
  94. else if(mii->curphy->anar != ~0)
  95. anar = mii->curphy->anar;
  96. else{
  97. anar = mii->mir(mii, phyno, Anar);
  98. anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
  99. if(bmsr & Bmsr10THD)
  100. anar |= Ana10HD;
  101. if(bmsr & Bmsr10TFD)
  102. anar |= Ana10FD;
  103. if(bmsr & Bmsr100TXHD)
  104. anar |= AnaTXHD;
  105. if(bmsr & Bmsr100TXFD)
  106. anar |= AnaTXFD;
  107. }
  108. mii->curphy->anar = anar;
  109. if(p != ~0)
  110. anar |= (AnaAP|AnaP) & p;
  111. else if(mii->curphy->fc != ~0)
  112. anar |= mii->curphy->fc;
  113. mii->curphy->fc = (AnaAP|AnaP) & anar;
  114. if(bmsr & BmsrEs){
  115. mscr = mii->mir(mii, phyno, Mscr);
  116. mscr &= ~(Mscr1000TFD|Mscr1000THD);
  117. if(e != ~0)
  118. mscr |= (Mscr1000TFD|Mscr1000THD) & e;
  119. else if(mii->curphy->mscr != ~0)
  120. mscr = mii->curphy->mscr;
  121. else{
  122. r = mii->mir(mii, phyno, Esr);
  123. if(r & Esr1000THD)
  124. mscr |= Mscr1000THD;
  125. if(r & Esr1000TFD)
  126. mscr |= Mscr1000TFD;
  127. }
  128. mii->curphy->mscr = mscr;
  129. mii->miw(mii, phyno, Mscr, mscr);
  130. }
  131. mii->miw(mii, phyno, Anar, anar);
  132. r = mii->mir(mii, phyno, Bmcr);
  133. if(!(r & BmcrR)){
  134. r |= BmcrAne|BmcrRan;
  135. mii->miw(mii, phyno, Bmcr, r);
  136. }
  137. return 0;
  138. }
  139. int
  140. miistatus(Mii* mii)
  141. {
  142. MiiPhy *phy;
  143. int anlpar, bmsr, p, r, phyno;
  144. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  145. return -1;
  146. phy = mii->curphy;
  147. phyno = phy->phyno;
  148. /*
  149. * Check Auto-Negotiation is complete and link is up.
  150. * (Read status twice as the Ls bit is sticky).
  151. */
  152. bmsr = mii->mir(mii, phyno, Bmsr);
  153. if(!(bmsr & (BmsrAnc|BmsrAna))) {
  154. // print("miistatus: auto-neg incomplete\n");
  155. return -1;
  156. }
  157. bmsr = mii->mir(mii, phyno, Bmsr);
  158. if(!(bmsr & BmsrLs)){
  159. // print("miistatus: link down\n");
  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. // print("miistatus: phy speed 0\n");
  191. return -1;
  192. }
  193. if(phy->fd){
  194. p = phy->fc;
  195. r = anlpar & (AnaAP|AnaP);
  196. if(p == AnaAP && r == (AnaAP|AnaP))
  197. phy->tfc = 1;
  198. else if(p == (AnaAP|AnaP) && r == AnaAP)
  199. phy->rfc = 1;
  200. else if((p & AnaP) && (r & AnaP))
  201. phy->rfc = phy->tfc = 1;
  202. }
  203. phy->link = 1;
  204. return 0;
  205. }