xref: /titanic_44/usr/src/uts/common/io/bge/bge_mii.c (revision 98573c1925f3692d1e8ea9eb018cb915fc0becc5)
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 (c) 2010-2013, by Broadcom, Inc.
24  * All Rights Reserved.
25  */
26 
27 /*
28  * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
29  * All rights reserved.
30  */
31 
32 #include "bge_impl.h"
33 
34 /*
35  * Bit test macros, returning boolean_t values
36  */
37 #define	BIS(w, b)	(((w) & (b)) ? B_TRUE : B_FALSE)
38 #define	BIC(w, b)	(((w) & (b)) ? B_FALSE : B_TRUE)
39 #define	UPORDOWN(x)	((x) ? "up" : "down")
40 
41 /*
42  * ========== Copper (PHY) support ==========
43  */
44 
45 #define	BGE_DBG		BGE_DBG_PHY	/* debug flag for this code	*/
46 
47 /*
48  * #defines:
49  *	BGE_COPPER_WIRESPEED controls whether the Broadcom WireSpeed(tm)
50  *	feature is enabled.  We need to recheck whether this can be
51  *	enabled; at one time it seemed to interact unpleasantly with the
52  *	loopback modes.
53  *
54  *	BGE_COPPER_IDLEOFF controls whether the (copper) PHY power is
55  *	turned off when the PHY is idled i.e. during driver suspend().
56  *	For now this is disabled because the chip doesn't seem to
57  *	resume cleanly if the PHY power is turned off.
58  */
59 #define	BGE_COPPER_WIRESPEED	B_TRUE
60 #define	BGE_COPPER_IDLEOFF	B_FALSE
61 
62 /*
63  * The arrays below can be indexed by the MODE bits from the Auxiliary
64  * Status register to determine the current speed/duplex settings.
65  */
66 static const int16_t bge_copper_link_speed[] = {
67 	0,				/* MII_AUX_STATUS_MODE_NONE	*/
68 	10,				/* MII_AUX_STATUS_MODE_10_H	*/
69 	10,				/* MII_AUX_STATUS_MODE_10_F	*/
70 	100,				/* MII_AUX_STATUS_MODE_100_H	*/
71 	0,				/* MII_AUX_STATUS_MODE_100_4	*/
72 	100,				/* MII_AUX_STATUS_MODE_100_F	*/
73 	1000,				/* MII_AUX_STATUS_MODE_1000_H	*/
74 	1000				/* MII_AUX_STATUS_MODE_1000_F	*/
75 };
76 
77 static const int8_t bge_copper_link_duplex[] = {
78 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_NONE	*/
79 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_10_H	*/
80 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_10_F	*/
81 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_100_H	*/
82 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_100_4	*/
83 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_100_F	*/
84 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_1000_H	*/
85 	LINK_DUPLEX_FULL		/* MII_AUX_STATUS_MODE_1000_F	*/
86 };
87 
88 static const int16_t bge_copper_link_speed_5906[] = {
89 	0,				/* MII_AUX_STATUS_MODE_NONE	*/
90 	10,				/* MII_AUX_STATUS_MODE_10_H	*/
91 	10,				/* MII_AUX_STATUS_MODE_10_F	*/
92 	100,				/* MII_AUX_STATUS_MODE_100_H	*/
93 	0,				/* MII_AUX_STATUS_MODE_100_4	*/
94 	100,				/* MII_AUX_STATUS_MODE_100_F	*/
95 	0,				/* MII_AUX_STATUS_MODE_1000_H	*/
96 	0				/* MII_AUX_STATUS_MODE_1000_F	*/
97 };
98 
99 static const int8_t bge_copper_link_duplex_5906[] = {
100 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_NONE	*/
101 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_10_H	*/
102 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_10_F	*/
103 	LINK_DUPLEX_HALF,		/* MII_AUX_STATUS_MODE_100_H	*/
104 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_100_4	*/
105 	LINK_DUPLEX_FULL,		/* MII_AUX_STATUS_MODE_100_F	*/
106 	LINK_DUPLEX_UNKNOWN,		/* MII_AUX_STATUS_MODE_1000_H	*/
107 	LINK_DUPLEX_UNKNOWN		/* MII_AUX_STATUS_MODE_1000_F	*/
108 };
109 
110 #if	BGE_DEBUGGING
111 
112 static void
113 bge_phydump(bge_t *bgep, uint16_t mii_status, uint16_t aux)
114 {
115 	uint16_t regs[32];
116 	int i;
117 
118 	ASSERT(mutex_owned(bgep->genlock));
119 
120 	for (i = 0; i < 32; ++i)
121 		switch (i) {
122 		default:
123 			regs[i] = bge_mii_get16(bgep, i);
124 			break;
125 
126 		case MII_STATUS:
127 			regs[i] = mii_status;
128 			break;
129 
130 		case MII_AUX_STATUS:
131 			regs[i] = aux;
132 			break;
133 
134 		case 0x0b: case 0x0c: case 0x0d: case 0x0e:
135 		case 0x15: case 0x16: case 0x17:
136 		case 0x1c:
137 		case 0x1f:
138 			/* reserved registers -- don't read these */
139 			regs[i] = 0;
140 			break;
141 		}
142 
143 	for (i = 0; i < 32; i += 8)
144 		BGE_DEBUG(("bge_phydump: "
145 		    "0x%04x %04x %04x %04x %04x %04x %04x %04x",
146 		    regs[i+0], regs[i+1], regs[i+2], regs[i+3],
147 		    regs[i+4], regs[i+5], regs[i+6], regs[i+7]));
148 }
149 
150 #endif	/* BGE_DEBUGGING */
151 
152 static void
153 bge_phy_toggle_auxctl_smdsp(bge_t *bgep,
154                             boolean_t enable)
155 {
156 	uint16_t val;
157 
158 	val = bge_mii_get16(bgep, MII_AUX_CONTROL);
159 
160 	if (enable) {
161 		val |= MII_AUX_CTRL_SMDSP_ENA;
162 	} else {
163 		val &= ~MII_AUX_CTRL_SMDSP_ENA;
164 	}
165 
166 	bge_mii_put16(bgep, MII_AUX_CONTROL, (val | MII_AUX_CTRL_TX_6DB));
167 }
168 
169 /*
170  * Basic low-level function to probe for a PHY
171  *
172  * Returns TRUE if the PHY responds with valid data, FALSE otherwise
173  */
174 static boolean_t
175 bge_phy_probe(bge_t *bgep)
176 {
177 	uint16_t miicfg;
178 	uint32_t nicsig, niccfg;
179 	int i;
180 
181 	BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep));
182 
183 	ASSERT(mutex_owned(bgep->genlock));
184 
185 	nicsig = bge_nic_read32(bgep, BGE_NIC_DATA_SIG_ADDR);
186 	if (nicsig == BGE_NIC_DATA_SIG) {
187 		niccfg = bge_nic_read32(bgep, BGE_NIC_DATA_NIC_CFG_ADDR);
188 		switch (niccfg & BGE_NIC_CFG_PHY_TYPE_MASK) {
189 		default:
190 		case BGE_NIC_CFG_PHY_TYPE_COPPER:
191 			return (B_TRUE);
192 		case BGE_NIC_CFG_PHY_TYPE_FIBER:
193 			return (B_FALSE);
194 		}
195 	} else {
196 		/*
197 		 * Read the MII_STATUS register twice, in
198 		 * order to clear any sticky bits (but they should
199 		 * have been cleared by the RESET, I think).
200 		 */
201 		for (i = 0; i < 100; i++) {
202 			drv_usecwait(40);
203 			miicfg = bge_mii_get16(bgep, MII_STATUS);
204 		}
205 		BGE_DEBUG(("bge_phy_probe: status 0x%x", miicfg));
206 
207 		/*
208 		 * Now check the value read; it should have at least one bit set
209 		 * (for the device capabilities) and at least one clear (one of
210 		 * the error bits). So if we see all 0s or all 1s, there's a
211 		 * problem.  In particular, bge_mii_get16() returns all 1s if
212 		 * communications fails ...
213 		 */
214 		switch (miicfg) {
215 		case 0x0000:
216 		case 0xffff:
217 			return (B_FALSE);
218 
219 		default:
220 			return (B_TRUE);
221 		}
222 	}
223 }
224 
225 /*
226  * Basic low-level function to reset the PHY.
227  * Doesn't incorporate any special-case workarounds.
228  *
229  * Returns TRUE on success, FALSE if the RESET bit doesn't clear
230  */
231 static boolean_t
232 bge_phy_reset(bge_t *bgep)
233 {
234 	uint16_t control;
235 	uint_t count;
236 
237 	BGE_TRACE(("bge_phy_reset($%p)", (void *)bgep));
238 
239 	ASSERT(mutex_owned(bgep->genlock));
240 
241 	if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
242 		drv_usecwait(40);
243 		/* put PHY into ready state */
244 		bge_reg_clr32(bgep, MISC_CONFIG_REG, MISC_CONFIG_EPHY_IDDQ);
245 		(void) bge_reg_get32(bgep, MISC_CONFIG_REG); /* flush */
246 		drv_usecwait(40);
247 	}
248 
249 	/*
250 	 * Set the PHY RESET bit, then wait up to 5 ms for it to self-clear
251 	 */
252 	bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_RESET);
253 	for (count = 0; ++count < 1000; ) {
254 		drv_usecwait(5);
255 		control = bge_mii_get16(bgep, MII_CONTROL);
256 		if (BIC(control, MII_CONTROL_RESET))
257 			return (B_TRUE);
258 	}
259 
260 	if (DEVICE_5906_SERIES_CHIPSETS(bgep))
261 		(void) bge_adj_volt_5906(bgep);
262 
263 	BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
264 
265 	return (B_FALSE);
266 }
267 
268 /*
269  * Basic low-level function to powerdown the PHY, if supported
270  * If powerdown support is compiled out, this function does nothing.
271  */
272 static void
273 bge_phy_powerdown(bge_t *bgep)
274 {
275 	BGE_TRACE(("bge_phy_powerdown"));
276 #if	BGE_COPPER_IDLEOFF
277 	bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_PWRDN);
278 #endif	/* BGE_COPPER_IDLEOFF */
279 }
280 
281 /*
282  * The following functions are based on sample code provided by
283  * Broadcom (20-June-2003), and implement workarounds said to be
284  * required on the early revisions of the BCM5703/4C.
285  *
286  * The registers and values used are mostly UNDOCUMENTED, and
287  * therefore don't have symbolic names ;-(
288  *
289  * Many of the comments are straight out of the Broadcom code:
290  * even where the code has been restructured, the original
291  * comments have been preserved in order to explain what these
292  * undocumented registers & values are all about ...
293  */
294 
295 static void
296 bge_phy_macro_wait(bge_t *bgep)
297 {
298 	uint_t count;
299 
300 	for (count = 100; --count; )
301 		if ((bge_mii_get16(bgep, 0x16) & 0x1000) == 0)
302 			break;
303 }
304 
305 /*
306  * PHY test data pattern:
307  *
308  * For 5703/04, each DFE TAP has 21-bits (low word 15, hi word 6)
309  * For 5705,    each DFE TAP has 19-bits (low word 15, hi word 4)
310  * For simplicity, we check only 19-bits, so we don't have to
311  * distinguish which chip it is.
312  * the LO word contains 15 bits, make sure pattern data is < 0x7fff
313  * the HI word contains  6 bits, make sure pattern data is < 0x003f
314  */
315 #define	N_CHANNELS	4
316 #define	N_TAPS		3
317 
318 static struct {
319 	uint16_t	lo;
320 	uint16_t	hi;
321 } tap_data[N_CHANNELS][N_TAPS] = {
322 	{
323 		{ 0x5555, 0x0005 },	/* ch0, TAP 0, LO/HI pattern */
324 		{ 0x2aaa, 0x000a },	/* ch0, TAP 1, LO/HI pattern */
325 		{ 0x3456, 0x0003 }	/* ch0, TAP 2, LO/HI pattern */
326 	},
327 	{
328 		{ 0x2aaa, 0x000a },	/* ch1, TAP 0, LO/HI pattern */
329 		{ 0x3333, 0x0003 },	/* ch1, TAP 1, LO/HI pattern */
330 		{ 0x789a, 0x0005 }	/* ch1, TAP 2, LO/HI pattern */
331 	},
332 	{
333 		{ 0x5a5a, 0x0005 },	/* ch2, TAP 0, LO/HI pattern */
334 		{ 0x2a6a, 0x000a },	/* ch2, TAP 1, LO/HI pattern */
335 		{ 0x1bcd, 0x0003 }	/* ch2, TAP 2, LO/HI pattern */
336 	},
337 	{
338 		{ 0x2a5a, 0x000a },	/* ch3, TAP 0, LO/HI pattern */
339 		{ 0x33c3, 0x0003 },	/* ch3, TAP 1, LO/HI pattern */
340 		{ 0x2ef1, 0x0005 }	/* ch3, TAP 2, LO/HI pattern */
341 	}
342 };
343 
344 /*
345  * Check whether the PHY has locked up after a RESET.
346  *
347  * Returns TRUE if it did, FALSE is it's OK ;-)
348  */
349 static boolean_t
350 bge_phy_locked_up(bge_t *bgep)
351 {
352 	uint16_t dataLo;
353 	uint16_t dataHi;
354 	uint_t chan;
355 	uint_t tap;
356 
357 	/*
358 	 * Check TAPs for all 4 channels, as soon as we see a lockup
359 	 * we'll stop checking.
360 	 */
361 	for (chan = 0; chan < N_CHANNELS; ++chan) {
362 		/* Select channel and set TAP index to 0 */
363 		bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
364 		/* Freeze filter again just to be safe */
365 		bge_mii_put16(bgep, 0x16, 0x0002);
366 
367 		/*
368 		 * Write fixed pattern to the RAM, 3 TAPs for
369 		 * each channel, each TAP have 2 WORDs (LO/HI)
370 		 */
371 		for (tap = 0; tap < N_TAPS; ++tap) {
372 			bge_mii_put16(bgep, 0x15, tap_data[chan][tap].lo);
373 			bge_mii_put16(bgep, 0x15, tap_data[chan][tap].hi);
374 		}
375 
376 		/*
377 		 * Active PHY's Macro operation to write DFE
378 		 * TAP from RAM, and wait for Macro to complete.
379 		 */
380 		bge_mii_put16(bgep, 0x16, 0x0202);
381 		bge_phy_macro_wait(bgep);
382 
383 		/*
384 		 * Done with write phase, now begin read phase.
385 		 */
386 
387 		/* Select channel and set TAP index to 0 */
388 		bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
389 
390 		/*
391 		 * Active PHY's Macro operation to load DFE
392 		 * TAP to RAM, and wait for Macro to complete
393 		 */
394 		bge_mii_put16(bgep, 0x16, 0x0082);
395 		bge_phy_macro_wait(bgep);
396 
397 		/* Enable "pre-fetch" */
398 		bge_mii_put16(bgep, 0x16, 0x0802);
399 		bge_phy_macro_wait(bgep);
400 
401 		/*
402 		 * Read back the TAP values.  3 TAPs for each
403 		 * channel, each TAP have 2 WORDs (LO/HI)
404 		 */
405 		for (tap = 0; tap < N_TAPS; ++tap) {
406 			/*
407 			 * Read Lo/Hi then wait for 'done' is faster.
408 			 * For DFE TAP, the HI word contains 6 bits,
409 			 * LO word contains 15 bits
410 			 */
411 			dataLo = bge_mii_get16(bgep, 0x15) & 0x7fff;
412 			dataHi = bge_mii_get16(bgep, 0x15) & 0x003f;
413 			bge_phy_macro_wait(bgep);
414 
415 			/*
416 			 * Check if what we wrote is what we read back.
417 			 * If failed, then the PHY is locked up, we need
418 			 * to do PHY reset again
419 			 */
420 			if (dataLo != tap_data[chan][tap].lo)
421 				return (B_TRUE);	/* wedged!	*/
422 
423 			if (dataHi != tap_data[chan][tap].hi)
424 				return (B_TRUE);	/* wedged!	*/
425 		}
426 	}
427 
428 	/*
429 	 * The PHY isn't locked up ;-)
430 	 */
431 	return (B_FALSE);
432 }
433 
434 /*
435  * Special-case code to reset the PHY on the 5702/5703/5704C/5705/5782.
436  * Tries up to 5 times to recover from failure to reset or PHY lockup.
437  *
438  * Returns TRUE on success, FALSE if there's an unrecoverable problem
439  */
440 static boolean_t
441 bge_phy_reset_and_check(bge_t *bgep)
442 {
443 	boolean_t reset_success;
444 	boolean_t phy_locked;
445 	uint16_t extctrl;
446 	uint16_t gigctrl;
447 	uint_t retries;
448 
449 	for (retries = 0; retries < 5; ++retries) {
450 		/* Issue a phy reset, and wait for reset to complete */
451 		/* Assuming reset is successful first */
452 		reset_success = bge_phy_reset(bgep);
453 
454 		/*
455 		 * Now go check the DFE TAPs to see if locked up, but
456 		 * first, we need to set up PHY so we can read DFE
457 		 * TAPs.
458 		 */
459 
460 		/*
461 		 * Disable Transmitter and Interrupt, while we play
462 		 * with the PHY registers, so the link partner won't
463 		 * see any strange data and the Driver won't see any
464 		 * interrupts.
465 		 */
466 		extctrl = bge_mii_get16(bgep, 0x10);
467 		bge_mii_put16(bgep, 0x10, extctrl | 0x3000);
468 
469 		/* Setup Full-Duplex, 1000 mbps */
470 		bge_mii_put16(bgep, 0x0, 0x0140);
471 
472 		/* Set to Master mode */
473 		gigctrl = bge_mii_get16(bgep, 0x9);
474 		bge_mii_put16(bgep, 0x9, 0x1800);
475 
476 		/* Enable SM_DSP_CLOCK & 6dB */
477 		bge_mii_put16(bgep, 0x18, 0x0c00);	/* "the ADC fix" */
478 
479 		/* Work-arounds */
480 		bge_mii_put16(bgep, 0x17, 0x201f);
481 		bge_mii_put16(bgep, 0x15, 0x2aaa);
482 
483 		/* More workarounds */
484 		bge_mii_put16(bgep, 0x17, 0x000a);
485 		bge_mii_put16(bgep, 0x15, 0x0323);	/* "the Gamma fix" */
486 
487 		/* Blocks the PHY control access */
488 		bge_mii_put16(bgep, 0x17, 0x8005);
489 		bge_mii_put16(bgep, 0x15, 0x0800);
490 
491 		/* Test whether PHY locked up ;-( */
492 		phy_locked = bge_phy_locked_up(bgep);
493 		if (reset_success && !phy_locked)
494 			break;
495 
496 		/*
497 		 * Some problem here ... log it & retry
498 		 */
499 		if (!reset_success)
500 			BGE_REPORT((bgep, "PHY didn't reset!"));
501 		if (phy_locked)
502 			BGE_REPORT((bgep, "PHY locked up!"));
503 	}
504 
505 	/* Remove block phy control */
506 	bge_mii_put16(bgep, 0x17, 0x8005);
507 	bge_mii_put16(bgep, 0x15, 0x0000);
508 
509 	/* Unfreeze DFE TAP filter for all channels */
510 	bge_mii_put16(bgep, 0x17, 0x8200);
511 	bge_mii_put16(bgep, 0x16, 0x0000);
512 
513 	/* Restore PHY back to operating state */
514 	bge_mii_put16(bgep, 0x18, 0x0400);
515 
516 	/* Restore 1000BASE-T Control Register */
517 	bge_mii_put16(bgep, 0x9, gigctrl);
518 
519 	/* Enable transmitter and interrupt */
520 	extctrl = bge_mii_get16(bgep, 0x10);
521 	bge_mii_put16(bgep, 0x10, extctrl & ~0x3000);
522 
523 	if (DEVICE_5906_SERIES_CHIPSETS(bgep))
524 		(void) bge_adj_volt_5906(bgep);
525 
526 	if (!reset_success)
527 		bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
528 	else if (phy_locked)
529 		bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
530 	return (reset_success && !phy_locked);
531 }
532 
533 static void
534 bge_phy_tweak_gmii(bge_t *bgep)
535 {
536 	/* Tweak GMII timing */
537 	bge_mii_put16(bgep, 0x1c, 0x8d68);
538 	bge_mii_put16(bgep, 0x1c, 0x8d68);
539 }
540 
541 /* Bit Error Rate reduction fix */
542 static void
543 bge_phy_bit_err_fix(bge_t *bgep)
544 {
545 	bge_mii_put16(bgep, 0x18, 0x0c00);
546 	bge_mii_put16(bgep, 0x17, 0x000a);
547 	bge_mii_put16(bgep, 0x15, 0x310b);
548 	bge_mii_put16(bgep, 0x17, 0x201f);
549 	bge_mii_put16(bgep, 0x15, 0x9506);
550 	bge_mii_put16(bgep, 0x17, 0x401f);
551 	bge_mii_put16(bgep, 0x15, 0x14e2);
552 	bge_mii_put16(bgep, 0x18, 0x0400);
553 }
554 
555 /*
556  * End of Broadcom-derived workaround code
557  */
558 
559 static int
560 bge_restart_copper(bge_t *bgep, boolean_t powerdown)
561 {
562 	uint16_t phy_status;
563 	boolean_t reset_ok;
564 	uint16_t extctrl, auxctrl;
565 	int i;
566 
567 	BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
568 
569 	ASSERT(mutex_owned(bgep->genlock));
570 
571 	switch (MHCR_CHIP_ASIC_REV(bgep)) {
572 	default:
573 		/*
574 		 * Shouldn't happen; it means we don't recognise this chip.
575 		 * It's probably a new one, so we'll try our best anyway ...
576 		 */
577 	case MHCR_CHIP_ASIC_REV_5703:
578 	case MHCR_CHIP_ASIC_REV_5704:
579 	case MHCR_CHIP_ASIC_REV_5705:
580 	case MHCR_CHIP_ASIC_REV_5752:
581 	case MHCR_CHIP_ASIC_REV_5714:
582 	case MHCR_CHIP_ASIC_REV_5715:
583 		reset_ok = bge_phy_reset_and_check(bgep);
584 		break;
585 
586 	case MHCR_CHIP_ASIC_REV_5906:
587 	case MHCR_CHIP_ASIC_REV_5700:
588 	case MHCR_CHIP_ASIC_REV_5701:
589 	case MHCR_CHIP_ASIC_REV_5723: /* 5717 and 5725 series as well */
590 	case MHCR_CHIP_ASIC_REV_5721_5751:
591 		/*
592 		 * Just a plain reset; the "check" code breaks these chips
593 		 */
594 		reset_ok = bge_phy_reset(bgep);
595 		if (!reset_ok)
596 			bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
597 		break;
598 	}
599 	if (!reset_ok) {
600 		BGE_REPORT((bgep, "PHY failed to reset correctly"));
601 		return (DDI_FAILURE);
602 	}
603 
604 	/*
605 	 * Step 5: disable WOL (not required after RESET)
606 	 *
607 	 * Step 6: refer to errata
608 	 */
609 	switch (bgep->chipid.asic_rev) {
610 	default:
611 		break;
612 
613 	case MHCR_CHIP_REV_5704_A0:
614 		bge_phy_tweak_gmii(bgep);
615 		break;
616 	}
617 
618 	switch (MHCR_CHIP_ASIC_REV(bgep)) {
619 	case MHCR_CHIP_ASIC_REV_5705:
620 	case MHCR_CHIP_ASIC_REV_5721_5751:
621 		bge_phy_bit_err_fix(bgep);
622 		break;
623 	}
624 
625 	if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) &&
626 	    (bgep->chipid.default_mtu > BGE_DEFAULT_MTU)) {
627 		/* Set the GMII Fifo Elasticity to high latency */
628 		extctrl = bge_mii_get16(bgep, 0x10);
629 		bge_mii_put16(bgep, 0x10, extctrl | 0x1);
630 
631 		/* Allow reception of extended length packets */
632 		bge_mii_put16(bgep, MII_AUX_CONTROL, 0x0007);
633 		auxctrl = bge_mii_get16(bgep, MII_AUX_CONTROL);
634 		auxctrl |= 0x4000;
635 		bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
636 	}
637 
638 	/*
639 	 * Step 7: read the MII_INTR_STATUS register twice,
640 	 * in order to clear any sticky bits (but they should
641 	 * have been cleared by the RESET, I think), and we're
642 	 * not using PHY interrupts anyway.
643 	 *
644 	 * Step 8: enable the PHY to interrupt on link status
645 	 * change (not required)
646 	 *
647 	 * Step 9: configure PHY LED Mode - not applicable?
648 	 *
649 	 * Step 10: read the MII_STATUS register twice, in
650 	 * order to clear any sticky bits (but they should
651 	 * have been cleared by the RESET, I think).
652 	 */
653 	for (i = 0; i < 100; i++) {
654 		drv_usecwait(40);
655 		phy_status = bge_mii_get16(bgep, MII_STATUS);
656 	}
657 	BGE_DEBUG(("bge_restart_copper: status 0x%x", phy_status));
658 
659 	/*
660 	 * Finally, shut down the PHY, if required
661 	 */
662 	if (powerdown)
663 		bge_phy_powerdown(bgep);
664 	return (DDI_SUCCESS);
665 }
666 
667 boolean_t
668 bge_eee_cap(bge_t * bgep)
669 {
670 	if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
671 	    DEVICE_5725_SERIES_CHIPSETS(bgep))) {
672 		/* EEE is not supported on this chip */
673 		BGE_DEBUG(("bge_eee: eee not supported (device 0x%x)",
674 		    bgep->chipid.device));
675 		return (B_FALSE);
676 	}
677 
678 	switch (CHIP_ASIC_REV_PROD_ID(bgep)) {
679 	case CHIP_ASIC_REV_5717_B0: /* = CHIP_ASIC_REV_5718_B0 */
680 	case CHIP_ASIC_REV_5717_C0:
681 	/* case CHIP_ASIC_REV_5718_B0: */
682 	case CHIP_ASIC_REV_5719_A0:
683 	case CHIP_ASIC_REV_5719_A1:
684 	case CHIP_ASIC_REV_5720_A0:
685 	case CHIP_ASIC_REV_5725_A0:
686 	case CHIP_ASIC_REV_5727_B0:
687 		return (B_TRUE);
688 
689 	default:
690 		/* EEE is not supported on this asic rev */
691 		BGE_DEBUG(("bge_eee: eee not supported (asic rev 0x%08x)",
692 		    bgep->chipid.asic_rev));
693 		return (B_FALSE);
694 	}
695 }
696 
697 void
698 bge_eee_init(bge_t * bgep)
699 {
700 	uint32_t val;
701 
702 	BGE_TRACE(("bge_eee_init($%p)", (void *)bgep));
703 
704 	ASSERT(mutex_owned(bgep->genlock));
705 
706 	if (!bge_eee_cap(bgep)) {
707 		return;
708 	}
709 
710 	/* Enable MAC control of LPI */
711 
712 	val = (EEE_LINK_IDLE_PCIE_NL0 | EEE_LINK_IDLE_UART_IDL);
713 	if (DEVICE_5725_SERIES_CHIPSETS(bgep))
714 		val |= EEE_LINK_IDLE_APE_TX_MT;
715 	bge_reg_put32(bgep, EEE_LINK_IDLE_CONTROL_REG, val);
716 
717 	bge_reg_put32(bgep, EEE_CONTROL_REG, EEE_CONTROL_EXIT_20_1_US);
718 
719 	val = EEE_MODE_ERLY_L1_XIT_DET | EEE_MODE_LPI_IN_TX |
720 	    EEE_MODE_LPI_IN_RX | EEE_MODE_EEE_ENABLE;
721 
722 	if (bgep->chipid.device != DEVICE_ID_5717)
723 		val |= EEE_MODE_SND_IDX_DET_EN;
724 
725 	//val |= EEE_MODE_APE_TX_DET_EN;
726 
727 	if (!bgep->chipid.eee) {
728 		val = 0;
729 	}
730 
731 	bge_reg_put32(bgep, EEE_MODE_REG, val);
732 
733 	/* Set EEE timer debounce values */
734 
735 	bge_reg_put32(bgep, EEE_DEBOUNCE_T1_CONTROL_REG,
736 	    EEE_DEBOUNCE_T1_PCIEXIT_2047US | EEE_DEBOUNCE_T1_LNKIDLE_2047US);
737 
738 	bge_reg_put32(bgep, EEE_DEBOUNCE_T2_CONTROL_REG,
739 	    EEE_DEBOUNCE_T2_APE_TX_2047US | EEE_DEBOUNCE_T2_TXIDXEQ_2047US);
740 }
741 
742 void
743 bge_eee_autoneg(bge_t * bgep, boolean_t adv_100fdx, boolean_t adv_1000fdx)
744 {
745 	uint32_t val;
746 	uint16_t mii_val;
747 
748 	BGE_TRACE(("bge_eee_autoneg($%p)", (void *)bgep));
749 
750 	ASSERT(mutex_owned(bgep->genlock));
751 
752 	if (!bge_eee_cap(bgep)) {
753 		return;
754 	}
755 
756 	/* Disable LPI Requests */
757 	val = bge_reg_get32(bgep, EEE_MODE_REG);
758 	val &= ~EEE_MODE_LPI_ENABLE;
759 	bge_reg_put32(bgep, EEE_MODE_REG, val);
760 
761 	bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
762 
763 	mii_val = 0;
764 
765 	if (bgep->chipid.eee) {
766 		if (adv_100fdx) {
767 			mii_val |= EEE_CL45_D7_RESULT_STAT_LP_100TX;
768 		}
769 		if (adv_1000fdx) {
770 			mii_val |= EEE_CL45_D7_RESULT_STAT_LP_1000T;
771 		}
772 	}
773 
774 	/* Enable EEE advertisement for the specified mode(s)... */
775 	bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN);
776 	bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, MDIO_AN_EEE_ADV);
777 	bge_mii_put16(bgep, MII_MMD_CTRL,
778 	    MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN);
779 	bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, mii_val);
780 
781 	/* Setup PHY DSP for EEE */
782 	switch (bgep->chipid.device) {
783 	case DEVICE_ID_5717:
784 	case DEVICE_ID_5718:
785 	case DEVICE_ID_5719:
786 		/* If we advertised any EEE advertisements above... */
787 		if (mii_val) {
788 			mii_val = (MII_DSP_TAP26_ALNOKO |
789 			    MII_DSP_TAP26_RMRXSTO |
790 			    MII_DSP_TAP26_OPCSINPT);
791 		}
792 		bge_phydsp_write(bgep, MII_DSP_TAP26, mii_val);
793 		/* fall through */
794 	case DEVICE_ID_5720:
795 	case DEVICE_ID_5725:
796 	case DEVICE_ID_5727:
797 		mii_val = bge_phydsp_read(bgep, MII_DSP_CH34TP2);
798 		bge_phydsp_write(bgep, MII_DSP_CH34TP2,
799 		    (mii_val | MII_DSP_CH34TP2_HIBW01));
800 	}
801 
802 	bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
803 }
804 
805 void
806 bge_eee_adjust(bge_t * bgep)
807 {
808 	uint32_t val;
809 	uint16_t mii_val;
810 
811 	BGE_TRACE(("bge_eee_adjust($%p, %d)", (void *)bgep));
812 
813 	ASSERT(mutex_owned(bgep->genlock));
814 
815 	if (!bge_eee_cap(bgep)) {
816 		return;
817 	}
818 
819 	bgep->eee_lpi_wait = 0;
820 
821 	/* Check for PHY link status */
822 	if (bgep->param_link_up) {
823 		BGE_DEBUG(("bge_eee_adjust: link status up"));
824 
825 		/*
826 		 * XXX if duplex full and speed is 1000 or 100 then do the
827 		 * following...
828 		 */
829 
830 		if (bgep->param_link_speed == 1000) {
831 			BGE_DEBUG(("bge_eee_adjust: eee timing for 1000Mb"));
832 			bge_reg_put32(bgep, EEE_CONTROL_REG,
833 			    EEE_CONTROL_EXIT_16_5_US);
834 		} else if (bgep->param_link_speed == 100) {
835 			BGE_DEBUG(("bge_eee_adjust: eee timing for 100Mb"));
836 			bge_reg_put32(bgep, EEE_CONTROL_REG,
837 			    EEE_CONTROL_EXIT_36_US);
838 		}
839 
840 		/* Read PHY's EEE negotiation status */
841 		bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN);
842 		bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA,
843 		    EEE_CL45_D7_RESULT_STAT);
844 		bge_mii_put16(bgep, MII_MMD_CTRL,
845 		    MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN);
846 		mii_val = bge_mii_get16(bgep, MII_MMD_ADDRESS_DATA);
847 
848 		/* Enable EEE LPI request if EEE negotiated */
849 		if ((mii_val == EEE_CL45_D7_RESULT_STAT_LP_1000T) ||
850 		    (mii_val == EEE_CL45_D7_RESULT_STAT_LP_100TX)) {
851 			BGE_DEBUG(("bge_eee_adjust: eee negotiaton success, lpi scheduled"));
852 			bgep->eee_lpi_wait = 2;
853 		} else {
854 			BGE_DEBUG(("bge_eee_adjust: eee negotiation failed"));
855 		}
856 	} else {
857 		BGE_DEBUG(("bge_eee_adjust: link status down"));
858 	}
859 
860 	if (!bgep->eee_lpi_wait) {
861 		if (bgep->param_link_up) {
862 			bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
863 			bge_phydsp_write(bgep, MII_DSP_TAP26, 0);
864 			bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
865 		}
866 
867 		/* Disable LPI requests */
868 		val = bge_reg_get32(bgep, EEE_MODE_REG);
869 		val &= ~EEE_MODE_LPI_ENABLE;
870 		bge_reg_put32(bgep, EEE_MODE_REG, val);
871 	}
872 }
873 
874 void
875 bge_eee_enable(bge_t * bgep)
876 {
877 	uint32_t val;
878 
879 	/* XXX check for EEE for 5717 family... */
880 
881 	if (bgep->param_link_speed == 1000) {
882 		bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
883 		bge_phydsp_write(bgep, MII_DSP_TAP26,
884 		    MII_DSP_TAP26_ALNOKO | MII_DSP_TAP26_RMRXSTO);
885 		bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
886 	}
887 
888 	val = bge_reg_get32(bgep, EEE_MODE_REG);
889 	val |= EEE_MODE_LPI_ENABLE;
890 	bge_reg_put32(bgep, EEE_MODE_REG, val);
891 }
892 
893 /*
894  * Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities
895  * and advertisements with the required settings as specified by the various
896  * param_* variables that can be poked via the NDD interface.
897  *
898  * We always reset the PHY and reprogram *all* the relevant registers,
899  * not just those changed.  This should cause the link to go down, and then
900  * back up again once the link is stable and autonegotiation (if enabled)
901  * is complete.  We should get a link state change interrupt somewhere along
902  * the way ...
903  *
904  * NOTE: <genlock> must already be held by the caller
905  */
906 static int
907 bge_update_copper(bge_t *bgep)
908 {
909 	boolean_t adv_autoneg;
910 	boolean_t adv_pause;
911 	boolean_t adv_asym_pause;
912 	boolean_t adv_1000fdx;
913 	boolean_t adv_1000hdx;
914 	boolean_t adv_100fdx;
915 	boolean_t adv_100hdx;
916 	boolean_t adv_10fdx;
917 	boolean_t adv_10hdx;
918 
919 	uint16_t control;
920 	uint16_t gigctrl;
921 	uint16_t auxctrl;
922 	uint16_t anar;
923 
924 	BGE_TRACE(("bge_update_copper($%p)", (void *)bgep));
925 
926 	ASSERT(mutex_owned(bgep->genlock));
927 
928 	BGE_DEBUG(("bge_update_copper: autoneg %d "
929 	    "pause %d asym_pause %d "
930 	    "1000fdx %d 1000hdx %d "
931 	    "100fdx %d 100hdx %d "
932 	    "10fdx %d 10hdx %d ",
933 	    bgep->param_adv_autoneg,
934 	    bgep->param_adv_pause, bgep->param_adv_asym_pause,
935 	    bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
936 	    bgep->param_adv_100fdx, bgep->param_adv_100hdx,
937 	    bgep->param_adv_10fdx, bgep->param_adv_10hdx));
938 
939 	control = gigctrl = auxctrl = anar = 0;
940 
941 	/*
942 	 * PHY settings are normally based on the param_* variables,
943 	 * but if any loopback mode is in effect, that takes precedence.
944 	 *
945 	 * BGE supports MAC-internal loopback, PHY-internal loopback,
946 	 * and External loopback at a variety of speeds (with a special
947 	 * cable).  In all cases, autoneg is turned OFF, full-duplex
948 	 * is turned ON, and the speed/mastership is forced.
949 	 */
950 	switch (bgep->param_loop_mode) {
951 	case BGE_LOOP_NONE:
952 	default:
953 		adv_autoneg = bgep->param_adv_autoneg;
954 		adv_pause = bgep->param_adv_pause;
955 		adv_asym_pause = bgep->param_adv_asym_pause;
956 		adv_1000fdx = bgep->param_adv_1000fdx;
957 		adv_1000hdx = bgep->param_adv_1000hdx;
958 		adv_100fdx = bgep->param_adv_100fdx;
959 		adv_100hdx = bgep->param_adv_100hdx;
960 		adv_10fdx = bgep->param_adv_10fdx;
961 		adv_10hdx = bgep->param_adv_10hdx;
962 		break;
963 
964 	case BGE_LOOP_EXTERNAL_1000:
965 	case BGE_LOOP_EXTERNAL_100:
966 	case BGE_LOOP_EXTERNAL_10:
967 	case BGE_LOOP_INTERNAL_PHY:
968 	case BGE_LOOP_INTERNAL_MAC:
969 		adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
970 		adv_1000fdx = adv_100fdx = adv_10fdx = B_FALSE;
971 		adv_1000hdx = adv_100hdx = adv_10hdx = B_FALSE;
972 		bgep->param_link_duplex = LINK_DUPLEX_FULL;
973 
974 		switch (bgep->param_loop_mode) {
975 		case BGE_LOOP_EXTERNAL_1000:
976 			bgep->param_link_speed = 1000;
977 			adv_1000fdx = B_TRUE;
978 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
979 			gigctrl |= MII_MSCONTROL_MANUAL;
980 			gigctrl |= MII_MSCONTROL_MASTER;
981 			break;
982 
983 		case BGE_LOOP_EXTERNAL_100:
984 			bgep->param_link_speed = 100;
985 			adv_100fdx = B_TRUE;
986 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
987 			break;
988 
989 		case BGE_LOOP_EXTERNAL_10:
990 			bgep->param_link_speed = 10;
991 			adv_10fdx = B_TRUE;
992 			auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
993 			break;
994 
995 		case BGE_LOOP_INTERNAL_PHY:
996 			bgep->param_link_speed = 1000;
997 			adv_1000fdx = B_TRUE;
998 			control = MII_CONTROL_LOOPBACK;
999 			break;
1000 
1001 		case BGE_LOOP_INTERNAL_MAC:
1002 			bgep->param_link_speed = 1000;
1003 			adv_1000fdx = B_TRUE;
1004 			break;
1005 		}
1006 	}
1007 
1008 	BGE_DEBUG(("bge_update_copper: autoneg %d "
1009 	    "pause %d asym_pause %d "
1010 	    "1000fdx %d 1000hdx %d "
1011 	    "100fdx %d 100hdx %d "
1012 	    "10fdx %d 10hdx %d ",
1013 	    adv_autoneg,
1014 	    adv_pause, adv_asym_pause,
1015 	    adv_1000fdx, adv_1000hdx,
1016 	    adv_100fdx, adv_100hdx,
1017 	    adv_10fdx, adv_10hdx));
1018 
1019 	/*
1020 	 * We should have at least one technology capability set;
1021 	 * if not, we select a default of 1000Mb/s full-duplex
1022 	 */
1023 	if (!adv_1000fdx && !adv_100fdx && !adv_10fdx &&
1024 	    !adv_1000hdx && !adv_100hdx && !adv_10hdx)
1025 		adv_1000fdx = B_TRUE;
1026 
1027 	/*
1028 	 * Now transform the adv_* variables into the proper settings
1029 	 * of the PHY registers ...
1030 	 *
1031 	 * If autonegotiation is (now) enabled, we want to trigger
1032 	 * a new autonegotiation cycle once the PHY has been
1033 	 * programmed with the capabilities to be advertised.
1034 	 */
1035 	if (adv_autoneg)
1036 		control |= MII_CONTROL_ANE|MII_CONTROL_RSAN;
1037 
1038 	if (adv_1000fdx)
1039 		control |= MII_CONTROL_1GB|MII_CONTROL_FDUPLEX;
1040 	else if (adv_1000hdx)
1041 		control |= MII_CONTROL_1GB;
1042 	else if (adv_100fdx)
1043 		control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX;
1044 	else if (adv_100hdx)
1045 		control |= MII_CONTROL_100MB;
1046 	else if (adv_10fdx)
1047 		control |= MII_CONTROL_FDUPLEX;
1048 	else if (adv_10hdx)
1049 		control |= 0;
1050 	else
1051 		{ _NOTE(EMPTY); }	/* Can't get here anyway ...	*/
1052 
1053 	if (adv_1000fdx)
1054 		gigctrl |= MII_MSCONTROL_1000T_FD;
1055 	if (adv_1000hdx)
1056 		gigctrl |= MII_MSCONTROL_1000T;
1057 
1058 	if (adv_100fdx)
1059 		anar |= MII_ABILITY_100BASE_TX_FD;
1060 	if (adv_100hdx)
1061 		anar |= MII_ABILITY_100BASE_TX;
1062 	if (adv_10fdx)
1063 		anar |= MII_ABILITY_10BASE_T_FD;
1064 	if (adv_10hdx)
1065 		anar |= MII_ABILITY_10BASE_T;
1066 
1067 	if (adv_pause)
1068 		anar |= MII_ABILITY_PAUSE;
1069 	if (adv_asym_pause)
1070 		anar |= MII_ABILITY_ASMPAUSE;
1071 
1072 	/*
1073 	 * Munge in any other fixed bits we require ...
1074 	 */
1075 	anar |= MII_AN_SELECTOR_8023;
1076 	auxctrl |= MII_AUX_CTRL_NORM_TX_MODE;
1077 	auxctrl |= MII_AUX_CTRL_NORMAL;
1078 
1079 	/*
1080 	 * Restart the PHY and write the new values.  Note the
1081 	 * time, so that we can say whether subsequent link state
1082 	 * changes can be attributed to our reprogramming the PHY
1083 	 */
1084 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) == DDI_FAILURE)
1085 		return (DDI_FAILURE);
1086 	bge_mii_put16(bgep, MII_AN_ADVERT, anar);
1087 	if (auxctrl & MII_AUX_CTRL_NORM_EXT_LOOPBACK)
1088 		bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
1089 	bge_mii_put16(bgep, MII_MSCONTROL, gigctrl);
1090 	bge_mii_put16(bgep, MII_CONTROL, control);
1091 
1092 	BGE_DEBUG(("bge_update_copper: anar <- 0x%x", anar));
1093 	BGE_DEBUG(("bge_update_copper: auxctrl <- 0x%x", auxctrl));
1094 	BGE_DEBUG(("bge_update_copper: gigctrl <- 0x%x", gigctrl));
1095 	BGE_DEBUG(("bge_update_copper: control <- 0x%x", control));
1096 
1097 #if	BGE_COPPER_WIRESPEED
1098 	/*
1099 	 * Enable the 'wire-speed' feature, if the chip supports it
1100 	 * and we haven't got (any) loopback mode selected.
1101 	 */
1102 	switch (bgep->chipid.device) {
1103 	case DEVICE_ID_5700:
1104 	case DEVICE_ID_5700x:
1105 	case DEVICE_ID_5705C:
1106 	case DEVICE_ID_5782:
1107 		/*
1108 		 * These chips are known or assumed not to support it
1109 		 */
1110 		break;
1111 
1112 	default:
1113 		/*
1114 		 * All other Broadcom chips are expected to support it.
1115 		 */
1116 		if (bgep->param_loop_mode == BGE_LOOP_NONE)
1117 			bge_mii_put16(bgep, MII_AUX_CONTROL,
1118 			    MII_AUX_CTRL_MISC_WRITE_ENABLE |
1119 			    MII_AUX_CTRL_MISC_WIRE_SPEED |
1120 			    MII_AUX_CTRL_MISC);
1121 		break;
1122 	}
1123 #endif	/* BGE_COPPER_WIRESPEED */
1124 
1125 	/* enable EEE on those chips that support it */
1126 	bge_eee_autoneg(bgep, adv_100fdx, adv_1000fdx);
1127 
1128 	return (DDI_SUCCESS);
1129 }
1130 
1131 static boolean_t
1132 bge_check_copper(bge_t *bgep, boolean_t recheck)
1133 {
1134 	uint32_t emac_status;
1135 	uint16_t mii_status;
1136 	uint16_t aux;
1137 	uint_t mode;
1138 	boolean_t linkup;
1139 	int i;
1140 
1141 	/*
1142 	 * Step 10: read the status from the PHY (which is self-clearing
1143 	 * on read!); also read & clear the main (Ethernet) MAC status
1144 	 * (the relevant bits of this are write-one-to-clear).
1145 	 */
1146 	for (i = 0; i < 100; i++) {
1147 		drv_usecwait(40);
1148 		mii_status = bge_mii_get16(bgep, MII_STATUS);
1149 	}
1150 	emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
1151 	bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status);
1152 
1153 	BGE_DEBUG(("bge_check_copper: link %d/%s, MII status 0x%x "
1154 	    "(was 0x%x), Ethernet MAC status 0x%x",
1155 	    bgep->link_state, UPORDOWN(bgep->param_link_up), mii_status,
1156 	    bgep->phy_gen_status, emac_status));
1157 
1158 	/*
1159 	 * If the PHY status hasn't changed since last we looked, and
1160 	 * we not forcing a recheck (i.e. the link state was already
1161 	 * known), there's nothing to do.
1162 	 */
1163 	if (mii_status == bgep->phy_gen_status && !recheck) {
1164 		BGE_DEBUG(("bge_check_copper: no link change"));
1165 		return (B_FALSE);
1166 	}
1167 
1168 	do {
1169 		/*
1170 		 * Step 11: read AUX STATUS register to find speed/duplex
1171 		 */
1172 		for (i = 0; i < 2000; i++) {
1173 			drv_usecwait(10);
1174 			aux = bge_mii_get16(bgep, MII_AUX_STATUS);
1175 		}
1176 		BGE_CDB(bge_phydump, (bgep, mii_status, aux));
1177 
1178 		/*
1179 		 * We will only consider the link UP if all the readings
1180 		 * are consistent and give meaningful results ...
1181 		 */
1182 		mode = aux & MII_AUX_STATUS_MODE_MASK;
1183 		mode >>= MII_AUX_STATUS_MODE_SHIFT;
1184 		if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
1185 			linkup = BIS(aux, MII_AUX_STATUS_LINKUP);
1186 			linkup &= BIS(mii_status, MII_STATUS_LINKUP);
1187 		} else {
1188 			linkup = bge_copper_link_speed[mode] > 0;
1189 			linkup &= bge_copper_link_duplex[mode] !=
1190 			    LINK_DUPLEX_UNKNOWN;
1191 			linkup &= BIS(aux, MII_AUX_STATUS_LINKUP);
1192 			linkup &= BIS(mii_status, MII_STATUS_LINKUP);
1193 		}
1194 
1195 		BGE_DEBUG(("bge_check_copper: MII status 0x%x aux 0x%x "
1196 		    "=> mode %d (%s)",
1197 		    mii_status, aux,
1198 		    mode, UPORDOWN(linkup)));
1199 
1200 		/*
1201 		 * Record current register values, then reread status
1202 		 * register & loop until it stabilises ...
1203 		 */
1204 		bgep->phy_aux_status = aux;
1205 		bgep->phy_gen_status = mii_status;
1206 
1207 		for (i = 0; i < 100; i++)
1208 		{
1209 			drv_usecwait(40);
1210 			mii_status = bge_mii_get16(bgep, MII_STATUS);
1211 		}
1212 	} while (mii_status != bgep->phy_gen_status);
1213 
1214 	/*
1215 	 * Assume very little ...
1216 	 */
1217 	bgep->param_lp_autoneg = B_FALSE;
1218 	bgep->param_lp_1000fdx = B_FALSE;
1219 	bgep->param_lp_1000hdx = B_FALSE;
1220 	bgep->param_lp_100fdx = B_FALSE;
1221 	bgep->param_lp_100hdx = B_FALSE;
1222 	bgep->param_lp_10fdx = B_FALSE;
1223 	bgep->param_lp_10hdx = B_FALSE;
1224 	bgep->param_lp_pause = B_FALSE;
1225 	bgep->param_lp_asym_pause = B_FALSE;
1226 	bgep->param_link_autoneg = B_FALSE;
1227 	bgep->param_link_tx_pause = B_FALSE;
1228 	if (bgep->param_adv_autoneg)
1229 		bgep->param_link_rx_pause = B_FALSE;
1230 	else
1231 		bgep->param_link_rx_pause = bgep->param_adv_pause;
1232 
1233 	/*
1234 	 * Discover all the link partner's abilities.
1235 	 * These are scattered through various registers ...
1236 	 */
1237 	if (BIS(aux, MII_AUX_STATUS_LP_ANEG_ABLE)) {
1238 		bgep->param_lp_autoneg = B_TRUE;
1239 		bgep->param_link_autoneg = B_TRUE;
1240 		bgep->param_link_tx_pause = BIS(aux, MII_AUX_STATUS_TX_PAUSE);
1241 		bgep->param_link_rx_pause = BIS(aux, MII_AUX_STATUS_RX_PAUSE);
1242 
1243 		aux = bge_mii_get16(bgep, MII_MSSTATUS);
1244 		bgep->param_lp_1000fdx = BIS(aux, MII_MSSTATUS_LP1000T_FD);
1245 		bgep->param_lp_1000hdx = BIS(aux, MII_MSSTATUS_LP1000T);
1246 
1247 		aux = bge_mii_get16(bgep, MII_AN_LPABLE);
1248 		bgep->param_lp_100fdx = BIS(aux, MII_ABILITY_100BASE_TX_FD);
1249 		bgep->param_lp_100hdx = BIS(aux, MII_ABILITY_100BASE_TX);
1250 		bgep->param_lp_10fdx = BIS(aux, MII_ABILITY_10BASE_T_FD);
1251 		bgep->param_lp_10hdx = BIS(aux, MII_ABILITY_10BASE_T);
1252 		bgep->param_lp_pause = BIS(aux, MII_ABILITY_PAUSE);
1253 		bgep->param_lp_asym_pause = BIS(aux, MII_ABILITY_ASMPAUSE);
1254 	}
1255 
1256 	/*
1257 	 * Step 12: update ndd-visible state parameters, BUT!
1258 	 * we don't transfer the new state to <link_state> just yet;
1259 	 * instead we mark the <link_state> as UNKNOWN, and our caller
1260 	 * will resolve it once the status has stopped changing and
1261 	 * been stable for several seconds.
1262 	 */
1263 	BGE_DEBUG(("bge_check_copper: link was %s speed %d duplex %d",
1264 	    UPORDOWN(bgep->param_link_up),
1265 	    bgep->param_link_speed,
1266 	    bgep->param_link_duplex));
1267 
1268 	if (!linkup)
1269 		mode = MII_AUX_STATUS_MODE_NONE;
1270 	bgep->param_link_up = linkup;
1271 	bgep->link_state = LINK_STATE_UNKNOWN;
1272 	if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
1273 		if (bgep->phy_aux_status & MII_AUX_STATUS_NEG_ENABLED_5906) {
1274 			bgep->param_link_speed =
1275 			    bge_copper_link_speed_5906[mode];
1276 			bgep->param_link_duplex =
1277 			    bge_copper_link_duplex_5906[mode];
1278 		} else {
1279 			bgep->param_link_speed = (bgep->phy_aux_status &
1280 			    MII_AUX_STATUS_SPEED_IND_5906) ?  100 : 10;
1281 			bgep->param_link_duplex = (bgep->phy_aux_status &
1282 			    MII_AUX_STATUS_DUPLEX_IND_5906) ? LINK_DUPLEX_FULL :
1283 			    LINK_DUPLEX_HALF;
1284 		}
1285 	} else {
1286 		bgep->param_link_speed = bge_copper_link_speed[mode];
1287 		bgep->param_link_duplex = bge_copper_link_duplex[mode];
1288 	}
1289 
1290 	bge_eee_adjust(bgep);
1291 
1292 	bge_log(bgep, "bge_check_copper: link now %s speed %d duplex %d",
1293 	        UPORDOWN(bgep->param_link_up),
1294 	        bgep->param_link_speed,
1295 	        bgep->param_link_duplex);
1296 
1297 	return (B_TRUE);
1298 }
1299 
1300 static const phys_ops_t copper_ops = {
1301 	bge_restart_copper,
1302 	bge_update_copper,
1303 	bge_check_copper
1304 };
1305 
1306 
1307 /*
1308  * ========== SerDes support ==========
1309  */
1310 
1311 #undef	BGE_DBG
1312 #define	BGE_DBG		BGE_DBG_SERDES	/* debug flag for this code	*/
1313 
1314 /*
1315  * Reinitialise the SerDes interface.  Note that it normally powers
1316  * up in the disabled state, so we need to explicitly activate it.
1317  */
1318 static int
1319 bge_restart_serdes(bge_t *bgep, boolean_t powerdown)
1320 {
1321 	uint32_t macmode;
1322 
1323 	BGE_TRACE(("bge_restart_serdes($%p, %d)", (void *)bgep, powerdown));
1324 
1325 	ASSERT(mutex_owned(bgep->genlock));
1326 
1327 	/*
1328 	 * Ensure that the main Ethernet MAC mode register is programmed
1329 	 * appropriately for the SerDes interface ...
1330 	 */
1331 	macmode = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG);
1332 	macmode &= ~ETHERNET_MODE_LINK_POLARITY;
1333 	macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
1334 	if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
1335 	    DEVICE_5725_SERIES_CHIPSETS(bgep) ||
1336 	    DEVICE_5714_SERIES_CHIPSETS(bgep)) {
1337 		macmode |= ETHERNET_MODE_PORTMODE_GMII;
1338 	} else {
1339 		macmode |= ETHERNET_MODE_PORTMODE_TBI;
1340 	}
1341 	bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, macmode);
1342 
1343 	/*
1344 	 * Ensure that loopback is OFF and comma detection is enabled.  Then
1345 	 * disable the SerDes output (the first time through, it may/will
1346 	 * already be disabled).  If we're shutting down, leave it disabled.
1347 	 */
1348 	bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TBI_LOOPBACK);
1349 	bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_COMMA_DETECT);
1350 	bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
1351 	if (powerdown)
1352 		return (DDI_SUCCESS);
1353 
1354 	/*
1355 	 * Otherwise, pause, (re-)enable the SerDes output, and send
1356 	 * all-zero config words in order to force autoneg restart.
1357 	 * Invalidate the saved "link partners received configs", as
1358 	 * we're starting over ...
1359 	 */
1360 	drv_usecwait(10000);
1361 	bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
1362 	bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG, 0);
1363 	bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
1364 	drv_usecwait(10);
1365 	bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
1366 	bgep->serdes_lpadv = AUTONEG_CODE_FAULT_ANEG_ERR;
1367 	bgep->serdes_status = ~0U;
1368 	return (DDI_SUCCESS);
1369 }
1370 
1371 /*
1372  * Synchronise the SerDes speed/duplex/autonegotiation capabilities and
1373  * advertisements with the required settings as specified by the various
1374  * param_* variables that can be poked via the NDD interface.
1375  *
1376  * We always reinitalise the SerDes; this should cause the link to go down,
1377  * and then back up again once the link is stable and autonegotiation
1378  * (if enabled) is complete.  We should get a link state change interrupt
1379  * somewhere along the way ...
1380  *
1381  * NOTE: SerDes only supports 1000FDX/HDX (with or without pause) so the
1382  * param_* variables relating to lower speeds are ignored.
1383  *
1384  * NOTE: <genlock> must already be held by the caller
1385  */
1386 static int
1387 bge_update_serdes(bge_t *bgep)
1388 {
1389 	boolean_t adv_autoneg;
1390 	boolean_t adv_pause;
1391 	boolean_t adv_asym_pause;
1392 	boolean_t adv_1000fdx;
1393 	boolean_t adv_1000hdx;
1394 
1395 	uint32_t serdes;
1396 	uint32_t advert;
1397 
1398 	BGE_TRACE(("bge_update_serdes($%p)", (void *)bgep));
1399 
1400 	ASSERT(mutex_owned(bgep->genlock));
1401 
1402 	BGE_DEBUG(("bge_update_serdes: autoneg %d "
1403 	    "pause %d asym_pause %d "
1404 	    "1000fdx %d 1000hdx %d "
1405 	    "100fdx %d 100hdx %d "
1406 	    "10fdx %d 10hdx %d ",
1407 	    bgep->param_adv_autoneg,
1408 	    bgep->param_adv_pause, bgep->param_adv_asym_pause,
1409 	    bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
1410 	    bgep->param_adv_100fdx, bgep->param_adv_100hdx,
1411 	    bgep->param_adv_10fdx, bgep->param_adv_10hdx));
1412 
1413 	serdes = advert = 0;
1414 
1415 	/*
1416 	 * SerDes settings are normally based on the param_* variables,
1417 	 * but if any loopback mode is in effect, that takes precedence.
1418 	 *
1419 	 * BGE supports MAC-internal loopback, PHY-internal loopback,
1420 	 * and External loopback at a variety of speeds (with a special
1421 	 * cable).  In all cases, autoneg is turned OFF, full-duplex
1422 	 * is turned ON, and the speed/mastership is forced.
1423 	 *
1424 	 * Note: for the SerDes interface, "PHY" internal loopback is
1425 	 * interpreted as SerDes internal loopback, and all external
1426 	 * loopback modes are treated equivalently, as 1Gb/external.
1427 	 */
1428 	switch (bgep->param_loop_mode) {
1429 	case BGE_LOOP_NONE:
1430 	default:
1431 		adv_autoneg = bgep->param_adv_autoneg;
1432 		adv_pause = bgep->param_adv_pause;
1433 		adv_asym_pause = bgep->param_adv_asym_pause;
1434 		adv_1000fdx = bgep->param_adv_1000fdx;
1435 		adv_1000hdx = bgep->param_adv_1000hdx;
1436 		break;
1437 
1438 	case BGE_LOOP_INTERNAL_PHY:
1439 		serdes |= SERDES_CONTROL_TBI_LOOPBACK;
1440 		/* FALLTHRU */
1441 	case BGE_LOOP_INTERNAL_MAC:
1442 	case BGE_LOOP_EXTERNAL_1000:
1443 	case BGE_LOOP_EXTERNAL_100:
1444 	case BGE_LOOP_EXTERNAL_10:
1445 		adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
1446 		adv_1000fdx = B_TRUE;
1447 		adv_1000hdx = B_FALSE;
1448 		break;
1449 	}
1450 
1451 	BGE_DEBUG(("bge_update_serdes: autoneg %d "
1452 	    "pause %d asym_pause %d "
1453 	    "1000fdx %d 1000hdx %d ",
1454 	    adv_autoneg,
1455 	    adv_pause, adv_asym_pause,
1456 	    adv_1000fdx, adv_1000hdx));
1457 
1458 	/*
1459 	 * We should have at least one gigabit technology capability
1460 	 * set; if not, we select a default of 1000Mb/s full-duplex
1461 	 */
1462 	if (!adv_1000fdx && !adv_1000hdx)
1463 		adv_1000fdx = B_TRUE;
1464 
1465 	/*
1466 	 * Now transform the adv_* variables into the proper settings
1467 	 * of the SerDes registers ...
1468 	 *
1469 	 * If autonegotiation is (now) not enabled, pretend it's been
1470 	 * done and failed ...
1471 	 */
1472 	if (!adv_autoneg)
1473 		advert |= AUTONEG_CODE_FAULT_ANEG_ERR;
1474 
1475 	if (adv_1000fdx) {
1476 		advert |= AUTONEG_CODE_FULL_DUPLEX;
1477 		bgep->param_adv_1000fdx = adv_1000fdx;
1478 		bgep->param_link_duplex = LINK_DUPLEX_FULL;
1479 		bgep->param_link_speed = 1000;
1480 	}
1481 	if (adv_1000hdx) {
1482 		advert |= AUTONEG_CODE_HALF_DUPLEX;
1483 		bgep->param_adv_1000hdx = adv_1000hdx;
1484 		bgep->param_link_duplex = LINK_DUPLEX_HALF;
1485 		bgep->param_link_speed = 1000;
1486 	}
1487 
1488 	if (adv_pause)
1489 		advert |= AUTONEG_CODE_PAUSE;
1490 	if (adv_asym_pause)
1491 		advert |= AUTONEG_CODE_ASYM_PAUSE;
1492 
1493 	/*
1494 	 * Restart the SerDes and write the new values.  Note the
1495 	 * time, so that we can say whether subsequent link state
1496 	 * changes can be attributed to our reprogramming the SerDes
1497 	 */
1498 	bgep->serdes_advert = advert;
1499 	(void) bge_restart_serdes(bgep, B_FALSE);
1500 	bge_reg_set32(bgep, SERDES_CONTROL_REG, serdes);
1501 
1502 	BGE_DEBUG(("bge_update_serdes: serdes |= 0x%x, advert 0x%x",
1503 	    serdes, advert));
1504 	return (DDI_SUCCESS);
1505 }
1506 
1507 /*
1508  * Bare-minimum autoneg protocol
1509  *
1510  * This code is only called when the link is up and we're receiving config
1511  * words, which implies that the link partner wants to autonegotiate
1512  * (otherwise, we wouldn't see configs and wouldn't reach this code).
1513  */
1514 static void
1515 bge_autoneg_serdes(bge_t *bgep)
1516 {
1517 	boolean_t ack;
1518 
1519 	bgep->serdes_lpadv = bge_reg_get32(bgep, RX_1000BASEX_AUTONEG_REG);
1520 	ack = BIS(bgep->serdes_lpadv, AUTONEG_CODE_ACKNOWLEDGE);
1521 
1522 	if (!ack) {
1523 		/*
1524 		 * Phase 1: after SerDes reset, we send a few zero configs
1525 		 * but then stop.  Here the partner is sending configs, but
1526 		 * not ACKing ours; we assume that's 'cos we're not sending
1527 		 * any.  So here we send ours, with ACK already set.
1528 		 */
1529 		bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG,
1530 		    bgep->serdes_advert | AUTONEG_CODE_ACKNOWLEDGE);
1531 		bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG,
1532 		    ETHERNET_MODE_SEND_CFGS);
1533 	} else {
1534 		/*
1535 		 * Phase 2: partner has ACKed our configs, so now we can
1536 		 * stop sending; once our partner also stops sending, we
1537 		 * can resolve the Tx/Rx configs.
1538 		 */
1539 		bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG,
1540 		    ETHERNET_MODE_SEND_CFGS);
1541 	}
1542 
1543 	BGE_DEBUG(("bge_autoneg_serdes: Rx 0x%x %s Tx 0x%x",
1544 	    bgep->serdes_lpadv,
1545 	    ack ? "stop" : "send",
1546 	    bgep->serdes_advert));
1547 }
1548 
1549 static boolean_t
1550 bge_check_serdes(bge_t *bgep, boolean_t recheck)
1551 {
1552 	uint32_t emac_status;
1553 	uint32_t tx_status;
1554 	uint32_t lpadv;
1555 	boolean_t linkup;
1556 	boolean_t linkup_old = bgep->param_link_up;
1557 
1558 	for (;;) {
1559 		/*
1560 		 * Step 10: BCM5714S, BCM5715S only
1561 		 * Don't call function bge_autoneg_serdes() as
1562 		 * RX_1000BASEX_AUTONEG_REG (0x0448) is not applicable
1563 		 * to BCM5705, BCM5788, BCM5721, BCM5751, BCM5752,
1564 		 * BCM5714, and BCM5715 devices.
1565 		 */
1566 		if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
1567 		    DEVICE_5725_SERIES_CHIPSETS(bgep) ||
1568 		    DEVICE_5714_SERIES_CHIPSETS(bgep)) {
1569 			tx_status = bge_reg_get32(bgep,
1570 			    TRANSMIT_MAC_STATUS_REG);
1571 			linkup = BIS(tx_status, TRANSMIT_STATUS_LINK_UP);
1572 			emac_status = bge_reg_get32(bgep,
1573 			    ETHERNET_MAC_STATUS_REG);
1574 			bgep->serdes_status = emac_status;
1575 			/* clear write-one-to-clear bits in MAC status */
1576 			if ((emac_status & ETHERNET_STATUS_MI_COMPLETE) &&
1577 			    (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
1578 			     DEVICE_5725_SERIES_CHIPSETS(bgep))) {
1579 				emac_status |= ETHERNET_STATUS_SYNC_CHANGED |
1580 				    ETHERNET_STATUS_CFG_CHANGED;
1581 			}
1582 			bge_reg_put32(bgep,
1583 			    ETHERNET_MAC_STATUS_REG, emac_status);
1584 			/*
1585 			 * If the link status has not changed then then
1586 			 * break. If it has loop around and recheck again.
1587 			 * Keep looping until the link status has not
1588 			 * changed.
1589 			 */
1590 			if ((linkup && linkup_old) ||
1591 			    (!linkup && !linkup_old)) {
1592 				break;
1593 			}
1594 			if (linkup)
1595 				linkup_old = B_TRUE;
1596 			else
1597 				linkup_old = B_FALSE;
1598 			recheck = B_TRUE;
1599 		} else {
1600 			/*
1601 			 * Step 10: others
1602 			 * read & clear the main (Ethernet) MAC status
1603 			 * (the relevant bits of this are write-one-to-clear).
1604 			 */
1605 			emac_status = bge_reg_get32(bgep,
1606 			    ETHERNET_MAC_STATUS_REG);
1607 			bge_reg_put32(bgep,
1608 			    ETHERNET_MAC_STATUS_REG, emac_status);
1609 
1610 			BGE_DEBUG(("bge_check_serdes: link %d/%s, "
1611 			    "MAC status 0x%x (was 0x%x)",
1612 			    bgep->link_state, UPORDOWN(bgep->param_link_up),
1613 			    emac_status, bgep->serdes_status));
1614 
1615 			/*
1616 			 * We will only consider the link UP if all the readings
1617 			 * are consistent and give meaningful results ...
1618 			 */
1619 			bgep->serdes_status = emac_status;
1620 			linkup = BIS(emac_status,
1621 			    ETHERNET_STATUS_SIGNAL_DETECT);
1622 			linkup &= BIS(emac_status, ETHERNET_STATUS_PCS_SYNCHED);
1623 
1624 			/*
1625 			 * Now some fiddling with the interpretation:
1626 			 *	if there's been an error at the PCS level, treat
1627 			 *	it as a link change (the h/w doesn't do this)
1628 			 *
1629 			 *	if there's been a change, but it's only a PCS
1630 			 *	sync change (not a config change), AND the link
1631 			 *	already was & is still UP, then ignore the
1632 			 *	change
1633 			 */
1634 			if (BIS(emac_status, ETHERNET_STATUS_PCS_ERROR))
1635 				emac_status |= ETHERNET_STATUS_LINK_CHANGED;
1636 			else if (BIC(emac_status, ETHERNET_STATUS_CFG_CHANGED))
1637 				if (bgep->param_link_up && linkup)
1638 					emac_status &=
1639 					    ~ETHERNET_STATUS_LINK_CHANGED;
1640 
1641 			BGE_DEBUG(("bge_check_serdes: status 0x%x => 0x%x %s",
1642 			    bgep->serdes_status, emac_status,
1643 			    UPORDOWN(linkup)));
1644 
1645 			/*
1646 			 * If we're receiving configs, run the autoneg protocol
1647 			 */
1648 			if (linkup && BIS(emac_status,
1649 			    ETHERNET_STATUS_RECEIVING_CFG))
1650 				bge_autoneg_serdes(bgep);
1651 
1652 			/*
1653 			 * If the SerDes status hasn't changed, we're done ...
1654 			 */
1655 			if (BIC(emac_status, ETHERNET_STATUS_LINK_CHANGED))
1656 				break;
1657 
1658 			/*
1659 			 * Go round again until we no longer see a change ...
1660 			 */
1661 			recheck = B_TRUE;
1662 		}
1663 	}
1664 
1665 	/*
1666 	 * If we're not forcing a recheck (i.e. the link state was already
1667 	 * known), and we didn't see the hardware flag a change, there's
1668 	 * no more to do (and we tell the caller nothing happened).
1669 	 */
1670 	if (!recheck)
1671 		return (B_FALSE);
1672 
1673 	/*
1674 	 * Don't resolve autoneg until we're no longer receiving configs
1675 	 */
1676 	if (linkup && BIS(emac_status, ETHERNET_STATUS_RECEIVING_CFG))
1677 		return (B_FALSE);
1678 
1679 	/*
1680 	 * Assume very little ...
1681 	 */
1682 	bgep->param_lp_autoneg = B_FALSE;
1683 	bgep->param_lp_1000fdx = B_FALSE;
1684 	bgep->param_lp_1000hdx = B_FALSE;
1685 	bgep->param_lp_100fdx = B_FALSE;
1686 	bgep->param_lp_100hdx = B_FALSE;
1687 	bgep->param_lp_10fdx = B_FALSE;
1688 	bgep->param_lp_10hdx = B_FALSE;
1689 	bgep->param_lp_pause = B_FALSE;
1690 	bgep->param_lp_asym_pause = B_FALSE;
1691 	bgep->param_link_autoneg = B_FALSE;
1692 	bgep->param_link_tx_pause = B_FALSE;
1693 	if (bgep->param_adv_autoneg)
1694 		bgep->param_link_rx_pause = B_FALSE;
1695 	else
1696 		bgep->param_link_rx_pause = bgep->param_adv_pause;
1697 
1698 	/*
1699 	 * Discover all the link partner's abilities.
1700 	 */
1701 	lpadv = bgep->serdes_lpadv;
1702 	if (lpadv != 0 && BIC(lpadv, AUTONEG_CODE_FAULT_MASK)) {
1703 		/*
1704 		 * No fault, so derive partner's capabilities
1705 		 */
1706 		bgep->param_lp_autoneg = B_TRUE;
1707 		bgep->param_lp_1000fdx = BIS(lpadv, AUTONEG_CODE_FULL_DUPLEX);
1708 		bgep->param_lp_1000hdx = BIS(lpadv, AUTONEG_CODE_HALF_DUPLEX);
1709 		bgep->param_lp_pause = BIS(lpadv, AUTONEG_CODE_PAUSE);
1710 		bgep->param_lp_asym_pause = BIS(lpadv, AUTONEG_CODE_ASYM_PAUSE);
1711 
1712 		/*
1713 		 * Pause direction resolution
1714 		 */
1715 		bgep->param_link_autoneg = B_TRUE;
1716 		if (bgep->param_adv_pause &&
1717 		    bgep->param_lp_pause) {
1718 			bgep->param_link_tx_pause = B_TRUE;
1719 			bgep->param_link_rx_pause = B_TRUE;
1720 		}
1721 		if (bgep->param_adv_asym_pause &&
1722 		    bgep->param_lp_asym_pause) {
1723 			if (bgep->param_adv_pause)
1724 				bgep->param_link_rx_pause = B_TRUE;
1725 			if (bgep->param_lp_pause)
1726 				bgep->param_link_tx_pause = B_TRUE;
1727 		}
1728 	}
1729 
1730 	/*
1731 	 * Step 12: update ndd-visible state parameters, BUT!
1732 	 * we don't transfer the new state to <link_state> just yet;
1733 	 * instead we mark the <link_state> as UNKNOWN, and our caller
1734 	 * will resolve it once the status has stopped changing and
1735 	 * been stable for several seconds.
1736 	 */
1737 	BGE_DEBUG(("bge_check_serdes: link was %s speed %d duplex %d",
1738 	    UPORDOWN(bgep->param_link_up),
1739 	    bgep->param_link_speed,
1740 	    bgep->param_link_duplex));
1741 
1742 	if (linkup) {
1743 		bgep->param_link_up = B_TRUE;
1744 		bgep->param_link_speed = 1000;
1745 		if (bgep->param_adv_1000fdx)
1746 			bgep->param_link_duplex = LINK_DUPLEX_FULL;
1747 		else
1748 			bgep->param_link_duplex = LINK_DUPLEX_HALF;
1749 		if (bgep->param_lp_autoneg && !bgep->param_lp_1000fdx)
1750 			bgep->param_link_duplex = LINK_DUPLEX_HALF;
1751 	} else {
1752 		bgep->param_link_up = B_FALSE;
1753 		bgep->param_link_speed = 0;
1754 		bgep->param_link_duplex = LINK_DUPLEX_UNKNOWN;
1755 	}
1756 	bgep->link_state = LINK_STATE_UNKNOWN;
1757 
1758 	bge_log(bgep, "bge_check_serdes: link now %s speed %d duplex %d",
1759 	        UPORDOWN(bgep->param_link_up),
1760 	        bgep->param_link_speed,
1761 	        bgep->param_link_duplex);
1762 
1763 	return (B_TRUE);
1764 }
1765 
1766 static const phys_ops_t serdes_ops = {
1767 	bge_restart_serdes,
1768 	bge_update_serdes,
1769 	bge_check_serdes
1770 };
1771 
1772 /*
1773  * ========== Exported physical layer control routines ==========
1774  */
1775 
1776 #undef	BGE_DBG
1777 #define	BGE_DBG		BGE_DBG_PHYS	/* debug flag for this code	*/
1778 
1779 /*
1780  * Here we have to determine which media we're using (copper or serdes).
1781  * Once that's done, we can initialise the physical layer appropriately.
1782  */
1783 int
1784 bge_phys_init(bge_t *bgep)
1785 {
1786 	uint32_t regval;
1787 
1788 	BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
1789 
1790 	mutex_enter(bgep->genlock);
1791 
1792 	/*
1793 	 * Probe for the (internal) PHY.  If it's not there, we'll assume
1794 	 * that this is a 5703/4S, with a SerDes interface rather than
1795 	 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
1796 	 * BCM800x PHY.
1797 	 */
1798 	bgep->phy_mii_addr = 1;
1799 
1800 	if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
1801 		bgep->phy_mii_addr = (bgep->pci_func + 1);
1802 		regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
1803 		if (regval & MEDIA_SELECTION_MODE)
1804 			bgep->phy_mii_addr += 7; /* sgmii */
1805 	}
1806 
1807 	if (bge_phy_probe(bgep)) {
1808 		bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
1809 		bgep->physops = &copper_ops;
1810 	} else {
1811 		bgep->chipid.flags |= CHIP_FLAG_SERDES;
1812 		bgep->physops = &serdes_ops;
1813 	}
1814 
1815 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
1816 		mutex_exit(bgep->genlock);
1817 		return (EIO);
1818 	}
1819 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
1820 		mutex_exit(bgep->genlock);
1821 		return (EIO);
1822 	}
1823 	mutex_exit(bgep->genlock);
1824 	return (0);
1825 }
1826 
1827 /*
1828  * Reset the physical layer
1829  */
1830 void
1831 bge_phys_reset(bge_t *bgep)
1832 {
1833 	BGE_TRACE(("bge_phys_reset($%p)", (void *)bgep));
1834 
1835 	mutex_enter(bgep->genlock);
1836 	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS)
1837 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1838 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
1839 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1840 	mutex_exit(bgep->genlock);
1841 }
1842 
1843 /*
1844  * Reset and power off the physical layer.
1845  *
1846  * Another RESET should get it back to working, but it may take a few
1847  * seconds it may take a few moments to return to normal operation ...
1848  */
1849 int
1850 bge_phys_idle(bge_t *bgep)
1851 {
1852 	BGE_TRACE(("bge_phys_idle($%p)", (void *)bgep));
1853 
1854 	ASSERT(mutex_owned(bgep->genlock));
1855 	return ((*bgep->physops->phys_restart)(bgep, B_TRUE));
1856 }
1857 
1858 /*
1859  * Synchronise the PHYSICAL layer's speed/duplex/autonegotiation capabilities
1860  * and advertisements with the required settings as specified by the various
1861  * param_* variables that can be poked via the NDD interface.
1862  *
1863  * We always reset the PHYSICAL layer and reprogram *all* relevant registers.
1864  * This is expected to cause the link to go down, and then back up again once
1865  * the link is stable and autonegotiation (if enabled) is complete.  We should
1866  * get a link state change interrupt somewhere along the way ...
1867  *
1868  * NOTE: <genlock> must already be held by the caller
1869  */
1870 int
1871 bge_phys_update(bge_t *bgep)
1872 {
1873 	BGE_TRACE(("bge_phys_update($%p)", (void *)bgep));
1874 
1875 	ASSERT(mutex_owned(bgep->genlock));
1876 	return ((*bgep->physops->phys_update)(bgep));
1877 }
1878 
1879 #undef	BGE_DBG
1880 #define	BGE_DBG		BGE_DBG_LINK	/* debug flag for this code	*/
1881 
1882 /*
1883  * Read the link status and determine whether anything's changed ...
1884  *
1885  * This routine should be called whenever the chip flags a change
1886  * in the hardware link state.
1887  *
1888  * This routine returns B_FALSE if the link state has not changed,
1889  * returns B_TRUE when the change to the new state should be accepted.
1890  * In such a case, the param_* variables give the new hardware state,
1891  * which the caller should use to update link_state etc.
1892  *
1893  * The caller must already hold <genlock>
1894  */
1895 boolean_t
1896 bge_phys_check(bge_t *bgep)
1897 {
1898 	BGE_TRACE(("bge_phys_check($%p)", (void *)bgep));
1899 
1900 	ASSERT(mutex_owned(bgep->genlock));
1901 
1902 	/*
1903 	 * Force a link recheck if current state is unknown.
1904 	 * phys_check() returns TRUE if the link status changed,
1905 	 * FALSE otherwise.
1906 	 */
1907 	return ((*bgep->physops->phys_check)(bgep,
1908 	    (bgep->link_state == LINK_STATE_UNKNOWN)));
1909 }
1910