xref: /titanic_41/usr/src/uts/common/io/bge/bge_mii.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "sys/bge_impl2.h"
30 
31 /*
32  * Bit test macros, returning boolean_t values
33  */
34 #define	BIS(w, b)	(((w) & (b)) ? B_TRUE : B_FALSE)
35 #define	BIC(w, b)	(((w) & (b)) ? B_FALSE : B_TRUE)
36 #define	UPORDOWN(x)	((x) ? "up" : "down")
37 
38 /*
39  * ========== Copper (PHY) support ==========
40  */
41 
42 #define	BGE_DBG		BGE_DBG_PHY	/* debug flag for this code	*/
43 
44 /*
45  * #defines:
46  *	BGE_COPPER_WIRESPEED controls whether the Broadcom WireSpeed(tm)
47  *	feature is enabled.  We need to recheck whether this can be
48  *	enabled; at one time it seemed to interact unpleasantly with the
49  *	loopback modes.
50  *
51  *	BGE_COPPER_IDLEOFF controls whether the (copper) PHY power is
52  *	turned off when the PHY is idled i.e. during driver suspend().
53  *	For now this is disabled because the chip doesn't seem to
54  *	resume cleanly if the PHY power is turned off.
55  */
56 #define	BGE_COPPER_WIRESPEED	B_TRUE
57 #define	BGE_COPPER_IDLEOFF	B_FALSE
58 
59 /*
60  * The arrays below can be indexed by the MODE bits from the Auxiliary
61  * Status register to determine the current speed/duplex settings.
62  */
63 static const int16_t bge_copper_link_speed[] = {
64 	0,				/* MII_AUX_STATUS_MODE_NONE	*/
65 	10,				/* MII_AUX_STATUS_MODE_10_H	*/
66 	10,				/* MII_AUX_STATUS_MODE_10_F	*/
67 	100,				/* MII_AUX_STATUS_MODE_100_H	*/
68 	0,				/* MII_AUX_STATUS_MODE_100_4	*/
69 	100,				/* MII_AUX_STATUS_MODE_100_F	*/
70 	1000,				/* MII_AUX_STATUS_MODE_1000_H	*/
71 	1000				/* MII_AUX_STATUS_MODE_1000_F	*/
72 };
73 
74 static const int8_t bge_copper_link_duplex[] = {
75 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_NONE	*/
76 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_10_H	*/
77 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_10_F	*/
78 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_100_H	*/
79 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_100_4	*/
80 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_100_F	*/
81 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_1000_H	*/
82 	LINK_DUPLEX_FULL		/* MII_AUX_STATUS_MODE_1000_F	*/
83 };
84 
85 static const char * const bge_copper_link_text[] = {
86 	"down",				/* MII_AUX_STATUS_MODE_NONE	*/
87 	"up 10Mbps Half-Duplex",	/* MII_AUX_STATUS_MODE_10_H	*/
88 	"up 10Mbps Full-Duplex",	/* MII_AUX_STATUS_MODE_10_F	*/
89 	"up 100Mbps Half-Duplex",	/* MII_AUX_STATUS_MODE_100_H	*/
90 	"down",				/* MII_AUX_STATUS_MODE_100_4	*/
91 	"up 100Mbps Full-Duplex",	/* MII_AUX_STATUS_MODE_100_F	*/
92 	"up 1000Mbps Half-Duplex",	/* MII_AUX_STATUS_MODE_1000_H	*/
93 	"up 1000Mbps Full-Duplex"	/* MII_AUX_STATUS_MODE_1000_F	*/
94 };
95 
96 #if	BGE_DEBUGGING
97 
98 static void
99 bge_phydump(bge_t *bgep, uint16_t mii_status, uint16_t aux)
100 {
101 	uint16_t regs[32];
102 	int i;
103 
104 	ASSERT(mutex_owned(bgep->genlock));
105 
106 	for (i = 0; i < 32; ++i)
107 		switch (i) {
108 		default:
109 			regs[i] = bge_mii_get16(bgep, i);
110 			break;
111 
112 		case MII_STATUS:
113 			regs[i] = mii_status;
114 			break;
115 
116 		case MII_AUX_STATUS:
117 			regs[i] = aux;
118 			break;
119 
120 		case 0x0b: case 0x0c: case 0x0d: case 0x0e:
121 		case 0x15: case 0x16: case 0x17:
122 		case 0x1c:
123 		case 0x1f:
124 			/* reserved registers -- don't read these */
125 			regs[i] = 0;
126 			break;
127 		}
128 
129 	for (i = 0; i < 32; i += 8)
130 		BGE_DEBUG(("bge_phydump: "
131 				"0x%04x %04x %04x %04x %04x %04x %04x %04x",
132 			regs[i+0], regs[i+1], regs[i+2], regs[i+3],
133 			regs[i+4], regs[i+5], regs[i+6], regs[i+7]));
134 }
135 
136 #endif	/* BGE_DEBUGGING */
137 
138 /*
139  * Basic low-level function to probe for a PHY
140  *
141  * Returns TRUE if the PHY responds with valid data, FALSE otherwise
142  */
143 static boolean_t
144 bge_phy_probe(bge_t *bgep)
145 {
146 	uint16_t phy_status;
147 
148 	BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep));
149 
150 	ASSERT(mutex_owned(bgep->genlock));
151 
152 	/*
153 	 * Read the MII_STATUS register twice, in
154 	 * order to clear any sticky bits (but they should
155 	 * have been cleared by the RESET, I think).
156 	 */
157 	phy_status = bge_mii_get16(bgep, MII_STATUS);
158 	phy_status = bge_mii_get16(bgep, MII_STATUS);
159 	BGE_DEBUG(("bge_phy_probe: status 0x%x", phy_status));
160 
161 	/*
162 	 * Now check the value read; it should have at least one bit set
163 	 * (for the device capabilities) and at least one clear (one of
164 	 * the error bits). So if we see all 0s or all 1s, there's a
165 	 * problem.  In particular, bge_mii_get16() returns all 1s if
166 	 * communications fails ...
167 	 */
168 	switch (phy_status) {
169 	case 0x0000:
170 	case 0xffff:
171 		return (B_FALSE);
172 
173 	default :
174 		return (B_TRUE);
175 	}
176 }
177 
178 /*
179  * Basic low-level function to reset the PHY.
180  * Doesn't incorporate any special-case workarounds.
181  *
182  * Returns TRUE on success, FALSE if the RESET bit doesn't clear
183  */
184 static boolean_t
185 bge_phy_reset(bge_t *bgep)
186 {
187 	uint16_t control;
188 	uint_t count;
189 
190 	BGE_TRACE(("bge_phy_reset($%p)", (void *)bgep));
191 
192 	ASSERT(mutex_owned(bgep->genlock));
193 
194 	/*
195 	 * Set the PHY RESET bit, then wait up to 5 ms for it to self-clear
196 	 */
197 	bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_RESET);
198 	for (count = 0; ++count < 1000; ) {
199 		drv_usecwait(5);
200 		control = bge_mii_get16(bgep, MII_CONTROL);
201 		if (BIC(control, MII_CONTROL_RESET))
202 			return (B_TRUE);
203 	}
204 
205 	BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
206 
207 	return (B_FALSE);
208 }
209 
210 /*
211  * Basic low-level function to powerdown the PHY, if supported
212  * If powerdown support is compiled out, this function does nothing.
213  */
214 static void
215 bge_phy_powerdown(bge_t *bgep)
216 {
217 	BGE_TRACE(("bge_phy_powerdown"));
218 #if	BGE_COPPER_IDLEOFF
219 	bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_PWRDN);
220 #endif	/* BGE_COPPER_IDLEOFF */
221 }
222 
223 /*
224  * The following functions are based on sample code provided by
225  * Broadcom (20-June-2003), and implement workarounds said to be
226  * required on the early revisions of the BCM5703/4C.
227  *
228  * The registers and values used are mostly UNDOCUMENTED, and
229  * therefore don't have symbolic names ;-(
230  *
231  * Many of the comments are straight out of the Broadcom code:
232  * even where the code has been restructured, the original
233  * comments have been preserved in order to explain what these
234  * undocumented registers & values are all about ...
235  */
236 
237 static void
238 bge_phy_macro_wait(bge_t *bgep)
239 {
240 	uint_t count;
241 
242 	for (count = 100; --count; )
243 		if ((bge_mii_get16(bgep, 0x16) & 0x1000) == 0)
244 			break;
245 }
246 
247 /*
248  * PHY test data pattern:
249  *
250  * For 5703/04, each DFE TAP has 21-bits (low word 15, hi word 6)
251  * For 5705,    each DFE TAP has 19-bits (low word 15, hi word 4)
252  * For simplicity, we check only 19-bits, so we don't have to
253  * distinguish which chip it is.
254  * the LO word contains 15 bits, make sure pattern data is < 0x7fff
255  * the HI word contains  6 bits, make sure pattern data is < 0x003f
256  */
257 #define	N_CHANNELS	4
258 #define	N_TAPS		3
259 
260 static struct {
261 	uint16_t	lo;
262 	uint16_t	hi;
263 } tap_data[N_CHANNELS][N_TAPS] = {
264 	{
265 		{ 0x5555, 0x0005 },	/* ch0, TAP 0, LO/HI pattern */
266 		{ 0x2aaa, 0x000a },	/* ch0, TAP 1, LO/HI pattern */
267 		{ 0x3456, 0x0003 }	/* ch0, TAP 2, LO/HI pattern */
268 	},
269 	{
270 		{ 0x2aaa, 0x000a },	/* ch1, TAP 0, LO/HI pattern */
271 		{ 0x3333, 0x0003 },	/* ch1, TAP 1, LO/HI pattern */
272 		{ 0x789a, 0x0005 }	/* ch1, TAP 2, LO/HI pattern */
273 	},
274 	{
275 		{ 0x5a5a, 0x0005 },	/* ch2, TAP 0, LO/HI pattern */
276 		{ 0x2a6a, 0x000a },	/* ch2, TAP 1, LO/HI pattern */
277 		{ 0x1bcd, 0x0003 }	/* ch2, TAP 2, LO/HI pattern */
278 	},
279 	{
280 		{ 0x2a5a, 0x000a },	/* ch3, TAP 0, LO/HI pattern */
281 		{ 0x33c3, 0x0003 },	/* ch3, TAP 1, LO/HI pattern */
282 		{ 0x2ef1, 0x0005 }	/* ch3, TAP 2, LO/HI pattern */
283 	}
284 };
285 
286 /*
287  * Check whether the PHY has locked up after a RESET.
288  *
289  * Returns TRUE if it did, FALSE is it's OK ;-)
290  */
291 static boolean_t
292 bge_phy_locked_up(bge_t *bgep)
293 {
294 	uint16_t dataLo;
295 	uint16_t dataHi;
296 	uint_t chan;
297 	uint_t tap;
298 
299 	/*
300 	 * Check TAPs for all 4 channels, as soon as we see a lockup
301 	 * we'll stop checking.
302 	 */
303 	for (chan = 0; chan < N_CHANNELS; ++chan) {
304 		/* Select channel and set TAP index to 0 */
305 		bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
306 		/* Freeze filter again just to be safe */
307 		bge_mii_put16(bgep, 0x16, 0x0002);
308 
309 		/*
310 		 * Write fixed pattern to the RAM, 3 TAPs for
311 		 * each channel, each TAP have 2 WORDs (LO/HI)
312 		 */
313 		for (tap = 0; tap < N_TAPS; ++tap) {
314 			bge_mii_put16(bgep, 0x15, tap_data[chan][tap].lo);
315 			bge_mii_put16(bgep, 0x15, tap_data[chan][tap].hi);
316 		}
317 
318 		/*
319 		 * Active PHY's Macro operation to write DFE
320 		 * TAP from RAM, and wait for Macro to complete.
321 		 */
322 		bge_mii_put16(bgep, 0x16, 0x0202);
323 		bge_phy_macro_wait(bgep);
324 
325 		/*
326 		 * Done with write phase, now begin read phase.
327 		 */
328 
329 		/* Select channel and set TAP index to 0 */
330 		bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
331 
332 		/*
333 		 * Active PHY's Macro operation to load DFE
334 		 * TAP to RAM, and wait for Macro to complete
335 		 */
336 		bge_mii_put16(bgep, 0x16, 0x0082);
337 		bge_phy_macro_wait(bgep);
338 
339 		/* Enable "pre-fetch" */
340 		bge_mii_put16(bgep, 0x16, 0x0802);
341 		bge_phy_macro_wait(bgep);
342 
343 		/*
344 		 * Read back the TAP values.  3 TAPs for each
345 		 * channel, each TAP have 2 WORDs (LO/HI)
346 		 */
347 		for (tap = 0; tap < N_TAPS; ++tap) {
348 			/*
349 			 * Read Lo/Hi then wait for 'done' is faster.
350 			 * For DFE TAP, the HI word contains 6 bits,
351 			 * LO word contains 15 bits
352 			 */
353 			dataLo = bge_mii_get16(bgep, 0x15) & 0x7fff;
354 			dataHi = bge_mii_get16(bgep, 0x15) & 0x003f;
355 			bge_phy_macro_wait(bgep);
356 
357 			/*
358 			 * Check if what we wrote is what we read back.
359 			 * If failed, then the PHY is locked up, we need
360 			 * to do PHY reset again
361 			 */
362 			if (dataLo != tap_data[chan][tap].lo)
363 				return (B_TRUE);	/* wedged!	*/
364 
365 			if (dataHi != tap_data[chan][tap].hi)
366 				return (B_TRUE);	/* wedged!	*/
367 		}
368 	}
369 
370 	/*
371 	 * The PHY isn't locked up ;-)
372 	 */
373 	return (B_FALSE);
374 }
375 
376 /*
377  * Special-case code to reset the PHY on the 5702/5703/5704C/5705/5782.
378  * Tries up to 5 times to recover from failure to reset or PHY lockup.
379  *
380  * Returns TRUE on success, FALSE if there's an unrecoverable problem
381  */
382 static boolean_t
383 bge_phy_reset_and_check(bge_t *bgep)
384 {
385 	boolean_t reset_success;
386 	boolean_t phy_locked;
387 	uint16_t extctrl;
388 	uint_t retries;
389 
390 	for (retries = 0; retries < 5; ++retries) {
391 		/* Issue a phy reset, and wait for reset to complete */
392 		/* Assuming reset is successful first */
393 		reset_success = bge_phy_reset(bgep);
394 
395 		/*
396 		 * Now go check the DFE TAPs to see if locked up, but
397 		 * first, we need to set up PHY so we can read DFE
398 		 * TAPs.
399 		 */
400 
401 		/*
402 		 * Disable Transmitter and Interrupt, while we play
403 		 * with the PHY registers, so the link partner won't
404 		 * see any strange data and the Driver won't see any
405 		 * interrupts.
406 		 */
407 		extctrl = bge_mii_get16(bgep, 0x10);
408 		bge_mii_put16(bgep, 0x10, extctrl | 0x3000);
409 
410 		/* Setup Full-Duplex, 1000 mbps */
411 		bge_mii_put16(bgep, 0x0, 0x0140);
412 
413 		/* Set to Master mode */
414 		bge_mii_put16(bgep, 0x9, 0x1800);
415 
416 		/* Enable SM_DSP_CLOCK & 6dB */
417 		bge_mii_put16(bgep, 0x18, 0x0c00);	/* "the ADC fix" */
418 
419 		/* Work-arounds */
420 		bge_mii_put16(bgep, 0x17, 0x201f);
421 		bge_mii_put16(bgep, 0x15, 0x2aaa);
422 
423 		/* More workarounds */
424 		bge_mii_put16(bgep, 0x17, 0x000a);
425 		bge_mii_put16(bgep, 0x15, 0x0323);	/* "the Gamma fix" */
426 
427 		/* Blocks the PHY control access */
428 		bge_mii_put16(bgep, 0x17, 0x8005);
429 		bge_mii_put16(bgep, 0x15, 0x0800);
430 
431 		/* Test whether PHY locked up ;-( */
432 		phy_locked = bge_phy_locked_up(bgep);
433 		if (reset_success && !phy_locked)
434 			break;
435 
436 		/*
437 		 * Some problem here ... log it & retry
438 		 */
439 		if (!reset_success)
440 			BGE_REPORT((bgep, "PHY didn't reset!"));
441 		if (phy_locked)
442 			BGE_REPORT((bgep, "PHY locked up!"));
443 	}
444 
445 	/* Remove block phy control */
446 	bge_mii_put16(bgep, 0x17, 0x8005);
447 	bge_mii_put16(bgep, 0x15, 0x0000);
448 
449 	/* Unfreeze DFE TAP filter for all channels */
450 	bge_mii_put16(bgep, 0x17, 0x8200);
451 	bge_mii_put16(bgep, 0x16, 0x0000);
452 
453 	/* Restore PHY back to operating state */
454 	bge_mii_put16(bgep, 0x18, 0x0400);
455 
456 	/* Enable transmitter and interrupt */
457 	extctrl = bge_mii_get16(bgep, 0x10);
458 	bge_mii_put16(bgep, 0x10, extctrl & ~0x3000);
459 
460 	if (!reset_success)
461 		bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
462 	else if (phy_locked)
463 		bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
464 	return (reset_success && !phy_locked);
465 }
466 
467 static void
468 bge_phy_tweak_gmii(bge_t *bgep)
469 {
470 	/* Tweak GMII timing */
471 	bge_mii_put16(bgep, 0x1c, 0x8d68);
472 	bge_mii_put16(bgep, 0x1c, 0x8d68);
473 }
474 
475 /*
476  * End of Broadcom-derived workaround code				*
477  */
478 
479 static int
480 bge_restart_copper(bge_t *bgep, boolean_t powerdown)
481 {
482 	uint16_t phy_status;
483 	boolean_t reset_ok;
484 
485 	BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
486 
487 	ASSERT(mutex_owned(bgep->genlock));
488 
489 	switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
490 	default:
491 		/*
492 		 * Shouldn't happen; it means we don't recognise this chip.
493 		 * It's probably a new one, so we'll try our best anyway ...
494 		 */
495 	case MHCR_CHIP_ASIC_REV_5703:
496 	case MHCR_CHIP_ASIC_REV_5704:
497 	case MHCR_CHIP_ASIC_REV_5705:
498 	case MHCR_CHIP_ASIC_REV_5721_5751:
499 	case MHCR_CHIP_ASIC_REV_5714:
500 	case MHCR_CHIP_ASIC_REV_5715:
501 		reset_ok = bge_phy_reset_and_check(bgep);
502 		break;
503 
504 	case MHCR_CHIP_ASIC_REV_5700:
505 	case MHCR_CHIP_ASIC_REV_5701:
506 		/*
507 		 * Just a plain reset; the "check" code breaks these chips
508 		 */
509 		reset_ok = bge_phy_reset(bgep);
510 		if (!reset_ok)
511 			bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
512 		break;
513 	}
514 	if (!reset_ok) {
515 		BGE_REPORT((bgep, "PHY failed to reset correctly"));
516 		return (DDI_FAILURE);
517 	}
518 
519 	/*
520 	 * Step 5: disable WOL (not required after RESET)
521 	 *
522 	 * Step 6: refer to errata
523 	 */
524 	switch (bgep->chipid.asic_rev) {
525 	default:
526 		break;
527 
528 	case MHCR_CHIP_REV_5704_A0:
529 		bge_phy_tweak_gmii(bgep);
530 		break;
531 	}
532 
533 	/*
534 	 * Step 7: read the MII_INTR_STATUS register twice,
535 	 * in order to clear any sticky bits (but they should
536 	 * have been cleared by the RESET, I think), and we're
537 	 * not using PHY interrupts anyway.
538 	 *
539 	 * Step 8: enable the PHY to interrupt on link status
540 	 * change (not required)
541 	 *
542 	 * Step 9: configure PHY LED Mode - not applicable?
543 	 *
544 	 * Step 10: read the MII_STATUS register twice, in
545 	 * order to clear any sticky bits (but they should
546 	 * have been cleared by the RESET, I think).
547 	 */
548 	phy_status = bge_mii_get16(bgep, MII_STATUS);
549 	phy_status = bge_mii_get16(bgep, MII_STATUS);
550 	BGE_DEBUG(("bge_restart_copper: status 0x%x", phy_status));
551 
552 	/*
553 	 * Finally, shut down the PHY, if required
554 	 */
555 	if (powerdown)
556 		bge_phy_powerdown(bgep);
557 	return (DDI_SUCCESS);
558 }
559 
560 /*
561  * Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities
562  * and advertisements with the required settings as specified by the various
563  * param_* variables that can be poked via the NDD interface.
564  *
565  * We always reset the PHY and reprogram *all* the relevant registers,
566  * not just those changed.  This should cause the link to go down, and then
567  * back up again once the link is stable and autonegotiation (if enabled)
568  * is complete.  We should get a link state change interrupt somewhere along
569  * the way ...
570  *
571  * NOTE: <genlock> must already be held by the caller
572  */
573 static int
574 bge_update_copper(bge_t *bgep)
575 {
576 	boolean_t adv_autoneg;
577 	boolean_t adv_pause;
578 	boolean_t adv_asym_pause;
579 	boolean_t adv_1000fdx;
580 	boolean_t adv_1000hdx;
581 	boolean_t adv_100fdx;
582 	boolean_t adv_100hdx;
583 	boolean_t adv_10fdx;
584 	boolean_t adv_10hdx;
585 
586 	uint16_t control;
587 	uint16_t gigctrl;
588 	uint16_t auxctrl;
589 	uint16_t anar;
590 
591 	BGE_TRACE(("bge_update_copper($%p)", (void *)bgep));
592 
593 	ASSERT(mutex_owned(bgep->genlock));
594 
595 	BGE_DEBUG(("bge_update_copper: autoneg %d "
596 			"pause %d asym_pause %d "
597 			"1000fdx %d 1000hdx %d "
598 			"100fdx %d 100hdx %d "
599 			"10fdx %d 10hdx %d ",
600 		bgep->param_adv_autoneg,
601 		bgep->param_adv_pause, bgep->param_adv_asym_pause,
602 		bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
603 		bgep->param_adv_100fdx, bgep->param_adv_100hdx,
604 		bgep->param_adv_10fdx, bgep->param_adv_10hdx));
605 
606 	control = gigctrl = auxctrl = anar = 0;
607 
608 	/*
609 	 * PHY settings are normally based on the param_* variables,
610 	 * but if any loopback mode is in effect, that takes precedence.
611 	 *
612 	 * BGE supports MAC-internal loopback, PHY-internal loopback,
613 	 * and External loopback at a variety of speeds (with a special
614 	 * cable).  In all cases, autoneg is turned OFF, full-duplex
615 	 * is turned ON, and the speed/mastership is forced.
616 	 */
617 	switch (bgep->param_loop_mode) {
618 	case BGE_LOOP_NONE:
619 	default:
620 		adv_autoneg = bgep->param_adv_autoneg;
621 		adv_pause = bgep->param_adv_pause;
622 		adv_asym_pause = bgep->param_adv_asym_pause;
623 		adv_1000fdx = bgep->param_adv_1000fdx;
624 		adv_1000hdx = bgep->param_adv_1000hdx;
625 		adv_100fdx = bgep->param_adv_100fdx;
626 		adv_100hdx = bgep->param_adv_100hdx;
627 		adv_10fdx = bgep->param_adv_10fdx;
628 		adv_10hdx = bgep->param_adv_10hdx;
629 		break;
630 
631 	case BGE_LOOP_EXTERNAL_1000:
632 	case BGE_LOOP_EXTERNAL_100:
633 	case BGE_LOOP_EXTERNAL_10:
634 	case BGE_LOOP_INTERNAL_PHY:
635 	case BGE_LOOP_INTERNAL_MAC:
636 		adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
637 		adv_1000fdx = adv_100fdx = adv_10fdx = B_FALSE;
638 		adv_1000hdx = adv_100hdx = adv_10hdx = B_FALSE;
639 		bgep->param_link_duplex = LINK_DUPLEX_FULL;
640 
641 		switch (bgep->param_loop_mode) {
642 		case BGE_LOOP_EXTERNAL_1000:
643 			bgep->param_link_speed = 1000;
644 			adv_1000fdx = B_TRUE;
645 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
646 			gigctrl |= MII_1000BT_CTL_MASTER_CFG;
647 			gigctrl |= MII_1000BT_CTL_MASTER_SEL;
648 			break;
649 
650 		case BGE_LOOP_EXTERNAL_100:
651 			bgep->param_link_speed = 100;
652 			adv_100fdx = B_TRUE;
653 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
654 			break;
655 
656 		case BGE_LOOP_EXTERNAL_10:
657 			bgep->param_link_speed = 10;
658 			adv_10fdx = B_TRUE;
659 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
660 			break;
661 
662 		case BGE_LOOP_INTERNAL_PHY:
663 			bgep->param_link_speed = 1000;
664 			adv_1000fdx = B_TRUE;
665 			control = MII_CONTROL_LOOPBACK;
666 			break;
667 
668 		case BGE_LOOP_INTERNAL_MAC:
669 			bgep->param_link_speed = 1000;
670 			adv_1000fdx = B_TRUE;
671 			break;
672 		}
673 	}
674 
675 	BGE_DEBUG(("bge_update_copper: autoneg %d "
676 			"pause %d asym_pause %d "
677 			"1000fdx %d 1000hdx %d "
678 			"100fdx %d 100hdx %d "
679 			"10fdx %d 10hdx %d ",
680 		adv_autoneg,
681 		adv_pause, adv_asym_pause,
682 		adv_1000fdx, adv_1000hdx,
683 		adv_100fdx, adv_100hdx,
684 		adv_10fdx, adv_10hdx));
685 
686 	/*
687 	 * We should have at least one technology capability set;
688 	 * if not, we select a default of 1000Mb/s full-duplex
689 	 */
690 	if (!adv_1000fdx && !adv_100fdx && !adv_10fdx &&
691 	    !adv_1000hdx && !adv_100hdx && !adv_10hdx)
692 		adv_1000fdx = B_TRUE;
693 
694 	/*
695 	 * Now transform the adv_* variables into the proper settings
696 	 * of the PHY registers ...
697 	 *
698 	 * If autonegotiation is (now) enabled, we want to trigger
699 	 * a new autonegotiation cycle once the PHY has been
700 	 * programmed with the capabilities to be advertised.
701 	 */
702 	if (adv_autoneg)
703 		control |= MII_CONTROL_ANE|MII_CONTROL_RSAN;
704 
705 	if (adv_1000fdx)
706 		control |= MII_CONTROL_1000MB|MII_CONTROL_FDUPLEX;
707 	else if (adv_1000hdx)
708 		control |= MII_CONTROL_1000MB;
709 	else if (adv_100fdx)
710 		control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX;
711 	else if (adv_100hdx)
712 		control |= MII_CONTROL_100MB;
713 	else if (adv_10fdx)
714 		control |= MII_CONTROL_FDUPLEX;
715 	else if (adv_10hdx)
716 		control |= 0;
717 	else
718 		{ _NOTE(EMPTY); }	/* Can't get here anyway ...	*/
719 
720 	if (adv_1000fdx)
721 		gigctrl |= MII_1000BT_CTL_ADV_FDX;
722 	if (adv_1000hdx)
723 		gigctrl |= MII_1000BT_CTL_ADV_HDX;
724 
725 	if (adv_100fdx)
726 		anar |= MII_ABILITY_100BASE_TX_FD;
727 	if (adv_100hdx)
728 		anar |= MII_ABILITY_100BASE_TX;
729 	if (adv_10fdx)
730 		anar |= MII_ABILITY_10BASE_T_FD;
731 	if (adv_10hdx)
732 		anar |= MII_ABILITY_10BASE_T;
733 
734 	if (adv_pause)
735 		anar |= MII_ABILITY_PAUSE;
736 	if (adv_asym_pause)
737 		anar |= MII_ABILITY_ASYM_PAUSE;
738 
739 	/*
740 	 * Munge in any other fixed bits we require ...
741 	 */
742 	anar |= MII_AN_SELECTOR_8023;
743 	auxctrl |= MII_AUX_CTRL_NORM_TX_MODE;
744 	auxctrl |= MII_AUX_CTRL_NORMAL;
745 
746 	/*
747 	 * Restart the PHY and write the new values.  Note the
748 	 * time, so that we can say whether subsequent link state
749 	 * changes can be attributed to our reprogramming the PHY
750 	 */
751 	bgep->phys_write_time = gethrtime();
752 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) == DDI_FAILURE)
753 		return (DDI_FAILURE);
754 	bge_mii_put16(bgep, MII_AN_ADVERT, anar);
755 	bge_mii_put16(bgep, MII_CONTROL, control);
756 	bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
757 	bge_mii_put16(bgep, MII_1000BASE_T_CONTROL, gigctrl);
758 
759 	BGE_DEBUG(("bge_update_copper: anar <- 0x%x", anar));
760 	BGE_DEBUG(("bge_update_copper: control <- 0x%x", control));
761 	BGE_DEBUG(("bge_update_copper: auxctrl <- 0x%x", auxctrl));
762 	BGE_DEBUG(("bge_update_copper: gigctrl <- 0x%x", gigctrl));
763 
764 #if	BGE_COPPER_WIRESPEED
765 	/*
766 	 * Enable the 'wire-speed' feature, if the chip supports it
767 	 * and we haven't got (any) loopback mode selected.
768 	 */
769 	switch (bgep->chipid.device) {
770 	case DEVICE_ID_5700:
771 	case DEVICE_ID_5700x:
772 	case DEVICE_ID_5705C:
773 	case DEVICE_ID_5782:
774 		/*
775 		 * These chips are known or assumed not to support it
776 		 */
777 		break;
778 
779 	default:
780 		/*
781 		 * All other Broadcom chips are expected to support it.
782 		 */
783 		if (bgep->param_loop_mode == BGE_LOOP_NONE)
784 			bge_mii_put16(bgep, MII_AUX_CONTROL,
785 					MII_AUX_CTRL_MISC_WRITE_ENABLE |
786 					MII_AUX_CTRL_MISC_WIRE_SPEED |
787 					MII_AUX_CTRL_MISC);
788 		break;
789 	}
790 #endif	/* BGE_COPPER_WIRESPEED */
791 	return (DDI_SUCCESS);
792 }
793 
794 static boolean_t
795 bge_check_copper(bge_t *bgep, boolean_t recheck)
796 {
797 	uint32_t emac_status;
798 	uint16_t mii_status;
799 	uint16_t aux;
800 	uint_t mode;
801 	boolean_t linkup;
802 
803 	/*
804 	 * Step 10: read the status from the PHY (which is self-clearing
805 	 * on read!); also read & clear the main (Ethernet) MAC status
806 	 * (the relevant bits of this are write-one-to-clear).
807 	 */
808 	mii_status = bge_mii_get16(bgep, MII_STATUS);
809 	emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
810 	bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status);
811 
812 	BGE_DEBUG(("bge_check_copper: link %d/%s, MII status 0x%x "
813 			"(was 0x%x), Ethernet MAC status 0x%x",
814 		bgep->link_state, UPORDOWN(bgep->param_link_up), mii_status,
815 		bgep->phy_gen_status, emac_status));
816 
817 	/*
818 	 * If the PHY status hasn't changed since last we looked, and
819 	 * we not forcing a recheck (i.e. the link state was already
820 	 * known), there's nothing to do.
821 	 */
822 	if (mii_status == bgep->phy_gen_status && !recheck)
823 		return (B_FALSE);
824 
825 	do {
826 		/*
827 		 * If the PHY status changed, record the time
828 		 */
829 		if (mii_status != bgep->phy_gen_status)
830 			bgep->phys_event_time = gethrtime();
831 
832 		/*
833 		 * Step 11: read AUX STATUS register to find speed/duplex
834 		 */
835 		aux = bge_mii_get16(bgep, MII_AUX_STATUS);
836 		BGE_CDB(bge_phydump, (bgep, mii_status, aux));
837 
838 		/*
839 		 * We will only consider the link UP if all the readings
840 		 * are consistent and give meaningful results ...
841 		 */
842 		mode = aux & MII_AUX_STATUS_MODE_MASK;
843 		mode >>= MII_AUX_STATUS_MODE_SHIFT;
844 		linkup = bge_copper_link_speed[mode] > 0;
845 		linkup &= bge_copper_link_duplex[mode] != LINK_DUPLEX_UNKNOWN;
846 		linkup &= BIS(aux, MII_AUX_STATUS_LINKUP);
847 		linkup &= BIS(mii_status, MII_STATUS_LINKUP);
848 
849 		BGE_DEBUG(("bge_check_copper: MII status 0x%x aux 0x%x "
850 				"=> mode %d (%s)",
851 			mii_status, aux,
852 			mode, UPORDOWN(linkup)));
853 
854 		/*
855 		 * Record current register values, then reread status
856 		 * register & loop until it stabilises ...
857 		 */
858 		bgep->phy_aux_status = aux;
859 		bgep->phy_gen_status = mii_status;
860 		mii_status = bge_mii_get16(bgep, MII_STATUS);
861 	} while (mii_status != bgep->phy_gen_status);
862 
863 	/*
864 	 * Assume very little ...
865 	 */
866 	bgep->param_lp_autoneg = B_FALSE;
867 	bgep->param_lp_1000fdx = B_FALSE;
868 	bgep->param_lp_1000hdx = B_FALSE;
869 	bgep->param_lp_100fdx = B_FALSE;
870 	bgep->param_lp_100hdx = B_FALSE;
871 	bgep->param_lp_10fdx = B_FALSE;
872 	bgep->param_lp_10hdx = B_FALSE;
873 	bgep->param_lp_pause = B_FALSE;
874 	bgep->param_lp_asym_pause = B_FALSE;
875 	bgep->param_link_autoneg = B_FALSE;
876 	bgep->param_link_tx_pause = B_FALSE;
877 	if (bgep->param_adv_autoneg)
878 		bgep->param_link_rx_pause = B_FALSE;
879 	else
880 		bgep->param_link_rx_pause = bgep->param_adv_pause;
881 
882 	/*
883 	 * Discover all the link partner's abilities.
884 	 * These are scattered through various registters ...
885 	 */
886 	if (BIS(aux, MII_AUX_STATUS_LP_ANEG_ABLE)) {
887 		bgep->param_lp_autoneg = B_TRUE;
888 		bgep->param_link_autoneg = B_TRUE;
889 		bgep->param_link_tx_pause = BIS(aux, MII_AUX_STATUS_TX_PAUSE);
890 		bgep->param_link_rx_pause = BIS(aux, MII_AUX_STATUS_RX_PAUSE);
891 
892 		aux = bge_mii_get16(bgep, MII_1000BASE_T_STATUS);
893 		bgep->param_lp_1000fdx = BIS(aux, MII_1000BT_STAT_LP_FDX_CAP);
894 		bgep->param_lp_1000hdx = BIS(aux, MII_1000BT_STAT_LP_HDX_CAP);
895 
896 		aux = bge_mii_get16(bgep, MII_AN_LPABLE);
897 		bgep->param_lp_100fdx = BIS(aux, MII_ABILITY_100BASE_TX_FD);
898 		bgep->param_lp_100hdx = BIS(aux, MII_ABILITY_100BASE_TX);
899 		bgep->param_lp_10fdx = BIS(aux, MII_ABILITY_10BASE_T_FD);
900 		bgep->param_lp_10hdx = BIS(aux, MII_ABILITY_10BASE_T);
901 		bgep->param_lp_pause = BIS(aux, MII_ABILITY_PAUSE);
902 		bgep->param_lp_asym_pause = BIS(aux, MII_ABILITY_ASYM_PAUSE);
903 	}
904 
905 	/*
906 	 * Step 12: update ndd-visible state parameters, BUT!
907 	 * we don't transfer the new state to <link_state> just yet;
908 	 * instead we mark the <link_state> as UNKNOWN, and our caller
909 	 * will resolve it once the status has stopped changing and
910 	 * been stable for several seconds.
911 	 */
912 	BGE_DEBUG(("bge_check_copper: link was %s speed %d duplex %d",
913 		UPORDOWN(bgep->param_link_up),
914 		bgep->param_link_speed,
915 		bgep->param_link_duplex));
916 
917 	if (!linkup)
918 		mode = MII_AUX_STATUS_MODE_NONE;
919 	bgep->param_link_up = linkup;
920 	bgep->param_link_speed = bge_copper_link_speed[mode];
921 	bgep->param_link_duplex = bge_copper_link_duplex[mode];
922 	bgep->link_mode_msg = bge_copper_link_text[mode];
923 	bgep->link_state = LINK_STATE_UNKNOWN;
924 
925 	BGE_DEBUG(("bge_check_copper: link now %s speed %d duplex %d",
926 		UPORDOWN(bgep->param_link_up),
927 		bgep->param_link_speed,
928 		bgep->param_link_duplex));
929 
930 	return (B_TRUE);
931 }
932 
933 static const phys_ops_t copper_ops = {
934 	bge_restart_copper,
935 	bge_update_copper,
936 	bge_check_copper
937 };
938 
939 
940 /*
941  * ========== SerDes support ==========
942  */
943 
944 #undef	BGE_DBG
945 #define	BGE_DBG		BGE_DBG_SERDES	/* debug flag for this code	*/
946 
947 /*
948  * Reinitialise the SerDes interface.  Note that it normally powers
949  * up in the disabled state, so we need to explicitly activate it.
950  */
951 static int
952 bge_restart_serdes(bge_t *bgep, boolean_t powerdown)
953 {
954 	uint32_t macmode;
955 
956 	BGE_TRACE(("bge_restart_serdes($%p, %d)", (void *)bgep, powerdown));
957 
958 	ASSERT(mutex_owned(bgep->genlock));
959 
960 	/*
961 	 * Ensure that the main Ethernet MAC mode register is programmed
962 	 * appropriately for the SerDes interface ...
963 	 */
964 	macmode = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG);
965 	macmode &= ~ETHERNET_MODE_LINK_POLARITY;
966 	macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
967 	macmode |= ETHERNET_MODE_PORTMODE_TBI;
968 	bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, macmode);
969 
970 	/*
971 	 * Ensure that loopback is OFF and comma detection is enabled.  Then
972 	 * disable the SerDes output (the first time through, it may/will
973 	 * already be disabled).  If we're shutting down, leave it disabled.
974 	 */
975 	bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TBI_LOOPBACK);
976 	bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_COMMA_DETECT);
977 	bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
978 	if (powerdown)
979 		return (DDI_SUCCESS);
980 
981 	/*
982 	 * Otherwise, pause, (re-)enable the SerDes output, and send
983 	 * all-zero config words in order to force autoneg restart.
984 	 * Invalidate the saved "link partners received configs", as
985 	 * we're starting over ...
986 	 */
987 	drv_usecwait(10000);
988 	bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
989 	bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG, 0);
990 	bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
991 	drv_usecwait(10);
992 	bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
993 	bgep->serdes_lpadv = AUTONEG_CODE_FAULT_ANEG_ERR;
994 	bgep->serdes_status = ~0U;
995 	return (DDI_SUCCESS);
996 }
997 
998 /*
999  * Synchronise the SerDes speed/duplex/autonegotiation capabilities and
1000  * advertisements with the required settings as specified by the various
1001  * param_* variables that can be poked via the NDD interface.
1002  *
1003  * We always reinitalise the SerDes; this should cause the link to go down,
1004  * and then back up again once the link is stable and autonegotiation
1005  * (if enabled) is complete.  We should get a link state change interrupt
1006  * somewhere along the way ...
1007  *
1008  * NOTE: SerDes only supports 1000FDX/HDX (with or without pause) so the
1009  * param_* variables relating to lower speeds are ignored.
1010  *
1011  * NOTE: <genlock> must already be held by the caller
1012  */
1013 static int
1014 bge_update_serdes(bge_t *bgep)
1015 {
1016 	boolean_t adv_autoneg;
1017 	boolean_t adv_pause;
1018 	boolean_t adv_asym_pause;
1019 	boolean_t adv_1000fdx;
1020 	boolean_t adv_1000hdx;
1021 
1022 	uint32_t serdes;
1023 	uint32_t advert;
1024 
1025 	BGE_TRACE(("bge_update_serdes($%p)", (void *)bgep));
1026 
1027 	ASSERT(mutex_owned(bgep->genlock));
1028 
1029 	BGE_DEBUG(("bge_update_serdes: autoneg %d "
1030 			"pause %d asym_pause %d "
1031 			"1000fdx %d 1000hdx %d "
1032 			"100fdx %d 100hdx %d "
1033 			"10fdx %d 10hdx %d ",
1034 		bgep->param_adv_autoneg,
1035 		bgep->param_adv_pause, bgep->param_adv_asym_pause,
1036 		bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
1037 		bgep->param_adv_100fdx, bgep->param_adv_100hdx,
1038 		bgep->param_adv_10fdx, bgep->param_adv_10hdx));
1039 
1040 	serdes = advert = 0;
1041 
1042 	/*
1043 	 * SerDes settings are normally based on the param_* variables,
1044 	 * but if any loopback mode is in effect, that takes precedence.
1045 	 *
1046 	 * BGE supports MAC-internal loopback, PHY-internal loopback,
1047 	 * and External loopback at a variety of speeds (with a special
1048 	 * cable).  In all cases, autoneg is turned OFF, full-duplex
1049 	 * is turned ON, and the speed/mastership is forced.
1050 	 *
1051 	 * Note: for the SerDes interface, "PHY" internal loopback is
1052 	 * interpreted as SerDes internal loopback, and all external
1053 	 * loopback modes are treated equivalently, as 1Gb/external.
1054 	 */
1055 	switch (bgep->param_loop_mode) {
1056 	case BGE_LOOP_NONE:
1057 	default:
1058 		adv_autoneg = bgep->param_adv_autoneg;
1059 		adv_pause = bgep->param_adv_pause;
1060 		adv_asym_pause = bgep->param_adv_asym_pause;
1061 		adv_1000fdx = bgep->param_adv_1000fdx;
1062 		adv_1000hdx = bgep->param_adv_1000hdx;
1063 		break;
1064 
1065 	case BGE_LOOP_INTERNAL_PHY:
1066 		serdes |= SERDES_CONTROL_TBI_LOOPBACK;
1067 		/* FALLTHRU */
1068 	case BGE_LOOP_INTERNAL_MAC:
1069 	case BGE_LOOP_EXTERNAL_1000:
1070 	case BGE_LOOP_EXTERNAL_100:
1071 	case BGE_LOOP_EXTERNAL_10:
1072 		adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
1073 		adv_1000fdx = B_TRUE;
1074 		adv_1000hdx = B_FALSE;
1075 		break;
1076 	}
1077 
1078 	BGE_DEBUG(("bge_update_serdes: autoneg %d "
1079 			"pause %d asym_pause %d "
1080 			"1000fdx %d 1000hdx %d ",
1081 		adv_autoneg,
1082 		adv_pause, adv_asym_pause,
1083 		adv_1000fdx, adv_1000hdx));
1084 
1085 	/*
1086 	 * We should have at least one gigabit technology capability
1087 	 * set; if not, we select a default of 1000Mb/s full-duplex
1088 	 */
1089 	if (!adv_1000fdx && !adv_1000hdx)
1090 		adv_1000fdx = B_TRUE;
1091 
1092 	/*
1093 	 * Now transform the adv_* variables into the proper settings
1094 	 * of the SerDes registers ...
1095 	 *
1096 	 * If autonegotiation is (now) not enabled, pretend it's been
1097 	 * done and failed ...
1098 	 */
1099 	if (!adv_autoneg)
1100 		advert |= AUTONEG_CODE_FAULT_ANEG_ERR;
1101 
1102 	if (adv_1000fdx) {
1103 		advert |= AUTONEG_CODE_FULL_DUPLEX;
1104 		bgep->param_adv_1000fdx = adv_1000fdx;
1105 		bgep->param_link_duplex = LINK_DUPLEX_FULL;
1106 		bgep->param_link_speed = 1000;
1107 	}
1108 	if (adv_1000hdx) {
1109 		advert |= AUTONEG_CODE_HALF_DUPLEX;
1110 		bgep->param_adv_1000hdx = adv_1000hdx;
1111 		bgep->param_link_duplex = LINK_DUPLEX_HALF;
1112 		bgep->param_link_speed = 1000;
1113 	}
1114 
1115 	if (adv_pause)
1116 		advert |= AUTONEG_CODE_PAUSE;
1117 	if (adv_asym_pause)
1118 		advert |= AUTONEG_CODE_ASYM_PAUSE;
1119 
1120 	/*
1121 	 * Restart the SerDes and write the new values.  Note the
1122 	 * time, so that we can say whether subsequent link state
1123 	 * changes can be attributed to our reprogramming the SerDes
1124 	 */
1125 	bgep->serdes_advert = advert;
1126 	bgep->phys_write_time = gethrtime();
1127 	(void) bge_restart_serdes(bgep, B_FALSE);
1128 	bge_reg_set32(bgep, SERDES_CONTROL_REG, serdes);
1129 
1130 	BGE_DEBUG(("bge_update_serdes: serdes |= 0x%x, advert 0x%x",
1131 		serdes, advert));
1132 	return (DDI_SUCCESS);
1133 }
1134 
1135 /*
1136  * Bare-minimum autoneg protocol
1137  *
1138  * This code is only called when the link is up and we're receiving config
1139  * words, which implies that the link partner wants to autonegotiate
1140  * (otherwise, we wouldn't see configs and wouldn't reach this code).
1141  */
1142 static void
1143 bge_autoneg_serdes(bge_t *bgep)
1144 {
1145 	boolean_t ack;
1146 
1147 	bgep->serdes_lpadv = bge_reg_get32(bgep, RX_1000BASEX_AUTONEG_REG);
1148 	ack = BIS(bgep->serdes_lpadv, AUTONEG_CODE_ACKNOWLEDGE);
1149 
1150 	if (!ack) {
1151 		/*
1152 		 * Phase 1: after SerDes reset, we send a few zero configs
1153 		 * but then stop.  Here the partner is sending configs, but
1154 		 * not ACKing ours; we assume that's 'cos we're not sending
1155 		 * any.  So here we send ours, with ACK already set.
1156 		 */
1157 		bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG,
1158 			bgep->serdes_advert | AUTONEG_CODE_ACKNOWLEDGE);
1159 		bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG,
1160 			ETHERNET_MODE_SEND_CFGS);
1161 	} else {
1162 		/*
1163 		 * Phase 2: partner has ACKed our configs, so now we can
1164 		 * stop sending; once our partner also stops sending, we
1165 		 * can resolve the Tx/Rx configs.
1166 		 */
1167 		bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG,
1168 			ETHERNET_MODE_SEND_CFGS);
1169 	}
1170 
1171 	BGE_DEBUG(("bge_autoneg_serdes: Rx 0x%x %s Tx 0x%x",
1172 		bgep->serdes_lpadv,
1173 		ack ? "stop" : "send",
1174 		bgep->serdes_advert));
1175 }
1176 
1177 static boolean_t
1178 bge_check_serdes(bge_t *bgep, boolean_t recheck)
1179 {
1180 	uint32_t emac_status;
1181 	uint32_t lpadv;
1182 	boolean_t linkup;
1183 
1184 	for (;;) {
1185 		/*
1186 		 * Step 10: read & clear the main (Ethernet) MAC status
1187 		 * (the relevant bits of this are write-one-to-clear).
1188 		 */
1189 		emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
1190 		bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status);
1191 
1192 		BGE_DEBUG(("bge_check_serdes: link %d/%s, "
1193 				"MAC status 0x%x (was 0x%x)",
1194 			bgep->link_state, UPORDOWN(bgep->param_link_up),
1195 			emac_status, bgep->serdes_status));
1196 
1197 		/*
1198 		 * We will only consider the link UP if all the readings
1199 		 * are consistent and give meaningful results ...
1200 		 */
1201 		bgep->serdes_status = emac_status;
1202 		linkup = BIS(emac_status, ETHERNET_STATUS_SIGNAL_DETECT);
1203 		linkup &= BIS(emac_status, ETHERNET_STATUS_PCS_SYNCHED);
1204 
1205 		/*
1206 		 * Now some fiddling with the interpretation:
1207 		 *	if there's been an error at the PCS level, treat
1208 		 *	it as a link change (the h/w doesn't do this)
1209 		 *
1210 		 *	if there's been a change, but it's only a PCS sync
1211 		 *	change (not a config change), AND the link already
1212 		 *	was & is still UP, then ignore the change
1213 		 */
1214 		if (BIS(emac_status, ETHERNET_STATUS_PCS_ERROR))
1215 			emac_status |= ETHERNET_STATUS_LINK_CHANGED;
1216 		else if (BIC(emac_status, ETHERNET_STATUS_CFG_CHANGED))
1217 			if (bgep->param_link_up && linkup)
1218 				emac_status &= ~ETHERNET_STATUS_LINK_CHANGED;
1219 
1220 		BGE_DEBUG(("bge_check_serdes: status 0x%x => 0x%x %s",
1221 			bgep->serdes_status, emac_status, UPORDOWN(linkup)));
1222 
1223 		/*
1224 		 * If we're receiving configs, run the autoneg protocol
1225 		 */
1226 		if (linkup && BIS(emac_status, ETHERNET_STATUS_RECEIVING_CFG))
1227 			bge_autoneg_serdes(bgep);
1228 
1229 		/*
1230 		 * If the SerDes status hasn't changed, we're done ...
1231 		 */
1232 		if (BIC(emac_status, ETHERNET_STATUS_LINK_CHANGED))
1233 			break;
1234 
1235 		/*
1236 		 * Record when the SerDes status changed, then go
1237 		 * round again until we no longer see a change ...
1238 		 */
1239 		bgep->phys_event_time = gethrtime();
1240 		recheck = B_TRUE;
1241 	}
1242 
1243 	/*
1244 	 * If we're not forcing a recheck (i.e. the link state was already
1245 	 * known), and we didn't see the hardware flag a change, there's
1246 	 * no more to do (and we tell the caller nothing happened).
1247 	 */
1248 	if (!recheck)
1249 		return (B_FALSE);
1250 
1251 	/*
1252 	 * Don't resolve autoneg until we're no longer receiving configs
1253 	 */
1254 	if (linkup && BIS(emac_status, ETHERNET_STATUS_RECEIVING_CFG))
1255 		return (B_FALSE);
1256 
1257 	/*
1258 	 * Assume very little ...
1259 	 */
1260 	bgep->param_lp_autoneg = B_FALSE;
1261 	bgep->param_lp_1000fdx = B_FALSE;
1262 	bgep->param_lp_1000hdx = B_FALSE;
1263 	bgep->param_lp_100fdx = B_FALSE;
1264 	bgep->param_lp_100hdx = B_FALSE;
1265 	bgep->param_lp_10fdx = B_FALSE;
1266 	bgep->param_lp_10hdx = B_FALSE;
1267 	bgep->param_lp_pause = B_FALSE;
1268 	bgep->param_lp_asym_pause = B_FALSE;
1269 	bgep->param_link_autoneg = B_FALSE;
1270 	bgep->param_link_tx_pause = B_FALSE;
1271 	if (bgep->param_adv_autoneg)
1272 		bgep->param_link_rx_pause = B_FALSE;
1273 	else
1274 		bgep->param_link_rx_pause = bgep->param_adv_pause;
1275 
1276 	/*
1277 	 * Discover all the link partner's abilities.
1278 	 */
1279 	lpadv = bgep->serdes_lpadv;
1280 	if (lpadv != 0 && BIC(lpadv, AUTONEG_CODE_FAULT_MASK)) {
1281 		/*
1282 		 * No fault, so derive partner's capabilities
1283 		 */
1284 		bgep->param_lp_autoneg = B_TRUE;
1285 		bgep->param_lp_1000fdx = BIS(lpadv, AUTONEG_CODE_FULL_DUPLEX);
1286 		bgep->param_lp_1000hdx = BIS(lpadv, AUTONEG_CODE_HALF_DUPLEX);
1287 		bgep->param_lp_pause = BIS(lpadv, AUTONEG_CODE_PAUSE);
1288 		bgep->param_lp_asym_pause = BIS(lpadv, AUTONEG_CODE_ASYM_PAUSE);
1289 
1290 		/*
1291 		 * Pause direction resolution
1292 		 */
1293 		bgep->param_link_autoneg = B_TRUE;
1294 		if (bgep->param_adv_pause &&
1295 		    bgep->param_lp_pause) {
1296 			bgep->param_link_tx_pause = B_TRUE;
1297 			bgep->param_link_rx_pause = B_TRUE;
1298 		}
1299 		if (bgep->param_adv_asym_pause &&
1300 		    bgep->param_lp_asym_pause) {
1301 			if (bgep->param_adv_pause)
1302 				bgep->param_link_rx_pause = B_TRUE;
1303 			if (bgep->param_lp_pause)
1304 				bgep->param_link_tx_pause = B_TRUE;
1305 		}
1306 	}
1307 
1308 	/*
1309 	 * Step 12: update ndd-visible state parameters, BUT!
1310 	 * we don't transfer the new state to <link_state> just yet;
1311 	 * instead we mark the <link_state> as UNKNOWN, and our caller
1312 	 * will resolve it once the status has stopped changing and
1313 	 * been stable for several seconds.
1314 	 */
1315 	BGE_DEBUG(("bge_check_serdes: link was %s speed %d duplex %d",
1316 		UPORDOWN(bgep->param_link_up),
1317 		bgep->param_link_speed,
1318 		bgep->param_link_duplex));
1319 
1320 	if (linkup) {
1321 		bgep->param_link_up = B_TRUE;
1322 		bgep->param_link_speed = 1000;
1323 		if (bgep->param_adv_1000fdx)
1324 			bgep->param_link_duplex = LINK_DUPLEX_FULL;
1325 		else
1326 			bgep->param_link_duplex = LINK_DUPLEX_HALF;
1327 		if (bgep->param_lp_autoneg && !bgep->param_lp_1000fdx)
1328 			bgep->param_link_duplex = LINK_DUPLEX_HALF;
1329 	} else {
1330 		bgep->param_link_up = B_FALSE;
1331 		bgep->param_link_speed = 0;
1332 		bgep->param_link_duplex = LINK_DUPLEX_UNKNOWN;
1333 	}
1334 	switch (bgep->param_link_duplex) {
1335 	default:
1336 	case LINK_DUPLEX_UNKNOWN:
1337 		bgep->link_mode_msg = "down";
1338 		break;
1339 
1340 	case LINK_DUPLEX_HALF:
1341 		bgep->link_mode_msg = "up 1000Mbps Half-Duplex";
1342 		break;
1343 
1344 	case LINK_DUPLEX_FULL:
1345 		bgep->link_mode_msg = "up 1000Mbps Full-Duplex";
1346 		break;
1347 	}
1348 	bgep->link_state = LINK_STATE_UNKNOWN;
1349 
1350 	BGE_DEBUG(("bge_check_serdes: link now %s speed %d duplex %d",
1351 		UPORDOWN(bgep->param_link_up),
1352 		bgep->param_link_speed,
1353 		bgep->param_link_duplex));
1354 
1355 	return (B_TRUE);
1356 }
1357 
1358 static const phys_ops_t serdes_ops = {
1359 	bge_restart_serdes,
1360 	bge_update_serdes,
1361 	bge_check_serdes
1362 };
1363 
1364 /*
1365  * ========== Exported physical layer control routines ==========
1366  */
1367 
1368 #undef	BGE_DBG
1369 #define	BGE_DBG		BGE_DBG_PHYS	/* debug flag for this code	*/
1370 
1371 /*
1372  * Here we have to determine which media we're using (copper or serdes).
1373  * Once that's done, we can initialise the physical layer appropriately.
1374  */
1375 int
1376 bge_phys_init(bge_t *bgep)
1377 {
1378 	BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
1379 
1380 	mutex_enter(bgep->genlock);
1381 
1382 	/*
1383 	 * Probe for the (internal) PHY.  If it's not there, we'll assume
1384 	 * that this is a 5703/4S, with a SerDes interface rather than
1385 	 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
1386 	 * BCM800x PHY.
1387 	 */
1388 	bgep->phy_mii_addr = 1;
1389 	if (bge_phy_probe(bgep)) {
1390 		bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
1391 		bgep->phys_delta_time = BGE_PHY_STABLE_TIME;
1392 		bgep->physops = &copper_ops;
1393 	} else {
1394 		bgep->chipid.flags |= CHIP_FLAG_SERDES;
1395 		bgep->phys_delta_time = BGE_SERDES_STABLE_TIME;
1396 		bgep->physops = &serdes_ops;
1397 	}
1398 
1399 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
1400 		mutex_exit(bgep->genlock);
1401 		return (EIO);
1402 	}
1403 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
1404 		mutex_exit(bgep->genlock);
1405 		return (EIO);
1406 	}
1407 	mutex_exit(bgep->genlock);
1408 	return (0);
1409 }
1410 
1411 /*
1412  * Reset the physical layer
1413  */
1414 void
1415 bge_phys_reset(bge_t *bgep)
1416 {
1417 	BGE_TRACE(("bge_phys_reset($%p)", (void *)bgep));
1418 
1419 	mutex_enter(bgep->genlock);
1420 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS)
1421 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1422 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
1423 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1424 	mutex_exit(bgep->genlock);
1425 }
1426 
1427 /*
1428  * Reset and power off the physical layer.
1429  *
1430  * Another RESET should get it back to working, but it may take a few
1431  * seconds it may take a few moments to return to normal operation ...
1432  */
1433 int
1434 bge_phys_idle(bge_t *bgep)
1435 {
1436 	BGE_TRACE(("bge_phys_idle($%p)", (void *)bgep));
1437 
1438 	ASSERT(mutex_owned(bgep->genlock));
1439 	return ((*bgep->physops->phys_restart)(bgep, B_TRUE));
1440 }
1441 
1442 /*
1443  * Synchronise the PHYSICAL layer's speed/duplex/autonegotiation capabilities
1444  * and advertisements with the required settings as specified by the various
1445  * param_* variables that can be poked via the NDD interface.
1446  *
1447  * We always reset the PHYSICAL layer and reprogram *all* relevant registers.
1448  * This is expected to cause the link to go down, and then back up again once
1449  * the link is stable and autonegotiation (if enabled) is complete.  We should
1450  * get a link state change interrupt somewhere along the way ...
1451  *
1452  * NOTE: <genlock> must already be held by the caller
1453  */
1454 int
1455 bge_phys_update(bge_t *bgep)
1456 {
1457 	BGE_TRACE(("bge_phys_update($%p)", (void *)bgep));
1458 
1459 	ASSERT(mutex_owned(bgep->genlock));
1460 	return ((*bgep->physops->phys_update)(bgep));
1461 }
1462 
1463 #undef	BGE_DBG
1464 #define	BGE_DBG		BGE_DBG_LINK	/* debug flag for this code	*/
1465 
1466 /*
1467  * Read the link status and determine whether anything's changed ...
1468  *
1469  * This routine should be called whenever the chip flags a change
1470  * in the hardware link state, and repeatedly for several seconds
1471  * afterwards, until we're sure the state has stabilised (sometimes
1472  * it goes up and down several times during autonegotiation before
1473  * settling on the proper configuration).  This routine applies
1474  * timing-based heuristics to determine when the state is stable.
1475  *
1476  * This routine returns B_FALSE if the link state has not changed,
1477  * or if it has changed, but hasn't settled for long enough yet.  It
1478  * returns B_TRUE when the change to the new state should be accepted.
1479  * In such a case, the param_* variables give the new hardware state,
1480  * which the caller should use to update link_state etc.
1481  *
1482  * The caller must already hold <genlock>
1483  */
1484 boolean_t
1485 bge_phys_check(bge_t *bgep)
1486 {
1487 	int32_t orig_state;
1488 	boolean_t recheck;
1489 	boolean_t linkup;
1490 	hrtime_t deltat;
1491 	hrtime_t now;
1492 
1493 	BGE_TRACE(("bge_phys_check($%p)", (void *)bgep));
1494 
1495 	ASSERT(mutex_owned(bgep->genlock));
1496 
1497 	linkup = bgep->param_link_up;
1498 	orig_state = bgep->link_state;
1499 	recheck = orig_state == LINK_STATE_UNKNOWN;
1500 	recheck = (*bgep->physops->phys_check)(bgep, recheck);
1501 	if (!recheck)
1502 		return (B_FALSE);
1503 
1504 	/*
1505 	 * At this point, the check_*_link() function above has detected
1506 	 * a change and updated the param_* variables to show what the
1507 	 * latest hardware state seems to be -- but it might still be
1508 	 * changing.
1509 	 *
1510 	 * The link_state must now be UNKNOWN, but if it was previously
1511 	 * UP, we want to recognise this immediately, whereas in any other
1512 	 * case (e.g. DOWN->UP) we don't accept it until a few seconds have
1513 	 * elapsed, to give the hardware time to settle.
1514 	 */
1515 	now = gethrtime();
1516 	deltat = now - bgep->phys_event_time;
1517 
1518 	BGE_DEBUG(("bge_phys_check: link was %d/%s now %d/%s",
1519 		orig_state, UPORDOWN(linkup),
1520 		bgep->link_state, UPORDOWN(bgep->param_link_up)));
1521 	BGE_DEBUG(("bge_phys_check: update %lld change %lld "
1522 			"now %lld delta %lld",
1523 		bgep->phys_write_time, bgep->phys_event_time, now, deltat));
1524 
1525 	if (orig_state == LINK_STATE_UP)
1526 		return (B_TRUE);
1527 	else
1528 		return (deltat > bgep->phys_delta_time);
1529 }
1530