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