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