ethermii.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 "../port/netif.h"
  15. #include "ethermii.h"
  16. static int
  17. miiprobe(Mii* mii, int mask)
  18. {
  19. MiiPhy *miiphy;
  20. int bit, oui, phyno, r, rmask;
  21. /*
  22. * Probe through mii for PHYs in mask;
  23. * return the mask of those found in the current probe.
  24. * If the PHY has not already been probed, update
  25. * the Mii information.
  26. */
  27. rmask = 0;
  28. for(phyno = 0; phyno < NMiiPhy; phyno++){
  29. bit = 1<<phyno;
  30. if(!(mask & bit))
  31. continue;
  32. if(mii->mask & bit){
  33. rmask |= bit;
  34. continue;
  35. }
  36. if(mii->rw(mii, 0, phyno, Bmsr, 0) == -1)
  37. continue;
  38. r = mii->rw(mii, 0, phyno, Phyidr1, 0)<<16;
  39. r |= mii->rw(mii, 0, phyno, Phyidr2, 0);
  40. oui = (r>>10) & 0xffff;
  41. if(oui == 0xffff || oui == 0)
  42. continue;
  43. if((miiphy = malloc(sizeof(MiiPhy))) == nil)
  44. continue;
  45. miiphy->mii = mii;
  46. miiphy->phyno = phyno;
  47. miiphy->phyid = r;
  48. miiphy->oui = oui;
  49. miiphy->anar = ~0;
  50. miiphy->fc = ~0;
  51. miiphy->mscr = ~0;
  52. mii->phy[phyno] = miiphy;
  53. if(mii->curphy == nil)
  54. mii->curphy = miiphy;
  55. mii->mask |= bit;
  56. mii->nphy++;
  57. rmask |= bit;
  58. }
  59. return rmask;
  60. }
  61. int
  62. miimir(Mii* mii, int r)
  63. {
  64. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  65. return -1;
  66. return mii->rw(mii, 0, mii->curphy->phyno, r, 0);
  67. }
  68. int
  69. miimiw(Mii* mii, int r, int data)
  70. {
  71. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  72. return -1;
  73. return mii->rw(mii, 1, mii->curphy->phyno, r, data);
  74. }
  75. int
  76. miireset(Mii* mii)
  77. {
  78. int bmcr, timeo;
  79. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  80. return -1;
  81. bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
  82. mii->rw(mii, 1, mii->curphy->phyno, Bmcr, BmcrR|bmcr);
  83. for(timeo = 0; timeo < 1000; timeo++){
  84. bmcr = mii->rw(mii, 0, mii->curphy->phyno, Bmcr, 0);
  85. if(!(bmcr & BmcrR))
  86. break;
  87. microdelay(1);
  88. }
  89. if(bmcr & BmcrR)
  90. return -1;
  91. if(bmcr & BmcrI)
  92. mii->rw(mii, 1, mii->curphy->phyno, Bmcr, bmcr & ~BmcrI);
  93. return 0;
  94. }
  95. int
  96. miiane(Mii* mii, int a, int p, int e)
  97. {
  98. int anar, bmsr, mscr, r, phyno;
  99. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  100. return -1;
  101. phyno = mii->curphy->phyno;
  102. mii->rw(mii, 1, phyno, Bmsr, 0);
  103. bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
  104. if(!(bmsr & BmsrAna))
  105. return -1;
  106. if(a != ~0)
  107. anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
  108. else if(mii->curphy->anar != ~0)
  109. anar = mii->curphy->anar;
  110. else{
  111. anar = mii->rw(mii, 0, phyno, Anar, 0);
  112. anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
  113. if(bmsr & Bmsr10THD)
  114. anar |= Ana10HD;
  115. if(bmsr & Bmsr10TFD)
  116. anar |= Ana10FD;
  117. if(bmsr & Bmsr100TXHD)
  118. anar |= AnaTXHD;
  119. if(bmsr & Bmsr100TXFD)
  120. anar |= AnaTXFD;
  121. }
  122. mii->curphy->anar = anar;
  123. if(p != ~0)
  124. anar |= (AnaAP|AnaP) & p;
  125. else if(mii->curphy->fc != ~0)
  126. anar |= mii->curphy->fc;
  127. mii->curphy->fc = (AnaAP|AnaP) & anar;
  128. if(bmsr & BmsrEs){
  129. mscr = mii->rw(mii, 0, phyno, Mscr, 0);
  130. mscr &= ~(Mscr1000TFD|Mscr1000THD);
  131. if(e != ~0)
  132. mscr |= (Mscr1000TFD|Mscr1000THD) & e;
  133. else if(mii->curphy->mscr != ~0)
  134. mscr = mii->curphy->mscr;
  135. else{
  136. r = mii->rw(mii, 0, phyno, Esr, 0);
  137. if(r & Esr1000THD)
  138. mscr |= Mscr1000THD;
  139. if(r & Esr1000TFD)
  140. mscr |= Mscr1000TFD;
  141. }
  142. mii->curphy->mscr = mscr;
  143. mii->rw(mii, 1, phyno, Mscr, mscr);
  144. }
  145. else
  146. mii->curphy->mscr = 0;
  147. mii->rw(mii, 1, phyno, Anar, anar);
  148. r = mii->rw(mii, 0, phyno, Bmcr, 0);
  149. if(!(r & BmcrR)){
  150. r |= BmcrAne|BmcrRan;
  151. mii->rw(mii, 1, phyno, Bmcr, r);
  152. }
  153. return 0;
  154. }
  155. int
  156. miistatus(Mii* mii)
  157. {
  158. MiiPhy *phy;
  159. int anlpar, bmsr, p, r, phyno;
  160. if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
  161. return -1;
  162. phy = mii->curphy;
  163. phyno = phy->phyno;
  164. /*
  165. * Check Auto-Negotiation is complete and link is up.
  166. * (Read status twice as the Ls bit is sticky).
  167. */
  168. bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
  169. if(!(bmsr & (BmsrAnc|BmsrAna)))
  170. return -1;
  171. bmsr = mii->rw(mii, 0, phyno, Bmsr, 0);
  172. if(!(bmsr & BmsrLs)){
  173. phy->link = 0;
  174. return -1;
  175. }
  176. phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
  177. if(phy->mscr){
  178. r = mii->rw(mii, 0, phyno, Mssr, 0);
  179. if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
  180. phy->speed = 1000;
  181. phy->fd = 1;
  182. }
  183. else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
  184. phy->speed = 1000;
  185. }
  186. anlpar = mii->rw(mii, 0, phyno, Anlpar, 0);
  187. if(phy->speed == 0){
  188. r = phy->anar & anlpar;
  189. if(r & AnaTXFD){
  190. phy->speed = 100;
  191. phy->fd = 1;
  192. }
  193. else if(r & AnaTXHD)
  194. phy->speed = 100;
  195. else if(r & Ana10FD){
  196. phy->speed = 10;
  197. phy->fd = 1;
  198. }
  199. else if(r & Ana10HD)
  200. phy->speed = 10;
  201. }
  202. if(phy->speed == 0)
  203. return -1;
  204. if(phy->fd){
  205. p = phy->fc;
  206. r = anlpar & (AnaAP|AnaP);
  207. if(p == AnaAP && r == (AnaAP|AnaP))
  208. phy->tfc = 1;
  209. else if(p == (AnaAP|AnaP) && r == AnaAP)
  210. phy->rfc = 1;
  211. else if((p & AnaP) && (r & AnaP))
  212. phy->rfc = phy->tfc = 1;
  213. }
  214. phy->link = 1;
  215. return 0;
  216. }
  217. char*
  218. miidumpphy(Mii* mii, char* p, char* e)
  219. {
  220. int i, r;
  221. if(mii == nil || mii->curphy == nil)
  222. return p;
  223. p = seprint(p, e, "phy: ");
  224. for(i = 0; i < NMiiPhyr; i++){
  225. if(i && ((i & 0x07) == 0))
  226. p = seprint(p, e, "\n ");
  227. r = mii->rw(mii, 0, mii->curphy->phyno, i, 0);
  228. p = seprint(p, e, " %4.4ux", r);
  229. }
  230. p = seprint(p, e, "\n");
  231. return p;
  232. }
  233. void
  234. miidetach(Mii* mii)
  235. {
  236. int i;
  237. for(i = 0; i < NMiiPhy; i++){
  238. if(mii->phy[i] == nil)
  239. continue;
  240. free(mii);
  241. mii->phy[i] = nil;
  242. }
  243. free(mii);
  244. }
  245. Mii*
  246. miiattach(void* ctlr, int mask, int (*rw)(Mii*, int, int, int, int))
  247. {
  248. Mii* mii;
  249. if((mii = malloc(sizeof(Mii))) == nil)
  250. return nil;
  251. mii->ctlr = ctlr;
  252. mii->rw = rw;
  253. if(miiprobe(mii, mask) == 0){
  254. free(mii);
  255. mii = nil;
  256. }
  257. return mii;
  258. }