ethermii.c 4.8 KB

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