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 "nge.h" 28 29 #undef NGE_DBG 30 #define NGE_DBG NGE_DBG_NDD 31 32 static char transfer_speed_propname[] = "transfer-speed"; 33 static char speed_propname[] = "speed"; 34 static char duplex_propname[] = "full-duplex"; 35 36 /* 37 * synchronize the adv* and en* parameters. 38 * 39 * See comments in <sys/dld.h> for details of the *_en_* 40 * parameters. The usage of ndd for setting adv parameters will 41 * synchronize all the en parameters with the nge parameters, 42 * implicitly disabling any settings made via dladm. 43 */ 44 static void 45 nge_param_sync(nge_t *ngep) 46 { 47 ngep->param_en_pause = ngep->param_adv_pause; 48 ngep->param_en_asym_pause = ngep->param_adv_asym_pause; 49 ngep->param_en_1000fdx = ngep->param_adv_1000fdx; 50 ngep->param_en_1000hdx = ngep->param_adv_1000hdx; 51 ngep->param_en_100fdx = ngep->param_adv_100fdx; 52 ngep->param_en_100hdx = ngep->param_adv_100hdx; 53 ngep->param_en_10fdx = ngep->param_adv_10fdx; 54 ngep->param_en_10hdx = ngep->param_adv_10hdx; 55 } 56 57 58 boolean_t 59 nge_nd_get_prop_val(dev_info_t *dip, char *nm, long min, long max, int *pval) 60 { 61 /* 62 * If the parameter is writable, and there's a property 63 * with the same name, and its value is in range, we use 64 * it to initialise the parameter. If it exists but is 65 * out of range, it's ignored. 66 */ 67 if (NGE_PROP_EXISTS(dip, nm)) { 68 *pval = NGE_PROP_GET_INT(dip, nm); 69 if (*pval >= min && *pval <= max) 70 return (B_TRUE); 71 } 72 return (B_FALSE); 73 } 74 75 #define NGE_INIT_PROP(propname, fieldname, initval) { \ 76 if (nge_nd_get_prop_val(dip, propname, 0, 1, &propval)) \ 77 ngep->fieldname = propval; \ 78 else \ 79 ngep->fieldname = initval; \ 80 } 81 82 static void 83 nge_nd_param_init(nge_t *ngep) 84 { 85 dev_info_t *dip; 86 int propval; 87 88 dip = ngep->devinfo; 89 90 /* 91 * initialize values to those from driver.conf (if available) 92 * or the default value otherwise. 93 */ 94 NGE_INIT_PROP("adv_autoneg_cap", param_adv_autoneg, 1); 95 NGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 1); 96 NGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 0); 97 NGE_INIT_PROP("adv_pause_cap", param_adv_pause, 1); 98 NGE_INIT_PROP("adv_asym_pause_cap", param_adv_asym_pause, 1); 99 NGE_INIT_PROP("adv_100fdx_cap", param_adv_100fdx, 1); 100 NGE_INIT_PROP("adv_100hdx_cap", param_adv_100hdx, 1); 101 NGE_INIT_PROP("adv_10fdx_cap", param_adv_10fdx, 1); 102 NGE_INIT_PROP("adv_10hdx_cap", param_adv_10hdx, 1); 103 } 104 105 int 106 nge_nd_init(nge_t *ngep) 107 { 108 dev_info_t *dip; 109 int duplex; 110 int speed; 111 112 NGE_TRACE(("nge_nd_init($%p)", (void *)ngep)); 113 114 /* 115 * initialize from .conf file, if appropriate. 116 */ 117 nge_nd_param_init(ngep); 118 119 /* 120 * The link speed may be forced to 10, 100 or 1000 Mbps using 121 * the property "transfer-speed". This may be done in OBP by 122 * using the command "apply transfer-speed=<speed> <device>". 123 * The speed may be 10, 100 or 1000 - any other value will be 124 * ignored. Note that this does *enables* autonegotiation, but 125 * restricts it to the speed specified by the property. 126 */ 127 dip = ngep->devinfo; 128 if (NGE_PROP_EXISTS(dip, transfer_speed_propname)) { 129 130 speed = NGE_PROP_GET_INT(dip, transfer_speed_propname); 131 nge_log(ngep, "%s property is %d", 132 transfer_speed_propname, speed); 133 134 switch (speed) { 135 case 1000: 136 ngep->param_adv_autoneg = 1; 137 ngep->param_adv_1000fdx = 1; 138 ngep->param_adv_1000hdx = 0; 139 ngep->param_adv_100fdx = 0; 140 ngep->param_adv_100hdx = 0; 141 ngep->param_adv_10fdx = 0; 142 ngep->param_adv_10hdx = 0; 143 break; 144 145 case 100: 146 ngep->param_adv_autoneg = 1; 147 ngep->param_adv_1000fdx = 0; 148 ngep->param_adv_1000hdx = 0; 149 ngep->param_adv_100fdx = 1; 150 ngep->param_adv_100hdx = 1; 151 ngep->param_adv_10fdx = 0; 152 ngep->param_adv_10hdx = 0; 153 break; 154 155 case 10: 156 ngep->param_adv_autoneg = 1; 157 ngep->param_adv_1000fdx = 0; 158 ngep->param_adv_1000hdx = 0; 159 ngep->param_adv_100fdx = 0; 160 ngep->param_adv_100hdx = 0; 161 ngep->param_adv_10fdx = 1; 162 ngep->param_adv_10hdx = 1; 163 break; 164 165 default: 166 break; 167 } 168 } 169 170 /* 171 * Also check the "speed" and "full-duplex" properties. Setting 172 * these properties will override all other settings and *disable* 173 * autonegotiation, so both should be specified if either one is. 174 * Otherwise, the unspecified parameter will be set to a default 175 * value (1000Mb/s, full-duplex). 176 */ 177 if (NGE_PROP_EXISTS(dip, speed_propname) || 178 NGE_PROP_EXISTS(dip, duplex_propname)) { 179 180 ngep->param_adv_autoneg = 0; 181 ngep->param_adv_1000fdx = 1; 182 ngep->param_adv_1000hdx = 0; 183 ngep->param_adv_100fdx = 1; 184 ngep->param_adv_100hdx = 1; 185 ngep->param_adv_10fdx = 1; 186 ngep->param_adv_10hdx = 1; 187 188 speed = NGE_PROP_GET_INT(dip, speed_propname); 189 duplex = NGE_PROP_GET_INT(dip, duplex_propname); 190 nge_log(ngep, "%s property is %d", 191 speed_propname, speed); 192 nge_log(ngep, "%s property is %d", 193 duplex_propname, duplex); 194 195 switch (speed) { 196 case 1000: 197 default: 198 ngep->param_adv_100fdx = 0; 199 ngep->param_adv_100hdx = 0; 200 ngep->param_adv_10fdx = 0; 201 ngep->param_adv_10hdx = 0; 202 break; 203 204 case 100: 205 ngep->param_adv_1000fdx = 0; 206 ngep->param_adv_1000hdx = 0; 207 ngep->param_adv_10fdx = 0; 208 ngep->param_adv_10hdx = 0; 209 break; 210 211 case 10: 212 ngep->param_adv_1000fdx = 0; 213 ngep->param_adv_1000hdx = 0; 214 ngep->param_adv_100fdx = 0; 215 ngep->param_adv_100hdx = 0; 216 break; 217 } 218 219 switch (duplex) { 220 default: 221 case 1: 222 ngep->param_adv_1000hdx = 0; 223 ngep->param_adv_100hdx = 0; 224 ngep->param_adv_10hdx = 0; 225 break; 226 227 case 0: 228 ngep->param_adv_1000fdx = 0; 229 ngep->param_adv_100fdx = 0; 230 ngep->param_adv_10fdx = 0; 231 break; 232 } 233 } 234 235 236 nge_param_sync(ngep); 237 238 return (0); 239 } 240