xref: /titanic_44/usr/src/uts/common/io/dmfe/dmfe_mii.c (revision ea01bd62c06264135e67699c4e213c6de9313abe)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "dmfe_impl.h"
29 
30 /*
31  * The bit-twiddling required by the MII interface makes the functions
32  * in this file relatively slow, so they should probably only be called
33  * from base/low-pri code.  However, there's nothing here that really
34  * won't work at hi-pri, AFAIK; and 'relatively slow' only means that
35  * they have microsecond busy-waits all over the place.
36  *
37  * dmfe_recheck_link(), on the other hand, uses delay() and loops for
38  * up to dmfe_restart_time_us microseconds (currently 12 seconds), so
39  * it should only be called from user (ioctl) or factotum context.
40  *
41  * Time parameters:
42  *
43  *	RESTART_TIME is the time in microseconds to allow for the link
44  *	to go down and recover after changing the PHY parameters.
45  *
46  *	RESTART_POLL is the interval between checks on the link state
47  *	while waiting for up to RESTART_TIME in total.
48  *
49  *	SETTLE_TIME is the time to allow for the PHY to stabilise
50  *	after a change from LINK DOWN to LINK UP; multiple changes
51  *	within this time are coalesced into one (in case the link
52  *	goes UP-DOWN-UP as negotiation tries different speeds, etc).
53  *
54  * Patchable globals:
55  *	dmfe_restart_time_us:	RESTART_TIME
56  *	dmfe_restart_poll_us:	RESTART_POLL
57  *	dmfe_mii_settle_time:	SETTLE_TIME
58  */
59 
60 #define	RESTART_POLL		600000		/* microseconds		*/
61 #define	RESTART_TIME		12000000	/* microseconds		*/
62 #define	SETTLE_TIME		3000000		/* microseconds		*/
63 
64 #define	MII_AN_SELECTOR_8023	1
65 #define	MII_STATUS_INVAL	0xffffU
66 
67 static clock_t dmfe_restart_poll_us = RESTART_POLL;
68 static clock_t dmfe_restart_time_us = RESTART_TIME;
69 static clock_t dmfe_mii_settle_time = SETTLE_TIME;
70 static const int mii_reg_size = 16;			/* bits		*/
71 
72 #define	DMFE_DBG	DMFE_DBG_MII	/* debug flag for this code	*/
73 
74 /*
75  * Type of transceiver currently in use.  The IEEE 802.3 std aPhyType
76  * enumerates the following set
77  */
78 enum xcvr_type {
79 	XCVR_TYPE_UNDEFINED	= 0,	/* undefined, or not yet known	*/
80 	XCVR_TYPE_10BASE_T	= 7,	/* 10 Mbps copper		*/
81 	XCVR_TYPE_100BASE_X	= 24	/* 100 Mbps copper		*/
82 };
83 
84 /*
85  * ======== Low-level SROM access ========
86  */
87 
88 /*
89  * EEPROM access is here because it shares register functionality with MII.
90  * NB: <romaddr> is a byte address but must be 16-bit aligned.
91  *     <cnt> is a byte count, and must be a multiple of 2.
92  */
93 void
94 dmfe_read_eeprom(dmfe_t *dmfep, uint16_t raddr, uint8_t *ptr, int cnt)
95 {
96 	uint16_t value;
97 	uint16_t bit;
98 
99 	/* only a whole number of words for now */
100 	ASSERT((cnt % 2) == 0);
101 	ASSERT((raddr % 2) == 0);
102 	ASSERT(cnt > 0);
103 	ASSERT(((raddr + cnt) / 2) < (HIGH_ADDRESS_BIT << 1));
104 
105 	raddr /= 2;	/* make it a word address */
106 
107 	/* loop over multiple words... rom access in 16-bit increments */
108 	while (cnt > 0) {
109 
110 		/* select the eeprom */
111 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM);
112 		drv_usecwait(1);
113 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS);
114 		drv_usecwait(1);
115 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS | SEL_CLK);
116 		drv_usecwait(1);
117 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS);
118 		drv_usecwait(1);
119 
120 		/* send 3 bit read command */
121 		for (bit = HIGH_CMD_BIT; bit != 0; bit >>= 1) {
122 
123 			value = (bit & EEPROM_READ_CMD) ? DATA_IN : 0;
124 
125 			/* strobe the bit in */
126 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
127 			    READ_EEPROM_CS | value);
128 			drv_usecwait(1);
129 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
130 			    READ_EEPROM_CS | SEL_CLK | value);
131 			drv_usecwait(1);
132 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
133 			    READ_EEPROM_CS | value);
134 			drv_usecwait(1);
135 		}
136 
137 		/* send 6 bit address */
138 		for (bit = HIGH_ADDRESS_BIT; bit != 0; bit >>= 1) {
139 			value = (bit & raddr) ? DATA_IN : 0;
140 
141 			/* strobe the bit in */
142 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
143 			    READ_EEPROM_CS | value);
144 			drv_usecwait(1);
145 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
146 			    READ_EEPROM_CS | SEL_CLK | value);
147 			drv_usecwait(1);
148 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
149 			    READ_EEPROM_CS | value);
150 			drv_usecwait(1);
151 		}
152 
153 		/* shift out data */
154 		value = 0;
155 		for (bit = HIGH_DATA_BIT; bit != 0; bit >>= 1) {
156 
157 			dmfe_chip_put32(dmfep, ETHER_ROM_REG,
158 			    READ_EEPROM_CS | SEL_CLK);
159 			drv_usecwait(1);
160 
161 			if (dmfe_chip_get32(dmfep, ETHER_ROM_REG) & DATA_OUT)
162 				value |= bit;
163 			drv_usecwait(1);
164 
165 			dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS);
166 			drv_usecwait(1);
167 		}
168 
169 		/* turn off EEPROM access */
170 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM);
171 		drv_usecwait(1);
172 
173 		/* this makes it endian neutral */
174 		*ptr++ = value & 0xff;
175 		*ptr++ = (value >> 8);
176 
177 		cnt -= 2;
178 		raddr++;
179 	}
180 }
181 
182 /*
183  * ======== Lowest-level bit-twiddling to drive MII interface ========
184  */
185 
186 /*
187  * Poke <nbits> (up to 32) bits from <mii_data> along the MII control lines.
188  * Note: the data is taken starting with the MSB of <mii_data> and working
189  * down through progressively less significant bits.
190  */
191 static void
192 dmfe_poke_mii(dmfe_t *dmfep, uint32_t mii_data, uint_t nbits)
193 {
194 	uint32_t dbit;
195 
196 	ASSERT(mutex_owned(dmfep->milock));
197 
198 	for (; nbits > 0; mii_data <<= 1, --nbits) {
199 		/*
200 		 * Extract the MSB of <mii_data> and shift it to the
201 		 * proper bit position in the MII-poking register
202 		 */
203 		dbit = mii_data >> 31;
204 		dbit <<= MII_DATA_OUT_SHIFT;
205 		ASSERT((dbit & ~MII_DATA_OUT) == 0);
206 
207 		/*
208 		 * Drive the bit across the wire ...
209 		 */
210 		dmfe_chip_put32(dmfep, ETHER_ROM_REG,
211 		    MII_WRITE | dbit);			/* Clock Low	*/
212 		drv_usecwait(MII_DELAY);
213 		dmfe_chip_put32(dmfep, ETHER_ROM_REG,
214 		    MII_WRITE | MII_CLOCK | dbit);	/* Clock High	*/
215 		drv_usecwait(MII_DELAY);
216 	}
217 
218 	dmfe_chip_put32(dmfep, ETHER_ROM_REG,
219 	    MII_WRITE | dbit);				/* Clock Low	*/
220 	drv_usecwait(MII_DELAY);
221 }
222 
223 /*
224  * Put the MDIO port in tri-state for the turn around bits
225  * in MII read and at end of MII management sequence.
226  */
227 static void
228 dmfe_tristate_mii(dmfe_t *dmfep)
229 {
230 	ASSERT(mutex_owned(dmfep->milock));
231 
232 	dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_TRISTATE);
233 	drv_usecwait(MII_DELAY);
234 	dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_TRISTATE | MII_CLOCK);
235 	drv_usecwait(MII_DELAY);
236 }
237 
238 
239 /*
240  * ======== Next level: issue an MII access command/get a response ========
241  */
242 
243 static void
244 dmfe_mii_command(dmfe_t *dmfep, uint32_t command_word, int nbits)
245 {
246 	ASSERT(mutex_owned(dmfep->milock));
247 
248 	/* Write Preamble & Command & return to tristate */
249 	dmfe_poke_mii(dmfep, MII_PREAMBLE, 2*mii_reg_size);
250 	dmfe_poke_mii(dmfep, command_word, nbits);
251 	dmfe_tristate_mii(dmfep);
252 }
253 
254 static uint16_t
255 dmfe_mii_response(dmfe_t *dmfep)
256 {
257 	boolean_t ack;
258 	uint16_t data;
259 	uint32_t tmp;
260 	int i;
261 
262 	/* Check that the PHY generated a zero bit on the 2nd clock */
263 	tmp = dmfe_chip_get32(dmfep, ETHER_ROM_REG);
264 	ack = (tmp & MII_DATA_IN) == 0;
265 
266 	/* read data WORD */
267 	for (data = 0, i = 0; i < mii_reg_size; ++i) {
268 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_READ);
269 		drv_usecwait(MII_DELAY);
270 		dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_READ | MII_CLOCK);
271 		drv_usecwait(MII_DELAY);
272 		tmp = dmfe_chip_get32(dmfep, ETHER_ROM_REG);
273 		data <<= 1;
274 		data |= (tmp >> MII_DATA_IN_SHIFT) & 1;
275 	}
276 
277 	/* leave the interface tristated */
278 	dmfe_tristate_mii(dmfep);
279 
280 	return (ack ? data : ~0);
281 }
282 
283 /*
284  * ======== Next level: 16-bit PHY register access routines ========
285  */
286 
287 static void
288 dmfe_phy_write(dmfe_t *dmfep, uint_t reg_num, uint_t reg_dat)
289 {
290 	uint32_t command_word;
291 
292 	/* Issue MII command */
293 	command_word = MII_WRITE_FRAME;
294 	command_word |= dmfep->phy_addr << MII_PHY_ADDR_SHIFT;
295 	command_word |= reg_num << MII_REG_ADDR_SHIFT;
296 	command_word |= reg_dat;
297 	dmfe_mii_command(dmfep, command_word, 2*mii_reg_size);
298 }
299 
300 static uint16_t
301 dmfe_phy_read(dmfe_t *dmfep, uint_t reg_num)
302 {
303 	uint32_t command_word;
304 
305 	/* Issue MII command */
306 	command_word = MII_READ_FRAME;
307 	command_word |= dmfep->phy_addr << MII_PHY_ADDR_SHIFT;
308 	command_word |= reg_num << MII_REG_ADDR_SHIFT;
309 	dmfe_mii_command(dmfep, command_word, mii_reg_size-2);
310 
311 	return (dmfe_mii_response(dmfep));
312 }
313 
314 /*
315  * ======== Next level: PHY control operations ========
316  */
317 
318 /*
319  * Reset the PHYceiver, using a wierd sequence of accesses to CR12
320  *
321  * This could be done using MII accesses; but this should be quicker ....
322  */
323 static void
324 dmfe_phy_reset(dmfe_t *dmfep)
325 {
326 	DMFE_TRACE(("dmfe_phy_reset($%p)", (void *)dmfep));
327 
328 	ASSERT(mutex_owned(dmfep->milock));
329 
330 	dmfe_chip_put32(dmfep, PHY_STATUS_REG, GPS_WRITE_ENABLE|GPS_PHY_RESET);
331 	drv_usecwait(10);
332 	dmfe_chip_put32(dmfep, PHY_STATUS_REG, GPS_PHY_RESET);
333 	drv_usecwait(10);
334 	dmfe_chip_put32(dmfep, PHY_STATUS_REG, 0);
335 	drv_usecwait(10);
336 }
337 
338 /*
339  * Read the MII_STATUS register (BMSR)
340  */
341 static uint16_t
342 dmfe_mii_status(dmfe_t *dmfep)
343 {
344 	uint16_t bmsr;
345 
346 	bmsr = dmfe_phy_read(dmfep, MII_STATUS);
347 
348 	DMFE_DEBUG(("dmfe_mii_status: bmsr 0x%x", bmsr));
349 
350 	return (bmsr);
351 }
352 
353 /*
354  * Returns true if PHY at address <phy_addr> is present and accessible.
355  * We determine whether the PHY is there by looking for at least one
356  * set bit, and at least one clear bit, in the value returned from its
357  * status register (i.e. BMSR is not all zeroes or all ones).
358  */
359 static boolean_t
360 dmfe_probe_phy(dmfe_t *dmfep)
361 {
362 	uint16_t bmsr;
363 
364 	ASSERT(mutex_owned(dmfep->milock));
365 
366 	/* Clear any latched bits by reading twice */
367 	bmsr = dmfe_mii_status(dmfep);
368 	bmsr = dmfe_mii_status(dmfep);
369 
370 	DMFE_DEBUG(("dmfe_probe_phy($%p, %d) BMSR 0x%x",
371 	    (void *)dmfep, dmfep->phy_addr, bmsr));
372 
373 	/*
374 	 * At least one bit in BMSR should be set (for the device
375 	 * capabilities) and at least one clear (one of the error
376 	 * bits).  Unconnected devices tend to show 0xffff, but
377 	 * 0x0000 has also been seen.
378 	 */
379 	return (bmsr != 0 && bmsr != MII_STATUS_INVAL);
380 }
381 
382 static boolean_t
383 dmfe_find_phy(dmfe_t *dmfep)
384 {
385 	int mii_addr;
386 
387 	ASSERT(mutex_owned(dmfep->milock));
388 
389 	/*
390 	 * Verify that the PHY responds to MII accesses.  It *should*
391 	 * be at MII address 1, but the Davicom internal PHY can be
392 	 * reprogrammed to appear at a different address, so we'll
393 	 * check all 32 possible addresses if necessary (in the order
394 	 * 1, 2, 3..31, 0)
395 	 */
396 	for (mii_addr = 1; ; ) {
397 		dmfep->phy_addr = mii_addr % 32;
398 		if (dmfe_probe_phy(dmfep))
399 			break;
400 		if (++mii_addr > 32) {
401 			DMFE_DEBUG(("No PHY found"));
402 			return (B_FALSE);
403 		}
404 	}
405 
406 	dmfep->phy_id = dmfe_phy_read(dmfep, MII_PHYIDH) << 16;
407 	dmfep->phy_id |= dmfe_phy_read(dmfep, MII_PHYIDL);
408 
409 	DMFE_DEBUG(("PHY at address %d, id 0x%x", mii_addr, dmfep->phy_id));
410 
411 	switch (PHY_MANUFACTURER(dmfep->phy_id)) {
412 	case OUI_DAVICOM:
413 		return (B_TRUE);
414 
415 	default:
416 		dmfe_warning(dmfep, "unsupported (non-Davicom) PHY found!");
417 		return (B_FALSE);
418 	}
419 }
420 
421 #undef	DMFE_DBG
422 
423 #define	DMFE_DBG	DMFE_DBG_LINK	/* debug flag for this code	*/
424 
425 /*
426  * ======== Top-level PHY management routines ========
427  */
428 
429 /*
430  * (Re)initalise the PHY's speed/duplex/autonegotiation registers, basing
431  * the required settings on the various param_* variables that can be poked
432  * via the NDD interface.
433  *
434  * NOTE: the Tx/Rx processes should be STOPPED when this routine is called
435  */
436 void
437 dmfe_update_phy(dmfe_t *dmfep)
438 {
439 	uint16_t control;
440 	uint16_t anar;
441 
442 	DMFE_DEBUG(("dmfe_update_phy: autoneg %d 100fdx %d 100hdx %d "
443 	    "10fdx %d 10hdx %d", dmfep->param_autoneg,
444 	    dmfep->param_anar_100fdx, dmfep->param_anar_100hdx,
445 	    dmfep->param_anar_10fdx, dmfep->param_anar_10hdx));
446 
447 	ASSERT(mutex_owned(dmfep->milock));
448 
449 	/*
450 	 * NDD initialisation will have already set up the param_*
451 	 * variables based on the values of the various properties.
452 	 * Here we have to transform these into the proper settings
453 	 * of the PHY registers ...
454 	 */
455 	anar = control = 0;
456 
457 	if (dmfep->param_anar_100fdx)
458 		control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX;
459 	else if (dmfep->param_anar_100hdx)
460 		control |= MII_CONTROL_100MB;
461 	else if (dmfep->param_anar_10fdx)
462 		control |= MII_CONTROL_FDUPLEX;
463 
464 	if (dmfep->param_anar_100fdx)
465 		anar |= MII_ABILITY_100BASE_TX_FD;
466 	if (dmfep->param_anar_100hdx)
467 		anar |= MII_ABILITY_100BASE_TX;
468 	if (dmfep->param_anar_10fdx)
469 		anar |= MII_ABILITY_10BASE_T_FD;
470 	if (dmfep->param_anar_10hdx)
471 		anar |= MII_ABILITY_10BASE_T;
472 
473 	if (anar == 0) {
474 		/*
475 		 * A stupid combination of settings has left us with no
476 		 * options - so select the default (100Mb/s half-duplex)
477 		 * for now and re-enable ALL autonegotiation options.
478 		 */
479 		control |= MII_CONTROL_100MB;
480 		anar |= MII_ABILITY_100BASE_TX_FD;
481 		anar |= MII_ABILITY_100BASE_TX;
482 		anar |= MII_ABILITY_10BASE_T_FD;
483 		anar |= MII_ABILITY_10BASE_T;
484 	}
485 
486 	if ((dmfep->opmode & LOOPBACK_MODE_MASK) != LOOPBACK_OFF) {
487 		/*
488 		 * If loopback is selected at the MAC level, we have
489 		 * to make sure that the settings are consistent at
490 		 * the PHY, and also keep autonegotiation switched OFF,
491 		 * otherwise we can get all sorts of strange effects
492 		 * including continuous link change interrupts :-(
493 		 */
494 		control |= MII_CONTROL_LOOPBACK;
495 	} else if (dmfep->param_autoneg) {
496 		/*
497 		 * Autonegotiation is only possible if loopback is OFF
498 		 */
499 		control |= MII_CONTROL_ANE;
500 	}
501 
502 	DMFE_DEBUG(("dmfe_update_phy: anar 0x%x control 0x%x", anar, control));
503 
504 	anar |= MII_AN_SELECTOR_8023;
505 	if ((anar != dmfep->phy_anar_w) || (control != dmfep->phy_control) ||
506 	    (dmfep->update_phy)) {
507 		/*
508 		 * Something's changed; reset the PHY and write the new
509 		 * values to the PHY CONTROL and ANAR registers.  This
510 		 * will probably cause the link to go down, and then back
511 		 * up again once the link is stable and autonegotiation
512 		 * (if enabled) is complete.  We should get a link state
513 		 * change at the end; but in any case the ticker will keep
514 		 * an eye on what's going on ...
515 		 */
516 		dmfe_phy_reset(dmfep);
517 		dmfe_phy_write(dmfep, MII_CONTROL, control);
518 		dmfe_phy_write(dmfep, MII_AN_ADVERT, anar);
519 	}
520 
521 	/*
522 	 * If autonegotiation is (now) enabled, we want to trigger
523 	 * a new autonegotiation cycle now that the PHY has been
524 	 * programmed with the capabilities to be advertised.
525 	 */
526 	if (control & MII_CONTROL_ANE)
527 		dmfe_phy_write(dmfep, MII_CONTROL, control | MII_CONTROL_RSAN);
528 
529 	/*
530 	 * Save the values written in the shadow copies of the CONTROL
531 	 * and ANAR registers, and clear the shadow BMSR 'cos it's no
532 	 * longer valid.
533 	 */
534 	dmfep->phy_control = control;
535 	dmfep->phy_anar_w = anar;
536 	dmfep->phy_bmsr = 0;
537 }
538 
539 
540 /*
541  * PHY initialisation, called only once
542  *
543  * Discover the MII address of the PHY (should be 1).
544  * Initialise according to preset NDD parameters.
545  * Return status
546  */
547 boolean_t
548 dmfe_init_phy(dmfe_t *dmfep)
549 {
550 	boolean_t ok;
551 
552 	mutex_enter(dmfep->milock);
553 	ok = dmfe_find_phy(dmfep);
554 	if (ok)
555 		dmfe_update_phy(dmfep);
556 	mutex_exit(dmfep->milock);
557 
558 	return (ok);
559 }
560 
561 /*
562  *	========== Active Media Determination Routines ==========
563  */
564 
565 
566 /*
567  * Check whether the BMSR has changed.  If it hasn't, this routine
568  * just returns B_FALSE (no further action required).  Otherwise,
569  * it records the time when the change was seen and returns B_TRUE.
570  *
571  * This routine needs only the <milock>, although <oplock> may
572  * also be held.  This is why full processing of the link change
573  * is left to dmfe_recheck_link() below.
574  */
575 static boolean_t
576 dmfe_check_bmsr(dmfe_t *dmfep)
577 {
578 	uint16_t new_bmsr;
579 
580 	DMFE_TRACE(("dmfe_check_bmsr($%p)", (void *)dmfep));
581 
582 	ASSERT(mutex_owned(dmfep->milock));
583 
584 	/*
585 	 * Read the BMSR and check it against the previous value
586 	 */
587 	new_bmsr = dmfe_mii_status(dmfep);
588 	DMFE_DEBUG(("dmfe_check_bmsr: bmsr 0x%x -> 0x%x",
589 	    dmfep->phy_bmsr, new_bmsr));
590 
591 	/*
592 	 * Record new value and timestamp if it's changed
593 	 */
594 	if (new_bmsr != dmfep->phy_bmsr) {
595 		dmfep->phy_bmsr = new_bmsr;
596 		dmfep->phy_bmsr_lbolt = ddi_get_lbolt();
597 		return (B_TRUE);
598 	}
599 
600 	return (B_FALSE);
601 }
602 
603 /*
604  * 'Quick' link check routine
605  *
606  * Call whenever the link state may have changed, or periodically to
607  * poll for link up/down events.  Returns B_FALSE if nothing interesting
608  * has happened.  Otherwise, it returns B_TRUE, telling the caller to
609  * call dmfe_recheck_link() (below).  If the link state is UNKNOWN, we
610  * return B_TRUE anyway, even if the BMSR hasn't changed - but only after
611  * going through the motions, 'cos the read of the BMSR has side-effects -
612  * some of the BMSR bits are latching-until-read, and dmfe_check_bmsr()
613  * also records the time of any change to the BMSR!
614  */
615 boolean_t
616 dmfe_check_link(dmfe_t *dmfep)
617 {
618 	if (dmfe_check_bmsr(dmfep))
619 		return (B_TRUE);
620 	return (dmfep->link_state == LINK_STATE_UNKNOWN);
621 }
622 
623 
624 /*
625  * Update all parameters and statistics after a link state change.
626  */
627 static void
628 dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex)
629 {
630 	int ks_id;
631 
632 	ASSERT(mutex_owned(dmfep->milock));
633 	ASSERT(mutex_owned(dmfep->oplock));
634 	ASSERT(newstate != dmfep->link_state);
635 
636 	switch (newstate) {
637 	case LINK_STATE_UP:
638 		dmfep->param_linkup = 1;
639 		break;
640 
641 	default:
642 		dmfep->param_linkup = 0;
643 		break;
644 	}
645 
646 	switch (speed) {
647 	case 100:
648 		dmfep->op_stats_speed = 100000000;
649 		dmfep->param_speed = speed;
650 		dmfep->phy_inuse = XCVR_100X;
651 		break;
652 
653 	case 10:
654 		dmfep->op_stats_speed = 10000000;
655 		dmfep->param_speed = speed;
656 		dmfep->phy_inuse = XCVR_10;
657 		break;
658 
659 	default:
660 		dmfep->op_stats_speed = 0;
661 		dmfep->phy_inuse = XCVR_UNDEFINED;
662 		break;
663 	}
664 
665 	dmfep->op_stats_duplex = dmfep->param_duplex = duplex;
666 
667 	if (newstate == LINK_STATE_UP)
668 		ks_id = KS_LINK_UP_CNT;
669 	else
670 		ks_id = KS_LINK_DROP_CNT;
671 	DRV_KS_INC(dmfep, ks_id);
672 }
673 
674 /*
675  * Verify and report a change in the state of the link ...
676  */
677 static void
678 dmfe_link_change(dmfe_t *dmfep, link_state_t newstate)
679 {
680 	boolean_t report;
681 	uint32_t gpsr;
682 	int speed;
683 	int duplex;
684 
685 	ASSERT(mutex_owned(dmfep->milock));
686 	ASSERT(mutex_owned(dmfep->oplock));
687 	ASSERT(newstate != dmfep->link_state);
688 
689 	switch (newstate) {
690 	case LINK_STATE_UP:
691 		gpsr = dmfe_chip_get32(dmfep, PHY_STATUS_REG);
692 		speed = gpsr & GPS_LINK_100 ? 100 : 10;
693 		duplex = (gpsr & GPS_FULL_DUPLEX) ?
694 		    LINK_DUPLEX_FULL: LINK_DUPLEX_HALF;
695 		report = B_TRUE;
696 		break;
697 
698 	default:
699 		speed = 0;
700 		duplex = LINK_DUPLEX_UNKNOWN;
701 		switch (dmfep->link_state) {
702 		case LINK_STATE_DOWN:		/* DOWN->UNKNOWN	*/
703 		case LINK_STATE_UNKNOWN:	/* UNKNOWN->DOWN	*/
704 			report = B_FALSE;
705 			break;
706 
707 		case LINK_STATE_UP:		/* UP->DOWN/UNKNOWN	*/
708 			report = B_TRUE;
709 			break;
710 		}
711 		break;
712 	}
713 
714 	/*
715 	 * Update status & report new link state if required ...
716 	 */
717 	if (report)
718 		dmfe_media_update(dmfep, newstate, speed, duplex);
719 }
720 
721 /*
722  * Examine the value most recently read from the BMSR and derive
723  * the (new) link state.
724  *
725  * This routine also incorporates heuristics determining when to
726  * accept a new state as valid and report it, based on the new
727  * (apparent) state, the old state, and the time elapsed since
728  * the last time we saw a (potential) state change.  For example,
729  * we want to accept UP->DOWN immediately, but UNKNOWN->UP only
730  * once autonegotiation is completed and the results are stable.
731  */
732 static link_state_t
733 dmfe_process_bmsr(dmfe_t *dmfep, clock_t time)
734 {
735 	link_state_t newstate;
736 	uint32_t gpsr;
737 	uint16_t bmsr;
738 	uint16_t anlpar;
739 	uint16_t anar;
740 
741 	ASSERT(mutex_owned(dmfep->milock));
742 	ASSERT(mutex_owned(dmfep->oplock));
743 
744 	/*
745 	 * Read PHY registers & publish through driver-specific kstats
746 	 * Decode abilities & publish through ndd & standard MII kstats
747 	 */
748 	dmfep->phy_anar_r = dmfe_phy_read(dmfep, MII_AN_ADVERT);
749 	dmfep->phy_aner   = dmfe_phy_read(dmfep, MII_AN_EXPANSION);
750 	dmfep->phy_anlpar = dmfe_phy_read(dmfep, MII_AN_LPABLE);
751 	dmfep->phy_dscsr  = dmfe_phy_read(dmfep, DM_SCSR);
752 
753 	DRV_KS_SET(dmfep, KS_MIIREG_BMSR, dmfep->phy_bmsr);
754 	DRV_KS_SET(dmfep, KS_MIIREG_ANAR, dmfep->phy_anar_r);
755 	DRV_KS_SET(dmfep, KS_MIIREG_ANER, dmfep->phy_aner);
756 	DRV_KS_SET(dmfep, KS_MIIREG_ANLPAR, dmfep->phy_anlpar);
757 	DRV_KS_SET(dmfep, KS_MIIREG_DSCSR, dmfep->phy_dscsr);
758 
759 	DMFE_DEBUG(("dmfe_process_bmsr: ANAR 0x%x->0x%x ANLPAR 0x%x SCSR 0x%x",
760 	    dmfep->phy_anar_w, dmfep->phy_anar_r,
761 	    dmfep->phy_anlpar, dmfep->phy_dscsr));
762 
763 	/*
764 	 * Capabilities of DM9102A
765 	 */
766 	bmsr = dmfep->phy_bmsr;
767 
768 	dmfep->param_bmsr_100T4    = BIS(bmsr, MII_STATUS_100_BASE_T4);
769 	dmfep->param_bmsr_100fdx   = BIS(bmsr, MII_STATUS_100_BASEX_FD);
770 	dmfep->param_bmsr_100hdx   = BIS(bmsr, MII_STATUS_100_BASEX);
771 	dmfep->param_bmsr_10fdx    = BIS(bmsr, MII_STATUS_10_FD);
772 	dmfep->param_bmsr_10hdx    = BIS(bmsr, MII_STATUS_10);
773 	dmfep->param_bmsr_remfault = 1;
774 	dmfep->param_bmsr_autoneg  = BIS(bmsr, MII_STATUS_CANAUTONEG);
775 
776 	/*
777 	 * Advertised abilities of DM9102A
778 	 */
779 	anar = dmfep->phy_anar_r;
780 	dmfep->param_anar_remfault = BIS(anar, MII_AN_ADVERT_REMFAULT);
781 
782 	/*
783 	 * Link Partners advertised abilities
784 	 */
785 	if ((dmfep->phy_aner & MII_AN_EXP_LPCANAN) == 0) {
786 		anlpar = 0;
787 		dmfep->param_lp_autoneg = 0;
788 	} else {
789 		anlpar = dmfep->phy_anlpar;
790 		dmfep->param_lp_autoneg = 1;
791 	}
792 
793 	dmfep->param_lp_100T4    = BIS(anlpar, MII_ABILITY_100BASE_T4);
794 	dmfep->param_lp_100fdx   = BIS(anlpar, MII_ABILITY_100BASE_TX_FD);
795 	dmfep->param_lp_100hdx   = BIS(anlpar, MII_ABILITY_100BASE_TX);
796 	dmfep->param_lp_10fdx    = BIS(anlpar, MII_ABILITY_10BASE_T_FD);
797 	dmfep->param_lp_10hdx    = BIS(anlpar, MII_ABILITY_10BASE_T);
798 	dmfep->param_lp_remfault = BIS(anlpar, MII_AN_ADVERT_REMFAULT);
799 
800 	/*
801 	 * Derive new state & time since last change
802 	 */
803 	newstate = (dmfep->phy_bmsr & MII_STATUS_LINKUP) ?
804 	    LINK_STATE_UP : LINK_STATE_DOWN;
805 	time -= dmfep->phy_bmsr_lbolt;
806 
807 	/*
808 	 * Hah! That would be just too easy ... we have to check
809 	 * for all sorts of special cases before we decide :(
810 	 */
811 	if (dmfep->phy_bmsr == MII_STATUS_INVAL)
812 		newstate = LINK_STATE_DOWN;
813 	else if ((dmfep->link_state == LINK_STATE_UP) &&
814 	    (newstate == LINK_STATE_DOWN))
815 		/*EMPTY*/;
816 	else if (time < drv_usectohz(dmfe_mii_settle_time))
817 		newstate = LINK_STATE_UNKNOWN;
818 	else if (dmfep->phy_bmsr & MII_STATUS_ANDONE)
819 		/*EMPTY*/;
820 	else if (dmfep->phy_control & MII_CONTROL_ANE)
821 		newstate = LINK_STATE_DOWN;
822 
823 	if (newstate == LINK_STATE_UP) {
824 		/*
825 		 * Link apparently UP - but get the PHY status register
826 		 * (GPSR) and make sure it also shows a consistent value.
827 		 * In particular, both the link status bits should be 1,
828 		 * and the speed bits should show one set and one clear.
829 		 * Any other combination indicates that we haven't really
830 		 * got a stable link yet ...
831 		 */
832 		gpsr = dmfe_chip_get32(dmfep, PHY_STATUS_REG);
833 		DMFE_DEBUG(("dmfe_process_bmsr: GPSR 0x%x", gpsr));
834 
835 		switch (gpsr & (GPS_LINK_STATUS|GPS_UTP_SIG)) {
836 		case GPS_LINK_STATUS|GPS_UTP_SIG:
837 			break;
838 		default:
839 			newstate = LINK_STATE_UNKNOWN;
840 			break;
841 		}
842 
843 		switch (gpsr & (GPS_LINK_10|GPS_LINK_100)) {
844 		case GPS_LINK_100:
845 		case GPS_LINK_10:
846 			break;
847 		default:
848 			newstate = LINK_STATE_UNKNOWN;
849 			break;
850 		}
851 	}
852 
853 	DMFE_DEBUG(("dmfe_process_bmsr: BMSR 0x%x state %d -> %d @ %d",
854 	    dmfep->phy_bmsr, dmfep->link_state, newstate, time));
855 
856 	return (newstate);
857 }
858 
859 /*
860  * 'Full' link check routine
861  *
862  * Call whenever dmfe_check_link() above indicates that the link
863  * state may have changed.  Handles all changes to the link state
864  * (up/down, speed/duplex changes), including multiple changes
865  * occuring within the <timeout>.  <timeout> will be zero if called
866  * from the factotum (for an unexpected change) or the number of
867  * ticks for which to wait for stability after an ioctl that changes
868  * the link parameters.  Even when <timeout> is zero, we loop while
869  * the BMSR keeps changing ...
870  *
871  * Needs both <milock> and <oplock>, and the Tx/Rx processes
872  * should already be stopped so we're not liable to confuse them
873  * by changing the PHY/MAC parameters under them ...
874  *
875  */
876 void
877 dmfe_recheck_link(dmfe_t *dmfep, boolean_t ioctl)
878 {
879 	link_state_t newstate;
880 	boolean_t again;
881 	clock_t deadline;
882 	clock_t now;
883 
884 	DMFE_TRACE(("dmfe_recheck_link($%p, %d)", (void *)dmfep, ioctl));
885 
886 	ASSERT(mutex_owned(dmfep->milock));
887 	ASSERT(mutex_owned(dmfep->oplock));
888 
889 	now = deadline = ddi_get_lbolt();
890 	if (ioctl)
891 		deadline += drv_usectohz(dmfe_restart_time_us);
892 
893 	for (; ; now = ddi_get_lbolt()) {
894 		newstate = dmfe_process_bmsr(dmfep, now);
895 		again = dmfe_check_bmsr(dmfep);
896 		if (newstate != dmfep->link_state) {
897 			dmfe_link_change(dmfep, newstate);
898 			dmfep->link_state = newstate;
899 			again = B_TRUE;
900 		}
901 		ASSERT(dmfep->link_state == newstate);
902 		if (again)
903 			continue;
904 		if (newstate == LINK_STATE_UP) {
905 			dmfep->update_phy = B_TRUE;
906 			break;
907 		}
908 		if (now >= deadline)
909 			break;
910 		delay(drv_usectohz(dmfe_restart_poll_us));
911 	}
912 }
913 
914 #undef	DMFE_DBG
915