]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/network/drvPPCUniN/UniNEnetMII.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Drivers / network / drvPPCUniN / UniNEnetMII.cpp
1 /*
2 * Copyright (c) 1999 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 /*
24 * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved.
25 *
26 * MII/PHY (National Semiconductor DP83840/DP83840A) support methods.
27 * It is general enough to work with most MII/PHYs.
28 *
29 * HISTORY
30 *
31 */
32 #include "UniNEnetPrivate.h"
33
34
35 /*
36 * Read from MII/PHY registers.
37 */
38 bool UniNEnet::miiReadWord( UInt16 *dataPtr, UInt16 reg, UInt8 phy )
39 {
40 UInt32 i;
41 UInt32 miiReg;
42
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 );
49
50 for (i=0; i < 20; i++ )
51 {
52 miiReg = READ_REGISTER( MIFBitBangFrame_Output );
53
54 if ( miiReg & kMIFBitBangFrame_Output_TA_LSB )
55 {
56 // IOLog("Phy = %d Reg = %d miiReg = %08x\n\r", phy, reg, miiReg );
57 *dataPtr = (UInt16) miiReg;
58 return true;
59 }
60 IODelay(10);
61 }
62
63 return false;
64 }
65
66 /*
67 * Write to MII/PHY registers.
68 */
69 bool UniNEnet::miiWriteWord( UInt16 data, UInt16 reg, UInt8 phy )
70 {
71 UInt32 i;
72 UInt32 miiReg;
73
74
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
81 | data );
82
83 for ( i=0; i < 20; i++ )
84 {
85 miiReg = READ_REGISTER( MIFBitBangFrame_Output );
86
87 if ( miiReg & kMIFBitBangFrame_Output_TA_LSB )
88 {
89 return true;
90 }
91 IODelay(10);
92 }
93
94 return false;
95 }
96
97
98 bool UniNEnet::miiResetPHY( UInt8 phy )
99 {
100 int i = MII_RESET_TIMEOUT;
101 UInt16 mii_control;
102
103 // Set the reset bit
104 //
105 miiWriteWord( MII_CONTROL_RESET, MII_CONTROL, phy );
106
107 IOSleep(MII_RESET_DELAY);
108
109 // Wait till reset process is complete (MII_CONTROL_RESET returns to zero)
110 //
111 while ( i > 0 )
112 {
113 if ( miiReadWord( &mii_control, MII_CONTROL, phy) == false )
114 return false;
115
116 if (!(mii_control & MII_CONTROL_RESET))
117 {
118 miiReadWord( &mii_control, MII_CONTROL, phy);
119 mii_control &= ~MII_CONTROL_ISOLATE;
120 miiWriteWord( mii_control, MII_CONTROL, phy );
121 return true;
122 }
123
124 IOSleep(MII_RESET_DELAY);
125 i -= MII_RESET_DELAY;
126 }
127 return false;
128 }
129
130 bool UniNEnet::miiWaitForLink( UInt8 phy )
131 {
132 int i = MII_LINK_TIMEOUT;
133 unsigned short mii_status;
134
135 while (i > 0)
136 {
137 if ( miiReadWord( &mii_status, MII_STATUS, phy ) == false)
138 return false;
139
140 if (mii_status & MII_STATUS_LINK_STATUS)
141 return true;
142
143 IOSleep(MII_LINK_DELAY);
144 i -= MII_LINK_DELAY;
145 }
146 return false;
147 }
148
149 bool UniNEnet::miiWaitForAutoNegotiation( UInt8 phy )
150 {
151 int i = MII_LINK_TIMEOUT;
152 unsigned short mii_status;
153
154 while (i > 0)
155 {
156 if ( miiReadWord( &mii_status, MII_STATUS, phy ) == false)
157 return false;
158
159 if (mii_status & MII_STATUS_NEGOTIATION_COMPLETE)
160 return true;
161
162 IOSleep(MII_LINK_DELAY);
163 i -= MII_LINK_DELAY;
164 }
165 return false;
166 }
167
168 void UniNEnet::miiRestartAutoNegotiation( UInt8 phy )
169 {
170 unsigned short mii_control;
171
172 miiReadWord( &mii_control, MII_CONTROL, phy);
173 mii_control |= MII_CONTROL_RESTART_NEGOTIATION;
174 miiWriteWord( mii_control, MII_CONTROL, phy);
175
176 /*
177 * If the system is not connected to the network, then auto-negotiation
178 * never completes and we hang in this loop!
179 */
180 #if 0
181 while (1)
182 {
183 miiReadWord( &mii_control, MII_CONTROL, phy );
184 if ((mii_control & MII_CONTROL_RESTART_NEGOTIATION) == 0)
185 break;
186 }
187 #endif
188 }
189
190 /*
191 * Find the first PHY device on the MII interface.
192 *
193 * Return
194 * true PHY found
195 * false PHY not found
196 */
197 bool UniNEnet::miiFindPHY( UInt8 *phy )
198 {
199 int i;
200 UInt16 phyWord[2];
201
202 *phy = 0xff;
203
204 // The first two PHY registers are required.
205 //
206 for (i = 0; i < MII_MAX_PHY; i++)
207 {
208 if ( miiReadWord( &phyWord[0], MII_STATUS, i ) == false )
209 {
210 continue;
211 }
212 if ( miiReadWord( &phyWord[1], MII_CONTROL, i ) == false )
213 {
214 continue;
215 }
216 if ( phyWord[0] == 0xffff && phyWord[1] == 0xffff )
217 {
218 continue;
219 }
220
221 if ( *phy == 0xff ) *phy = i;
222 }
223
224 return (*phy == 0xff) ? false : true;
225 }
226
227 /*
228 *
229 *
230 */
231 bool UniNEnet::miiInitializePHY( UInt8 phy )
232 {
233 UInt16 phyWord;
234
235 // Clear enable auto-negotiation bit
236 //
237 miiReadWord( &phyWord, MII_CONTROL, phy );
238 phyWord &= ~MII_CONTROL_AUTONEGOTIATION;
239 miiWriteWord( phyWord, MII_CONTROL, phy );
240
241 // Advertise 10/100 Half/Full duplex capable to link partner
242 //
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 );
247
248 // Set enable auto-negotiation bit
249 //
250 miiReadWord( &phyWord, MII_CONTROL, phy );
251 phyWord |= MII_CONTROL_AUTONEGOTIATION;
252 miiWriteWord( phyWord, MII_CONTROL, phy );
253
254 miiRestartAutoNegotiation( phy );
255
256 return true;
257 }
258
259