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 "../ppc/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 93 return 0; 94 } 95 96 int 97 miiane(Mii* mii, int a, int p, int e) 98 { 99 int anar, bmsr, mscr, r, phyno; 100 101 if(mii == nil || mii->ctlr == nil || mii->curphy == nil) 102 return -1; 103 phyno = mii->curphy->phyno; 104 105 bmsr = mii->mir(mii, phyno, Bmsr); 106 if(!(bmsr & BmsrAna)) 107 return -1; 108 109 anar = mii->mir(mii, phyno, Anar); 110 anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD); 111 112 if(a != ~0) 113 anar |= (AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a; 114 else if(mii->curphy->anar != ~0) 115 anar = mii->curphy->anar; 116 else{ 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 mii->miw(mii, phyno, Anar, anar); 135 136 mscr = 0; 137 if(bmsr & BmsrEs){ 138 mscr = mii->mir(mii, phyno, Mscr); 139 mscr &= ~(Mscr1000TFD|Mscr1000THD); 140 if(e != ~0) 141 mscr |= (Mscr1000TFD|Mscr1000THD) & e; 142 else if(mii->curphy->mscr != ~0) 143 mscr = mii->curphy->mscr; 144 else{ 145 r = mii->mir(mii, phyno, Esr); 146 if(r & Esr1000THD) 147 mscr |= Mscr1000THD; 148 if(r & Esr1000TFD) 149 mscr |= Mscr1000TFD; 150 } 151 mii->miw(mii, phyno, Mscr, mscr); 152 } 153 mii->curphy->mscr = mscr; 154 155 r = mii->mir(mii, phyno, Bmcr); 156 if(!(r & BmcrR)){ 157 r |= BmcrAne|BmcrRan; 158 mii->miw(mii, phyno, Bmcr, r); 159 } 160 161 return 0; 162 } 163 164 int 165 miistatus(Mii* mii) 166 { 167 MiiPhy *phy; 168 int anlpar, bmsr, p, r, phyno; 169 170 if(mii == nil || mii->ctlr == nil || mii->curphy == nil) 171 return -1; 172 phy = mii->curphy; 173 phyno = phy->phyno; 174 175 /* 176 * Check Auto-Negotiation is complete and link is up. 177 * (Read status twice as the Ls bit is sticky). 178 */ 179 phy->bmsr = bmsr = mii->mir(mii, phyno, Bmsr); 180 if(!(bmsr & (BmsrAnc|BmsrAna))) 181 return -1; 182 183 phy->bmsr = bmsr = mii->mir(mii, phyno, Bmsr); 184 if(!(bmsr & BmsrLs)){ 185 phy->link = 0; 186 return 0; 187 } 188 189 phy->speed = phy->fd = phy->rfc = phy->tfc = 0; 190 if(phy->mscr & (Mscr1000TFD|Mscr1000THD)){ 191 r = mii->mir(mii, phyno, Mssr); 192 if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){ 193 phy->speed = 1000; 194 phy->fd = 1; 195 } 196 else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD)) 197 phy->speed = 1000; 198 } 199 200 anlpar = mii->mir(mii, phyno, Anlpar); 201 if(phy->speed == 0){ 202 r = phy->anar & anlpar; 203 if(r & AnaTXFD){ 204 phy->speed = 100; 205 phy->fd = 1; 206 } 207 else if(r & AnaTXHD) 208 phy->speed = 100; 209 else if(r & Ana10FD){ 210 phy->speed = 10; 211 phy->fd = 1; 212 } 213 else if(r & Ana10HD) 214 phy->speed = 10; 215 } 216 if(phy->speed == 0) 217 return -1; 218 219 if(phy->fd){ 220 p = phy->fc; 221 r = anlpar & (AnaAP|AnaP); 222 if(p == AnaAP && r == (AnaAP|AnaP)) 223 phy->tfc = 1; 224 else if(p == (AnaAP|AnaP) && r == AnaAP) 225 phy->rfc = 1; 226 else if((p & AnaP) && (r & AnaP)) 227 phy->rfc = phy->tfc = 1; 228 } 229 230 phy->link = 1; 231 232 return 0; 233 } 234