|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. ! 24: * ! 25: * MII/PHY (National Semiconductor DP83840/DP83840A) support methods. ! 26: * It is general enough to work with most MII/PHYs. ! 27: * ! 28: * HISTORY ! 29: * ! 30: */ ! 31: ! 32: #include "BMacEnet.h" ! 33: #include "BMacEnetPrivate.h" ! 34: ! 35: /* ! 36: * Read from MII/PHY registers. ! 37: */ ! 38: bool BMacEnet::miiReadWord(unsigned short *dataPtr, unsigned short reg, ! 39: unsigned char phy) ! 40: { ! 41: int i; ! 42: miiFrameUnion frame; ! 43: unsigned short phyreg; ! 44: bool ret = true; ! 45: ! 46: do ! 47: { ! 48: // Write preamble ! 49: // ! 50: miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE); ! 51: ! 52: if ( miiCheckZeroBit() == true ) ! 53: { ! 54: // IOLog("Ethernet(BMac): MII not floating before read\n\r"); ! 55: ret = false; ! 56: break; ! 57: } ! 58: ! 59: // Prepare command frame ! 60: // ! 61: frame.data = MII_FRAME_READ; ! 62: frame.bit.regad = reg; ! 63: frame.bit.phyad = phy; ! 64: ! 65: // write ST, OP, PHYAD, REGAD in the MII command frame ! 66: // ! 67: miiWrite(frame.data, 14); ! 68: ! 69: // Hi-Z state ! 70: // Make sure the PHY generated a zero bit after the 2nd Hi-Z bit ! 71: // ! 72: ! 73: miiOutThreeState(); ! 74: ! 75: if (miiCheckZeroBit() == false) ! 76: { ! 77: // IOLog("Ethernet(BMac): MII not driven after turnaround\n\r"); ! 78: ret = false; ! 79: break; ! 80: } ! 81: ! 82: // read 16-bit data ! 83: // ! 84: phyreg = 0; ! 85: for (i = 0; i < 16; i++) ! 86: { ! 87: phyreg = miiReadBit() | (phyreg << 1); ! 88: } ! 89: if (dataPtr) ! 90: *dataPtr = phyreg; ! 91: ! 92: // Hi-Z state ! 93: miiOutThreeState(); ! 94: ! 95: if (miiCheckZeroBit() == true) ! 96: { ! 97: // IOLog("Ethernet(BMac): MII not floating after read\n\r"); ! 98: ret = false; ! 99: break; ! 100: } ! 101: } ! 102: while ( 0 ); ! 103: ! 104: return ret; ! 105: } ! 106: ! 107: /* ! 108: * Write to MII/PHY registers. ! 109: */ ! 110: bool BMacEnet::miiWriteWord(unsigned short data, unsigned short reg, ! 111: unsigned char phy) ! 112: { ! 113: miiFrameUnion frame; ! 114: bool ret = true; ! 115: ! 116: do ! 117: { ! 118: // Write preamble ! 119: // ! 120: miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE); ! 121: ! 122: if (miiCheckZeroBit() == true) ! 123: { ! 124: ret = false; ! 125: break; ! 126: } ! 127: ! 128: // Prepare command frame ! 129: // ! 130: frame.data = MII_FRAME_WRITE; ! 131: frame.bit.regad = reg; ! 132: frame.bit.phyad = phy; ! 133: frame.bit.data = data; ! 134: ! 135: // Write command frame ! 136: // ! 137: miiWrite(frame.data, MII_FRAME_SIZE); ! 138: ! 139: // Hi-Z state ! 140: miiOutThreeState(); ! 141: ! 142: if (miiCheckZeroBit() == true) ! 143: { ! 144: ret = false; ! 145: break; ! 146: } ! 147: } ! 148: while ( 0 ); ! 149: ! 150: return ret; ! 151: } ! 152: ! 153: /* ! 154: * Write 'dataSize' number of bits to the MII management interface, ! 155: * starting with the most significant bit of 'miiData'. ! 156: * ! 157: */ ! 158: void BMacEnet::miiWrite(unsigned int miiData, unsigned int dataSize) ! 159: { ! 160: int i; ! 161: u_int16_t regValue; ! 162: ! 163: regValue = kMIFCSR_DataOutEnable; ! 164: ! 165: for (i = dataSize; i > 0; i--) ! 166: { ! 167: int bit = ((miiData & 0x80000000) ? kMIFCSR_DataOut : 0); ! 168: ! 169: regValue &= ~(kMIFCSR_Clock | kMIFCSR_DataOut) ; ! 170: regValue |= bit; ! 171: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); ! 172: IODelay(phyMIIDelay); ! 173: ! 174: regValue |= kMIFCSR_Clock; ! 175: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue ); ! 176: IODelay(phyMIIDelay); ! 177: ! 178: miiData = miiData << 1; ! 179: } ! 180: } ! 181: ! 182: /* ! 183: * Read one bit from the MII management interface. ! 184: */ ! 185: int BMacEnet::miiReadBit() ! 186: { ! 187: u_int16_t regValue; ! 188: u_int16_t regValueRead; ! 189: ! 190: regValue = 0; ! 191: ! 192: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); ! 193: IODelay(phyMIIDelay); ! 194: ! 195: regValue |= kMIFCSR_Clock; ! 196: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); ! 197: IODelay(phyMIIDelay); ! 198: ! 199: regValueRead = ReadBigMacRegister(ioBaseEnet, kMIFCSR); ! 200: IODelay(phyMIIDelay); // delay next invocation of this routine ! 201: ! 202: return ( (regValueRead & kMIFCSR_DataIn) ? 1 : 0 ); ! 203: } ! 204: ! 205: /* ! 206: * Read the zero bit on the second clock of the turn-around (TA) ! 207: * when reading a PHY register. ! 208: */ ! 209: bool BMacEnet::miiCheckZeroBit() ! 210: { ! 211: u_int16_t regValue; ! 212: ! 213: regValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR); ! 214: ! 215: return (((regValue & kMIFCSR_DataIn) == 0) ? true : false ); ! 216: } ! 217: ! 218: /* ! 219: * Tri-state the STA's MDIO pin. ! 220: */ ! 221: void BMacEnet::miiOutThreeState() ! 222: { ! 223: u_int16_t regValue; ! 224: ! 225: regValue = 0; ! 226: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); ! 227: IODelay(phyMIIDelay); ! 228: ! 229: regValue |= kMIFCSR_Clock; ! 230: WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); ! 231: IODelay(phyMIIDelay); ! 232: } ! 233: ! 234: bool BMacEnet::miiResetPHY(unsigned char phy) ! 235: { ! 236: int i = MII_RESET_TIMEOUT; ! 237: unsigned short mii_control; ! 238: ! 239: // Set the reset bit ! 240: // ! 241: miiWriteWord(MII_CONTROL_RESET, MII_CONTROL, phy); ! 242: ! 243: IOSleep(MII_RESET_DELAY); ! 244: ! 245: // Wait till reset process is complete (MII_CONTROL_RESET returns to zero) ! 246: // ! 247: while (i > 0) ! 248: { ! 249: if (miiReadWord(&mii_control, MII_CONTROL, phy) == false) ! 250: return false; ! 251: ! 252: if (!(mii_control & MII_CONTROL_RESET)) ! 253: { ! 254: miiReadWord(&mii_control, MII_CONTROL, phy); ! 255: mii_control &= ~MII_CONTROL_ISOLATE; ! 256: miiWriteWord(mii_control, MII_CONTROL, phy); ! 257: return true; ! 258: } ! 259: ! 260: IOSleep(MII_RESET_DELAY); ! 261: i -= MII_RESET_DELAY; ! 262: } ! 263: return false; ! 264: } ! 265: ! 266: bool BMacEnet::miiWaitForLink(unsigned char phy) ! 267: { ! 268: int i = MII_LINK_TIMEOUT; ! 269: unsigned short mii_status; ! 270: ! 271: while (i > 0) ! 272: { ! 273: if (miiReadWord(&mii_status, MII_STATUS, phy) == false) ! 274: return false; ! 275: ! 276: if (mii_status & MII_STATUS_LINK_STATUS) ! 277: return true; ! 278: ! 279: IOSleep(MII_LINK_DELAY); ! 280: i -= MII_LINK_DELAY; ! 281: } ! 282: return false; ! 283: } ! 284: ! 285: bool BMacEnet::miiWaitForAutoNegotiation(unsigned char phy) ! 286: { ! 287: int i = MII_LINK_TIMEOUT; ! 288: unsigned short mii_status; ! 289: ! 290: while (i > 0) ! 291: { ! 292: if (miiReadWord(&mii_status, MII_STATUS, phy) == false) ! 293: return false; ! 294: ! 295: if (mii_status & MII_STATUS_NEGOTIATION_COMPLETE) ! 296: return true; ! 297: ! 298: IOSleep(MII_LINK_DELAY); ! 299: i -= MII_LINK_DELAY; ! 300: } ! 301: return false; ! 302: } ! 303: ! 304: void BMacEnet::miiRestartAutoNegotiation(unsigned char phy) ! 305: { ! 306: unsigned short mii_control; ! 307: ! 308: miiReadWord(&mii_control, MII_CONTROL, phy); ! 309: mii_control |= MII_CONTROL_RESTART_NEGOTIATION; ! 310: miiWriteWord(mii_control, MII_CONTROL, phy); ! 311: ! 312: /* ! 313: * If the system is not connected to the network, then auto-negotiation ! 314: * never completes and we hang in this loop! ! 315: */ ! 316: #if 0 ! 317: while (1) ! 318: { ! 319: miiReadWord(&mii_control, MII_CONTROL, phy); ! 320: if ((mii_control & MII_CONTROL_RESTART_NEGOTIATION) == 0) ! 321: break; ! 322: } ! 323: #endif ! 324: } ! 325: ! 326: /* ! 327: * Find the first PHY device on the MII interface. ! 328: * ! 329: * Return ! 330: * true PHY found ! 331: * false PHY not found ! 332: */ ! 333: bool BMacEnet::miiFindPHY(unsigned char *phy) ! 334: { ! 335: int i; ! 336: ! 337: *phy = 0xff; ! 338: ! 339: // The first two PHY registers are required. ! 340: // ! 341: for (i = 0; i < MII_MAX_PHY; i++) ! 342: { ! 343: if (miiReadWord(NULL, MII_STATUS, i) && ! 344: miiReadWord(NULL, MII_CONTROL, i)) ! 345: break; ! 346: } ! 347: ! 348: if (i >= MII_MAX_PHY) ! 349: return false; ! 350: ! 351: *phy = i; ! 352: ! 353: return true; ! 354: } ! 355: ! 356: /* ! 357: * ! 358: * ! 359: */ ! 360: bool BMacEnet::miiInitializePHY(unsigned char phy) ! 361: { ! 362: u_int16_t phyWord; ! 363: ! 364: // Clear then set the enable auto-negotiation bit ! 365: // ! 366: miiReadWord(&phyWord, MII_CONTROL, phy); ! 367: phyWord &= ~MII_CONTROL_AUTONEGOTIATION; ! 368: miiWriteWord(phyWord, MII_CONTROL, phy); ! 369: ! 370: // Advertise 10/100 Half/Full duplex capable to link partner ! 371: // ! 372: miiReadWord(&phyWord, MII_ADVERTISEMENT, phy); ! 373: phyWord |= (MII_ANAR_100BASETX_FD | MII_ANAR_100BASETX | ! 374: MII_ANAR_10BASET_FD | MII_ANAR_10BASET ); ! 375: miiWriteWord(phyWord, MII_ADVERTISEMENT, phy); ! 376: ! 377: // Set enable auto-negotiation bit ! 378: // ! 379: miiReadWord(&phyWord, MII_CONTROL, phy); ! 380: phyWord |= MII_CONTROL_AUTONEGOTIATION; ! 381: miiWriteWord(phyWord, MII_CONTROL, phy); ! 382: ! 383: miiRestartAutoNegotiation(phy); ! 384: ! 385: return true; ! 386: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.