xref: /onnv-gate/usr/src/uts/common/io/hxge/hxge_ndd.c (revision 7650:03f086e6b0b5)
16349Sqs148142 /*
26349Sqs148142  * CDDL HEADER START
36349Sqs148142  *
46349Sqs148142  * The contents of this file are subject to the terms of the
56349Sqs148142  * Common Development and Distribution License (the "License").
66349Sqs148142  * You may not use this file except in compliance with the License.
76349Sqs148142  *
86349Sqs148142  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96349Sqs148142  * or http://www.opensolaris.org/os/licensing.
106349Sqs148142  * See the License for the specific language governing permissions
116349Sqs148142  * and limitations under the License.
126349Sqs148142  *
136349Sqs148142  * When distributing Covered Code, include this CDDL HEADER in each
146349Sqs148142  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156349Sqs148142  * If applicable, add the following below this CDDL HEADER, with the
166349Sqs148142  * fields enclosed by brackets "[]" replaced with your own identifying
176349Sqs148142  * information: Portions Copyright [yyyy] [name of copyright owner]
186349Sqs148142  *
196349Sqs148142  * CDDL HEADER END
206349Sqs148142  */
216349Sqs148142 /*
226349Sqs148142  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236349Sqs148142  * Use is subject to license terms.
246349Sqs148142  */
256349Sqs148142 
266349Sqs148142 #include <hxge_impl.h>
276349Sqs148142 #include <inet/common.h>
286349Sqs148142 #include <inet/mi.h>
296349Sqs148142 #include <inet/nd.h>
306349Sqs148142 
316349Sqs148142 extern uint64_t hpi_debug_level;
326349Sqs148142 
336349Sqs148142 #define	HXGE_PARAM_MAC_RW \
346349Sqs148142 	HXGE_PARAM_RW | HXGE_PARAM_MAC | \
356349Sqs148142 	HXGE_PARAM_NDD_WR_OK | HXGE_PARAM_READ_PROP
366349Sqs148142 
376349Sqs148142 #define	HXGE_PARAM_RXDMA_RW	HXGE_PARAM_RWP | HXGE_PARAM_RXDMA | \
386349Sqs148142 	HXGE_PARAM_NDD_WR_OK | HXGE_PARAM_READ_PROP
396349Sqs148142 
406349Sqs148142 #define	HXGE_PARAM_L2CLASS_CFG	\
416349Sqs148142 	HXGE_PARAM_RW | HXGE_PARAM_PROP_ARR32 | \
426349Sqs148142 	HXGE_PARAM_READ_PROP | HXGE_PARAM_NDD_WR_OK
436349Sqs148142 
446349Sqs148142 #define	HXGE_PARAM_CLASS_RWS \
456349Sqs148142 	HXGE_PARAM_RWS | HXGE_PARAM_READ_PROP
466349Sqs148142 
476349Sqs148142 #define	HXGE_PARAM_ARRAY_INIT_SIZE	0x20ULL
486349Sqs148142 
496349Sqs148142 #define	BASE_ANY	0
506349Sqs148142 #define	BASE_BINARY	2
516349Sqs148142 #define	BASE_HEX	16
526349Sqs148142 #define	BASE_DECIMAL	10
536349Sqs148142 #define	ALL_FF_64	0xFFFFFFFFFFFFFFFFULL
546349Sqs148142 #define	ALL_FF_32	0xFFFFFFFFUL
556349Sqs148142 
566349Sqs148142 #define	HXGE_NDD_INFODUMP_BUFF_SIZE	2048	/* is 2k enough? */
576349Sqs148142 #define	HXGE_NDD_INFODUMP_BUFF_8K	8192
586349Sqs148142 #define	HXGE_NDD_INFODUMP_BUFF_16K	0x2000
596349Sqs148142 #define	HXGE_NDD_INFODUMP_BUFF_64K	0x8000
606349Sqs148142 
616349Sqs148142 #define	PARAM_OUTOF_RANGE(vptr, eptr, rval, pa)	\
626349Sqs148142 	((vptr == eptr) || (rval < pa->minimum) || (rval > pa->maximum))
636349Sqs148142 
646349Sqs148142 #define	ADVANCE_PRINT_BUFFER(pmp, plen, rlen) { \
656349Sqs148142 	((mblk_t *)pmp)->b_wptr += plen; \
666349Sqs148142 	rlen -= plen; \
676349Sqs148142 }
686349Sqs148142 
697584SQiyan.Sun@Sun.COM int hxge_param_rx_intr_pkts(p_hxge_t hxgep, queue_t *,
706349Sqs148142 	mblk_t *, char *, caddr_t);
717584SQiyan.Sun@Sun.COM int hxge_param_rx_intr_time(p_hxge_t hxgep, queue_t *,
726349Sqs148142 	mblk_t *, char *, caddr_t);
736349Sqs148142 static int hxge_param_set_mac(p_hxge_t, queue_t *,
746349Sqs148142 	mblk_t *, char *, caddr_t);
756349Sqs148142 static int hxge_param_set_ether_usr(p_hxge_t hxgep, queue_t *, mblk_t *,
766349Sqs148142 	char *, caddr_t);
777584SQiyan.Sun@Sun.COM int hxge_param_set_ip_opt(p_hxge_t hxgep,
786349Sqs148142 	queue_t *, mblk_t *, char *, caddr_t);
796349Sqs148142 static int hxge_param_pfc_hash_init(p_hxge_t hxgep,
806349Sqs148142 	queue_t *, mblk_t *, char *, caddr_t);
816349Sqs148142 static int hxge_param_tcam_enable(p_hxge_t hxgep, queue_t *,
826349Sqs148142 	mblk_t *, char *, caddr_t);
836349Sqs148142 static int hxge_param_get_rxdma_info(p_hxge_t hxgep, queue_t *q,
846349Sqs148142 	p_mblk_t mp, caddr_t cp);
856349Sqs148142 static int hxge_param_set_vlan_ids(p_hxge_t hxgep, queue_t *q,
866349Sqs148142 	mblk_t *mp, char *value, caddr_t cp);
876349Sqs148142 static int hxge_param_get_vlan_ids(p_hxge_t hxgep, queue_t *q,
886349Sqs148142 	p_mblk_t mp, caddr_t cp);
897584SQiyan.Sun@Sun.COM int hxge_param_get_ip_opt(p_hxge_t hxgep,
906349Sqs148142 	queue_t *, mblk_t *, caddr_t);
916349Sqs148142 static int hxge_param_get_mac(p_hxge_t hxgep, queue_t *q, p_mblk_t mp,
926349Sqs148142 	caddr_t cp);
936349Sqs148142 static int hxge_param_get_debug_flag(p_hxge_t hxgep, queue_t *q,
946349Sqs148142 	p_mblk_t mp, caddr_t cp);
956349Sqs148142 static int hxge_param_set_hxge_debug_flag(p_hxge_t hxgep,
966349Sqs148142 	queue_t *, mblk_t *, char *, caddr_t);
976349Sqs148142 static int hxge_param_set_hpi_debug_flag(p_hxge_t hxgep,
986349Sqs148142 	queue_t *, mblk_t *, char *, caddr_t);
996349Sqs148142 static int hxge_param_dump_ptrs(p_hxge_t hxgep, queue_t *q,
1006349Sqs148142 	p_mblk_t mp, caddr_t cp);
1016349Sqs148142 
1026349Sqs148142 /*
1036349Sqs148142  * Global array of Hydra changable parameters.
1046349Sqs148142  * This array is initialized to correspond to the default
1056349Sqs148142  * Hydra configuration. This array would be copied
1066349Sqs148142  * into the parameter structure and modifed per
1076349Sqs148142  * fcode and hxge.conf configuration. Later, the parameters are
1086349Sqs148142  * exported to ndd to display and run-time configuration (at least
1096349Sqs148142  * some of them).
1106349Sqs148142  */
1116349Sqs148142 
1126349Sqs148142 static hxge_param_t hxge_param_arr[] = {
1136349Sqs148142 	/* min	max	value	old	hw-name 	conf-name	*/
1146349Sqs148142 	{hxge_param_get_generic, NULL, HXGE_PARAM_READ,
1156349Sqs148142 		0, 999, 1000, 0, "instance", "instance"},
1166349Sqs148142 
1176349Sqs148142 	/* MTU cannot be propagated to the stack from here, so don't show it */
1186349Sqs148142 	{hxge_param_get_mac, hxge_param_set_mac,
1196349Sqs148142 		HXGE_PARAM_MAC_RW | HXGE_PARAM_DONT_SHOW,
1206349Sqs148142 		0, 1, 0, 0, "accept-jumbo", "accept_jumbo"},
1216349Sqs148142 
1226349Sqs148142 	{hxge_param_get_rxdma_info, NULL,
1236349Sqs148142 		HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW,
1246349Sqs148142 		HXGE_RBR_RBB_MIN, HXGE_RBR_RBB_MAX, HXGE_RBR_RBB_DEFAULT, 0,
1256349Sqs148142 		"rx-rbr-size", "rx_rbr_size"},
1266349Sqs148142 
1276349Sqs148142 	{hxge_param_get_rxdma_info, NULL,
1286349Sqs148142 		HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW,
1296349Sqs148142 		HXGE_RCR_MIN, HXGE_RCR_MAX, HXGE_RCR_DEFAULT, 0,
1306349Sqs148142 		"rx-rcr-size", "rx_rcr_size"},
1316349Sqs148142 
1326349Sqs148142 	{hxge_param_get_generic, hxge_param_rx_intr_time,
1336349Sqs148142 		HXGE_PARAM_RXDMA_RW,
1346349Sqs148142 		HXGE_RDC_RCR_TIMEOUT_MIN, HXGE_RDC_RCR_TIMEOUT_MAX,
1356349Sqs148142 		RXDMA_RCR_TO_DEFAULT, 0, "rxdma-intr-time", "rxdma_intr_time"},
1366349Sqs148142 
1376349Sqs148142 	{hxge_param_get_generic, hxge_param_rx_intr_pkts,
1386349Sqs148142 		HXGE_PARAM_RXDMA_RW,
1396349Sqs148142 		HXGE_RDC_RCR_THRESHOLD_MIN, HXGE_RDC_RCR_THRESHOLD_MAX,
1406349Sqs148142 		RXDMA_RCR_PTHRES_DEFAULT, 0,
1416349Sqs148142 		"rxdma-intr-pkts", "rxdma_intr_pkts"},
1426349Sqs148142 
1436349Sqs148142 	/* Hardware VLAN is not used currently, so don't show it */
1446349Sqs148142 	{hxge_param_get_vlan_ids, hxge_param_set_vlan_ids,
1456349Sqs148142 		HXGE_PARAM_L2CLASS_CFG | HXGE_PARAM_DONT_SHOW,
1466349Sqs148142 		VLAN_ID_MIN, VLAN_ID_MAX, 0, 0, "vlan-ids", "vlan_ids"},
1476349Sqs148142 
1486349Sqs148142 	/* Hardware VLAN is not used currently, so don't show it */
1496349Sqs148142 	{hxge_param_get_generic, hxge_param_set_generic,
1506349Sqs148142 		HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW,
1516349Sqs148142 		VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_IMPLICIT, VLAN_ID_IMPLICIT,
1526349Sqs148142 		"implicit-vlan-id", "implicit_vlan_id"},
1536349Sqs148142 
1546349Sqs148142 	{hxge_param_get_generic, hxge_param_tcam_enable,
1556349Sqs148142 		HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW,
1566349Sqs148142 		0, 0x1, 0x0, 0, "tcam-enable", "tcam_enable"},
1576349Sqs148142 
1586349Sqs148142 	{hxge_param_get_generic, hxge_param_pfc_hash_init,
1596349Sqs148142 		HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW,
1606349Sqs148142 		0, ALL_FF_32, ALL_FF_32, 0,
1616349Sqs148142 		"hash-init-value", "hash_init_value"},
1626349Sqs148142 
1636349Sqs148142 	{hxge_param_get_generic, hxge_param_set_ether_usr,
1646349Sqs148142 		HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW,
1656349Sqs148142 		0, ALL_FF_32, 0x0, 0,
1666349Sqs148142 		"class-cfg-ether-usr1", "class_cfg_ether_usr1"},
1676349Sqs148142 
1686349Sqs148142 	{hxge_param_get_generic, hxge_param_set_ether_usr,
1696349Sqs148142 		HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW,
1706349Sqs148142 		0, ALL_FF_32, 0x0, 0,
1716349Sqs148142 		"class-cfg-ether-usr2", "class_cfg_ether_usr2"},
1726349Sqs148142 
1736349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1746349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1756349Sqs148142 		"class-opt-ipv4-tcp", "class_opt_ipv4_tcp"},
1766349Sqs148142 
1776349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1786349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1796349Sqs148142 		"class-opt-ipv4-udp", "class_opt_ipv4_udp"},
1806349Sqs148142 
1816349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1826349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1836349Sqs148142 		"class-opt-ipv4-ah", "class_opt_ipv4_ah"},
1846349Sqs148142 
1856349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1866349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1876349Sqs148142 		"class-opt-ipv4-sctp", "class_opt_ipv4_sctp"},
1886349Sqs148142 
1896349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1906349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1916349Sqs148142 		"class-opt-ipv6-tcp", "class_opt_ipv6_tcp"},
1926349Sqs148142 
1936349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1946349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1956349Sqs148142 		"class-opt-ipv6-udp", "class_opt_ipv6_udp"},
1966349Sqs148142 
1976349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
1986349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
1996349Sqs148142 		"class-opt-ipv6-ah", "class_opt_ipv6_ah"},
2006349Sqs148142 
2016349Sqs148142 	{hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS,
2026349Sqs148142 		0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
2036349Sqs148142 		"class-opt-ipv6-sctp", "class_opt_ipv6_sctp"},
2046349Sqs148142 
2056349Sqs148142 	{hxge_param_get_debug_flag, hxge_param_set_hxge_debug_flag,
2066349Sqs148142 		HXGE_PARAM_RW | HXGE_PARAM_DONT_SHOW,
2076349Sqs148142 		0ULL, ALL_FF_64, 0ULL, 0ULL,
2086349Sqs148142 		"hxge-debug-flag", "hxge_debug_flag"},
2096349Sqs148142 
2106349Sqs148142 	{hxge_param_get_debug_flag, hxge_param_set_hpi_debug_flag,
2116349Sqs148142 		HXGE_PARAM_RW | HXGE_PARAM_DONT_SHOW,
2126349Sqs148142 		0ULL, ALL_FF_64, 0ULL, 0ULL,
2136349Sqs148142 		"hpi-debug-flag", "hpi_debug_flag"},
2146349Sqs148142 
2156349Sqs148142 	{hxge_param_dump_ptrs, NULL, HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW,
2166349Sqs148142 		0, 0x0fffffff, 0x0fffffff, 0, "dump-ptrs", "dump_ptrs"},
2176349Sqs148142 
2186349Sqs148142 	{NULL, NULL, HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW,
2196349Sqs148142 		0, 0x0fffffff, 0x0fffffff, 0, "end", "end"},
2206349Sqs148142 };
2216349Sqs148142 
2226349Sqs148142 extern void *hxge_list;
2236349Sqs148142 
2246349Sqs148142 /*
2256349Sqs148142  * Update the NDD array from the soft properties.
2266349Sqs148142  */
2276349Sqs148142 void
hxge_get_param_soft_properties(p_hxge_t hxgep)2286349Sqs148142 hxge_get_param_soft_properties(p_hxge_t hxgep)
2296349Sqs148142 {
2306349Sqs148142 	p_hxge_param_t	param_arr;
2316349Sqs148142 	uint_t		prop_len;
2326349Sqs148142 	int		i, j;
2336349Sqs148142 	uint32_t	param_count;
2346349Sqs148142 	uint32_t	*int_prop_val;
2356349Sqs148142 
2366349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, " ==> hxge_get_param_soft_properties"));
2376349Sqs148142 
2386349Sqs148142 	param_arr = hxgep->param_arr;
2396349Sqs148142 	param_count = hxgep->param_count;
2406349Sqs148142 	for (i = 0; i < param_count; i++) {
2416349Sqs148142 
2426349Sqs148142 		if ((param_arr[i].type & HXGE_PARAM_READ_PROP) == 0)
2436349Sqs148142 			continue;
2446349Sqs148142 
2456349Sqs148142 		if ((param_arr[i].type & HXGE_PARAM_PROP_STR))
2466349Sqs148142 			continue;
2476349Sqs148142 
2486349Sqs148142 		if ((param_arr[i].type & HXGE_PARAM_PROP_ARR32) ||
2496349Sqs148142 		    (param_arr[i].type & HXGE_PARAM_PROP_ARR64)) {
2506349Sqs148142 
2516349Sqs148142 			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
2526349Sqs148142 			    hxgep->dip, 0, param_arr[i].fcode_name,
2536349Sqs148142 			    (int **)&int_prop_val, (uint_t *)&prop_len) ==
2546349Sqs148142 			    DDI_PROP_SUCCESS) {
2556349Sqs148142 				uint64_t *cfg_value;
2566349Sqs148142 				uint64_t prop_count;
2576349Sqs148142 
2586349Sqs148142 				if (prop_len > HXGE_PARAM_ARRAY_INIT_SIZE)
2596349Sqs148142 					prop_len = HXGE_PARAM_ARRAY_INIT_SIZE;
2606349Sqs148142 #if defined(__i386)
2616349Sqs148142 				cfg_value =
2626349Sqs148142 				    (uint64_t *)(int32_t)param_arr[i].value;
2636349Sqs148142 #else
2646349Sqs148142 				cfg_value = (uint64_t *)param_arr[i].value;
2656349Sqs148142 #endif
2666349Sqs148142 				for (j = 0; j < prop_len; j++) {
2676349Sqs148142 					cfg_value[j] = int_prop_val[j];
2686349Sqs148142 				}
2696349Sqs148142 				prop_count = prop_len;
2706349Sqs148142 				param_arr[i].type |=
2716349Sqs148142 				    (prop_count << HXGE_PARAM_ARRAY_CNT_SHIFT);
2726349Sqs148142 
2736349Sqs148142 				ddi_prop_free(int_prop_val);
2746349Sqs148142 			}
2756349Sqs148142 			continue;
2766349Sqs148142 		}
2776349Sqs148142 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0,
2786349Sqs148142 		    param_arr[i].fcode_name, (int **)&int_prop_val,
2796349Sqs148142 		    &prop_len) == DDI_PROP_SUCCESS) {
2806349Sqs148142 			if ((*int_prop_val >= param_arr[i].minimum) &&
2816349Sqs148142 			    (*int_prop_val <= param_arr[i].maximum))
2826349Sqs148142 				param_arr[i].value = *int_prop_val;
2836349Sqs148142 			ddi_prop_free(int_prop_val);
2846349Sqs148142 		}
2856349Sqs148142 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0,
2866349Sqs148142 		    param_arr[i].name, (int **)&int_prop_val, &prop_len) ==
2876349Sqs148142 		    DDI_PROP_SUCCESS) {
2886349Sqs148142 			if ((*int_prop_val >= param_arr[i].minimum) &&
2896349Sqs148142 			    (*int_prop_val <= param_arr[i].maximum))
2906349Sqs148142 				param_arr[i].value = *int_prop_val;
2916349Sqs148142 			ddi_prop_free(int_prop_val);
2926349Sqs148142 		}
2936349Sqs148142 	}
2946349Sqs148142 }
2956349Sqs148142 
2966349Sqs148142 static int
hxge_private_param_register(p_hxge_t hxgep,p_hxge_param_t param_arr)2976349Sqs148142 hxge_private_param_register(p_hxge_t hxgep, p_hxge_param_t param_arr)
2986349Sqs148142 {
2996349Sqs148142 	int		status = B_TRUE;
3006349Sqs148142 	int		channel;
3016349Sqs148142 	char		*prop_name;
3026349Sqs148142 	char		*end;
3036349Sqs148142 	uint32_t	name_chars;
3046349Sqs148142 
3056349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD2_CTL, " hxge_private_param_register %s",
3066349Sqs148142 	    param_arr->name));
3076349Sqs148142 
3086349Sqs148142 	if ((param_arr->type & HXGE_PARAM_PRIV) != HXGE_PARAM_PRIV)
3096349Sqs148142 		return (B_TRUE);
3106349Sqs148142 	prop_name = param_arr->name;
3116349Sqs148142 	if (param_arr->type & HXGE_PARAM_RXDMA) {
3126349Sqs148142 		if (strncmp("rxdma_intr", prop_name, 10) == 0)
3136349Sqs148142 			return (B_TRUE);
3146349Sqs148142 		else
3156349Sqs148142 			return (B_FALSE);
3166349Sqs148142 	}
3176349Sqs148142 
3186349Sqs148142 	if (param_arr->type & HXGE_PARAM_TXDMA) {
3196349Sqs148142 		name_chars = strlen("txdma");
3206349Sqs148142 		if (strncmp("txdma", prop_name, name_chars) == 0) {
3216349Sqs148142 			prop_name += name_chars;
3226349Sqs148142 			channel = mi_strtol(prop_name, &end, 10);
3236349Sqs148142 			/* now check if this rdc is in config */
3246349Sqs148142 			HXGE_DEBUG_MSG((hxgep, NDD2_CTL,
3256349Sqs148142 			    " hxge_private_param_register: %d", channel));
3266349Sqs148142 			return (hxge_check_txdma_port_member(hxgep, channel));
3276349Sqs148142 		}
3286349Sqs148142 		return (B_FALSE);
3296349Sqs148142 	}
3306349Sqs148142 
3316349Sqs148142 	status = B_FALSE;
3326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD2_CTL, "<== hxge_private_param_register"));
3336349Sqs148142 
3346349Sqs148142 	return (status);
3356349Sqs148142 }
3366349Sqs148142 
3376349Sqs148142 void
hxge_setup_param(p_hxge_t hxgep)3386349Sqs148142 hxge_setup_param(p_hxge_t hxgep)
3396349Sqs148142 {
3406349Sqs148142 	p_hxge_param_t	param_arr;
3416349Sqs148142 	int		i;
3426349Sqs148142 	pfi_t		set_pfi;
3436349Sqs148142 
3446349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_setup_param"));
3456349Sqs148142 	/*
3466349Sqs148142 	 * Make sure the param_instance is set to a valid device instance.
3476349Sqs148142 	 */
3486349Sqs148142 	if (hxge_param_arr[param_instance].value == 1000)
3496349Sqs148142 		hxge_param_arr[param_instance].value = hxgep->instance;
3506349Sqs148142 
3516349Sqs148142 	param_arr = hxgep->param_arr;
3526349Sqs148142 	param_arr[param_instance].value = hxgep->instance;
3536349Sqs148142 
3546349Sqs148142 	for (i = 0; i < hxgep->param_count; i++) {
3556349Sqs148142 		if ((param_arr[i].type & HXGE_PARAM_PRIV) &&
3566349Sqs148142 		    (hxge_private_param_register(hxgep, &param_arr[i]) ==
3576349Sqs148142 		    B_FALSE)) {
3586349Sqs148142 			param_arr[i].setf = NULL;
3596349Sqs148142 			param_arr[i].getf = NULL;
3606349Sqs148142 		}
3616349Sqs148142 		if (param_arr[i].type & HXGE_PARAM_CMPLX)
3626349Sqs148142 			param_arr[i].setf = NULL;
3636349Sqs148142 
3646349Sqs148142 		if (param_arr[i].type & HXGE_PARAM_DONT_SHOW) {
3656349Sqs148142 			param_arr[i].setf = NULL;
3666349Sqs148142 			param_arr[i].getf = NULL;
3676349Sqs148142 		}
3686349Sqs148142 		set_pfi = (pfi_t)param_arr[i].setf;
3696349Sqs148142 
3706349Sqs148142 		if ((set_pfi) && (param_arr[i].type & HXGE_PARAM_INIT_ONLY)) {
3716349Sqs148142 			set_pfi = NULL;
3726349Sqs148142 		}
3736349Sqs148142 		if (!hxge_nd_load(&hxgep->param_list, param_arr[i].name,
3746349Sqs148142 		    (pfi_t)param_arr[i].getf, set_pfi,
3756349Sqs148142 		    (caddr_t)&param_arr[i])) {
3766349Sqs148142 			(void) hxge_nd_free(&hxgep->param_list);
3776349Sqs148142 			break;
3786349Sqs148142 		}
3796349Sqs148142 	}
3806349Sqs148142 
3816349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_setup_param"));
3826349Sqs148142 }
3836349Sqs148142 
3846349Sqs148142 /*
3856349Sqs148142  * Called from the attached function, it allocates memory for
3866349Sqs148142  * the parameter array and some members.
3876349Sqs148142  */
3886349Sqs148142 void
hxge_init_param(p_hxge_t hxgep)3896349Sqs148142 hxge_init_param(p_hxge_t hxgep)
3906349Sqs148142 {
3916349Sqs148142 	p_hxge_param_t	param_arr;
3926349Sqs148142 	int		i, alloc_size;
3936349Sqs148142 	uint64_t	alloc_count;
3946349Sqs148142 
3956349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_init_param"));
3966349Sqs148142 	/*
3976349Sqs148142 	 * Make sure the param_instance is set to a valid device instance.
3986349Sqs148142 	 */
3996349Sqs148142 	if (hxge_param_arr[param_instance].value == 1000)
4006349Sqs148142 		hxge_param_arr[param_instance].value = hxgep->instance;
4016349Sqs148142 
4026349Sqs148142 	param_arr = hxgep->param_arr;
4036349Sqs148142 	if (param_arr == NULL) {
4046349Sqs148142 		param_arr = (p_hxge_param_t)KMEM_ZALLOC(
4056349Sqs148142 		    sizeof (hxge_param_arr), KM_SLEEP);
4066349Sqs148142 	}
4076349Sqs148142 	for (i = 0; i < sizeof (hxge_param_arr) / sizeof (hxge_param_t); i++) {
4086349Sqs148142 		param_arr[i] = hxge_param_arr[i];
4096349Sqs148142 		if ((param_arr[i].type & HXGE_PARAM_PROP_ARR32) ||
4106349Sqs148142 		    (param_arr[i].type & HXGE_PARAM_PROP_ARR64)) {
4116349Sqs148142 			alloc_count = HXGE_PARAM_ARRAY_INIT_SIZE;
4126349Sqs148142 			alloc_size = alloc_count * sizeof (uint64_t);
4136349Sqs148142 #if defined(__i386)
4146349Sqs148142 			param_arr[i].value =
4156349Sqs148142 			    (uint64_t)(uint32_t)KMEM_ZALLOC(alloc_size,
4166349Sqs148142 			    KM_SLEEP);
4176349Sqs148142 			param_arr[i].old_value =
4186349Sqs148142 			    (uint64_t)(uint32_t)KMEM_ZALLOC(alloc_size,
4196349Sqs148142 			    KM_SLEEP);
4206349Sqs148142 #else
4216349Sqs148142 			param_arr[i].value =
4226349Sqs148142 			    (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP);
4236349Sqs148142 			param_arr[i].old_value =
4246349Sqs148142 			    (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP);
4256349Sqs148142 #endif
4266349Sqs148142 			param_arr[i].type |=
4276349Sqs148142 			    (alloc_count << HXGE_PARAM_ARRAY_ALLOC_SHIFT);
4286349Sqs148142 		}
4296349Sqs148142 	}
4306349Sqs148142 
4316349Sqs148142 	hxgep->param_arr = param_arr;
4326349Sqs148142 	hxgep->param_count = sizeof (hxge_param_arr) / sizeof (hxge_param_t);
4336349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init_param: count %d",
4346349Sqs148142 	    hxgep->param_count));
4356349Sqs148142 }
4366349Sqs148142 
4376349Sqs148142 /*
4386349Sqs148142  * Called from the attached functions, it frees memory for the parameter array
4396349Sqs148142  */
4406349Sqs148142 void
hxge_destroy_param(p_hxge_t hxgep)4416349Sqs148142 hxge_destroy_param(p_hxge_t hxgep)
4426349Sqs148142 {
4436349Sqs148142 	int		i;
4446349Sqs148142 	uint64_t	free_size, free_count;
4456349Sqs148142 
4466349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_param"));
4476349Sqs148142 	/*
4486349Sqs148142 	 * Make sure the param_instance is set to a valid device instance.
4496349Sqs148142 	 */
4506349Sqs148142 	if (hxge_param_arr[param_instance].value == hxgep->instance) {
4516349Sqs148142 		for (i = 0; i <= hxge_param_arr[param_instance].maximum; i++) {
4526349Sqs148142 			if ((ddi_get_soft_state(hxge_list, i) != NULL) &&
4536349Sqs148142 			    (i != hxgep->instance))
4546349Sqs148142 				break;
4556349Sqs148142 		}
4566349Sqs148142 		hxge_param_arr[param_instance].value = i;
4576349Sqs148142 	}
4586349Sqs148142 	if (hxgep->param_list)
4596349Sqs148142 		hxge_nd_free(&hxgep->param_list);
4606349Sqs148142 	for (i = 0; i < hxgep->param_count; i++) {
4616349Sqs148142 		if ((hxgep->param_arr[i].type & HXGE_PARAM_PROP_ARR32) ||
4626349Sqs148142 		    (hxgep->param_arr[i].type & HXGE_PARAM_PROP_ARR64)) {
4636349Sqs148142 			free_count = ((hxgep->param_arr[i].type &
4646349Sqs148142 			    HXGE_PARAM_ARRAY_ALLOC_MASK) >>
4656349Sqs148142 			    HXGE_PARAM_ARRAY_ALLOC_SHIFT);
4666349Sqs148142 			free_count = HXGE_PARAM_ARRAY_INIT_SIZE;
4676349Sqs148142 			free_size = sizeof (uint64_t) * free_count;
4686349Sqs148142 #if defined(__i386)
4696349Sqs148142 			KMEM_FREE((void *)(uint32_t)
4706349Sqs148142 			    hxgep->param_arr[i].value, free_size);
4716349Sqs148142 			KMEM_FREE((void *)(uint32_t)
4726349Sqs148142 			    hxgep->param_arr[i].old_value, free_size);
4736349Sqs148142 #else
4746349Sqs148142 			KMEM_FREE((void *) hxgep->param_arr[i].value,
4756349Sqs148142 			    free_size);
4766349Sqs148142 			KMEM_FREE((void *) hxgep->param_arr[i].old_value,
4776349Sqs148142 			    free_size);
4786349Sqs148142 #endif
4796349Sqs148142 		}
4806349Sqs148142 	}
4816349Sqs148142 
4826349Sqs148142 	KMEM_FREE(hxgep->param_arr, sizeof (hxge_param_arr));
4836349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_param"));
4846349Sqs148142 }
4856349Sqs148142 
4866349Sqs148142 /*
4876349Sqs148142  * Extracts the value from the 'hxge' parameter array and prints the
4886349Sqs148142  * parameter value. cp points to the required parameter.
4896349Sqs148142  */
4906349Sqs148142 /* ARGSUSED */
4916349Sqs148142 int
hxge_param_get_generic(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)4926349Sqs148142 hxge_param_get_generic(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
4936349Sqs148142 {
4946349Sqs148142 	p_hxge_param_t pa = (p_hxge_param_t)cp;
4956349Sqs148142 
4966349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, " ==> hxge_param_get_generic name %s ",
4976349Sqs148142 	    pa->name));
4986349Sqs148142 
4996349Sqs148142 	if (pa->value > 0xffffffff)
5006349Sqs148142 		(void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32),
5016349Sqs148142 		    (int)(pa->value & 0xffffffff));
5026349Sqs148142 	else
5036349Sqs148142 		(void) mi_mpprintf(mp, "%x", (int)pa->value);
5046349Sqs148142 
5056349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_generic"));
5066349Sqs148142 	return (0);
5076349Sqs148142 }
5086349Sqs148142 
5096349Sqs148142 /* ARGSUSED */
5106349Sqs148142 static int
hxge_param_get_mac(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)5116349Sqs148142 hxge_param_get_mac(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
5126349Sqs148142 {
5136349Sqs148142 	p_hxge_param_t pa = (p_hxge_param_t)cp;
5146349Sqs148142 
5156349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_mac"));
5166349Sqs148142 
5176349Sqs148142 	(void) mi_mpprintf(mp, "%d", (uint32_t)pa->value);
5186349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_mac"));
5196349Sqs148142 	return (0);
5206349Sqs148142 }
5216349Sqs148142 
5226349Sqs148142 /* ARGSUSED */
5236349Sqs148142 int
hxge_param_get_rxdma_info(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)5246349Sqs148142 hxge_param_get_rxdma_info(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
5256349Sqs148142 {
5266349Sqs148142 	uint_t			print_len, buf_len;
5276349Sqs148142 	p_mblk_t		np;
5286349Sqs148142 	int			rdc;
5296349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
5306349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
5316349Sqs148142 	int			buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_SIZE;
5326349Sqs148142 
5336349Sqs148142 	p_rx_rcr_rings_t rx_rcr_rings;
5346349Sqs148142 	p_rx_rcr_ring_t *rcr_rings;
5356349Sqs148142 	p_rx_rbr_rings_t rx_rbr_rings;
5366349Sqs148142 	p_rx_rbr_ring_t *rbr_rings;
5376349Sqs148142 
5386349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_rxdma_info"));
5396349Sqs148142 
5406349Sqs148142 	(void) mi_mpprintf(mp, "RXDMA Information\n");
5416349Sqs148142 
5426349Sqs148142 	if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
5436349Sqs148142 		/* The following may work even if we cannot get a large buf. */
5446349Sqs148142 		(void) mi_mpprintf(mp, "%s\n", "out of buffer");
5456349Sqs148142 		return (0);
5466349Sqs148142 	}
5476349Sqs148142 	buf_len = buff_alloc_size;
5486349Sqs148142 
5496349Sqs148142 	mp->b_cont = np;
5506349Sqs148142 
5516349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
5526349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
5536349Sqs148142 
5546349Sqs148142 	rx_rcr_rings = hxgep->rx_rcr_rings;
5556349Sqs148142 	rcr_rings = rx_rcr_rings->rcr_rings;
5566349Sqs148142 	rx_rbr_rings = hxgep->rx_rbr_rings;
5576349Sqs148142 	rbr_rings = rx_rbr_rings->rbr_rings;
5586349Sqs148142 
5596349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
5606349Sqs148142 	    "Total RDCs\t %d\n", p_cfgp->max_rdcs);
5616349Sqs148142 	((mblk_t *)np)->b_wptr += print_len;
5626349Sqs148142 	buf_len -= print_len;
5636349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
5646349Sqs148142 	    "RDC\t HW RDC\t Timeout\t Packets RBR ptr \t"
5656349Sqs148142 	    "chunks\t RCR ptr\n");
5666349Sqs148142 	((mblk_t *)np)->b_wptr += print_len;
5676349Sqs148142 	buf_len -= print_len;
5686349Sqs148142 	for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) {
5696349Sqs148142 		print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
5706349Sqs148142 		    " %d\t  %d\t $%p\t 0x%x\t $%p\n",
571*7650SMichael.Speer@Sun.COM 		    rdc, hxgep->rdc[rdc], (void *)rbr_rings[rdc],
572*7650SMichael.Speer@Sun.COM 		    rbr_rings[rdc]->num_blocks, (void *)rcr_rings[rdc]);
5736349Sqs148142 		((mblk_t *)np)->b_wptr += print_len;
5746349Sqs148142 		buf_len -= print_len;
5756349Sqs148142 	}
5766349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_rxdma_info"));
5776349Sqs148142 	return (0);
5786349Sqs148142 }
5796349Sqs148142 
5806349Sqs148142 int
hxge_mk_mblk_tail_space(p_mblk_t mp,p_mblk_t * nmp,size_t size)5816349Sqs148142 hxge_mk_mblk_tail_space(p_mblk_t mp, p_mblk_t *nmp, size_t size)
5826349Sqs148142 {
5836349Sqs148142 	p_mblk_t tmp;
5846349Sqs148142 
5856349Sqs148142 	tmp = mp;
5866349Sqs148142 	while (tmp->b_cont)
5876349Sqs148142 		tmp = tmp->b_cont;
5886349Sqs148142 	if ((tmp->b_wptr + size) >= tmp->b_datap->db_lim) {
5896349Sqs148142 		tmp->b_cont = allocb(1024, BPRI_HI);
5906349Sqs148142 		tmp = tmp->b_cont;
5916349Sqs148142 		if (!tmp)
5926349Sqs148142 			return (ENOMEM);
5936349Sqs148142 	}
5946349Sqs148142 	*nmp = tmp;
5956349Sqs148142 	return (0);
5966349Sqs148142 }
5976349Sqs148142 
5986349Sqs148142 /*
5996349Sqs148142  * Sets the ge parameter to the value in the hxge_param_register using
6006349Sqs148142  * hxge_nd_load().
6016349Sqs148142  */
6026349Sqs148142 /* ARGSUSED */
6036349Sqs148142 int
hxge_param_set_generic(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)6046349Sqs148142 hxge_param_set_generic(p_hxge_t hxgep, queue_t *q, mblk_t *mp,
6056349Sqs148142 	char *value, caddr_t cp)
6066349Sqs148142 {
6076349Sqs148142 	char		*end;
6086349Sqs148142 	uint32_t	new_value;
6096349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
6106349Sqs148142 
6116349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, " ==> hxge_param_set_generic"));
6126349Sqs148142 	new_value = (uint32_t)mi_strtol(value, &end, 10);
6136349Sqs148142 	if (end == value || new_value < pa->minimum ||
6146349Sqs148142 	    new_value > pa->maximum) {
6156349Sqs148142 		return (EINVAL);
6166349Sqs148142 	}
6176349Sqs148142 	pa->value = new_value;
6186349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, " <== hxge_param_set_generic"));
6196349Sqs148142 	return (0);
6206349Sqs148142 }
6216349Sqs148142 
6226349Sqs148142 /* ARGSUSED */
6236349Sqs148142 int
hxge_param_set_mac(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)6246349Sqs148142 hxge_param_set_mac(p_hxge_t hxgep, queue_t *q, mblk_t *mp,
6256349Sqs148142 	char *value, caddr_t cp)
6266349Sqs148142 {
6276349Sqs148142 	char		*end;
6286349Sqs148142 	uint32_t	new_value;
6296349Sqs148142 	int		status = 0;
6306349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
6316349Sqs148142 
6326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_mac"));
6336349Sqs148142 	new_value = (uint32_t)mi_strtol(value, &end, BASE_DECIMAL);
6346349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, new_value, pa)) {
6356349Sqs148142 		return (EINVAL);
6366349Sqs148142 	}
6376349Sqs148142 
6386349Sqs148142 	if (pa->value != new_value) {
6396349Sqs148142 		pa->old_value = pa->value;
6406349Sqs148142 		pa->value = new_value;
6416349Sqs148142 	}
6426349Sqs148142 
6436349Sqs148142 	if (pa->value != pa->old_value) {
6446349Sqs148142 		RW_ENTER_WRITER(&hxgep->filter_lock);
6456349Sqs148142 		(void) hxge_rx_vmac_disable(hxgep);
6466349Sqs148142 		(void) hxge_tx_vmac_disable(hxgep);
6476349Sqs148142 
6486349Sqs148142 		/*
6496349Sqs148142 		 * Apply the new jumbo parameter here.
6506349Sqs148142 		 * The order of the following two calls is important.
6516349Sqs148142 		 */
6526349Sqs148142 		(void) hxge_tx_vmac_enable(hxgep);
6536349Sqs148142 		(void) hxge_rx_vmac_enable(hxgep);
6546349Sqs148142 		RW_EXIT(&hxgep->filter_lock);
6556349Sqs148142 	}
6566349Sqs148142 
6576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_mac"));
6586349Sqs148142 	return (status);
6596349Sqs148142 }
6606349Sqs148142 
6616349Sqs148142 /* ARGSUSED */
6627584SQiyan.Sun@Sun.COM int
hxge_param_rx_intr_pkts(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)6636349Sqs148142 hxge_param_rx_intr_pkts(p_hxge_t hxgep, queue_t *q,
6646349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
6656349Sqs148142 {
6666349Sqs148142 	char		*end;
6676349Sqs148142 	uint32_t	cfg_value;
6686349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
6696349Sqs148142 
6706349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_rx_intr_pkts"));
6716349Sqs148142 
6727584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
6737584SQiyan.Sun@Sun.COM 		value += 2;
6747584SQiyan.Sun@Sun.COM 
6757584SQiyan.Sun@Sun.COM 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
6766349Sqs148142 
6776349Sqs148142 	if ((cfg_value > HXGE_RDC_RCR_THRESHOLD_MAX) ||
6786349Sqs148142 	    (cfg_value < HXGE_RDC_RCR_THRESHOLD_MIN)) {
6796349Sqs148142 		return (EINVAL);
6806349Sqs148142 	}
6816349Sqs148142 
6826349Sqs148142 	if ((pa->value != cfg_value)) {
6836349Sqs148142 		pa->old_value = pa->value;
6846349Sqs148142 		pa->value = cfg_value;
6856349Sqs148142 		hxgep->intr_threshold = pa->value;
6866349Sqs148142 	}
6876349Sqs148142 
6886349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_rx_intr_pkts"));
6896349Sqs148142 	return (0);
6906349Sqs148142 }
6916349Sqs148142 
6926349Sqs148142 /* ARGSUSED */
6937584SQiyan.Sun@Sun.COM int
hxge_param_rx_intr_time(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)6946349Sqs148142 hxge_param_rx_intr_time(p_hxge_t hxgep, queue_t *q,
6956349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
6966349Sqs148142 {
6976349Sqs148142 	char		*end;
6986349Sqs148142 	uint32_t	cfg_value;
6996349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
7006349Sqs148142 
7016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_rx_intr_time"));
7026349Sqs148142 
7037584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
7047584SQiyan.Sun@Sun.COM 		value += 2;
7057584SQiyan.Sun@Sun.COM 
7067584SQiyan.Sun@Sun.COM 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
7076349Sqs148142 
7086349Sqs148142 	if ((cfg_value > HXGE_RDC_RCR_TIMEOUT_MAX) ||
7096349Sqs148142 	    (cfg_value < HXGE_RDC_RCR_TIMEOUT_MIN)) {
7106349Sqs148142 		return (EINVAL);
7116349Sqs148142 	}
7126349Sqs148142 
7136349Sqs148142 	if ((pa->value != cfg_value)) {
7146349Sqs148142 		pa->old_value = pa->value;
7156349Sqs148142 		pa->value = cfg_value;
7166349Sqs148142 		hxgep->intr_timeout = pa->value;
7176349Sqs148142 	}
7186349Sqs148142 
7196349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_rx_intr_time"));
7206349Sqs148142 	return (0);
7216349Sqs148142 }
7226349Sqs148142 
7236349Sqs148142 /* ARGSUSED */
7246349Sqs148142 static int
hxge_param_set_vlan_ids(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)7256349Sqs148142 hxge_param_set_vlan_ids(p_hxge_t hxgep, queue_t *q, mblk_t *mp, char *value,
7266349Sqs148142     caddr_t cp)
7276349Sqs148142 {
7286349Sqs148142 	char			*end;
7296349Sqs148142 	uint32_t		status = 0, cfg_value;
7306349Sqs148142 	p_hxge_param_t		pa = (p_hxge_param_t)cp;
7316349Sqs148142 	uint32_t		cfg_it = B_FALSE;
7326349Sqs148142 	uint32_t		*val_ptr, *old_val_ptr;
7336349Sqs148142 	hxge_param_map_t	*vmap, *old_map;
7346349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
7356349Sqs148142 	uint64_t		cfgd_vlans;
7366349Sqs148142 	int			i, inc = 0, cfg_position;
7376349Sqs148142 	hxge_mv_cfg_t		*vlan_tbl;
7386349Sqs148142 	hpi_handle_t		handle;
7396349Sqs148142 
7406349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_vlan_ids "));
7416349Sqs148142 
7426349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
7436349Sqs148142 	vlan_tbl = (hxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
7446349Sqs148142 	handle = hxgep->hpi_reg_handle;
7456349Sqs148142 
7467584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
7477584SQiyan.Sun@Sun.COM 		value += 2;
7487584SQiyan.Sun@Sun.COM 
7496349Sqs148142 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
7506349Sqs148142 
7516349Sqs148142 	/* now do decoding */
7526349Sqs148142 	cfgd_vlans = ((pa->type & HXGE_PARAM_ARRAY_CNT_MASK) >>
7536349Sqs148142 	    HXGE_PARAM_ARRAY_CNT_SHIFT);
7546349Sqs148142 
7556349Sqs148142 	if (cfgd_vlans >= HXGE_PARAM_ARRAY_INIT_SIZE) {
7566349Sqs148142 		/*
7576349Sqs148142 		 * for now, we process only upto HXGE_PARAM_ARRAY_INIT_SIZE
7586349Sqs148142 		 * parameters In the future, we may want to expand
7596349Sqs148142 		 * the storage array and continue
7606349Sqs148142 		 */
7616349Sqs148142 		return (EINVAL);
7626349Sqs148142 	}
7636349Sqs148142 
7646349Sqs148142 	vmap = (hxge_param_map_t *)&cfg_value;
7656349Sqs148142 	if ((vmap->param_id == 0) || (vmap->param_id > VLAN_ID_MAX)) {
7666349Sqs148142 		return (EINVAL);
7676349Sqs148142 	}
7686349Sqs148142 
7696349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, " hxge_param_set_vlan_ids id %d",
7706349Sqs148142 	    vmap->param_id));
7716349Sqs148142 #if defined(__i386)
7726349Sqs148142 	val_ptr = (uint32_t *)(uint32_t)pa->value;
7736349Sqs148142 	old_val_ptr = (uint32_t *)(uint32_t)pa->old_value;
7746349Sqs148142 #else
7756349Sqs148142 	val_ptr = (uint32_t *)pa->value;
7766349Sqs148142 	old_val_ptr = (uint32_t *)pa->old_value;
7776349Sqs148142 #endif
7786349Sqs148142 
7796349Sqs148142 	/* Search to see if this vlan id is already configured */
7806349Sqs148142 	for (i = 0; i < cfgd_vlans; i++) {
7816349Sqs148142 		old_map = (hxge_param_map_t *)&val_ptr[i];
7826349Sqs148142 		if ((old_map->param_id == 0) ||
7836349Sqs148142 		    (vmap->param_id == old_map->param_id) ||
7846349Sqs148142 		    (vlan_tbl[vmap->param_id].flag)) {
7856349Sqs148142 			cfg_position = i;
7866349Sqs148142 			break;
7876349Sqs148142 		}
7886349Sqs148142 	}
7896349Sqs148142 
7906349Sqs148142 	if (cfgd_vlans == 0) {
7916349Sqs148142 		cfg_position = 0;
7926349Sqs148142 		inc++;
7936349Sqs148142 	}
7946349Sqs148142 
7956349Sqs148142 	if (i == cfgd_vlans) {
7966349Sqs148142 		cfg_position = i;
7976349Sqs148142 		inc++;
7986349Sqs148142 	}
7996349Sqs148142 
8006349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD2_CTL,
8016349Sqs148142 	    " set_vlan_ids mapping i %d cfgd_vlans %llx position %d ",
8026349Sqs148142 	    i, cfgd_vlans, cfg_position));
8036349Sqs148142 
8046349Sqs148142 	if (val_ptr[cfg_position] != cfg_value) {
8056349Sqs148142 		old_val_ptr[cfg_position] = val_ptr[cfg_position];
8066349Sqs148142 		val_ptr[cfg_position] = cfg_value;
8076349Sqs148142 		vlan_tbl[vmap->param_id].flag = 1;
8086349Sqs148142 		cfg_it = B_TRUE;
8096349Sqs148142 		if (inc) {
8106349Sqs148142 			cfgd_vlans++;
8116349Sqs148142 			pa->type &= ~HXGE_PARAM_ARRAY_CNT_MASK;
8126349Sqs148142 			pa->type |= (cfgd_vlans << HXGE_PARAM_ARRAY_CNT_SHIFT);
8136349Sqs148142 
8146349Sqs148142 		}
8156349Sqs148142 
8166349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NDD2_CTL,
8176349Sqs148142 		    " after: param_set_vlan_ids cfg_vlans %llx position %d \n",
8186349Sqs148142 		    cfgd_vlans, cfg_position));
8196349Sqs148142 	}
8206349Sqs148142 
8216349Sqs148142 	if (cfg_it == B_TRUE) {
8226349Sqs148142 		status = hpi_pfc_cfg_vlan_table_entry_set(handle,
8236349Sqs148142 		    (vlan_id_t)vmap->param_id);
8246349Sqs148142 		if (status != HPI_SUCCESS)
8256349Sqs148142 			return (EINVAL);
8266349Sqs148142 	}
8276349Sqs148142 
8286349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_vlan_ids"));
8296349Sqs148142 
8306349Sqs148142 	return (0);
8316349Sqs148142 }
8326349Sqs148142 
8336349Sqs148142 
8346349Sqs148142 /* ARGSUSED */
8356349Sqs148142 static int
hxge_param_get_vlan_ids(p_hxge_t hxgep,queue_t * q,mblk_t * mp,caddr_t cp)8366349Sqs148142 hxge_param_get_vlan_ids(p_hxge_t hxgep, queue_t *q, mblk_t *mp, caddr_t cp)
8376349Sqs148142 {
8386349Sqs148142 	uint_t			print_len, buf_len;
8396349Sqs148142 	p_mblk_t		np;
8406349Sqs148142 	int			i;
8416349Sqs148142 	uint32_t		*val_ptr;
8426349Sqs148142 	hxge_param_map_t	*vmap;
8436349Sqs148142 	p_hxge_param_t		pa = (p_hxge_param_t)cp;
8446349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
8456349Sqs148142 	uint64_t		cfgd_vlans = 0;
8466349Sqs148142 	int buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_SIZE * 32;
8476349Sqs148142 
8486349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_vlan_ids "));
8496349Sqs148142 	(void) mi_mpprintf(mp, "VLAN Information\n");
8506349Sqs148142 
8516349Sqs148142 	if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
8526349Sqs148142 		(void) mi_mpprintf(mp, "%s\n", "out of buffer");
8536349Sqs148142 		return (0);
8546349Sqs148142 	}
8556349Sqs148142 
8566349Sqs148142 	buf_len = buff_alloc_size;
8576349Sqs148142 	mp->b_cont = np;
8586349Sqs148142 	cfgd_vlans = (pa->type & HXGE_PARAM_ARRAY_CNT_MASK) >>
8596349Sqs148142 	    HXGE_PARAM_ARRAY_CNT_SHIFT;
8606349Sqs148142 
8616349Sqs148142 	i = (int)cfgd_vlans;
8626349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
8636349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
8646349Sqs148142 	    "Configured VLANs %d\n VLAN ID\n", i);
8656349Sqs148142 	((mblk_t *)np)->b_wptr += print_len;
8666349Sqs148142 	buf_len -= print_len;
8676349Sqs148142 
8686349Sqs148142 #if defined(__i386)
8696349Sqs148142 	val_ptr = (uint32_t *)(uint32_t)pa->value;
8706349Sqs148142 #else
8716349Sqs148142 	val_ptr = (uint32_t *)pa->value;
8726349Sqs148142 #endif
8736349Sqs148142 
8746349Sqs148142 	for (i = 0; i < cfgd_vlans; i++) {
8756349Sqs148142 		vmap = (hxge_param_map_t *)&val_ptr[i];
8766349Sqs148142 		if (p_class_cfgp->vlan_tbl[vmap->param_id].flag) {
8776349Sqs148142 			print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
8786349Sqs148142 			    buf_len, "  %d\n", vmap->param_id);
8796349Sqs148142 			((mblk_t *)np)->b_wptr += print_len;
8806349Sqs148142 			buf_len -= print_len;
8816349Sqs148142 		}
8826349Sqs148142 	}
8836349Sqs148142 
8846349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_vlan_ids"));
8856349Sqs148142 
8866349Sqs148142 	return (0);
8876349Sqs148142 }
8886349Sqs148142 
8896349Sqs148142 /* ARGSUSED */
8906349Sqs148142 static int
hxge_param_tcam_enable(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)8916349Sqs148142 hxge_param_tcam_enable(p_hxge_t hxgep, queue_t *q,
8926349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
8936349Sqs148142 {
8946349Sqs148142 	uint32_t	status = 0, cfg_value;
8956349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
8966349Sqs148142 	uint32_t	cfg_it = B_FALSE;
8976349Sqs148142 	char		*end;
8986349Sqs148142 
8996349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_tcam_enable"));
9006349Sqs148142 
9016349Sqs148142 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_BINARY);
9026349Sqs148142 	if (pa->value != cfg_value) {
9036349Sqs148142 		pa->old_value = pa->value;
9046349Sqs148142 		pa->value = cfg_value;
9056349Sqs148142 		cfg_it = B_TRUE;
9066349Sqs148142 	}
9076349Sqs148142 	if (cfg_it == B_TRUE) {
9086349Sqs148142 		if (pa->value)
9096349Sqs148142 			status = hxge_pfc_config_tcam_enable(hxgep);
9106349Sqs148142 		else
9116349Sqs148142 			status = hxge_pfc_config_tcam_disable(hxgep);
9126349Sqs148142 		if (status != HXGE_OK)
9136349Sqs148142 			return (EINVAL);
9146349Sqs148142 	}
9156349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, " <== hxge_param_tcam_enable"));
9166349Sqs148142 	return (0);
9176349Sqs148142 }
9186349Sqs148142 
9196349Sqs148142 /* ARGSUSED */
9206349Sqs148142 static int
hxge_param_set_ether_usr(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)9216349Sqs148142 hxge_param_set_ether_usr(p_hxge_t hxgep, queue_t *q,
9226349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
9236349Sqs148142 {
9246349Sqs148142 	char		*end;
9256349Sqs148142 	uint32_t	status = 0, cfg_value;
9266349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
9276349Sqs148142 
9286349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_ether_usr"));
9296349Sqs148142 
9307584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
9317584SQiyan.Sun@Sun.COM 		value += 2;
9327584SQiyan.Sun@Sun.COM 
9336349Sqs148142 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
9346349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
9356349Sqs148142 		return (EINVAL);
9366349Sqs148142 	}
9376349Sqs148142 	if (pa->value != cfg_value) {
9386349Sqs148142 		pa->old_value = pa->value;
9396349Sqs148142 		pa->value = cfg_value;
9406349Sqs148142 	}
9416349Sqs148142 
9426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_ether_usr"));
9436349Sqs148142 	return (status);
9446349Sqs148142 }
9456349Sqs148142 
9466349Sqs148142 static int
hxge_class_name_2value(p_hxge_t hxgep,char * name)9476349Sqs148142 hxge_class_name_2value(p_hxge_t hxgep, char *name)
9486349Sqs148142 {
9496349Sqs148142 	int		i;
9506349Sqs148142 	int		class_instance = param_class_opt_ipv4_tcp;
9516349Sqs148142 	p_hxge_param_t	param_arr;
9526349Sqs148142 
9536349Sqs148142 	param_arr = hxgep->param_arr;
9546349Sqs148142 	for (i = TCAM_CLASS_TCP_IPV4; i <= TCAM_CLASS_SCTP_IPV6; i++) {
9556349Sqs148142 		if (strcmp(param_arr[class_instance].name, name) == 0)
9566349Sqs148142 			return (i);
9576349Sqs148142 		class_instance++;
9586349Sqs148142 	}
9596349Sqs148142 	return (-1);
9606349Sqs148142 }
9616349Sqs148142 
9626349Sqs148142 /* ARGSUSED */
9637584SQiyan.Sun@Sun.COM int
hxge_param_set_ip_opt(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)9646349Sqs148142 hxge_param_set_ip_opt(p_hxge_t hxgep, queue_t *q,
9656349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
9666349Sqs148142 {
9676349Sqs148142 	char		*end;
9686349Sqs148142 	uint32_t	status, cfg_value;
9696349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
9706349Sqs148142 	tcam_class_t	class;
9716349Sqs148142 	uint32_t	cfg_it = B_FALSE;
9726349Sqs148142 
9736349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_ip_opt"));
9746349Sqs148142 
9757584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
9767584SQiyan.Sun@Sun.COM 		value += 2;
9777584SQiyan.Sun@Sun.COM 
9786349Sqs148142 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
9796349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
9806349Sqs148142 		return (EINVAL);
9816349Sqs148142 	}
9826349Sqs148142 	if (pa->value != cfg_value) {
9836349Sqs148142 		pa->old_value = pa->value;
9846349Sqs148142 		pa->value = cfg_value;
9856349Sqs148142 		cfg_it = B_TRUE;
9866349Sqs148142 	}
9876349Sqs148142 	if (cfg_it == B_TRUE) {
9886349Sqs148142 		/* do the actual hw setup  */
9896349Sqs148142 		class = hxge_class_name_2value(hxgep, pa->name);
9906349Sqs148142 		if (class == -1)
9916349Sqs148142 			return (EINVAL);
9926349Sqs148142 
9936349Sqs148142 		status = hxge_pfc_ip_class_config(hxgep, class, pa->value);
9946349Sqs148142 		if (status != HXGE_OK)
9956349Sqs148142 			return (EINVAL);
9966349Sqs148142 	}
9976349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_ip_opt"));
9986349Sqs148142 	return (0);
9996349Sqs148142 }
10006349Sqs148142 
10016349Sqs148142 /* ARGSUSED */
10027584SQiyan.Sun@Sun.COM int
hxge_param_get_ip_opt(p_hxge_t hxgep,queue_t * q,mblk_t * mp,caddr_t cp)10036349Sqs148142 hxge_param_get_ip_opt(p_hxge_t hxgep, queue_t *q, mblk_t *mp, caddr_t cp)
10046349Sqs148142 {
10056349Sqs148142 	uint32_t	status, cfg_value;
10066349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
10076349Sqs148142 	tcam_class_t	class;
10086349Sqs148142 
10096349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_ip_opt"));
10106349Sqs148142 
10116349Sqs148142 	/* do the actual hw setup  */
10126349Sqs148142 	class = hxge_class_name_2value(hxgep, pa->name);
10136349Sqs148142 	if (class == -1)
10146349Sqs148142 		return (EINVAL);
10156349Sqs148142 	cfg_value = 0;
10166349Sqs148142 	status = hxge_pfc_ip_class_config_get(hxgep, class, &cfg_value);
10176349Sqs148142 	if (status != HXGE_OK)
10186349Sqs148142 		return (EINVAL);
10196349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL,
10206349Sqs148142 	    "hxge_param_get_ip_opt_get %x ", cfg_value));
10216349Sqs148142 	pa->value = cfg_value;
10226349Sqs148142 
10237584SQiyan.Sun@Sun.COM 	if (mp != NULL)
10247584SQiyan.Sun@Sun.COM 		(void) mi_mpprintf(mp, "%x", cfg_value);
10257584SQiyan.Sun@Sun.COM 
10266349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_ip_opt status "));
10276349Sqs148142 	return (0);
10286349Sqs148142 }
10296349Sqs148142 
10306349Sqs148142 /* ARGSUSED */
10316349Sqs148142 static int
hxge_param_pfc_hash_init(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)10326349Sqs148142 hxge_param_pfc_hash_init(p_hxge_t hxgep, queue_t *q, mblk_t *mp,
10336349Sqs148142 	char *value, caddr_t cp)
10346349Sqs148142 {
10356349Sqs148142 	char		*end;
10366349Sqs148142 	uint32_t	status, cfg_value;
10376349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
10386349Sqs148142 	uint32_t	cfg_it = B_FALSE;
10396349Sqs148142 
10406349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_pfc_hash_init"));
10416349Sqs148142 
10427584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
10437584SQiyan.Sun@Sun.COM 		value += 2;
10447584SQiyan.Sun@Sun.COM 
10456349Sqs148142 	cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
10466349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
10476349Sqs148142 		return (EINVAL);
10486349Sqs148142 	}
10496349Sqs148142 
10506349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL,
10516349Sqs148142 	    " hxge_param_pfc_hash_init value %x", cfg_value));
10526349Sqs148142 	if (pa->value != cfg_value) {
10536349Sqs148142 		pa->old_value = pa->value;
10546349Sqs148142 		pa->value = cfg_value;
10556349Sqs148142 		cfg_it = B_TRUE;
10566349Sqs148142 	}
10576349Sqs148142 
10586349Sqs148142 	if (cfg_it == B_TRUE) {
10596349Sqs148142 		status = hxge_pfc_set_hash(hxgep, (uint32_t)pa->value);
10606349Sqs148142 		if (status != HXGE_OK)
10616349Sqs148142 			return (EINVAL);
10626349Sqs148142 	}
10636349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, " <== hxge_param_pfc_hash_init"));
10646349Sqs148142 	return (0);
10656349Sqs148142 }
10666349Sqs148142 
10676349Sqs148142 /* ARGSUSED */
10686349Sqs148142 static int
hxge_param_set_hxge_debug_flag(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)10696349Sqs148142 hxge_param_set_hxge_debug_flag(p_hxge_t hxgep, queue_t *q,
10706349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
10716349Sqs148142 {
10726349Sqs148142 	char		*end;
10736349Sqs148142 	uint32_t	status = 0;
10746349Sqs148142 	uint64_t	cfg_value = 0;
10756349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
10766349Sqs148142 	uint32_t	cfg_it = B_FALSE;
10776349Sqs148142 
10786349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_hxge_debug_flag"));
10797584SQiyan.Sun@Sun.COM 
10807584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
10817584SQiyan.Sun@Sun.COM 		value += 2;
10827584SQiyan.Sun@Sun.COM 
10836349Sqs148142 	cfg_value = mi_strtol(value, &end, BASE_HEX);
10846349Sqs148142 
10856349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
10866349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NDD_CTL,
10876349Sqs148142 		    " hxge_param_set_hxge_debug_flag"
10886349Sqs148142 		    " outof range %llx", cfg_value));
10896349Sqs148142 		return (EINVAL);
10906349Sqs148142 	}
10916349Sqs148142 	if (pa->value != cfg_value) {
10926349Sqs148142 		pa->old_value = pa->value;
10936349Sqs148142 		pa->value = cfg_value;
10946349Sqs148142 		cfg_it = B_TRUE;
10956349Sqs148142 	}
10966349Sqs148142 	if (cfg_it == B_TRUE)
10976349Sqs148142 		hxgep->hxge_debug_level = pa->value;
10986349Sqs148142 
10996349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_hxge_debug_flag"));
11006349Sqs148142 	return (status);
11016349Sqs148142 }
11026349Sqs148142 
11036349Sqs148142 /* ARGSUSED */
11046349Sqs148142 static int
hxge_param_get_debug_flag(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)11056349Sqs148142 hxge_param_get_debug_flag(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
11066349Sqs148142 {
11076349Sqs148142 	int		status = 0;
11086349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
11096349Sqs148142 
11106349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_debug_flag"));
11116349Sqs148142 
11126349Sqs148142 	if (pa->value > 0xffffffff)
11136349Sqs148142 		(void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32),
11146349Sqs148142 		    (int)(pa->value & 0xffffffff));
11156349Sqs148142 	else
11166349Sqs148142 		(void) mi_mpprintf(mp, "%x", (int)pa->value);
11176349Sqs148142 
11186349Sqs148142 
11196349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_debug_flag"));
11206349Sqs148142 	return (status);
11216349Sqs148142 }
11226349Sqs148142 
11236349Sqs148142 /* ARGSUSED */
11246349Sqs148142 static int
hxge_param_set_hpi_debug_flag(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)11256349Sqs148142 hxge_param_set_hpi_debug_flag(p_hxge_t hxgep, queue_t *q,
11266349Sqs148142 	mblk_t *mp, char *value, caddr_t cp)
11276349Sqs148142 {
11286349Sqs148142 	char		*end;
11296349Sqs148142 	uint32_t	status = 0;
11306349Sqs148142 	uint64_t	cfg_value = 0;
11316349Sqs148142 	p_hxge_param_t	pa = (p_hxge_param_t)cp;
11326349Sqs148142 	uint32_t	cfg_it = B_FALSE;
11336349Sqs148142 
11346349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_hpi_debug_flag"));
11357584SQiyan.Sun@Sun.COM 
11367584SQiyan.Sun@Sun.COM 	if (strncasecmp(value, "0x", 2) == 0)
11377584SQiyan.Sun@Sun.COM 		value += 2;
11387584SQiyan.Sun@Sun.COM 
11396349Sqs148142 	cfg_value = mi_strtol(value, &end, BASE_HEX);
11406349Sqs148142 
11416349Sqs148142 	if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
11426349Sqs148142 		HXGE_DEBUG_MSG((hxgep, NDD_CTL, " hxge_param_set_hpi_debug_flag"
11436349Sqs148142 		    " outof range %llx", cfg_value));
11446349Sqs148142 		return (EINVAL);
11456349Sqs148142 	}
11466349Sqs148142 	if (pa->value != cfg_value) {
11476349Sqs148142 		pa->old_value = pa->value;
11486349Sqs148142 		pa->value = cfg_value;
11496349Sqs148142 		cfg_it = B_TRUE;
11506349Sqs148142 	}
11516349Sqs148142 	if (cfg_it == B_TRUE) {
11526349Sqs148142 		hpi_debug_level = pa->value;
11536349Sqs148142 	}
11546349Sqs148142 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_debug_flag"));
11556349Sqs148142 	return (status);
11566349Sqs148142 }
11576349Sqs148142 
11586349Sqs148142 typedef struct block_info {
11596349Sqs148142 	char *name;
11606349Sqs148142 	uint32_t offset;
11616349Sqs148142 } block_info_t;
11626349Sqs148142 
11636349Sqs148142 block_info_t reg_block[] = {
11646349Sqs148142 	{"PIO", PIO_BASE_ADDR},
11656349Sqs148142 	{"PIO_LDSV", PIO_LDSV_BASE_ADDR},
11666349Sqs148142 	{"PIO_LDMASK", PIO_LDMASK_BASE_ADDR},
11676349Sqs148142 	{"PFC", PFC_BASE_ADDR},
11686349Sqs148142 	{"RDC", RDC_BASE_ADDR},
11696349Sqs148142 	{"TDC", TDC_BASE_ADDR},
11706349Sqs148142 	{"VMAC", VMAC_BASE_ADDR},
11716349Sqs148142 	{"END", ALL_FF_32},
11726349Sqs148142 };
11736349Sqs148142 
11746349Sqs148142 /* ARGSUSED */
11756349Sqs148142 static int
hxge_param_dump_ptrs(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)11766349Sqs148142 hxge_param_dump_ptrs(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
11776349Sqs148142 {
11786349Sqs148142 	uint_t			print_len, buf_len;
11796349Sqs148142 	p_mblk_t		np;
11806349Sqs148142 	int			rdc, tdc, block;
11816349Sqs148142 	uint64_t		base;
11826349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
11836349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
11846349Sqs148142 	int			buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_8K;
11856349Sqs148142 	p_tx_ring_t		*tx_rings;
11866349Sqs148142 	p_rx_rcr_rings_t	rx_rcr_rings;
11876349Sqs148142 	p_rx_rcr_ring_t		*rcr_rings;
11886349Sqs148142 	p_rx_rbr_rings_t	rx_rbr_rings;
11896349Sqs148142 	p_rx_rbr_ring_t		*rbr_rings;
11906349Sqs148142 
11916349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, "==> hxge_param_dump_ptrs"));
11926349Sqs148142 
11936349Sqs148142 	(void) mi_mpprintf(mp, "ptr information\n");
11946349Sqs148142 
11956349Sqs148142 	if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
11966349Sqs148142 		/* The following may work even if we cannot get a large buf. */
11976349Sqs148142 		(void) mi_mpprintf(mp, "%s\n", "out of buffer");
11986349Sqs148142 		return (0);
11996349Sqs148142 	}
12006349Sqs148142 	buf_len = buff_alloc_size;
12016349Sqs148142 
12026349Sqs148142 	mp->b_cont = np;
12036349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
12046349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
12056349Sqs148142 
12066349Sqs148142 	rx_rcr_rings = hxgep->rx_rcr_rings;
12076349Sqs148142 	rcr_rings = rx_rcr_rings->rcr_rings;
12086349Sqs148142 	rx_rbr_rings = hxgep->rx_rbr_rings;
12096349Sqs148142 	rbr_rings = rx_rbr_rings->rbr_rings;
12106349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12116349Sqs148142 	    "hxgep (hxge_t) $%p\n dev_regs (dev_regs_t) $%p\n",
1212*7650SMichael.Speer@Sun.COM 	    (void *)hxgep, (void *)hxgep->dev_regs);
12136349Sqs148142 
12146349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12156349Sqs148142 	/* do register pointers */
12166349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12176349Sqs148142 	    "reg base (hpi_reg_ptr_t) $%p\t pci reg (hpi_reg_ptr_t) $%p\n",
1218*7650SMichael.Speer@Sun.COM 	    (void *)hxgep->dev_regs->hxge_regp,
1219*7650SMichael.Speer@Sun.COM 	    (void *)hxgep->dev_regs->hxge_pciregp);
12206349Sqs148142 
12216349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12226349Sqs148142 
12236349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12246349Sqs148142 	    "\nBlock \t Offset \n");
12256349Sqs148142 
12266349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12276349Sqs148142 	block = 0;
12286349Sqs148142 #if defined(__i386)
12296349Sqs148142 	base = (uint64_t)(uint32_t)hxgep->dev_regs->hxge_regp;
12306349Sqs148142 #else
12316349Sqs148142 	base = (uint64_t)hxgep->dev_regs->hxge_regp;
12326349Sqs148142 #endif
12336349Sqs148142 	while (reg_block[block].offset != ALL_FF_32) {
12346349Sqs148142 		print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12356349Sqs148142 		    "%9s\t 0x%llx\n", reg_block[block].name,
12366349Sqs148142 		    (unsigned long long) (reg_block[block].offset + base));
12376349Sqs148142 		ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12386349Sqs148142 		block++;
12396349Sqs148142 	}
12406349Sqs148142 
12416349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12426349Sqs148142 	    "\nRDC\t rcrp (rx_rcr_ring_t)\t rbrp (rx_rbr_ring_t)\n");
12436349Sqs148142 
12446349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12456349Sqs148142 
12466349Sqs148142 	for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) {
12476349Sqs148142 		print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12486349Sqs148142 		    " %d\t  $%p\t\t   $%p\n",
1249*7650SMichael.Speer@Sun.COM 		    rdc, (void *)rcr_rings[rdc], (void *)rbr_rings[rdc]);
12506349Sqs148142 		ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12516349Sqs148142 	}
12526349Sqs148142 
12536349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
12546349Sqs148142 	    "\nTDC\t tdcp (tx_ring_t)\n");
12556349Sqs148142 
12566349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12576349Sqs148142 	tx_rings = hxgep->tx_rings->rings;
12586349Sqs148142 	for (tdc = 0; tdc < p_cfgp->max_tdcs; tdc++) {
12596349Sqs148142 		print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
1260*7650SMichael.Speer@Sun.COM 		    " %d\t  $%p\n", tdc, (void *)tx_rings[tdc]);
12616349Sqs148142 		ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12626349Sqs148142 	}
12636349Sqs148142 
12646349Sqs148142 	print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, "\n\n");
12656349Sqs148142 
12666349Sqs148142 	ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
12676349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, "<== hxge_param_dump_ptrs"));
12686349Sqs148142 	return (0);
12696349Sqs148142 }
12706349Sqs148142 
12716349Sqs148142 /*
12726349Sqs148142  * Load 'name' into the named dispatch table pointed to by 'ndp'.
12736349Sqs148142  * 'ndp' should be the address of a char pointer cell.  If the table
12746349Sqs148142  * does not exist (*ndp == 0), a new table is allocated and 'ndp'
12756349Sqs148142  * is stuffed.  If there is not enough space in the table for a new
12766349Sqs148142  * entry, more space is allocated.
12776349Sqs148142  */
12786349Sqs148142 boolean_t
hxge_nd_load(caddr_t * pparam,char * name,pfi_t get_pfi,pfi_t set_pfi,caddr_t data)12796349Sqs148142 hxge_nd_load(caddr_t *pparam, char *name,
12806349Sqs148142 	pfi_t get_pfi, pfi_t set_pfi, caddr_t data)
12816349Sqs148142 {
12826349Sqs148142 	ND	*nd;
12836349Sqs148142 	NDE	*nde;
12846349Sqs148142 
12856349Sqs148142 	HXGE_DEBUG_MSG((NULL, NDD2_CTL, " ==> hxge_nd_load: %s", name));
12866349Sqs148142 	if (!pparam)
12876349Sqs148142 		return (B_FALSE);
12886349Sqs148142 	if ((nd = (ND *) * pparam) == NULL) {
12896349Sqs148142 		if ((nd = (ND *) KMEM_ZALLOC(sizeof (ND), KM_NOSLEEP)) == NULL)
12906349Sqs148142 			return (B_FALSE);
12916349Sqs148142 		*pparam = (caddr_t)nd;
12926349Sqs148142 	}
12936349Sqs148142 	if (nd->nd_tbl) {
12946349Sqs148142 		for (nde = nd->nd_tbl; nde->nde_name; nde++) {
12956349Sqs148142 			if (strcmp(name, nde->nde_name) == 0)
12966349Sqs148142 				goto fill_it;
12976349Sqs148142 		}
12986349Sqs148142 	}
12996349Sqs148142 	if (nd->nd_free_count <= 1) {
13006349Sqs148142 		if ((nde = (NDE *) KMEM_ZALLOC(nd->nd_size +
13016349Sqs148142 		    NDE_ALLOC_SIZE, KM_NOSLEEP)) == NULL)
13026349Sqs148142 			return (B_FALSE);
13036349Sqs148142 		nd->nd_free_count += NDE_ALLOC_COUNT;
13046349Sqs148142 		if (nd->nd_tbl) {
13056349Sqs148142 			bcopy((char *)nd->nd_tbl, (char *)nde, nd->nd_size);
13066349Sqs148142 			KMEM_FREE((char *)nd->nd_tbl, nd->nd_size);
13076349Sqs148142 		} else {
13086349Sqs148142 			nd->nd_free_count--;
13096349Sqs148142 			nde->nde_name = "?";
13106349Sqs148142 			nde->nde_get_pfi = hxge_nd_get_names;
13116349Sqs148142 			nde->nde_set_pfi = hxge_set_default;
13126349Sqs148142 		}
13136349Sqs148142 		nde->nde_data = (caddr_t)nd;
13146349Sqs148142 		nd->nd_tbl = nde;
13156349Sqs148142 		nd->nd_size += NDE_ALLOC_SIZE;
13166349Sqs148142 	}
13176349Sqs148142 	for (nde = nd->nd_tbl; nde->nde_name; nde++)
13186349Sqs148142 		noop;
13196349Sqs148142 	nd->nd_free_count--;
13206349Sqs148142 fill_it:
13216349Sqs148142 	nde->nde_name = name;
13226349Sqs148142 	nde->nde_get_pfi = get_pfi;
13236349Sqs148142 	nde->nde_set_pfi = set_pfi;
13246349Sqs148142 	nde->nde_data = data;
13256349Sqs148142 	HXGE_DEBUG_MSG((NULL, NDD2_CTL, " <== hxge_nd_load"));
13266349Sqs148142 
13276349Sqs148142 	return (B_TRUE);
13286349Sqs148142 }
13296349Sqs148142 
13306349Sqs148142 /*
13316349Sqs148142  * Free the table pointed to by 'pparam'
13326349Sqs148142  */
13336349Sqs148142 void
hxge_nd_free(caddr_t * pparam)13346349Sqs148142 hxge_nd_free(caddr_t *pparam)
13356349Sqs148142 {
13366349Sqs148142 	ND *nd;
13376349Sqs148142 
13386349Sqs148142 	if ((nd = (ND *)*pparam) != NULL) {
13396349Sqs148142 		if (nd->nd_tbl)
13406349Sqs148142 			KMEM_FREE((char *)nd->nd_tbl, nd->nd_size);
13416349Sqs148142 		KMEM_FREE((char *)nd, sizeof (ND));
13426349Sqs148142 		*pparam = nil(caddr_t);
13436349Sqs148142 	}
13446349Sqs148142 }
13456349Sqs148142 
13466349Sqs148142 int
hxge_nd_getset(p_hxge_t hxgep,queue_t * q,caddr_t param,p_mblk_t mp)13476349Sqs148142 hxge_nd_getset(p_hxge_t hxgep, queue_t *q, caddr_t param, p_mblk_t mp)
13486349Sqs148142 {
13496349Sqs148142 	int		err;
13506349Sqs148142 	IOCP		iocp;
13516349Sqs148142 	p_mblk_t	mp1, mp2;
13526349Sqs148142 	ND		*nd;
13536349Sqs148142 	NDE		*nde;
13546349Sqs148142 	char		*valp;
13556349Sqs148142 
13566349Sqs148142 	size_t		avail;
13576349Sqs148142 
13586349Sqs148142 	if (!param) {
13596349Sqs148142 		return (B_FALSE);
13606349Sqs148142 	}
13616349Sqs148142 	nd = (ND *) param;
13626349Sqs148142 	iocp = (IOCP) mp->b_rptr;
13636349Sqs148142 	if ((iocp->ioc_count == 0) || !(mp1 = mp->b_cont)) {
13646349Sqs148142 		mp->b_datap->db_type = M_IOCACK;
13656349Sqs148142 		iocp->ioc_count = 0;
13666349Sqs148142 		iocp->ioc_error = EINVAL;
13676349Sqs148142 		return (B_FALSE);
13686349Sqs148142 	}
13696349Sqs148142 	/*
13706349Sqs148142 	 * NOTE - logic throughout nd_xxx assumes single data block for ioctl.
13716349Sqs148142 	 * However, existing code sends in some big buffers.
13726349Sqs148142 	 */
13736349Sqs148142 	avail = iocp->ioc_count;
13746349Sqs148142 	if (mp1->b_cont) {
13756349Sqs148142 		freemsg(mp1->b_cont);
13766349Sqs148142 		mp1->b_cont = NULL;
13776349Sqs148142 	}
13786349Sqs148142 	mp1->b_datap->db_lim[-1] = '\0';	/* Force null termination */
13796349Sqs148142 	for (valp = (char *)mp1->b_rptr; *valp != '\0'; valp++) {
13806349Sqs148142 		if (*valp == '-')
13816349Sqs148142 			*valp = '_';
13826349Sqs148142 	}
13836349Sqs148142 
13846349Sqs148142 	valp = (char *)mp1->b_rptr;
13856349Sqs148142 
13866349Sqs148142 	for (nde = nd->nd_tbl; /* */; nde++) {
13876349Sqs148142 		if (!nde->nde_name)
13886349Sqs148142 			return (B_FALSE);
13896349Sqs148142 		if (strcmp(nde->nde_name, valp) == 0)
13906349Sqs148142 			break;
13916349Sqs148142 	}
13926349Sqs148142 	err = EINVAL;
13936349Sqs148142 	while (*valp++)
13946349Sqs148142 		noop;
13956349Sqs148142 	if (!*valp || valp >= (char *)mp1->b_wptr)
13966349Sqs148142 		valp = nilp(char);
13976349Sqs148142 	switch (iocp->ioc_cmd) {
13986349Sqs148142 	case ND_GET:
13997584SQiyan.Sun@Sun.COM 		if (*nde->nde_get_pfi == NULL)
14007584SQiyan.Sun@Sun.COM 			return (B_FALSE);
14017584SQiyan.Sun@Sun.COM 
14026349Sqs148142 		/*
14036349Sqs148142 		 * (temporary) hack: "*valp" is size of user buffer for
14046349Sqs148142 		 * copyout. If result of action routine is too big, free excess
14056349Sqs148142 		 * and return ioc_rval as buffer size needed. Return as many
14066349Sqs148142 		 * mblocks as will fit, free the rest.  For backward
14076349Sqs148142 		 * compatibility, assume size of original ioctl buffer if
14086349Sqs148142 		 * "*valp" bad or not given.
14096349Sqs148142 		 */
14106349Sqs148142 		if (valp)
14116349Sqs148142 			avail = mi_strtol(valp, (char **)0, 10);
14126349Sqs148142 		/*
14136349Sqs148142 		 * We overwrite the name/value with the reply data
14146349Sqs148142 		 */
14156349Sqs148142 		mp2 = mp1;
14166349Sqs148142 		while (mp2) {
14176349Sqs148142 			mp2->b_wptr = mp2->b_rptr;
14186349Sqs148142 			mp2 = mp2->b_cont;
14196349Sqs148142 		}
14206349Sqs148142 
14216349Sqs148142 		err = (*nde->nde_get_pfi) (hxgep, q, mp1, nde->nde_data);
14226349Sqs148142 
14236349Sqs148142 		if (!err) {
14246349Sqs148142 			size_t size_out = 0;
14256349Sqs148142 			ssize_t excess;
14266349Sqs148142 
14276349Sqs148142 			iocp->ioc_rval = 0;
14286349Sqs148142 
14296349Sqs148142 			/* Tack on the null */
14306349Sqs148142 			err = hxge_mk_mblk_tail_space(mp1, &mp2, 1);
14316349Sqs148142 			if (!err) {
14326349Sqs148142 				*mp2->b_wptr++ = '\0';
14336349Sqs148142 				size_out = msgdsize(mp1);
14346349Sqs148142 				excess = size_out - avail;
14356349Sqs148142 				if (excess > 0) {
14366349Sqs148142 					iocp->ioc_rval = (int)size_out;
14376349Sqs148142 					size_out -= excess;
14386349Sqs148142 					(void) adjmsg(mp1, -(excess + 1));
14396349Sqs148142 					err = hxge_mk_mblk_tail_space(
14406349Sqs148142 					    mp1, &mp2, 1);
14416349Sqs148142 					if (!err)
14426349Sqs148142 						*mp2->b_wptr++ = '\0';
14436349Sqs148142 					else
14446349Sqs148142 						size_out = 0;
14456349Sqs148142 				}
14466349Sqs148142 			} else
14476349Sqs148142 				size_out = 0;
14486349Sqs148142 			iocp->ioc_count = size_out;
14496349Sqs148142 		}
14506349Sqs148142 		break;
14516349Sqs148142 
14526349Sqs148142 	case ND_SET:
14536349Sqs148142 		if (valp) {
14546349Sqs148142 			if (nde->nde_set_pfi) {
14556349Sqs148142 				err = (*nde->nde_set_pfi) (hxgep, q, mp1, valp,
14566349Sqs148142 				    nde->nde_data);
14576349Sqs148142 				iocp->ioc_count = 0;
14586349Sqs148142 				freemsg(mp1);
14596349Sqs148142 				mp->b_cont = NULL;
14606349Sqs148142 			}
14616349Sqs148142 		}
14626349Sqs148142 		break;
14636349Sqs148142 
14646349Sqs148142 	default:
14656349Sqs148142 		break;
14666349Sqs148142 	}
14676349Sqs148142 	iocp->ioc_error = err;
14686349Sqs148142 	mp->b_datap->db_type = M_IOCACK;
14696349Sqs148142 	return (B_TRUE);
14706349Sqs148142 }
14716349Sqs148142 
14726349Sqs148142 /* ARGSUSED */
14736349Sqs148142 int
hxge_nd_get_names(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t param)14746349Sqs148142 hxge_nd_get_names(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t param)
14756349Sqs148142 {
14766349Sqs148142 	ND		*nd;
14776349Sqs148142 	NDE		*nde;
14786349Sqs148142 	char		*rwtag;
14796349Sqs148142 	boolean_t	get_ok, set_ok;
14806349Sqs148142 	size_t		param_len;
14816349Sqs148142 	int		status = 0;
14826349Sqs148142 
14836349Sqs148142 	nd = (ND *) param;
14846349Sqs148142 	if (!nd)
14856349Sqs148142 		return (ENOENT);
14866349Sqs148142 
14876349Sqs148142 	for (nde = nd->nd_tbl; nde->nde_name; nde++) {
14886349Sqs148142 		get_ok = (nde->nde_get_pfi != hxge_get_default) &&
14896349Sqs148142 		    (nde->nde_get_pfi != NULL);
14906349Sqs148142 		set_ok = (nde->nde_set_pfi != hxge_set_default) &&
14916349Sqs148142 		    (nde->nde_set_pfi != NULL);
14926349Sqs148142 		if (get_ok) {
14936349Sqs148142 			if (set_ok)
14946349Sqs148142 				rwtag = "read and write";
14956349Sqs148142 			else
14966349Sqs148142 				rwtag = "read only";
14976349Sqs148142 		} else if (set_ok)
14986349Sqs148142 			rwtag = "write only";
14996349Sqs148142 		else {
15006349Sqs148142 			continue;
15016349Sqs148142 		}
15026349Sqs148142 		param_len = strlen(rwtag);
15036349Sqs148142 		param_len += strlen(nde->nde_name);
15046349Sqs148142 		param_len += 4;
15056349Sqs148142 
15066349Sqs148142 		(void) mi_mpprintf(mp, "%s (%s)", nde->nde_name, rwtag);
15076349Sqs148142 	}
15086349Sqs148142 	return (status);
15096349Sqs148142 }
15106349Sqs148142 
15116349Sqs148142 /* ARGSUSED */
15126349Sqs148142 int
hxge_get_default(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t data)15136349Sqs148142 hxge_get_default(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t data)
15146349Sqs148142 {
15156349Sqs148142 	return (EACCES);
15166349Sqs148142 }
15176349Sqs148142 
15186349Sqs148142 /* ARGSUSED */
15196349Sqs148142 int
hxge_set_default(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,char * value,caddr_t data)15206349Sqs148142 hxge_set_default(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, char *value,
15216349Sqs148142 	caddr_t data)
15226349Sqs148142 {
15236349Sqs148142 	return (EACCES);
15246349Sqs148142 }
15256349Sqs148142 
15266349Sqs148142 void
hxge_param_ioctl(p_hxge_t hxgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)15276349Sqs148142 hxge_param_ioctl(p_hxge_t hxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
15286349Sqs148142 {
15296349Sqs148142 	int cmd;
15306349Sqs148142 	int status = B_FALSE;
15316349Sqs148142 
15326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, "==> hxge_param_ioctl"));
15336349Sqs148142 	cmd = iocp->ioc_cmd;
15346349Sqs148142 	switch (cmd) {
15356349Sqs148142 	default:
15366349Sqs148142 		HXGE_DEBUG_MSG((hxgep, IOC_CTL,
15376349Sqs148142 		    "hxge_param_ioctl: bad cmd 0x%0x", cmd));
15386349Sqs148142 		break;
15396349Sqs148142 
15406349Sqs148142 	case ND_GET:
15416349Sqs148142 	case ND_SET:
15426349Sqs148142 		HXGE_DEBUG_MSG((hxgep, IOC_CTL,
15436349Sqs148142 		    "hxge_param_ioctl: cmd 0x%0x", cmd));
15446349Sqs148142 		if (!hxge_nd_getset(hxgep, wq, hxgep->param_list, mp)) {
15456349Sqs148142 			HXGE_DEBUG_MSG((hxgep, IOC_CTL,
15466349Sqs148142 			    "false ret from hxge_nd_getset"));
15476349Sqs148142 			break;
15486349Sqs148142 		}
15496349Sqs148142 		status = B_TRUE;
15506349Sqs148142 		break;
15516349Sqs148142 	}
15526349Sqs148142 
15536349Sqs148142 	if (status) {
15546349Sqs148142 		qreply(wq, mp);
15556349Sqs148142 	} else {
15566349Sqs148142 		miocnak(wq, mp, 0, EINVAL);
15576349Sqs148142 	}
15586349Sqs148142 	HXGE_DEBUG_MSG((hxgep, IOC_CTL, "<== hxge_param_ioctl"));
15596349Sqs148142 }
1560