/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include "nge.h" #undef NGE_DBG #define NGE_DBG NGE_DBG_NDD static char transfer_speed_propname[] = "transfer-speed"; static char speed_propname[] = "speed"; static char duplex_propname[] = "full-duplex"; /* * synchronize the adv* and en* parameters. * * See comments in for details of the *_en_* * parameters. The usage of ndd for setting adv parameters will * synchronize all the en parameters with the nge parameters, * implicitly disabling any settings made via dladm. */ static void nge_param_sync(nge_t *ngep) { ngep->param_en_pause = ngep->param_adv_pause; ngep->param_en_asym_pause = ngep->param_adv_asym_pause; ngep->param_en_1000fdx = ngep->param_adv_1000fdx; ngep->param_en_1000hdx = ngep->param_adv_1000hdx; ngep->param_en_100fdx = ngep->param_adv_100fdx; ngep->param_en_100hdx = ngep->param_adv_100hdx; ngep->param_en_10fdx = ngep->param_adv_10fdx; ngep->param_en_10hdx = ngep->param_adv_10hdx; } boolean_t nge_nd_get_prop_val(dev_info_t *dip, char *nm, long min, long max, int *pval) { /* * If the parameter is writable, and there's a property * with the same name, and its value is in range, we use * it to initialise the parameter. If it exists but is * out of range, it's ignored. */ if (NGE_PROP_EXISTS(dip, nm)) { *pval = NGE_PROP_GET_INT(dip, nm); if (*pval >= min && *pval <= max) return (B_TRUE); } return (B_FALSE); } #define NGE_INIT_PROP(propname, fieldname, initval) { \ if (nge_nd_get_prop_val(dip, propname, 0, 1, &propval)) \ ngep->fieldname = propval; \ else \ ngep->fieldname = initval; \ } static void nge_nd_param_init(nge_t *ngep) { dev_info_t *dip; int propval; dip = ngep->devinfo; /* * initialize values to those from driver.conf (if available) * or the default value otherwise. */ NGE_INIT_PROP("adv_autoneg_cap", param_adv_autoneg, 1); NGE_INIT_PROP("adv_1000fdx_cap", param_adv_1000fdx, 1); NGE_INIT_PROP("adv_1000hdx_cap", param_adv_1000hdx, 0); NGE_INIT_PROP("adv_pause_cap", param_adv_pause, 1); NGE_INIT_PROP("adv_asym_pause_cap", param_adv_asym_pause, 1); NGE_INIT_PROP("adv_100fdx_cap", param_adv_100fdx, 1); NGE_INIT_PROP("adv_100hdx_cap", param_adv_100hdx, 1); NGE_INIT_PROP("adv_10fdx_cap", param_adv_10fdx, 1); NGE_INIT_PROP("adv_10hdx_cap", param_adv_10hdx, 1); } int nge_nd_init(nge_t *ngep) { dev_info_t *dip; int duplex; int speed; NGE_TRACE(("nge_nd_init($%p)", (void *)ngep)); /* * initialize from .conf file, if appropriate. */ nge_nd_param_init(ngep); /* * The link speed may be forced to 10, 100 or 1000 Mbps using * the property "transfer-speed". This may be done in OBP by * using the command "apply transfer-speed= ". * The speed may be 10, 100 or 1000 - any other value will be * ignored. Note that this does *enables* autonegotiation, but * restricts it to the speed specified by the property. */ dip = ngep->devinfo; if (NGE_PROP_EXISTS(dip, transfer_speed_propname)) { speed = NGE_PROP_GET_INT(dip, transfer_speed_propname); nge_log(ngep, "%s property is %d", transfer_speed_propname, speed); switch (speed) { case 1000: ngep->param_adv_autoneg = 1; ngep->param_adv_1000fdx = 1; ngep->param_adv_1000hdx = 0; ngep->param_adv_100fdx = 0; ngep->param_adv_100hdx = 0; ngep->param_adv_10fdx = 0; ngep->param_adv_10hdx = 0; break; case 100: ngep->param_adv_autoneg = 1; ngep->param_adv_1000fdx = 0; ngep->param_adv_1000hdx = 0; ngep->param_adv_100fdx = 1; ngep->param_adv_100hdx = 1; ngep->param_adv_10fdx = 0; ngep->param_adv_10hdx = 0; break; case 10: ngep->param_adv_autoneg = 1; ngep->param_adv_1000fdx = 0; ngep->param_adv_1000hdx = 0; ngep->param_adv_100fdx = 0; ngep->param_adv_100hdx = 0; ngep->param_adv_10fdx = 1; ngep->param_adv_10hdx = 1; break; default: break; } } /* * Also check the "speed" and "full-duplex" properties. Setting * these properties will override all other settings and *disable* * autonegotiation, so both should be specified if either one is. * Otherwise, the unspecified parameter will be set to a default * value (1000Mb/s, full-duplex). */ if (NGE_PROP_EXISTS(dip, speed_propname) || NGE_PROP_EXISTS(dip, duplex_propname)) { ngep->param_adv_autoneg = 0; ngep->param_adv_1000fdx = 1; ngep->param_adv_1000hdx = 0; ngep->param_adv_100fdx = 1; ngep->param_adv_100hdx = 1; ngep->param_adv_10fdx = 1; ngep->param_adv_10hdx = 1; speed = NGE_PROP_GET_INT(dip, speed_propname); duplex = NGE_PROP_GET_INT(dip, duplex_propname); nge_log(ngep, "%s property is %d", speed_propname, speed); nge_log(ngep, "%s property is %d", duplex_propname, duplex); switch (speed) { case 1000: default: ngep->param_adv_100fdx = 0; ngep->param_adv_100hdx = 0; ngep->param_adv_10fdx = 0; ngep->param_adv_10hdx = 0; break; case 100: ngep->param_adv_1000fdx = 0; ngep->param_adv_1000hdx = 0; ngep->param_adv_10fdx = 0; ngep->param_adv_10hdx = 0; break; case 10: ngep->param_adv_1000fdx = 0; ngep->param_adv_1000hdx = 0; ngep->param_adv_100fdx = 0; ngep->param_adv_100hdx = 0; break; } switch (duplex) { default: case 1: ngep->param_adv_1000hdx = 0; ngep->param_adv_100hdx = 0; ngep->param_adv_10hdx = 0; break; case 0: ngep->param_adv_1000fdx = 0; ngep->param_adv_100fdx = 0; ngep->param_adv_10fdx = 0; break; } } nge_param_sync(ngep); return (0); }