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