xref: /onnv-gate/usr/src/uts/common/io/nge/nge_ndd.c (revision 6512:707ffe0297ab)
15578Smx205022 /*
25578Smx205022  * CDDL HEADER START
35578Smx205022  *
45578Smx205022  * The contents of this file are subject to the terms of the
55578Smx205022  * Common Development and Distribution License (the "License").
65578Smx205022  * You may not use this file except in compliance with the License.
75578Smx205022  *
85578Smx205022  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95578Smx205022  * or http://www.opensolaris.org/os/licensing.
105578Smx205022  * See the License for the specific language governing permissions
115578Smx205022  * and limitations under the License.
125578Smx205022  *
135578Smx205022  * When distributing Covered Code, include this CDDL HEADER in each
145578Smx205022  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155578Smx205022  * If applicable, add the following below this CDDL HEADER, with the
165578Smx205022  * fields enclosed by brackets "[]" replaced with your own identifying
175578Smx205022  * information: Portions Copyright [yyyy] [name of copyright owner]
185578Smx205022  *
195578Smx205022  * CDDL HEADER END
205578Smx205022  */
215578Smx205022 
225574Smx205022 /*
236200Smx205022  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245574Smx205022  * Use is subject to license terms.
255574Smx205022  */
265574Smx205022 
275574Smx205022 #pragma ident	"%Z%%M%	%I%	%E% SMI"
285574Smx205022 
295574Smx205022 #include "nge.h"
305574Smx205022 
315574Smx205022 #undef	NGE_DBG
325574Smx205022 #define	NGE_DBG		NGE_DBG_NDD
335574Smx205022 
345574Smx205022 static char transfer_speed_propname[] = "transfer-speed";
355574Smx205022 static char speed_propname[] = "speed";
365574Smx205022 static char duplex_propname[] = "full-duplex";
375574Smx205022 
385574Smx205022 /*
396200Smx205022  * synchronize the  adv* and en* parameters.
406200Smx205022  *
416200Smx205022  * See comments in <sys/dld.h> for details of the *_en_*
426200Smx205022  * parameters.  The usage of ndd for setting adv parameters will
436200Smx205022  * synchronize all the en parameters with the nge parameters,
446200Smx205022  * implicitly disabling any settings made via dladm.
456200Smx205022  */
466200Smx205022 static void
nge_param_sync(nge_t * ngep)476200Smx205022 nge_param_sync(nge_t *ngep)
486200Smx205022 {
496200Smx205022 	ngep->param_en_pause = ngep->param_adv_pause;
506200Smx205022 	ngep->param_en_asym_pause = ngep->param_adv_asym_pause;
516200Smx205022 	ngep->param_en_1000fdx = ngep->param_adv_1000fdx;
526200Smx205022 	ngep->param_en_1000hdx = ngep->param_adv_1000hdx;
536200Smx205022 	ngep->param_en_100fdx = ngep->param_adv_100fdx;
546200Smx205022 	ngep->param_en_100hdx = ngep->param_adv_100hdx;
556200Smx205022 	ngep->param_en_10fdx = ngep->param_adv_10fdx;
566200Smx205022 	ngep->param_en_10hdx = ngep->param_adv_10hdx;
576200Smx205022 }
586200Smx205022 
59*6512Ssowmini 
60*6512Ssowmini boolean_t
nge_nd_get_prop_val(dev_info_t * dip,char * nm,long min,long max,int * pval)61*6512Ssowmini nge_nd_get_prop_val(dev_info_t *dip, char *nm, long min, long max, int *pval)
625574Smx205022 {
63*6512Ssowmini 	/*
64*6512Ssowmini 	 * If the parameter is writable, and there's a property
65*6512Ssowmini 	 * with the same name, and its value is in range, we use
66*6512Ssowmini 	 * it to initialise the parameter.  If it exists but is
67*6512Ssowmini 	 * out of range, it's ignored.
68*6512Ssowmini 	 */
69*6512Ssowmini 	if (NGE_PROP_EXISTS(dip, nm)) {
70*6512Ssowmini 		*pval = NGE_PROP_GET_INT(dip, nm);
71*6512Ssowmini 		if (*pval >= min && *pval <= max)
72*6512Ssowmini 			return (B_TRUE);
73*6512Ssowmini 	}
74*6512Ssowmini 	return (B_FALSE);
755574Smx205022 }
765574Smx205022 
77*6512Ssowmini #define	NGE_INIT_PROP(propname, fieldname, initval) {		\
78*6512Ssowmini 	if (nge_nd_get_prop_val(dip, propname, 0, 1, &propval)) \
79*6512Ssowmini 		ngep->fieldname = propval;			\
80*6512Ssowmini 	else							\
81*6512Ssowmini 		ngep->fieldname = initval;			\
82*6512Ssowmini }
83*6512Ssowmini 
84*6512Ssowmini static void
nge_nd_param_init(nge_t * ngep)85*6512Ssowmini nge_nd_param_init(nge_t *ngep)
865574Smx205022 {
875574Smx205022 	dev_info_t *dip;
88*6512Ssowmini 	int propval;
895574Smx205022 
905574Smx205022 	dip = ngep->devinfo;
915574Smx205022 
92*6512Ssowmini 	/*
93*6512Ssowmini 	 * initialize values to those from driver.conf (if available)
94*6512Ssowmini 	 * or the default value otherwise.
95*6512Ssowmini 	 */
96*6512Ssowmini 	NGE_INIT_PROP("adv_autoneg_cap", param_adv_autoneg, 1);
97*6512Ssowmini 	NGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 1);
98*6512Ssowmini 	NGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 0);
99*6512Ssowmini 	NGE_INIT_PROP("adv_pause_cap", param_adv_pause, 1);
100*6512Ssowmini 	NGE_INIT_PROP("adv_asym_pause_cap", param_adv_asym_pause, 1);
101*6512Ssowmini 	NGE_INIT_PROP("adv_100fdx_cap", param_adv_100fdx, 1);
102*6512Ssowmini 	NGE_INIT_PROP("adv_100hdx_cap", param_adv_100hdx, 1);
103*6512Ssowmini 	NGE_INIT_PROP("adv_10fdx_cap", param_adv_10fdx, 1);
104*6512Ssowmini 	NGE_INIT_PROP("adv_10hdx_cap", param_adv_10hdx, 1);
1055574Smx205022 }
1065574Smx205022 
1075574Smx205022 int
nge_nd_init(nge_t * ngep)1085574Smx205022 nge_nd_init(nge_t *ngep)
1095574Smx205022 {
110*6512Ssowmini 	dev_info_t *dip;
1115574Smx205022 	int duplex;
1125574Smx205022 	int speed;
1135574Smx205022 
1145574Smx205022 	NGE_TRACE(("nge_nd_init($%p)", (void *)ngep));
115*6512Ssowmini 
1165574Smx205022 	/*
117*6512Ssowmini 	 * initialize from .conf file, if appropriate.
1185574Smx205022 	 */
119*6512Ssowmini 	nge_nd_param_init(ngep);
1205574Smx205022 
1215574Smx205022 	/*
1225574Smx205022 	 * The link speed may be forced to 10, 100 or 1000 Mbps using
1235574Smx205022 	 * the property "transfer-speed". This may be done in OBP by
1245574Smx205022 	 * using the command "apply transfer-speed=<speed> <device>".
1255574Smx205022 	 * The speed may be 10, 100 or 1000 - any other value will be
1265574Smx205022 	 * ignored.  Note that this does *enables* autonegotiation, but
1275574Smx205022 	 * restricts it to the speed specified by the property.
1285574Smx205022 	 */
1295574Smx205022 	dip = ngep->devinfo;
1305574Smx205022 	if (NGE_PROP_EXISTS(dip, transfer_speed_propname)) {
1315574Smx205022 
1325574Smx205022 		speed = NGE_PROP_GET_INT(dip, transfer_speed_propname);
1335574Smx205022 		nge_log(ngep, "%s property is %d",
1345574Smx205022 		    transfer_speed_propname, speed);
1355574Smx205022 
1365574Smx205022 		switch (speed) {
1375574Smx205022 		case 1000:
1385574Smx205022 			ngep->param_adv_autoneg = 1;
1395574Smx205022 			ngep->param_adv_1000fdx = 1;
1405574Smx205022 			ngep->param_adv_1000hdx = 0;
1415574Smx205022 			ngep->param_adv_100fdx = 0;
1425574Smx205022 			ngep->param_adv_100hdx = 0;
1435574Smx205022 			ngep->param_adv_10fdx = 0;
1445574Smx205022 			ngep->param_adv_10hdx = 0;
1455574Smx205022 			break;
1465574Smx205022 
1475574Smx205022 		case 100:
1485574Smx205022 			ngep->param_adv_autoneg = 1;
1495574Smx205022 			ngep->param_adv_1000fdx = 0;
1505574Smx205022 			ngep->param_adv_1000hdx = 0;
1515574Smx205022 			ngep->param_adv_100fdx = 1;
1525574Smx205022 			ngep->param_adv_100hdx = 1;
1535574Smx205022 			ngep->param_adv_10fdx = 0;
1545574Smx205022 			ngep->param_adv_10hdx = 0;
1555574Smx205022 			break;
1565574Smx205022 
1575574Smx205022 		case 10:
1585574Smx205022 			ngep->param_adv_autoneg = 1;
1595574Smx205022 			ngep->param_adv_1000fdx = 0;
1605574Smx205022 			ngep->param_adv_1000hdx = 0;
1615574Smx205022 			ngep->param_adv_100fdx = 0;
1625574Smx205022 			ngep->param_adv_100hdx = 0;
1635574Smx205022 			ngep->param_adv_10fdx = 1;
1645574Smx205022 			ngep->param_adv_10hdx = 1;
1655574Smx205022 			break;
1665574Smx205022 
1675574Smx205022 		default:
1685574Smx205022 			break;
1695574Smx205022 		}
1705574Smx205022 	}
1715574Smx205022 
1725574Smx205022 	/*
1735574Smx205022 	 * Also check the "speed" and "full-duplex" properties.  Setting
1745574Smx205022 	 * these properties will override all other settings and *disable*
1755574Smx205022 	 * autonegotiation, so both should be specified if either one is.
1765574Smx205022 	 * Otherwise, the unspecified parameter will be set to a default
1775574Smx205022 	 * value (1000Mb/s, full-duplex).
1785574Smx205022 	 */
1795574Smx205022 	if (NGE_PROP_EXISTS(dip, speed_propname) ||
1805574Smx205022 	    NGE_PROP_EXISTS(dip, duplex_propname)) {
1815574Smx205022 
1825574Smx205022 		ngep->param_adv_autoneg = 0;
1835574Smx205022 		ngep->param_adv_1000fdx = 1;
1845574Smx205022 		ngep->param_adv_1000hdx = 0;
1855574Smx205022 		ngep->param_adv_100fdx = 1;
1865574Smx205022 		ngep->param_adv_100hdx = 1;
1875574Smx205022 		ngep->param_adv_10fdx = 1;
1885574Smx205022 		ngep->param_adv_10hdx = 1;
1895574Smx205022 
1905574Smx205022 		speed = NGE_PROP_GET_INT(dip, speed_propname);
1915574Smx205022 		duplex = NGE_PROP_GET_INT(dip, duplex_propname);
1925574Smx205022 		nge_log(ngep, "%s property is %d",
1935574Smx205022 		    speed_propname, speed);
1945574Smx205022 		nge_log(ngep, "%s property is %d",
1955574Smx205022 		    duplex_propname, duplex);
1965574Smx205022 
1975574Smx205022 		switch (speed) {
1985574Smx205022 		case 1000:
1995574Smx205022 		default:
2005574Smx205022 			ngep->param_adv_100fdx = 0;
2015574Smx205022 			ngep->param_adv_100hdx = 0;
2025574Smx205022 			ngep->param_adv_10fdx = 0;
2035574Smx205022 			ngep->param_adv_10hdx = 0;
2045574Smx205022 			break;
2055574Smx205022 
2065574Smx205022 		case 100:
2075574Smx205022 			ngep->param_adv_1000fdx = 0;
2085574Smx205022 			ngep->param_adv_1000hdx = 0;
2095574Smx205022 			ngep->param_adv_10fdx = 0;
2105574Smx205022 			ngep->param_adv_10hdx = 0;
2115574Smx205022 			break;
2125574Smx205022 
2135574Smx205022 		case 10:
2145574Smx205022 			ngep->param_adv_1000fdx = 0;
2155574Smx205022 			ngep->param_adv_1000hdx = 0;
2165574Smx205022 			ngep->param_adv_100fdx = 0;
2175574Smx205022 			ngep->param_adv_100hdx = 0;
2185574Smx205022 			break;
2195574Smx205022 		}
2205574Smx205022 
2215574Smx205022 		switch (duplex) {
2225574Smx205022 		default:
2235574Smx205022 		case 1:
2245574Smx205022 			ngep->param_adv_1000hdx = 0;
2255574Smx205022 			ngep->param_adv_100hdx = 0;
2265574Smx205022 			ngep->param_adv_10hdx = 0;
2275574Smx205022 			break;
2285574Smx205022 
2295574Smx205022 		case 0:
2305574Smx205022 			ngep->param_adv_1000fdx = 0;
2315574Smx205022 			ngep->param_adv_100fdx = 0;
2325574Smx205022 			ngep->param_adv_10fdx = 0;
2335574Smx205022 			break;
2345574Smx205022 		}
2355574Smx205022 	}
2365574Smx205022 
237*6512Ssowmini 
2386200Smx205022 	nge_param_sync(ngep);
2396200Smx205022 
2405574Smx205022 	return (0);
2415574Smx205022 }
242