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