2 * Copyright (c) 1998-2000 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@
23 * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved.
25 * MII/PHY (National Semiconductor DP83840/DP83840A) support methods.
26 * It is general enough to work with most MII/PHYs.
33 #include "BMacEnetPrivate.h"
36 * Read from MII/PHY registers.
38 bool BMacEnet::miiReadWord(unsigned short *dataPtr
, unsigned short reg
,
43 unsigned short phyreg
;
50 miiWrite(MII_FRAME_PREAMBLE
, MII_FRAME_SIZE
);
52 if ( miiCheckZeroBit() == true )
54 // IOLog("Ethernet(BMac): MII not floating before read\n\r");
59 // Prepare command frame
61 frame
.data
= MII_FRAME_READ
;
62 frame
.bit
.regad
= reg
;
63 frame
.bit
.phyad
= phy
;
65 // write ST, OP, PHYAD, REGAD in the MII command frame
67 miiWrite(frame
.data
, 14);
70 // Make sure the PHY generated a zero bit after the 2nd Hi-Z bit
75 if (miiCheckZeroBit() == false)
77 // IOLog("Ethernet(BMac): MII not driven after turnaround\n\r");
85 for (i
= 0; i
< 16; i
++)
87 phyreg
= miiReadBit() | (phyreg
<< 1);
95 if (miiCheckZeroBit() == true)
97 // IOLog("Ethernet(BMac): MII not floating after read\n\r");
108 * Write to MII/PHY registers.
110 bool BMacEnet::miiWriteWord(unsigned short data
, unsigned short reg
,
120 miiWrite(MII_FRAME_PREAMBLE
, MII_FRAME_SIZE
);
122 if (miiCheckZeroBit() == true)
128 // Prepare command frame
130 frame
.data
= MII_FRAME_WRITE
;
131 frame
.bit
.regad
= reg
;
132 frame
.bit
.phyad
= phy
;
133 frame
.bit
.data
= data
;
135 // Write command frame
137 miiWrite(frame
.data
, MII_FRAME_SIZE
);
142 if (miiCheckZeroBit() == true)
154 * Write 'dataSize' number of bits to the MII management interface,
155 * starting with the most significant bit of 'miiData'.
158 void BMacEnet::miiWrite(unsigned int miiData
, unsigned int dataSize
)
163 regValue
= kMIFCSR_DataOutEnable
;
165 for (i
= dataSize
; i
> 0; i
--)
167 int bit
= ((miiData
& 0x80000000) ? kMIFCSR_DataOut
: 0);
169 regValue
&= ~(kMIFCSR_Clock
| kMIFCSR_DataOut
) ;
171 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
172 IODelay(phyMIIDelay
);
174 regValue
|= kMIFCSR_Clock
;
175 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
176 IODelay(phyMIIDelay
);
178 miiData
= miiData
<< 1;
183 * Read one bit from the MII management interface.
185 int BMacEnet::miiReadBit()
188 u_int16_t regValueRead
;
192 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
193 IODelay(phyMIIDelay
);
195 regValue
|= kMIFCSR_Clock
;
196 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
197 IODelay(phyMIIDelay
);
199 regValueRead
= ReadBigMacRegister(ioBaseEnet
, kMIFCSR
);
200 IODelay(phyMIIDelay
); // delay next invocation of this routine
202 return ( (regValueRead
& kMIFCSR_DataIn
) ? 1 : 0 );
206 * Read the zero bit on the second clock of the turn-around (TA)
207 * when reading a PHY register.
209 bool BMacEnet::miiCheckZeroBit()
213 regValue
= ReadBigMacRegister(ioBaseEnet
, kMIFCSR
);
215 return (((regValue
& kMIFCSR_DataIn
) == 0) ? true : false );
219 * Tri-state the STA's MDIO pin.
221 void BMacEnet::miiOutThreeState()
226 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
227 IODelay(phyMIIDelay
);
229 regValue
|= kMIFCSR_Clock
;
230 WriteBigMacRegister(ioBaseEnet
, kMIFCSR
, regValue
);
231 IODelay(phyMIIDelay
);
234 bool BMacEnet::miiResetPHY(unsigned char phy
)
236 int i
= MII_RESET_TIMEOUT
;
237 unsigned short mii_control
;
241 miiWriteWord(MII_CONTROL_RESET
, MII_CONTROL
, phy
);
243 IOSleep(MII_RESET_DELAY
);
245 // Wait till reset process is complete (MII_CONTROL_RESET returns to zero)
249 if (miiReadWord(&mii_control
, MII_CONTROL
, phy
) == false)
252 if (!(mii_control
& MII_CONTROL_RESET
))
254 miiReadWord(&mii_control
, MII_CONTROL
, phy
);
255 mii_control
&= ~MII_CONTROL_ISOLATE
;
256 miiWriteWord(mii_control
, MII_CONTROL
, phy
);
260 IOSleep(MII_RESET_DELAY
);
261 i
-= MII_RESET_DELAY
;
266 bool BMacEnet::miiWaitForLink(unsigned char phy
)
268 int i
= MII_LINK_TIMEOUT
;
269 unsigned short mii_status
;
273 if (miiReadWord(&mii_status
, MII_STATUS
, phy
) == false)
276 if (mii_status
& MII_STATUS_LINK_STATUS
)
279 IOSleep(MII_LINK_DELAY
);
285 bool BMacEnet::miiWaitForAutoNegotiation(unsigned char phy
)
287 int i
= MII_LINK_TIMEOUT
;
288 unsigned short mii_status
;
292 if (miiReadWord(&mii_status
, MII_STATUS
, phy
) == false)
295 if (mii_status
& MII_STATUS_NEGOTIATION_COMPLETE
)
298 IOSleep(MII_LINK_DELAY
);
304 void BMacEnet::miiRestartAutoNegotiation(unsigned char phy
)
306 unsigned short mii_control
;
308 miiReadWord(&mii_control
, MII_CONTROL
, phy
);
309 mii_control
|= MII_CONTROL_RESTART_NEGOTIATION
;
310 miiWriteWord(mii_control
, MII_CONTROL
, phy
);
313 * If the system is not connected to the network, then auto-negotiation
314 * never completes and we hang in this loop!
319 miiReadWord(&mii_control
, MII_CONTROL
, phy
);
320 if ((mii_control
& MII_CONTROL_RESTART_NEGOTIATION
) == 0)
327 * Find the first PHY device on the MII interface.
331 * false PHY not found
333 bool BMacEnet::miiFindPHY(unsigned char *phy
)
339 // The first two PHY registers are required.
341 for (i
= 0; i
< MII_MAX_PHY
; i
++)
343 if (miiReadWord(NULL
, MII_STATUS
, i
) &&
344 miiReadWord(NULL
, MII_CONTROL
, i
))
348 if (i
>= MII_MAX_PHY
)
360 bool BMacEnet::miiInitializePHY(unsigned char phy
)
364 // Clear then set the enable auto-negotiation bit
366 miiReadWord(&phyWord
, MII_CONTROL
, phy
);
367 phyWord
&= ~MII_CONTROL_AUTONEGOTIATION
;
368 miiWriteWord(phyWord
, MII_CONTROL
, phy
);
370 // Advertise 10/100 Half/Full duplex capable to link partner
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
);
377 // Set enable auto-negotiation bit
379 miiReadWord(&phyWord
, MII_CONTROL
, phy
);
380 phyWord
|= MII_CONTROL_AUTONEGOTIATION
;
381 miiWriteWord(phyWord
, MII_CONTROL
, phy
);
383 miiRestartAutoNegotiation(phy
);