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