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