xref: /titanic_52/usr/src/uts/common/io/nxge/nxge_virtual.c (revision d2ec54f7875f7e05edd56195adbeb593c947763f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/nxge/nxge_impl.h>
29 #include <sys/nxge/nxge_mac.h>
30 #include <sys/nxge/nxge_hio.h>
31 
32 static void nxge_get_niu_property(dev_info_t *, niu_type_t *);
33 static nxge_status_t nxge_get_mac_addr_properties(p_nxge_t);
34 static nxge_status_t nxge_use_cfg_n2niu_properties(p_nxge_t);
35 static void nxge_use_cfg_neptune_properties(p_nxge_t);
36 static void nxge_use_cfg_dma_config(p_nxge_t);
37 static void nxge_use_cfg_vlan_class_config(p_nxge_t);
38 static void nxge_use_cfg_mac_class_config(p_nxge_t);
39 static void nxge_use_cfg_class_config(p_nxge_t);
40 static void nxge_use_cfg_link_cfg(p_nxge_t);
41 static void nxge_set_hw_dma_config(p_nxge_t);
42 static void nxge_set_hw_vlan_class_config(p_nxge_t);
43 static void nxge_set_hw_mac_class_config(p_nxge_t);
44 static void nxge_set_hw_class_config(p_nxge_t);
45 static nxge_status_t nxge_use_default_dma_config_n2(p_nxge_t);
46 static void nxge_ldgv_setup(p_nxge_ldg_t *, p_nxge_ldv_t *, uint8_t,
47 	uint8_t, int *);
48 static void nxge_init_mmac(p_nxge_t, boolean_t);
49 static void nxge_set_rdc_intr_property(p_nxge_t);
50 
51 uint32_t nxge_use_hw_property = 1;
52 uint32_t nxge_groups_per_port = 2;
53 
54 extern uint32_t nxge_use_partition;
55 extern uint32_t nxge_dma_obp_props_only;
56 
57 extern uint16_t nxge_rcr_timeout;
58 extern uint16_t nxge_rcr_threshold;
59 
60 extern uint_t nxge_rx_intr(void *, void *);
61 extern uint_t nxge_tx_intr(void *, void *);
62 extern uint_t nxge_mif_intr(void *, void *);
63 extern uint_t nxge_mac_intr(void *, void *);
64 extern uint_t nxge_syserr_intr(void *, void *);
65 extern void *nxge_list;
66 
67 #define	NXGE_SHARED_REG_SW_SIM
68 
69 #ifdef NXGE_SHARED_REG_SW_SIM
70 uint64_t global_dev_ctrl = 0;
71 #endif
72 
73 #define	MAX_SIBLINGS	NXGE_MAX_PORTS
74 
75 extern uint32_t nxge_rbr_size;
76 extern uint32_t nxge_rcr_size;
77 extern uint32_t nxge_tx_ring_size;
78 extern uint32_t nxge_rbr_spare_size;
79 
80 extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
81 
82 static uint8_t p2_tx_fair[2] = {12, 12};
83 static uint8_t p2_tx_equal[2] = {12, 12};
84 static uint8_t p4_tx_fair[4] = {6, 6, 6, 6};
85 static uint8_t p4_tx_equal[4] = {6, 6, 6, 6};
86 static uint8_t p2_rx_fair[2] = {8, 8};
87 static uint8_t p2_rx_equal[2] = {8, 8};
88 static uint8_t p4_rx_fair[4] = {4, 4, 4, 4};
89 static uint8_t p4_rx_equal[4] = {4, 4, 4, 4};
90 
91 static uint8_t p2_rdcgrp_fair[2] = {4, 4};
92 static uint8_t p2_rdcgrp_equal[2] = {4, 4};
93 static uint8_t p4_rdcgrp_fair[4] = {2, 2, 1, 1};
94 static uint8_t p4_rdcgrp_equal[4] = {2, 2, 2, 2};
95 static uint8_t p2_rdcgrp_cls[2] = {1, 1};
96 static uint8_t p4_rdcgrp_cls[4] = {1, 1, 1, 1};
97 
98 static uint8_t rx_4_1G[4] = {4, 4, 4, 4};
99 static uint8_t rx_2_10G[2] = {8, 8};
100 static uint8_t rx_2_10G_2_1G[4] = {6, 6, 2, 2};
101 static uint8_t rx_1_10G_3_1G[4] = {10, 2, 2, 2};
102 static uint8_t rx_1_1G_1_10G_2_1G[4] = {2, 10, 2, 2};
103 
104 static uint8_t tx_4_1G[4] = {6, 6, 6, 6};
105 static uint8_t tx_2_10G[2] = {12, 12};
106 static uint8_t tx_2_10G_2_1G[4] = {10, 10, 2, 2};
107 static uint8_t tx_1_10G_3_1G[4] = {12, 4, 4, 4};
108 static uint8_t tx_1_1G_1_10G_2_1G[4] = {4, 12, 4, 4};
109 
110 typedef enum {
111 	DEFAULT = 0,
112 	EQUAL,
113 	FAIR,
114 	CUSTOM,
115 	CLASSIFY,
116 	L2_CLASSIFY,
117 	L3_DISTRIBUTE,
118 	L3_CLASSIFY,
119 	L3_TCAM,
120 	CONFIG_TOKEN_NONE
121 } config_token_t;
122 
123 static char *token_names[] = {
124 	"default",
125 	"equal",
126 	"fair",
127 	"custom",
128 	"classify",
129 	"l2_classify",
130 	"l3_distribute",
131 	"l3_classify",
132 	"l3_tcam",
133 	"none",
134 };
135 
136 void nxge_virint_regs_dump(p_nxge_t nxgep);
137 
138 void
139 nxge_virint_regs_dump(p_nxge_t nxgep)
140 {
141 	npi_handle_t handle;
142 
143 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_virint_regs_dump"));
144 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
145 	(void) npi_vir_dump_pio_fzc_regs_one(handle);
146 	(void) npi_vir_dump_ldgnum(handle);
147 	(void) npi_vir_dump_ldsv(handle);
148 	(void) npi_vir_dump_imask0(handle);
149 	(void) npi_vir_dump_sid(handle);
150 	(void) npi_mac_dump_regs(handle, nxgep->function_num);
151 	(void) npi_ipp_dump_regs(handle, nxgep->function_num);
152 	(void) npi_fflp_dump_regs(handle);
153 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_virint_regs_dump"));
154 }
155 
156 /*
157  * For now: we hard coded the DMA configurations.
158  *	    and assume for one partition only.
159  *
160  *       OBP. Then OBP will pass this partition's
161  *	 Neptune configurations to fcode to create
162  *	 properties for them.
163  *
164  *	Since Neptune(PCI-E) and NIU (Niagara-2) has
165  *	different bus interfaces, the driver needs
166  *	to know which bus it is connected to.
167  *  	Ravinder suggested: create a device property.
168  *	In partitioning environment, we cannot
169  *	use .conf file (need to check). If conf changes,
170  *	need to reboot the system.
171  *	The following function assumes that we will
172  *	retrieve its properties from a virtualized nexus driver.
173  */
174 
175 nxge_status_t
176 nxge_cntlops(dev_info_t *dip, nxge_ctl_enum_t ctlop, void *arg, void *result)
177 {
178 	nxge_status_t status = NXGE_OK;
179 	int instance;
180 	p_nxge_t nxgep;
181 
182 #ifndef NXGE_SHARED_REG_SW_SIM
183 	npi_handle_t handle;
184 	uint16_t sr16, cr16;
185 #endif
186 	instance = ddi_get_instance(dip);
187 	NXGE_DEBUG_MSG((NULL, VIR_CTL, "Instance %d ", instance));
188 
189 	if (nxge_list == NULL) {
190 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
191 				"nxge_cntlops: nxge_list null"));
192 		return (NXGE_ERROR);
193 	}
194 	nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
195 	if (nxgep == NULL) {
196 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
197 				"nxge_cntlops: nxgep null"));
198 		return (NXGE_ERROR);
199 	}
200 #ifndef NXGE_SHARED_REG_SW_SIM
201 	handle = nxgep->npi_reg_handle;
202 #endif
203 	switch (ctlop) {
204 	case NXGE_CTLOPS_NIUTYPE:
205 		nxge_get_niu_property(dip, (niu_type_t *)result);
206 		return (status);
207 
208 	case NXGE_CTLOPS_GET_SHARED_REG:
209 #ifdef NXGE_SHARED_REG_SW_SIM
210 		*(uint64_t *)result = global_dev_ctrl;
211 		return (0);
212 #else
213 		status = npi_dev_func_sr_sr_get(handle, &sr16);
214 		*(uint16_t *)result = sr16;
215 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
216 			"nxge_cntlops: NXGE_CTLOPS_GET_SHARED_REG"));
217 		return (0);
218 #endif
219 
220 	case NXGE_CTLOPS_SET_SHARED_REG_LOCK:
221 #ifdef NXGE_SHARED_REG_SW_SIM
222 		global_dev_ctrl = *(uint64_t *)arg;
223 		return (0);
224 #else
225 		status = NPI_FAILURE;
226 		while (status != NPI_SUCCESS)
227 			status = npi_dev_func_sr_lock_enter(handle);
228 
229 		sr16 = *(uint16_t *)arg;
230 		status = npi_dev_func_sr_sr_set_only(handle, &sr16);
231 		status = npi_dev_func_sr_lock_free(handle);
232 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
233 			"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
234 		return (0);
235 #endif
236 
237 	case NXGE_CTLOPS_UPDATE_SHARED_REG:
238 #ifdef NXGE_SHARED_REG_SW_SIM
239 		global_dev_ctrl |= *(uint64_t *)arg;
240 		return (0);
241 #else
242 		status = NPI_FAILURE;
243 		while (status != NPI_SUCCESS)
244 			status = npi_dev_func_sr_lock_enter(handle);
245 		status = npi_dev_func_sr_sr_get(handle, &sr16);
246 		sr16 |= *(uint16_t *)arg;
247 		status = npi_dev_func_sr_sr_set_only(handle, &sr16);
248 		status = npi_dev_func_sr_lock_free(handle);
249 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
250 			"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
251 		return (0);
252 #endif
253 
254 	case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG_UL:
255 #ifdef NXGE_SHARED_REG_SW_SIM
256 		global_dev_ctrl |= *(uint64_t *)arg;
257 		return (0);
258 #else
259 		status = npi_dev_func_sr_sr_get(handle, &sr16);
260 		cr16 = *(uint16_t *)arg;
261 		sr16 &= ~cr16;
262 		status = npi_dev_func_sr_sr_set_only(handle, &sr16);
263 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
264 			"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
265 		return (0);
266 #endif
267 
268 	case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG:
269 #ifdef NXGE_SHARED_REG_SW_SIM
270 		global_dev_ctrl |= *(uint64_t *)arg;
271 		return (0);
272 #else
273 		status = NPI_FAILURE;
274 		while (status != NPI_SUCCESS)
275 			status = npi_dev_func_sr_lock_enter(handle);
276 		status = npi_dev_func_sr_sr_get(handle, &sr16);
277 		cr16 = *(uint16_t *)arg;
278 		sr16 &= ~cr16;
279 		status = npi_dev_func_sr_sr_set_only(handle, &sr16);
280 		status = npi_dev_func_sr_lock_free(handle);
281 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
282 			"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
283 		return (0);
284 #endif
285 
286 	case NXGE_CTLOPS_GET_LOCK_BLOCK:
287 #ifdef NXGE_SHARED_REG_SW_SIM
288 		global_dev_ctrl |= *(uint64_t *)arg;
289 		return (0);
290 #else
291 		status = NPI_FAILURE;
292 		while (status != NPI_SUCCESS)
293 			status = npi_dev_func_sr_lock_enter(handle);
294 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
295 			"nxge_cntlops: NXGE_CTLOPS_GET_LOCK_BLOCK"));
296 		return (0);
297 #endif
298 	case NXGE_CTLOPS_GET_LOCK_TRY:
299 #ifdef NXGE_SHARED_REG_SW_SIM
300 		global_dev_ctrl |= *(uint64_t *)arg;
301 		return (0);
302 #else
303 		status = npi_dev_func_sr_lock_enter(handle);
304 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
305 			"nxge_cntlops: NXGE_CTLOPS_GET_LOCK_TRY"));
306 		if (status == NPI_SUCCESS)
307 			return (NXGE_OK);
308 		else
309 			return (NXGE_ERROR);
310 #endif
311 	case NXGE_CTLOPS_FREE_LOCK:
312 #ifdef NXGE_SHARED_REG_SW_SIM
313 		global_dev_ctrl |= *(uint64_t *)arg;
314 		return (0);
315 #else
316 		status = npi_dev_func_sr_lock_free(handle);
317 		NXGE_DEBUG_MSG((NULL, VIR_CTL,
318 			"nxge_cntlops: NXGE_CTLOPS_GET_LOCK_FREE"));
319 		if (status == NPI_SUCCESS)
320 			return (NXGE_OK);
321 		else
322 			return (NXGE_ERROR);
323 #endif
324 
325 	default:
326 		status = NXGE_ERROR;
327 	}
328 
329 	return (status);
330 }
331 
332 void
333 nxge_common_lock_get(p_nxge_t nxgep)
334 {
335 	uint32_t status = NPI_FAILURE;
336 	npi_handle_t handle;
337 
338 #if	defined(NXGE_SHARE_REG_SW_SIM)
339 	return;
340 #endif
341 	handle = nxgep->npi_reg_handle;
342 	while (status != NPI_SUCCESS)
343 		status = npi_dev_func_sr_lock_enter(handle);
344 }
345 
346 void
347 nxge_common_lock_free(p_nxge_t nxgep)
348 {
349 	npi_handle_t handle;
350 
351 #if	defined(NXGE_SHARE_REG_SW_SIM)
352 	return;
353 #endif
354 	handle = nxgep->npi_reg_handle;
355 	(void) npi_dev_func_sr_lock_free(handle);
356 }
357 
358 
359 static void
360 nxge_get_niu_property(dev_info_t *dip, niu_type_t *niu_type)
361 {
362 	uchar_t *prop_val;
363 	uint_t prop_len;
364 
365 	*niu_type = NIU_TYPE_NONE;
366 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0,
367 			"niu-type", (uchar_t **)&prop_val,
368 			&prop_len) == DDI_PROP_SUCCESS) {
369 		if (strncmp("niu", (caddr_t)prop_val, (size_t)prop_len) == 0) {
370 			*niu_type = N2_NIU;
371 		}
372 		ddi_prop_free(prop_val);
373 	}
374 }
375 
376 static config_token_t
377 nxge_get_config_token(char *prop)
378 {
379 	config_token_t token = DEFAULT;
380 
381 	while (token < CONFIG_TOKEN_NONE) {
382 		if (strncmp(prop, token_names[token], 4) == 0)
383 			break;
384 		token++;
385 	}
386 	return (token);
387 }
388 
389 /* per port */
390 
391 static nxge_status_t
392 nxge_update_rxdma_grp_properties(p_nxge_t nxgep, config_token_t token,
393 	dev_info_t *s_dip[])
394 {
395 	nxge_status_t status = NXGE_OK;
396 	int ddi_status;
397 	int num_ports = nxgep->nports;
398 	int port, bits, j;
399 	uint8_t start_grp = 0, num_grps = 0;
400 	p_nxge_param_t param_arr;
401 	uint32_t grp_bitmap[MAX_SIBLINGS];
402 	int custom_start_grp[MAX_SIBLINGS];
403 	int custom_num_grp[MAX_SIBLINGS];
404 	uint8_t bad_config = B_FALSE;
405 	char *start_prop, *num_prop, *cfg_prop;
406 
407 	start_grp = 0;
408 	param_arr = nxgep->param_arr;
409 	start_prop = param_arr[param_rdc_grps_start].fcode_name;
410 	num_prop = param_arr[param_rx_rdc_grps].fcode_name;
411 
412 	switch (token) {
413 	case FAIR:
414 		cfg_prop = "fair";
415 		for (port = 0; port < num_ports; port++) {
416 			custom_num_grp[port] =
417 				(num_ports == 4) ?
418 				p4_rdcgrp_fair[port] :
419 				p2_rdcgrp_fair[port];
420 			custom_start_grp[port] = start_grp;
421 			start_grp += custom_num_grp[port];
422 		}
423 		break;
424 
425 	case EQUAL:
426 		cfg_prop = "equal";
427 		for (port = 0; port < num_ports; port++) {
428 			custom_num_grp[port] =
429 				(num_ports == 4) ?
430 				p4_rdcgrp_equal[port] :
431 				p2_rdcgrp_equal[port];
432 			custom_start_grp[port] = start_grp;
433 			start_grp += custom_num_grp[port];
434 		}
435 		break;
436 
437 
438 	case CLASSIFY:
439 		cfg_prop = "classify";
440 		for (port = 0; port < num_ports; port++) {
441 			custom_num_grp[port] = (num_ports == 4) ?
442 				p4_rdcgrp_cls[port] : p2_rdcgrp_cls[port];
443 			custom_start_grp[port] = start_grp;
444 			start_grp += custom_num_grp[port];
445 		}
446 		break;
447 
448 	case CUSTOM:
449 		cfg_prop = "custom";
450 		/* See if it is good config */
451 		num_grps = 0;
452 		for (port = 0; port < num_ports; port++) {
453 			custom_start_grp[port] =
454 				ddi_prop_get_int(DDI_DEV_T_NONE, s_dip[port],
455 				DDI_PROP_DONTPASS, start_prop, -1);
456 			if ((custom_start_grp[port] == -1) ||
457 				(custom_start_grp[port] >=
458 					NXGE_MAX_RDC_GRPS)) {
459 				bad_config = B_TRUE;
460 				break;
461 			}
462 			custom_num_grp[port] = ddi_prop_get_int(
463 				DDI_DEV_T_NONE,
464 				s_dip[port],
465 				DDI_PROP_DONTPASS,
466 				num_prop, -1);
467 
468 			if ((custom_num_grp[port] == -1) ||
469 				(custom_num_grp[port] >
470 					NXGE_MAX_RDC_GRPS) ||
471 				((custom_num_grp[port] +
472 						custom_start_grp[port]) >=
473 					NXGE_MAX_RDC_GRPS)) {
474 				bad_config = B_TRUE;
475 				break;
476 			}
477 			num_grps += custom_num_grp[port];
478 			if (num_grps > NXGE_MAX_RDC_GRPS) {
479 				bad_config = B_TRUE;
480 				break;
481 			}
482 			grp_bitmap[port] = 0;
483 			for (bits = 0;
484 				bits < custom_num_grp[port];
485 				bits++) {
486 				grp_bitmap[port] |=
487 					(1 << (bits + custom_start_grp[port]));
488 			}
489 
490 		}
491 
492 		if (bad_config == B_FALSE) {
493 			/* check for overlap */
494 			for (port = 0; port < num_ports - 1; port++) {
495 				for (j = port + 1; j < num_ports; j++) {
496 					if (grp_bitmap[port] &
497 						grp_bitmap[j]) {
498 						bad_config = B_TRUE;
499 						break;
500 					}
501 				}
502 				if (bad_config == B_TRUE)
503 					break;
504 			}
505 		}
506 		if (bad_config == B_TRUE) {
507 			/* use default config */
508 			for (port = 0; port < num_ports; port++) {
509 				custom_num_grp[port] =
510 					(num_ports == 4) ?
511 					p4_rx_fair[port] : p2_rx_fair[port];
512 				custom_start_grp[port] = start_grp;
513 				start_grp += custom_num_grp[port];
514 			}
515 		}
516 		break;
517 
518 	default:
519 		/* use default config */
520 		cfg_prop = "fair";
521 		for (port = 0; port < num_ports; port++) {
522 			custom_num_grp[port] = (num_ports == 4) ?
523 				p4_rx_fair[port] : p2_rx_fair[port];
524 			custom_start_grp[port] = start_grp;
525 			start_grp += custom_num_grp[port];
526 		}
527 		break;
528 	}
529 
530 	/* Now Update the rx properties */
531 	for (port = 0; port < num_ports; port++) {
532 		ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
533 			"rxdma-grp-cfg", cfg_prop);
534 		if (ddi_status != DDI_PROP_SUCCESS) {
535 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
536 					" property %s not updating",
537 					cfg_prop));
538 			status |= NXGE_DDI_FAILED;
539 		}
540 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
541 			num_prop, custom_num_grp[port]);
542 
543 		if (ddi_status != DDI_PROP_SUCCESS) {
544 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
545 					" property %s not updating",
546 					num_prop));
547 			status |= NXGE_DDI_FAILED;
548 		}
549 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
550 			start_prop, custom_start_grp[port]);
551 
552 		if (ddi_status != DDI_PROP_SUCCESS) {
553 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
554 					" property %s not updating",
555 					start_prop));
556 			status |= NXGE_DDI_FAILED;
557 		}
558 	}
559 	if (status & NXGE_DDI_FAILED)
560 		status |= NXGE_ERROR;
561 
562 	return (status);
563 }
564 
565 static nxge_status_t
566 nxge_update_rxdma_properties(p_nxge_t nxgep, config_token_t token,
567 	dev_info_t *s_dip[])
568 {
569 	nxge_status_t status = NXGE_OK;
570 	int ddi_status;
571 	int num_ports = nxgep->nports;
572 	int port, bits, j;
573 	uint8_t start_rdc = 0, num_rdc = 0;
574 	p_nxge_param_t param_arr;
575 	uint32_t rdc_bitmap[MAX_SIBLINGS];
576 	int custom_start_rdc[MAX_SIBLINGS];
577 	int custom_num_rdc[MAX_SIBLINGS];
578 	uint8_t bad_config = B_FALSE;
579 	int *prop_val;
580 	uint_t prop_len;
581 	char *start_rdc_prop, *num_rdc_prop, *cfg_prop;
582 
583 	start_rdc = 0;
584 	param_arr = nxgep->param_arr;
585 	start_rdc_prop = param_arr[param_rxdma_channels_begin].fcode_name;
586 	num_rdc_prop = param_arr[param_rxdma_channels].fcode_name;
587 
588 	switch (token) {
589 	case FAIR:
590 		cfg_prop = "fair";
591 		for (port = 0; port < num_ports; port++) {
592 			custom_num_rdc[port] = (num_ports == 4) ?
593 				p4_rx_fair[port] : p2_rx_fair[port];
594 			custom_start_rdc[port] = start_rdc;
595 			start_rdc += custom_num_rdc[port];
596 		}
597 		break;
598 
599 	case EQUAL:
600 		cfg_prop = "equal";
601 		for (port = 0; port < num_ports; port++) {
602 			custom_num_rdc[port] = (num_ports == 4) ?
603 				p4_rx_equal[port] :
604 				p2_rx_equal[port];
605 			custom_start_rdc[port] = start_rdc;
606 			start_rdc += custom_num_rdc[port];
607 		}
608 		break;
609 
610 	case CUSTOM:
611 		cfg_prop = "custom";
612 		/* See if it is good config */
613 		num_rdc = 0;
614 		for (port = 0; port < num_ports; port++) {
615 			ddi_status = ddi_prop_lookup_int_array(
616 				DDI_DEV_T_ANY,
617 				s_dip[port], 0,
618 				start_rdc_prop,
619 				&prop_val,
620 				&prop_len);
621 			if (ddi_status == DDI_SUCCESS)
622 				custom_start_rdc[port] = *prop_val;
623 			else {
624 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
625 						" %s custom start port %d"
626 						" read failed ",
627 						" rxdma-cfg", port));
628 				bad_config = B_TRUE;
629 				status |= NXGE_DDI_FAILED;
630 			}
631 			if ((custom_start_rdc[port] == -1) ||
632 				(custom_start_rdc[port] >=
633 					NXGE_MAX_RDCS)) {
634 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
635 						" %s custom start %d"
636 						" out of range %x ",
637 						" rxdma-cfg",
638 						port,
639 						custom_start_rdc[port]));
640 				bad_config = B_TRUE;
641 				break;
642 			}
643 			ddi_status = ddi_prop_lookup_int_array(
644 				DDI_DEV_T_ANY,
645 				s_dip[port],
646 				0,
647 				num_rdc_prop,
648 				&prop_val,
649 				&prop_len);
650 
651 			if (ddi_status == DDI_SUCCESS)
652 				custom_num_rdc[port] = *prop_val;
653 			else {
654 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
655 					" %s custom num port %d"
656 					" read failed ",
657 					"rxdma-cfg", port));
658 				bad_config = B_TRUE;
659 				status |= NXGE_DDI_FAILED;
660 			}
661 
662 			if ((custom_num_rdc[port] == -1) ||
663 					(custom_num_rdc[port] >
664 						NXGE_MAX_RDCS) ||
665 					((custom_num_rdc[port] +
666 						custom_start_rdc[port]) >
667 					NXGE_MAX_RDCS)) {
668 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
669 					" %s custom num %d"
670 					" out of range %x ",
671 					" rxdma-cfg",
672 					port, custom_num_rdc[port]));
673 				bad_config = B_TRUE;
674 				break;
675 			}
676 			num_rdc += custom_num_rdc[port];
677 			if (num_rdc > NXGE_MAX_RDCS) {
678 				bad_config = B_TRUE;
679 				break;
680 			}
681 			rdc_bitmap[port] = 0;
682 			for (bits = 0;
683 				bits < custom_num_rdc[port]; bits++) {
684 				rdc_bitmap[port] |=
685 					(1 << (bits + custom_start_rdc[port]));
686 			}
687 		}
688 
689 		if (bad_config == B_FALSE) {
690 			/* check for overlap */
691 			for (port = 0; port < num_ports - 1; port++) {
692 				for (j = port + 1; j < num_ports; j++) {
693 					if (rdc_bitmap[port] &
694 						rdc_bitmap[j]) {
695 						NXGE_DEBUG_MSG((nxgep,
696 							CFG_CTL,
697 							" rxdma-cfg"
698 							" property custom"
699 							" bit overlap"
700 							" %d %d ",
701 							port, j));
702 						bad_config = B_TRUE;
703 						break;
704 					}
705 				}
706 				if (bad_config == B_TRUE)
707 					break;
708 			}
709 		}
710 		if (bad_config == B_TRUE) {
711 			/* use default config */
712 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
713 				" rxdma-cfg property:"
714 				" bad custom config:"
715 				" use default"));
716 			for (port = 0; port < num_ports; port++) {
717 				custom_num_rdc[port] =
718 					(num_ports == 4) ?
719 					p4_rx_fair[port] :
720 					p2_rx_fair[port];
721 				custom_start_rdc[port] = start_rdc;
722 				start_rdc += custom_num_rdc[port];
723 			}
724 		}
725 		break;
726 
727 	default:
728 		/* use default config */
729 		cfg_prop = "fair";
730 		for (port = 0; port < num_ports; port++) {
731 			custom_num_rdc[port] = (num_ports == 4) ?
732 				p4_rx_fair[port] : p2_rx_fair[port];
733 			custom_start_rdc[port] = start_rdc;
734 			start_rdc += custom_num_rdc[port];
735 		}
736 		break;
737 	}
738 
739 	/* Now Update the rx properties */
740 	for (port = 0; port < num_ports; port++) {
741 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
742 			" update property rxdma-cfg with %s ", cfg_prop));
743 		ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
744 			"rxdma-cfg", cfg_prop);
745 		if (ddi_status != DDI_PROP_SUCCESS) {
746 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
747 				" property rxdma-cfg is not updating to %s",
748 				cfg_prop));
749 			status |= NXGE_DDI_FAILED;
750 		}
751 		NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
752 			num_rdc_prop, custom_num_rdc[port]));
753 
754 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
755 			num_rdc_prop, custom_num_rdc[port]);
756 
757 		if (ddi_status != DDI_PROP_SUCCESS) {
758 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
759 				" property %s not updating with %d",
760 				num_rdc_prop, custom_num_rdc[port]));
761 			status |= NXGE_DDI_FAILED;
762 		}
763 		NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
764 			start_rdc_prop, custom_start_rdc[port]));
765 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
766 			start_rdc_prop, custom_start_rdc[port]);
767 
768 		if (ddi_status != DDI_PROP_SUCCESS) {
769 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
770 				" property %s not updating with %d ",
771 				start_rdc_prop, custom_start_rdc[port]));
772 			status |= NXGE_DDI_FAILED;
773 		}
774 	}
775 	if (status & NXGE_DDI_FAILED)
776 		status |= NXGE_ERROR;
777 	return (status);
778 }
779 
780 static nxge_status_t
781 nxge_update_txdma_properties(p_nxge_t nxgep, config_token_t token,
782 	dev_info_t *s_dip[])
783 {
784 	nxge_status_t status = NXGE_OK;
785 	int ddi_status = DDI_SUCCESS;
786 	int num_ports = nxgep->nports;
787 	int port, bits, j;
788 	uint8_t start_tdc = 0, num_tdc = 0;
789 	p_nxge_param_t param_arr;
790 	uint32_t tdc_bitmap[MAX_SIBLINGS];
791 	int custom_start_tdc[MAX_SIBLINGS];
792 	int custom_num_tdc[MAX_SIBLINGS];
793 	uint8_t bad_config = B_FALSE;
794 	int *prop_val;
795 	uint_t prop_len;
796 	char *start_tdc_prop, *num_tdc_prop, *cfg_prop;
797 
798 	start_tdc = 0;
799 	param_arr = nxgep->param_arr;
800 	start_tdc_prop = param_arr[param_txdma_channels_begin].fcode_name;
801 	num_tdc_prop = param_arr[param_txdma_channels].fcode_name;
802 
803 	switch (token) {
804 	case FAIR:
805 		cfg_prop = "fair";
806 		for (port = 0; port < num_ports; port++) {
807 			custom_num_tdc[port] = (num_ports == 4) ?
808 				p4_tx_fair[port] : p2_tx_fair[port];
809 			custom_start_tdc[port] = start_tdc;
810 			start_tdc += custom_num_tdc[port];
811 		}
812 		break;
813 
814 	case EQUAL:
815 		cfg_prop = "equal";
816 		for (port = 0; port < num_ports; port++) {
817 			custom_num_tdc[port] = (num_ports == 4) ?
818 				p4_tx_equal[port] : p2_tx_equal[port];
819 			custom_start_tdc[port] = start_tdc;
820 			start_tdc += custom_num_tdc[port];
821 		}
822 		break;
823 
824 	case CUSTOM:
825 		cfg_prop = "custom";
826 		/* See if it is good config */
827 		num_tdc = 0;
828 		for (port = 0; port < num_ports; port++) {
829 			ddi_status = ddi_prop_lookup_int_array(
830 				DDI_DEV_T_ANY, s_dip[port], 0, start_tdc_prop,
831 				&prop_val, &prop_len);
832 			if (ddi_status == DDI_SUCCESS)
833 				custom_start_tdc[port] = *prop_val;
834 			else {
835 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
836 					" %s custom start port %d"
837 					" read failed ", " txdma-cfg", port));
838 				bad_config = B_TRUE;
839 				status |= NXGE_DDI_FAILED;
840 			}
841 
842 			if ((custom_start_tdc[port] == -1) ||
843 					(custom_start_tdc[port] >=
844 					NXGE_MAX_RDCS)) {
845 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
846 					" %s custom start %d"
847 					" out of range %x ", " txdma-cfg",
848 					port, custom_start_tdc[port]));
849 				bad_config = B_TRUE;
850 				break;
851 			}
852 
853 			ddi_status = ddi_prop_lookup_int_array(
854 				DDI_DEV_T_ANY, s_dip[port], 0, num_tdc_prop,
855 				&prop_val, &prop_len);
856 			if (ddi_status == DDI_SUCCESS)
857 				custom_num_tdc[port] = *prop_val;
858 			else {
859 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
860 					" %s custom num port %d"
861 					" read failed ", " txdma-cfg", port));
862 				bad_config = B_TRUE;
863 				status |= NXGE_DDI_FAILED;
864 			}
865 
866 			if ((custom_num_tdc[port] == -1) ||
867 					(custom_num_tdc[port] >
868 						NXGE_MAX_TDCS) ||
869 					((custom_num_tdc[port] +
870 						custom_start_tdc[port]) >
871 					NXGE_MAX_TDCS)) {
872 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
873 					" %s custom num %d"
874 					" out of range %x ", " rxdma-cfg",
875 					port, custom_num_tdc[port]));
876 				bad_config = B_TRUE;
877 				break;
878 			}
879 			num_tdc += custom_num_tdc[port];
880 			if (num_tdc > NXGE_MAX_TDCS) {
881 				bad_config = B_TRUE;
882 				break;
883 			}
884 			tdc_bitmap[port] = 0;
885 			for (bits = 0;
886 				bits < custom_num_tdc[port]; bits++) {
887 				tdc_bitmap[port] |=
888 					(1 <<
889 					(bits + custom_start_tdc[port]));
890 			}
891 
892 		}
893 
894 		if (bad_config == B_FALSE) {
895 			/* check for overlap */
896 			for (port = 0; port < num_ports - 1; port++) {
897 				for (j = port + 1; j < num_ports; j++) {
898 					if (tdc_bitmap[port] &
899 						tdc_bitmap[j]) {
900 						NXGE_DEBUG_MSG((nxgep, CFG_CTL,
901 							" rxdma-cfg"
902 							" property custom"
903 							" bit overlap"
904 							" %d %d ",
905 							port, j));
906 						bad_config = B_TRUE;
907 						break;
908 					}
909 				}
910 				if (bad_config == B_TRUE)
911 					break;
912 			}
913 		}
914 		if (bad_config == B_TRUE) {
915 			/* use default config */
916 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
917 				" txdma-cfg property:"
918 				" bad custom config:" " use default"));
919 
920 			for (port = 0; port < num_ports; port++) {
921 				custom_num_tdc[port] = (num_ports == 4) ?
922 					p4_tx_fair[port] : p2_tx_fair[port];
923 				custom_start_tdc[port] = start_tdc;
924 				start_tdc += custom_num_tdc[port];
925 			}
926 		}
927 		break;
928 
929 	default:
930 		/* use default config */
931 		cfg_prop = "fair";
932 		for (port = 0; port < num_ports; port++) {
933 			custom_num_tdc[port] = (num_ports == 4) ?
934 				p4_tx_fair[port] : p2_tx_fair[port];
935 			custom_start_tdc[port] = start_tdc;
936 			start_tdc += custom_num_tdc[port];
937 		}
938 		break;
939 	}
940 
941 	/* Now Update the tx properties */
942 	for (port = 0; port < num_ports; port++) {
943 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
944 			" update property txdma-cfg with %s ", cfg_prop));
945 		ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
946 			"txdma-cfg", cfg_prop);
947 		if (ddi_status != DDI_PROP_SUCCESS) {
948 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
949 				" property txdma-cfg is not updating to %s",
950 				cfg_prop));
951 			status |= NXGE_DDI_FAILED;
952 		}
953 		NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
954 			num_tdc_prop, custom_num_tdc[port]));
955 
956 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
957 			num_tdc_prop, custom_num_tdc[port]);
958 
959 		if (ddi_status != DDI_PROP_SUCCESS) {
960 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
961 				" property %s not updating with %d",
962 				num_tdc_prop,
963 				custom_num_tdc[port]));
964 			status |= NXGE_DDI_FAILED;
965 		}
966 
967 		NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
968 			start_tdc_prop, custom_start_tdc[port]));
969 
970 		ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
971 			start_tdc_prop, custom_start_tdc[port]);
972 		if (ddi_status != DDI_PROP_SUCCESS) {
973 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
974 				" property %s not updating with %d ",
975 				start_tdc_prop, custom_start_tdc[port]));
976 			status |= NXGE_DDI_FAILED;
977 		}
978 	}
979 	if (status & NXGE_DDI_FAILED)
980 		status |= NXGE_ERROR;
981 	return (status);
982 }
983 
984 static nxge_status_t
985 nxge_update_cfg_properties(p_nxge_t nxgep, uint32_t flags,
986 	config_token_t token, dev_info_t *s_dip[])
987 {
988 	nxge_status_t status = NXGE_OK;
989 
990 	switch (flags) {
991 	case COMMON_TXDMA_CFG:
992 		if (nxge_dma_obp_props_only == 0)
993 			status = nxge_update_txdma_properties(nxgep,
994 				token, s_dip);
995 		break;
996 	case COMMON_RXDMA_CFG:
997 		if (nxge_dma_obp_props_only == 0)
998 			status = nxge_update_rxdma_properties(nxgep,
999 				token, s_dip);
1000 
1001 		break;
1002 	case COMMON_RXDMA_GRP_CFG:
1003 		status = nxge_update_rxdma_grp_properties(nxgep,
1004 			token, s_dip);
1005 		break;
1006 	default:
1007 		return (NXGE_ERROR);
1008 	}
1009 	return (status);
1010 }
1011 
1012 /*
1013  * verify consistence.
1014  * (May require publishing the properties on all the ports.
1015  *
1016  * What if properties are published on function 0 device only?
1017  *
1018  *
1019  * rxdma-cfg, txdma-cfg, rxdma-grp-cfg (required )
1020  * What about class configs?
1021  *
1022  * If consistent, update the property on all the siblings.
1023  * set  a flag on hardware shared register
1024  * The rest of the siblings will check the flag
1025  * if the flag is set, they will use the updated property
1026  * without doing any validation.
1027  */
1028 
1029 nxge_status_t
1030 nxge_cfg_verify_set_classify_prop(p_nxge_t nxgep, char *prop,
1031 	uint64_t known_cfg, uint32_t override, dev_info_t *c_dip[])
1032 {
1033 	nxge_status_t status = NXGE_OK;
1034 	int ddi_status = DDI_SUCCESS;
1035 	int i = 0, found = 0, update_prop = B_TRUE;
1036 	int *cfg_val;
1037 	uint_t new_value, cfg_value[MAX_SIBLINGS];
1038 	uint_t prop_len;
1039 	uint_t known_cfg_value;
1040 
1041 	known_cfg_value = (uint_t)known_cfg;
1042 
1043 	if (override == B_TRUE) {
1044 		new_value = known_cfg_value;
1045 		for (i = 0; i < nxgep->nports; i++) {
1046 			ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE,
1047 				c_dip[i], prop, new_value);
1048 #ifdef NXGE_DEBUG_ERROR
1049 			if (ddi_status != DDI_PROP_SUCCESS)
1050 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1051 					" property %s failed update ", prop));
1052 #endif
1053 		}
1054 		if (ddi_status != DDI_PROP_SUCCESS)
1055 			return (NXGE_ERROR | NXGE_DDI_FAILED);
1056 	}
1057 	for (i = 0; i < nxgep->nports; i++) {
1058 		cfg_value[i] = known_cfg_value;
1059 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, c_dip[i], 0,
1060 				prop, &cfg_val,
1061 				&prop_len) == DDI_PROP_SUCCESS) {
1062 			cfg_value[i] = *cfg_val;
1063 			ddi_prop_free(cfg_val);
1064 			found++;
1065 		}
1066 	}
1067 
1068 	if (found != i) {
1069 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1070 			" property %s not specified on all ports", prop));
1071 		if (found == 0) {
1072 			/* not specified: Use default */
1073 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1074 				" property %s not specified on any port:"
1075 				" Using default", prop));
1076 			new_value = known_cfg_value;
1077 		} else {
1078 			/* specified on some */
1079 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1080 				" property %s not specified"
1081 				" on some ports: Using default", prop));
1082 			/* ? use p0 value instead ? */
1083 			new_value = known_cfg_value;
1084 		}
1085 	} else {
1086 		/* check type and consistence */
1087 		/* found on all devices */
1088 		for (i = 1; i < found; i++) {
1089 			if (cfg_value[i] != cfg_value[i - 1]) {
1090 				NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1091 					" property %s inconsistent:"
1092 					" Using default", prop));
1093 				new_value = known_cfg_value;
1094 				break;
1095 			}
1096 			/*
1097 			 * Found on all the ports and consistent. Nothing to
1098 			 * do.
1099 			 */
1100 			update_prop = B_FALSE;
1101 		}
1102 	}
1103 
1104 	if (update_prop == B_TRUE) {
1105 		for (i = 0; i < nxgep->nports; i++) {
1106 			ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE,
1107 				c_dip[i], prop, new_value);
1108 #ifdef NXGE_DEBUG_ERROR
1109 			if (ddi_status != DDI_SUCCESS)
1110 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1111 					" property %s not updating with %d"
1112 					" Using default",
1113 					prop, new_value));
1114 #endif
1115 			if (ddi_status != DDI_PROP_SUCCESS)
1116 				status |= NXGE_DDI_FAILED;
1117 		}
1118 	}
1119 	if (status & NXGE_DDI_FAILED)
1120 		status |= NXGE_ERROR;
1121 
1122 	return (status);
1123 }
1124 
1125 static uint64_t
1126 nxge_class_get_known_cfg(p_nxge_t nxgep, int class_prop, int rx_quick_cfg)
1127 {
1128 	int start_prop;
1129 	uint64_t cfg_value;
1130 	p_nxge_param_t param_arr;
1131 
1132 	param_arr = nxgep->param_arr;
1133 	cfg_value = param_arr[class_prop].value;
1134 	start_prop = param_h1_init_value;
1135 
1136 	/* update the properties per quick config */
1137 	switch (rx_quick_cfg) {
1138 	case CFG_L3_WEB:
1139 	case CFG_L3_DISTRIBUTE:
1140 		cfg_value = nxge_classify_get_cfg_value(nxgep,
1141 			rx_quick_cfg, class_prop - start_prop);
1142 		break;
1143 	default:
1144 		cfg_value = param_arr[class_prop].value;
1145 		break;
1146 	}
1147 	return (cfg_value);
1148 }
1149 
1150 static nxge_status_t
1151 nxge_cfg_verify_set_classify(p_nxge_t nxgep, dev_info_t *c_dip[])
1152 {
1153 	nxge_status_t status = NXGE_OK;
1154 	int rx_quick_cfg, class_prop, start_prop, end_prop;
1155 	char *prop_name;
1156 	int override = B_TRUE;
1157 	uint64_t cfg_value;
1158 	p_nxge_param_t param_arr;
1159 
1160 	param_arr = nxgep->param_arr;
1161 	rx_quick_cfg = param_arr[param_rx_quick_cfg].value;
1162 	start_prop = param_h1_init_value;
1163 	end_prop = param_class_opt_ipv6_sctp;
1164 
1165 	/* update the properties per quick config */
1166 	if (rx_quick_cfg == CFG_NOT_SPECIFIED)
1167 		override = B_FALSE;
1168 
1169 	/*
1170 	 * these parameter affect the classification outcome.
1171 	 * these parameters are used to configure the Flow key and
1172 	 * the TCAM key for each of the IP classes.
1173 	 * Included here are also the H1 and H2 initial values
1174 	 * which affect the distribution as well as final hash value
1175 	 * (hence the offset into RDC table and FCRAM bucket location)
1176 	 *
1177 	 */
1178 	for (class_prop = start_prop; class_prop <= end_prop; class_prop++) {
1179 		prop_name = param_arr[class_prop].fcode_name;
1180 		cfg_value = nxge_class_get_known_cfg(nxgep,
1181 			class_prop, rx_quick_cfg);
1182 		status = nxge_cfg_verify_set_classify_prop(nxgep, prop_name,
1183 			cfg_value, override, c_dip);
1184 	}
1185 
1186 	/*
1187 	 * these properties do not affect the actual classification outcome.
1188 	 * used to enable/disable or tune the fflp hardware
1189 	 *
1190 	 * fcram_access_ratio, tcam_access_ratio, tcam_enable, llc_snap_enable
1191 	 *
1192 	 */
1193 	override = B_FALSE;
1194 	for (class_prop = param_fcram_access_ratio;
1195 			class_prop <= param_llc_snap_enable; class_prop++) {
1196 		prop_name = param_arr[class_prop].fcode_name;
1197 		cfg_value = param_arr[class_prop].value;
1198 		status = nxge_cfg_verify_set_classify_prop(nxgep, prop_name,
1199 			cfg_value, override, c_dip);
1200 	}
1201 
1202 	return (status);
1203 }
1204 
1205 nxge_status_t
1206 nxge_cfg_verify_set(p_nxge_t nxgep, uint32_t flag)
1207 {
1208 	nxge_status_t status = NXGE_OK;
1209 	int i = 0, found = 0;
1210 	int num_siblings;
1211 	dev_info_t *c_dip[MAX_SIBLINGS + 1];
1212 	char *prop_val[MAX_SIBLINGS];
1213 	config_token_t c_token[MAX_SIBLINGS];
1214 	char *prop;
1215 
1216 	if (nxge_dma_obp_props_only)
1217 		return (NXGE_OK);
1218 
1219 	num_siblings = 0;
1220 	c_dip[num_siblings] = ddi_get_child(nxgep->p_dip);
1221 	while (c_dip[num_siblings]) {
1222 		c_dip[num_siblings + 1] =
1223 			ddi_get_next_sibling(c_dip[num_siblings]);
1224 		num_siblings++;
1225 	}
1226 
1227 	switch (flag) {
1228 	case COMMON_TXDMA_CFG:
1229 		prop = "txdma-cfg";
1230 		break;
1231 	case COMMON_RXDMA_CFG:
1232 		prop = "rxdma-cfg";
1233 		break;
1234 	case COMMON_RXDMA_GRP_CFG:
1235 		prop = "rxdma-grp-cfg";
1236 		break;
1237 	case COMMON_CLASS_CFG:
1238 		status = nxge_cfg_verify_set_classify(nxgep, c_dip);
1239 		return (status);
1240 	default:
1241 		return (NXGE_ERROR);
1242 	}
1243 
1244 	i = 0;
1245 	while (i < num_siblings) {
1246 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, c_dip[i], 0, prop,
1247 				(char **)&prop_val[i]) == DDI_PROP_SUCCESS) {
1248 			c_token[i] = nxge_get_config_token(prop_val[i]);
1249 			ddi_prop_free(prop_val[i]);
1250 			found++;
1251 		} else
1252 			c_token[i] = CONFIG_TOKEN_NONE;
1253 		i++;
1254 	}
1255 
1256 	if (found != i) {
1257 		if (found == 0) {
1258 			/* not specified: Use default */
1259 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1260 				" property %s not specified on any port:"
1261 					" Using default", prop));
1262 
1263 			status = nxge_update_cfg_properties(nxgep,
1264 				flag, FAIR, c_dip);
1265 			return (status);
1266 		} else {
1267 			/*
1268 			 * if  the convention is to use function 0 device then
1269 			 * populate the other devices with this configuration.
1270 			 *
1271 			 * The other alternative is to use the default config.
1272 			 */
1273 			/* not specified: Use default */
1274 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1275 				" property %s not specified on some ports:"
1276 				" Using default", prop));
1277 			status = nxge_update_cfg_properties(nxgep,
1278 				flag, FAIR, c_dip);
1279 			return (status);
1280 		}
1281 	}
1282 
1283 	/* check type and consistence */
1284 	/* found on all devices */
1285 	for (i = 1; i < found; i++) {
1286 		if (c_token[i] != c_token[i - 1]) {
1287 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1288 				" property %s inconsistent:"
1289 				" Using default", prop));
1290 			status = nxge_update_cfg_properties(nxgep,
1291 				flag, FAIR, c_dip);
1292 			return (status);
1293 		}
1294 	}
1295 
1296 	/*
1297 	 * Found on all the ports check if it is custom configuration. if
1298 	 * custom, then verify consistence
1299 	 *
1300 	 * finally create soft properties
1301 	 */
1302 	status = nxge_update_cfg_properties(nxgep, flag, c_token[0], c_dip);
1303 	return (status);
1304 }
1305 
1306 nxge_status_t
1307 nxge_cfg_verify_set_quick_config(p_nxge_t nxgep)
1308 {
1309 	nxge_status_t status = NXGE_OK;
1310 	int ddi_status = DDI_SUCCESS;
1311 	char *prop_val;
1312 	char *rx_prop;
1313 	char *prop;
1314 	uint32_t cfg_value = CFG_NOT_SPECIFIED;
1315 	p_nxge_param_t param_arr;
1316 
1317 	param_arr = nxgep->param_arr;
1318 	rx_prop = param_arr[param_rx_quick_cfg].fcode_name;
1319 
1320 	prop = "rx-quick-cfg";
1321 
1322 	/*
1323 	 * good value are
1324 	 *
1325 	 * "web-server" "generic-server" "l3-classify" "flow-classify"
1326 	 */
1327 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
1328 			prop, (char **)&prop_val) != DDI_PROP_SUCCESS) {
1329 		NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1330 			" property %s not specified: using default ", prop));
1331 		cfg_value = CFG_NOT_SPECIFIED;
1332 	} else {
1333 		cfg_value = CFG_L3_DISTRIBUTE;
1334 		if (strncmp("web-server", (caddr_t)prop_val, 8) == 0) {
1335 			cfg_value = CFG_L3_WEB;
1336 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1337 				" %s: web server ", prop));
1338 		}
1339 		if (strncmp("generic-server", (caddr_t)prop_val, 8) == 0) {
1340 			cfg_value = CFG_L3_DISTRIBUTE;
1341 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
1342 				" %s: distribute ", prop));
1343 		}
1344 		/* more */
1345 		ddi_prop_free(prop_val);
1346 	}
1347 
1348 	ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
1349 		rx_prop, cfg_value);
1350 	if (ddi_status != DDI_PROP_SUCCESS)
1351 		status |= NXGE_DDI_FAILED;
1352 
1353 	/* now handle specified cases: */
1354 	if (status & NXGE_DDI_FAILED)
1355 		status |= NXGE_ERROR;
1356 	return (status);
1357 }
1358 
1359 static void
1360 nxge_use_cfg_link_cfg(p_nxge_t nxgep)
1361 {
1362 	int *prop_val;
1363 	uint_t prop_len;
1364 	dev_info_t *dip;
1365 	int speed;
1366 	int duplex;
1367 	int adv_autoneg_cap;
1368 	int adv_10gfdx_cap;
1369 	int adv_10ghdx_cap;
1370 	int adv_1000fdx_cap;
1371 	int adv_1000hdx_cap;
1372 	int adv_100fdx_cap;
1373 	int adv_100hdx_cap;
1374 	int adv_10fdx_cap;
1375 	int adv_10hdx_cap;
1376 	int status = DDI_SUCCESS;
1377 
1378 	dip = nxgep->dip;
1379 
1380 	/*
1381 	 * first find out the card type and the supported link speeds and
1382 	 * features
1383 	 */
1384 	/* add code for card type */
1385 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-autoneg-cap",
1386 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1387 		ddi_prop_free(prop_val);
1388 		return;
1389 	}
1390 
1391 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10gfdx-cap",
1392 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1393 		ddi_prop_free(prop_val);
1394 		return;
1395 	}
1396 
1397 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000hdx-cap",
1398 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1399 		ddi_prop_free(prop_val);
1400 		return;
1401 	}
1402 
1403 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000fdx-cap",
1404 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1405 		ddi_prop_free(prop_val);
1406 		return;
1407 	}
1408 
1409 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100fdx-cap",
1410 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1411 		ddi_prop_free(prop_val);
1412 		return;
1413 	}
1414 
1415 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100hdx-cap",
1416 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1417 		ddi_prop_free(prop_val);
1418 		return;
1419 	}
1420 
1421 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10fdx-cap",
1422 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1423 		ddi_prop_free(prop_val);
1424 		return;
1425 	}
1426 
1427 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10hdx-cap",
1428 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1429 		ddi_prop_free(prop_val);
1430 		return;
1431 	}
1432 
1433 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "speed",
1434 			(uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1435 		if (strncmp("10000", (caddr_t)prop_val,
1436 				(size_t)prop_len) == 0) {
1437 			speed = 10000;
1438 		} else if (strncmp("1000", (caddr_t)prop_val,
1439 				(size_t)prop_len) == 0) {
1440 			speed = 1000;
1441 		} else if (strncmp("100", (caddr_t)prop_val,
1442 				(size_t)prop_len) == 0) {
1443 			speed = 100;
1444 		} else if (strncmp("10", (caddr_t)prop_val,
1445 				(size_t)prop_len) == 0) {
1446 			speed = 10;
1447 		} else if (strncmp("auto", (caddr_t)prop_val,
1448 				(size_t)prop_len) == 0) {
1449 			speed = 0;
1450 		} else {
1451 			NXGE_ERROR_MSG((nxgep, NXGE_NOTE,
1452 				"speed property is invalid reverting to auto"));
1453 			speed = 0;
1454 		}
1455 		ddi_prop_free(prop_val);
1456 	} else
1457 		speed = 0;
1458 
1459 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "duplex",
1460 			(uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1461 		if (strncmp("full", (caddr_t)prop_val,
1462 				(size_t)prop_len) == 0) {
1463 			duplex = 2;
1464 		} else if (strncmp("half", (caddr_t)prop_val,
1465 				(size_t)prop_len) == 0) {
1466 			duplex = 1;
1467 		} else if (strncmp("auto", (caddr_t)prop_val,
1468 				(size_t)prop_len) == 0) {
1469 			duplex = 0;
1470 		} else {
1471 			NXGE_ERROR_MSG((nxgep, NXGE_NOTE,
1472 				"duplex property is invalid"
1473 				" reverting to auto"));
1474 			duplex = 0;
1475 		}
1476 		ddi_prop_free(prop_val);
1477 	} else
1478 		duplex = 0;
1479 
1480 	adv_autoneg_cap = (speed == 0) || (duplex == 0);
1481 	if (adv_autoneg_cap == 0) {
1482 		adv_10gfdx_cap = ((speed == 10000) && (duplex == 2));
1483 		adv_10ghdx_cap = adv_10gfdx_cap;
1484 		adv_10ghdx_cap |= ((speed == 10000) && (duplex == 1));
1485 		adv_1000fdx_cap = adv_10ghdx_cap;
1486 		adv_1000fdx_cap |= ((speed == 1000) && (duplex == 2));
1487 		adv_1000hdx_cap = adv_1000fdx_cap;
1488 		adv_1000hdx_cap |= ((speed == 1000) && (duplex == 1));
1489 		adv_100fdx_cap = adv_1000hdx_cap;
1490 		adv_100fdx_cap |= ((speed == 100) && (duplex == 2));
1491 		adv_100hdx_cap = adv_100fdx_cap;
1492 		adv_100hdx_cap |= ((speed == 100) && (duplex == 1));
1493 		adv_10fdx_cap = adv_100hdx_cap;
1494 		adv_10fdx_cap |= ((speed == 10) && (duplex == 2));
1495 		adv_10hdx_cap = adv_10fdx_cap;
1496 		adv_10hdx_cap |= ((speed == 10) && (duplex == 1));
1497 	} else if (speed == 0) {
1498 		adv_10gfdx_cap = (duplex == 2);
1499 		adv_10ghdx_cap = (duplex == 1);
1500 		adv_1000fdx_cap = (duplex == 2);
1501 		adv_1000hdx_cap = (duplex == 1);
1502 		adv_100fdx_cap = (duplex == 2);
1503 		adv_100hdx_cap = (duplex == 1);
1504 		adv_10fdx_cap = (duplex == 2);
1505 		adv_10hdx_cap = (duplex == 1);
1506 	}
1507 	if (duplex == 0) {
1508 		adv_10gfdx_cap = (speed == 0);
1509 		adv_10gfdx_cap |= (speed == 10000);
1510 		adv_10ghdx_cap = adv_10gfdx_cap;
1511 		adv_10ghdx_cap |= (speed == 10000);
1512 		adv_1000fdx_cap = adv_10ghdx_cap;
1513 		adv_1000fdx_cap |= (speed == 1000);
1514 		adv_1000hdx_cap = adv_1000fdx_cap;
1515 		adv_1000hdx_cap |= (speed == 1000);
1516 		adv_100fdx_cap = adv_1000hdx_cap;
1517 		adv_100fdx_cap |= (speed == 100);
1518 		adv_100hdx_cap = adv_100fdx_cap;
1519 		adv_100hdx_cap |= (speed == 100);
1520 		adv_10fdx_cap = adv_100hdx_cap;
1521 		adv_10fdx_cap |= (speed == 10);
1522 		adv_10hdx_cap = adv_10fdx_cap;
1523 		adv_10hdx_cap |= (speed == 10);
1524 	}
1525 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1526 		"adv-autoneg-cap", &adv_autoneg_cap, 1);
1527 	if (status)
1528 		return;
1529 
1530 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1531 		"adv-10gfdx-cap", &adv_10gfdx_cap, 1);
1532 	if (status)
1533 		goto nxge_map_myargs_to_gmii_fail1;
1534 
1535 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1536 		"adv-10ghdx-cap", &adv_10ghdx_cap, 1);
1537 	if (status)
1538 		goto nxge_map_myargs_to_gmii_fail2;
1539 
1540 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1541 		"adv-1000fdx-cap", &adv_1000fdx_cap, 1);
1542 	if (status)
1543 		goto nxge_map_myargs_to_gmii_fail3;
1544 
1545 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1546 		"adv-1000hdx-cap", &adv_1000hdx_cap, 1);
1547 	if (status)
1548 		goto nxge_map_myargs_to_gmii_fail4;
1549 
1550 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1551 		"adv-100fdx-cap", &adv_100fdx_cap, 1);
1552 	if (status)
1553 		goto nxge_map_myargs_to_gmii_fail5;
1554 
1555 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1556 		"adv-100hdx-cap", &adv_100hdx_cap, 1);
1557 	if (status)
1558 		goto nxge_map_myargs_to_gmii_fail6;
1559 
1560 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1561 		"adv-10fdx-cap", &adv_10fdx_cap, 1);
1562 	if (status)
1563 		goto nxge_map_myargs_to_gmii_fail7;
1564 
1565 	status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1566 		"adv-10hdx-cap", &adv_10hdx_cap, 1);
1567 	if (status)
1568 		goto nxge_map_myargs_to_gmii_fail8;
1569 
1570 	return;
1571 
1572 nxge_map_myargs_to_gmii_fail9:
1573 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10hdx-cap");
1574 
1575 nxge_map_myargs_to_gmii_fail8:
1576 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10fdx-cap");
1577 
1578 nxge_map_myargs_to_gmii_fail7:
1579 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100hdx-cap");
1580 
1581 nxge_map_myargs_to_gmii_fail6:
1582 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100fdx-cap");
1583 
1584 nxge_map_myargs_to_gmii_fail5:
1585 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000hdx-cap");
1586 
1587 nxge_map_myargs_to_gmii_fail4:
1588 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000fdx-cap");
1589 
1590 nxge_map_myargs_to_gmii_fail3:
1591 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10ghdx-cap");
1592 
1593 nxge_map_myargs_to_gmii_fail2:
1594 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10gfdx-cap");
1595 
1596 nxge_map_myargs_to_gmii_fail1:
1597 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-autoneg-cap");
1598 }
1599 
1600 nxge_status_t
1601 nxge_get_config_properties(p_nxge_t nxgep)
1602 {
1603 	nxge_status_t status = NXGE_OK;
1604 	p_nxge_hw_list_t hw_p;
1605 
1606 	NXGE_DEBUG_MSG((nxgep, VPD_CTL, " ==> nxge_get_config_properties"));
1607 
1608 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1609 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1610 			" nxge_get_config_properties:"
1611 			" common hardware not set", nxgep->niu_type));
1612 		return (NXGE_ERROR);
1613 	}
1614 
1615 	/*
1616 	 * Get info on how many ports Neptune card has.
1617 	 */
1618 	nxgep->nports = nxge_get_nports(nxgep);
1619 	if (nxgep->nports <= 0) {
1620 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1621 		    "<==nxge_get_config_properties: Invalid Neptune type 0x%x",
1622 		    nxgep->niu_type));
1623 		return (NXGE_ERROR);
1624 	}
1625 	nxgep->classifier.tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
1626 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1627 		nxgep->classifier.tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
1628 	}
1629 	if (nxgep->function_num >= nxgep->nports) {
1630 		return (NXGE_ERROR);
1631 	}
1632 
1633 	status = nxge_get_mac_addr_properties(nxgep);
1634 	if (status != NXGE_OK)
1635 		return (NXGE_ERROR);
1636 
1637 	/*
1638 	 * read the configuration type. If none is specified, used default.
1639 	 * Config types: equal: (default) DMA channels, RDC groups, TCAM, FCRAM
1640 	 * are shared equally across all the ports.
1641 	 *
1642 	 * Fair: DMA channels, RDC groups, TCAM, FCRAM are shared proportional
1643 	 * to the port speed.
1644 	 *
1645 	 *
1646 	 * custom: DMA channels, RDC groups, TCAM, FCRAM partition is
1647 	 * specified in nxge.conf. Need to read each parameter and set
1648 	 * up the parameters in nxge structures.
1649 	 *
1650 	 */
1651 	switch (nxgep->niu_type) {
1652 	case N2_NIU:
1653 		NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1654 			" ==> nxge_get_config_properties: N2"));
1655 		MUTEX_ENTER(&hw_p->nxge_cfg_lock);
1656 		if ((hw_p->flags & COMMON_CFG_VALID) !=
1657 			COMMON_CFG_VALID) {
1658 			status = nxge_cfg_verify_set(nxgep,
1659 				COMMON_RXDMA_GRP_CFG);
1660 			status = nxge_cfg_verify_set(nxgep,
1661 				COMMON_CLASS_CFG);
1662 			hw_p->flags |= COMMON_CFG_VALID;
1663 		}
1664 		MUTEX_EXIT(&hw_p->nxge_cfg_lock);
1665 		status = nxge_use_cfg_n2niu_properties(nxgep);
1666 		break;
1667 	default:
1668 		if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1669 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1670 			    " nxge_get_config_properties:"
1671 			    " unknown NIU type 0x%x", nxgep->niu_type));
1672 			return (NXGE_ERROR);
1673 		}
1674 
1675 		NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1676 			" ==> nxge_get_config_properties: Neptune"));
1677 		status = nxge_cfg_verify_set_quick_config(nxgep);
1678 		MUTEX_ENTER(&hw_p->nxge_cfg_lock);
1679 		if ((hw_p->flags & COMMON_CFG_VALID) !=
1680 			COMMON_CFG_VALID) {
1681 			status = nxge_cfg_verify_set(nxgep,
1682 				COMMON_TXDMA_CFG);
1683 			status = nxge_cfg_verify_set(nxgep,
1684 				COMMON_RXDMA_CFG);
1685 			status = nxge_cfg_verify_set(nxgep,
1686 				COMMON_RXDMA_GRP_CFG);
1687 			status = nxge_cfg_verify_set(nxgep,
1688 				COMMON_CLASS_CFG);
1689 			hw_p->flags |= COMMON_CFG_VALID;
1690 		}
1691 		MUTEX_EXIT(&hw_p->nxge_cfg_lock);
1692 		nxge_use_cfg_neptune_properties(nxgep);
1693 		status = NXGE_OK;
1694 		break;
1695 	}
1696 
1697 	/*
1698 	 * Get the software LSO enable flag property from the
1699 	 * driver configuration file (nxge.conf).
1700 	 * This flag will be set to disable (0) if this property
1701 	 * does not exist.
1702 	 */
1703 	nxgep->soft_lso_enable = ddi_prop_get_int(DDI_DEV_T_ANY, nxgep->dip,
1704 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "soft-lso-enable", 0);
1705 	NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1706 	    "nxge_get_config_properties: software lso %d\n",
1707 	    nxgep->soft_lso_enable));
1708 
1709 	NXGE_DEBUG_MSG((nxgep, VPD_CTL, " <== nxge_get_config_properties"));
1710 	return (status);
1711 }
1712 
1713 static nxge_status_t
1714 nxge_use_cfg_n2niu_properties(p_nxge_t nxgep)
1715 {
1716 	nxge_status_t status = NXGE_OK;
1717 
1718 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_n2niu_properties"));
1719 
1720 	status = nxge_use_default_dma_config_n2(nxgep);
1721 	if (status != NXGE_OK) {
1722 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1723 			" ==> nxge_use_cfg_n2niu_properties (err 0x%x)",
1724 			status));
1725 		return (status | NXGE_ERROR);
1726 	}
1727 
1728 	(void) nxge_use_cfg_vlan_class_config(nxgep);
1729 	(void) nxge_use_cfg_mac_class_config(nxgep);
1730 	(void) nxge_use_cfg_class_config(nxgep);
1731 	(void) nxge_use_cfg_link_cfg(nxgep);
1732 
1733 	/*
1734 	 * Read in the hardware (fcode) properties. Use the ndd array to read
1735 	 * each property.
1736 	 */
1737 	(void) nxge_get_param_soft_properties(nxgep);
1738 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_n2niu_properties"));
1739 
1740 	return (status);
1741 }
1742 
1743 static void
1744 nxge_use_cfg_neptune_properties(p_nxge_t nxgep)
1745 {
1746 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_neptune_properties"));
1747 
1748 	(void) nxge_use_cfg_dma_config(nxgep);
1749 	(void) nxge_use_cfg_vlan_class_config(nxgep);
1750 	(void) nxge_use_cfg_mac_class_config(nxgep);
1751 	(void) nxge_use_cfg_class_config(nxgep);
1752 	(void) nxge_use_cfg_link_cfg(nxgep);
1753 
1754 	/*
1755 	 * Read in the hardware (fcode) properties. Use the ndd array to read
1756 	 * each property.
1757 	 */
1758 	(void) nxge_get_param_soft_properties(nxgep);
1759 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_neptune_properties"));
1760 }
1761 
1762 /*
1763  * FWARC 2006/556
1764  */
1765 
1766 static nxge_status_t
1767 nxge_use_default_dma_config_n2(p_nxge_t nxgep)
1768 {
1769 	int ndmas;
1770 	uint8_t func;
1771 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
1772 	p_nxge_hw_pt_cfg_t p_cfgp;
1773 	int *prop_val;
1774 	uint_t prop_len;
1775 	int i;
1776 	nxge_status_t status = NXGE_OK;
1777 
1778 	NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2"));
1779 
1780 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1781 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1782 
1783 	func = nxgep->function_num;
1784 	p_cfgp->function_number = func;
1785 	ndmas = NXGE_TDMA_PER_NIU_PORT;
1786 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
1787 			"tx-dma-channels", (int **)&prop_val,
1788 			&prop_len) == DDI_PROP_SUCCESS) {
1789 		p_cfgp->tdc.start = prop_val[0];
1790 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1791 			"==> nxge_use_default_dma_config_n2: tdc starts %d "
1792 			"(#%d)", p_cfgp->tdc.start, prop_len));
1793 
1794 		ndmas = prop_val[1];
1795 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1796 			"==> nxge_use_default_dma_config_n2: #tdc %d (#%d)",
1797 			ndmas, prop_len));
1798 		ddi_prop_free(prop_val);
1799 	} else {
1800 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1801 			"==> nxge_use_default_dma_config_n2: "
1802 			"get tx-dma-channels failed"));
1803 		return (NXGE_DDI_FAILED);
1804 	}
1805 
1806 	p_cfgp->tdc.count = nxgep->max_tdcs = ndmas;
1807 	p_cfgp->tdc.owned = p_cfgp->tdc.count;
1808 
1809 	NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
1810 		"p_cfgp 0x%llx max_tdcs %d nxgep->max_tdcs %d start %d",
1811 		p_cfgp, p_cfgp->tdc.count, nxgep->max_tdcs, p_cfgp->tdc.start));
1812 
1813 	/* Receive DMA */
1814 	ndmas = NXGE_RDMA_PER_NIU_PORT;
1815 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
1816 			"rx-dma-channels", (int **)&prop_val,
1817 			&prop_len) == DDI_PROP_SUCCESS) {
1818 		p_cfgp->start_rdc = prop_val[0];
1819 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1820 			"==> nxge_use_default_dma_config_n2(obp): rdc start %d"
1821 			" (#%d)", p_cfgp->start_rdc, prop_len));
1822 		ndmas = prop_val[1];
1823 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1824 			"==> nxge_use_default_dma_config_n2(obp):#rdc %d (#%d)",
1825 			ndmas, prop_len));
1826 		ddi_prop_free(prop_val);
1827 	} else {
1828 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1829 			"==> nxge_use_default_dma_config_n2: "
1830 			"get rx-dma-channel failed"));
1831 		return (NXGE_DDI_FAILED);
1832 	}
1833 
1834 	p_cfgp->max_rdcs = nxgep->max_rdcs = ndmas;
1835 	nxgep->rdc_mask = (ndmas - 1);
1836 
1837 	/* Hypervisor: rdc # and group # use the same # !! */
1838 	p_cfgp->max_grpids = p_cfgp->max_rdcs + p_cfgp->tdc.owned;
1839 	p_cfgp->start_grpid = 0;
1840 	p_cfgp->mif_ldvid = p_cfgp->mac_ldvid = p_cfgp->ser_ldvid = 0;
1841 
1842 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
1843 			"interrupts", (int **)&prop_val,
1844 			&prop_len) == DDI_PROP_SUCCESS) {
1845 		/*
1846 		 * For each device assigned, the content of each interrupts
1847 		 * property is its logical device group.
1848 		 *
1849 		 * Assignment of interrupts property is in the the following
1850 		 * order:
1851 		 *
1852 		 * MAC MIF (if configured) SYSTEM ERROR (if configured) first
1853 		 * receive channel next channel...... last receive channel
1854 		 * first transmit channel next channel...... last transmit
1855 		 * channel
1856 		 *
1857 		 * prop_len should be at least for one mac and total # of rx and
1858 		 * tx channels. Function 0 owns MIF and ERROR
1859 		 */
1860 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1861 			"==> nxge_use_default_dma_config_n2(obp): "
1862 			"# interrupts %d", prop_len));
1863 
1864 		switch (func) {
1865 		case 0:
1866 			p_cfgp->ldg_chn_start = 3;
1867 			p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT0;
1868 			p_cfgp->mif_ldvid = NXGE_MIF_LD;
1869 			p_cfgp->ser_ldvid = NXGE_SYS_ERROR_LD;
1870 
1871 			break;
1872 		case 1:
1873 			p_cfgp->ldg_chn_start = 1;
1874 			p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT1;
1875 
1876 			break;
1877 		default:
1878 			status = NXGE_DDI_FAILED;
1879 			break;
1880 		}
1881 
1882 		if (status != NXGE_OK)
1883 			return (status);
1884 
1885 		for (i = 0; i < prop_len; i++) {
1886 			p_cfgp->ldg[i] = prop_val[i];
1887 			NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1888 				"==> nxge_use_default_dma_config_n2(obp): "
1889 				"F%d: interrupt #%d, ldg %d",
1890 				nxgep->function_num, i, p_cfgp->ldg[i]));
1891 		}
1892 
1893 		p_cfgp->max_grpids = prop_len;
1894 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1895 			"==> nxge_use_default_dma_config_n2(obp): %d "
1896 			"(#%d) maxgrpids %d channel starts %d",
1897 			p_cfgp->mac_ldvid, i, p_cfgp->max_grpids,
1898 			p_cfgp->ldg_chn_start));
1899 		ddi_prop_free(prop_val);
1900 	} else {
1901 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1902 			"==> nxge_use_default_dma_config_n2: "
1903 			"get interrupts failed"));
1904 		return (NXGE_DDI_FAILED);
1905 	}
1906 
1907 	p_cfgp->max_ldgs = p_cfgp->max_grpids;
1908 	NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1909 		"==> nxge_use_default_dma_config_n2: "
1910 		"p_cfgp 0x%llx max_rdcs %d nxgep->max_rdcs %d max_grpids %d"
1911 		"start_grpid %d macid %d mifid %d serrid %d",
1912 		p_cfgp, p_cfgp->max_rdcs, nxgep->max_rdcs, p_cfgp->max_grpids,
1913 		p_cfgp->start_grpid,
1914 		p_cfgp->mac_ldvid, p_cfgp->mif_ldvid, p_cfgp->ser_ldvid));
1915 
1916 	NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
1917 		"p_cfgp p%p start_ldg %d nxgep->max_ldgs %d",
1918 		p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs));
1919 
1920 	/*
1921 	 * RDC groups and the beginning RDC group assigned to this function.
1922 	 */
1923 	p_cfgp->max_rdc_grpids = 1;
1924 	p_cfgp->def_mac_rxdma_grpid = (nxgep->function_num * 1);
1925 
1926 	if ((p_cfgp->def_mac_rxdma_grpid = nxge_fzc_rdc_tbl_bind
1927 		(nxgep, p_cfgp->def_mac_rxdma_grpid, B_TRUE))
1928 	    >= NXGE_MAX_RDC_GRPS) {
1929 		NXGE_ERROR_MSG((nxgep, CFG_CTL,
1930 		    "nxge_use_default_dma_config_n2(): "
1931 		    "nxge_fzc_rdc_tbl_bind failed"));
1932 		return (NXGE_DDI_FAILED);
1933 	}
1934 
1935 	status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
1936 	    "rx-rdc-grps", p_cfgp->max_rdc_grpids);
1937 	if (status) {
1938 		return (NXGE_DDI_FAILED);
1939 	}
1940 	status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
1941 		"rx-rdc-grps-begin", p_cfgp->def_mac_rxdma_grpid);
1942 	if (status) {
1943 		(void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip,
1944 			"rx-rdc-grps");
1945 		return (NXGE_DDI_FAILED);
1946 	}
1947 	NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
1948 		"p_cfgp $%p # rdc groups %d start rdc group id %d",
1949 		p_cfgp, p_cfgp->max_rdc_grpids,
1950 		p_cfgp->def_mac_rxdma_grpid));
1951 
1952 	nxge_set_hw_dma_config(nxgep);
1953 	NXGE_DEBUG_MSG((nxgep, OBP_CTL, "<== nxge_use_default_dma_config_n2"));
1954 	return (status);
1955 }
1956 
1957 static void
1958 nxge_use_cfg_dma_config(p_nxge_t nxgep)
1959 {
1960 	int tx_ndmas, rx_ndmas, nrxgp, st_txdma, st_rxdma;
1961 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
1962 	p_nxge_hw_pt_cfg_t p_cfgp;
1963 	dev_info_t *dip;
1964 	p_nxge_param_t param_arr;
1965 	char *prop;
1966 	int *prop_val;
1967 	uint_t prop_len;
1968 	int i;
1969 	uint8_t *ch_arr_p;
1970 
1971 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_dma_config"));
1972 	param_arr = nxgep->param_arr;
1973 
1974 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1975 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1976 	dip = nxgep->dip;
1977 	p_cfgp->function_number = nxgep->function_num;
1978 	prop = param_arr[param_txdma_channels_begin].fcode_name;
1979 
1980 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
1981 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1982 		p_cfgp->tdc.start = *prop_val;
1983 		ddi_prop_free(prop_val);
1984 	} else {
1985 		switch (nxgep->niu_type) {
1986 		case NEPTUNE_4_1GC:
1987 			ch_arr_p = &tx_4_1G[0];
1988 			break;
1989 		case NEPTUNE_2_10GF:
1990 			ch_arr_p = &tx_2_10G[0];
1991 			break;
1992 		case NEPTUNE_2_10GF_2_1GC:
1993 		case NEPTUNE_2_10GF_2_1GRF:
1994 			ch_arr_p = &tx_2_10G_2_1G[0];
1995 			break;
1996 		case NEPTUNE_1_10GF_3_1GC:
1997 			ch_arr_p = &tx_1_10G_3_1G[0];
1998 			break;
1999 		case NEPTUNE_1_1GC_1_10GF_2_1GC:
2000 			ch_arr_p = &tx_1_1G_1_10G_2_1G[0];
2001 			break;
2002 		default:
2003 			switch (nxgep->platform_type) {
2004 			case P_NEPTUNE_ALONSO:
2005 				ch_arr_p = &tx_2_10G_2_1G[0];
2006 				break;
2007 			default:
2008 				ch_arr_p = &p4_tx_equal[0];
2009 				break;
2010 			}
2011 			break;
2012 		}
2013 		st_txdma = 0;
2014 		for (i = 0; i < nxgep->function_num; i++, ch_arr_p++)
2015 			st_txdma += *ch_arr_p;
2016 
2017 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2018 		    prop, st_txdma);
2019 		p_cfgp->tdc.start = st_txdma;
2020 	}
2021 
2022 	prop = param_arr[param_txdma_channels].fcode_name;
2023 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2024 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2025 		tx_ndmas = *prop_val;
2026 		ddi_prop_free(prop_val);
2027 	} else {
2028 		switch (nxgep->niu_type) {
2029 		case NEPTUNE_4_1GC:
2030 			tx_ndmas = tx_4_1G[nxgep->function_num];
2031 			break;
2032 		case NEPTUNE_2_10GF:
2033 			tx_ndmas = tx_2_10G[nxgep->function_num];
2034 			break;
2035 		case NEPTUNE_2_10GF_2_1GC:
2036 		case NEPTUNE_2_10GF_2_1GRF:
2037 			tx_ndmas = tx_2_10G_2_1G[nxgep->function_num];
2038 			break;
2039 		case NEPTUNE_1_10GF_3_1GC:
2040 			tx_ndmas = tx_1_10G_3_1G[nxgep->function_num];
2041 			break;
2042 		case NEPTUNE_1_1GC_1_10GF_2_1GC:
2043 			tx_ndmas = tx_1_1G_1_10G_2_1G[nxgep->function_num];
2044 			break;
2045 		default:
2046 			switch (nxgep->platform_type) {
2047 			case P_NEPTUNE_ALONSO:
2048 				tx_ndmas = tx_2_10G_2_1G[nxgep->function_num];
2049 				break;
2050 			default:
2051 				tx_ndmas = p4_tx_equal[nxgep->function_num];
2052 				break;
2053 			}
2054 			break;
2055 		}
2056 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2057 			prop, tx_ndmas);
2058 	}
2059 
2060 	p_cfgp->tdc.count = nxgep->max_tdcs = tx_ndmas;
2061 	p_cfgp->tdc.owned = p_cfgp->tdc.count;
2062 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: "
2063 		"p_cfgp 0x%llx max_tdcs %d nxgep->max_tdcs %d",
2064 		p_cfgp, p_cfgp->tdc.count, nxgep->max_tdcs));
2065 
2066 	prop = param_arr[param_rxdma_channels_begin].fcode_name;
2067 
2068 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2069 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2070 		p_cfgp->start_rdc = *prop_val;
2071 		ddi_prop_free(prop_val);
2072 	} else {
2073 		switch (nxgep->niu_type) {
2074 		case NEPTUNE_4_1GC:
2075 			ch_arr_p = &rx_4_1G[0];
2076 			break;
2077 		case NEPTUNE_2_10GF:
2078 			ch_arr_p = &rx_2_10G[0];
2079 			break;
2080 		case NEPTUNE_2_10GF_2_1GC:
2081 		case NEPTUNE_2_10GF_2_1GRF:
2082 			ch_arr_p = &rx_2_10G_2_1G[0];
2083 			break;
2084 		case NEPTUNE_1_10GF_3_1GC:
2085 			ch_arr_p = &rx_1_10G_3_1G[0];
2086 			break;
2087 		case NEPTUNE_1_1GC_1_10GF_2_1GC:
2088 			ch_arr_p = &rx_1_1G_1_10G_2_1G[0];
2089 			break;
2090 		default:
2091 			switch (nxgep->platform_type) {
2092 			case P_NEPTUNE_ALONSO:
2093 				ch_arr_p = &rx_2_10G_2_1G[0];
2094 				break;
2095 			default:
2096 				ch_arr_p = &p4_rx_equal[0];
2097 				break;
2098 			}
2099 			break;
2100 		}
2101 		st_rxdma = 0;
2102 		for (i = 0; i < nxgep->function_num; i++, ch_arr_p++)
2103 			st_rxdma += *ch_arr_p;
2104 
2105 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2106 		    prop, st_rxdma);
2107 		p_cfgp->start_rdc = st_rxdma;
2108 	}
2109 
2110 	prop = param_arr[param_rxdma_channels].fcode_name;
2111 
2112 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2113 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2114 		rx_ndmas = *prop_val;
2115 		ddi_prop_free(prop_val);
2116 	} else {
2117 		switch (nxgep->niu_type) {
2118 		case NEPTUNE_4_1GC:
2119 			rx_ndmas = rx_4_1G[nxgep->function_num];
2120 			break;
2121 		case NEPTUNE_2_10GF:
2122 			rx_ndmas = rx_2_10G[nxgep->function_num];
2123 			break;
2124 		case NEPTUNE_2_10GF_2_1GC:
2125 		case NEPTUNE_2_10GF_2_1GRF:
2126 			rx_ndmas = rx_2_10G_2_1G[nxgep->function_num];
2127 			break;
2128 		case NEPTUNE_1_10GF_3_1GC:
2129 			rx_ndmas = rx_1_10G_3_1G[nxgep->function_num];
2130 			break;
2131 		case NEPTUNE_1_1GC_1_10GF_2_1GC:
2132 			rx_ndmas = rx_1_1G_1_10G_2_1G[nxgep->function_num];
2133 			break;
2134 		default:
2135 			switch (nxgep->platform_type) {
2136 			case P_NEPTUNE_ALONSO:
2137 				rx_ndmas = rx_2_10G_2_1G[nxgep->function_num];
2138 				break;
2139 			default:
2140 				rx_ndmas = p4_rx_equal[nxgep->function_num];
2141 				break;
2142 			}
2143 			break;
2144 		}
2145 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2146 			prop, rx_ndmas);
2147 	}
2148 
2149 	p_cfgp->max_rdcs = nxgep->max_rdcs = rx_ndmas;
2150 
2151 	prop = param_arr[param_rdc_grps_start].fcode_name;
2152 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2153 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2154 		p_cfgp->def_mac_rxdma_grpid = *prop_val;
2155 		ddi_prop_free(prop_val);
2156 		if ((p_cfgp->def_mac_rxdma_grpid = nxge_fzc_rdc_tbl_bind
2157 			(nxgep, p_cfgp->def_mac_rxdma_grpid, B_TRUE))
2158 		    >= NXGE_MAX_RDC_GRPS) {
2159 			NXGE_ERROR_MSG((nxgep, CFG_CTL,
2160 			    "nxge_use_cfg_dma_config(): "
2161 			    "nxge_fzc_rdc_tbl_bind failed"));
2162 			cmn_err(CE_CONT, "nxge%d: group not available!\n",
2163 			    nxgep->instance);
2164 			goto nxge_use_cfg_dma_config_exit;
2165 		}
2166 
2167 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
2168 		    "==> nxge_use_default_dma_config: "
2169 		    "use property " "start_grpid %d ",
2170 			p_cfgp->start_grpid));
2171 	} else {
2172 		p_cfgp->def_mac_rxdma_grpid = nxgep->function_num;
2173 		if ((p_cfgp->def_mac_rxdma_grpid = nxge_fzc_rdc_tbl_bind(
2174 		    nxgep, p_cfgp->def_mac_rxdma_grpid, B_TRUE)) >=
2175 		    NXGE_MAX_RDC_GRPS) {
2176 			cmn_err(CE_CONT, "nxge%d: group not available!\n",
2177 			    nxgep->instance);
2178 			goto nxge_use_cfg_dma_config_exit;
2179 		}
2180 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2181 			prop, p_cfgp->def_mac_rxdma_grpid);
2182 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
2183 			"==> nxge_use_default_dma_config: "
2184 			"use default "
2185 			"start_grpid %d (same as function #)",
2186 			p_cfgp->start_grpid));
2187 	}
2188 
2189 	prop = param_arr[param_rx_rdc_grps].fcode_name;
2190 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2191 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2192 		nrxgp = *prop_val;
2193 		ddi_prop_free(prop_val);
2194 	} else {
2195 		nrxgp = 1;
2196 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
2197 			prop, nrxgp);
2198 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
2199 			"==> nxge_use_default_dma_config: "
2200 			"num_rdc_grpid not found: use def:# of "
2201 			"rdc groups %d\n", nrxgp));
2202 	}
2203 
2204 	p_cfgp->max_rdc_grpids = nrxgp;
2205 
2206 	/*
2207 	 * 2/4 ports have the same hard-wired logical groups assigned.
2208 	 */
2209 	p_cfgp->start_ldg = nxgep->function_num * NXGE_LDGRP_PER_4PORTS;
2210 	p_cfgp->max_ldgs = NXGE_LDGRP_PER_4PORTS;
2211 
2212 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_default_dma_config: "
2213 		"p_cfgp 0x%llx max_rdcs %d nxgep->max_rdcs %d max_grpids %d"
2214 		"start_grpid %d",
2215 		p_cfgp, p_cfgp->max_rdcs, nxgep->max_rdcs, p_cfgp->max_grpids,
2216 		p_cfgp->start_grpid));
2217 
2218 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: "
2219 		"p_cfgp 0x%016llx start_ldg %d nxgep->max_ldgs %d "
2220 		"def_mac_rxdma_grpid %d",
2221 		p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs,
2222 		p_cfgp->def_mac_rxdma_grpid));
2223 
2224 	prop = param_arr[param_rxdma_intr_time].fcode_name;
2225 
2226 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2227 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2228 		if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
2229 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2230 				nxgep->dip, prop, prop_val, prop_len);
2231 		}
2232 		ddi_prop_free(prop_val);
2233 	}
2234 	prop = param_arr[param_rxdma_intr_pkts].fcode_name;
2235 
2236 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2237 			&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2238 		if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
2239 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2240 				nxgep->dip, prop, prop_val, prop_len);
2241 		}
2242 		ddi_prop_free(prop_val);
2243 	}
2244 	nxge_set_hw_dma_config(nxgep);
2245 
2246 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_dma_config: "
2247 	    "sTDC[%d] nTDC[%d] sRDC[%d] nRDC[%d]",
2248 	    p_cfgp->tdc.start, p_cfgp->tdc.count,
2249 	    p_cfgp->start_rdc, p_cfgp->max_rdcs));
2250 
2251 nxge_use_cfg_dma_config_exit:
2252 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_dma_config"));
2253 }
2254 
2255 void
2256 nxge_get_logical_props(p_nxge_t nxgep)
2257 {
2258 	nxge_dma_pt_cfg_t *port = &nxgep->pt_config;
2259 	nxge_hw_pt_cfg_t *hardware;
2260 	nxge_rdc_grp_t *group;
2261 
2262 	(void) memset(port, 0, sizeof (*port));
2263 
2264 	port->mac_port = 0;	/* := function number */
2265 
2266 	/*
2267 	 * alloc_buf_size:
2268 	 * dead variables.
2269 	 */
2270 	port->rbr_size = nxge_rbr_size;
2271 	port->rcr_size = nxge_rcr_size;
2272 
2273 	port->tx_dma_map = 0;	/* Transmit DMA channel bit map */
2274 
2275 	nxge_set_rdc_intr_property(nxgep);
2276 
2277 	port->rcr_full_header = NXGE_RCR_FULL_HEADER;
2278 	port->rx_drr_weight = PT_DRR_WT_DEFAULT_10G;
2279 
2280 	/* ----------------------------------------------------- */
2281 	hardware = &port->hw_config;
2282 
2283 	(void) memset(hardware, 0, sizeof (*hardware));
2284 
2285 	/*
2286 	 * partition_id, read_write_mode:
2287 	 * dead variables.
2288 	 */
2289 
2290 	/*
2291 	 * drr_wt, rx_full_header, *_ldg?, start_mac_entry,
2292 	 * mac_pref, def_mac_rxdma_grpid, start_vlan, max_vlans,
2293 	 * start_ldgs, max_ldgs, max_ldvs,
2294 	 * vlan_pref, def_vlan_rxdma_grpid are meaningful only
2295 	 * in the service domain.
2296 	 */
2297 
2298 	group = &port->rdc_grps[0];
2299 
2300 	group->flag = 1;	/* configured */
2301 	group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
2302 
2303 	/* HIO futures: this is still an open question. */
2304 	hardware->max_macs = 1;
2305 }
2306 
2307 static void
2308 nxge_use_cfg_vlan_class_config(p_nxge_t nxgep)
2309 {
2310 	uint_t vlan_cnt;
2311 	int *vlan_cfg_val;
2312 	int status;
2313 	p_nxge_param_t param_arr;
2314 	char *prop;
2315 
2316 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_vlan_config"));
2317 	param_arr = nxgep->param_arr;
2318 	prop = param_arr[param_vlan_2rdc_grp].fcode_name;
2319 
2320 	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2321 		&vlan_cfg_val, &vlan_cnt);
2322 	if (status == DDI_PROP_SUCCESS) {
2323 		status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
2324 			nxgep->dip, prop, vlan_cfg_val, vlan_cnt);
2325 		ddi_prop_free(vlan_cfg_val);
2326 	}
2327 	nxge_set_hw_vlan_class_config(nxgep);
2328 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_vlan_config"));
2329 }
2330 
2331 static void
2332 nxge_use_cfg_mac_class_config(p_nxge_t nxgep)
2333 {
2334 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2335 	p_nxge_hw_pt_cfg_t p_cfgp;
2336 	uint_t mac_cnt;
2337 	int *mac_cfg_val;
2338 	int status;
2339 	p_nxge_param_t param_arr;
2340 	char *prop;
2341 
2342 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_mac_class_config"));
2343 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2344 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2345 	p_cfgp->start_mac_entry = 0;
2346 	param_arr = nxgep->param_arr;
2347 	prop = param_arr[param_mac_2rdc_grp].fcode_name;
2348 
2349 	switch (nxgep->function_num) {
2350 	case 0:
2351 	case 1:
2352 		/* 10G ports */
2353 		p_cfgp->max_macs = NXGE_MAX_MACS_XMACS;
2354 		break;
2355 	case 2:
2356 	case 3:
2357 		/* 1G ports */
2358 	default:
2359 		p_cfgp->max_macs = NXGE_MAX_MACS_BMACS;
2360 		break;
2361 	}
2362 
2363 	p_cfgp->mac_pref = 1;
2364 	NXGE_DEBUG_MSG((nxgep, OBP_CTL,
2365 		"== nxge_use_cfg_mac_class_config: "
2366 		" mac_pref bit set def_mac_rxdma_grpid %d",
2367 		p_cfgp->def_mac_rxdma_grpid));
2368 
2369 	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2370 		&mac_cfg_val, &mac_cnt);
2371 	if (status == DDI_PROP_SUCCESS) {
2372 		if (mac_cnt <= p_cfgp->max_macs)
2373 			status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
2374 				nxgep->dip, prop, mac_cfg_val, mac_cnt);
2375 		ddi_prop_free(mac_cfg_val);
2376 	}
2377 	nxge_set_hw_mac_class_config(nxgep);
2378 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_mac_class_config"));
2379 }
2380 
2381 static void
2382 nxge_use_cfg_class_config(p_nxge_t nxgep)
2383 {
2384 	nxge_set_hw_class_config(nxgep);
2385 }
2386 
2387 static void
2388 nxge_set_rdc_intr_property(p_nxge_t nxgep)
2389 {
2390 	int i;
2391 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2392 
2393 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_rdc_intr_property"));
2394 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2395 
2396 	for (i = 0; i < NXGE_MAX_RDCS; i++) {
2397 		p_dma_cfgp->rcr_timeout[i] = nxge_rcr_timeout;
2398 		p_dma_cfgp->rcr_threshold[i] = nxge_rcr_threshold;
2399 	}
2400 
2401 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_rdc_intr_property"));
2402 }
2403 
2404 static void
2405 nxge_set_hw_dma_config(p_nxge_t nxgep)
2406 {
2407 	int i, ndmas, ngrps, bitmap, end, st_rdc;
2408 	int32_t status;
2409 	uint8_t rdcs_per_grp;
2410 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2411 	p_nxge_hw_pt_cfg_t p_cfgp;
2412 	p_nxge_rdc_grp_t rdc_grp_p;
2413 	int rdcgrp_cfg = CFG_NOT_SPECIFIED, rx_quick_cfg;
2414 	char *prop, *prop_val;
2415 	p_nxge_param_t param_arr;
2416 	config_token_t token;
2417 	nxge_grp_t *group;
2418 
2419 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_set_hw_dma_config"));
2420 
2421 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2422 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2423 	rdc_grp_p = p_dma_cfgp->rdc_grps;
2424 
2425 	bitmap = 0;
2426 	end = p_cfgp->tdc.start + p_cfgp->tdc.owned;
2427 	p_dma_cfgp->tx_dma_map = 0;
2428 	for (i = p_cfgp->tdc.start; i < end; i++) {
2429 		bitmap |= (1 << i);
2430 	}
2431 
2432 	nxgep->tx_set.owned.map |= bitmap; /* Owned, & not shared. */
2433 
2434 	group = (nxge_grp_t *)nxge_grp_add(nxgep, NXGE_TRANSMIT_GROUP);
2435 	group->map = bitmap;
2436 
2437 	p_dma_cfgp->tx_dma_map = bitmap;
2438 	param_arr = nxgep->param_arr;
2439 
2440 	/* Assume RDCs are evenly distributed */
2441 	rx_quick_cfg = param_arr[param_rx_quick_cfg].value;
2442 	switch (rx_quick_cfg) {
2443 	case CFG_NOT_SPECIFIED:
2444 		prop = "rxdma-grp-cfg";
2445 		status = ddi_prop_lookup_string(DDI_DEV_T_NONE,
2446 			nxgep->dip, 0, prop, (char **)&prop_val);
2447 		if (status != DDI_PROP_SUCCESS) {
2448 			NXGE_DEBUG_MSG((nxgep, CFG_CTL,
2449 				" property %s not found", prop));
2450 			rdcgrp_cfg = CFG_L3_DISTRIBUTE;
2451 		} else {
2452 			token = nxge_get_config_token(prop_val);
2453 			switch (token) {
2454 			case L2_CLASSIFY:
2455 				break;
2456 			case CLASSIFY:
2457 			case L3_CLASSIFY:
2458 			case L3_DISTRIBUTE:
2459 			case L3_TCAM:
2460 				rdcgrp_cfg = CFG_L3_DISTRIBUTE;
2461 				break;
2462 			default:
2463 				rdcgrp_cfg = CFG_L3_DISTRIBUTE;
2464 				break;
2465 			}
2466 			ddi_prop_free(prop_val);
2467 		}
2468 		break;
2469 	case CFG_L3_WEB:
2470 	case CFG_L3_DISTRIBUTE:
2471 	case CFG_L2_CLASSIFY:
2472 	case CFG_L3_TCAM:
2473 		rdcgrp_cfg = rx_quick_cfg;
2474 		break;
2475 	default:
2476 		rdcgrp_cfg = CFG_L3_DISTRIBUTE;
2477 		break;
2478 	}
2479 
2480 	st_rdc = p_cfgp->start_rdc;
2481 
2482 	switch (rdcgrp_cfg) {
2483 	case CFG_L3_DISTRIBUTE:
2484 	case CFG_L3_WEB:
2485 	case CFG_L3_TCAM:
2486 		ndmas = p_cfgp->max_rdcs;
2487 		ngrps = 1;
2488 		rdcs_per_grp = ndmas / ngrps;
2489 		break;
2490 	case CFG_L2_CLASSIFY:
2491 		ndmas = p_cfgp->max_rdcs / 2;
2492 		if (p_cfgp->max_rdcs < 2)
2493 			ndmas = 1;
2494 		ngrps = 1;
2495 		rdcs_per_grp = ndmas / ngrps;
2496 		break;
2497 	default:
2498 		ngrps = p_cfgp->max_rdc_grpids;
2499 		ndmas = p_cfgp->max_rdcs;
2500 		rdcs_per_grp = ndmas / ngrps;
2501 		break;
2502 	}
2503 
2504 	for (i = 0; i < ngrps; i++) {
2505 		uint8_t count = rdcs_per_grp;
2506 		dc_map_t map = 0;
2507 
2508 		rdc_grp_p = &p_dma_cfgp->rdc_grps[
2509 			p_cfgp->def_mac_rxdma_grpid + i];
2510 		rdc_grp_p->start_rdc = st_rdc + i * rdcs_per_grp;
2511 		rdc_grp_p->max_rdcs = rdcs_per_grp;
2512 		rdc_grp_p->def_rdc = rdc_grp_p->start_rdc;
2513 
2514 		/* default to: 0, 1, 2, 3, ...., 0, 1, 2, 3.... */
2515 		while (count) {
2516 			map |= (1 << count);
2517 			count--;
2518 		}
2519 		map >>= 1;	/* In case <start_rdc> is zero (0) */
2520 		map <<= rdc_grp_p->start_rdc;
2521 		rdc_grp_p->map = map;
2522 
2523 		nxgep->rx_set.owned.map |= map; /* Owned, & not shared. */
2524 
2525 		group = (nxge_grp_t *)nxge_grp_add(nxgep, NXGE_RECEIVE_GROUP);
2526 		group->map = rdc_grp_p->map;
2527 
2528 		rdc_grp_p->config_method = RDC_TABLE_ENTRY_METHOD_SEQ;
2529 		rdc_grp_p->flag = 1; /* This group has been configured. */
2530 	}
2531 
2532 
2533 	/* default RDC */
2534 	p_cfgp->def_rdc = p_cfgp->start_rdc;
2535 	nxgep->def_rdc = p_cfgp->start_rdc;
2536 
2537 	/* full 18 byte header ? */
2538 	p_dma_cfgp->rcr_full_header = NXGE_RCR_FULL_HEADER;
2539 	p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_10G;
2540 	if (nxgep->function_num > 1)
2541 		p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_1G;
2542 	p_dma_cfgp->rbr_size = nxge_rbr_size;
2543 	p_dma_cfgp->rcr_size = nxge_rcr_size;
2544 
2545 	nxge_set_rdc_intr_property(nxgep);
2546 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_dma_config"));
2547 }
2548 
2549 boolean_t
2550 nxge_check_rxdma_port_member(p_nxge_t nxgep, uint8_t rdc)
2551 {
2552 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2553 	p_nxge_hw_pt_cfg_t p_cfgp;
2554 	int status = B_TRUE;
2555 
2556 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_rxdma_port_member"));
2557 
2558 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2559 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2560 
2561 	/* Receive DMA Channels */
2562 	if (rdc < p_cfgp->max_rdcs)
2563 		status = B_TRUE;
2564 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_rxdma_port_member"));
2565 	return (status);
2566 }
2567 
2568 boolean_t
2569 nxge_check_txdma_port_member(p_nxge_t nxgep, uint8_t tdc)
2570 {
2571 	int status = B_FALSE;
2572 
2573 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_txdma_port_member"));
2574 
2575 	if (tdc >= nxgep->pt_config.hw_config.tdc.start &&
2576 	    tdc < nxgep->pt_config.hw_config.tdc.count)
2577 		status = B_TRUE;
2578 
2579 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_txdma_port_member"));
2580 	return (status);
2581 }
2582 
2583 boolean_t
2584 nxge_check_rxdma_rdcgrp_member(p_nxge_t nxgep, uint8_t rdc_grp, uint8_t rdc)
2585 {
2586 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2587 	int status = B_TRUE;
2588 	p_nxge_rdc_grp_t rdc_grp_p;
2589 
2590 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
2591 		" ==> nxge_check_rxdma_rdcgrp_member"));
2592 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "  nxge_check_rxdma_rdcgrp_member"
2593 		" rdc  %d group %d", rdc, rdc_grp));
2594 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2595 
2596 	rdc_grp_p = &p_dma_cfgp->rdc_grps[rdc_grp];
2597 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "  max  %d ", rdc_grp_p->max_rdcs));
2598 	if (rdc >= rdc_grp_p->max_rdcs) {
2599 		status = B_FALSE;
2600 	}
2601 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
2602 		" <== nxge_check_rxdma_rdcgrp_member"));
2603 	return (status);
2604 }
2605 
2606 boolean_t
2607 nxge_check_rdcgrp_port_member(p_nxge_t nxgep, uint8_t rdc_grp)
2608 {
2609 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2610 	p_nxge_hw_pt_cfg_t p_cfgp;
2611 	int status = B_TRUE;
2612 
2613 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_rdcgrp_port_member"));
2614 
2615 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2616 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2617 
2618 	if (rdc_grp >= p_cfgp->max_rdc_grpids)
2619 		status = B_FALSE;
2620 	NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_rdcgrp_port_member"));
2621 	return (status);
2622 }
2623 
2624 static void
2625 nxge_set_hw_vlan_class_config(p_nxge_t nxgep)
2626 {
2627 	int i;
2628 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2629 	p_nxge_hw_pt_cfg_t p_cfgp;
2630 	p_nxge_param_t param_arr;
2631 	uint_t vlan_cnt;
2632 	int *vlan_cfg_val;
2633 	nxge_param_map_t *vmap;
2634 	char *prop;
2635 	p_nxge_class_pt_cfg_t p_class_cfgp;
2636 	uint32_t good_cfg[32];
2637 	int good_count = 0;
2638 	nxge_mv_cfg_t *vlan_tbl;
2639 
2640 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_hw_vlan_config"));
2641 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2642 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2643 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
2644 
2645 	param_arr = nxgep->param_arr;
2646 	prop = param_arr[param_vlan_2rdc_grp].fcode_name;
2647 
2648 	/*
2649 	 * By default, VLAN to RDC group mapping is disabled Need to read HW or
2650 	 * .conf properties to find out if mapping is required
2651 	 *
2652 	 * Format
2653 	 *
2654 	 * uint32_t array, each array entry specifying the VLAN id and the
2655 	 * mapping
2656 	 *
2657 	 * bit[30] = add bit[29] = remove bit[28]  = preference bits[23-16] =
2658 	 * rdcgrp bits[15-0] = VLAN ID ( )
2659 	 */
2660 
2661 	for (i = 0; i < NXGE_MAX_VLANS; i++) {
2662 		p_class_cfgp->vlan_tbl[i].flag = 0;
2663 	}
2664 
2665 	vlan_tbl = (nxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
2666 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2667 			&vlan_cfg_val, &vlan_cnt) == DDI_PROP_SUCCESS) {
2668 		for (i = 0; i < vlan_cnt; i++) {
2669 			vmap = (nxge_param_map_t *)&vlan_cfg_val[i];
2670 			if ((vmap->param_id) &&
2671 					(vmap->param_id < NXGE_MAX_VLANS) &&
2672 					(vmap->map_to <
2673 						p_cfgp->max_rdc_grpids) &&
2674 					(vmap->map_to >= (uint8_t)0)) {
2675 				NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
2676 					" nxge_vlan_config mapping"
2677 					" id %d grp %d",
2678 					vmap->param_id, vmap->map_to));
2679 				good_cfg[good_count] = vlan_cfg_val[i];
2680 				if (vlan_tbl[vmap->param_id].flag == 0)
2681 					good_count++;
2682 				vlan_tbl[vmap->param_id].flag = 1;
2683 				vlan_tbl[vmap->param_id].rdctbl =
2684 				    vmap->map_to + p_cfgp->def_mac_rxdma_grpid;
2685 				vlan_tbl[vmap->param_id].mpr_npr = vmap->pref;
2686 			}
2687 		}
2688 		ddi_prop_free(vlan_cfg_val);
2689 		if (good_count != vlan_cnt) {
2690 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2691 				nxgep->dip, prop, (int *)good_cfg, good_count);
2692 		}
2693 	}
2694 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_set_hw_vlan_config"));
2695 }
2696 
2697 static void
2698 nxge_set_hw_mac_class_config(p_nxge_t nxgep)
2699 {
2700 	int i;
2701 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2702 	p_nxge_hw_pt_cfg_t p_cfgp;
2703 	p_nxge_param_t param_arr;
2704 	uint_t mac_cnt;
2705 	int *mac_cfg_val;
2706 	nxge_param_map_t *mac_map;
2707 	char *prop;
2708 	p_nxge_class_pt_cfg_t p_class_cfgp;
2709 	int good_count = 0;
2710 	int good_cfg[NXGE_MAX_MACS];
2711 	nxge_mv_cfg_t *mac_host_info;
2712 
2713 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_set_hw_mac_config"));
2714 
2715 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2716 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2717 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
2718 	mac_host_info = (nxge_mv_cfg_t *)&p_class_cfgp->mac_host_info[0];
2719 
2720 	param_arr = nxgep->param_arr;
2721 	prop = param_arr[param_mac_2rdc_grp].fcode_name;
2722 
2723 	for (i = 0; i < NXGE_MAX_MACS; i++) {
2724 		p_class_cfgp->mac_host_info[i].flag = 0;
2725 		p_class_cfgp->mac_host_info[i].rdctbl =
2726 		    p_cfgp->def_mac_rxdma_grpid;
2727 	}
2728 
2729 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2730 			&mac_cfg_val, &mac_cnt) == DDI_PROP_SUCCESS) {
2731 		for (i = 0; i < mac_cnt; i++) {
2732 			mac_map = (nxge_param_map_t *)&mac_cfg_val[i];
2733 			if ((mac_map->param_id < p_cfgp->max_macs) &&
2734 					(mac_map->map_to <
2735 						p_cfgp->max_rdc_grpids) &&
2736 					(mac_map->map_to >= (uint8_t)0)) {
2737 				NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
2738 					" nxge_mac_config mapping"
2739 					" id %d grp %d",
2740 					mac_map->param_id, mac_map->map_to));
2741 				mac_host_info[mac_map->param_id].mpr_npr =
2742 					mac_map->pref;
2743 				mac_host_info[mac_map->param_id].rdctbl =
2744 					mac_map->map_to +
2745 					p_cfgp->def_mac_rxdma_grpid;
2746 				good_cfg[good_count] = mac_cfg_val[i];
2747 				if (mac_host_info[mac_map->param_id].flag == 0)
2748 					good_count++;
2749 				mac_host_info[mac_map->param_id].flag = 1;
2750 			}
2751 		}
2752 		ddi_prop_free(mac_cfg_val);
2753 		if (good_count != mac_cnt) {
2754 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2755 				nxgep->dip, prop, good_cfg, good_count);
2756 		}
2757 	}
2758 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_set_hw_mac_config"));
2759 }
2760 
2761 static void
2762 nxge_set_hw_class_config(p_nxge_t nxgep)
2763 {
2764 	int i;
2765 	p_nxge_param_t param_arr;
2766 	int *int_prop_val;
2767 	uint32_t cfg_value;
2768 	char *prop;
2769 	p_nxge_class_pt_cfg_t p_class_cfgp;
2770 	int start_prop, end_prop;
2771 	uint_t prop_cnt;
2772 
2773 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_hw_class_config"));
2774 
2775 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
2776 	param_arr = nxgep->param_arr;
2777 	start_prop = param_class_opt_ip_usr4;
2778 	end_prop = param_class_opt_ipv6_sctp;
2779 
2780 	for (i = start_prop; i <= end_prop; i++) {
2781 		prop = param_arr[i].fcode_name;
2782 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
2783 				0, prop, &int_prop_val,
2784 				&prop_cnt) == DDI_PROP_SUCCESS) {
2785 			cfg_value = (uint32_t)*int_prop_val;
2786 			ddi_prop_free(int_prop_val);
2787 		} else {
2788 			cfg_value = (uint32_t)param_arr[i].value;
2789 		}
2790 		p_class_cfgp->class_cfg[i - start_prop] = cfg_value;
2791 	}
2792 
2793 	prop = param_arr[param_h1_init_value].fcode_name;
2794 
2795 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2796 			&int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
2797 		cfg_value = (uint32_t)*int_prop_val;
2798 		ddi_prop_free(int_prop_val);
2799 	} else {
2800 		cfg_value = (uint32_t)param_arr[param_h1_init_value].value;
2801 	}
2802 
2803 	p_class_cfgp->init_h1 = (uint32_t)cfg_value;
2804 	prop = param_arr[param_h2_init_value].fcode_name;
2805 
2806 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
2807 			&int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
2808 		cfg_value = (uint32_t)*int_prop_val;
2809 		ddi_prop_free(int_prop_val);
2810 	} else {
2811 		cfg_value = (uint32_t)param_arr[param_h2_init_value].value;
2812 	}
2813 
2814 	p_class_cfgp->init_h2 = (uint16_t)cfg_value;
2815 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_class_config"));
2816 }
2817 
2818 nxge_status_t
2819 nxge_ldgv_init_n2(p_nxge_t nxgep, int *navail_p, int *nrequired_p)
2820 {
2821 	int i, maxldvs, maxldgs, nldvs;
2822 	int ldv, endldg;
2823 	uint8_t func;
2824 	uint8_t channel;
2825 	uint8_t chn_start;
2826 	boolean_t own_sys_err = B_FALSE, own_fzc = B_FALSE;
2827 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2828 	p_nxge_hw_pt_cfg_t p_cfgp;
2829 	p_nxge_ldgv_t ldgvp;
2830 	p_nxge_ldg_t ldgp, ptr;
2831 	p_nxge_ldv_t ldvp;
2832 	nxge_status_t status = NXGE_OK;
2833 	nxge_grp_set_t *set;
2834 
2835 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2"));
2836 	if (!*navail_p) {
2837 		*nrequired_p = 0;
2838 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2839 			"<== nxge_ldgv_init:no avail"));
2840 		return (NXGE_ERROR);
2841 	}
2842 	/*
2843 	 * N2/NIU: one logical device owns one logical group. and each
2844 	 * device/group will be assigned one vector by Hypervisor.
2845 	 */
2846 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2847 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2848 	maxldgs = p_cfgp->max_ldgs;
2849 	if (!maxldgs) {
2850 		/* No devices configured. */
2851 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_init_n2: "
2852 			"no logical groups configured."));
2853 		return (NXGE_ERROR);
2854 	} else {
2855 		maxldvs = maxldgs + 1;
2856 	}
2857 
2858 	/*
2859 	 * If function zero instance, it needs to handle the system and MIF
2860 	 * error interrupts. MIF interrupt may not be needed for N2/NIU.
2861 	 */
2862 	func = nxgep->function_num;
2863 	if (func == 0) {
2864 		own_sys_err = B_TRUE;
2865 		if (!p_cfgp->ser_ldvid) {
2866 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2867 				"nxge_ldgv_init_n2: func 0, ERR ID not set!"));
2868 		}
2869 		/* MIF interrupt */
2870 		if (!p_cfgp->mif_ldvid) {
2871 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2872 				"nxge_ldgv_init_n2: func 0, MIF ID not set!"));
2873 		}
2874 	}
2875 
2876 	/*
2877 	 * Assume single partition, each function owns mac.
2878 	 */
2879 	if (!nxge_use_partition)
2880 		own_fzc = B_TRUE;
2881 
2882 	ldgvp = nxgep->ldgvp;
2883 	if (ldgvp == NULL) {
2884 		ldgvp = KMEM_ZALLOC(sizeof (nxge_ldgv_t), KM_SLEEP);
2885 		nxgep->ldgvp = ldgvp;
2886 		ldgvp->maxldgs = (uint8_t)maxldgs;
2887 		ldgvp->maxldvs = (uint8_t)maxldvs;
2888 		ldgp = ldgvp->ldgp = KMEM_ZALLOC(
2889 			sizeof (nxge_ldg_t) * maxldgs, KM_SLEEP);
2890 		ldvp = ldgvp->ldvp = KMEM_ZALLOC(
2891 			sizeof (nxge_ldv_t) * maxldvs, KM_SLEEP);
2892 	} else {
2893 		ldgp = ldgvp->ldgp;
2894 		ldvp = ldgvp->ldvp;
2895 	}
2896 
2897 	ldgvp->ndma_ldvs = p_cfgp->tdc.owned + p_cfgp->max_rdcs;
2898 	ldgvp->tmres = NXGE_TIMER_RESO;
2899 
2900 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
2901 		"==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d",
2902 		maxldvs, maxldgs));
2903 
2904 	/* logical start_ldg is ldv */
2905 	ptr = ldgp;
2906 	for (i = 0; i < maxldgs; i++) {
2907 		ptr->func = func;
2908 		ptr->arm = B_TRUE;
2909 		ptr->vldg_index = (uint8_t)i;
2910 		ptr->ldg_timer = NXGE_TIMER_LDG;
2911 		ptr->ldg = p_cfgp->ldg[i];
2912 		ptr->sys_intr_handler = nxge_intr;
2913 		ptr->nldvs = 0;
2914 		ptr->ldvp = NULL;
2915 		ptr->nxgep = nxgep;
2916 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
2917 			"==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d "
2918 			"ldg %d ldgptr $%p",
2919 			maxldvs, maxldgs, ptr->ldg, ptr));
2920 		ptr++;
2921 	}
2922 
2923 	endldg = NXGE_INT_MAX_LDG;
2924 	nldvs = 0;
2925 	ldgvp->nldvs = 0;
2926 	ldgp->ldvp = NULL;
2927 	*nrequired_p = 0;
2928 
2929 	/*
2930 	 * logical device group table is organized in the following order (same
2931 	 * as what interrupt property has). function 0: owns MAC, MIF, error,
2932 	 * rx, tx. function 1: owns MAC, rx, tx.
2933 	 */
2934 
2935 	if (own_fzc && p_cfgp->mac_ldvid) {
2936 		/* Each function should own MAC interrupt */
2937 		ldv = p_cfgp->mac_ldvid;
2938 		ldvp->ldv = (uint8_t)ldv;
2939 		ldvp->is_mac = B_TRUE;
2940 		ldvp->ldv_intr_handler = nxge_mac_intr;
2941 		ldvp->ldv_ldf_masks = 0;
2942 		ldvp->nxgep = nxgep;
2943 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
2944 			"==> nxge_ldgv_init_n2(mac): maxldvs %d ldv %d "
2945 			"ldg %d ldgptr $%p ldvptr $%p",
2946 			maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
2947 		nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
2948 		nldvs++;
2949 	}
2950 
2951 	if (own_fzc && p_cfgp->mif_ldvid) {
2952 		ldv = p_cfgp->mif_ldvid;
2953 		ldvp->ldv = (uint8_t)ldv;
2954 		ldvp->is_mif = B_TRUE;
2955 		ldvp->ldv_intr_handler = nxge_mif_intr;
2956 		ldvp->ldv_ldf_masks = 0;
2957 		ldvp->nxgep = nxgep;
2958 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
2959 			"==> nxge_ldgv_init_n2(mif): maxldvs %d ldv %d "
2960 			"ldg %d ldgptr $%p ldvptr $%p",
2961 			maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
2962 		nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
2963 		nldvs++;
2964 	}
2965 
2966 	ldv = NXGE_SYS_ERROR_LD;
2967 	ldvp->use_timer = B_TRUE;
2968 	if (own_sys_err && p_cfgp->ser_ldvid) {
2969 		ldv = p_cfgp->ser_ldvid;
2970 		/*
2971 		 * Unmask the system interrupt states.
2972 		 */
2973 		(void) nxge_fzc_sys_err_mask_set(nxgep, SYS_ERR_SMX_MASK |
2974 			SYS_ERR_IPP_MASK | SYS_ERR_TXC_MASK |
2975 			SYS_ERR_ZCP_MASK);
2976 	}
2977 	ldvp->ldv = (uint8_t)ldv;
2978 	ldvp->is_syserr = B_TRUE;
2979 	ldvp->ldv_intr_handler = nxge_syserr_intr;
2980 	ldvp->ldv_ldf_masks = 0;
2981 	ldvp->nxgep = nxgep;
2982 	ldgvp->ldvp_syserr = ldvp;
2983 
2984 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
2985 		"==> nxge_ldgv_init_n2(syserr): maxldvs %d ldv %d "
2986 		"ldg %d ldgptr $%p ldvptr p%p",
2987 		maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
2988 
2989 	if (own_sys_err && p_cfgp->ser_ldvid) {
2990 		(void) nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
2991 	} else {
2992 		ldvp++;
2993 	}
2994 
2995 	nldvs++;
2996 
2997 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
2998 		"(before rx) func %d nldvs %d navail %d nrequired %d",
2999 		func, nldvs, *navail_p, *nrequired_p));
3000 
3001 	/*
3002 	 * Start with RDC to configure logical devices for each group.
3003 	 */
3004 	chn_start = p_cfgp->ldg_chn_start;
3005 	set = &nxgep->rx_set;
3006 	for (channel = 0; channel < NXGE_MAX_RDCS; channel++) {
3007 		if ((1 << channel) & set->owned.map) {
3008 			ldvp->is_rxdma = B_TRUE;
3009 			ldvp->ldv = (uint8_t)channel + NXGE_RDMA_LD_START;
3010 			ldvp->channel = channel;
3011 			ldvp->vdma_index = (uint8_t)channel;
3012 			ldvp->ldv_intr_handler = nxge_rx_intr;
3013 			ldvp->ldv_ldf_masks = 0;
3014 			ldvp->nxgep = nxgep;
3015 			ldgp->ldg = p_cfgp->ldg[chn_start];
3016 
3017 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
3018 			    "==> nxge_ldgv_init_n2(rx%d): maxldvs %d ldv %d "
3019 			    "ldg %d ldgptr 0x%016llx ldvptr 0x%016llx",
3020 			    i, maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
3021 			nxge_ldgv_setup(&ldgp, &ldvp, ldvp->ldv,
3022 			    endldg, nrequired_p);
3023 			nldvs++;
3024 			chn_start++;
3025 		}
3026 	}
3027 
3028 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
3029 		"func %d nldvs %d navail %d nrequired %d",
3030 		func, nldvs, *navail_p, *nrequired_p));
3031 
3032 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
3033 		"func %d nldvs %d navail %d nrequired %d ldgp 0x%llx "
3034 		"ldvp 0x%llx",
3035 		func, nldvs, *navail_p, *nrequired_p, ldgp, ldvp));
3036 	/*
3037 	 * Transmit DMA channels.
3038 	 */
3039 	chn_start = p_cfgp->ldg_chn_start + 8;
3040 	set = &nxgep->tx_set;
3041 	for (channel = 0; channel < NXGE_MAX_TDCS; channel++) {
3042 		if ((1 << channel) & set->owned.map) {
3043 			ldvp->is_txdma = B_TRUE;
3044 			ldvp->ldv = (uint8_t)channel + NXGE_TDMA_LD_START;
3045 			ldvp->channel = channel;
3046 			ldvp->vdma_index = (uint8_t)channel;
3047 			ldvp->ldv_intr_handler = nxge_tx_intr;
3048 			ldvp->ldv_ldf_masks = 0;
3049 			ldgp->ldg = p_cfgp->ldg[chn_start];
3050 			ldvp->nxgep = nxgep;
3051 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
3052 			    "==> nxge_ldgv_init_n2(tx%d): maxldvs %d ldv %d "
3053 			    "ldg %d ldgptr %p ldvptr %p",
3054 			    channel, maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
3055 			nxge_ldgv_setup(&ldgp, &ldvp, ldvp->ldv,
3056 			    endldg, nrequired_p);
3057 			nldvs++;
3058 			chn_start++;
3059 		}
3060 	}
3061 
3062 	ldgvp->ldg_intrs = *nrequired_p;
3063 	ldgvp->nldvs = (uint8_t)nldvs;
3064 
3065 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
3066 		"func %d nldvs %d maxgrps %d navail %d nrequired %d",
3067 		func, nldvs, maxldgs, *navail_p, *nrequired_p));
3068 
3069 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_init_n2"));
3070 	return (status);
3071 }
3072 
3073 /*
3074  * Interrupts related interface functions.
3075  */
3076 
3077 nxge_status_t
3078 nxge_ldgv_init(p_nxge_t nxgep, int *navail_p, int *nrequired_p)
3079 {
3080 	int i, maxldvs, maxldgs, nldvs;
3081 	int ldv, ldg, endldg, ngrps;
3082 	uint8_t func;
3083 	uint8_t channel;
3084 	boolean_t own_sys_err = B_FALSE, own_fzc = B_FALSE;
3085 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
3086 	p_nxge_hw_pt_cfg_t p_cfgp;
3087 	p_nxge_ldgv_t ldgvp;
3088 	p_nxge_ldg_t ldgp, ptr;
3089 	p_nxge_ldv_t ldvp;
3090 	nxge_grp_set_t *set;
3091 
3092 	nxge_status_t status = NXGE_OK;
3093 
3094 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init"));
3095 	if (!*navail_p) {
3096 		*nrequired_p = 0;
3097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3098 			"<== nxge_ldgv_init:no avail"));
3099 		return (NXGE_ERROR);
3100 	}
3101 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
3102 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
3103 
3104 	nldvs = p_cfgp->tdc.owned + p_cfgp->max_rdcs;
3105 
3106 	/*
3107 	 * If function zero instance, it needs to handle the system error
3108 	 * interrupts.
3109 	 */
3110 	func = nxgep->function_num;
3111 	if (func == 0) {
3112 		nldvs++;
3113 		own_sys_err = B_TRUE;
3114 	} else {
3115 		/* use timer */
3116 		nldvs++;
3117 	}
3118 
3119 	/*
3120 	 * Assume single partition, each function owns mac.
3121 	 */
3122 	if (!nxge_use_partition) {
3123 		/* mac */
3124 		nldvs++;
3125 		/* MIF */
3126 		nldvs++;
3127 		own_fzc = B_TRUE;
3128 	}
3129 	maxldvs = nldvs;
3130 	maxldgs = p_cfgp->max_ldgs;
3131 	if (!maxldvs || !maxldgs) {
3132 		/* No devices configured. */
3133 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_init: "
3134 			"no logical devices or groups configured."));
3135 		return (NXGE_ERROR);
3136 	}
3137 	ldgvp = nxgep->ldgvp;
3138 	if (ldgvp == NULL) {
3139 		ldgvp = KMEM_ZALLOC(sizeof (nxge_ldgv_t), KM_SLEEP);
3140 		nxgep->ldgvp = ldgvp;
3141 		ldgvp->maxldgs = (uint8_t)maxldgs;
3142 		ldgvp->maxldvs = (uint8_t)maxldvs;
3143 		ldgp = ldgvp->ldgp = KMEM_ZALLOC(sizeof (nxge_ldg_t) * maxldgs,
3144 			KM_SLEEP);
3145 		ldvp = ldgvp->ldvp = KMEM_ZALLOC(sizeof (nxge_ldv_t) * maxldvs,
3146 			KM_SLEEP);
3147 	}
3148 	ldgvp->ndma_ldvs = p_cfgp->tdc.owned + p_cfgp->max_rdcs;
3149 	ldgvp->tmres = NXGE_TIMER_RESO;
3150 
3151 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3152 		"==> nxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d",
3153 		maxldvs, maxldgs, nldvs));
3154 	ldg = p_cfgp->start_ldg;
3155 	ptr = ldgp;
3156 	for (i = 0; i < maxldgs; i++) {
3157 		ptr->func = func;
3158 		ptr->arm = B_TRUE;
3159 		ptr->vldg_index = (uint8_t)i;
3160 		ptr->ldg_timer = NXGE_TIMER_LDG;
3161 		ptr->ldg = ldg++;
3162 		ptr->sys_intr_handler = nxge_intr;
3163 		ptr->nldvs = 0;
3164 		ptr->nxgep = nxgep;
3165 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3166 			"==> nxge_ldgv_init: maxldvs %d maxldgs %d ldg %d",
3167 			maxldvs, maxldgs, ptr->ldg));
3168 		ptr++;
3169 	}
3170 
3171 	ldg = p_cfgp->start_ldg;
3172 	if (maxldgs > *navail_p) {
3173 		ngrps = *navail_p;
3174 	} else {
3175 		ngrps = maxldgs;
3176 	}
3177 	endldg = ldg + ngrps;
3178 
3179 	/*
3180 	 * Receive DMA channels.
3181 	 */
3182 	nldvs = 0;
3183 	ldgvp->nldvs = 0;
3184 	ldgp->ldvp = NULL;
3185 	*nrequired_p = 0;
3186 
3187 	/*
3188 	 * Start with RDC to configure logical devices for each group.
3189 	 */
3190 	set = &nxgep->rx_set;
3191 	for (channel = 0; channel < NXGE_MAX_RDCS; channel++) {
3192 		if ((1 << channel) & set->owned.map) {
3193 			/* For now, <channel & <vdma_index> are the same. */
3194 			ldvp->is_rxdma = B_TRUE;
3195 			ldvp->ldv = (uint8_t)channel + NXGE_RDMA_LD_START;
3196 			ldvp->channel = channel;
3197 			ldvp->vdma_index = (uint8_t)channel;
3198 			ldvp->ldv_intr_handler = nxge_rx_intr;
3199 			ldvp->ldv_ldf_masks = 0;
3200 			ldvp->use_timer = B_FALSE;
3201 			ldvp->nxgep = nxgep;
3202 			nxge_ldgv_setup(&ldgp, &ldvp, ldvp->ldv,
3203 			    endldg, nrequired_p);
3204 			nldvs++;
3205 		}
3206 	}
3207 
3208 	/*
3209 	 * Transmit DMA channels.
3210 	 */
3211 	set = &nxgep->tx_set;
3212 	for (channel = 0; channel < NXGE_MAX_TDCS; channel++) {
3213 		if ((1 << channel) & set->owned.map) {
3214 			/* For now, <channel & <vdma_index> are the same. */
3215 			ldvp->is_txdma = B_TRUE;
3216 			ldvp->ldv = (uint8_t)channel + NXGE_TDMA_LD_START;
3217 			ldvp->channel = channel;
3218 			ldvp->vdma_index = (uint8_t)channel;
3219 			ldvp->ldv_intr_handler = nxge_tx_intr;
3220 			ldvp->ldv_ldf_masks = 0;
3221 			ldvp->use_timer = B_FALSE;
3222 			ldvp->nxgep = nxgep;
3223 			nxge_ldgv_setup(&ldgp, &ldvp, ldvp->ldv,
3224 			    endldg, nrequired_p);
3225 			nldvs++;
3226 		}
3227 	}
3228 
3229 	if (own_fzc) {
3230 		ldv = NXGE_MIF_LD;
3231 		ldvp->ldv = (uint8_t)ldv;
3232 		ldvp->is_mif = B_TRUE;
3233 		ldvp->ldv_intr_handler = nxge_mif_intr;
3234 		ldvp->ldv_ldf_masks = 0;
3235 		ldvp->use_timer = B_FALSE;
3236 		ldvp->nxgep = nxgep;
3237 		nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
3238 		nldvs++;
3239 	}
3240 	/*
3241 	 * MAC port (function zero control)
3242 	 */
3243 	if (own_fzc) {
3244 		ldvp->is_mac = B_TRUE;
3245 		ldvp->ldv_intr_handler = nxge_mac_intr;
3246 		ldvp->ldv_ldf_masks = 0;
3247 		ldv = func + NXGE_MAC_LD_START;
3248 		ldvp->ldv = (uint8_t)ldv;
3249 		ldvp->use_timer = B_FALSE;
3250 		ldvp->nxgep = nxgep;
3251 		nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
3252 		nldvs++;
3253 	}
3254 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init: "
3255 		"func %d nldvs %d navail %d nrequired %d",
3256 		func, nldvs, *navail_p, *nrequired_p));
3257 	/*
3258 	 * Function 0 owns system error interrupts.
3259 	 */
3260 	ldvp->use_timer = B_TRUE;
3261 	if (own_sys_err) {
3262 		ldv = NXGE_SYS_ERROR_LD;
3263 		ldvp->ldv = (uint8_t)ldv;
3264 		ldvp->is_syserr = B_TRUE;
3265 		ldvp->ldv_intr_handler = nxge_syserr_intr;
3266 		ldvp->ldv_ldf_masks = 0;
3267 		ldvp->nxgep = nxgep;
3268 		ldgvp->ldvp_syserr = ldvp;
3269 		/*
3270 		 * Unmask the system interrupt states.
3271 		 */
3272 		(void) nxge_fzc_sys_err_mask_set(nxgep, SYS_ERR_SMX_MASK |
3273 			SYS_ERR_IPP_MASK | SYS_ERR_TXC_MASK |
3274 			SYS_ERR_ZCP_MASK);
3275 
3276 		(void) nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
3277 		nldvs++;
3278 	} else {
3279 		ldv = NXGE_SYS_ERROR_LD;
3280 		ldvp->ldv = (uint8_t)ldv;
3281 		ldvp->is_syserr = B_TRUE;
3282 		ldvp->ldv_intr_handler = nxge_syserr_intr;
3283 		ldvp->nxgep = nxgep;
3284 		ldvp->ldv_ldf_masks = 0;
3285 		ldgvp->ldvp_syserr = ldvp;
3286 	}
3287 
3288 	ldgvp->ldg_intrs = *nrequired_p;
3289 
3290 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init: "
3291 		"func %d nldvs %d navail %d nrequired %d",
3292 		func, nldvs, *navail_p, *nrequired_p));
3293 
3294 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_init"));
3295 	return (status);
3296 }
3297 
3298 nxge_status_t
3299 nxge_ldgv_uninit(p_nxge_t nxgep)
3300 {
3301 	p_nxge_ldgv_t ldgvp;
3302 
3303 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_uninit"));
3304 	ldgvp = nxgep->ldgvp;
3305 	if (ldgvp == NULL) {
3306 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_uninit: "
3307 				"no logical group configured."));
3308 		return (NXGE_OK);
3309 	}
3310 	if (ldgvp->ldgp) {
3311 		KMEM_FREE(ldgvp->ldgp, sizeof (nxge_ldg_t) * ldgvp->maxldgs);
3312 	}
3313 	if (ldgvp->ldvp) {
3314 		KMEM_FREE(ldgvp->ldvp, sizeof (nxge_ldv_t) * ldgvp->maxldvs);
3315 	}
3316 	KMEM_FREE(ldgvp, sizeof (nxge_ldgv_t));
3317 	nxgep->ldgvp = NULL;
3318 
3319 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_uninit"));
3320 	return (NXGE_OK);
3321 }
3322 
3323 nxge_status_t
3324 nxge_intr_ldgv_init(p_nxge_t nxgep)
3325 {
3326 	nxge_status_t status = NXGE_OK;
3327 
3328 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_ldgv_init"));
3329 	/*
3330 	 * Configure the logical device group numbers, state vectors and
3331 	 * interrupt masks for each logical device.
3332 	 */
3333 	status = nxge_fzc_intr_init(nxgep);
3334 
3335 	/*
3336 	 * Configure logical device masks and timers.
3337 	 */
3338 	status = nxge_intr_mask_mgmt(nxgep);
3339 
3340 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_ldgv_init"));
3341 	return (status);
3342 }
3343 
3344 nxge_status_t
3345 nxge_intr_mask_mgmt(p_nxge_t nxgep)
3346 {
3347 	p_nxge_ldgv_t ldgvp;
3348 	p_nxge_ldg_t ldgp;
3349 	p_nxge_ldv_t ldvp;
3350 	npi_handle_t handle;
3351 	int i, j;
3352 	npi_status_t rs = NPI_SUCCESS;
3353 
3354 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_mask_mgmt"));
3355 
3356 	if ((ldgvp = nxgep->ldgvp) == NULL) {
3357 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3358 			"<== nxge_intr_mask_mgmt: Null ldgvp"));
3359 		return (NXGE_ERROR);
3360 	}
3361 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3362 	ldgp = ldgvp->ldgp;
3363 	ldvp = ldgvp->ldvp;
3364 	if (ldgp == NULL || ldvp == NULL) {
3365 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3366 			"<== nxge_intr_mask_mgmt: Null ldgp or ldvp"));
3367 		return (NXGE_ERROR);
3368 	}
3369 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3370 		"==> nxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs));
3371 	/* Initialize masks. */
3372 	if (nxgep->niu_type != N2_NIU) {
3373 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3374 			"==> nxge_intr_mask_mgmt(Neptune): # intrs %d ",
3375 			ldgvp->ldg_intrs));
3376 		for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
3377 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
3378 				"==> nxge_intr_mask_mgmt(Neptune): # ldv %d "
3379 				"in group %d", ldgp->nldvs, ldgp->ldg));
3380 			for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
3381 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
3382 					"==> nxge_intr_mask_mgmt: set ldv # %d "
3383 					"for ldg %d", ldvp->ldv, ldgp->ldg));
3384 				rs = npi_intr_mask_set(handle, ldvp->ldv,
3385 					ldvp->ldv_ldf_masks);
3386 				if (rs != NPI_SUCCESS) {
3387 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3388 						"<== nxge_intr_mask_mgmt: "
3389 						"set mask failed "
3390 						" rs 0x%x ldv %d mask 0x%x",
3391 						rs, ldvp->ldv,
3392 						ldvp->ldv_ldf_masks));
3393 					return (NXGE_ERROR | rs);
3394 				}
3395 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
3396 					"==> nxge_intr_mask_mgmt: "
3397 					"set mask OK "
3398 					" rs 0x%x ldv %d mask 0x%x",
3399 					rs, ldvp->ldv,
3400 					ldvp->ldv_ldf_masks));
3401 			}
3402 		}
3403 	}
3404 	ldgp = ldgvp->ldgp;
3405 	/* Configure timer and arm bit */
3406 	for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
3407 		rs = npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
3408 			ldgp->arm, ldgp->ldg_timer);
3409 		if (rs != NPI_SUCCESS) {
3410 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3411 				"<== nxge_intr_mask_mgmt: "
3412 				"set timer failed "
3413 				" rs 0x%x dg %d timer 0x%x",
3414 				rs, ldgp->ldg, ldgp->ldg_timer));
3415 			return (NXGE_ERROR | rs);
3416 		}
3417 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3418 			"==> nxge_intr_mask_mgmt: "
3419 			"set timer OK "
3420 			" rs 0x%x ldg %d timer 0x%x",
3421 			rs, ldgp->ldg, ldgp->ldg_timer));
3422 	}
3423 
3424 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_mask_mgmt"));
3425 	return (NXGE_OK);
3426 }
3427 
3428 nxge_status_t
3429 nxge_intr_mask_mgmt_set(p_nxge_t nxgep, boolean_t on)
3430 {
3431 	p_nxge_ldgv_t ldgvp;
3432 	p_nxge_ldg_t ldgp;
3433 	p_nxge_ldv_t ldvp;
3434 	npi_handle_t handle;
3435 	int i, j;
3436 	npi_status_t rs = NPI_SUCCESS;
3437 
3438 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3439 		"==> nxge_intr_mask_mgmt_set (%d)", on));
3440 
3441 	if (nxgep->niu_type == N2_NIU) {
3442 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3443 			"<== nxge_intr_mask_mgmt_set (%d) not set (N2/NIU)",
3444 			on));
3445 		return (NXGE_ERROR);
3446 	}
3447 
3448 	if ((ldgvp = nxgep->ldgvp) == NULL) {
3449 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3450 			"==> nxge_intr_mask_mgmt_set: Null ldgvp"));
3451 		return (NXGE_ERROR);
3452 	}
3453 
3454 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3455 	ldgp = ldgvp->ldgp;
3456 	ldvp = ldgvp->ldvp;
3457 	if (ldgp == NULL || ldvp == NULL) {
3458 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3459 			"<== nxge_intr_mask_mgmt_set: Null ldgp or ldvp"));
3460 		return (NXGE_ERROR);
3461 	}
3462 	/* set masks. */
3463 	for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
3464 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3465 			"==> nxge_intr_mask_mgmt_set: flag %d ldg %d"
3466 			"set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs));
3467 		for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
3468 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
3469 				"==> nxge_intr_mask_mgmt_set: "
3470 				"for %d %d flag %d", i, j, on));
3471 			if (on) {
3472 				ldvp->ldv_ldf_masks = 0;
3473 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
3474 					"==> nxge_intr_mask_mgmt_set: "
3475 					"ON mask off"));
3476 			} else if (!on) {
3477 				ldvp->ldv_ldf_masks = (uint8_t)LD_IM1_MASK;
3478 				NXGE_DEBUG_MSG((nxgep, INT_CTL,
3479 					"==> nxge_intr_mask_mgmt_set:mask on"));
3480 			}
3481 			rs = npi_intr_mask_set(handle, ldvp->ldv,
3482 				ldvp->ldv_ldf_masks);
3483 			if (rs != NPI_SUCCESS) {
3484 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3485 					"==> nxge_intr_mask_mgmt_set: "
3486 					"set mask failed "
3487 					" rs 0x%x ldv %d mask 0x%x",
3488 					rs, ldvp->ldv, ldvp->ldv_ldf_masks));
3489 				return (NXGE_ERROR | rs);
3490 			}
3491 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
3492 				"==> nxge_intr_mask_mgmt_set: flag %d"
3493 				"set mask OK "
3494 				" ldv %d mask 0x%x",
3495 				on, ldvp->ldv, ldvp->ldv_ldf_masks));
3496 		}
3497 	}
3498 
3499 	ldgp = ldgvp->ldgp;
3500 	/* set the arm bit */
3501 	for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
3502 		if (on && !ldgp->arm) {
3503 			ldgp->arm = B_TRUE;
3504 		} else if (!on && ldgp->arm) {
3505 			ldgp->arm = B_FALSE;
3506 		}
3507 		rs = npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
3508 			ldgp->arm, ldgp->ldg_timer);
3509 		if (rs != NPI_SUCCESS) {
3510 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3511 				"<== nxge_intr_mask_mgmt_set: "
3512 				"set timer failed "
3513 				" rs 0x%x ldg %d timer 0x%x",
3514 				rs, ldgp->ldg, ldgp->ldg_timer));
3515 			return (NXGE_ERROR | rs);
3516 		}
3517 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
3518 			"==> nxge_intr_mask_mgmt_set: OK (flag %d) "
3519 			"set timer "
3520 			" ldg %d timer 0x%x",
3521 			on, ldgp->ldg, ldgp->ldg_timer));
3522 	}
3523 
3524 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_mask_mgmt_set"));
3525 	return (NXGE_OK);
3526 }
3527 
3528 static nxge_status_t
3529 nxge_get_mac_addr_properties(p_nxge_t nxgep)
3530 {
3531 #if defined(_BIG_ENDIAN)
3532 	uchar_t *prop_val;
3533 	uint_t prop_len;
3534 	uint_t j;
3535 #endif
3536 	uint_t i;
3537 	uint8_t func_num;
3538 	boolean_t compute_macs = B_TRUE;
3539 
3540 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_get_mac_addr_properties "));
3541 
3542 #if defined(_BIG_ENDIAN)
3543 	/*
3544 	 * Get the ethernet address.
3545 	 */
3546 	(void) localetheraddr((struct ether_addr *)NULL, &nxgep->ouraddr);
3547 
3548 	/*
3549 	 * Check if it is an adapter with its own local mac address If it is
3550 	 * present, override the system mac address.
3551 	 */
3552 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
3553 			"local-mac-address", &prop_val,
3554 			&prop_len) == DDI_PROP_SUCCESS) {
3555 		if (prop_len == ETHERADDRL) {
3556 			nxgep->factaddr = *(p_ether_addr_t)prop_val;
3557 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Local mac address = "
3558 				"%02x:%02x:%02x:%02x:%02x:%02x",
3559 				prop_val[0], prop_val[1], prop_val[2],
3560 				prop_val[3], prop_val[4], prop_val[5]));
3561 		}
3562 		ddi_prop_free(prop_val);
3563 	}
3564 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
3565 			"local-mac-address?", &prop_val,
3566 			&prop_len) == DDI_PROP_SUCCESS) {
3567 		if (strncmp("true", (caddr_t)prop_val, (size_t)prop_len) == 0) {
3568 			nxgep->ouraddr = nxgep->factaddr;
3569 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
3570 				"Using local MAC address"));
3571 		}
3572 		ddi_prop_free(prop_val);
3573 	} else {
3574 		nxgep->ouraddr = nxgep->factaddr;
3575 	}
3576 
3577 	if ((!nxgep->vpd_info.present) ||
3578 	    (nxge_is_valid_local_mac(nxgep->factaddr)))
3579 		goto got_mac_addr;
3580 
3581 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_get_mac_addr_properties: "
3582 	    "MAC address from properties is not valid...reading from PROM"));
3583 
3584 #endif
3585 	if (!nxgep->vpd_info.ver_valid) {
3586 		(void) nxge_espc_mac_addrs_get(nxgep);
3587 		if (!nxge_is_valid_local_mac(nxgep->factaddr)) {
3588 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Failed to get "
3589 			    "MAC address"));
3590 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3591 			    "[%s] invalid...please update",
3592 			    nxgep->vpd_info.ver));
3593 			return (NXGE_ERROR);
3594 		}
3595 		nxgep->ouraddr = nxgep->factaddr;
3596 		goto got_mac_addr;
3597 	}
3598 	/*
3599 	 * First get the MAC address from the info in the VPD data read
3600 	 * from the EEPROM.
3601 	 */
3602 	nxge_espc_get_next_mac_addr(nxgep->vpd_info.mac_addr,
3603 	    nxgep->function_num, &nxgep->factaddr);
3604 
3605 	if (!nxge_is_valid_local_mac(nxgep->factaddr)) {
3606 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
3607 		    "nxge_get_mac_addr_properties: "
3608 		    "MAC address in EEPROM VPD data not valid"
3609 		    "...reading from NCR registers"));
3610 		(void) nxge_espc_mac_addrs_get(nxgep);
3611 		if (!nxge_is_valid_local_mac(nxgep->factaddr)) {
3612 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Failed to get "
3613 			    "MAC address"));
3614 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3615 			    "[%s] invalid...please update",
3616 			    nxgep->vpd_info.ver));
3617 			return (NXGE_ERROR);
3618 		}
3619 	}
3620 
3621 	nxgep->ouraddr = nxgep->factaddr;
3622 
3623 got_mac_addr:
3624 	func_num = nxgep->function_num;
3625 
3626 	/*
3627 	 * Note: mac-addresses property is the list of mac addresses for a
3628 	 * port. NXGE_MAX_MMAC_ADDRS is the total number of MAC addresses
3629 	 * allocated for a board.
3630 	 */
3631 	nxgep->nxge_mmac_info.total_factory_macs = NXGE_MAX_MMAC_ADDRS;
3632 
3633 #if defined(_BIG_ENDIAN)
3634 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
3635 	    "mac-addresses", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
3636 		/*
3637 		 * XAUI may have up to 18 MACs, more than the XMAC can
3638 		 * use (1 unique MAC plus 16 alternate MACs)
3639 		 */
3640 		nxgep->nxge_mmac_info.num_factory_mmac =
3641 		    prop_len / ETHERADDRL - 1;
3642 		if (nxgep->nxge_mmac_info.num_factory_mmac >
3643 		    XMAC_MAX_ALT_ADDR_ENTRY) {
3644 			nxgep->nxge_mmac_info.num_factory_mmac =
3645 			    XMAC_MAX_ALT_ADDR_ENTRY;
3646 		}
3647 
3648 		for (i = 1; i <= nxgep->nxge_mmac_info.num_factory_mmac; i++) {
3649 			for (j = 0; j < ETHERADDRL; j++) {
3650 				nxgep->nxge_mmac_info.factory_mac_pool[i][j] =
3651 				    *(prop_val + (i * ETHERADDRL) + j);
3652 			}
3653 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
3654 			    "nxge_get_mac_addr_properties: Alt mac[%d] from "
3655 			    "mac-addresses property[%2x:%2x:%2x:%2x:%2x:%2x]",
3656 			    i, nxgep->nxge_mmac_info.factory_mac_pool[i][0],
3657 			    nxgep->nxge_mmac_info.factory_mac_pool[i][1],
3658 			    nxgep->nxge_mmac_info.factory_mac_pool[i][2],
3659 			    nxgep->nxge_mmac_info.factory_mac_pool[i][3],
3660 			    nxgep->nxge_mmac_info.factory_mac_pool[i][4],
3661 			    nxgep->nxge_mmac_info.factory_mac_pool[i][5]));
3662 		}
3663 
3664 		compute_macs = B_FALSE;
3665 		ddi_prop_free(prop_val);
3666 		goto got_mmac_info;
3667 	}
3668 #endif
3669 	/*
3670 	 * total_factory_macs = 32
3671 	 * num_factory_mmac = (32 >> (nports/2)) - 1
3672 	 * So if nports = 4, then num_factory_mmac =  7
3673 	 *    if nports = 2, then num_factory_mmac = 15
3674 	 */
3675 	nxgep->nxge_mmac_info.num_factory_mmac =
3676 	    ((nxgep->nxge_mmac_info.total_factory_macs >>
3677 	    (nxgep->nports >> 1))) - 1;
3678 
3679 got_mmac_info:
3680 
3681 	if ((nxgep->function_num < 2) &&
3682 	    (nxgep->nxge_mmac_info.num_factory_mmac >
3683 	    XMAC_MAX_ALT_ADDR_ENTRY)) {
3684 		nxgep->nxge_mmac_info.num_factory_mmac =
3685 		    XMAC_MAX_ALT_ADDR_ENTRY;
3686 	} else if ((nxgep->function_num > 1) &&
3687 	    (nxgep->nxge_mmac_info.num_factory_mmac >
3688 	    BMAC_MAX_ALT_ADDR_ENTRY)) {
3689 		nxgep->nxge_mmac_info.num_factory_mmac =
3690 		    BMAC_MAX_ALT_ADDR_ENTRY;
3691 	}
3692 
3693 	for (i = 0; i <= nxgep->nxge_mmac_info.num_mmac; i++) {
3694 		(void) npi_mac_altaddr_disable(nxgep->npi_handle,
3695 			NXGE_GET_PORT_NUM(func_num), i);
3696 	}
3697 
3698 	(void) nxge_init_mmac(nxgep, compute_macs);
3699 	return (NXGE_OK);
3700 }
3701 
3702 void
3703 nxge_get_xcvr_properties(p_nxge_t nxgep)
3704 {
3705 	uchar_t *prop_val;
3706 	uint_t prop_len;
3707 
3708 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_get_xcvr_properties"));
3709 
3710 	/*
3711 	 * Read the type of physical layer interface being used.
3712 	 */
3713 	nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3714 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
3715 			"phy-type", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
3716 		if (strncmp("pcs", (caddr_t)prop_val,
3717 				(size_t)prop_len) == 0) {
3718 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3719 		} else {
3720 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3721 		}
3722 		ddi_prop_free(prop_val);
3723 	} else if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
3724 			"phy-interface", &prop_val,
3725 			&prop_len) == DDI_PROP_SUCCESS) {
3726 		if (strncmp("pcs", (caddr_t)prop_val, (size_t)prop_len) == 0) {
3727 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3728 		} else {
3729 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3730 		}
3731 		ddi_prop_free(prop_val);
3732 	}
3733 }
3734 
3735 /*
3736  * Static functions start here.
3737  */
3738 
3739 static void
3740 nxge_ldgv_setup(p_nxge_ldg_t *ldgp, p_nxge_ldv_t *ldvp, uint8_t ldv,
3741 	uint8_t endldg, int *ngrps)
3742 {
3743 	NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup"));
3744 	/* Assign the group number for each device. */
3745 	(*ldvp)->ldg_assigned = (*ldgp)->ldg;
3746 	(*ldvp)->ldgp = *ldgp;
3747 	(*ldvp)->ldv = ldv;
3748 
3749 	NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup: "
3750 		"ldv %d endldg %d ldg %d, ldvp $%p",
3751 		ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
3752 
3753 	(*ldgp)->nldvs++;
3754 	if ((*ldgp)->ldg == (endldg - 1)) {
3755 		if ((*ldgp)->ldvp == NULL) {
3756 			(*ldgp)->ldvp = *ldvp;
3757 			*ngrps += 1;
3758 			NXGE_DEBUG_MSG((NULL, INT_CTL,
3759 				"==> nxge_ldgv_setup: ngrps %d", *ngrps));
3760 		}
3761 		NXGE_DEBUG_MSG((NULL, INT_CTL,
3762 			"==> nxge_ldgv_setup: ldvp $%p ngrps %d",
3763 			*ldvp, *ngrps));
3764 		++*ldvp;
3765 	} else {
3766 		(*ldgp)->ldvp = *ldvp;
3767 		*ngrps += 1;
3768 		NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup(done): "
3769 			"ldv %d endldg %d ldg %d, ldvp $%p",
3770 			ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
3771 		(*ldvp) = ++*ldvp;
3772 		(*ldgp) = ++*ldgp;
3773 		NXGE_DEBUG_MSG((NULL, INT_CTL,
3774 			"==> nxge_ldgv_setup: new ngrps %d", *ngrps));
3775 	}
3776 
3777 	NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup: "
3778 		"ldv %d ldvp $%p endldg %d ngrps %d",
3779 		ldv, ldvp, endldg, *ngrps));
3780 
3781 	NXGE_DEBUG_MSG((NULL, INT_CTL, "<== nxge_ldgv_setup"));
3782 }
3783 
3784 /*
3785  * Note: This function assumes the following distribution of mac
3786  * addresses among 4 ports in neptune:
3787  *
3788  *      -------------
3789  *    0|            |0 - local-mac-address for fn 0
3790  *      -------------
3791  *    1|            |1 - local-mac-address for fn 1
3792  *      -------------
3793  *    2|            |2 - local-mac-address for fn 2
3794  *      -------------
3795  *    3|            |3 - local-mac-address for fn 3
3796  *      -------------
3797  *     |            |4 - Start of alt. mac addr. for fn 0
3798  *     |            |
3799  *     |            |
3800  *     |            |10
3801  *     --------------
3802  *     |            |11 - Start of alt. mac addr. for fn 1
3803  *     |            |
3804  *     |            |
3805  *     |            |17
3806  *     --------------
3807  *     |            |18 - Start of alt. mac addr. for fn 2
3808  *     |            |
3809  *     |            |
3810  *     |            |24
3811  *     --------------
3812  *     |            |25 - Start of alt. mac addr. for fn 3
3813  *     |            |
3814  *     |            |
3815  *     |            |31
3816  *     --------------
3817  *
3818  * For N2/NIU the mac addresses is from XAUI card.
3819  *
3820  * When 'compute_addrs' is true, the alternate mac addresses are computed
3821  * using the unique mac address as base. Otherwise the alternate addresses
3822  * are assigned from the list read off the 'mac-addresses' property.
3823  */
3824 
3825 static void
3826 nxge_init_mmac(p_nxge_t nxgep, boolean_t compute_addrs)
3827 {
3828 	int slot;
3829 	uint8_t func_num;
3830 	uint16_t *base_mmac_addr;
3831 	uint32_t alt_mac_ls4b;
3832 	uint16_t *mmac_addr;
3833 	uint32_t base_mac_ls4b; /* least significant 4 bytes */
3834 	nxge_mmac_t *mmac_info;
3835 	npi_mac_addr_t mac_addr;
3836 
3837 	func_num = nxgep->function_num;
3838 	base_mmac_addr = (uint16_t *)&nxgep->factaddr;
3839 	mmac_info = (nxge_mmac_t *)&nxgep->nxge_mmac_info;
3840 
3841 	if (compute_addrs) {
3842 		base_mac_ls4b = ((uint32_t)base_mmac_addr[1]) << 16 |
3843 		    base_mmac_addr[2];
3844 
3845 		if (nxgep->niu_type == N2_NIU) {
3846 			/* ls4b of 1st altmac */
3847 			alt_mac_ls4b = base_mac_ls4b + 1;
3848 		} else {			/* Neptune */
3849 			alt_mac_ls4b = base_mac_ls4b +
3850 			    (nxgep->nports - func_num) +
3851 			    (func_num * (mmac_info->num_factory_mmac));
3852 		}
3853 	}
3854 
3855 	/* Set flags for unique MAC */
3856 	mmac_info->mac_pool[0].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR;
3857 
3858 	/* Clear flags of all alternate MAC slots */
3859 	for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
3860 		if (slot <= mmac_info->num_factory_mmac)
3861 			mmac_info->mac_pool[slot].flags = MMAC_VENDOR_ADDR;
3862 		else
3863 			mmac_info->mac_pool[slot].flags = 0;
3864 	}
3865 
3866 	/* Generate and store factory alternate MACs */
3867 	for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) {
3868 		mmac_addr = (uint16_t *)&mmac_info->factory_mac_pool[slot];
3869 		if (compute_addrs) {
3870 			mmac_addr[0] = base_mmac_addr[0];
3871 			mac_addr.w2 = mmac_addr[0];
3872 
3873 			mmac_addr[1] = (alt_mac_ls4b >> 16) & 0x0FFFF;
3874 			mac_addr.w1 = mmac_addr[1];
3875 
3876 			mmac_addr[2] = alt_mac_ls4b & 0x0FFFF;
3877 			mac_addr.w0 = mmac_addr[2];
3878 
3879 			alt_mac_ls4b++;
3880 		} else {
3881 			mac_addr.w2 = mmac_addr[0];
3882 			mac_addr.w1 = mmac_addr[1];
3883 			mac_addr.w0 = mmac_addr[2];
3884 		}
3885 
3886 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
3887 		    "mac_pool_addr[%2x:%2x:%2x:%2x:%2x:%2x] npi_addr[%x%x%x]",
3888 		    mmac_info->factory_mac_pool[slot][0],
3889 		    mmac_info->factory_mac_pool[slot][1],
3890 		    mmac_info->factory_mac_pool[slot][2],
3891 		    mmac_info->factory_mac_pool[slot][3],
3892 		    mmac_info->factory_mac_pool[slot][4],
3893 		    mmac_info->factory_mac_pool[slot][5],
3894 		    mac_addr.w0, mac_addr.w1, mac_addr.w2));
3895 		/*
3896 		 * slot minus 1 because npi_mac_altaddr_entry expects 0
3897 		 * for the first alternate mac address.
3898 		 */
3899 		(void) npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET,
3900 			NXGE_GET_PORT_NUM(func_num), slot - 1, &mac_addr);
3901 	}
3902 	/* Initialize the first two parameters for mmac kstat */
3903 	nxgep->statsp->mmac_stats.mmac_max_cnt = mmac_info->num_mmac;
3904 	nxgep->statsp->mmac_stats.mmac_avail_cnt = mmac_info->num_mmac;
3905 }
3906