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