|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.