ethermii.c 5.0 KB

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