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