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