17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 562387023Sdduvall * Common Development and Distribution License (the "License"). 662387023Sdduvall * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2162387023Sdduvall 227c478bd9Sstevel@tonic-gate /* 23e7801d59Ssowmini * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27f724721bSzh199473 #include "bge_impl.h" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #define BGE_DBG BGE_DBG_NDD /* debug flag for this code */ 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Property names 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate static char transfer_speed_propname[] = "transfer-speed"; 357c478bd9Sstevel@tonic-gate static char speed_propname[] = "speed"; 367c478bd9Sstevel@tonic-gate static char duplex_propname[] = "full-duplex"; 37256e438eSzh199473 static char supported_net[] = "supported-network-types"; 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 40e7801d59Ssowmini * synchronize the adv* and en* parameters. 41e7801d59Ssowmini * 42e7801d59Ssowmini * See comments in <sys/dld.h> for details of the *_en_* 43e7801d59Ssowmini * parameters. The usage of ndd for setting adv parameters will 44e7801d59Ssowmini * synchronize all the en parameters with the bge parameters, 45e7801d59Ssowmini * implicitly disabling any settings made via dladm. 46e7801d59Ssowmini */ 47e7801d59Ssowmini static void 48e7801d59Ssowmini bge_param_sync(bge_t *bgep) 49e7801d59Ssowmini { 50e7801d59Ssowmini bgep->param_en_pause = bgep->param_adv_pause; 51e7801d59Ssowmini bgep->param_en_asym_pause = bgep->param_adv_asym_pause; 52e7801d59Ssowmini bgep->param_en_1000fdx = bgep->param_adv_1000fdx; 53e7801d59Ssowmini bgep->param_en_1000hdx = bgep->param_adv_1000hdx; 54e7801d59Ssowmini bgep->param_en_100fdx = bgep->param_adv_100fdx; 55e7801d59Ssowmini bgep->param_en_100hdx = bgep->param_adv_100hdx; 56e7801d59Ssowmini bgep->param_en_10fdx = bgep->param_adv_10fdx; 57e7801d59Ssowmini bgep->param_en_10hdx = bgep->param_adv_10hdx; 58e7801d59Ssowmini } 59e7801d59Ssowmini 604045d941Ssowmini boolean_t 614045d941Ssowmini bge_nd_get_prop_val(dev_info_t *dip, char *nm, long min, long max, int *pval) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate /* 644045d941Ssowmini * If there is a driver.conf setting for the prop, we use 657c478bd9Sstevel@tonic-gate * it to initialise the parameter. If it exists but is 667c478bd9Sstevel@tonic-gate * out of range, it's ignored. 677c478bd9Sstevel@tonic-gate */ 684045d941Ssowmini if (BGE_PROP_EXISTS(dip, nm)) { 694045d941Ssowmini *pval = BGE_PROP_GET_INT(dip, nm); 704045d941Ssowmini if (*pval >= min && *pval <= max) 714045d941Ssowmini return (B_TRUE); 727c478bd9Sstevel@tonic-gate } 734045d941Ssowmini return (B_FALSE); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 764045d941Ssowmini #define BGE_INIT_PROP(propname, fieldname, initval) { \ 774045d941Ssowmini if (bge_nd_get_prop_val(dip, propname, 0, 1, &propval)) \ 784045d941Ssowmini bgep->fieldname = propval; \ 794045d941Ssowmini else \ 804045d941Ssowmini bgep->fieldname = initval; \ 814045d941Ssowmini } 827c478bd9Sstevel@tonic-gate 834045d941Ssowmini static void 844045d941Ssowmini bge_nd_param_init(bge_t *bgep) 854045d941Ssowmini { 864045d941Ssowmini dev_info_t *dip; 874045d941Ssowmini int flags = bgep->chipid.flags; 884045d941Ssowmini int propval; 894045d941Ssowmini 904045d941Ssowmini dip = bgep->devinfo; 914045d941Ssowmini 924045d941Ssowmini /* 934045d941Ssowmini * initialize values to those from driver.conf (if available) 944045d941Ssowmini * or the default value otherwise. 954045d941Ssowmini */ 964045d941Ssowmini BGE_INIT_PROP("adv_autoneg_cap", param_adv_autoneg, 1); 97*5a506a18Syong tan - Sun Microsystems - Beijing China if (DEVICE_5906_SERIES_CHIPSETS(bgep)) { 98*5a506a18Syong tan - Sun Microsystems - Beijing China BGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 0); 99*5a506a18Syong tan - Sun Microsystems - Beijing China BGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 0); 100*5a506a18Syong tan - Sun Microsystems - Beijing China } else { 1014045d941Ssowmini BGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 1); 1024045d941Ssowmini BGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 1); 103*5a506a18Syong tan - Sun Microsystems - Beijing China } 1049729ce87SSowmini Varadhan BGE_INIT_PROP("adv_pause_cap", param_adv_pause, 1); 1059729ce87SSowmini Varadhan BGE_INIT_PROP("adv_asym_pause_cap", param_adv_asym_pause, 1); 1064045d941Ssowmini 1074045d941Ssowmini if (flags & CHIP_FLAG_SERDES) { 1084045d941Ssowmini bgep->param_adv_100fdx = 0; 1094045d941Ssowmini bgep->param_adv_100hdx = 0; 1104045d941Ssowmini bgep->param_adv_10fdx = 0; 1114045d941Ssowmini bgep->param_adv_10hdx = 0; 1124045d941Ssowmini } else { 1134045d941Ssowmini BGE_INIT_PROP("adv_100fdx_cap", param_adv_100fdx, 1); 1144045d941Ssowmini BGE_INIT_PROP("adv_100hdx_cap", param_adv_100hdx, 1); 1154045d941Ssowmini BGE_INIT_PROP("adv_10fdx_cap", param_adv_10fdx, 1); 1164045d941Ssowmini BGE_INIT_PROP("adv_10hdx_cap", param_adv_10hdx, 1); 1174045d941Ssowmini } 1184045d941Ssowmini 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate int 1227c478bd9Sstevel@tonic-gate bge_nd_init(bge_t *bgep) 1237c478bd9Sstevel@tonic-gate { 1247c478bd9Sstevel@tonic-gate dev_info_t *dip; 1257c478bd9Sstevel@tonic-gate int duplex; 1267c478bd9Sstevel@tonic-gate int speed; 127256e438eSzh199473 char **options, *prop; 128256e438eSzh199473 uint_t noptions; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate BGE_TRACE(("bge_nd_init($%p)", (void *)bgep)); 1314045d941Ssowmini bge_nd_param_init(bgep); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1344045d941Ssowmini * initialize from .conf file, if appropriate. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 138256e438eSzh199473 * check the OBP property "supported-network-types" 139256e438eSzh199473 */ 140256e438eSzh199473 if (BGE_PROP_EXISTS(bgep->devinfo, supported_net)) { 141256e438eSzh199473 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, bgep->devinfo, 142256e438eSzh199473 DDI_PROP_DONTPASS, supported_net, 143256e438eSzh199473 &options, &noptions) == DDI_PROP_SUCCESS) { 144256e438eSzh199473 145256e438eSzh199473 bgep->param_adv_autoneg = 0; 146256e438eSzh199473 bgep->param_adv_1000fdx = 0; 147256e438eSzh199473 bgep->param_adv_1000hdx = 0; 148256e438eSzh199473 bgep->param_adv_100fdx = 0; 149256e438eSzh199473 bgep->param_adv_100hdx = 0; 150256e438eSzh199473 bgep->param_adv_10fdx = 0; 151256e438eSzh199473 bgep->param_adv_10hdx = 0; 152256e438eSzh199473 153256e438eSzh199473 for (; noptions > 0; noptions--) { 154256e438eSzh199473 prop = options[noptions-1]; 155256e438eSzh199473 if (strstr(prop, "ethernet") == NULL) 156256e438eSzh199473 continue; 157256e438eSzh199473 if (strstr(prop, "1000")) { 158256e438eSzh199473 if (strstr(prop, "auto")) { 159256e438eSzh199473 bgep->param_adv_1000fdx = 1; 160256e438eSzh199473 bgep->param_adv_1000hdx = 1; 161256e438eSzh199473 bgep->param_adv_autoneg = 1; 162256e438eSzh199473 } else if (strstr(prop, "full")) 163256e438eSzh199473 bgep->param_adv_1000fdx = 1; 164256e438eSzh199473 else if (strstr(prop, "half")) 165256e438eSzh199473 bgep->param_adv_1000hdx = 1; 166256e438eSzh199473 } else if (strstr(prop, "100")) { 167256e438eSzh199473 if (strstr(prop, "auto")) { 168256e438eSzh199473 bgep->param_adv_100fdx = 1; 169256e438eSzh199473 bgep->param_adv_100hdx = 1; 170256e438eSzh199473 bgep->param_adv_autoneg = 1; 171256e438eSzh199473 } else if (strstr(prop, "full")) 172256e438eSzh199473 bgep->param_adv_100fdx = 1; 173256e438eSzh199473 else if (strstr(prop, "half")) 174256e438eSzh199473 bgep->param_adv_100hdx = 1; 175256e438eSzh199473 } else if (strstr(prop, "10")) { 176256e438eSzh199473 if (strstr(prop, "auto")) { 177256e438eSzh199473 bgep->param_adv_10fdx = 1; 178256e438eSzh199473 bgep->param_adv_10hdx = 1; 179256e438eSzh199473 bgep->param_adv_autoneg = 1; 180256e438eSzh199473 } else if (strstr(prop, "full")) 181256e438eSzh199473 bgep->param_adv_10fdx = 1; 182256e438eSzh199473 else if (strstr(prop, "half")) 183256e438eSzh199473 bgep->param_adv_10hdx = 1; 184256e438eSzh199473 } 185256e438eSzh199473 } 186256e438eSzh199473 187256e438eSzh199473 ddi_prop_free(options); 188256e438eSzh199473 } 189256e438eSzh199473 } 190256e438eSzh199473 191256e438eSzh199473 /* 1927c478bd9Sstevel@tonic-gate * The link speed may be forced to 10, 100 or 1000 Mbps using 1937c478bd9Sstevel@tonic-gate * the property "transfer-speed". This may be done in OBP by 1947c478bd9Sstevel@tonic-gate * using the command "apply transfer-speed=<speed> <device>". 1957c478bd9Sstevel@tonic-gate * The speed may be 10, 100 or 1000 - any other value will be 1967c478bd9Sstevel@tonic-gate * ignored. Note that this does *enables* autonegotiation, but 1977c478bd9Sstevel@tonic-gate * restricts it to the speed specified by the property. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate dip = bgep->devinfo; 2007c478bd9Sstevel@tonic-gate if (BGE_PROP_EXISTS(dip, transfer_speed_propname)) { 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate speed = BGE_PROP_GET_INT(dip, transfer_speed_propname); 2037c478bd9Sstevel@tonic-gate bge_log(bgep, "%s property is %d", 2047c478bd9Sstevel@tonic-gate transfer_speed_propname, speed); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate switch (speed) { 2077c478bd9Sstevel@tonic-gate case 1000: 2087c478bd9Sstevel@tonic-gate bgep->param_adv_autoneg = 1; 2097c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 1; 2107c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 1; 2117c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 0; 2127c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 0; 2137c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 0; 2147c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 0; 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate case 100: 2187c478bd9Sstevel@tonic-gate bgep->param_adv_autoneg = 1; 2197c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 0; 2207c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 0; 2217c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 1; 2227c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 1; 2237c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 0; 2247c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 0; 2257c478bd9Sstevel@tonic-gate break; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate case 10: 2287c478bd9Sstevel@tonic-gate bgep->param_adv_autoneg = 1; 2297c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 0; 2307c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 0; 2317c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 0; 2327c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 0; 2337c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 1; 2347c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 1; 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate default: 2387c478bd9Sstevel@tonic-gate break; 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Also check the "speed" and "full-duplex" properties. Setting 2447c478bd9Sstevel@tonic-gate * these properties will override all other settings and *disable* 2457c478bd9Sstevel@tonic-gate * autonegotiation, so both should be specified if either one is. 2467c478bd9Sstevel@tonic-gate * Otherwise, the unspecified parameter will be set to a default 2477c478bd9Sstevel@tonic-gate * value (1000Mb/s, full-duplex). 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate if (BGE_PROP_EXISTS(dip, speed_propname) || 2507c478bd9Sstevel@tonic-gate BGE_PROP_EXISTS(dip, duplex_propname)) { 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate bgep->param_adv_autoneg = 0; 2537c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 1; 2547c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 1; 2557c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 1; 2567c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 1; 2577c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 1; 2587c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 1; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate speed = BGE_PROP_GET_INT(dip, speed_propname); 2617c478bd9Sstevel@tonic-gate duplex = BGE_PROP_GET_INT(dip, duplex_propname); 2627c478bd9Sstevel@tonic-gate bge_log(bgep, "%s property is %d", 2637c478bd9Sstevel@tonic-gate speed_propname, speed); 2647c478bd9Sstevel@tonic-gate bge_log(bgep, "%s property is %d", 2657c478bd9Sstevel@tonic-gate duplex_propname, duplex); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate switch (speed) { 2687c478bd9Sstevel@tonic-gate case 1000: 2697c478bd9Sstevel@tonic-gate default: 2707c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 0; 2717c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 0; 2727c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 0; 2737c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 0; 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate case 100: 2777c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 0; 2787c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 0; 2797c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 0; 2807c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 0; 2817c478bd9Sstevel@tonic-gate break; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate case 10: 2847c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 0; 2857c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 0; 2867c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 0; 2877c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 0; 2887c478bd9Sstevel@tonic-gate break; 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate switch (duplex) { 2927c478bd9Sstevel@tonic-gate default: 2937c478bd9Sstevel@tonic-gate case 1: 2947c478bd9Sstevel@tonic-gate bgep->param_adv_1000hdx = 0; 2957c478bd9Sstevel@tonic-gate bgep->param_adv_100hdx = 0; 2967c478bd9Sstevel@tonic-gate bgep->param_adv_10hdx = 0; 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate case 0: 3007c478bd9Sstevel@tonic-gate bgep->param_adv_1000fdx = 0; 3017c478bd9Sstevel@tonic-gate bgep->param_adv_100fdx = 0; 3027c478bd9Sstevel@tonic-gate bgep->param_adv_10fdx = 0; 3037c478bd9Sstevel@tonic-gate break; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 307e7801d59Ssowmini bge_param_sync(bgep); 308e7801d59Ssowmini 3097c478bd9Sstevel@tonic-gate return (0); 3107c478bd9Sstevel@tonic-gate } 311