17956Sxiuyan.wang@Sun.COM /*
27956Sxiuyan.wang@Sun.COM * CDDL HEADER START
37956Sxiuyan.wang@Sun.COM *
47956Sxiuyan.wang@Sun.COM * The contents of this file are subject to the terms of the
57956Sxiuyan.wang@Sun.COM * Common Development and Distribution License (the "License").
67956Sxiuyan.wang@Sun.COM * You may not use this file except in compliance with the License.
77956Sxiuyan.wang@Sun.COM *
87956Sxiuyan.wang@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97956Sxiuyan.wang@Sun.COM * or http://www.opensolaris.org/os/licensing.
107956Sxiuyan.wang@Sun.COM * See the License for the specific language governing permissions
117956Sxiuyan.wang@Sun.COM * and limitations under the License.
127956Sxiuyan.wang@Sun.COM *
137956Sxiuyan.wang@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147956Sxiuyan.wang@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157956Sxiuyan.wang@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167956Sxiuyan.wang@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177956Sxiuyan.wang@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187956Sxiuyan.wang@Sun.COM *
197956Sxiuyan.wang@Sun.COM * CDDL HEADER END
207956Sxiuyan.wang@Sun.COM */
218687SJing.Xiong@Sun.COM
227956Sxiuyan.wang@Sun.COM /*
237956Sxiuyan.wang@Sun.COM * Copyright 2008 NetXen, Inc. All rights reserved.
247956Sxiuyan.wang@Sun.COM * Use is subject to license terms.
257956Sxiuyan.wang@Sun.COM */
268687SJing.Xiong@Sun.COM
277956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
287956Sxiuyan.wang@Sun.COM
297956Sxiuyan.wang@Sun.COM static char transfer_speed_propname[] = "transfer-speed";
307956Sxiuyan.wang@Sun.COM static char speed_propname[] = "speed";
317956Sxiuyan.wang@Sun.COM static char duplex_propname[] = "full-duplex";
327956Sxiuyan.wang@Sun.COM
337956Sxiuyan.wang@Sun.COM /*
347956Sxiuyan.wang@Sun.COM * Notes:
357956Sxiuyan.wang@Sun.COM * The first character of the <name> field encodes the read/write
367956Sxiuyan.wang@Sun.COM * status of the parameter:
377956Sxiuyan.wang@Sun.COM * '-' => read-only,
387956Sxiuyan.wang@Sun.COM * '+' => read/write,
397956Sxiuyan.wang@Sun.COM * '!' => invisible!
407956Sxiuyan.wang@Sun.COM *
417956Sxiuyan.wang@Sun.COM * For writable parameters, we check for a driver property with the
427956Sxiuyan.wang@Sun.COM * same name; if found, and its value is in range, we initialise
437956Sxiuyan.wang@Sun.COM * the parameter from the property, overriding the default in the
447956Sxiuyan.wang@Sun.COM * table below.
457956Sxiuyan.wang@Sun.COM *
467956Sxiuyan.wang@Sun.COM * A NULL in the <name> field terminates the array.
477956Sxiuyan.wang@Sun.COM *
487956Sxiuyan.wang@Sun.COM * The <info> field is used here to provide the index of the
497956Sxiuyan.wang@Sun.COM * parameter to be initialised; thus it doesn't matter whether
507956Sxiuyan.wang@Sun.COM * this table is kept ordered or not.
517956Sxiuyan.wang@Sun.COM *
527956Sxiuyan.wang@Sun.COM * The <info> field in the per-instance copy, on the other hand,
537956Sxiuyan.wang@Sun.COM * is used to count assignments so that we can tell when a magic
547956Sxiuyan.wang@Sun.COM * parameter has been set via ndd (see unm_param_set()).
557956Sxiuyan.wang@Sun.COM */
567956Sxiuyan.wang@Sun.COM static const nd_param_t nd_template_10000[] = {
577956Sxiuyan.wang@Sun.COM /* info min max init r/w+name */
587956Sxiuyan.wang@Sun.COM
597956Sxiuyan.wang@Sun.COM /* Our hardware capabilities */
607956Sxiuyan.wang@Sun.COM { PARAM_AUTONEG_CAP, 0, 1, 1, "-autoneg_cap" },
617956Sxiuyan.wang@Sun.COM { PARAM_PAUSE_CAP, 0, 1, 1, "-pause_cap" },
627956Sxiuyan.wang@Sun.COM { PARAM_ASYM_PAUSE_CAP, 0, 1, 1, "-asym_pause_cap" },
637956Sxiuyan.wang@Sun.COM { PARAM_10000FDX_CAP, 0, 1, 1, "-10000fdx_cap" },
647956Sxiuyan.wang@Sun.COM { PARAM_1000FDX_CAP, 0, 1, 0, "-1000fdx_cap" },
657956Sxiuyan.wang@Sun.COM { PARAM_1000HDX_CAP, 0, 1, 0, "-1000hdx_cap" },
667956Sxiuyan.wang@Sun.COM { PARAM_100T4_CAP, 0, 1, 0, "-100T4_cap" },
677956Sxiuyan.wang@Sun.COM { PARAM_100FDX_CAP, 0, 1, 0, "-100fdx_cap" },
687956Sxiuyan.wang@Sun.COM { PARAM_100HDX_CAP, 0, 1, 0, "-100hdx_cap" },
697956Sxiuyan.wang@Sun.COM { PARAM_10FDX_CAP, 0, 1, 0, "-10fdx_cap" },
707956Sxiuyan.wang@Sun.COM { PARAM_10HDX_CAP, 0, 1, 0, "-10hdx_cap" },
717956Sxiuyan.wang@Sun.COM
727956Sxiuyan.wang@Sun.COM /* Our advertised capabilities */
737956Sxiuyan.wang@Sun.COM { PARAM_ADV_AUTONEG_CAP, 0, 1, 1, "-adv_autoneg_cap" },
747956Sxiuyan.wang@Sun.COM { PARAM_ADV_PAUSE_CAP, 0, 1, 1, "+adv_pause_cap" },
757956Sxiuyan.wang@Sun.COM { PARAM_ADV_ASYM_PAUSE_CAP, 0, 1, 1, "+adv_asym_pause_cap" },
767956Sxiuyan.wang@Sun.COM { PARAM_ADV_10000FDX_CAP, 0, 1, 1, "+adv_10000fdx_cap" },
777956Sxiuyan.wang@Sun.COM { PARAM_ADV_1000FDX_CAP, 0, 1, 0, "+adv_1000fdx_cap" },
787956Sxiuyan.wang@Sun.COM { PARAM_ADV_1000HDX_CAP, 0, 1, 0, "-adv_1000hdx_cap" },
797956Sxiuyan.wang@Sun.COM { PARAM_ADV_100T4_CAP, 0, 1, 0, "-adv_100T4_cap" },
807956Sxiuyan.wang@Sun.COM { PARAM_ADV_100FDX_CAP, 0, 1, 0, "+adv_100fdx_cap" },
817956Sxiuyan.wang@Sun.COM { PARAM_ADV_100HDX_CAP, 0, 1, 0, "+adv_100hdx_cap" },
827956Sxiuyan.wang@Sun.COM { PARAM_ADV_10FDX_CAP, 0, 1, 0, "+adv_10fdx_cap" },
837956Sxiuyan.wang@Sun.COM { PARAM_ADV_10HDX_CAP, 0, 1, 0, "+adv_10hdx_cap" },
847956Sxiuyan.wang@Sun.COM
857956Sxiuyan.wang@Sun.COM /* Current operating modes */
867956Sxiuyan.wang@Sun.COM { PARAM_LINK_STATUS, 0, 1, 0, "-link_status" },
877956Sxiuyan.wang@Sun.COM { PARAM_LINK_SPEED, 0, 10000, 0, "-link_speed" },
887956Sxiuyan.wang@Sun.COM { PARAM_LINK_DUPLEX, 0, 2, 0, "-link_duplex" },
897956Sxiuyan.wang@Sun.COM
907956Sxiuyan.wang@Sun.COM /* Loopback status */
917956Sxiuyan.wang@Sun.COM { PARAM_LOOP_MODE, 0, 2, 0, "-loop_mode" },
927956Sxiuyan.wang@Sun.COM
937956Sxiuyan.wang@Sun.COM /* Terminator */
947956Sxiuyan.wang@Sun.COM { PARAM_COUNT, 0, 0, 0, NULL }
957956Sxiuyan.wang@Sun.COM };
967956Sxiuyan.wang@Sun.COM
977956Sxiuyan.wang@Sun.COM static const nd_param_t nd_template_1000[] = {
987956Sxiuyan.wang@Sun.COM /* info min max init r/w+name */
997956Sxiuyan.wang@Sun.COM
1007956Sxiuyan.wang@Sun.COM /* Our hardware capabilities */
1017956Sxiuyan.wang@Sun.COM { PARAM_AUTONEG_CAP, 0, 1, 1, "-autoneg_cap" },
1027956Sxiuyan.wang@Sun.COM { PARAM_PAUSE_CAP, 0, 1, 1, "-pause_cap" },
1037956Sxiuyan.wang@Sun.COM { PARAM_ASYM_PAUSE_CAP, 0, 1, 1, "-asym_pause_cap" },
1047956Sxiuyan.wang@Sun.COM { PARAM_1000FDX_CAP, 0, 1, 1, "-1000fdx_cap" },
1057956Sxiuyan.wang@Sun.COM { PARAM_1000HDX_CAP, 0, 1, 0, "-1000hdx_cap" },
1067956Sxiuyan.wang@Sun.COM { PARAM_100T4_CAP, 0, 1, 0, "-100T4_cap" },
107*9436SJing.Xiong@Sun.COM { PARAM_100FDX_CAP, 0, 1, 0, "-100fdx_cap" },
108*9436SJing.Xiong@Sun.COM { PARAM_100HDX_CAP, 0, 1, 0, "-100hdx_cap" },
109*9436SJing.Xiong@Sun.COM { PARAM_10FDX_CAP, 0, 1, 0, "-10fdx_cap" },
110*9436SJing.Xiong@Sun.COM { PARAM_10HDX_CAP, 0, 1, 0, "-10hdx_cap" },
1117956Sxiuyan.wang@Sun.COM
1127956Sxiuyan.wang@Sun.COM /* Our advertised capabilities */
1137956Sxiuyan.wang@Sun.COM { PARAM_ADV_AUTONEG_CAP, 0, 1, 1, "-adv_autoneg_cap" },
1147956Sxiuyan.wang@Sun.COM { PARAM_ADV_PAUSE_CAP, 0, 1, 1, "+adv_pause_cap" },
1157956Sxiuyan.wang@Sun.COM { PARAM_ADV_ASYM_PAUSE_CAP, 0, 1, 1, "+adv_asym_pause_cap" },
1167956Sxiuyan.wang@Sun.COM { PARAM_ADV_1000FDX_CAP, 0, 1, 1, "+adv_1000fdx_cap" },
1177956Sxiuyan.wang@Sun.COM { PARAM_ADV_1000HDX_CAP, 0, 1, 0, "-adv_1000hdx_cap" },
1187956Sxiuyan.wang@Sun.COM { PARAM_ADV_100T4_CAP, 0, 1, 0, "-adv_100T4_cap" },
119*9436SJing.Xiong@Sun.COM { PARAM_ADV_100FDX_CAP, 0, 1, 0, "+adv_100fdx_cap" },
120*9436SJing.Xiong@Sun.COM { PARAM_ADV_100HDX_CAP, 0, 1, 0, "+adv_100hdx_cap" },
121*9436SJing.Xiong@Sun.COM { PARAM_ADV_10FDX_CAP, 0, 1, 0, "+adv_10fdx_cap" },
122*9436SJing.Xiong@Sun.COM { PARAM_ADV_10HDX_CAP, 0, 1, 0, "+adv_10hdx_cap" },
1237956Sxiuyan.wang@Sun.COM
1247956Sxiuyan.wang@Sun.COM /* Current operating modes */
1257956Sxiuyan.wang@Sun.COM { PARAM_LINK_STATUS, 0, 1, 0, "-link_status" },
1267956Sxiuyan.wang@Sun.COM { PARAM_LINK_SPEED, 0, 1000, 0, "-link_speed" },
1277956Sxiuyan.wang@Sun.COM { PARAM_LINK_DUPLEX, 0, 2, 0, "-link_duplex" },
1287956Sxiuyan.wang@Sun.COM
1297956Sxiuyan.wang@Sun.COM /* Loopback status */
1307956Sxiuyan.wang@Sun.COM { PARAM_LOOP_MODE, 0, 2, 0, "-loop_mode" },
1317956Sxiuyan.wang@Sun.COM
1327956Sxiuyan.wang@Sun.COM /* Terminator */
1337956Sxiuyan.wang@Sun.COM { PARAM_COUNT, 0, 0, 0, NULL }
1347956Sxiuyan.wang@Sun.COM };
1357956Sxiuyan.wang@Sun.COM
1367956Sxiuyan.wang@Sun.COM /* ============== NDD Support Functions =============== */
1377956Sxiuyan.wang@Sun.COM
1387956Sxiuyan.wang@Sun.COM /*
1397956Sxiuyan.wang@Sun.COM * Extracts the value from the unm parameter array and prints
1407956Sxiuyan.wang@Sun.COM * the parameter value. cp points to the required parameter.
1417956Sxiuyan.wang@Sun.COM */
1427956Sxiuyan.wang@Sun.COM /* ARGSUSED */
1437956Sxiuyan.wang@Sun.COM static int
unm_param_get(queue_t * q,mblk_t * mp,caddr_t cp,cred_t * credp)1447956Sxiuyan.wang@Sun.COM unm_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
1457956Sxiuyan.wang@Sun.COM {
1467956Sxiuyan.wang@Sun.COM nd_param_t *ndp;
1477956Sxiuyan.wang@Sun.COM
1487956Sxiuyan.wang@Sun.COM ndp = (nd_param_t *)(uintptr_t)cp;
1497956Sxiuyan.wang@Sun.COM (void) mi_mpprintf(mp, "%d", ndp->ndp_val);
1507956Sxiuyan.wang@Sun.COM
1517956Sxiuyan.wang@Sun.COM return (0);
1527956Sxiuyan.wang@Sun.COM }
1537956Sxiuyan.wang@Sun.COM
1547956Sxiuyan.wang@Sun.COM /*
1557956Sxiuyan.wang@Sun.COM * Validates the request to set a UNM parameter to a specific value.
1567956Sxiuyan.wang@Sun.COM * If the request is OK, the parameter is set. Also the <info> field
1577956Sxiuyan.wang@Sun.COM * is incremented to show that the parameter was touched, even though
1587956Sxiuyan.wang@Sun.COM * it may have been set to the same value it already had.
1597956Sxiuyan.wang@Sun.COM */
1607956Sxiuyan.wang@Sun.COM /* ARGSUSED */
1617956Sxiuyan.wang@Sun.COM static int
unm_param_set(queue_t * q,mblk_t * mp,char * value,caddr_t cp,cred_t * credp)1627956Sxiuyan.wang@Sun.COM unm_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
1637956Sxiuyan.wang@Sun.COM {
1647956Sxiuyan.wang@Sun.COM nd_param_t *ndp;
1657956Sxiuyan.wang@Sun.COM int new_value;
1667956Sxiuyan.wang@Sun.COM char *end;
1677956Sxiuyan.wang@Sun.COM
1687956Sxiuyan.wang@Sun.COM ndp = (nd_param_t *)(uintptr_t)cp;
1697956Sxiuyan.wang@Sun.COM new_value = mi_strtol(value, &end, 10);
1707956Sxiuyan.wang@Sun.COM if (end == value)
1717956Sxiuyan.wang@Sun.COM return (EINVAL);
1727956Sxiuyan.wang@Sun.COM if (new_value < ndp->ndp_min || new_value > ndp->ndp_max)
1737956Sxiuyan.wang@Sun.COM return (EINVAL);
1747956Sxiuyan.wang@Sun.COM
1757956Sxiuyan.wang@Sun.COM ndp->ndp_val = new_value;
1767956Sxiuyan.wang@Sun.COM ndp->ndp_info += 1;
1777956Sxiuyan.wang@Sun.COM return (0);
1787956Sxiuyan.wang@Sun.COM }
1797956Sxiuyan.wang@Sun.COM
1807956Sxiuyan.wang@Sun.COM /*
1817956Sxiuyan.wang@Sun.COM * Initialise the per-instance parameter array from the global prototype,
1827956Sxiuyan.wang@Sun.COM * and register each element with the named dispatch handler using nd_load()
1837956Sxiuyan.wang@Sun.COM */
1847956Sxiuyan.wang@Sun.COM static int
unm_param_register(unm_adapter * adapter)1857956Sxiuyan.wang@Sun.COM unm_param_register(unm_adapter *adapter)
1867956Sxiuyan.wang@Sun.COM {
1877956Sxiuyan.wang@Sun.COM const nd_param_t *tmplp;
1887956Sxiuyan.wang@Sun.COM dev_info_t *dip;
1897956Sxiuyan.wang@Sun.COM nd_param_t *ndp;
1907956Sxiuyan.wang@Sun.COM caddr_t *nddpp;
1917956Sxiuyan.wang@Sun.COM pfi_t setfn;
1927956Sxiuyan.wang@Sun.COM char *nm;
1937956Sxiuyan.wang@Sun.COM int pval;
1947956Sxiuyan.wang@Sun.COM
1957956Sxiuyan.wang@Sun.COM dip = adapter->dip;
1967956Sxiuyan.wang@Sun.COM nddpp = &adapter->nd_data_p;
1977956Sxiuyan.wang@Sun.COM ASSERT(*nddpp == NULL);
1987956Sxiuyan.wang@Sun.COM
1997956Sxiuyan.wang@Sun.COM if (adapter->ahw.board_type == UNM_NIC_XGBE)
2007956Sxiuyan.wang@Sun.COM tmplp = nd_template_10000;
2017956Sxiuyan.wang@Sun.COM else
2027956Sxiuyan.wang@Sun.COM tmplp = nd_template_1000;
2037956Sxiuyan.wang@Sun.COM
2047956Sxiuyan.wang@Sun.COM for (; tmplp->ndp_name != NULL; ++tmplp) {
2057956Sxiuyan.wang@Sun.COM /*
2067956Sxiuyan.wang@Sun.COM * Copy the template from nd_template[] into the
2077956Sxiuyan.wang@Sun.COM * proper slot in the per-instance parameters,
2087956Sxiuyan.wang@Sun.COM * then register the parameter with nd_load()
2097956Sxiuyan.wang@Sun.COM */
2107956Sxiuyan.wang@Sun.COM ndp = &adapter->nd_params[tmplp->ndp_info];
2117956Sxiuyan.wang@Sun.COM *ndp = *tmplp;
2127956Sxiuyan.wang@Sun.COM nm = &ndp->ndp_name[0];
2137956Sxiuyan.wang@Sun.COM setfn = unm_param_set;
2147956Sxiuyan.wang@Sun.COM
2157956Sxiuyan.wang@Sun.COM switch (*nm) {
2167956Sxiuyan.wang@Sun.COM default:
2177956Sxiuyan.wang@Sun.COM case '!':
2187956Sxiuyan.wang@Sun.COM continue;
2197956Sxiuyan.wang@Sun.COM
2207956Sxiuyan.wang@Sun.COM case '+':
2217956Sxiuyan.wang@Sun.COM break;
2227956Sxiuyan.wang@Sun.COM
2237956Sxiuyan.wang@Sun.COM case '-':
2247956Sxiuyan.wang@Sun.COM setfn = NULL;
2257956Sxiuyan.wang@Sun.COM break;
2267956Sxiuyan.wang@Sun.COM }
2277956Sxiuyan.wang@Sun.COM
2287956Sxiuyan.wang@Sun.COM if (!nd_load(nddpp, ++nm, unm_param_get, setfn, (caddr_t)ndp))
2297956Sxiuyan.wang@Sun.COM goto nd_fail;
2307956Sxiuyan.wang@Sun.COM
2317956Sxiuyan.wang@Sun.COM /*
2327956Sxiuyan.wang@Sun.COM * If the parameter is writable, and there's a property
2337956Sxiuyan.wang@Sun.COM * with the same name, and its value is in range, we use
2347956Sxiuyan.wang@Sun.COM * it to initialise the parameter. If it exists but is
2357956Sxiuyan.wang@Sun.COM * out of range, it's ignored.
2367956Sxiuyan.wang@Sun.COM */
2377956Sxiuyan.wang@Sun.COM if (setfn && UNM_PROP_EXISTS(dip, nm)) {
2387956Sxiuyan.wang@Sun.COM pval = UNM_PROP_GET_INT(dip, nm);
2397956Sxiuyan.wang@Sun.COM if (pval >= ndp->ndp_min && pval <= ndp->ndp_max)
2407956Sxiuyan.wang@Sun.COM ndp->ndp_val = pval;
2417956Sxiuyan.wang@Sun.COM }
2427956Sxiuyan.wang@Sun.COM }
2437956Sxiuyan.wang@Sun.COM
2447956Sxiuyan.wang@Sun.COM DPRINTF(1, (CE_WARN, "unm_param_register: OK"));
2457956Sxiuyan.wang@Sun.COM return (DDI_SUCCESS);
2467956Sxiuyan.wang@Sun.COM
2477956Sxiuyan.wang@Sun.COM nd_fail:
2487956Sxiuyan.wang@Sun.COM if (adapter->ahw.board_type == UNM_NIC_XGBE) {
2497956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN,
2507956Sxiuyan.wang@Sun.COM "unm_param_register: FAILED at index %d [info %d]",
2517956Sxiuyan.wang@Sun.COM (int)(tmplp-nd_template_10000), tmplp->ndp_info);
2527956Sxiuyan.wang@Sun.COM } else {
2537956Sxiuyan.wang@Sun.COM cmn_err(CE_WARN,
2547956Sxiuyan.wang@Sun.COM "unm_param_register: FAILED at index %d [info %d]",
2557956Sxiuyan.wang@Sun.COM (int)(tmplp-nd_template_1000), tmplp->ndp_info);
2567956Sxiuyan.wang@Sun.COM }
2577956Sxiuyan.wang@Sun.COM nd_free(nddpp);
2587956Sxiuyan.wang@Sun.COM return (DDI_FAILURE);
2597956Sxiuyan.wang@Sun.COM }
2607956Sxiuyan.wang@Sun.COM
2617956Sxiuyan.wang@Sun.COM int
unm_nd_init(unm_adapter * adapter)2627956Sxiuyan.wang@Sun.COM unm_nd_init(unm_adapter *adapter)
2637956Sxiuyan.wang@Sun.COM {
2647956Sxiuyan.wang@Sun.COM dev_info_t *dip;
2657956Sxiuyan.wang@Sun.COM int duplex;
2667956Sxiuyan.wang@Sun.COM int speed;
2677956Sxiuyan.wang@Sun.COM
2687956Sxiuyan.wang@Sun.COM /*
2697956Sxiuyan.wang@Sun.COM * Register all the per-instance properties, initialising
2707956Sxiuyan.wang@Sun.COM * them from the table above or from driver properties set
2717956Sxiuyan.wang@Sun.COM * in the .conf file
2727956Sxiuyan.wang@Sun.COM */
2737956Sxiuyan.wang@Sun.COM if (unm_param_register(adapter) != DDI_SUCCESS)
2747956Sxiuyan.wang@Sun.COM return (-1);
2757956Sxiuyan.wang@Sun.COM
2767956Sxiuyan.wang@Sun.COM /*
2777956Sxiuyan.wang@Sun.COM * The link speed may be forced to 1000 or 10000 Mbps using
2787956Sxiuyan.wang@Sun.COM * the property "transfer-speed". This may be done in OBP by
2797956Sxiuyan.wang@Sun.COM * using the command "apply transfer-speed=<speed> <device>".
2807956Sxiuyan.wang@Sun.COM * The speed may be 1000 or 10000 - any other value will be
2817956Sxiuyan.wang@Sun.COM * ignored. Note that this does *enables* autonegotiation, but
2827956Sxiuyan.wang@Sun.COM * restricts it to the speed specified by the property.
2837956Sxiuyan.wang@Sun.COM */
2847956Sxiuyan.wang@Sun.COM dip = adapter->dip;
2857956Sxiuyan.wang@Sun.COM if (UNM_PROP_EXISTS(dip, transfer_speed_propname)) {
2867956Sxiuyan.wang@Sun.COM
2877956Sxiuyan.wang@Sun.COM speed = UNM_PROP_GET_INT(dip, transfer_speed_propname);
2887956Sxiuyan.wang@Sun.COM
2897956Sxiuyan.wang@Sun.COM switch (speed) {
2907956Sxiuyan.wang@Sun.COM case 10000:
2917956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg = 1;
2927956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 1;
2937956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
2947956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
2957956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
2967956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
2977956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
2987956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
2997956Sxiuyan.wang@Sun.COM break;
3007956Sxiuyan.wang@Sun.COM
3017956Sxiuyan.wang@Sun.COM case 1000:
3027956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg = 1;
3037956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 1;
3047956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 1;
3057956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
3067956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3077956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
3087956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
3097956Sxiuyan.wang@Sun.COM break;
3107956Sxiuyan.wang@Sun.COM
3117956Sxiuyan.wang@Sun.COM case 100:
3127956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg = 1;
3137956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
3147956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3157956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 1;
3167956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 1;
3177956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
3187956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
3197956Sxiuyan.wang@Sun.COM break;
3207956Sxiuyan.wang@Sun.COM
3217956Sxiuyan.wang@Sun.COM case 10:
3227956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg = 1;
3237956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
3247956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3257956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
3267956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3277956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 1;
3287956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 1;
3297956Sxiuyan.wang@Sun.COM break;
3307956Sxiuyan.wang@Sun.COM
3317956Sxiuyan.wang@Sun.COM default:
3327956Sxiuyan.wang@Sun.COM break;
3337956Sxiuyan.wang@Sun.COM }
3347956Sxiuyan.wang@Sun.COM }
3357956Sxiuyan.wang@Sun.COM
3367956Sxiuyan.wang@Sun.COM /*
3377956Sxiuyan.wang@Sun.COM * Also check the "speed" and "full-duplex" properties. Setting
3387956Sxiuyan.wang@Sun.COM * these properties will override all other settings and *disable*
3397956Sxiuyan.wang@Sun.COM * autonegotiation, so both should be specified if either one is.
3407956Sxiuyan.wang@Sun.COM * Otherwise, the unspecified parameter will be set to a default
3417956Sxiuyan.wang@Sun.COM * value (10000Mb/s, full-duplex).
3427956Sxiuyan.wang@Sun.COM */
3437956Sxiuyan.wang@Sun.COM if (UNM_PROP_EXISTS(dip, speed_propname) ||
3447956Sxiuyan.wang@Sun.COM UNM_PROP_EXISTS(dip, duplex_propname)) {
3457956Sxiuyan.wang@Sun.COM
3467956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg = 0;
3477956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 1;
3487956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 1;
3497956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 1;
3507956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 1;
3517956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 1;
3527956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 1;
3537956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 1;
3547956Sxiuyan.wang@Sun.COM
3557956Sxiuyan.wang@Sun.COM speed = UNM_PROP_GET_INT(dip, speed_propname);
3567956Sxiuyan.wang@Sun.COM duplex = UNM_PROP_GET_INT(dip, duplex_propname);
3577956Sxiuyan.wang@Sun.COM
3587956Sxiuyan.wang@Sun.COM switch (speed) {
3597956Sxiuyan.wang@Sun.COM case 10000:
3607956Sxiuyan.wang@Sun.COM default:
3617956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
3627956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3637956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
3647956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3657956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
3667956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
3677956Sxiuyan.wang@Sun.COM break;
3687956Sxiuyan.wang@Sun.COM
3697956Sxiuyan.wang@Sun.COM case 1000:
3707956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 0;
3717956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
3727956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3737956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
3747956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
3757956Sxiuyan.wang@Sun.COM break;
3767956Sxiuyan.wang@Sun.COM
3777956Sxiuyan.wang@Sun.COM case 100:
3787956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 0;
3797956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
3807956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3817956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
3827956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
3837956Sxiuyan.wang@Sun.COM break;
3847956Sxiuyan.wang@Sun.COM
3857956Sxiuyan.wang@Sun.COM case 10:
3867956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 0;
3877956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
3887956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3897956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
3907956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3917956Sxiuyan.wang@Sun.COM break;
3927956Sxiuyan.wang@Sun.COM }
3937956Sxiuyan.wang@Sun.COM
3947956Sxiuyan.wang@Sun.COM switch (duplex) {
3957956Sxiuyan.wang@Sun.COM default:
3967956Sxiuyan.wang@Sun.COM case 1:
3977956Sxiuyan.wang@Sun.COM adapter->param_adv_1000hdx = 0;
3987956Sxiuyan.wang@Sun.COM adapter->param_adv_100hdx = 0;
3997956Sxiuyan.wang@Sun.COM adapter->param_adv_10hdx = 0;
4007956Sxiuyan.wang@Sun.COM break;
4017956Sxiuyan.wang@Sun.COM
4027956Sxiuyan.wang@Sun.COM case 0:
4037956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx = 0;
4047956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx = 0;
4057956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx = 0;
4067956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx = 0;
4077956Sxiuyan.wang@Sun.COM break;
4087956Sxiuyan.wang@Sun.COM }
4097956Sxiuyan.wang@Sun.COM }
4107956Sxiuyan.wang@Sun.COM
4117956Sxiuyan.wang@Sun.COM DPRINTF(1, (CE_WARN, "unm_nd_init: autoneg %d"
4127956Sxiuyan.wang@Sun.COM "pause %d asym_pause %d "
4137956Sxiuyan.wang@Sun.COM "10000fdx %d "
4147956Sxiuyan.wang@Sun.COM "1000fdx %d 1000hdx %d "
4157956Sxiuyan.wang@Sun.COM "100fdx %d 100hdx %d "
4167956Sxiuyan.wang@Sun.COM "10fdx %d 10hdx %d ",
4177956Sxiuyan.wang@Sun.COM adapter->param_adv_autoneg,
4187956Sxiuyan.wang@Sun.COM adapter->param_adv_pause, adapter->param_adv_asym_pause,
4197956Sxiuyan.wang@Sun.COM adapter->param_adv_10000fdx,
4207956Sxiuyan.wang@Sun.COM adapter->param_adv_1000fdx, adapter->param_adv_1000hdx,
4217956Sxiuyan.wang@Sun.COM adapter->param_adv_100fdx, adapter->param_adv_100hdx,
4227956Sxiuyan.wang@Sun.COM adapter->param_adv_10fdx, adapter->param_adv_10hdx));
4237956Sxiuyan.wang@Sun.COM
4247956Sxiuyan.wang@Sun.COM return (0);
4257956Sxiuyan.wang@Sun.COM }
4267956Sxiuyan.wang@Sun.COM
4277956Sxiuyan.wang@Sun.COM enum ioc_reply
unm_nd_ioctl(unm_adapter * adapter,queue_t * wq,mblk_t * mp,struct iocblk * iocp)4287956Sxiuyan.wang@Sun.COM unm_nd_ioctl(unm_adapter *adapter, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
4297956Sxiuyan.wang@Sun.COM {
4307956Sxiuyan.wang@Sun.COM boolean_t ok;
4317956Sxiuyan.wang@Sun.COM int cmd;
4327956Sxiuyan.wang@Sun.COM
4337956Sxiuyan.wang@Sun.COM DPRINTF(1, (CE_WARN, "unm_nd_ioctl($%p, $%p, $%p, $%p)",
4347956Sxiuyan.wang@Sun.COM (void *)adapter, (void *)wq, (void *)mp, (void *)iocp));
4357956Sxiuyan.wang@Sun.COM
4367956Sxiuyan.wang@Sun.COM cmd = iocp->ioc_cmd;
4377956Sxiuyan.wang@Sun.COM switch (cmd) {
4387956Sxiuyan.wang@Sun.COM default:
4397956Sxiuyan.wang@Sun.COM /* NOTREACHED */
4407956Sxiuyan.wang@Sun.COM DPRINTF(-1, (CE_WARN, "unm_nd_ioctl: invalid cmd 0x%x", cmd));
4417956Sxiuyan.wang@Sun.COM return (IOC_INVAL);
4427956Sxiuyan.wang@Sun.COM
4437956Sxiuyan.wang@Sun.COM case ND_GET:
4447956Sxiuyan.wang@Sun.COM /*
4457956Sxiuyan.wang@Sun.COM * If nd_getset() returns B_FALSE, the command was
4467956Sxiuyan.wang@Sun.COM * not valid (e.g. unknown name), so we just tell the
4477956Sxiuyan.wang@Sun.COM * top-level ioctl code to send a NAK (with code EINVAL).
4487956Sxiuyan.wang@Sun.COM *
4497956Sxiuyan.wang@Sun.COM * Otherwise, nd_getset() will have built the reply to
4507956Sxiuyan.wang@Sun.COM * be sent (but not actually sent it), so we tell the
4517956Sxiuyan.wang@Sun.COM * caller to send the prepared reply.
4527956Sxiuyan.wang@Sun.COM */
4537956Sxiuyan.wang@Sun.COM ok = nd_getset(wq, adapter->nd_data_p, mp);
4547956Sxiuyan.wang@Sun.COM DPRINTF(1, (CE_WARN, "unm_nd_ioctl: get %s", ok ? "OK" :
4557956Sxiuyan.wang@Sun.COM "FAIL"));
4567956Sxiuyan.wang@Sun.COM return (ok ? IOC_REPLY : IOC_INVAL);
4577956Sxiuyan.wang@Sun.COM
4587956Sxiuyan.wang@Sun.COM case ND_SET:
4597956Sxiuyan.wang@Sun.COM /*
4607956Sxiuyan.wang@Sun.COM * All adv_* parameters are locked (read-only) while
4617956Sxiuyan.wang@Sun.COM * the device is in any sort of loopback mode ...
4627956Sxiuyan.wang@Sun.COM */
4637956Sxiuyan.wang@Sun.COM if (adapter->param_loop_mode != UNM_LOOP_NONE) {
4647956Sxiuyan.wang@Sun.COM iocp->ioc_error = EBUSY;
4657956Sxiuyan.wang@Sun.COM return (IOC_INVAL);
4667956Sxiuyan.wang@Sun.COM }
4677956Sxiuyan.wang@Sun.COM
4687956Sxiuyan.wang@Sun.COM ok = nd_getset(wq, adapter->nd_data_p, mp);
4697956Sxiuyan.wang@Sun.COM
4707956Sxiuyan.wang@Sun.COM /*
4717956Sxiuyan.wang@Sun.COM * If nd_getset() returns B_FALSE, the command was
4727956Sxiuyan.wang@Sun.COM * not valid (e.g. unknown name), so we just tell
4737956Sxiuyan.wang@Sun.COM * the top-level ioctl code to send a NAK (with code
4747956Sxiuyan.wang@Sun.COM * EINVAL by default).
4757956Sxiuyan.wang@Sun.COM *
4767956Sxiuyan.wang@Sun.COM * Otherwise, nd_getset() will have built the reply to
4777956Sxiuyan.wang@Sun.COM * be sent - but that doesn't imply success! In some
4787956Sxiuyan.wang@Sun.COM * cases, the reply it's built will have a non-zero
4797956Sxiuyan.wang@Sun.COM * error code in it (e.g. EPERM if not superuser).
4807956Sxiuyan.wang@Sun.COM * So, we also drop out in that case ...
4817956Sxiuyan.wang@Sun.COM */
4827956Sxiuyan.wang@Sun.COM DPRINTF(1, (CE_WARN,
4837956Sxiuyan.wang@Sun.COM "unm_nd_ioctl: set %s err %d autoneg %d info %d",
4847956Sxiuyan.wang@Sun.COM ok ? "OK" : "FAIL", iocp->ioc_error,
4857956Sxiuyan.wang@Sun.COM adapter->nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val,
4867956Sxiuyan.wang@Sun.COM adapter->nd_params[PARAM_ADV_AUTONEG_CAP].ndp_info));
4877956Sxiuyan.wang@Sun.COM if (!ok)
4887956Sxiuyan.wang@Sun.COM return (IOC_INVAL);
4897956Sxiuyan.wang@Sun.COM if (iocp->ioc_error)
4907956Sxiuyan.wang@Sun.COM return (IOC_REPLY);
4917956Sxiuyan.wang@Sun.COM
4927956Sxiuyan.wang@Sun.COM return (IOC_RESTART_REPLY);
4937956Sxiuyan.wang@Sun.COM }
4947956Sxiuyan.wang@Sun.COM }
4957956Sxiuyan.wang@Sun.COM
4967956Sxiuyan.wang@Sun.COM /* Free the Named Dispatch Table by calling nd_free */
4977956Sxiuyan.wang@Sun.COM void
unm_nd_cleanup(unm_adapter * adapter)4987956Sxiuyan.wang@Sun.COM unm_nd_cleanup(unm_adapter *adapter)
4997956Sxiuyan.wang@Sun.COM {
5007956Sxiuyan.wang@Sun.COM nd_free(&adapter->nd_data_p);
5017956Sxiuyan.wang@Sun.COM }
502