xref: /titanic_44/usr/src/uts/common/io/mii/mii.c (revision 1e4c938b57d1656808e4112127ff1dce3eba5314)
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  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * mii - MII/PHY support for MAC drivers
28  *
29  * Utility module to provide a consistent interface to a MAC driver accross
30  * different implementations of PHY devices
31  */
32 
33 #include <sys/types.h>
34 #include <sys/debug.h>
35 #include <sys/errno.h>
36 #include <sys/param.h>
37 #include <sys/kmem.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/cmn_err.h>
43 #include <sys/policy.h>
44 #include <sys/note.h>
45 #include <sys/strsun.h>
46 #include <sys/miiregs.h>
47 #include <sys/mac_provider.h>
48 #include <sys/mac_ether.h>
49 #include <sys/mii.h>
50 #include "miipriv.h"
51 
52 #define	MII_SECOND	1000000
53 
54 /* indices into error array */
55 enum {
56 	MII_EOK = 0,
57 	MII_ERESET,
58 	MII_ESTART,
59 	MII_ENOPHY,
60 	MII_ECHECK,
61 	MII_ELOOP,
62 };
63 
64 static const char *mii_errors[] = {
65 	"",
66 	"Failure resetting PHY.",
67 	"Failure starting PHY.",
68 	"No Ethernet PHY found.",
69 	"Failure reading PHY (removed?)",
70 	"Failure setting loopback."
71 };
72 
73 /* Indexed by XCVR_ type */
74 static const const char *mii_xcvr_types[] = {
75 	"Undefined",
76 	"Unknown",
77 	"10 Mbps",
78 	"100BASE-T4",
79 	"100BASE-X",
80 	"100BASE-T2",
81 	"1000BASE-X",
82 	"1000BASE-T"
83 };
84 
85 /* state machine */
86 typedef enum {
87 	MII_STATE_PROBE = 0,
88 	MII_STATE_RESET,
89 	MII_STATE_START,
90 	MII_STATE_RUN,
91 	MII_STATE_LOOPBACK,
92 } mii_tstate_t;
93 
94 struct mii_handle {
95 	dev_info_t	*m_dip;
96 	void		*m_private;
97 	mii_ops_t	m_ops;
98 
99 	kt_did_t	m_tq_id;
100 	kmutex_t	m_lock;
101 	kcondvar_t	m_cv;
102 	ddi_taskq_t	*m_tq;
103 	int		m_flags;
104 
105 	boolean_t	m_started;
106 	boolean_t	m_suspending;
107 	boolean_t	m_suspended;
108 	int		m_error;
109 	mii_tstate_t	m_tstate;
110 
111 #define	MII_FLAG_EXIT		0x1	/* exit the thread */
112 #define	MII_FLAG_STOP		0x2	/* shutdown MII monitoring */
113 #define	MII_FLAG_RESET		0x4	/* reset the MII */
114 #define	MII_FLAG_PROBE		0x8	/* probe for PHYs */
115 #define	MII_FLAG_NOTIFY		0x10	/* notify about a change */
116 #define	MII_FLAG_SUSPEND	0x20	/* monitoring suspended */
117 #define	MII_FLAG_MACRESET	0x40	/* send reset to MAC */
118 #define	MII_FLAG_PHYSTART	0x80	/* start up the PHY */
119 
120 	/* device name for printing, e.g. "hme0" */
121 	char		m_name[MODMAXNAMELEN + 16];
122 
123 	int		m_addr;
124 	phy_handle_t	m_phys[32];
125 	phy_handle_t	m_bogus_phy;
126 	phy_handle_t	*m_phy;
127 
128 	link_state_t	m_link;
129 
130 	/* these start out undefined, but get values due to mac_prop_set */
131 	int		m_en_aneg;
132 	int		m_en_10_hdx;
133 	int		m_en_10_fdx;
134 	int		m_en_100_t4;
135 	int		m_en_100_hdx;
136 	int		m_en_100_fdx;
137 	int		m_en_1000_hdx;
138 	int		m_en_1000_fdx;
139 	int		m_en_flowctrl;
140 
141 	boolean_t	m_cap_pause;
142 	boolean_t	m_cap_asmpause;
143 };
144 
145 
146 static void _mii_task(void *);
147 static void _mii_probe_phy(phy_handle_t *);
148 static void _mii_probe(mii_handle_t);
149 static int _mii_reset(mii_handle_t);
150 static int _mii_loopback(mii_handle_t);
151 static void _mii_notify(mii_handle_t);
152 static int _mii_check(mii_handle_t);
153 static int _mii_start(mii_handle_t);
154 
155 /*
156  * Loadable module structures/entrypoints
157  */
158 
159 extern struct mod_ops mod_misc_ops;
160 
161 static struct modlmisc modlmisc = {
162 	&mod_miscops,
163 	"802.3 MII support",
164 };
165 
166 static struct modlinkage modlinkage = {
167 	MODREV_1, &modlmisc, NULL
168 };
169 
170 int
171 _init(void)
172 {
173 	return (mod_install(&modlinkage));
174 }
175 
176 int
177 _fini(void)
178 {
179 	return (mod_remove(&modlinkage));
180 }
181 
182 int
183 _info(struct modinfo *modinfop)
184 {
185 	return (mod_info(&modlinkage, modinfop));
186 }
187 
188 void
189 _mii_error(mii_handle_t mh, int errno)
190 {
191 	/*
192 	 * This dumps an error message, but it avoids filling the log with
193 	 * repeated error messages.
194 	 */
195 	if (mh->m_error != errno) {
196 		cmn_err(CE_WARN, "%s: %s", mh->m_name, mii_errors[errno]);
197 		mh->m_error = errno;
198 	}
199 }
200 
201 /*
202  * Known list of specific PHY probes.
203  */
204 typedef boolean_t (*phy_probe_t)(phy_handle_t *);
205 phy_probe_t _phy_probes[] = {
206 	phy_natsemi_probe,
207 	phy_intel_probe,
208 	phy_qualsemi_probe,
209 	phy_cicada_probe,
210 	phy_marvell_probe,
211 	phy_realtek_probe,
212 	phy_other_probe,
213 	NULL
214 };
215 
216 /*
217  * MII Interface functions
218  */
219 
220 mii_handle_t
221 mii_alloc_instance(void *private, dev_info_t *dip, int inst, mii_ops_t *ops)
222 {
223 	mii_handle_t	mh;
224 	char		tqname[16];
225 
226 	if (ops->mii_version != MII_OPS_VERSION) {
227 		cmn_err(CE_WARN, "%s: incompatible MII version (%d)",
228 		    ddi_driver_name(dip), ops->mii_version);
229 		return (NULL);
230 	}
231 	mh = kmem_zalloc(sizeof (*mh), KM_SLEEP);
232 
233 	(void) snprintf(mh->m_name, sizeof (mh->m_name), "%s%d",
234 	    ddi_driver_name(dip), inst);
235 
236 	/* DDI will prepend the driver name */
237 	(void) snprintf(tqname, sizeof (tqname), "mii%d", inst);
238 
239 	mh->m_dip = dip;
240 	mh->m_ops = *ops;
241 	mh->m_private = private;
242 	mh->m_suspended = B_FALSE;
243 	mh->m_started = B_FALSE;
244 	mh->m_tstate = MII_STATE_PROBE;
245 	mh->m_link = LINK_STATE_UNKNOWN;
246 	mh->m_error = MII_EOK;
247 	mh->m_addr = -1;
248 	mutex_init(&mh->m_lock, NULL, MUTEX_DRIVER, NULL);
249 	cv_init(&mh->m_cv, NULL, CV_DRIVER, NULL);
250 
251 	mh->m_tq = ddi_taskq_create(dip, tqname, 1, TASKQ_DEFAULTPRI, 0);
252 	if (mh->m_tq == NULL) {
253 		cmn_err(CE_WARN, "%s: unable to create MII monitoring task",
254 		    ddi_driver_name(dip));
255 		cv_destroy(&mh->m_cv);
256 		mutex_destroy(&mh->m_lock);
257 		kmem_free(mh, sizeof (*mh));
258 		return (NULL);
259 	}
260 
261 	/*
262 	 * Initialize user prefs by loading properties.  Ultimately,
263 	 * Brussels interfaces would be superior here.
264 	 */
265 #define	GETPROP(name)	ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, name, -1)
266 	mh->m_en_aneg = GETPROP("adv_autoneg_cap");
267 	mh->m_en_10_hdx = GETPROP("adv_10hdx_cap");
268 	mh->m_en_10_fdx = GETPROP("adv_10fdx_cap");
269 	mh->m_en_100_hdx = GETPROP("adv_100hdx_cap");
270 	mh->m_en_100_fdx = GETPROP("adv_100fdx_cap");
271 	mh->m_en_100_t4 = GETPROP("adv_100T4_cap");
272 	mh->m_en_1000_hdx = GETPROP("adv_1000hdx_cap");
273 	mh->m_en_1000_fdx = GETPROP("adv_1000fdx_cap");
274 
275 	mh->m_cap_pause = B_FALSE;
276 	mh->m_cap_asmpause = B_FALSE;
277 
278 	bzero(&mh->m_bogus_phy, sizeof (mh->m_bogus_phy));
279 	mh->m_bogus_phy.phy_link = LINK_STATE_UNKNOWN;
280 	mh->m_bogus_phy.phy_duplex = LINK_DUPLEX_UNKNOWN;
281 	mh->m_bogus_phy.phy_addr = 0xff;
282 	mh->m_bogus_phy.phy_type = XCVR_NONE;
283 	mh->m_bogus_phy.phy_id = (uint32_t)-1;
284 	mh->m_bogus_phy.phy_loopback = PHY_LB_NONE;
285 	mh->m_bogus_phy.phy_flowctrl = LINK_FLOWCTRL_NONE;
286 	mh->m_phy = &mh->m_bogus_phy;
287 
288 	for (int i = 0; i < 32; i++) {
289 		mh->m_phys[i].phy_mii = mh;
290 	}
291 	mh->m_bogus_phy.phy_mii = mh;
292 
293 	return (mh);
294 }
295 
296 mii_handle_t
297 mii_alloc(void *private, dev_info_t *dip, mii_ops_t *ops)
298 {
299 	return (mii_alloc_instance(private, dip, ddi_get_instance(dip), ops));
300 }
301 
302 void
303 mii_set_pauseable(mii_handle_t mh, boolean_t pauseable, boolean_t asymetric)
304 {
305 	phy_handle_t	*ph;
306 
307 	mutex_enter(&mh->m_lock);
308 	ph = mh->m_phy;
309 	ph->phy_cap_pause = mh->m_cap_pause = pauseable;
310 	ph->phy_cap_asmpause = mh->m_cap_asmpause = asymetric;
311 	if (pauseable) {
312 		mh->m_en_flowctrl = LINK_FLOWCTRL_BI;
313 	} else {
314 		mh->m_en_flowctrl = LINK_FLOWCTRL_NONE;
315 	}
316 	mutex_exit(&mh->m_lock);
317 }
318 
319 void
320 mii_free(mii_handle_t mh)
321 {
322 	mutex_enter(&mh->m_lock);
323 	mh->m_started = B_FALSE;
324 	cv_broadcast(&mh->m_cv);
325 	mutex_exit(&mh->m_lock);
326 
327 	ddi_taskq_destroy(mh->m_tq);
328 	mutex_destroy(&mh->m_lock);
329 	cv_destroy(&mh->m_cv);
330 	kmem_free(mh, sizeof (*mh));
331 }
332 
333 void
334 mii_reset(mii_handle_t mh)
335 {
336 	mutex_enter(&mh->m_lock);
337 	if (mh->m_tstate > MII_STATE_RESET)
338 		mh->m_tstate = MII_STATE_RESET;
339 	cv_broadcast(&mh->m_cv);
340 	mutex_exit(&mh->m_lock);
341 }
342 
343 void
344 mii_suspend(mii_handle_t mh)
345 {
346 	mutex_enter(&mh->m_lock);
347 	while ((!mh->m_suspended) && (mh->m_started)) {
348 		mh->m_suspending = B_TRUE;
349 		cv_broadcast(&mh->m_cv);
350 		cv_wait(&mh->m_cv, &mh->m_lock);
351 	}
352 	mutex_exit(&mh->m_lock);
353 }
354 
355 void
356 mii_resume(mii_handle_t mh)
357 {
358 	mutex_enter(&mh->m_lock);
359 
360 	switch (mh->m_tstate) {
361 	case MII_STATE_PROBE:
362 		break;
363 	case MII_STATE_RESET:
364 	case MII_STATE_START:
365 	case MII_STATE_RUN:
366 		/* let monitor thread deal with this */
367 		mh->m_tstate = MII_STATE_RESET;
368 		break;
369 
370 	case MII_STATE_LOOPBACK:
371 		/* loopback is handled synchronously */
372 		(void) _mii_loopback(mh);
373 		break;
374 	}
375 
376 	mh->m_suspended = B_FALSE;
377 	cv_broadcast(&mh->m_cv);
378 	mutex_exit(&mh->m_lock);
379 }
380 
381 void
382 mii_start(mii_handle_t mh)
383 {
384 	mutex_enter(&mh->m_lock);
385 	if (!mh->m_started) {
386 		mh->m_tstate = MII_STATE_PROBE;
387 		mh->m_started = B_TRUE;
388 		if (ddi_taskq_dispatch(mh->m_tq, _mii_task, mh, DDI_NOSLEEP) !=
389 		    DDI_SUCCESS) {
390 			cmn_err(CE_WARN,
391 			    "%s: unable to start MII monitoring task",
392 			    mh->m_name);
393 			mh->m_started = B_FALSE;
394 		}
395 	}
396 	cv_broadcast(&mh->m_cv);
397 	mutex_exit(&mh->m_lock);
398 }
399 
400 void
401 mii_stop(mii_handle_t mh)
402 {
403 	mutex_enter(&mh->m_lock);
404 	mh->m_started = B_FALSE;
405 	/*
406 	 * Reset link state to unknown defaults, since we're not
407 	 * monitoring it anymore.  We'll reprobe all link state later.
408 	 */
409 	mh->m_link = LINK_STATE_UNKNOWN;
410 	mh->m_phy = &mh->m_bogus_phy;
411 	cv_broadcast(&mh->m_cv);
412 	mutex_exit(&mh->m_lock);
413 	/*
414 	 * Notify the MAC driver.  This will allow it to call back
415 	 * into the MAC framework to clear any previous link state.
416 	 */
417 	_mii_notify(mh);
418 }
419 
420 void
421 mii_probe(mii_handle_t mh)
422 {
423 	mutex_enter(&mh->m_lock);
424 	_mii_probe(mh);
425 	mutex_exit(&mh->m_lock);
426 }
427 
428 void
429 mii_check(mii_handle_t mh)
430 {
431 	mutex_enter(&mh->m_lock);
432 	cv_broadcast(&mh->m_cv);
433 	mutex_exit(&mh->m_lock);
434 }
435 
436 int
437 mii_get_speed(mii_handle_t mh)
438 {
439 	phy_handle_t	*ph = mh->m_phy;
440 
441 	return (ph->phy_speed);
442 }
443 
444 link_duplex_t
445 mii_get_duplex(mii_handle_t mh)
446 {
447 	phy_handle_t	*ph = mh->m_phy;
448 
449 	return (ph->phy_duplex);
450 }
451 
452 link_state_t
453 mii_get_state(mii_handle_t mh)
454 {
455 	phy_handle_t	*ph = mh->m_phy;
456 
457 	return (ph->phy_link);
458 }
459 
460 link_flowctrl_t
461 mii_get_flowctrl(mii_handle_t mh)
462 {
463 	phy_handle_t	*ph = mh->m_phy;
464 
465 	return (ph->phy_flowctrl);
466 }
467 
468 int
469 mii_get_loopmodes(mii_handle_t mh, lb_property_t *modes)
470 {
471 	phy_handle_t	*ph = mh->m_phy;
472 	int		cnt = 0;
473 	lb_property_t	lmodes[MII_LOOPBACK_MAX];
474 
475 	lmodes[cnt].lb_type = normal;
476 	(void) strlcpy(lmodes[cnt].key, "normal", sizeof (lmodes[cnt].key));
477 	lmodes[cnt].value = PHY_LB_NONE;
478 	cnt++;
479 
480 	if (ph->phy_cap_1000_fdx ||
481 	    ph->phy_cap_100_fdx ||
482 	    ph->phy_cap_10_fdx) {
483 		/* we only support full duplex internal phy testing */
484 		lmodes[cnt].lb_type = internal;
485 		(void) strlcpy(lmodes[cnt].key, "PHY",
486 		    sizeof (lmodes[cnt].key));
487 		lmodes[cnt].value = PHY_LB_INT_PHY;
488 		cnt++;
489 	}
490 
491 	if (ph->phy_cap_1000_fdx) {
492 		lmodes[cnt].lb_type = external;
493 		(void) strlcpy(lmodes[cnt].key, "1000Mbps",
494 		    sizeof (lmodes[cnt].key));
495 		lmodes[cnt].value = PHY_LB_EXT_1000;
496 		cnt++;
497 	}
498 
499 	if (ph->phy_cap_100_fdx) {
500 		lmodes[cnt].lb_type = external;
501 		(void) strlcpy(lmodes[cnt].key, "100Mbps",
502 		    sizeof (lmodes[cnt].key));
503 		lmodes[cnt].value = PHY_LB_EXT_100;
504 		cnt++;
505 	}
506 
507 	if (ph->phy_cap_10_fdx) {
508 		lmodes[cnt].lb_type = external;
509 		(void) strlcpy(lmodes[cnt].key, "10Mbps",
510 		    sizeof (lmodes[cnt].key));
511 		lmodes[cnt].value = PHY_LB_EXT_10;
512 		cnt++;
513 	}
514 
515 	if (modes) {
516 		bcopy(lmodes, modes, sizeof (lb_property_t) * cnt);
517 	}
518 
519 	return (cnt);
520 }
521 
522 uint32_t
523 mii_get_loopback(mii_handle_t mh)
524 {
525 	phy_handle_t	*ph = mh->m_phy;
526 
527 	return (ph->phy_loopback);
528 }
529 
530 int
531 mii_set_loopback(mii_handle_t mh, uint32_t loop)
532 {
533 	phy_handle_t	*ph;
534 	int		rv;
535 
536 	mutex_enter(&mh->m_lock);
537 	ph = mh->m_phy;
538 
539 	if ((!mh->m_started) || (!ph->phy_present) ||
540 	    (loop >= mii_get_loopmodes(mh, NULL))) {
541 		return (EINVAL);
542 	}
543 
544 	ph->phy_loopback = loop;
545 	rv = _mii_loopback(mh);
546 	if (rv == DDI_SUCCESS) {
547 		mh->m_tstate = MII_STATE_LOOPBACK;
548 	}
549 	cv_broadcast(&mh->m_cv);
550 	mutex_exit(&mh->m_lock);
551 
552 	return (rv == DDI_SUCCESS ? 0 : EIO);
553 }
554 
555 uint32_t
556 mii_get_id(mii_handle_t mh)
557 {
558 	phy_handle_t	*ph = mh->m_phy;
559 
560 	return (ph->phy_id);
561 }
562 
563 int
564 mii_get_addr(mii_handle_t mh)
565 {
566 	return (mh->m_addr);
567 }
568 
569 /* GLDv3 helpers */
570 
571 boolean_t
572 mii_m_loop_ioctl(mii_handle_t mh, queue_t *wq, mblk_t *mp)
573 {
574 	struct iocblk	*iocp;
575 	int		rv = 0;
576 	int		cnt;
577 	lb_property_t	modes[MII_LOOPBACK_MAX];
578 	lb_info_sz_t	sz;
579 	int		cmd;
580 	uint32_t	mode;
581 
582 	iocp = (void *)mp->b_rptr;
583 	cmd = iocp->ioc_cmd;
584 
585 	switch (cmd) {
586 	case LB_SET_MODE:
587 	case LB_GET_INFO_SIZE:
588 	case LB_GET_INFO:
589 	case LB_GET_MODE:
590 		break;
591 
592 	default:
593 		return (B_FALSE);
594 	}
595 
596 	if (mp->b_cont == NULL) {
597 		miocnak(wq, mp, 0, EINVAL);
598 		return (B_TRUE);
599 	}
600 
601 	switch (cmd) {
602 	case LB_GET_INFO_SIZE:
603 		cnt = mii_get_loopmodes(mh, modes);
604 		if (iocp->ioc_count != sizeof (sz)) {
605 			rv = EINVAL;
606 		} else {
607 			sz = cnt * sizeof (lb_property_t);
608 			bcopy(&sz, mp->b_cont->b_rptr, sizeof (sz));
609 		}
610 		break;
611 
612 	case LB_GET_INFO:
613 		cnt = mii_get_loopmodes(mh, modes);
614 		if (iocp->ioc_count != (cnt * sizeof (lb_property_t))) {
615 			rv = EINVAL;
616 		} else {
617 			bcopy(modes, mp->b_cont->b_rptr, iocp->ioc_count);
618 		}
619 		break;
620 
621 	case LB_GET_MODE:
622 		if (iocp->ioc_count != sizeof (mode)) {
623 			rv = EINVAL;
624 		} else {
625 			mode = mii_get_loopback(mh);
626 			bcopy(&mode, mp->b_cont->b_rptr, sizeof (mode));
627 		}
628 		break;
629 
630 	case LB_SET_MODE:
631 		rv = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
632 		if (rv != 0)
633 			break;
634 		if (iocp->ioc_count != sizeof (mode)) {
635 			rv = EINVAL;
636 			break;
637 		}
638 		bcopy(mp->b_cont->b_rptr, &mode, sizeof (mode));
639 		rv = mii_set_loopback(mh, mode);
640 		break;
641 	}
642 
643 	if (rv == 0) {
644 		miocack(wq, mp, iocp->ioc_count, 0);
645 	} else {
646 		miocnak(wq, mp, 0, rv);
647 	}
648 	return (B_TRUE);
649 }
650 
651 int
652 mii_m_getprop(mii_handle_t mh, const char *name, mac_prop_id_t num,
653     uint_t sz, void *val)
654 {
655 	phy_handle_t	*ph;
656 	int		err = 0;
657 
658 	_NOTE(ARGUNUSED(name));
659 
660 	if (sz < 1)
661 		return (EINVAL);
662 
663 	mutex_enter(&mh->m_lock);
664 
665 	ph = mh->m_phy;
666 
667 #define	CASE_PROP_ABILITY(PROP, VAR)					\
668 	case MAC_PROP_ADV_##PROP:					\
669 		*(uint8_t *)val = ph->phy_adv_##VAR;			\
670 		break;							\
671 									\
672 	case MAC_PROP_EN_##PROP:					\
673 		*(uint8_t *)val = ph->phy_en_##VAR;			\
674 		break;
675 
676 	switch (num) {
677 	case MAC_PROP_DUPLEX:
678 		ASSERT(sz >= sizeof (link_duplex_t));
679 		bcopy(&ph->phy_duplex, val, sizeof (link_duplex_t));
680 		break;
681 
682 	case MAC_PROP_SPEED: {
683 		uint64_t speed = ph->phy_speed * 1000000ull;
684 		ASSERT(sz >= sizeof (uint64_t));
685 		bcopy(&speed, val, sizeof (speed));
686 		break;
687 	}
688 
689 	case MAC_PROP_AUTONEG:
690 		*(uint8_t *)val = ph->phy_adv_aneg;
691 		break;
692 
693 	case MAC_PROP_FLOWCTRL:
694 		ASSERT(sz >= sizeof (link_flowctrl_t));
695 		bcopy(&ph->phy_flowctrl, val, sizeof (link_flowctrl_t));
696 		break;
697 
698 	CASE_PROP_ABILITY(1000FDX_CAP, 1000_fdx)
699 	CASE_PROP_ABILITY(1000HDX_CAP, 1000_hdx)
700 	CASE_PROP_ABILITY(100T4_CAP, 100_t4)
701 	CASE_PROP_ABILITY(100FDX_CAP, 100_fdx)
702 	CASE_PROP_ABILITY(100HDX_CAP, 100_hdx)
703 	CASE_PROP_ABILITY(10FDX_CAP, 10_fdx)
704 	CASE_PROP_ABILITY(10HDX_CAP, 10_hdx)
705 
706 	default:
707 		err = ENOTSUP;
708 		break;
709 	}
710 
711 	mutex_exit(&mh->m_lock);
712 
713 	return (err);
714 }
715 
716 void
717 mii_m_propinfo(mii_handle_t mh, const char *name, mac_prop_id_t num,
718     mac_prop_info_handle_t prh)
719 {
720 	phy_handle_t	*ph;
721 
722 	_NOTE(ARGUNUSED(name));
723 
724 	mutex_enter(&mh->m_lock);
725 
726 	ph = mh->m_phy;
727 
728 	switch (num) {
729 	case MAC_PROP_DUPLEX:
730 	case MAC_PROP_SPEED:
731 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
732 		break;
733 
734 	case MAC_PROP_AUTONEG:
735 		mac_prop_info_set_default_uint8(prh, ph->phy_cap_aneg);
736 		break;
737 
738 #define	CASE_PROP_PERM(PROP, VAR)					\
739 	case MAC_PROP_ADV_##PROP:					\
740 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);	\
741 		mac_prop_info_set_default_uint8(prh, ph->phy_cap_##VAR); \
742 		break;							\
743 									\
744 	case MAC_PROP_EN_##PROP:					\
745 		if (!ph->phy_cap_##VAR)					\
746 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); \
747 		mac_prop_info_set_default_uint8(prh, ph->phy_cap_##VAR); \
748 		break;
749 
750 	CASE_PROP_PERM(1000FDX_CAP, 1000_fdx)
751 	CASE_PROP_PERM(1000HDX_CAP, 1000_hdx)
752 	CASE_PROP_PERM(100T4_CAP, 100_t4)
753 	CASE_PROP_PERM(100FDX_CAP, 100_fdx)
754 	CASE_PROP_PERM(100HDX_CAP, 100_hdx)
755 	CASE_PROP_PERM(10FDX_CAP, 10_fdx)
756 	CASE_PROP_PERM(10HDX_CAP, 10_hdx)
757 	}
758 
759 	mutex_exit(&mh->m_lock);
760 }
761 
762 int
763 mii_m_setprop(mii_handle_t mh, const char *name, mac_prop_id_t num,
764     uint_t sz, const void *valp)
765 {
766 	phy_handle_t	*ph;
767 	boolean_t	*advp = NULL;
768 	boolean_t	*capp = NULL;
769 	int		*macpp = NULL;
770 	int		rv = ENOTSUP;
771 
772 	_NOTE(ARGUNUSED(name));
773 
774 	if (sz < 1)
775 		return (EINVAL);
776 
777 	mutex_enter(&mh->m_lock);
778 
779 	ph = mh->m_phy;
780 
781 	/* we don't support changing parameters while in loopback mode */
782 	if (ph->phy_loopback != PHY_LB_NONE) {
783 		switch (num) {
784 		case MAC_PROP_EN_1000FDX_CAP:
785 		case MAC_PROP_EN_1000HDX_CAP:
786 		case MAC_PROP_EN_100FDX_CAP:
787 		case MAC_PROP_EN_100HDX_CAP:
788 		case MAC_PROP_EN_100T4_CAP:
789 		case MAC_PROP_EN_10FDX_CAP:
790 		case MAC_PROP_EN_10HDX_CAP:
791 		case MAC_PROP_AUTONEG:
792 		case MAC_PROP_FLOWCTRL:
793 			return (EBUSY);
794 		}
795 	}
796 
797 	switch (num) {
798 	case MAC_PROP_EN_1000FDX_CAP:
799 		capp = &ph->phy_cap_1000_fdx;
800 		advp = &ph->phy_en_1000_fdx;
801 		macpp = &mh->m_en_1000_fdx;
802 		break;
803 	case MAC_PROP_EN_1000HDX_CAP:
804 		capp = &ph->phy_cap_1000_hdx;
805 		advp = &ph->phy_en_1000_hdx;
806 		macpp = &mh->m_en_1000_hdx;
807 		break;
808 	case MAC_PROP_EN_100FDX_CAP:
809 		capp = &ph->phy_cap_100_fdx;
810 		advp = &ph->phy_en_100_fdx;
811 		macpp = &mh->m_en_100_fdx;
812 		break;
813 	case MAC_PROP_EN_100HDX_CAP:
814 		capp = &ph->phy_cap_100_hdx;
815 		advp = &ph->phy_en_100_hdx;
816 		macpp = &mh->m_en_100_hdx;
817 		break;
818 	case MAC_PROP_EN_100T4_CAP:
819 		capp = &ph->phy_cap_100_t4;
820 		advp = &ph->phy_en_100_t4;
821 		macpp = &mh->m_en_100_t4;
822 		break;
823 	case MAC_PROP_EN_10FDX_CAP:
824 		capp = &ph->phy_cap_10_fdx;
825 		advp = &ph->phy_en_10_fdx;
826 		macpp = &mh->m_en_10_fdx;
827 		break;
828 	case MAC_PROP_EN_10HDX_CAP:
829 		capp = &ph->phy_cap_10_hdx;
830 		advp = &ph->phy_en_10_hdx;
831 		macpp = &mh->m_en_10_hdx;
832 		break;
833 	case MAC_PROP_AUTONEG:
834 		capp = &ph->phy_cap_aneg;
835 		advp = &ph->phy_en_aneg;
836 		macpp = &mh->m_en_aneg;
837 		break;
838 	case MAC_PROP_FLOWCTRL: {
839 		link_flowctrl_t	fc;
840 		boolean_t chg;
841 
842 		ASSERT(sz >= sizeof (link_flowctrl_t));
843 		bcopy(valp, &fc, sizeof (fc));
844 
845 		chg = fc == ph->phy_en_flowctrl ? B_FALSE : B_TRUE;
846 		switch (fc) {
847 		case LINK_FLOWCTRL_NONE:
848 			ph->phy_en_pause = B_FALSE;
849 			ph->phy_en_asmpause = B_FALSE;
850 			ph->phy_en_flowctrl = fc;
851 			break;
852 		/*
853 		 * Note that while we don't have a way to advertise
854 		 * that we can RX pause (we just won't send pause
855 		 * frames), we advertise full support.  The MAC driver
856 		 * will learn of the configuration via the saved value
857 		 * of the tunable.
858 		 */
859 		case LINK_FLOWCTRL_BI:
860 		case LINK_FLOWCTRL_RX:
861 			if (ph->phy_cap_pause) {
862 				ph->phy_en_pause = B_TRUE;
863 				ph->phy_en_asmpause = B_TRUE;
864 				ph->phy_en_flowctrl = fc;
865 			} else {
866 				rv = EINVAL;
867 			}
868 			break;
869 
870 		/*
871 		 * Tell the other side that we can assert pause, but
872 		 * we cannot resend.
873 		 */
874 		case LINK_FLOWCTRL_TX:
875 			if (ph->phy_cap_asmpause) {
876 				ph->phy_en_pause = B_FALSE;
877 				ph->phy_en_flowctrl = fc;
878 				ph->phy_en_asmpause = B_TRUE;
879 			} else {
880 				rv = EINVAL;
881 			}
882 			break;
883 		default:
884 			rv = EINVAL;
885 			break;
886 		}
887 		if ((rv == 0) && chg) {
888 			mh->m_en_flowctrl = fc;
889 			mh->m_tstate = MII_STATE_RESET;
890 			cv_broadcast(&mh->m_cv);
891 		}
892 		break;
893 	}
894 
895 	default:
896 		rv = ENOTSUP;
897 		break;
898 	}
899 
900 	if (capp && advp && macpp) {
901 		if (sz < sizeof (uint8_t)) {
902 			rv = EINVAL;
903 
904 		} else if (*capp) {
905 			if (*advp != *(uint8_t *)valp) {
906 				*advp = *(uint8_t *)valp;
907 				*macpp = *(uint8_t *)valp;
908 				mh->m_tstate = MII_STATE_RESET;
909 				cv_broadcast(&mh->m_cv);
910 			}
911 			rv = 0;
912 		}
913 	}
914 
915 	mutex_exit(&mh->m_lock);
916 	return (rv);
917 }
918 
919 int
920 mii_m_getstat(mii_handle_t mh, uint_t stat, uint64_t *val)
921 {
922 	phy_handle_t	*ph;
923 	int		rv = 0;
924 
925 	mutex_enter(&mh->m_lock);
926 
927 	ph = mh->m_phy;
928 
929 	switch (stat) {
930 	case MAC_STAT_IFSPEED:
931 		*val = ph->phy_speed * 1000000ull;
932 		break;
933 	case ETHER_STAT_LINK_DUPLEX:
934 		*val = ph->phy_duplex;
935 		break;
936 	case ETHER_STAT_LINK_AUTONEG:
937 		*val = !!(ph->phy_adv_aneg && ph->phy_lp_aneg);
938 		break;
939 	case ETHER_STAT_XCVR_ID:
940 		*val = ph->phy_id;
941 		break;
942 	case ETHER_STAT_XCVR_INUSE:
943 		*val = ph->phy_type;
944 		break;
945 	case ETHER_STAT_XCVR_ADDR:
946 		*val = ph->phy_addr;
947 		break;
948 	case ETHER_STAT_LINK_ASMPAUSE:
949 		*val = ph->phy_adv_asmpause && ph->phy_lp_asmpause &&
950 		    ph->phy_adv_pause != ph->phy_lp_pause;
951 		break;
952 	case ETHER_STAT_LINK_PAUSE:
953 		*val = (ph->phy_flowctrl == LINK_FLOWCTRL_BI) ||
954 		    (ph->phy_flowctrl == LINK_FLOWCTRL_RX);
955 		break;
956 	case ETHER_STAT_CAP_1000FDX:
957 		*val = ph->phy_cap_1000_fdx;
958 		break;
959 	case ETHER_STAT_CAP_1000HDX:
960 		*val = ph->phy_cap_1000_hdx;
961 		break;
962 	case ETHER_STAT_CAP_100FDX:
963 		*val = ph->phy_cap_100_fdx;
964 		break;
965 	case ETHER_STAT_CAP_100HDX:
966 		*val = ph->phy_cap_100_hdx;
967 		break;
968 	case ETHER_STAT_CAP_10FDX:
969 		*val = ph->phy_cap_10_fdx;
970 		break;
971 	case ETHER_STAT_CAP_10HDX:
972 		*val = ph->phy_cap_10_hdx;
973 		break;
974 	case ETHER_STAT_CAP_100T4:
975 		*val = ph->phy_cap_100_t4;
976 		break;
977 	case ETHER_STAT_CAP_AUTONEG:
978 		*val = ph->phy_cap_aneg;
979 		break;
980 	case ETHER_STAT_CAP_PAUSE:
981 		*val = ph->phy_cap_pause;
982 		break;
983 	case ETHER_STAT_CAP_ASMPAUSE:
984 		*val = ph->phy_cap_asmpause;
985 		break;
986 
987 	case ETHER_STAT_LP_CAP_1000FDX:
988 		*val = ph->phy_lp_1000_fdx;
989 		break;
990 	case ETHER_STAT_LP_CAP_1000HDX:
991 		*val = ph->phy_lp_1000_hdx;
992 		break;
993 	case ETHER_STAT_LP_CAP_100FDX:
994 		*val = ph->phy_lp_100_fdx;
995 		break;
996 	case ETHER_STAT_LP_CAP_100HDX:
997 		*val = ph->phy_lp_100_hdx;
998 		break;
999 	case ETHER_STAT_LP_CAP_10FDX:
1000 		*val = ph->phy_lp_10_fdx;
1001 		break;
1002 	case ETHER_STAT_LP_CAP_10HDX:
1003 		*val = ph->phy_lp_10_hdx;
1004 		break;
1005 	case ETHER_STAT_LP_CAP_100T4:
1006 		*val = ph->phy_lp_100_t4;
1007 		break;
1008 	case ETHER_STAT_LP_CAP_AUTONEG:
1009 		*val = ph->phy_lp_aneg;
1010 		break;
1011 	case ETHER_STAT_LP_CAP_PAUSE:
1012 		*val = ph->phy_lp_pause;
1013 		break;
1014 	case ETHER_STAT_LP_CAP_ASMPAUSE:
1015 		*val = ph->phy_lp_asmpause;
1016 		break;
1017 
1018 	case ETHER_STAT_ADV_CAP_1000FDX:
1019 		*val = ph->phy_adv_1000_fdx;
1020 		break;
1021 	case ETHER_STAT_ADV_CAP_1000HDX:
1022 		*val = ph->phy_adv_1000_hdx;
1023 		break;
1024 	case ETHER_STAT_ADV_CAP_100FDX:
1025 		*val = ph->phy_adv_100_fdx;
1026 		break;
1027 	case ETHER_STAT_ADV_CAP_100HDX:
1028 		*val = ph->phy_adv_100_hdx;
1029 		break;
1030 	case ETHER_STAT_ADV_CAP_10FDX:
1031 		*val = ph->phy_adv_10_fdx;
1032 		break;
1033 	case ETHER_STAT_ADV_CAP_10HDX:
1034 		*val = ph->phy_adv_10_hdx;
1035 		break;
1036 	case ETHER_STAT_ADV_CAP_100T4:
1037 		*val = ph->phy_adv_100_t4;
1038 		break;
1039 	case ETHER_STAT_ADV_CAP_AUTONEG:
1040 		*val = ph->phy_adv_aneg;
1041 		break;
1042 	case ETHER_STAT_ADV_CAP_PAUSE:
1043 		*val = ph->phy_adv_pause;
1044 		break;
1045 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
1046 		*val = ph->phy_adv_asmpause;
1047 		break;
1048 
1049 	default:
1050 		rv = ENOTSUP;
1051 		break;
1052 	}
1053 	mutex_exit(&mh->m_lock);
1054 
1055 	return (rv);
1056 }
1057 
1058 /*
1059  * PHY support routines.  Private to the MII module and the vendor
1060  * specific PHY implementation code.
1061  */
1062 uint16_t
1063 phy_read(phy_handle_t *ph, uint8_t reg)
1064 {
1065 	mii_handle_t	mh = ph->phy_mii;
1066 
1067 	return ((*mh->m_ops.mii_read)(mh->m_private, ph->phy_addr, reg));
1068 }
1069 
1070 void
1071 phy_write(phy_handle_t *ph, uint8_t reg, uint16_t val)
1072 {
1073 	mii_handle_t	mh = ph->phy_mii;
1074 
1075 	(*mh->m_ops.mii_write)(mh->m_private, ph->phy_addr, reg, val);
1076 }
1077 
1078 int
1079 phy_reset(phy_handle_t *ph)
1080 {
1081 	ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1082 
1083 	/*
1084 	 * For our device, make sure its powered up and unisolated.
1085 	 */
1086 	PHY_CLR(ph, MII_CONTROL,
1087 	    MII_CONTROL_PWRDN | MII_CONTROL_ISOLATE);
1088 
1089 	/*
1090 	 * Finally reset it.
1091 	 */
1092 	PHY_SET(ph, MII_CONTROL, MII_CONTROL_RESET);
1093 
1094 	/*
1095 	 * Apparently some devices (DP83840A) like to have a little
1096 	 * bit of a wait before we start accessing anything else on
1097 	 * the PHY.
1098 	 */
1099 	drv_usecwait(500);
1100 
1101 	/*
1102 	 * Wait for reset to complete - probably very fast, but no
1103 	 * more than 0.5 sec according to spec.  It would be nice if
1104 	 * we could use delay() here, but MAC drivers may call
1105 	 * functions which hold this lock in interrupt context, so
1106 	 * sleeping would be a definite no-no.  The good news here is
1107 	 * that it seems to be the case that most devices come back
1108 	 * within only a few hundred usec.
1109 	 */
1110 	for (int i = 500000; i; i -= 100) {
1111 		if ((phy_read(ph, MII_CONTROL) & MII_CONTROL_RESET) == 0) {
1112 			/* reset completed */
1113 			return (DDI_SUCCESS);
1114 		}
1115 		drv_usecwait(100);
1116 	}
1117 
1118 	return (DDI_FAILURE);
1119 }
1120 
1121 int
1122 phy_stop(phy_handle_t *ph)
1123 {
1124 	phy_write(ph, MII_CONTROL, MII_CONTROL_ISOLATE);
1125 
1126 	return (DDI_SUCCESS);
1127 }
1128 
1129 int
1130 phy_loop(phy_handle_t *ph)
1131 {
1132 	uint16_t	bmcr, gtcr;
1133 
1134 	ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1135 
1136 	/*
1137 	 * Disable everything to start... we'll add in modes as we go.
1138 	 */
1139 	ph->phy_adv_aneg = B_FALSE;
1140 	ph->phy_adv_1000_fdx = B_FALSE;
1141 	ph->phy_adv_1000_hdx = B_FALSE;
1142 	ph->phy_adv_100_fdx = B_FALSE;
1143 	ph->phy_adv_100_t4 = B_FALSE;
1144 	ph->phy_adv_100_hdx = B_FALSE;
1145 	ph->phy_adv_10_fdx = B_FALSE;
1146 	ph->phy_adv_10_hdx = B_FALSE;
1147 	ph->phy_adv_pause = B_FALSE;
1148 	ph->phy_adv_asmpause = B_FALSE;
1149 
1150 	bmcr = 0;
1151 	gtcr = MII_MSCONTROL_MANUAL | MII_MSCONTROL_MASTER;
1152 
1153 	switch (ph->phy_loopback) {
1154 	case PHY_LB_NONE:
1155 		/* We shouldn't be here */
1156 		ASSERT(0);
1157 		break;
1158 
1159 	case PHY_LB_INT_PHY:
1160 		bmcr |= MII_CONTROL_LOOPBACK;
1161 		ph->phy_duplex = LINK_DUPLEX_FULL;
1162 		if (ph->phy_cap_1000_fdx) {
1163 			bmcr |= MII_CONTROL_1GB | MII_CONTROL_FDUPLEX;
1164 			ph->phy_speed = 1000;
1165 		} else if (ph->phy_cap_100_fdx) {
1166 			bmcr |= MII_CONTROL_100MB | MII_CONTROL_FDUPLEX;
1167 			ph->phy_speed = 100;
1168 		} else if (ph->phy_cap_10_fdx) {
1169 			bmcr |= MII_CONTROL_FDUPLEX;
1170 			ph->phy_speed = 10;
1171 		}
1172 		break;
1173 
1174 	case PHY_LB_EXT_10:
1175 		bmcr = MII_CONTROL_FDUPLEX;
1176 		ph->phy_speed = 10;
1177 		ph->phy_duplex = LINK_DUPLEX_FULL;
1178 		break;
1179 
1180 	case PHY_LB_EXT_100:
1181 		bmcr = MII_CONTROL_100MB | MII_CONTROL_FDUPLEX;
1182 		ph->phy_speed = 100;
1183 		ph->phy_duplex = LINK_DUPLEX_FULL;
1184 		break;
1185 
1186 	case PHY_LB_EXT_1000:
1187 		bmcr = MII_CONTROL_1GB | MII_CONTROL_FDUPLEX;
1188 		ph->phy_speed = 1000;
1189 		ph->phy_duplex = LINK_DUPLEX_FULL;
1190 		break;
1191 	}
1192 
1193 	ph->phy_link = LINK_STATE_UP;	/* force up for loopback */
1194 	ph->phy_flowctrl = LINK_FLOWCTRL_NONE;
1195 
1196 	switch (ph->phy_type) {
1197 	case XCVR_1000T:
1198 	case XCVR_1000X:
1199 	case XCVR_100T2:
1200 		phy_write(ph, MII_MSCONTROL, gtcr);
1201 		break;
1202 	}
1203 
1204 	phy_write(ph, MII_CONTROL, bmcr);
1205 
1206 	return (DDI_SUCCESS);
1207 }
1208 
1209 int
1210 phy_start(phy_handle_t *ph)
1211 {
1212 	uint16_t	bmcr, anar, gtcr;
1213 	ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1214 
1215 	ASSERT(ph->phy_loopback == PHY_LB_NONE);
1216 
1217 	/*
1218 	 * No loopback overrides, so try to advertise everything
1219 	 * that is administratively enabled.
1220 	 */
1221 	ph->phy_adv_aneg = ph->phy_en_aneg;
1222 	ph->phy_adv_1000_fdx = ph->phy_en_1000_fdx;
1223 	ph->phy_adv_1000_hdx = ph->phy_en_1000_hdx;
1224 	ph->phy_adv_100_fdx = ph->phy_en_100_fdx;
1225 	ph->phy_adv_100_t4 = ph->phy_en_100_t4;
1226 	ph->phy_adv_100_hdx = ph->phy_en_100_hdx;
1227 	ph->phy_adv_10_fdx = ph->phy_en_10_fdx;
1228 	ph->phy_adv_10_hdx = ph->phy_en_10_hdx;
1229 	ph->phy_adv_pause = ph->phy_en_pause;
1230 	ph->phy_adv_asmpause = ph->phy_en_asmpause;
1231 
1232 	/*
1233 	 * Limit properties to what the hardware can actually support.
1234 	 */
1235 #define	FILTER_ADV(CAP)		\
1236 	if (!ph->phy_cap_##CAP)	\
1237 	    ph->phy_adv_##CAP = 0
1238 
1239 	FILTER_ADV(aneg);
1240 	FILTER_ADV(1000_fdx);
1241 	FILTER_ADV(1000_hdx);
1242 	FILTER_ADV(100_fdx);
1243 	FILTER_ADV(100_t4);
1244 	FILTER_ADV(100_hdx);
1245 	FILTER_ADV(10_fdx);
1246 	FILTER_ADV(10_hdx);
1247 	FILTER_ADV(pause);
1248 	FILTER_ADV(asmpause);
1249 
1250 #undef	FILTER_ADV
1251 
1252 	/*
1253 	 * We need at least one valid mode.
1254 	 */
1255 	if ((!ph->phy_adv_1000_fdx) &&
1256 	    (!ph->phy_adv_1000_hdx) &&
1257 	    (!ph->phy_adv_100_t4) &&
1258 	    (!ph->phy_adv_100_fdx) &&
1259 	    (!ph->phy_adv_100_hdx) &&
1260 	    (!ph->phy_adv_10_fdx) &&
1261 	    (!ph->phy_adv_10_hdx)) {
1262 
1263 		phy_warn(ph,
1264 		    "No valid link mode selected.  Powering down PHY.");
1265 
1266 		PHY_SET(ph, MII_CONTROL, MII_CONTROL_PWRDN);
1267 
1268 		ph->phy_link = LINK_STATE_DOWN;
1269 		return (DDI_SUCCESS);
1270 	}
1271 
1272 	bmcr = 0;
1273 	gtcr = 0;
1274 
1275 	if (ph->phy_adv_aneg) {
1276 		bmcr |= MII_CONTROL_ANE | MII_CONTROL_RSAN;
1277 	}
1278 
1279 	if ((ph->phy_adv_1000_fdx) || (ph->phy_adv_1000_hdx)) {
1280 		bmcr |= MII_CONTROL_1GB;
1281 
1282 	} else if (ph->phy_adv_100_fdx || ph->phy_adv_100_hdx ||
1283 	    ph->phy_adv_100_t4) {
1284 		bmcr |= MII_CONTROL_100MB;
1285 	}
1286 
1287 	if (ph->phy_adv_1000_fdx || ph->phy_adv_100_fdx || ph->phy_adv_10_fdx) {
1288 		bmcr |= MII_CONTROL_FDUPLEX;
1289 	}
1290 
1291 	if (ph->phy_type == XCVR_1000X) {
1292 		/* 1000BASE-X (usually fiber) */
1293 		anar = 0;
1294 		if (ph->phy_adv_1000_fdx) {
1295 			anar |= MII_ABILITY_X_FD;
1296 		}
1297 		if (ph->phy_adv_1000_hdx) {
1298 			anar |= MII_ABILITY_X_HD;
1299 		}
1300 		if (ph->phy_adv_pause) {
1301 			anar |= MII_ABILITY_X_PAUSE;
1302 		}
1303 		if (ph->phy_adv_asmpause) {
1304 			anar |= MII_ABILITY_X_ASMPAUSE;
1305 		}
1306 
1307 	} else if (ph->phy_type == XCVR_100T2) {
1308 		/* 100BASE-T2 */
1309 		anar = 0;
1310 		if (ph->phy_adv_100_fdx) {
1311 			anar |= MII_ABILITY_T2_FD;
1312 		}
1313 		if (ph->phy_adv_100_hdx) {
1314 			anar |= MII_ABILITY_T2_HD;
1315 		}
1316 
1317 	} else {
1318 		anar = MII_AN_SELECTOR_8023;
1319 
1320 		/* 1000BASE-T or 100BASE-X probably  */
1321 		if (ph->phy_adv_1000_fdx) {
1322 			gtcr |= MII_MSCONTROL_1000T_FD;
1323 		}
1324 		if (ph->phy_adv_1000_hdx) {
1325 			gtcr |= MII_MSCONTROL_1000T;
1326 		}
1327 		if (ph->phy_adv_100_fdx) {
1328 			anar |= MII_ABILITY_100BASE_TX_FD;
1329 		}
1330 		if (ph->phy_adv_100_hdx) {
1331 			anar |= MII_ABILITY_100BASE_TX;
1332 		}
1333 		if (ph->phy_adv_100_t4) {
1334 			anar |= MII_ABILITY_100BASE_T4;
1335 		}
1336 		if (ph->phy_adv_10_fdx) {
1337 			anar |= MII_ABILITY_10BASE_T_FD;
1338 		}
1339 		if (ph->phy_adv_10_hdx) {
1340 			anar |= MII_ABILITY_10BASE_T;
1341 		}
1342 		if (ph->phy_adv_pause) {
1343 			anar |= MII_ABILITY_PAUSE;
1344 		}
1345 		if (ph->phy_adv_asmpause) {
1346 			anar |= MII_ABILITY_ASMPAUSE;
1347 		}
1348 	}
1349 
1350 	ph->phy_link = LINK_STATE_DOWN;
1351 	ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1352 	ph->phy_speed = 0;
1353 
1354 	phy_write(ph, MII_AN_ADVERT, anar);
1355 	phy_write(ph, MII_CONTROL, bmcr & ~(MII_CONTROL_RSAN));
1356 
1357 	switch (ph->phy_type) {
1358 	case XCVR_1000T:
1359 	case XCVR_1000X:
1360 	case XCVR_100T2:
1361 		phy_write(ph, MII_MSCONTROL, gtcr);
1362 	}
1363 
1364 	/*
1365 	 * Finally, this will start up autoneg if it is enabled, or
1366 	 * force link settings otherwise.
1367 	 */
1368 	phy_write(ph, MII_CONTROL, bmcr);
1369 
1370 	return (DDI_SUCCESS);
1371 }
1372 
1373 
1374 int
1375 phy_check(phy_handle_t *ph)
1376 {
1377 	uint16_t control, status, lpar, msstat, anexp;
1378 	int debounces = 100;
1379 
1380 	ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1381 
1382 debounce:
1383 	status = phy_read(ph, MII_STATUS);
1384 	control = phy_read(ph, MII_CONTROL);
1385 
1386 	if (status & MII_STATUS_EXTENDED) {
1387 		lpar = phy_read(ph, MII_AN_LPABLE);
1388 		anexp = phy_read(ph, MII_AN_EXPANSION);
1389 	} else {
1390 		lpar = 0;
1391 		anexp = 0;
1392 	}
1393 
1394 	/*
1395 	 * We reread to clear any latched bits.  This also debounces
1396 	 * any state that might be in transition.
1397 	 */
1398 	drv_usecwait(10);
1399 	if ((status != phy_read(ph, MII_STATUS)) && debounces) {
1400 		debounces--;
1401 		goto debounce;
1402 	}
1403 
1404 	/*
1405 	 * Detect the situation where the PHY is removed or has died.
1406 	 * According to spec, at least one bit of status must be set,
1407 	 * and at least one bit must be clear.
1408 	 */
1409 	if ((status == 0xffff) || (status == 0)) {
1410 		ph->phy_speed = 0;
1411 		ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1412 		ph->phy_link = LINK_STATE_UNKNOWN;
1413 		ph->phy_present = B_FALSE;
1414 		return (DDI_FAILURE);
1415 	}
1416 
1417 	/* We only respect the link flag if we are not in loopback. */
1418 	if ((ph->phy_loopback != PHY_LB_INT_PHY) &&
1419 	    ((status & MII_STATUS_LINKUP) == 0)) {
1420 		ph->phy_speed = 0;
1421 		ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1422 		ph->phy_link = LINK_STATE_DOWN;
1423 		return (DDI_SUCCESS);
1424 	}
1425 
1426 	ph->phy_link = LINK_STATE_UP;
1427 
1428 	if ((control & MII_CONTROL_ANE) == 0) {
1429 
1430 		ph->phy_lp_aneg = B_FALSE;
1431 		ph->phy_lp_10_hdx = B_FALSE;
1432 		ph->phy_lp_10_fdx = B_FALSE;
1433 		ph->phy_lp_100_t4 = B_FALSE;
1434 		ph->phy_lp_100_hdx = B_FALSE;
1435 		ph->phy_lp_100_fdx = B_FALSE;
1436 		ph->phy_lp_1000_hdx = B_FALSE;
1437 		ph->phy_lp_1000_fdx = B_FALSE;
1438 
1439 		/*
1440 		 * We have no idea what our link partner might or might
1441 		 * not be able to support, except that it appears to
1442 		 * support the same mode that we have forced.
1443 		 */
1444 		if (control & MII_CONTROL_1GB) {
1445 			ph->phy_speed = 1000;
1446 		} else if (control & MII_CONTROL_100MB) {
1447 			ph->phy_speed = 100;
1448 		} else {
1449 			ph->phy_speed = 10;
1450 		}
1451 		ph->phy_duplex = control & MII_CONTROL_FDUPLEX ?
1452 		    LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
1453 
1454 		return (DDI_SUCCESS);
1455 	}
1456 
1457 	if (ph->phy_type == XCVR_1000X) {
1458 
1459 		ph->phy_lp_10_hdx = B_FALSE;
1460 		ph->phy_lp_10_fdx = B_FALSE;
1461 		ph->phy_lp_100_t4 = B_FALSE;
1462 		ph->phy_lp_100_hdx = B_FALSE;
1463 		ph->phy_lp_100_fdx = B_FALSE;
1464 
1465 		/* 1000BASE-X requires autonegotiation */
1466 		ph->phy_lp_aneg = B_TRUE;
1467 		ph->phy_lp_1000_fdx = !!(lpar & MII_ABILITY_X_FD);
1468 		ph->phy_lp_1000_hdx = !!(lpar & MII_ABILITY_X_HD);
1469 		ph->phy_lp_pause = !!(lpar & MII_ABILITY_X_PAUSE);
1470 		ph->phy_lp_asmpause = !!(lpar & MII_ABILITY_X_ASMPAUSE);
1471 
1472 	} else if (ph->phy_type == XCVR_100T2) {
1473 		ph->phy_lp_10_hdx = B_FALSE;
1474 		ph->phy_lp_10_fdx = B_FALSE;
1475 		ph->phy_lp_100_t4 = B_FALSE;
1476 		ph->phy_lp_1000_hdx = B_FALSE;
1477 		ph->phy_lp_1000_fdx = B_FALSE;
1478 		ph->phy_lp_pause = B_FALSE;
1479 		ph->phy_lp_asmpause = B_FALSE;
1480 
1481 		/* 100BASE-T2 requires autonegotiation */
1482 		ph->phy_lp_aneg = B_TRUE;
1483 		ph->phy_lp_100_fdx = !!(lpar & MII_ABILITY_T2_FD);
1484 		ph->phy_lp_100_hdx = !!(lpar & MII_ABILITY_T2_HD);
1485 
1486 	} else if (anexp & MII_AN_EXP_PARFAULT) {
1487 		/*
1488 		 * Parallel detection fault!  This happens when the
1489 		 * peer does not use autonegotiation, and the
1490 		 * detection logic reports more than one type of legal
1491 		 * link is available.  Note that parallel detection
1492 		 * can only happen with half duplex 10, 100, and
1493 		 * 100TX4.  We also should not have got here, because
1494 		 * the link state bit should have failed.
1495 		 */
1496 #ifdef	DEBUG
1497 		phy_warn(ph, "Parallel detection fault!");
1498 #endif
1499 		ph->phy_lp_10_hdx = B_FALSE;
1500 		ph->phy_lp_10_fdx = B_FALSE;
1501 		ph->phy_lp_100_t4 = B_FALSE;
1502 		ph->phy_lp_100_hdx = B_FALSE;
1503 		ph->phy_lp_100_fdx = B_FALSE;
1504 		ph->phy_lp_1000_hdx = B_FALSE;
1505 		ph->phy_lp_1000_fdx = B_FALSE;
1506 		ph->phy_lp_pause = B_FALSE;
1507 		ph->phy_lp_asmpause = B_FALSE;
1508 		ph->phy_speed = 0;
1509 		ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1510 		return (DDI_SUCCESS);
1511 
1512 	} else {
1513 		ph->phy_lp_aneg = !!(anexp & MII_AN_EXP_LPCANAN);
1514 
1515 		/*
1516 		 * Note: If the peer doesn't support autonegotiation, then
1517 		 * according to clause 28.5.4.5, the link partner ability
1518 		 * register will still have the right bits set.  However,
1519 		 * gigabit modes cannot use legacy parallel detection.
1520 		 */
1521 
1522 		if ((ph->phy_type == XCVR_1000T) &
1523 		    (anexp & MII_AN_EXP_LPCANAN)) {
1524 
1525 			/* check for gige */
1526 			msstat = phy_read(ph, MII_MSSTATUS);
1527 
1528 			ph->phy_lp_1000_hdx =
1529 			    !!(msstat & MII_MSSTATUS_LP1000T);
1530 
1531 			ph->phy_lp_1000_fdx =
1532 			    !!(msstat & MII_MSSTATUS_LP1000T_FD);
1533 		}
1534 
1535 		ph->phy_lp_100_fdx = !!(lpar & MII_ABILITY_100BASE_TX_FD);
1536 		ph->phy_lp_100_hdx = !!(lpar & MII_ABILITY_100BASE_TX);
1537 		ph->phy_lp_100_t4 = !!(lpar & MII_ABILITY_100BASE_T4);
1538 		ph->phy_lp_10_fdx = !!(lpar & MII_ABILITY_10BASE_T_FD);
1539 		ph->phy_lp_10_hdx = !!(lpar & MII_ABILITY_10BASE_T);
1540 		ph->phy_lp_pause = !!(lpar & MII_ABILITY_PAUSE);
1541 		ph->phy_lp_asmpause = !!(lpar & MII_ABILITY_ASMPAUSE);
1542 	}
1543 
1544 	/* resolve link pause */
1545 	if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_BI) &&
1546 	    (ph->phy_lp_pause)) {
1547 		ph->phy_flowctrl = LINK_FLOWCTRL_BI;
1548 	} else if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_RX) &&
1549 	    (ph->phy_lp_pause || ph->phy_lp_asmpause)) {
1550 		ph->phy_flowctrl = LINK_FLOWCTRL_RX;
1551 	} else if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_TX) &&
1552 	    (ph->phy_lp_pause)) {
1553 		ph->phy_flowctrl = LINK_FLOWCTRL_TX;
1554 	} else {
1555 		ph->phy_flowctrl = LINK_FLOWCTRL_NONE;
1556 	}
1557 
1558 	if (ph->phy_adv_1000_fdx && ph->phy_lp_1000_fdx) {
1559 		ph->phy_speed = 1000;
1560 		ph->phy_duplex = LINK_DUPLEX_FULL;
1561 
1562 	} else if (ph->phy_adv_1000_hdx && ph->phy_lp_1000_hdx) {
1563 		ph->phy_speed = 1000;
1564 		ph->phy_duplex = LINK_DUPLEX_HALF;
1565 
1566 	} else if (ph->phy_adv_100_fdx && ph->phy_lp_100_fdx) {
1567 		ph->phy_speed = 100;
1568 		ph->phy_duplex = LINK_DUPLEX_FULL;
1569 
1570 	} else if (ph->phy_adv_100_t4 && ph->phy_lp_100_t4) {
1571 		ph->phy_speed = 100;
1572 		ph->phy_duplex = LINK_DUPLEX_HALF;
1573 
1574 	} else if (ph->phy_adv_100_hdx && ph->phy_lp_100_hdx) {
1575 		ph->phy_speed = 100;
1576 		ph->phy_duplex = LINK_DUPLEX_HALF;
1577 
1578 	} else if (ph->phy_adv_10_fdx && ph->phy_lp_10_fdx) {
1579 		ph->phy_speed = 10;
1580 		ph->phy_duplex = LINK_DUPLEX_FULL;
1581 
1582 	} else if (ph->phy_adv_10_hdx && ph->phy_lp_10_hdx) {
1583 		ph->phy_speed = 10;
1584 		ph->phy_duplex = LINK_DUPLEX_HALF;
1585 
1586 	} else {
1587 #ifdef	DEBUG
1588 		phy_warn(ph, "No common abilities.");
1589 #endif
1590 		ph->phy_speed = 0;
1591 		ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1592 	}
1593 
1594 	return (DDI_SUCCESS);
1595 }
1596 
1597 int
1598 phy_get_prop(phy_handle_t *ph, char *prop, int dflt)
1599 {
1600 	mii_handle_t	mh = ph->phy_mii;
1601 
1602 	return (ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0, prop, dflt));
1603 }
1604 
1605 const char *
1606 phy_get_name(phy_handle_t *ph)
1607 {
1608 	mii_handle_t	mh = ph->phy_mii;
1609 
1610 	return (mh->m_name);
1611 }
1612 
1613 const char *
1614 phy_get_driver(phy_handle_t *ph)
1615 {
1616 	mii_handle_t	mh = ph->phy_mii;
1617 
1618 	return (ddi_driver_name(mh->m_dip));
1619 }
1620 
1621 void
1622 phy_warn(phy_handle_t *ph, const char *fmt, ...)
1623 {
1624 	va_list	va;
1625 	char buf[256];
1626 
1627 	(void) snprintf(buf, sizeof (buf), "%s: %s", phy_get_name(ph), fmt);
1628 
1629 	va_start(va, fmt);
1630 	vcmn_err(CE_WARN, buf, va);
1631 	va_end(va);
1632 }
1633 
1634 /*
1635  * Internal support routines.
1636  */
1637 
1638 void
1639 _mii_notify(mii_handle_t mh)
1640 {
1641 	if (mh->m_ops.mii_notify != NULL) {
1642 		mh->m_ops.mii_notify(mh->m_private, mh->m_link);
1643 	}
1644 }
1645 
1646 void
1647 _mii_probe_phy(phy_handle_t *ph)
1648 {
1649 	uint16_t	bmsr;
1650 	uint16_t	extsr;
1651 	mii_handle_t	mh = ph->phy_mii;
1652 
1653 
1654 	/*
1655 	 * Apparently, PHY 0 is less likely to be physically
1656 	 * connected, and should always be the last one tried.  Most
1657 	 * single solution NICs use PHY1 for their built-in
1658 	 * transceiver.  NICs with an external MII will often place
1659 	 * the external PHY at address 1, and use address 0 for the
1660 	 * internal PHY.
1661 	 */
1662 
1663 	ph->phy_id = 0;
1664 	ph->phy_model = "PHY";
1665 	ph->phy_vendor = "Unknown Vendor";
1666 
1667 	/* done twice to clear any latched bits */
1668 	bmsr = phy_read(ph, MII_STATUS);
1669 	bmsr = phy_read(ph, MII_STATUS);
1670 	if ((bmsr == 0) || (bmsr == 0xffff)) {
1671 		ph->phy_present = B_FALSE;
1672 		return;
1673 	}
1674 
1675 	if (bmsr & MII_STATUS_EXTSTAT) {
1676 		extsr = phy_read(ph, MII_EXTSTATUS);
1677 	} else {
1678 		extsr = 0;
1679 	}
1680 
1681 	ph->phy_present = B_TRUE;
1682 	ph->phy_id = ((uint32_t)phy_read(ph, MII_PHYIDH) << 16) |
1683 	    phy_read(ph, MII_PHYIDL);
1684 
1685 	/* setup default handlers */
1686 	ph->phy_reset = phy_reset;
1687 	ph->phy_start = phy_start;
1688 	ph->phy_stop = phy_stop;
1689 	ph->phy_check = phy_check;
1690 	ph->phy_loop = phy_loop;
1691 
1692 	/*
1693 	 * We ignore the non-existent 100baseT2 stuff -- no
1694 	 * known products for it exist.
1695 	 */
1696 	ph->phy_cap_aneg =	!!(bmsr & MII_STATUS_CANAUTONEG);
1697 	ph->phy_cap_100_t4 =	!!(bmsr & MII_STATUS_100_BASE_T4);
1698 	ph->phy_cap_100_fdx =	!!(bmsr & MII_STATUS_100_BASEX_FD);
1699 	ph->phy_cap_100_hdx =	!!(bmsr & MII_STATUS_100_BASEX);
1700 	ph->phy_cap_10_fdx =	!!(bmsr & MII_STATUS_10_FD);
1701 	ph->phy_cap_10_hdx =	!!(bmsr & MII_STATUS_10);
1702 	ph->phy_cap_1000_fdx =
1703 	    !!(extsr & (MII_EXTSTATUS_1000X_FD|MII_EXTSTATUS_1000T_FD));
1704 	ph->phy_cap_1000_hdx =
1705 	    !!(extsr & (MII_EXTSTATUS_1000X | MII_EXTSTATUS_1000T));
1706 	ph->phy_cap_pause =	mh->m_cap_pause;
1707 	ph->phy_cap_asmpause =	mh->m_cap_asmpause;
1708 
1709 	if (bmsr & MII_STATUS_10) {
1710 		ph->phy_cap_10_hdx = B_TRUE;
1711 		ph->phy_type = XCVR_10;
1712 	}
1713 	if (bmsr & MII_STATUS_10_FD) {
1714 		ph->phy_cap_10_fdx = B_TRUE;
1715 		ph->phy_type = XCVR_10;
1716 	}
1717 	if (bmsr & MII_STATUS_100T2) {
1718 		ph->phy_cap_100_hdx = B_TRUE;
1719 		ph->phy_type = XCVR_100T2;
1720 	}
1721 	if (bmsr & MII_STATUS_100T2_FD) {
1722 		ph->phy_cap_100_fdx = B_TRUE;
1723 		ph->phy_type = XCVR_100T2;
1724 	}
1725 	if (bmsr & MII_STATUS_100_BASE_T4) {
1726 		ph->phy_cap_100_hdx = B_TRUE;
1727 		ph->phy_type = XCVR_100T4;
1728 	}
1729 	if (bmsr & MII_STATUS_100_BASEX) {
1730 		ph->phy_cap_100_hdx = B_TRUE;
1731 		ph->phy_type = XCVR_100X;
1732 	}
1733 	if (bmsr & MII_STATUS_100_BASEX_FD) {
1734 		ph->phy_cap_100_fdx = B_TRUE;
1735 		ph->phy_type = XCVR_100X;
1736 	}
1737 	if (extsr & MII_EXTSTATUS_1000X) {
1738 		ph->phy_cap_1000_hdx = B_TRUE;
1739 		ph->phy_type = XCVR_1000X;
1740 	}
1741 	if (extsr & MII_EXTSTATUS_1000X_FD) {
1742 		ph->phy_cap_1000_fdx = B_TRUE;
1743 		ph->phy_type = XCVR_1000X;
1744 	}
1745 	if (extsr & MII_EXTSTATUS_1000T) {
1746 		ph->phy_cap_1000_hdx = B_TRUE;
1747 		ph->phy_type = XCVR_1000T;
1748 	}
1749 	if (extsr & MII_EXTSTATUS_1000T_FD) {
1750 		ph->phy_cap_1000_fdx = B_TRUE;
1751 		ph->phy_type = XCVR_1000T;
1752 	}
1753 
1754 	for (int j = 0; _phy_probes[j] != NULL; j++) {
1755 		if ((*_phy_probes[j])(ph)) {
1756 			break;
1757 		}
1758 	}
1759 
1760 #define	INIT_ENABLE(CAP)	\
1761 	ph->phy_en_##CAP = (mh->m_en_##CAP > 0) ? \
1762 	    mh->m_en_##CAP : ph->phy_cap_##CAP
1763 
1764 	INIT_ENABLE(aneg);
1765 	INIT_ENABLE(1000_fdx);
1766 	INIT_ENABLE(1000_hdx);
1767 	INIT_ENABLE(100_fdx);
1768 	INIT_ENABLE(100_t4);
1769 	INIT_ENABLE(100_hdx);
1770 	INIT_ENABLE(10_fdx);
1771 	INIT_ENABLE(10_hdx);
1772 
1773 #undef	INIT_ENABLE
1774 	ph->phy_en_flowctrl = mh->m_en_flowctrl;
1775 	switch (ph->phy_en_flowctrl) {
1776 	case LINK_FLOWCTRL_BI:
1777 	case LINK_FLOWCTRL_RX:
1778 		ph->phy_en_pause = B_TRUE;
1779 		ph->phy_en_asmpause = B_TRUE;
1780 		break;
1781 	case LINK_FLOWCTRL_TX:
1782 		ph->phy_en_pause = B_FALSE;
1783 		ph->phy_en_asmpause = B_TRUE;
1784 		break;
1785 	default:
1786 		ph->phy_en_pause = B_FALSE;
1787 		ph->phy_en_asmpause = B_FALSE;
1788 		break;
1789 	}
1790 }
1791 
1792 void
1793 _mii_probe(mii_handle_t mh)
1794 {
1795 	uint8_t		new_addr;
1796 	uint8_t		old_addr;
1797 	uint8_t		user_addr;
1798 	uint8_t		curr_addr;
1799 	phy_handle_t	*ph;
1800 	int		pri = 0;
1801 	int		first;
1802 
1803 	user_addr = ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0,
1804 	    "phy-addr", -1);
1805 	old_addr = mh->m_addr;
1806 	new_addr = 0xff;
1807 
1808 	/*
1809 	 * Apparently, PHY 0 is less likely to be physically
1810 	 * connected, and should always be the last one tried.  Most
1811 	 * single solution NICs use PHY1 for their built-in
1812 	 * transceiver.  NICs with an external MII will often place
1813 	 * the external PHY at address 1, and use address 0 for the
1814 	 * internal PHY.
1815 	 *
1816 	 * Some devices have a different preference however.  They can
1817 	 * override the default starting point of the search by
1818 	 * exporting a "first-phy" property.
1819 	 */
1820 
1821 	first = ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0, "first-phy", 1);
1822 	if ((first < 0) || (first > 31)) {
1823 		first = 1;
1824 	}
1825 	for (int i = first; i < (first + 32); i++) {
1826 
1827 		/*
1828 		 * This is tricky: it lets us start searching at an
1829 		 * arbitrary address instead of 0, dealing with the
1830 		 * wrap-around at address 31 properly.
1831 		 */
1832 		curr_addr = i % 32;
1833 
1834 		ph = &mh->m_phys[curr_addr];
1835 
1836 		bzero(ph, sizeof (*ph));
1837 		ph->phy_addr = curr_addr;
1838 		ph->phy_mii = mh;
1839 
1840 		_mii_probe_phy(ph);
1841 
1842 		if (!ph->phy_present)
1843 			continue;
1844 
1845 		if (curr_addr == user_addr) {
1846 			/*
1847 			 * We always try to honor the user configured phy.
1848 			 */
1849 			new_addr = curr_addr;
1850 			pri = 4;
1851 
1852 		}
1853 
1854 		/* two reads to clear latched bits */
1855 		if ((phy_read(ph, MII_STATUS) & MII_STATUS_LINKUP) &&
1856 		    (phy_read(ph, MII_STATUS) & MII_STATUS_LINKUP) &&
1857 		    (pri < 3)) {
1858 			/*
1859 			 * Link present is good.  We prefer this over
1860 			 * a possibly disconnected link.
1861 			 */
1862 			new_addr = curr_addr;
1863 			pri = 3;
1864 		}
1865 		if ((curr_addr == old_addr) && (pri < 2)) {
1866 			/*
1867 			 * All else being equal, minimize change.
1868 			 */
1869 			new_addr = curr_addr;
1870 			pri = 2;
1871 
1872 		}
1873 		if (pri < 1) {
1874 			/*
1875 			 * But make sure we at least select a present PHY.
1876 			 */
1877 			new_addr = curr_addr;
1878 			pri = 1;
1879 		}
1880 	}
1881 
1882 	if (new_addr == 0xff) {
1883 		mh->m_addr = -1;
1884 		mh->m_phy = &mh->m_bogus_phy;
1885 		_mii_error(mh, MII_ENOPHY);
1886 	} else {
1887 		mh->m_addr = new_addr;
1888 		mh->m_phy = &mh->m_phys[new_addr];
1889 		mh->m_tstate = MII_STATE_RESET;
1890 		if (new_addr != old_addr) {
1891 			cmn_err(CE_CONT,
1892 			    "?%s: Using %s Ethernet PHY at %d: %s %s\n",
1893 			    mh->m_name, mii_xcvr_types[mh->m_phy->phy_type],
1894 			    mh->m_addr, mh->m_phy->phy_vendor,
1895 			    mh->m_phy->phy_model);
1896 			mh->m_link = LINK_STATE_UNKNOWN;
1897 		}
1898 	}
1899 }
1900 
1901 int
1902 _mii_reset(mii_handle_t mh)
1903 {
1904 	phy_handle_t	*ph;
1905 	boolean_t	notify;
1906 
1907 	ASSERT(mutex_owned(&mh->m_lock));
1908 
1909 	/*
1910 	 * Reset logic.  We want to isolate all the other
1911 	 * phys that are not in use.
1912 	 */
1913 	for (int i = 0; i < 32; i++) {
1914 		ph = &mh->m_phys[i];
1915 
1916 		if (!ph->phy_present)
1917 			continue;
1918 
1919 		/* Don't touch our own phy, yet. */
1920 		if (ph == mh->m_phy)
1921 			continue;
1922 
1923 		ph->phy_stop(ph);
1924 	}
1925 
1926 	ph = mh->m_phy;
1927 
1928 	ASSERT(ph->phy_present);
1929 
1930 	/* If we're resetting the PHY, then we want to notify loss of link */
1931 	notify = (mh->m_link != LINK_STATE_DOWN);
1932 	mh->m_link = LINK_STATE_DOWN;
1933 	ph->phy_link = LINK_STATE_DOWN;
1934 	ph->phy_speed = 0;
1935 	ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1936 
1937 	if (ph->phy_reset(ph) != DDI_SUCCESS) {
1938 		_mii_error(mh, MII_ERESET);
1939 		return (DDI_FAILURE);
1940 	}
1941 
1942 	/* Perform optional mac layer reset. */
1943 	if (mh->m_ops.mii_reset != NULL) {
1944 		mh->m_ops.mii_reset(mh->m_private);
1945 	}
1946 
1947 	/* Perform optional mac layer notification. */
1948 	if (notify) {
1949 		_mii_notify(mh);
1950 	}
1951 	return (DDI_SUCCESS);
1952 }
1953 
1954 int
1955 _mii_loopback(mii_handle_t mh)
1956 {
1957 	phy_handle_t	*ph;
1958 
1959 	ASSERT(mutex_owned(&mh->m_lock));
1960 
1961 	ph = mh->m_phy;
1962 
1963 	if (_mii_reset(mh) != DDI_SUCCESS) {
1964 		return (DDI_FAILURE);
1965 	}
1966 	if (ph->phy_loopback == PHY_LB_NONE) {
1967 		mh->m_tstate = MII_STATE_START;
1968 		return (DDI_SUCCESS);
1969 	}
1970 	if (ph->phy_loop(ph) != DDI_SUCCESS) {
1971 		_mii_error(mh, MII_ELOOP);
1972 		return (DDI_FAILURE);
1973 	}
1974 
1975 	/* Just force loopback to link up. */
1976 	mh->m_link = ph->phy_link = LINK_STATE_UP;
1977 	_mii_notify(mh);
1978 
1979 	return (DDI_SUCCESS);
1980 }
1981 
1982 int
1983 _mii_start(mii_handle_t mh)
1984 {
1985 	phy_handle_t		*ph;
1986 
1987 	ph = mh->m_phy;
1988 
1989 	ASSERT(mutex_owned(&mh->m_lock));
1990 	ASSERT(ph->phy_present);
1991 	ASSERT(ph->phy_loopback == PHY_LB_NONE);
1992 
1993 	if (ph->phy_start(ph) != DDI_SUCCESS) {
1994 		_mii_error(mh, MII_ESTART);
1995 		return (DDI_FAILURE);
1996 	}
1997 	/* clear the error state since we got a good startup! */
1998 	mh->m_error = MII_EOK;
1999 	return (DDI_SUCCESS);
2000 }
2001 
2002 int
2003 _mii_check(mii_handle_t mh)
2004 {
2005 	link_state_t	olink;
2006 	int		ospeed;
2007 	link_duplex_t	oduplex;
2008 	link_flowctrl_t	ofctrl;
2009 	phy_handle_t	*ph;
2010 
2011 	ph = mh->m_phy;
2012 
2013 	olink = mh->m_link;
2014 	ospeed = ph->phy_speed;
2015 	oduplex = ph->phy_duplex;
2016 	ofctrl = ph->phy_flowctrl;
2017 
2018 	ASSERT(ph->phy_present);
2019 
2020 	if (ph->phy_check(ph) == DDI_FAILURE) {
2021 		_mii_error(mh, MII_ECHECK);
2022 		mh->m_link = LINK_STATE_UNKNOWN;
2023 		_mii_notify(mh);
2024 		return (DDI_FAILURE);
2025 	}
2026 
2027 	mh->m_link = ph->phy_link;
2028 
2029 	/* if anything changed, notify! */
2030 	if ((mh->m_link != olink) ||
2031 	    (ph->phy_speed != ospeed) ||
2032 	    (ph->phy_duplex != oduplex) ||
2033 	    (ph->phy_flowctrl != ofctrl)) {
2034 		_mii_notify(mh);
2035 	}
2036 
2037 	return (DDI_SUCCESS);
2038 }
2039 
2040 void
2041 _mii_task(void *_mh)
2042 {
2043 	mii_handle_t	mh = _mh;
2044 	phy_handle_t	*ph;
2045 	clock_t		wait;
2046 	clock_t		downtime;
2047 
2048 	mutex_enter(&mh->m_lock);
2049 
2050 	for (;;) {
2051 
2052 		/* If detaching, exit the thread. */
2053 		if (!mh->m_started) {
2054 			break;
2055 		}
2056 
2057 		ph = mh->m_phy;
2058 
2059 		/*
2060 		 * If we're suspended or otherwise not supposed to be
2061 		 * monitoring the link, just go back to sleep.
2062 		 *
2063 		 * Theoretically we could power down the PHY, but we
2064 		 * don't bother.  (The link might be used for
2065 		 * wake-on-lan!)  Another option would be to reduce
2066 		 * power on the PHY if both it and the link partner
2067 		 * support 10 Mbps mode.
2068 		 */
2069 		if (mh->m_suspending) {
2070 			mh->m_suspended = B_TRUE;
2071 			cv_broadcast(&mh->m_cv);
2072 		}
2073 		if (mh->m_suspended) {
2074 			mh->m_suspending = B_FALSE;
2075 			cv_wait(&mh->m_cv, &mh->m_lock);
2076 			continue;
2077 		}
2078 
2079 		switch (mh->m_tstate) {
2080 		case MII_STATE_PROBE:
2081 			_mii_probe(mh);
2082 			ph = mh->m_phy;
2083 			if (!ph->phy_present) {
2084 				/*
2085 				 * If no PHY is found, wait a bit before
2086 				 * trying the probe again.  10 seconds ought
2087 				 * to be enough.
2088 				 */
2089 				wait = 10 * MII_SECOND;
2090 			} else {
2091 				wait = 0;
2092 			}
2093 			break;
2094 
2095 		case MII_STATE_RESET:
2096 			if (_mii_reset(mh) == DDI_SUCCESS) {
2097 				mh->m_tstate = MII_STATE_START;
2098 				wait = 0;
2099 			} else {
2100 				/*
2101 				 * If an error occurred, wait a bit and
2102 				 * try again later.
2103 				 */
2104 				wait = 10 * MII_SECOND;
2105 			}
2106 			break;
2107 
2108 		case MII_STATE_START:
2109 			/*
2110 			 * If an error occurs, we're going to go back to
2111 			 * probe or reset state.  Otherwise we go to run
2112 			 * state.  In all cases we want to wait 1 second
2113 			 * before doing anything else - either for link to
2114 			 * settle, or to give other code a chance to run
2115 			 * while we reset.
2116 			 */
2117 			if (_mii_start(mh) == DDI_SUCCESS) {
2118 				/* reset watchdog to latest */
2119 				downtime = ddi_get_lbolt();
2120 				mh->m_tstate = MII_STATE_RUN;
2121 			} else {
2122 				mh->m_tstate = MII_STATE_PROBE;
2123 			}
2124 			wait = 0;
2125 			break;
2126 
2127 		case MII_STATE_LOOPBACK:
2128 			/*
2129 			 * In loopback mode we don't check anything,
2130 			 * and just wait for some condition to change.
2131 			 */
2132 			wait = (clock_t)-1;
2133 			break;
2134 
2135 		case MII_STATE_RUN:
2136 		default:
2137 			if (_mii_check(mh) == DDI_FAILURE) {
2138 				/*
2139 				 * On error (PHY removed?), wait a
2140 				 * short bit before reprobing or
2141 				 * resetting.
2142 				 */
2143 				wait = MII_SECOND;
2144 				mh->m_tstate = MII_STATE_PROBE;
2145 
2146 			} else if (mh->m_link == LINK_STATE_UP) {
2147 				/* got goood link, so reset the watchdog */
2148 				downtime = ddi_get_lbolt();
2149 				/* rescan again in a second */
2150 				wait = MII_SECOND;
2151 
2152 			} else if ((ddi_get_lbolt() - downtime) >
2153 			    (drv_usectohz(MII_SECOND * 10))) {
2154 
2155 				/*
2156 				 * If we were down for 10 seconds,
2157 				 * hard reset the PHY.
2158 				 */
2159 				mh->m_tstate = MII_STATE_RESET;
2160 				wait = 0;
2161 
2162 			} else {
2163 				/*
2164 				 * Otherwise, if we are still down,
2165 				 * rescan the link much more
2166 				 * frequently.  We might be trying to
2167 				 * autonegotiate.
2168 				 */
2169 				wait = MII_SECOND / 4;
2170 			}
2171 			break;
2172 		}
2173 
2174 		switch (wait) {
2175 		case 0:
2176 			break;
2177 
2178 		case (clock_t)-1:
2179 			cv_wait(&mh->m_cv, &mh->m_lock);
2180 			break;
2181 
2182 		default:
2183 			(void) cv_reltimedwait(&mh->m_cv, &mh->m_lock,
2184 			    drv_usectohz(wait), TR_CLOCK_TICK);
2185 		}
2186 	}
2187 
2188 	mutex_exit(&mh->m_lock);
2189 }
2190