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