Annotation of XNU/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp, revision 1.1

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: }        

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.