2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved.
26 * MII/PHY (National Semiconductor DP83840/DP83840A) support methods.
27 * It is general enough to work with most MII/PHYs.
32 #include "UniNEnetPrivate.h"
36 * Read from MII/PHY registers.
38 bool UniNEnet::miiReadWord( UInt16
*dataPtr
, UInt16 reg
, UInt8 phy
)
43 WRITE_REGISTER( MIFBitBangFrame_Output
,
44 kMIFBitBangFrame_Output_ST_default
45 | kMIFBitBangFrame_Output_OP_read
46 | phy
<< kMIFBitBangFrame_Output_PHYAD_shift
47 | reg
<< kMIFBitBangFrame_Output_REGAD_shift
48 | kMIFBitBangFrame_Output_TA_MSB
);
50 for (i
=0; i
< 20; i
++ )
52 miiReg
= READ_REGISTER( MIFBitBangFrame_Output
);
54 if ( miiReg
& kMIFBitBangFrame_Output_TA_LSB
)
56 // IOLog("Phy = %d Reg = %d miiReg = %08x\n\r", phy, reg, miiReg );
57 *dataPtr
= (UInt16
) miiReg
;
67 * Write to MII/PHY registers.
69 bool UniNEnet::miiWriteWord( UInt16 data
, UInt16 reg
, UInt8 phy
)
75 WRITE_REGISTER( MIFBitBangFrame_Output
,
76 kMIFBitBangFrame_Output_ST_default
77 | kMIFBitBangFrame_Output_OP_write
78 | phy
<< kMIFBitBangFrame_Output_PHYAD_shift
79 | reg
<< kMIFBitBangFrame_Output_REGAD_shift
80 | kMIFBitBangFrame_Output_TA_MSB
83 for ( i
=0; i
< 20; i
++ )
85 miiReg
= READ_REGISTER( MIFBitBangFrame_Output
);
87 if ( miiReg
& kMIFBitBangFrame_Output_TA_LSB
)
98 bool UniNEnet::miiResetPHY( UInt8 phy
)
100 int i
= MII_RESET_TIMEOUT
;
105 miiWriteWord( MII_CONTROL_RESET
, MII_CONTROL
, phy
);
107 IOSleep(MII_RESET_DELAY
);
109 // Wait till reset process is complete (MII_CONTROL_RESET returns to zero)
113 if ( miiReadWord( &mii_control
, MII_CONTROL
, phy
) == false )
116 if (!(mii_control
& MII_CONTROL_RESET
))
118 miiReadWord( &mii_control
, MII_CONTROL
, phy
);
119 mii_control
&= ~MII_CONTROL_ISOLATE
;
120 miiWriteWord( mii_control
, MII_CONTROL
, phy
);
124 IOSleep(MII_RESET_DELAY
);
125 i
-= MII_RESET_DELAY
;
130 bool UniNEnet::miiWaitForLink( UInt8 phy
)
132 int i
= MII_LINK_TIMEOUT
;
133 unsigned short mii_status
;
137 if ( miiReadWord( &mii_status
, MII_STATUS
, phy
) == false)
140 if (mii_status
& MII_STATUS_LINK_STATUS
)
143 IOSleep(MII_LINK_DELAY
);
149 bool UniNEnet::miiWaitForAutoNegotiation( UInt8 phy
)
151 int i
= MII_LINK_TIMEOUT
;
152 unsigned short mii_status
;
156 if ( miiReadWord( &mii_status
, MII_STATUS
, phy
) == false)
159 if (mii_status
& MII_STATUS_NEGOTIATION_COMPLETE
)
162 IOSleep(MII_LINK_DELAY
);
168 void UniNEnet::miiRestartAutoNegotiation( UInt8 phy
)
170 unsigned short mii_control
;
172 miiReadWord( &mii_control
, MII_CONTROL
, phy
);
173 mii_control
|= MII_CONTROL_RESTART_NEGOTIATION
;
174 miiWriteWord( mii_control
, MII_CONTROL
, phy
);
177 * If the system is not connected to the network, then auto-negotiation
178 * never completes and we hang in this loop!
183 miiReadWord( &mii_control
, MII_CONTROL
, phy
);
184 if ((mii_control
& MII_CONTROL_RESTART_NEGOTIATION
) == 0)
191 * Find the first PHY device on the MII interface.
195 * false PHY not found
197 bool UniNEnet::miiFindPHY( UInt8
*phy
)
204 // The first two PHY registers are required.
206 for (i
= 0; i
< MII_MAX_PHY
; i
++)
208 if ( miiReadWord( &phyWord
[0], MII_STATUS
, i
) == false )
212 if ( miiReadWord( &phyWord
[1], MII_CONTROL
, i
) == false )
216 if ( phyWord
[0] == 0xffff && phyWord
[1] == 0xffff )
221 if ( *phy
== 0xff ) *phy
= i
;
224 return (*phy
== 0xff) ? false : true;
231 bool UniNEnet::miiInitializePHY( UInt8 phy
)
235 // Clear enable auto-negotiation bit
237 miiReadWord( &phyWord
, MII_CONTROL
, phy
);
238 phyWord
&= ~MII_CONTROL_AUTONEGOTIATION
;
239 miiWriteWord( phyWord
, MII_CONTROL
, phy
);
241 // Advertise 10/100 Half/Full duplex capable to link partner
243 miiReadWord( &phyWord
, MII_ADVERTISEMENT
, phy
);
244 phyWord
|= (MII_ANAR_100BASETX_FD
| MII_ANAR_100BASETX
|
245 MII_ANAR_10BASET_FD
| MII_ANAR_10BASET
);
246 miiWriteWord( phyWord
, MII_ADVERTISEMENT
, phy
);
248 // Set enable auto-negotiation bit
250 miiReadWord( &phyWord
, MII_CONTROL
, phy
);
251 phyWord
|= MII_CONTROL_AUTONEGOTIATION
;
252 miiWriteWord( phyWord
, MII_CONTROL
, phy
);
254 miiRestartAutoNegotiation( phy
);