Annotation of kernel/bsd/dev/ppc/drvBMacEnet/BMacEnetMII.m, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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