Home | History | Annotate | Download | only in bge
      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 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include "bge_impl.h"
     28 
     29 
     30 #define	BGE_DBG		BGE_DBG_NDD	/* debug flag for this code	*/
     31 /*
     32  * Property names
     33  */
     34 static char transfer_speed_propname[] = "transfer-speed";
     35 static char speed_propname[] = "speed";
     36 static char duplex_propname[] = "full-duplex";
     37 static char supported_net[] = "supported-network-types";
     38 
     39 /*
     40  * synchronize the  adv* and en* parameters.
     41  *
     42  * See comments in <sys/dld.h> for details of the *_en_*
     43  * parameters.  The usage of ndd for setting adv parameters will
     44  * synchronize all the en parameters with the bge parameters,
     45  * implicitly disabling any settings made via dladm.
     46  */
     47 static void
     48 bge_param_sync(bge_t *bgep)
     49 {
     50 	bgep->param_en_pause = bgep->param_adv_pause;
     51 	bgep->param_en_asym_pause = bgep->param_adv_asym_pause;
     52 	bgep->param_en_1000fdx = bgep->param_adv_1000fdx;
     53 	bgep->param_en_1000hdx = bgep->param_adv_1000hdx;
     54 	bgep->param_en_100fdx = bgep->param_adv_100fdx;
     55 	bgep->param_en_100hdx = bgep->param_adv_100hdx;
     56 	bgep->param_en_10fdx = bgep->param_adv_10fdx;
     57 	bgep->param_en_10hdx = bgep->param_adv_10hdx;
     58 }
     59 
     60 boolean_t
     61 bge_nd_get_prop_val(dev_info_t *dip, char *nm, long min, long max, int *pval)
     62 {
     63 	/*
     64 	 * If there is a driver.conf setting for the prop, we use
     65 	 * it to initialise the parameter.  If it exists but is
     66 	 * out of range, it's ignored.
     67 	 */
     68 	if (BGE_PROP_EXISTS(dip, nm)) {
     69 		*pval = BGE_PROP_GET_INT(dip, nm);
     70 		if (*pval >= min && *pval <= max)
     71 			return (B_TRUE);
     72 	}
     73 	return (B_FALSE);
     74 }
     75 
     76 #define	BGE_INIT_PROP(propname, fieldname, initval) {		\
     77 	if (bge_nd_get_prop_val(dip, propname, 0, 1, &propval)) \
     78 		bgep->fieldname = propval;			\
     79 	else							\
     80 		bgep->fieldname = initval;			\
     81 }
     82 
     83 static void
     84 bge_nd_param_init(bge_t *bgep)
     85 {
     86 	dev_info_t *dip;
     87 	int flags = bgep->chipid.flags;
     88 	int propval;
     89 
     90 	dip = bgep->devinfo;
     91 
     92 	/*
     93 	 * initialize values to those from driver.conf (if available)
     94 	 * or the default value otherwise.
     95 	 */
     96 	BGE_INIT_PROP("adv_autoneg_cap", param_adv_autoneg, 1);
     97 	if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
     98 		BGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 0);
     99 		BGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 0);
    100 	} else {
    101 		BGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 1);
    102 		BGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 1);
    103 	}
    104 	BGE_INIT_PROP("adv_pause_cap", param_adv_pause, 1);
    105 	BGE_INIT_PROP("adv_asym_pause_cap", param_adv_asym_pause, 1);
    106 
    107 	if (flags & CHIP_FLAG_SERDES) {
    108 		bgep->param_adv_100fdx = 0;
    109 		bgep->param_adv_100hdx = 0;
    110 		bgep->param_adv_10fdx = 0;
    111 		bgep->param_adv_10hdx = 0;
    112 	} else {
    113 		BGE_INIT_PROP("adv_100fdx_cap", param_adv_100fdx, 1);
    114 		BGE_INIT_PROP("adv_100hdx_cap", param_adv_100hdx, 1);
    115 		BGE_INIT_PROP("adv_10fdx_cap", param_adv_10fdx, 1);
    116 		BGE_INIT_PROP("adv_10hdx_cap", param_adv_10hdx, 1);
    117 	}
    118 
    119 }
    120 
    121 int
    122 bge_nd_init(bge_t *bgep)
    123 {
    124 	dev_info_t *dip;
    125 	int duplex;
    126 	int speed;
    127 	char **options, *prop;
    128 	uint_t  noptions;
    129 
    130 	BGE_TRACE(("bge_nd_init($%p)", (void *)bgep));
    131 	bge_nd_param_init(bgep);
    132 
    133 	/*
    134 	 * initialize from .conf file, if appropriate.
    135 	 */
    136 
    137 	/*
    138 	 * check the OBP property "supported-network-types"
    139 	 */
    140 	if (BGE_PROP_EXISTS(bgep->devinfo, supported_net)) {
    141 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, bgep->devinfo,
    142 		    DDI_PROP_DONTPASS, supported_net,
    143 		    &options, &noptions) == DDI_PROP_SUCCESS) {
    144 
    145 			bgep->param_adv_autoneg = 0;
    146 			bgep->param_adv_1000fdx = 0;
    147 			bgep->param_adv_1000hdx = 0;
    148 			bgep->param_adv_100fdx = 0;
    149 			bgep->param_adv_100hdx = 0;
    150 			bgep->param_adv_10fdx = 0;
    151 			bgep->param_adv_10hdx = 0;
    152 
    153 			for (; noptions > 0; noptions--) {
    154 				prop = options[noptions-1];
    155 				if (strstr(prop, "ethernet") == NULL)
    156 					continue;
    157 				if (strstr(prop, "1000")) {
    158 					if (strstr(prop, "auto")) {
    159 						bgep->param_adv_1000fdx = 1;
    160 						bgep->param_adv_1000hdx = 1;
    161 						bgep->param_adv_autoneg = 1;
    162 					} else if (strstr(prop, "full"))
    163 						bgep->param_adv_1000fdx = 1;
    164 					else if (strstr(prop, "half"))
    165 						bgep->param_adv_1000hdx = 1;
    166 				} else if (strstr(prop, "100")) {
    167 					if (strstr(prop, "auto")) {
    168 						bgep->param_adv_100fdx = 1;
    169 						bgep->param_adv_100hdx = 1;
    170 						bgep->param_adv_autoneg = 1;
    171 					} else if (strstr(prop, "full"))
    172 						bgep->param_adv_100fdx = 1;
    173 					else if (strstr(prop, "half"))
    174 						bgep->param_adv_100hdx = 1;
    175 				} else if (strstr(prop, "10")) {
    176 					if (strstr(prop, "auto")) {
    177 						bgep->param_adv_10fdx = 1;
    178 						bgep->param_adv_10hdx = 1;
    179 						bgep->param_adv_autoneg = 1;
    180 					} else if (strstr(prop, "full"))
    181 						bgep->param_adv_10fdx = 1;
    182 					else if (strstr(prop, "half"))
    183 						bgep->param_adv_10hdx = 1;
    184 				}
    185 			}
    186 
    187 			ddi_prop_free(options);
    188 		}
    189 	}
    190 
    191 	/*
    192 	 * The link speed may be forced to 10, 100 or 1000 Mbps using
    193 	 * the property "transfer-speed". This may be done in OBP by
    194 	 * using the command "apply transfer-speed=<speed> <device>".
    195 	 * The speed may be 10, 100 or 1000 - any other value will be
    196 	 * ignored.  Note that this does *enables* autonegotiation, but
    197 	 * restricts it to the speed specified by the property.
    198 	 */
    199 	dip = bgep->devinfo;
    200 	if (BGE_PROP_EXISTS(dip, transfer_speed_propname)) {
    201 
    202 		speed = BGE_PROP_GET_INT(dip, transfer_speed_propname);
    203 		bge_log(bgep, "%s property is %d",
    204 		    transfer_speed_propname, speed);
    205 
    206 		switch (speed) {
    207 		case 1000:
    208 			bgep->param_adv_autoneg = 1;
    209 			bgep->param_adv_1000fdx = 1;
    210 			bgep->param_adv_1000hdx = 1;
    211 			bgep->param_adv_100fdx = 0;
    212 			bgep->param_adv_100hdx = 0;
    213 			bgep->param_adv_10fdx = 0;
    214 			bgep->param_adv_10hdx = 0;
    215 			break;
    216 
    217 		case 100:
    218 			bgep->param_adv_autoneg = 1;
    219 			bgep->param_adv_1000fdx = 0;
    220 			bgep->param_adv_1000hdx = 0;
    221 			bgep->param_adv_100fdx = 1;
    222 			bgep->param_adv_100hdx = 1;
    223 			bgep->param_adv_10fdx = 0;
    224 			bgep->param_adv_10hdx = 0;
    225 			break;
    226 
    227 		case 10:
    228 			bgep->param_adv_autoneg = 1;
    229 			bgep->param_adv_1000fdx = 0;
    230 			bgep->param_adv_1000hdx = 0;
    231 			bgep->param_adv_100fdx = 0;
    232 			bgep->param_adv_100hdx = 0;
    233 			bgep->param_adv_10fdx = 1;
    234 			bgep->param_adv_10hdx = 1;
    235 			break;
    236 
    237 		default:
    238 			break;
    239 		}
    240 	}
    241 
    242 	/*
    243 	 * Also check the "speed" and "full-duplex" properties.  Setting
    244 	 * these properties will override all other settings and *disable*
    245 	 * autonegotiation, so both should be specified if either one is.
    246 	 * Otherwise, the unspecified parameter will be set to a default
    247 	 * value (1000Mb/s, full-duplex).
    248 	 */
    249 	if (BGE_PROP_EXISTS(dip, speed_propname) ||
    250 	    BGE_PROP_EXISTS(dip, duplex_propname)) {
    251 
    252 		bgep->param_adv_autoneg = 0;
    253 		bgep->param_adv_1000fdx = 1;
    254 		bgep->param_adv_1000hdx = 1;
    255 		bgep->param_adv_100fdx = 1;
    256 		bgep->param_adv_100hdx = 1;
    257 		bgep->param_adv_10fdx = 1;
    258 		bgep->param_adv_10hdx = 1;
    259 
    260 		speed = BGE_PROP_GET_INT(dip, speed_propname);
    261 		duplex = BGE_PROP_GET_INT(dip, duplex_propname);
    262 		bge_log(bgep, "%s property is %d",
    263 		    speed_propname, speed);
    264 		bge_log(bgep, "%s property is %d",
    265 		    duplex_propname, duplex);
    266 
    267 		switch (speed) {
    268 		case 1000:
    269 		default:
    270 			bgep->param_adv_100fdx = 0;
    271 			bgep->param_adv_100hdx = 0;
    272 			bgep->param_adv_10fdx = 0;
    273 			bgep->param_adv_10hdx = 0;
    274 			break;
    275 
    276 		case 100:
    277 			bgep->param_adv_1000fdx = 0;
    278 			bgep->param_adv_1000hdx = 0;
    279 			bgep->param_adv_10fdx = 0;
    280 			bgep->param_adv_10hdx = 0;
    281 			break;
    282 
    283 		case 10:
    284 			bgep->param_adv_1000fdx = 0;
    285 			bgep->param_adv_1000hdx = 0;
    286 			bgep->param_adv_100fdx = 0;
    287 			bgep->param_adv_100hdx = 0;
    288 			break;
    289 		}
    290 
    291 		switch (duplex) {
    292 		default:
    293 		case 1:
    294 			bgep->param_adv_1000hdx = 0;
    295 			bgep->param_adv_100hdx = 0;
    296 			bgep->param_adv_10hdx = 0;
    297 			break;
    298 
    299 		case 0:
    300 			bgep->param_adv_1000fdx = 0;
    301 			bgep->param_adv_100fdx = 0;
    302 			bgep->param_adv_10fdx = 0;
    303 			break;
    304 		}
    305 	}
    306 
    307 	bge_param_sync(bgep);
    308 
    309 	return (0);
    310 }
    311