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