Annotation of XNU/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp, revision 1.1.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.