xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_main.c (revision c65ebfc7045424bd04a6c7719a27b0ad3399ad54)
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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
24  */
25 
26 /*
27  * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
28  */
29 #include	<sys/nxge/nxge_impl.h>
30 #include	<sys/nxge/nxge_hio.h>
31 #include	<sys/nxge/nxge_rxdma.h>
32 #include	<sys/pcie.h>
33 
34 uint32_t 	nxge_use_partition = 0;		/* debug partition flag */
35 uint32_t 	nxge_dma_obp_props_only = 1;	/* use obp published props */
36 uint32_t 	nxge_use_rdc_intr = 1;		/* debug to assign rdc intr */
37 /*
38  * PSARC/2007/453 MSI-X interrupt limit override
39  */
40 uint32_t	nxge_msi_enable = 2;
41 
42 /*
43  * Software workaround for a Neptune (PCI-E)
44  * hardware interrupt bug which the hardware
45  * may generate spurious interrupts after the
46  * device interrupt handler was removed. If this flag
47  * is enabled, the driver will reset the
48  * hardware when devices are being detached.
49  */
50 uint32_t	nxge_peu_reset_enable = 0;
51 
52 /*
53  * Software workaround for the hardware
54  * checksum bugs that affect packet transmission
55  * and receive:
56  *
57  * Usage of nxge_cksum_offload:
58  *
59  *  (1) nxge_cksum_offload = 0 (default):
60  *	- transmits packets:
61  *	  TCP: uses the hardware checksum feature.
62  *	  UDP: driver will compute the software checksum
63  *	       based on the partial checksum computed
64  *	       by the IP layer.
65  *	- receives packets
66  *	  TCP: marks packets checksum flags based on hardware result.
67  *	  UDP: will not mark checksum flags.
68  *
69  *  (2) nxge_cksum_offload = 1:
70  *	- transmit packets:
71  *	  TCP/UDP: uses the hardware checksum feature.
72  *	- receives packets
73  *	  TCP/UDP: marks packet checksum flags based on hardware result.
74  *
75  *  (3) nxge_cksum_offload = 2:
76  *	- The driver will not register its checksum capability.
77  *	  Checksum for both TCP and UDP will be computed
78  *	  by the stack.
79  *	- The software LSO is not allowed in this case.
80  *
81  *  (4) nxge_cksum_offload > 2:
82  *	- Will be treated as it is set to 2
83  *	  (stack will compute the checksum).
84  *
85  *  (5) If the hardware bug is fixed, this workaround
86  *	needs to be updated accordingly to reflect
87  *	the new hardware revision.
88  */
89 uint32_t	nxge_cksum_offload = 0;
90 
91 /*
92  * Globals: tunable parameters (/etc/system or adb)
93  *
94  */
95 uint32_t 	nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
96 uint32_t 	nxge_rbr_spare_size = 0;
97 uint32_t 	nxge_rcr_size = NXGE_RCR_DEFAULT;
98 uint16_t	nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET;
99 uint32_t 	nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
100 boolean_t 	nxge_no_msg = B_TRUE;		/* control message display */
101 uint32_t 	nxge_no_link_notify = 0;	/* control DL_NOTIFY */
102 uint32_t 	nxge_bcopy_thresh = TX_BCOPY_MAX;
103 uint32_t 	nxge_dvma_thresh = TX_FASTDVMA_MIN;
104 uint32_t 	nxge_dma_stream_thresh = TX_STREAM_MIN;
105 uint32_t	nxge_jumbo_mtu	= TX_JUMBO_MTU;
106 nxge_tx_mode_t	nxge_tx_scheme = NXGE_USE_SERIAL;
107 
108 /* MAX LSO size */
109 #define		NXGE_LSO_MAXLEN	65535
110 uint32_t	nxge_lso_max = NXGE_LSO_MAXLEN;
111 
112 
113 /*
114  * Add tunable to reduce the amount of time spent in the
115  * ISR doing Rx Processing.
116  */
117 uint32_t nxge_max_rx_pkts = 1024;
118 
119 /*
120  * Tunables to manage the receive buffer blocks.
121  *
122  * nxge_rx_threshold_hi: copy all buffers.
123  * nxge_rx_bcopy_size_type: receive buffer block size type.
124  * nxge_rx_threshold_lo: copy only up to tunable block size type.
125  */
126 nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
127 nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
128 nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
129 
130 /* Use kmem_alloc() to allocate data buffers. */
131 #if defined(__sparc)
132 uint32_t	nxge_use_kmem_alloc = 1;
133 #elif defined(__i386)
134 uint32_t	nxge_use_kmem_alloc = 0;
135 #else
136 uint32_t	nxge_use_kmem_alloc = 1;
137 #endif
138 
139 rtrace_t npi_rtracebuf;
140 
141 /*
142  * The hardware sometimes fails to allow enough time for the link partner
143  * to send an acknowledgement for packets that the hardware sent to it. The
144  * hardware resends the packets earlier than it should be in those instances.
145  * This behavior caused some switches to acknowledge the wrong packets
146  * and it triggered the fatal error.
147  * This software workaround is to set the replay timer to a value
148  * suggested by the hardware team.
149  *
150  * PCI config space replay timer register:
151  *     The following replay timeout value is 0xc
152  *     for bit 14:18.
153  */
154 #define	PCI_REPLAY_TIMEOUT_CFG_OFFSET	0xb8
155 #define	PCI_REPLAY_TIMEOUT_SHIFT	14
156 
157 uint32_t	nxge_set_replay_timer = 1;
158 uint32_t	nxge_replay_timeout = 0xc;
159 
160 /*
161  * The transmit serialization sometimes causes
162  * longer sleep before calling the driver transmit
163  * function as it sleeps longer than it should.
164  * The performace group suggests that a time wait tunable
165  * can be used to set the maximum wait time when needed
166  * and the default is set to 1 tick.
167  */
168 uint32_t	nxge_tx_serial_maxsleep = 1;
169 
170 #if	defined(sun4v)
171 /*
172  * Hypervisor N2/NIU services information.
173  */
174 /*
175  * The following is the default API supported:
176  * major 1 and minor 1.
177  *
178  * Please update the MAX_NIU_MAJORS,
179  * MAX_NIU_MINORS, and minor number supported
180  * when the newer Hypervior API interfaces
181  * are added. Also, please update nxge_hsvc_register()
182  * if needed.
183  */
184 static hsvc_info_t niu_hsvc = {
185 	HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
186 	NIU_MINOR_VER, "nxge"
187 };
188 
189 static int nxge_hsvc_register(p_nxge_t);
190 #endif
191 
192 /*
193  * Function Prototypes
194  */
195 static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
196 static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
197 static void nxge_unattach(p_nxge_t);
198 static int nxge_quiesce(dev_info_t *);
199 
200 #if NXGE_PROPERTY
201 static void nxge_remove_hard_properties(p_nxge_t);
202 #endif
203 
204 /*
205  * These two functions are required by nxge_hio.c
206  */
207 extern int nxge_m_mmac_remove(void *arg, int slot);
208 extern void nxge_grp_cleanup(p_nxge_t nxge);
209 
210 static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
211 
212 static nxge_status_t nxge_setup_mutexes(p_nxge_t);
213 static void nxge_destroy_mutexes(p_nxge_t);
214 
215 static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
216 static void nxge_unmap_regs(p_nxge_t nxgep);
217 #ifdef	NXGE_DEBUG
218 static void nxge_test_map_regs(p_nxge_t nxgep);
219 #endif
220 
221 static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
222 static void nxge_remove_intrs(p_nxge_t nxgep);
223 
224 static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
225 static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
226 static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
227 static void nxge_intrs_enable(p_nxge_t nxgep);
228 static void nxge_intrs_disable(p_nxge_t nxgep);
229 
230 static void nxge_suspend(p_nxge_t);
231 static nxge_status_t nxge_resume(p_nxge_t);
232 
233 static nxge_status_t nxge_setup_dev(p_nxge_t);
234 static void nxge_destroy_dev(p_nxge_t);
235 
236 static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
237 static void nxge_free_mem_pool(p_nxge_t);
238 
239 nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
240 static void nxge_free_rx_mem_pool(p_nxge_t);
241 
242 nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
243 static void nxge_free_tx_mem_pool(p_nxge_t);
244 
245 static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
246 	struct ddi_dma_attr *,
247 	size_t, ddi_device_acc_attr_t *, uint_t,
248 	p_nxge_dma_common_t);
249 
250 static void nxge_dma_mem_free(p_nxge_dma_common_t);
251 static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t);
252 
253 static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
254 	p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
255 static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
256 
257 static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
258 	p_nxge_dma_common_t *, size_t);
259 static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
260 
261 extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
262 	p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
263 static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
264 
265 extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
266 	p_nxge_dma_common_t *,
267 	size_t);
268 static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
269 
270 static int nxge_init_common_dev(p_nxge_t);
271 static void nxge_uninit_common_dev(p_nxge_t);
272 extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *,
273     char *, caddr_t);
274 #if defined(sun4v)
275 extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep);
276 extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm);
277 #endif
278 
279 /*
280  * The next declarations are for the GLDv3 interface.
281  */
282 static int nxge_m_start(void *);
283 static void nxge_m_stop(void *);
284 static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
285 static int nxge_m_promisc(void *, boolean_t);
286 static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
287 nxge_status_t nxge_mac_register(p_nxge_t);
288 static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr,
289 	int slot, int rdctbl, boolean_t usetbl);
290 void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot,
291 	boolean_t factory);
292 
293 static void nxge_m_getfactaddr(void *, uint_t, uint8_t *);
294 static	boolean_t nxge_m_getcapab(void *, mac_capab_t, void *);
295 static int nxge_m_setprop(void *, const char *, mac_prop_id_t,
296     uint_t, const void *);
297 static int nxge_m_getprop(void *, const char *, mac_prop_id_t,
298     uint_t, void *);
299 static void nxge_m_propinfo(void *, const char *, mac_prop_id_t,
300     mac_prop_info_handle_t);
301 static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t);
302 static int nxge_set_priv_prop(nxge_t *, const char *, uint_t,
303     const void *);
304 static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *);
305 static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int,
306     mac_ring_info_t *, mac_ring_handle_t);
307 static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t,
308     mac_ring_type_t);
309 static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t,
310     mac_ring_type_t);
311 
312 static void nxge_niu_peu_reset(p_nxge_t nxgep);
313 static void nxge_set_pci_replay_timeout(nxge_t *);
314 
315 char *nxge_priv_props[] = {
316 	"_adv_10gfdx_cap",
317 	"_adv_pause_cap",
318 	"_function_number",
319 	"_fw_version",
320 	"_port_mode",
321 	"_hot_swap_phy",
322 	"_rxdma_intr_time",
323 	"_rxdma_intr_pkts",
324 	"_class_opt_ipv4_tcp",
325 	"_class_opt_ipv4_udp",
326 	"_class_opt_ipv4_ah",
327 	"_class_opt_ipv4_sctp",
328 	"_class_opt_ipv6_tcp",
329 	"_class_opt_ipv6_udp",
330 	"_class_opt_ipv6_ah",
331 	"_class_opt_ipv6_sctp",
332 	"_soft_lso_enable",
333 	NULL
334 };
335 
336 #define	NXGE_NEPTUNE_MAGIC	0x4E584745UL
337 #define	MAX_DUMP_SZ 256
338 
339 #define	NXGE_M_CALLBACK_FLAGS	\
340 	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
341 
342 mac_callbacks_t nxge_m_callbacks = {
343 	NXGE_M_CALLBACK_FLAGS,
344 	nxge_m_stat,
345 	nxge_m_start,
346 	nxge_m_stop,
347 	nxge_m_promisc,
348 	nxge_m_multicst,
349 	NULL,
350 	NULL,
351 	NULL,
352 	nxge_m_ioctl,
353 	nxge_m_getcapab,
354 	NULL,
355 	NULL,
356 	nxge_m_setprop,
357 	nxge_m_getprop,
358 	nxge_m_propinfo
359 };
360 
361 void
362 nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
363 
364 /* PSARC/2007/453 MSI-X interrupt limit override. */
365 #define	NXGE_MSIX_REQUEST_10G	8
366 #define	NXGE_MSIX_REQUEST_1G	2
367 static int nxge_create_msi_property(p_nxge_t);
368 /*
369  * For applications that care about the
370  * latency, it was requested by PAE and the
371  * customers that the driver has tunables that
372  * allow the user to tune it to a higher number
373  * interrupts to spread the interrupts among
374  * multiple channels. The DDI framework limits
375  * the maximum number of MSI-X resources to allocate
376  * to 8 (ddi_msix_alloc_limit). If more than 8
377  * is set, ddi_msix_alloc_limit must be set accordingly.
378  * The default number of MSI interrupts are set to
379  * 8 for 10G and 2 for 1G link.
380  */
381 #define	NXGE_MSIX_MAX_ALLOWED	32
382 uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G;
383 uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G;
384 
385 /*
386  * These global variables control the message
387  * output.
388  */
389 out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
390 uint64_t nxge_debug_level;
391 
392 /*
393  * This list contains the instance structures for the Neptune
394  * devices present in the system. The lock exists to guarantee
395  * mutually exclusive access to the list.
396  */
397 void 			*nxge_list = NULL;
398 void			*nxge_hw_list = NULL;
399 nxge_os_mutex_t 	nxge_common_lock;
400 nxge_os_mutex_t 	nxgedebuglock;
401 
402 extern uint64_t 	npi_debug_level;
403 
404 extern nxge_status_t	nxge_ldgv_init(p_nxge_t, int *, int *);
405 extern nxge_status_t	nxge_ldgv_init_n2(p_nxge_t, int *, int *);
406 extern nxge_status_t	nxge_ldgv_uninit(p_nxge_t);
407 extern nxge_status_t	nxge_intr_ldgv_init(p_nxge_t);
408 extern void		nxge_fm_init(p_nxge_t,
409 					ddi_device_acc_attr_t *,
410 					ddi_dma_attr_t *);
411 extern void		nxge_fm_fini(p_nxge_t);
412 extern npi_status_t	npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
413 
414 /*
415  * Count used to maintain the number of buffers being used
416  * by Neptune instances and loaned up to the upper layers.
417  */
418 uint32_t nxge_mblks_pending = 0;
419 
420 /*
421  * Device register access attributes for PIO.
422  */
423 static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
424 	DDI_DEVICE_ATTR_V1,
425 	DDI_STRUCTURE_LE_ACC,
426 	DDI_STRICTORDER_ACC,
427 	DDI_DEFAULT_ACC
428 };
429 
430 /*
431  * Device descriptor access attributes for DMA.
432  */
433 static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
434 	DDI_DEVICE_ATTR_V0,
435 	DDI_STRUCTURE_LE_ACC,
436 	DDI_STRICTORDER_ACC
437 };
438 
439 /*
440  * Device buffer access attributes for DMA.
441  */
442 static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
443 	DDI_DEVICE_ATTR_V0,
444 	DDI_STRUCTURE_BE_ACC,
445 	DDI_STRICTORDER_ACC
446 };
447 
448 ddi_dma_attr_t nxge_desc_dma_attr = {
449 	DMA_ATTR_V0,		/* version number. */
450 	0,			/* low address */
451 	0xffffffffffffffff,	/* high address */
452 	0xffffffffffffffff,	/* address counter max */
453 #ifndef NIU_PA_WORKAROUND
454 	0x100000,		/* alignment */
455 #else
456 	0x2000,
457 #endif
458 	0xfc00fc,		/* dlim_burstsizes */
459 	0x1,			/* minimum transfer size */
460 	0xffffffffffffffff,	/* maximum transfer size */
461 	0xffffffffffffffff,	/* maximum segment size */
462 	1,			/* scatter/gather list length */
463 	(unsigned int) 1,	/* granularity */
464 	0			/* attribute flags */
465 };
466 
467 ddi_dma_attr_t nxge_tx_dma_attr = {
468 	DMA_ATTR_V0,		/* version number. */
469 	0,			/* low address */
470 	0xffffffffffffffff,	/* high address */
471 	0xffffffffffffffff,	/* address counter max */
472 #if defined(_BIG_ENDIAN)
473 	0x2000,			/* alignment */
474 #else
475 	0x1000,			/* alignment */
476 #endif
477 	0xfc00fc,		/* dlim_burstsizes */
478 	0x1,			/* minimum transfer size */
479 	0xffffffffffffffff,	/* maximum transfer size */
480 	0xffffffffffffffff,	/* maximum segment size */
481 	5,			/* scatter/gather list length */
482 	(unsigned int) 1,	/* granularity */
483 	0			/* attribute flags */
484 };
485 
486 ddi_dma_attr_t nxge_rx_dma_attr = {
487 	DMA_ATTR_V0,		/* version number. */
488 	0,			/* low address */
489 	0xffffffffffffffff,	/* high address */
490 	0xffffffffffffffff,	/* address counter max */
491 	0x2000,			/* alignment */
492 	0xfc00fc,		/* dlim_burstsizes */
493 	0x1,			/* minimum transfer size */
494 	0xffffffffffffffff,	/* maximum transfer size */
495 	0xffffffffffffffff,	/* maximum segment size */
496 	1,			/* scatter/gather list length */
497 	(unsigned int) 1,	/* granularity */
498 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
499 };
500 
501 ddi_dma_lim_t nxge_dma_limits = {
502 	(uint_t)0,		/* dlim_addr_lo */
503 	(uint_t)0xffffffff,	/* dlim_addr_hi */
504 	(uint_t)0xffffffff,	/* dlim_cntr_max */
505 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
506 	0x1,			/* dlim_minxfer */
507 	1024			/* dlim_speed */
508 };
509 
510 dma_method_t nxge_force_dma = DVMA;
511 
512 /*
513  * dma chunk sizes.
514  *
515  * Try to allocate the largest possible size
516  * so that fewer number of dma chunks would be managed
517  */
518 #ifdef NIU_PA_WORKAROUND
519 size_t alloc_sizes [] = {0x2000};
520 #else
521 size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
522 		0x10000, 0x20000, 0x40000, 0x80000,
523 		0x100000, 0x200000, 0x400000, 0x800000,
524 		0x1000000, 0x2000000, 0x4000000};
525 #endif
526 
527 /*
528  * Translate "dev_t" to a pointer to the associated "dev_info_t".
529  */
530 
531 extern void nxge_get_environs(nxge_t *);
532 
533 static int
534 nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
535 {
536 	p_nxge_t	nxgep = NULL;
537 	int		instance;
538 	int		status = DDI_SUCCESS;
539 	uint8_t		portn;
540 	nxge_mmac_t	*mmac_info;
541 
542 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
543 
544 	/*
545 	 * Get the device instance since we'll need to setup
546 	 * or retrieve a soft state for this instance.
547 	 */
548 	instance = ddi_get_instance(dip);
549 
550 	switch (cmd) {
551 	case DDI_ATTACH:
552 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
553 		break;
554 
555 	case DDI_RESUME:
556 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
557 		nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
558 		if (nxgep == NULL) {
559 			status = DDI_FAILURE;
560 			break;
561 		}
562 		if (nxgep->dip != dip) {
563 			status = DDI_FAILURE;
564 			break;
565 		}
566 		if (nxgep->suspended == DDI_PM_SUSPEND) {
567 			status = ddi_dev_is_needed(nxgep->dip, 0, 1);
568 		} else {
569 			status = nxge_resume(nxgep);
570 		}
571 		goto nxge_attach_exit;
572 
573 	case DDI_PM_RESUME:
574 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
575 		nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
576 		if (nxgep == NULL) {
577 			status = DDI_FAILURE;
578 			break;
579 		}
580 		if (nxgep->dip != dip) {
581 			status = DDI_FAILURE;
582 			break;
583 		}
584 		status = nxge_resume(nxgep);
585 		goto nxge_attach_exit;
586 
587 	default:
588 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
589 		status = DDI_FAILURE;
590 		goto nxge_attach_exit;
591 	}
592 
593 
594 	if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
595 		status = DDI_FAILURE;
596 		goto nxge_attach_exit;
597 	}
598 
599 	nxgep = ddi_get_soft_state(nxge_list, instance);
600 	if (nxgep == NULL) {
601 		status = NXGE_ERROR;
602 		goto nxge_attach_fail2;
603 	}
604 
605 	nxgep->nxge_magic = NXGE_MAGIC;
606 
607 	nxgep->drv_state = 0;
608 	nxgep->dip = dip;
609 	nxgep->instance = instance;
610 	nxgep->p_dip = ddi_get_parent(dip);
611 	nxgep->nxge_debug_level = nxge_debug_level;
612 	npi_debug_level = nxge_debug_level;
613 
614 	/* Are we a guest running in a Hybrid I/O environment? */
615 	nxge_get_environs(nxgep);
616 
617 	status = nxge_map_regs(nxgep);
618 
619 	if (status != NXGE_OK) {
620 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
621 		goto nxge_attach_fail3;
622 	}
623 
624 	nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr);
625 
626 	/* Create & initialize the per-Neptune data structure */
627 	/* (even if we're a guest). */
628 	status = nxge_init_common_dev(nxgep);
629 	if (status != NXGE_OK) {
630 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
631 		    "nxge_init_common_dev failed"));
632 		goto nxge_attach_fail4;
633 	}
634 
635 	/*
636 	 * Software workaround: set the replay timer.
637 	 */
638 	if (nxgep->niu_type != N2_NIU) {
639 		nxge_set_pci_replay_timeout(nxgep);
640 	}
641 
642 #if defined(sun4v)
643 	/* This is required by nxge_hio_init(), which follows. */
644 	if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS)
645 		goto nxge_attach_fail4;
646 #endif
647 
648 	if ((status = nxge_hio_init(nxgep)) != NXGE_OK) {
649 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
650 		    "nxge_hio_init failed"));
651 		goto nxge_attach_fail4;
652 	}
653 
654 	if (nxgep->niu_type == NEPTUNE_2_10GF) {
655 		if (nxgep->function_num > 1) {
656 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported"
657 			    " function %d. Only functions 0 and 1 are "
658 			    "supported for this card.", nxgep->function_num));
659 			status = NXGE_ERROR;
660 			goto nxge_attach_fail4;
661 		}
662 	}
663 
664 	if (isLDOMguest(nxgep)) {
665 		/*
666 		 * Use the function number here.
667 		 */
668 		nxgep->mac.portnum = nxgep->function_num;
669 		nxgep->mac.porttype = PORT_TYPE_LOGICAL;
670 
671 		/* XXX We'll set the MAC address counts to 1 for now. */
672 		mmac_info = &nxgep->nxge_mmac_info;
673 		mmac_info->num_mmac = 1;
674 		mmac_info->naddrfree = 1;
675 	} else {
676 		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
677 		nxgep->mac.portnum = portn;
678 		if ((portn == 0) || (portn == 1))
679 			nxgep->mac.porttype = PORT_TYPE_XMAC;
680 		else
681 			nxgep->mac.porttype = PORT_TYPE_BMAC;
682 		/*
683 		 * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC)
684 		 * internally, the rest 2 ports use BMAC (1G "Big" MAC).
685 		 * The two types of MACs have different characterizations.
686 		 */
687 		mmac_info = &nxgep->nxge_mmac_info;
688 		if (nxgep->function_num < 2) {
689 			mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY;
690 			mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY;
691 		} else {
692 			mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY;
693 			mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY;
694 		}
695 	}
696 	/*
697 	 * Setup the Ndd parameters for the this instance.
698 	 */
699 	nxge_init_param(nxgep);
700 
701 	/*
702 	 * Setup Register Tracing Buffer.
703 	 */
704 	npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
705 
706 	/* init stats ptr */
707 	nxge_init_statsp(nxgep);
708 
709 	/*
710 	 * Copy the vpd info from eeprom to a local data
711 	 * structure, and then check its validity.
712 	 */
713 	if (!isLDOMguest(nxgep)) {
714 		int *regp;
715 		uint_t reglen;
716 		int rv;
717 
718 		nxge_vpd_info_get(nxgep);
719 
720 		/* Find the NIU config handle. */
721 		rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
722 		    ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS,
723 		    "reg", &regp, &reglen);
724 
725 		if (rv != DDI_PROP_SUCCESS) {
726 			goto nxge_attach_fail5;
727 		}
728 		/*
729 		 * The address_hi, that is the first int, in the reg
730 		 * property consists of config handle, but need to remove
731 		 * the bits 28-31 which are OBP specific info.
732 		 */
733 		nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF;
734 		ddi_prop_free(regp);
735 	}
736 
737 	/*
738 	 * Set the defaults for the MTU size.
739 	 */
740 	nxge_hw_id_init(nxgep);
741 
742 	if (isLDOMguest(nxgep)) {
743 		uchar_t *prop_val;
744 		uint_t prop_len;
745 		uint32_t max_frame_size;
746 
747 		extern void nxge_get_logical_props(p_nxge_t);
748 
749 		nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR;
750 		nxgep->mac.portmode = PORT_LOGICAL;
751 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
752 		    "phy-type", "virtual transceiver");
753 
754 		nxgep->nports = 1;
755 		nxgep->board_ver = 0;	/* XXX What? */
756 
757 		/*
758 		 * local-mac-address property gives us info on which
759 		 * specific MAC address the Hybrid resource is associated
760 		 * with.
761 		 */
762 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
763 		    "local-mac-address", &prop_val,
764 		    &prop_len) != DDI_PROP_SUCCESS) {
765 			goto nxge_attach_fail5;
766 		}
767 		if (prop_len !=  ETHERADDRL) {
768 			ddi_prop_free(prop_val);
769 			goto nxge_attach_fail5;
770 		}
771 		ether_copy(prop_val, nxgep->hio_mac_addr);
772 		ddi_prop_free(prop_val);
773 		nxge_get_logical_props(nxgep);
774 
775 		/*
776 		 * Enable Jumbo property based on the "max-frame-size"
777 		 * property value.
778 		 */
779 		max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY,
780 		    nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
781 		    "max-frame-size", NXGE_MTU_DEFAULT_MAX);
782 		if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) &&
783 		    (max_frame_size <= TX_JUMBO_MTU)) {
784 			nxgep->mac.is_jumbo = B_TRUE;
785 			nxgep->mac.maxframesize = (uint16_t)max_frame_size;
786 			nxgep->mac.default_mtu = nxgep->mac.maxframesize -
787 			    NXGE_EHEADER_VLAN_CRC;
788 		}
789 	} else {
790 		status = nxge_xcvr_find(nxgep);
791 
792 		if (status != NXGE_OK) {
793 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
794 			    " Couldn't determine card type"
795 			    " .... exit "));
796 			goto nxge_attach_fail5;
797 		}
798 
799 		status = nxge_get_config_properties(nxgep);
800 
801 		if (status != NXGE_OK) {
802 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
803 			    "get_hw create failed"));
804 			goto nxge_attach_fail;
805 		}
806 	}
807 
808 	/*
809 	 * Setup the Kstats for the driver.
810 	 */
811 	nxge_setup_kstats(nxgep);
812 
813 	if (!isLDOMguest(nxgep))
814 		nxge_setup_param(nxgep);
815 
816 	status = nxge_setup_system_dma_pages(nxgep);
817 	if (status != NXGE_OK) {
818 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
819 		goto nxge_attach_fail;
820 	}
821 
822 
823 	if (!isLDOMguest(nxgep))
824 		nxge_hw_init_niu_common(nxgep);
825 
826 	status = nxge_setup_mutexes(nxgep);
827 	if (status != NXGE_OK) {
828 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
829 		goto nxge_attach_fail;
830 	}
831 
832 #if defined(sun4v)
833 	if (isLDOMguest(nxgep)) {
834 		/* Find our VR & channel sets. */
835 		status = nxge_hio_vr_add(nxgep);
836 		if (status != DDI_SUCCESS) {
837 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
838 			    "nxge_hio_vr_add failed"));
839 			(void) hsvc_unregister(&nxgep->niu_hsvc);
840 			nxgep->niu_hsvc_available = B_FALSE;
841 			goto nxge_attach_fail;
842 		}
843 		goto nxge_attach_exit;
844 	}
845 #endif
846 
847 	status = nxge_setup_dev(nxgep);
848 	if (status != DDI_SUCCESS) {
849 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
850 		goto nxge_attach_fail;
851 	}
852 
853 	status = nxge_add_intrs(nxgep);
854 	if (status != DDI_SUCCESS) {
855 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
856 		goto nxge_attach_fail;
857 	}
858 
859 	/* If a guest, register with vio_net instead. */
860 	if ((status = nxge_mac_register(nxgep)) != NXGE_OK) {
861 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
862 		    "unable to register to mac layer (%d)", status));
863 		goto nxge_attach_fail;
864 	}
865 
866 	mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
867 
868 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
869 	    "registered to mac (instance %d)", instance));
870 
871 	/* nxge_link_monitor calls xcvr.check_link recursively */
872 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
873 
874 	goto nxge_attach_exit;
875 
876 nxge_attach_fail:
877 	nxge_unattach(nxgep);
878 	goto nxge_attach_fail1;
879 
880 nxge_attach_fail5:
881 	/*
882 	 * Tear down the ndd parameters setup.
883 	 */
884 	nxge_destroy_param(nxgep);
885 
886 	/*
887 	 * Tear down the kstat setup.
888 	 */
889 	nxge_destroy_kstats(nxgep);
890 
891 nxge_attach_fail4:
892 	if (nxgep->nxge_hw_p) {
893 		nxge_uninit_common_dev(nxgep);
894 		nxgep->nxge_hw_p = NULL;
895 	}
896 
897 nxge_attach_fail3:
898 	/*
899 	 * Unmap the register setup.
900 	 */
901 	nxge_unmap_regs(nxgep);
902 
903 	nxge_fm_fini(nxgep);
904 
905 nxge_attach_fail2:
906 	ddi_soft_state_free(nxge_list, nxgep->instance);
907 
908 nxge_attach_fail1:
909 	if (status != NXGE_OK)
910 		status = (NXGE_ERROR | NXGE_DDI_FAILED);
911 	nxgep = NULL;
912 
913 nxge_attach_exit:
914 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
915 	    status));
916 
917 	return (status);
918 }
919 
920 static int
921 nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
922 {
923 	int 		status = DDI_SUCCESS;
924 	int 		instance;
925 	p_nxge_t 	nxgep = NULL;
926 
927 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
928 	instance = ddi_get_instance(dip);
929 	nxgep = ddi_get_soft_state(nxge_list, instance);
930 	if (nxgep == NULL) {
931 		status = DDI_FAILURE;
932 		goto nxge_detach_exit;
933 	}
934 
935 	switch (cmd) {
936 	case DDI_DETACH:
937 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
938 		break;
939 
940 	case DDI_PM_SUSPEND:
941 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
942 		nxgep->suspended = DDI_PM_SUSPEND;
943 		nxge_suspend(nxgep);
944 		break;
945 
946 	case DDI_SUSPEND:
947 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
948 		if (nxgep->suspended != DDI_PM_SUSPEND) {
949 			nxgep->suspended = DDI_SUSPEND;
950 			nxge_suspend(nxgep);
951 		}
952 		break;
953 
954 	default:
955 		status = DDI_FAILURE;
956 	}
957 
958 	if (cmd != DDI_DETACH)
959 		goto nxge_detach_exit;
960 
961 	/*
962 	 * Stop the xcvr polling.
963 	 */
964 	nxgep->suspended = cmd;
965 
966 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
967 
968 	if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
969 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
970 		    "<== nxge_detach status = 0x%08X", status));
971 		return (DDI_FAILURE);
972 	}
973 
974 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
975 	    "<== nxge_detach (mac_unregister) status = 0x%08X", status));
976 
977 	nxge_unattach(nxgep);
978 	nxgep = NULL;
979 
980 nxge_detach_exit:
981 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X",
982 	    status));
983 
984 	return (status);
985 }
986 
987 static void
988 nxge_unattach(p_nxge_t nxgep)
989 {
990 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach"));
991 
992 	if (nxgep == NULL || nxgep->dev_regs == NULL) {
993 		return;
994 	}
995 
996 	nxgep->nxge_magic = 0;
997 
998 	if (nxgep->nxge_timerid) {
999 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
1000 		nxgep->nxge_timerid = 0;
1001 	}
1002 
1003 	/*
1004 	 * If this flag is set, it will affect the Neptune
1005 	 * only.
1006 	 */
1007 	if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) {
1008 		nxge_niu_peu_reset(nxgep);
1009 	}
1010 
1011 #if	defined(sun4v)
1012 	if (isLDOMguest(nxgep)) {
1013 		(void) nxge_hio_vr_release(nxgep);
1014 	}
1015 #endif
1016 
1017 	if (nxgep->nxge_hw_p) {
1018 		nxge_uninit_common_dev(nxgep);
1019 		nxgep->nxge_hw_p = NULL;
1020 	}
1021 
1022 #if	defined(sun4v)
1023 	if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) {
1024 		(void) hsvc_unregister(&nxgep->niu_hsvc);
1025 		nxgep->niu_hsvc_available = B_FALSE;
1026 	}
1027 #endif
1028 	/*
1029 	 * Stop any further interrupts.
1030 	 */
1031 	nxge_remove_intrs(nxgep);
1032 
1033 	/*
1034 	 * Stop the device and free resources.
1035 	 */
1036 	if (!isLDOMguest(nxgep)) {
1037 		nxge_destroy_dev(nxgep);
1038 	}
1039 
1040 	/*
1041 	 * Tear down the ndd parameters setup.
1042 	 */
1043 	nxge_destroy_param(nxgep);
1044 
1045 	/*
1046 	 * Tear down the kstat setup.
1047 	 */
1048 	nxge_destroy_kstats(nxgep);
1049 
1050 	/*
1051 	 * Free any memory allocated for PHY properties
1052 	 */
1053 	if (nxgep->phy_prop.cnt > 0) {
1054 		KMEM_FREE(nxgep->phy_prop.arr,
1055 		    sizeof (nxge_phy_mdio_val_t) * nxgep->phy_prop.cnt);
1056 		nxgep->phy_prop.cnt = 0;
1057 	}
1058 
1059 	/*
1060 	 * Destroy all mutexes.
1061 	 */
1062 	nxge_destroy_mutexes(nxgep);
1063 
1064 	/*
1065 	 * Remove the list of ndd parameters which
1066 	 * were setup during attach.
1067 	 */
1068 	if (nxgep->dip) {
1069 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
1070 		    " nxge_unattach: remove all properties"));
1071 
1072 		(void) ddi_prop_remove_all(nxgep->dip);
1073 	}
1074 
1075 #if NXGE_PROPERTY
1076 	nxge_remove_hard_properties(nxgep);
1077 #endif
1078 
1079 	/*
1080 	 * Unmap the register setup.
1081 	 */
1082 	nxge_unmap_regs(nxgep);
1083 
1084 	nxge_fm_fini(nxgep);
1085 
1086 	ddi_soft_state_free(nxge_list, nxgep->instance);
1087 
1088 	NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach"));
1089 }
1090 
1091 #if defined(sun4v)
1092 int
1093 nxge_hsvc_register(nxge_t *nxgep)
1094 {
1095 	nxge_status_t status;
1096 	int i, j;
1097 
1098 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hsvc_register"));
1099 	if (nxgep->niu_type != N2_NIU) {
1100 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hsvc_register"));
1101 		return (DDI_SUCCESS);
1102 	}
1103 
1104 	/*
1105 	 * Currently, the NIU Hypervisor API supports two major versions:
1106 	 * version 1 and 2.
1107 	 * If Hypervisor introduces a higher major or minor version,
1108 	 * please update NIU_MAJOR_HI and NIU_MINOR_HI accordingly.
1109 	 */
1110 	nxgep->niu_hsvc_available = B_FALSE;
1111 	bcopy(&niu_hsvc, &nxgep->niu_hsvc,
1112 	    sizeof (hsvc_info_t));
1113 
1114 	for (i = NIU_MAJOR_HI; i > 0; i--) {
1115 		nxgep->niu_hsvc.hsvc_major = i;
1116 		for (j = NIU_MINOR_HI; j >= 0; j--) {
1117 			nxgep->niu_hsvc.hsvc_minor = j;
1118 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1119 			    "nxge_hsvc_register: %s: negotiating "
1120 			    "hypervisor services revision %d "
1121 			    "group: 0x%lx major: 0x%lx "
1122 			    "minor: 0x%lx",
1123 			    nxgep->niu_hsvc.hsvc_modname,
1124 			    nxgep->niu_hsvc.hsvc_rev,
1125 			    nxgep->niu_hsvc.hsvc_group,
1126 			    nxgep->niu_hsvc.hsvc_major,
1127 			    nxgep->niu_hsvc.hsvc_minor,
1128 			    nxgep->niu_min_ver));
1129 
1130 			if ((status = hsvc_register(&nxgep->niu_hsvc,
1131 			    &nxgep->niu_min_ver)) == 0) {
1132 				/* Use the supported minor */
1133 				nxgep->niu_hsvc.hsvc_minor = nxgep->niu_min_ver;
1134 				NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1135 				    "nxge_hsvc_register: %s: negotiated "
1136 				    "hypervisor services revision %d "
1137 				    "group: 0x%lx major: 0x%lx "
1138 				    "minor: 0x%lx (niu_min_ver 0x%lx)",
1139 				    nxgep->niu_hsvc.hsvc_modname,
1140 				    nxgep->niu_hsvc.hsvc_rev,
1141 				    nxgep->niu_hsvc.hsvc_group,
1142 				    nxgep->niu_hsvc.hsvc_major,
1143 				    nxgep->niu_hsvc.hsvc_minor,
1144 				    nxgep->niu_min_ver));
1145 
1146 				nxgep->niu_hsvc_available = B_TRUE;
1147 				NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1148 				    "<== nxge_hsvc_register: "
1149 				    "NIU Hypervisor service enabled"));
1150 				return (DDI_SUCCESS);
1151 			}
1152 
1153 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1154 			    "nxge_hsvc_register: %s: negotiated failed - "
1155 			    "try lower major number "
1156 			    "hypervisor services revision %d "
1157 			    "group: 0x%lx major: 0x%lx minor: 0x%lx "
1158 			    "errno: %d",
1159 			    nxgep->niu_hsvc.hsvc_modname,
1160 			    nxgep->niu_hsvc.hsvc_rev,
1161 			    nxgep->niu_hsvc.hsvc_group,
1162 			    nxgep->niu_hsvc.hsvc_major,
1163 			    nxgep->niu_hsvc.hsvc_minor, status));
1164 		}
1165 	}
1166 
1167 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1168 	    "nxge_hsvc_register: %s: cannot negotiate "
1169 	    "hypervisor services revision %d group: 0x%lx "
1170 	    "major: 0x%lx minor: 0x%lx errno: %d",
1171 	    niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev,
1172 	    niu_hsvc.hsvc_group, niu_hsvc.hsvc_major,
1173 	    niu_hsvc.hsvc_minor, status));
1174 
1175 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1176 	    "<== nxge_hsvc_register: Register to NIU Hypervisor failed"));
1177 
1178 	return (DDI_FAILURE);
1179 }
1180 #endif
1181 
1182 static char n2_siu_name[] = "niu";
1183 
1184 static nxge_status_t
1185 nxge_map_regs(p_nxge_t nxgep)
1186 {
1187 	int		ddi_status = DDI_SUCCESS;
1188 	p_dev_regs_t 	dev_regs;
1189 	char		buf[MAXPATHLEN + 1];
1190 	char 		*devname;
1191 #ifdef	NXGE_DEBUG
1192 	char 		*sysname;
1193 #endif
1194 	off_t		regsize;
1195 	nxge_status_t	status = NXGE_OK;
1196 #if !defined(_BIG_ENDIAN)
1197 	off_t pci_offset;
1198 	uint16_t pcie_devctl;
1199 #endif
1200 
1201 	if (isLDOMguest(nxgep)) {
1202 		return (nxge_guest_regs_map(nxgep));
1203 	}
1204 
1205 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs"));
1206 	nxgep->dev_regs = NULL;
1207 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
1208 	dev_regs->nxge_regh = NULL;
1209 	dev_regs->nxge_pciregh = NULL;
1210 	dev_regs->nxge_msix_regh = NULL;
1211 	dev_regs->nxge_vir_regh = NULL;
1212 	dev_regs->nxge_vir2_regh = NULL;
1213 	nxgep->niu_type = NIU_TYPE_NONE;
1214 
1215 	devname = ddi_pathname(nxgep->dip, buf);
1216 	ASSERT(strlen(devname) > 0);
1217 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1218 	    "nxge_map_regs: pathname devname %s", devname));
1219 
1220 	/*
1221 	 * The driver is running on a N2-NIU system if devname is something
1222 	 * like "/niu@80/network@0"
1223 	 */
1224 	if (strstr(devname, n2_siu_name)) {
1225 		/* N2/NIU */
1226 		nxgep->niu_type = N2_NIU;
1227 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1228 		    "nxge_map_regs: N2/NIU devname %s", devname));
1229 		/*
1230 		 * Get function number:
1231 		 *  - N2/NIU: "/niu@80/network@0" and "/niu@80/network@1"
1232 		 */
1233 		nxgep->function_num =
1234 		    (devname[strlen(devname) -1] == '1' ? 1 : 0);
1235 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1236 		    "nxge_map_regs: N2/NIU function number %d",
1237 		    nxgep->function_num));
1238 	} else {
1239 		int		*prop_val;
1240 		uint_t 		prop_len;
1241 		uint8_t 	func_num;
1242 
1243 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
1244 		    0, "reg",
1245 		    &prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1246 			NXGE_DEBUG_MSG((nxgep, VPD_CTL,
1247 			    "Reg property not found"));
1248 			ddi_status = DDI_FAILURE;
1249 			goto nxge_map_regs_fail0;
1250 
1251 		} else {
1252 			func_num = (prop_val[0] >> 8) & 0x7;
1253 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1254 			    "Reg property found: fun # %d",
1255 			    func_num));
1256 			nxgep->function_num = func_num;
1257 			if (isLDOMguest(nxgep)) {
1258 				nxgep->function_num /= 2;
1259 				return (NXGE_OK);
1260 			}
1261 			ddi_prop_free(prop_val);
1262 		}
1263 	}
1264 
1265 	switch (nxgep->niu_type) {
1266 	default:
1267 		(void) ddi_dev_regsize(nxgep->dip, 0, &regsize);
1268 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1269 		    "nxge_map_regs: pci config size 0x%x", regsize));
1270 
1271 		ddi_status = ddi_regs_map_setup(nxgep->dip, 0,
1272 		    (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0,
1273 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh);
1274 		if (ddi_status != DDI_SUCCESS) {
1275 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1276 			    "ddi_map_regs, nxge bus config regs failed"));
1277 			goto nxge_map_regs_fail0;
1278 		}
1279 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1280 		    "nxge_map_reg: PCI config addr 0x%0llx "
1281 		    " handle 0x%0llx", dev_regs->nxge_pciregp,
1282 		    dev_regs->nxge_pciregh));
1283 			/*
1284 			 * IMP IMP
1285 			 * workaround  for bit swapping bug in HW
1286 			 * which ends up in no-snoop = yes
1287 			 * resulting, in DMA not synched properly
1288 			 */
1289 #if !defined(_BIG_ENDIAN)
1290 		/* workarounds for x86 systems */
1291 		pci_offset = 0x80 + PCIE_DEVCTL;
1292 		pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh,
1293 		    pci_offset);
1294 		pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP;
1295 		pcie_devctl |= PCIE_DEVCTL_RO_EN;
1296 		pci_config_put16(dev_regs->nxge_pciregh, pci_offset,
1297 		    pcie_devctl);
1298 #endif
1299 
1300 		(void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1301 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1302 		    "nxge_map_regs: pio size 0x%x", regsize));
1303 		/* set up the device mapped register */
1304 		ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
1305 		    (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1306 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
1307 		if (ddi_status != DDI_SUCCESS) {
1308 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1309 			    "ddi_map_regs for Neptune global reg failed"));
1310 			goto nxge_map_regs_fail1;
1311 		}
1312 
1313 		/* set up the msi/msi-x mapped register */
1314 		(void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1315 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1316 		    "nxge_map_regs: msix size 0x%x", regsize));
1317 		ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
1318 		    (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0,
1319 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh);
1320 		if (ddi_status != DDI_SUCCESS) {
1321 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1322 			    "ddi_map_regs for msi reg failed"));
1323 			goto nxge_map_regs_fail2;
1324 		}
1325 
1326 		/* set up the vio region mapped register */
1327 		(void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1328 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1329 		    "nxge_map_regs: vio size 0x%x", regsize));
1330 		ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
1331 		    (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1332 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
1333 
1334 		if (ddi_status != DDI_SUCCESS) {
1335 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1336 			    "ddi_map_regs for nxge vio reg failed"));
1337 			goto nxge_map_regs_fail3;
1338 		}
1339 		nxgep->dev_regs = dev_regs;
1340 
1341 		NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh);
1342 		NPI_PCI_ADD_HANDLE_SET(nxgep,
1343 		    (npi_reg_ptr_t)dev_regs->nxge_pciregp);
1344 		NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh);
1345 		NPI_MSI_ADD_HANDLE_SET(nxgep,
1346 		    (npi_reg_ptr_t)dev_regs->nxge_msix_regp);
1347 
1348 		NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1349 		NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1350 
1351 		NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1352 		NPI_REG_ADD_HANDLE_SET(nxgep,
1353 		    (npi_reg_ptr_t)dev_regs->nxge_regp);
1354 
1355 		NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1356 		NPI_VREG_ADD_HANDLE_SET(nxgep,
1357 		    (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
1358 
1359 		break;
1360 
1361 	case N2_NIU:
1362 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU"));
1363 		/*
1364 		 * Set up the device mapped register (FWARC 2006/556)
1365 		 * (changed back to 1: reg starts at 1!)
1366 		 */
1367 		(void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1368 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1369 		    "nxge_map_regs: dev size 0x%x", regsize));
1370 		ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
1371 		    (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1372 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
1373 
1374 		if (ddi_status != DDI_SUCCESS) {
1375 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1376 			    "ddi_map_regs for N2/NIU, global reg failed "));
1377 			goto nxge_map_regs_fail1;
1378 		}
1379 
1380 		/* set up the first vio region mapped register */
1381 		(void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1382 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1383 		    "nxge_map_regs: vio (1) size 0x%x", regsize));
1384 		ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
1385 		    (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1386 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
1387 
1388 		if (ddi_status != DDI_SUCCESS) {
1389 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1390 			    "ddi_map_regs for nxge vio reg failed"));
1391 			goto nxge_map_regs_fail2;
1392 		}
1393 		/* set up the second vio region mapped register */
1394 		(void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1395 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1396 		    "nxge_map_regs: vio (3) size 0x%x", regsize));
1397 		ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
1398 		    (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0,
1399 		    &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh);
1400 
1401 		if (ddi_status != DDI_SUCCESS) {
1402 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1403 			    "ddi_map_regs for nxge vio2 reg failed"));
1404 			goto nxge_map_regs_fail3;
1405 		}
1406 		nxgep->dev_regs = dev_regs;
1407 
1408 		NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1409 		NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1410 
1411 		NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1412 		NPI_REG_ADD_HANDLE_SET(nxgep,
1413 		    (npi_reg_ptr_t)dev_regs->nxge_regp);
1414 
1415 		NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1416 		NPI_VREG_ADD_HANDLE_SET(nxgep,
1417 		    (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
1418 
1419 		NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh);
1420 		NPI_V2REG_ADD_HANDLE_SET(nxgep,
1421 		    (npi_reg_ptr_t)dev_regs->nxge_vir2_regp);
1422 
1423 		break;
1424 	}
1425 
1426 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx "
1427 	    " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh));
1428 
1429 	goto nxge_map_regs_exit;
1430 nxge_map_regs_fail3:
1431 	if (dev_regs->nxge_msix_regh) {
1432 		ddi_regs_map_free(&dev_regs->nxge_msix_regh);
1433 	}
1434 	if (dev_regs->nxge_vir_regh) {
1435 		ddi_regs_map_free(&dev_regs->nxge_regh);
1436 	}
1437 nxge_map_regs_fail2:
1438 	if (dev_regs->nxge_regh) {
1439 		ddi_regs_map_free(&dev_regs->nxge_regh);
1440 	}
1441 nxge_map_regs_fail1:
1442 	if (dev_regs->nxge_pciregh) {
1443 		ddi_regs_map_free(&dev_regs->nxge_pciregh);
1444 	}
1445 nxge_map_regs_fail0:
1446 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory"));
1447 	kmem_free(dev_regs, sizeof (dev_regs_t));
1448 
1449 nxge_map_regs_exit:
1450 	if (ddi_status != DDI_SUCCESS)
1451 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1452 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs"));
1453 	return (status);
1454 }
1455 
1456 static void
1457 nxge_unmap_regs(p_nxge_t nxgep)
1458 {
1459 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs"));
1460 
1461 	if (isLDOMguest(nxgep)) {
1462 		nxge_guest_regs_map_free(nxgep);
1463 		return;
1464 	}
1465 
1466 	if (nxgep->dev_regs) {
1467 		if (nxgep->dev_regs->nxge_pciregh) {
1468 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1469 			    "==> nxge_unmap_regs: bus"));
1470 			ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh);
1471 			nxgep->dev_regs->nxge_pciregh = NULL;
1472 		}
1473 		if (nxgep->dev_regs->nxge_regh) {
1474 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1475 			    "==> nxge_unmap_regs: device registers"));
1476 			ddi_regs_map_free(&nxgep->dev_regs->nxge_regh);
1477 			nxgep->dev_regs->nxge_regh = NULL;
1478 		}
1479 		if (nxgep->dev_regs->nxge_msix_regh) {
1480 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1481 			    "==> nxge_unmap_regs: device interrupts"));
1482 			ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh);
1483 			nxgep->dev_regs->nxge_msix_regh = NULL;
1484 		}
1485 		if (nxgep->dev_regs->nxge_vir_regh) {
1486 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1487 			    "==> nxge_unmap_regs: vio region"));
1488 			ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh);
1489 			nxgep->dev_regs->nxge_vir_regh = NULL;
1490 		}
1491 		if (nxgep->dev_regs->nxge_vir2_regh) {
1492 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1493 			    "==> nxge_unmap_regs: vio2 region"));
1494 			ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh);
1495 			nxgep->dev_regs->nxge_vir2_regh = NULL;
1496 		}
1497 
1498 		kmem_free(nxgep->dev_regs, sizeof (dev_regs_t));
1499 		nxgep->dev_regs = NULL;
1500 	}
1501 
1502 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs"));
1503 }
1504 
1505 static nxge_status_t
1506 nxge_setup_mutexes(p_nxge_t nxgep)
1507 {
1508 	int ddi_status = DDI_SUCCESS;
1509 	nxge_status_t status = NXGE_OK;
1510 	nxge_classify_t *classify_ptr;
1511 	int partition;
1512 
1513 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes"));
1514 
1515 	/*
1516 	 * Get the interrupt cookie so the mutexes can be
1517 	 * Initialized.
1518 	 */
1519 	if (isLDOMguest(nxgep)) {
1520 		nxgep->interrupt_cookie = 0;
1521 	} else {
1522 		ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0,
1523 		    &nxgep->interrupt_cookie);
1524 
1525 		if (ddi_status != DDI_SUCCESS) {
1526 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1527 			    "<== nxge_setup_mutexes: failed 0x%x",
1528 			    ddi_status));
1529 			goto nxge_setup_mutexes_exit;
1530 		}
1531 	}
1532 
1533 	cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL);
1534 	MUTEX_INIT(&nxgep->poll_lock, NULL,
1535 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1536 
1537 	/*
1538 	 * Initialize mutexes for this device.
1539 	 */
1540 	MUTEX_INIT(nxgep->genlock, NULL,
1541 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1542 	MUTEX_INIT(&nxgep->ouraddr_lock, NULL,
1543 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1544 	MUTEX_INIT(&nxgep->mif_lock, NULL,
1545 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1546 	MUTEX_INIT(&nxgep->group_lock, NULL,
1547 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1548 	RW_INIT(&nxgep->filter_lock, NULL,
1549 	    RW_DRIVER, (void *)nxgep->interrupt_cookie);
1550 
1551 	classify_ptr = &nxgep->classifier;
1552 		/*
1553 		 * FFLP Mutexes are never used in interrupt context
1554 		 * as fflp operation can take very long time to
1555 		 * complete and hence not suitable to invoke from interrupt
1556 		 * handlers.
1557 		 */
1558 	MUTEX_INIT(&classify_ptr->tcam_lock, NULL,
1559 	    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1560 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1561 		MUTEX_INIT(&classify_ptr->fcram_lock, NULL,
1562 		    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1563 		for (partition = 0; partition < MAX_PARTITION; partition++) {
1564 			MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL,
1565 			    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1566 		}
1567 	}
1568 
1569 nxge_setup_mutexes_exit:
1570 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1571 	    "<== nxge_setup_mutexes status = %x", status));
1572 
1573 	if (ddi_status != DDI_SUCCESS)
1574 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1575 
1576 	return (status);
1577 }
1578 
1579 static void
1580 nxge_destroy_mutexes(p_nxge_t nxgep)
1581 {
1582 	int partition;
1583 	nxge_classify_t *classify_ptr;
1584 
1585 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes"));
1586 	RW_DESTROY(&nxgep->filter_lock);
1587 	MUTEX_DESTROY(&nxgep->group_lock);
1588 	MUTEX_DESTROY(&nxgep->mif_lock);
1589 	MUTEX_DESTROY(&nxgep->ouraddr_lock);
1590 	MUTEX_DESTROY(nxgep->genlock);
1591 
1592 	classify_ptr = &nxgep->classifier;
1593 	MUTEX_DESTROY(&classify_ptr->tcam_lock);
1594 
1595 	/* Destroy all polling resources. */
1596 	MUTEX_DESTROY(&nxgep->poll_lock);
1597 	cv_destroy(&nxgep->poll_cv);
1598 
1599 	/* free data structures, based on HW type */
1600 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1601 		MUTEX_DESTROY(&classify_ptr->fcram_lock);
1602 		for (partition = 0; partition < MAX_PARTITION; partition++) {
1603 			MUTEX_DESTROY(&classify_ptr->hash_lock[partition]);
1604 		}
1605 	}
1606 
1607 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes"));
1608 }
1609 
1610 nxge_status_t
1611 nxge_init(p_nxge_t nxgep)
1612 {
1613 	nxge_status_t status = NXGE_OK;
1614 
1615 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init"));
1616 
1617 	if (nxgep->drv_state & STATE_HW_INITIALIZED) {
1618 		return (status);
1619 	}
1620 
1621 	/*
1622 	 * Allocate system memory for the receive/transmit buffer blocks
1623 	 * and receive/transmit descriptor rings.
1624 	 */
1625 	status = nxge_alloc_mem_pool(nxgep);
1626 	if (status != NXGE_OK) {
1627 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n"));
1628 		goto nxge_init_fail1;
1629 	}
1630 
1631 	if (!isLDOMguest(nxgep)) {
1632 		/*
1633 		 * Initialize and enable the TXC registers.
1634 		 * (Globally enable the Tx controller,
1635 		 *  enable the port, configure the dma channel bitmap,
1636 		 *  configure the max burst size).
1637 		 */
1638 		status = nxge_txc_init(nxgep);
1639 		if (status != NXGE_OK) {
1640 			NXGE_ERROR_MSG((nxgep,
1641 			    NXGE_ERR_CTL, "init txc failed\n"));
1642 			goto nxge_init_fail2;
1643 		}
1644 	}
1645 
1646 	/*
1647 	 * Initialize and enable TXDMA channels.
1648 	 */
1649 	status = nxge_init_txdma_channels(nxgep);
1650 	if (status != NXGE_OK) {
1651 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n"));
1652 		goto nxge_init_fail3;
1653 	}
1654 
1655 	/*
1656 	 * Initialize and enable RXDMA channels.
1657 	 */
1658 	status = nxge_init_rxdma_channels(nxgep);
1659 	if (status != NXGE_OK) {
1660 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n"));
1661 		goto nxge_init_fail4;
1662 	}
1663 
1664 	/*
1665 	 * The guest domain is now done.
1666 	 */
1667 	if (isLDOMguest(nxgep)) {
1668 		nxgep->drv_state |= STATE_HW_INITIALIZED;
1669 		goto nxge_init_exit;
1670 	}
1671 
1672 	/*
1673 	 * Initialize TCAM and FCRAM (Neptune).
1674 	 */
1675 	status = nxge_classify_init(nxgep);
1676 	if (status != NXGE_OK) {
1677 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n"));
1678 		goto nxge_init_fail5;
1679 	}
1680 
1681 	/*
1682 	 * Initialize ZCP
1683 	 */
1684 	status = nxge_zcp_init(nxgep);
1685 	if (status != NXGE_OK) {
1686 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n"));
1687 		goto nxge_init_fail5;
1688 	}
1689 
1690 	/*
1691 	 * Initialize IPP.
1692 	 */
1693 	status = nxge_ipp_init(nxgep);
1694 	if (status != NXGE_OK) {
1695 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n"));
1696 		goto nxge_init_fail5;
1697 	}
1698 
1699 	/*
1700 	 * Initialize the MAC block.
1701 	 */
1702 	status = nxge_mac_init(nxgep);
1703 	if (status != NXGE_OK) {
1704 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n"));
1705 		goto nxge_init_fail5;
1706 	}
1707 
1708 	/*
1709 	 * Enable the interrrupts for DDI.
1710 	 */
1711 	nxge_intrs_enable(nxgep);
1712 
1713 	nxgep->drv_state |= STATE_HW_INITIALIZED;
1714 
1715 	goto nxge_init_exit;
1716 
1717 nxge_init_fail5:
1718 	nxge_uninit_rxdma_channels(nxgep);
1719 nxge_init_fail4:
1720 	nxge_uninit_txdma_channels(nxgep);
1721 nxge_init_fail3:
1722 	if (!isLDOMguest(nxgep)) {
1723 		(void) nxge_txc_uninit(nxgep);
1724 	}
1725 nxge_init_fail2:
1726 	nxge_free_mem_pool(nxgep);
1727 nxge_init_fail1:
1728 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1729 	    "<== nxge_init status (failed) = 0x%08x", status));
1730 	return (status);
1731 
1732 nxge_init_exit:
1733 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x",
1734 	    status));
1735 	return (status);
1736 }
1737 
1738 
1739 timeout_id_t
1740 nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec)
1741 {
1742 	if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) {
1743 		return (timeout(func, (caddr_t)nxgep,
1744 		    drv_usectohz(1000 * msec)));
1745 	}
1746 	return (NULL);
1747 }
1748 
1749 /*ARGSUSED*/
1750 void
1751 nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid)
1752 {
1753 	if (timerid) {
1754 		(void) untimeout(timerid);
1755 	}
1756 }
1757 
1758 void
1759 nxge_uninit(p_nxge_t nxgep)
1760 {
1761 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit"));
1762 
1763 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
1764 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1765 		    "==> nxge_uninit: not initialized"));
1766 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1767 		    "<== nxge_uninit"));
1768 		return;
1769 	}
1770 
1771 	if (!isLDOMguest(nxgep)) {
1772 		/*
1773 		 * Reset the receive MAC side.
1774 		 */
1775 		(void) nxge_rx_mac_disable(nxgep);
1776 
1777 		/*
1778 		 * Drain the IPP.
1779 		 */
1780 		(void) nxge_ipp_drain(nxgep);
1781 	}
1782 
1783 	/* stop timer */
1784 	if (nxgep->nxge_timerid) {
1785 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
1786 		nxgep->nxge_timerid = 0;
1787 	}
1788 
1789 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
1790 	(void) nxge_intr_hw_disable(nxgep);
1791 
1792 
1793 	/* Disable and soft reset the IPP */
1794 	if (!isLDOMguest(nxgep))
1795 		(void) nxge_ipp_disable(nxgep);
1796 
1797 	/* Free classification resources */
1798 	(void) nxge_classify_uninit(nxgep);
1799 
1800 	/*
1801 	 * Reset the transmit/receive DMA side.
1802 	 */
1803 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
1804 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
1805 
1806 	nxge_uninit_txdma_channels(nxgep);
1807 	nxge_uninit_rxdma_channels(nxgep);
1808 
1809 	/*
1810 	 * Reset the transmit MAC side.
1811 	 */
1812 	(void) nxge_tx_mac_disable(nxgep);
1813 
1814 	nxge_free_mem_pool(nxgep);
1815 
1816 	/*
1817 	 * Start the timer if the reset flag is not set.
1818 	 * If this reset flag is set, the link monitor
1819 	 * will not be started in order to stop furthur bus
1820 	 * activities coming from this interface.
1821 	 * The driver will start the monitor function
1822 	 * if the interface was initialized again later.
1823 	 */
1824 	if (!nxge_peu_reset_enable) {
1825 		(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
1826 	}
1827 
1828 	nxgep->drv_state &= ~STATE_HW_INITIALIZED;
1829 
1830 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: "
1831 	    "nxge_mblks_pending %d", nxge_mblks_pending));
1832 }
1833 
1834 void
1835 nxge_get64(p_nxge_t nxgep, p_mblk_t mp)
1836 {
1837 	uint64_t	reg;
1838 	uint64_t	regdata;
1839 	int		i, retry;
1840 
1841 	bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
1842 	regdata = 0;
1843 	retry = 1;
1844 
1845 	for (i = 0; i < retry; i++) {
1846 		NXGE_REG_RD64(nxgep->npi_handle, reg, &regdata);
1847 	}
1848 	bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
1849 }
1850 
1851 void
1852 nxge_put64(p_nxge_t nxgep, p_mblk_t mp)
1853 {
1854 	uint64_t	reg;
1855 	uint64_t	buf[2];
1856 
1857 	bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
1858 	reg = buf[0];
1859 
1860 	NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]);
1861 }
1862 
1863 /*ARGSUSED*/
1864 /*VARARGS*/
1865 void
1866 nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...)
1867 {
1868 	char msg_buffer[1048];
1869 	char prefix_buffer[32];
1870 	int instance;
1871 	uint64_t debug_level;
1872 	int cmn_level = CE_CONT;
1873 	va_list ap;
1874 
1875 	if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) {
1876 		/* In case a developer has changed nxge_debug_level. */
1877 		if (nxgep->nxge_debug_level != nxge_debug_level)
1878 			nxgep->nxge_debug_level = nxge_debug_level;
1879 	}
1880 
1881 	debug_level = (nxgep == NULL) ? nxge_debug_level :
1882 	    nxgep->nxge_debug_level;
1883 
1884 	if ((level & debug_level) ||
1885 	    (level == NXGE_NOTE) ||
1886 	    (level == NXGE_ERR_CTL)) {
1887 		/* do the msg processing */
1888 		MUTEX_ENTER(&nxgedebuglock);
1889 
1890 		if ((level & NXGE_NOTE)) {
1891 			cmn_level = CE_NOTE;
1892 		}
1893 
1894 		if (level & NXGE_ERR_CTL) {
1895 			cmn_level = CE_WARN;
1896 		}
1897 
1898 		va_start(ap, fmt);
1899 		(void) vsprintf(msg_buffer, fmt, ap);
1900 		va_end(ap);
1901 		if (nxgep == NULL) {
1902 			instance = -1;
1903 			(void) sprintf(prefix_buffer, "%s :", "nxge");
1904 		} else {
1905 			instance = nxgep->instance;
1906 			(void) sprintf(prefix_buffer,
1907 			    "%s%d :", "nxge", instance);
1908 		}
1909 
1910 		MUTEX_EXIT(&nxgedebuglock);
1911 		cmn_err(cmn_level, "!%s %s\n",
1912 		    prefix_buffer, msg_buffer);
1913 
1914 	}
1915 }
1916 
1917 char *
1918 nxge_dump_packet(char *addr, int size)
1919 {
1920 	uchar_t *ap = (uchar_t *)addr;
1921 	int i;
1922 	static char etherbuf[1024];
1923 	char *cp = etherbuf;
1924 	char digits[] = "0123456789abcdef";
1925 
1926 	if (!size)
1927 		size = 60;
1928 
1929 	if (size > MAX_DUMP_SZ) {
1930 		/* Dump the leading bytes */
1931 		for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1932 			if (*ap > 0x0f)
1933 				*cp++ = digits[*ap >> 4];
1934 			*cp++ = digits[*ap++ & 0xf];
1935 			*cp++ = ':';
1936 		}
1937 		for (i = 0; i < 20; i++)
1938 			*cp++ = '.';
1939 		/* Dump the last MAX_DUMP_SZ/2 bytes */
1940 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2));
1941 		for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1942 			if (*ap > 0x0f)
1943 				*cp++ = digits[*ap >> 4];
1944 			*cp++ = digits[*ap++ & 0xf];
1945 			*cp++ = ':';
1946 		}
1947 	} else {
1948 		for (i = 0; i < size; i++) {
1949 			if (*ap > 0x0f)
1950 				*cp++ = digits[*ap >> 4];
1951 			*cp++ = digits[*ap++ & 0xf];
1952 			*cp++ = ':';
1953 		}
1954 	}
1955 	*--cp = 0;
1956 	return (etherbuf);
1957 }
1958 
1959 #ifdef	NXGE_DEBUG
1960 static void
1961 nxge_test_map_regs(p_nxge_t nxgep)
1962 {
1963 	ddi_acc_handle_t cfg_handle;
1964 	p_pci_cfg_t	cfg_ptr;
1965 	ddi_acc_handle_t dev_handle;
1966 	char		*dev_ptr;
1967 	ddi_acc_handle_t pci_config_handle;
1968 	uint32_t	regval;
1969 	int		i;
1970 
1971 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs"));
1972 
1973 	dev_handle = nxgep->dev_regs->nxge_regh;
1974 	dev_ptr = (char *)nxgep->dev_regs->nxge_regp;
1975 
1976 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1977 		cfg_handle = nxgep->dev_regs->nxge_pciregh;
1978 		cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
1979 
1980 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1981 		    "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr));
1982 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1983 		    "Neptune PCI cfg_ptr vendor id ptr 0x%llx",
1984 		    &cfg_ptr->vendorid));
1985 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1986 		    "\tvendorid 0x%x devid 0x%x",
1987 		    NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0),
1988 		    NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid,    0)));
1989 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1990 		    "PCI BAR: base 0x%x base14 0x%x base 18 0x%x "
1991 		    "bar1c 0x%x",
1992 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base,   0),
1993 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0),
1994 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0),
1995 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0)));
1996 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1997 		    "\nNeptune PCI BAR: base20 0x%x base24 0x%x "
1998 		    "base 28 0x%x bar2c 0x%x\n",
1999 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0),
2000 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0),
2001 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0),
2002 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0)));
2003 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2004 		    "\nNeptune PCI BAR: base30 0x%x\n",
2005 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0)));
2006 
2007 		cfg_handle = nxgep->dev_regs->nxge_pciregh;
2008 		cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
2009 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2010 		    "first  0x%llx second 0x%llx third 0x%llx "
2011 		    "last 0x%llx ",
2012 		    NXGE_PIO_READ64(dev_handle,
2013 		    (uint64_t *)(dev_ptr + 0),  0),
2014 		    NXGE_PIO_READ64(dev_handle,
2015 		    (uint64_t *)(dev_ptr + 8),  0),
2016 		    NXGE_PIO_READ64(dev_handle,
2017 		    (uint64_t *)(dev_ptr + 16), 0),
2018 		    NXGE_PIO_READ64(cfg_handle,
2019 		    (uint64_t *)(dev_ptr + 24), 0)));
2020 	}
2021 }
2022 
2023 #endif
2024 
2025 static void
2026 nxge_suspend(p_nxge_t nxgep)
2027 {
2028 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend"));
2029 
2030 	nxge_intrs_disable(nxgep);
2031 	nxge_destroy_dev(nxgep);
2032 
2033 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend"));
2034 }
2035 
2036 static nxge_status_t
2037 nxge_resume(p_nxge_t nxgep)
2038 {
2039 	nxge_status_t status = NXGE_OK;
2040 
2041 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume"));
2042 
2043 	nxgep->suspended = DDI_RESUME;
2044 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2045 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START);
2046 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
2047 	(void) nxge_rx_mac_enable(nxgep);
2048 	(void) nxge_tx_mac_enable(nxgep);
2049 	nxge_intrs_enable(nxgep);
2050 	nxgep->suspended = 0;
2051 
2052 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2053 	    "<== nxge_resume status = 0x%x", status));
2054 	return (status);
2055 }
2056 
2057 static nxge_status_t
2058 nxge_setup_dev(p_nxge_t nxgep)
2059 {
2060 	nxge_status_t	status = NXGE_OK;
2061 
2062 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d",
2063 	    nxgep->mac.portnum));
2064 
2065 	status = nxge_link_init(nxgep);
2066 
2067 	if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
2068 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2069 		    "port%d Bad register acc handle", nxgep->mac.portnum));
2070 		status = NXGE_ERROR;
2071 	}
2072 
2073 	if (status != NXGE_OK) {
2074 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2075 		    " nxge_setup_dev status "
2076 		    "(xcvr init 0x%08x)", status));
2077 		goto nxge_setup_dev_exit;
2078 	}
2079 
2080 nxge_setup_dev_exit:
2081 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2082 	    "<== nxge_setup_dev port %d status = 0x%08x",
2083 	    nxgep->mac.portnum, status));
2084 
2085 	return (status);
2086 }
2087 
2088 static void
2089 nxge_destroy_dev(p_nxge_t nxgep)
2090 {
2091 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev"));
2092 
2093 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
2094 
2095 	(void) nxge_hw_stop(nxgep);
2096 
2097 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev"));
2098 }
2099 
2100 static nxge_status_t
2101 nxge_setup_system_dma_pages(p_nxge_t nxgep)
2102 {
2103 	int 			ddi_status = DDI_SUCCESS;
2104 	uint_t 			count;
2105 	ddi_dma_cookie_t 	cookie;
2106 	uint_t 			iommu_pagesize;
2107 	nxge_status_t		status = NXGE_OK;
2108 
2109 	NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages"));
2110 	nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1);
2111 	if (nxgep->niu_type != N2_NIU) {
2112 		iommu_pagesize = dvma_pagesize(nxgep->dip);
2113 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2114 		    " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2115 		    " default_block_size %d iommu_pagesize %d",
2116 		    nxgep->sys_page_sz,
2117 		    ddi_ptob(nxgep->dip, (ulong_t)1),
2118 		    nxgep->rx_default_block_size,
2119 		    iommu_pagesize));
2120 
2121 		if (iommu_pagesize != 0) {
2122 			if (nxgep->sys_page_sz == iommu_pagesize) {
2123 				if (iommu_pagesize > 0x4000)
2124 					nxgep->sys_page_sz = 0x4000;
2125 			} else {
2126 				if (nxgep->sys_page_sz > iommu_pagesize)
2127 					nxgep->sys_page_sz = iommu_pagesize;
2128 			}
2129 		}
2130 	}
2131 	nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2132 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2133 	    "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2134 	    "default_block_size %d page mask %d",
2135 	    nxgep->sys_page_sz,
2136 	    ddi_ptob(nxgep->dip, (ulong_t)1),
2137 	    nxgep->rx_default_block_size,
2138 	    nxgep->sys_page_mask));
2139 
2140 
2141 	switch (nxgep->sys_page_sz) {
2142 	default:
2143 		nxgep->sys_page_sz = 0x1000;
2144 		nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2145 		nxgep->rx_default_block_size = 0x1000;
2146 		nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2147 		break;
2148 	case 0x1000:
2149 		nxgep->rx_default_block_size = 0x1000;
2150 		nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2151 		break;
2152 	case 0x2000:
2153 		nxgep->rx_default_block_size = 0x2000;
2154 		nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2155 		break;
2156 	case 0x4000:
2157 		nxgep->rx_default_block_size = 0x4000;
2158 		nxgep->rx_bksize_code = RBR_BKSIZE_16K;
2159 		break;
2160 	case 0x8000:
2161 		nxgep->rx_default_block_size = 0x8000;
2162 		nxgep->rx_bksize_code = RBR_BKSIZE_32K;
2163 		break;
2164 	}
2165 
2166 #ifndef USE_RX_BIG_BUF
2167 	nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz;
2168 #else
2169 		nxgep->rx_default_block_size = 0x2000;
2170 		nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2171 #endif
2172 	/*
2173 	 * Get the system DMA burst size.
2174 	 */
2175 	ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
2176 	    DDI_DMA_DONTWAIT, 0,
2177 	    &nxgep->dmasparehandle);
2178 	if (ddi_status != DDI_SUCCESS) {
2179 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2180 		    "ddi_dma_alloc_handle: failed "
2181 		    " status 0x%x", ddi_status));
2182 		goto nxge_get_soft_properties_exit;
2183 	}
2184 
2185 	ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL,
2186 	    (caddr_t)nxgep->dmasparehandle,
2187 	    sizeof (nxgep->dmasparehandle),
2188 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2189 	    DDI_DMA_DONTWAIT, 0,
2190 	    &cookie, &count);
2191 	if (ddi_status != DDI_DMA_MAPPED) {
2192 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2193 		    "Binding spare handle to find system"
2194 		    " burstsize failed."));
2195 		ddi_status = DDI_FAILURE;
2196 		goto nxge_get_soft_properties_fail1;
2197 	}
2198 
2199 	nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle);
2200 	(void) ddi_dma_unbind_handle(nxgep->dmasparehandle);
2201 
2202 nxge_get_soft_properties_fail1:
2203 	ddi_dma_free_handle(&nxgep->dmasparehandle);
2204 
2205 nxge_get_soft_properties_exit:
2206 
2207 	if (ddi_status != DDI_SUCCESS)
2208 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2209 
2210 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
2211 	    "<== nxge_setup_system_dma_pages status = 0x%08x", status));
2212 	return (status);
2213 }
2214 
2215 static nxge_status_t
2216 nxge_alloc_mem_pool(p_nxge_t nxgep)
2217 {
2218 	nxge_status_t	status = NXGE_OK;
2219 
2220 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool"));
2221 
2222 	status = nxge_alloc_rx_mem_pool(nxgep);
2223 	if (status != NXGE_OK) {
2224 		return (NXGE_ERROR);
2225 	}
2226 
2227 	status = nxge_alloc_tx_mem_pool(nxgep);
2228 	if (status != NXGE_OK) {
2229 		nxge_free_rx_mem_pool(nxgep);
2230 		return (NXGE_ERROR);
2231 	}
2232 
2233 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool"));
2234 	return (NXGE_OK);
2235 }
2236 
2237 static void
2238 nxge_free_mem_pool(p_nxge_t nxgep)
2239 {
2240 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool"));
2241 
2242 	nxge_free_rx_mem_pool(nxgep);
2243 	nxge_free_tx_mem_pool(nxgep);
2244 
2245 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool"));
2246 }
2247 
2248 nxge_status_t
2249 nxge_alloc_rx_mem_pool(p_nxge_t nxgep)
2250 {
2251 	uint32_t		rdc_max;
2252 	p_nxge_dma_pt_cfg_t	p_all_cfgp;
2253 	p_nxge_hw_pt_cfg_t	p_cfgp;
2254 	p_nxge_dma_pool_t	dma_poolp;
2255 	p_nxge_dma_common_t	*dma_buf_p;
2256 	p_nxge_dma_pool_t	dma_cntl_poolp;
2257 	p_nxge_dma_common_t	*dma_cntl_p;
2258 	uint32_t 		*num_chunks; /* per dma */
2259 	nxge_status_t		status = NXGE_OK;
2260 
2261 	uint32_t		nxge_port_rbr_size;
2262 	uint32_t		nxge_port_rbr_spare_size;
2263 	uint32_t		nxge_port_rcr_size;
2264 	uint32_t		rx_cntl_alloc_size;
2265 
2266 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool"));
2267 
2268 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2269 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
2270 	rdc_max = NXGE_MAX_RDCS;
2271 
2272 	/*
2273 	 * Allocate memory for the common DMA data structures.
2274 	 */
2275 	dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
2276 	    KM_SLEEP);
2277 	dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
2278 	    sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP);
2279 
2280 	dma_cntl_poolp = (p_nxge_dma_pool_t)
2281 	    KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
2282 	dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
2283 	    sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP);
2284 
2285 	num_chunks = (uint32_t *)KMEM_ZALLOC(
2286 	    sizeof (uint32_t) * rdc_max, KM_SLEEP);
2287 
2288 	/*
2289 	 * Assume that each DMA channel will be configured with
2290 	 * the default block size.
2291 	 * rbr block counts are modulo the batch count (16).
2292 	 */
2293 	nxge_port_rbr_size = p_all_cfgp->rbr_size;
2294 	nxge_port_rcr_size = p_all_cfgp->rcr_size;
2295 
2296 	if (!nxge_port_rbr_size) {
2297 		nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT;
2298 	}
2299 	if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) {
2300 		nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH *
2301 		    (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1));
2302 	}
2303 
2304 	p_all_cfgp->rbr_size = nxge_port_rbr_size;
2305 	nxge_port_rbr_spare_size = nxge_rbr_spare_size;
2306 
2307 	if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) {
2308 		nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH *
2309 		    (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1));
2310 	}
2311 	if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) {
2312 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
2313 		    "nxge_alloc_rx_mem_pool: RBR size too high %d, "
2314 		    "set to default %d",
2315 		    nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS));
2316 		nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS;
2317 	}
2318 	if (nxge_port_rcr_size > RCR_DEFAULT_MAX) {
2319 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
2320 		    "nxge_alloc_rx_mem_pool: RCR too high %d, "
2321 		    "set to default %d",
2322 		    nxge_port_rcr_size, RCR_DEFAULT_MAX));
2323 		nxge_port_rcr_size = RCR_DEFAULT_MAX;
2324 	}
2325 
2326 	/*
2327 	 * N2/NIU has limitation on the descriptor sizes (contiguous
2328 	 * memory allocation on data buffers to 4M (contig_mem_alloc)
2329 	 * and little endian for control buffers (must use the ddi/dki mem alloc
2330 	 * function).
2331 	 */
2332 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
2333 	if (nxgep->niu_type == N2_NIU) {
2334 		nxge_port_rbr_spare_size = 0;
2335 		if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) ||
2336 		    (!ISP2(nxge_port_rbr_size))) {
2337 			nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX;
2338 		}
2339 		if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) ||
2340 		    (!ISP2(nxge_port_rcr_size))) {
2341 			nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX;
2342 		}
2343 	}
2344 #endif
2345 
2346 	/*
2347 	 * Addresses of receive block ring, receive completion ring and the
2348 	 * mailbox must be all cache-aligned (64 bytes).
2349 	 */
2350 	rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size;
2351 	rx_cntl_alloc_size *= (sizeof (rx_desc_t));
2352 	rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size);
2353 	rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
2354 
2355 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: "
2356 	    "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d "
2357 	    "nxge_port_rcr_size = %d "
2358 	    "rx_cntl_alloc_size = %d",
2359 	    nxge_port_rbr_size, nxge_port_rbr_spare_size,
2360 	    nxge_port_rcr_size,
2361 	    rx_cntl_alloc_size));
2362 
2363 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
2364 	if (nxgep->niu_type == N2_NIU) {
2365 		uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size *
2366 		    (nxge_port_rbr_size + nxge_port_rbr_spare_size));
2367 
2368 		if (!ISP2(rx_buf_alloc_size)) {
2369 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2370 			    "==> nxge_alloc_rx_mem_pool: "
2371 			    " must be power of 2"));
2372 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2373 			goto nxge_alloc_rx_mem_pool_exit;
2374 		}
2375 
2376 		if (rx_buf_alloc_size > (1 << 22)) {
2377 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2378 			    "==> nxge_alloc_rx_mem_pool: "
2379 			    " limit size to 4M"));
2380 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2381 			goto nxge_alloc_rx_mem_pool_exit;
2382 		}
2383 
2384 		if (rx_cntl_alloc_size < 0x2000) {
2385 			rx_cntl_alloc_size = 0x2000;
2386 		}
2387 	}
2388 #endif
2389 	nxgep->nxge_port_rbr_size = nxge_port_rbr_size;
2390 	nxgep->nxge_port_rcr_size = nxge_port_rcr_size;
2391 	nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size;
2392 	nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size;
2393 
2394 	dma_poolp->ndmas = p_cfgp->max_rdcs;
2395 	dma_poolp->num_chunks = num_chunks;
2396 	dma_poolp->buf_allocated = B_TRUE;
2397 	nxgep->rx_buf_pool_p = dma_poolp;
2398 	dma_poolp->dma_buf_pool_p = dma_buf_p;
2399 
2400 	dma_cntl_poolp->ndmas = p_cfgp->max_rdcs;
2401 	dma_cntl_poolp->buf_allocated = B_TRUE;
2402 	nxgep->rx_cntl_pool_p = dma_cntl_poolp;
2403 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
2404 
2405 	/* Allocate the receive rings, too. */
2406 	nxgep->rx_rbr_rings =
2407 	    KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP);
2408 	nxgep->rx_rbr_rings->rbr_rings =
2409 	    KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP);
2410 	nxgep->rx_rcr_rings =
2411 	    KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP);
2412 	nxgep->rx_rcr_rings->rcr_rings =
2413 	    KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP);
2414 	nxgep->rx_mbox_areas_p =
2415 	    KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP);
2416 	nxgep->rx_mbox_areas_p->rxmbox_areas =
2417 	    KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP);
2418 
2419 	nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas =
2420 	    p_cfgp->max_rdcs;
2421 
2422 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2423 	    "<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
2424 
2425 nxge_alloc_rx_mem_pool_exit:
2426 	return (status);
2427 }
2428 
2429 /*
2430  * nxge_alloc_rxb
2431  *
2432  *	Allocate buffers for an RDC.
2433  *
2434  * Arguments:
2435  * 	nxgep
2436  * 	channel	The channel to map into our kernel space.
2437  *
2438  * Notes:
2439  *
2440  * NPI function calls:
2441  *
2442  * NXGE function calls:
2443  *
2444  * Registers accessed:
2445  *
2446  * Context:
2447  *
2448  * Taking apart:
2449  *
2450  * Open questions:
2451  *
2452  */
2453 nxge_status_t
2454 nxge_alloc_rxb(
2455 	p_nxge_t nxgep,
2456 	int channel)
2457 {
2458 	size_t			rx_buf_alloc_size;
2459 	nxge_status_t		status = NXGE_OK;
2460 
2461 	nxge_dma_common_t	**data;
2462 	nxge_dma_common_t	**control;
2463 	uint32_t 		*num_chunks;
2464 
2465 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb"));
2466 
2467 	/*
2468 	 * Allocate memory for the receive buffers and descriptor rings.
2469 	 * Replace these allocation functions with the interface functions
2470 	 * provided by the partition manager if/when they are available.
2471 	 */
2472 
2473 	/*
2474 	 * Allocate memory for the receive buffer blocks.
2475 	 */
2476 	rx_buf_alloc_size = (nxgep->rx_default_block_size *
2477 	    (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size));
2478 
2479 	data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel];
2480 	num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel];
2481 
2482 	if ((status = nxge_alloc_rx_buf_dma(
2483 	    nxgep, channel, data, rx_buf_alloc_size,
2484 	    nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) {
2485 		return (status);
2486 	}
2487 
2488 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): "
2489 	    "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data));
2490 
2491 	/*
2492 	 * Allocate memory for descriptor rings and mailbox.
2493 	 */
2494 	control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel];
2495 
2496 	if ((status = nxge_alloc_rx_cntl_dma(
2497 	    nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size))
2498 	    != NXGE_OK) {
2499 		nxge_free_rx_cntl_dma(nxgep, *control);
2500 		(*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE;
2501 		nxge_free_rx_buf_dma(nxgep, *data, *num_chunks);
2502 		return (status);
2503 	}
2504 
2505 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2506 	    "<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
2507 
2508 	return (status);
2509 }
2510 
2511 void
2512 nxge_free_rxb(
2513 	p_nxge_t nxgep,
2514 	int channel)
2515 {
2516 	nxge_dma_common_t	*data;
2517 	nxge_dma_common_t	*control;
2518 	uint32_t 		num_chunks;
2519 
2520 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb"));
2521 
2522 	data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel];
2523 	num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel];
2524 	nxge_free_rx_buf_dma(nxgep, data, num_chunks);
2525 
2526 	nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0;
2527 	nxgep->rx_buf_pool_p->num_chunks[channel] = 0;
2528 
2529 	control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel];
2530 	nxge_free_rx_cntl_dma(nxgep, control);
2531 
2532 	nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0;
2533 
2534 	KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2535 	KMEM_FREE(control, sizeof (nxge_dma_common_t));
2536 
2537 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb"));
2538 }
2539 
2540 static void
2541 nxge_free_rx_mem_pool(p_nxge_t nxgep)
2542 {
2543 	int rdc_max = NXGE_MAX_RDCS;
2544 
2545 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool"));
2546 
2547 	if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) {
2548 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2549 		    "<== nxge_free_rx_mem_pool "
2550 		    "(null rx buf pool or buf not allocated"));
2551 		return;
2552 	}
2553 	if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) {
2554 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2555 		    "<== nxge_free_rx_mem_pool "
2556 		    "(null rx cntl buf pool or cntl buf not allocated"));
2557 		return;
2558 	}
2559 
2560 	KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p,
2561 	    sizeof (p_nxge_dma_common_t) * rdc_max);
2562 	KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t));
2563 
2564 	KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks,
2565 	    sizeof (uint32_t) * rdc_max);
2566 	KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p,
2567 	    sizeof (p_nxge_dma_common_t) * rdc_max);
2568 	KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t));
2569 
2570 	nxgep->rx_buf_pool_p = 0;
2571 	nxgep->rx_cntl_pool_p = 0;
2572 
2573 	KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings,
2574 	    sizeof (p_rx_rbr_ring_t) * rdc_max);
2575 	KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t));
2576 	KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings,
2577 	    sizeof (p_rx_rcr_ring_t) * rdc_max);
2578 	KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t));
2579 	KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas,
2580 	    sizeof (p_rx_mbox_t) * rdc_max);
2581 	KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t));
2582 
2583 	nxgep->rx_rbr_rings = 0;
2584 	nxgep->rx_rcr_rings = 0;
2585 	nxgep->rx_mbox_areas_p = 0;
2586 
2587 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool"));
2588 }
2589 
2590 
2591 static nxge_status_t
2592 nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
2593 	p_nxge_dma_common_t *dmap,
2594 	size_t alloc_size, size_t block_size, uint32_t *num_chunks)
2595 {
2596 	p_nxge_dma_common_t 	rx_dmap;
2597 	nxge_status_t		status = NXGE_OK;
2598 	size_t			total_alloc_size;
2599 	size_t			allocated = 0;
2600 	int			i, size_index, array_size;
2601 	boolean_t		use_kmem_alloc = B_FALSE;
2602 
2603 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma"));
2604 
2605 	rx_dmap = (p_nxge_dma_common_t)
2606 	    KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
2607 	    KM_SLEEP);
2608 
2609 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2610 	    " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
2611 	    dma_channel, alloc_size, block_size, dmap));
2612 
2613 	total_alloc_size = alloc_size;
2614 
2615 #if defined(RX_USE_RECLAIM_POST)
2616 	total_alloc_size = alloc_size + alloc_size/4;
2617 #endif
2618 
2619 	i = 0;
2620 	size_index = 0;
2621 	array_size =  sizeof (alloc_sizes)/sizeof (size_t);
2622 	while ((size_index < array_size) &&
2623 	    (alloc_sizes[size_index] < alloc_size))
2624 		size_index++;
2625 	if (size_index >= array_size) {
2626 		size_index = array_size - 1;
2627 	}
2628 
2629 	/* For Neptune, use kmem_alloc if the kmem flag is set. */
2630 	if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) {
2631 		use_kmem_alloc = B_TRUE;
2632 #if defined(__i386) || defined(__amd64)
2633 		size_index = 0;
2634 #endif
2635 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2636 		    "==> nxge_alloc_rx_buf_dma: "
2637 		    "Neptune use kmem_alloc() - size_index %d",
2638 		    size_index));
2639 	}
2640 
2641 	while ((allocated < total_alloc_size) &&
2642 	    (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
2643 		rx_dmap[i].dma_chunk_index = i;
2644 		rx_dmap[i].block_size = block_size;
2645 		rx_dmap[i].alength = alloc_sizes[size_index];
2646 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
2647 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
2648 		rx_dmap[i].dma_channel = dma_channel;
2649 		rx_dmap[i].contig_alloc_type = B_FALSE;
2650 		rx_dmap[i].kmem_alloc_type = B_FALSE;
2651 		rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC;
2652 
2653 		/*
2654 		 * N2/NIU: data buffers must be contiguous as the driver
2655 		 *	   needs to call Hypervisor api to set up
2656 		 *	   logical pages.
2657 		 */
2658 		if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
2659 			rx_dmap[i].contig_alloc_type = B_TRUE;
2660 			rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC;
2661 		} else if (use_kmem_alloc) {
2662 			/* For Neptune, use kmem_alloc */
2663 			NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2664 			    "==> nxge_alloc_rx_buf_dma: "
2665 			    "Neptune use kmem_alloc()"));
2666 			rx_dmap[i].kmem_alloc_type = B_TRUE;
2667 			rx_dmap[i].buf_alloc_type = KMEM_ALLOC;
2668 		}
2669 
2670 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2671 		    "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
2672 		    "i %d nblocks %d alength %d",
2673 		    dma_channel, i, &rx_dmap[i], block_size,
2674 		    i, rx_dmap[i].nblocks,
2675 		    rx_dmap[i].alength));
2676 		status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
2677 		    &nxge_rx_dma_attr,
2678 		    rx_dmap[i].alength,
2679 		    &nxge_dev_buf_dma_acc_attr,
2680 		    DDI_DMA_READ | DDI_DMA_STREAMING,
2681 		    (p_nxge_dma_common_t)(&rx_dmap[i]));
2682 		if (status != NXGE_OK) {
2683 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2684 			    "nxge_alloc_rx_buf_dma: Alloc Failed: "
2685 			    "dma %d size_index %d size requested %d",
2686 			    dma_channel,
2687 			    size_index,
2688 			    rx_dmap[i].alength));
2689 			size_index--;
2690 		} else {
2691 			rx_dmap[i].buf_alloc_state = BUF_ALLOCATED;
2692 			NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2693 			    " nxge_alloc_rx_buf_dma DONE  alloc mem: "
2694 			    "dma %d dma_buf_p $%p kaddrp $%p alength %d "
2695 			    "buf_alloc_state %d alloc_type %d",
2696 			    dma_channel,
2697 			    &rx_dmap[i],
2698 			    rx_dmap[i].kaddrp,
2699 			    rx_dmap[i].alength,
2700 			    rx_dmap[i].buf_alloc_state,
2701 			    rx_dmap[i].buf_alloc_type));
2702 			NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2703 			    " alloc_rx_buf_dma allocated rdc %d "
2704 			    "chunk %d size %x dvma %x bufp %llx kaddrp $%p",
2705 			    dma_channel, i, rx_dmap[i].alength,
2706 			    rx_dmap[i].ioaddr_pp, &rx_dmap[i],
2707 			    rx_dmap[i].kaddrp));
2708 			i++;
2709 			allocated += alloc_sizes[size_index];
2710 		}
2711 	}
2712 
2713 	if (allocated < total_alloc_size) {
2714 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2715 		    "==> nxge_alloc_rx_buf_dma: not enough for channel %d "
2716 		    "allocated 0x%x requested 0x%x",
2717 		    dma_channel,
2718 		    allocated, total_alloc_size));
2719 		status = NXGE_ERROR;
2720 		goto nxge_alloc_rx_mem_fail1;
2721 	}
2722 
2723 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2724 	    "==> nxge_alloc_rx_buf_dma: Allocated for channel %d "
2725 	    "allocated 0x%x requested 0x%x",
2726 	    dma_channel,
2727 	    allocated, total_alloc_size));
2728 
2729 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2730 	    " alloc_rx_buf_dma rdc %d allocated %d chunks",
2731 	    dma_channel, i));
2732 	*num_chunks = i;
2733 	*dmap = rx_dmap;
2734 
2735 	goto nxge_alloc_rx_mem_exit;
2736 
2737 nxge_alloc_rx_mem_fail1:
2738 	KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2739 
2740 nxge_alloc_rx_mem_exit:
2741 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2742 	    "<== nxge_alloc_rx_buf_dma status 0x%08x", status));
2743 
2744 	return (status);
2745 }
2746 
2747 /*ARGSUSED*/
2748 static void
2749 nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
2750     uint32_t num_chunks)
2751 {
2752 	int		i;
2753 
2754 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2755 	    "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks));
2756 
2757 	if (dmap == 0)
2758 		return;
2759 
2760 	for (i = 0; i < num_chunks; i++) {
2761 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
2762 		    "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx",
2763 		    i, dmap));
2764 		nxge_dma_free_rx_data_buf(dmap++);
2765 	}
2766 
2767 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma"));
2768 }
2769 
2770 /*ARGSUSED*/
2771 static nxge_status_t
2772 nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
2773     p_nxge_dma_common_t *dmap, size_t size)
2774 {
2775 	p_nxge_dma_common_t 	rx_dmap;
2776 	nxge_status_t		status = NXGE_OK;
2777 
2778 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma"));
2779 
2780 	rx_dmap = (p_nxge_dma_common_t)
2781 	    KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
2782 
2783 	rx_dmap->contig_alloc_type = B_FALSE;
2784 	rx_dmap->kmem_alloc_type = B_FALSE;
2785 
2786 	status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
2787 	    &nxge_desc_dma_attr,
2788 	    size,
2789 	    &nxge_dev_desc_dma_acc_attr,
2790 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2791 	    rx_dmap);
2792 	if (status != NXGE_OK) {
2793 		goto nxge_alloc_rx_cntl_dma_fail1;
2794 	}
2795 
2796 	*dmap = rx_dmap;
2797 	goto nxge_alloc_rx_cntl_dma_exit;
2798 
2799 nxge_alloc_rx_cntl_dma_fail1:
2800 	KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t));
2801 
2802 nxge_alloc_rx_cntl_dma_exit:
2803 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2804 	    "<== nxge_alloc_rx_cntl_dma status 0x%08x", status));
2805 
2806 	return (status);
2807 }
2808 
2809 /*ARGSUSED*/
2810 static void
2811 nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
2812 {
2813 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma"));
2814 
2815 	if (dmap == 0)
2816 		return;
2817 
2818 	nxge_dma_mem_free(dmap);
2819 
2820 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma"));
2821 }
2822 
2823 typedef struct {
2824 	size_t	tx_size;
2825 	size_t	cr_size;
2826 	size_t	threshhold;
2827 } nxge_tdc_sizes_t;
2828 
2829 static
2830 nxge_status_t
2831 nxge_tdc_sizes(
2832 	nxge_t *nxgep,
2833 	nxge_tdc_sizes_t *sizes)
2834 {
2835 	uint32_t threshhold;	/* The bcopy() threshhold */
2836 	size_t tx_size;		/* Transmit buffer size */
2837 	size_t cr_size;		/* Completion ring size */
2838 
2839 	/*
2840 	 * Assume that each DMA channel will be configured with the
2841 	 * default transmit buffer size for copying transmit data.
2842 	 * (If a packet is bigger than this, it will not be copied.)
2843 	 */
2844 	if (nxgep->niu_type == N2_NIU) {
2845 		threshhold = TX_BCOPY_SIZE;
2846 	} else {
2847 		threshhold = nxge_bcopy_thresh;
2848 	}
2849 	tx_size = nxge_tx_ring_size * threshhold;
2850 
2851 	cr_size = nxge_tx_ring_size * sizeof (tx_desc_t);
2852 	cr_size += sizeof (txdma_mailbox_t);
2853 
2854 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
2855 	if (nxgep->niu_type == N2_NIU) {
2856 		if (!ISP2(tx_size)) {
2857 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2858 			    "==> nxge_tdc_sizes: Tx size"
2859 			    " must be power of 2"));
2860 			return (NXGE_ERROR);
2861 		}
2862 
2863 		if (tx_size > (1 << 22)) {
2864 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2865 			    "==> nxge_tdc_sizes: Tx size"
2866 			    " limited to 4M"));
2867 			return (NXGE_ERROR);
2868 		}
2869 
2870 		if (cr_size < 0x2000)
2871 			cr_size = 0x2000;
2872 	}
2873 #endif
2874 
2875 	sizes->threshhold = threshhold;
2876 	sizes->tx_size = tx_size;
2877 	sizes->cr_size = cr_size;
2878 
2879 	return (NXGE_OK);
2880 }
2881 /*
2882  * nxge_alloc_txb
2883  *
2884  *	Allocate buffers for an TDC.
2885  *
2886  * Arguments:
2887  * 	nxgep
2888  * 	channel	The channel to map into our kernel space.
2889  *
2890  * Notes:
2891  *
2892  * NPI function calls:
2893  *
2894  * NXGE function calls:
2895  *
2896  * Registers accessed:
2897  *
2898  * Context:
2899  *
2900  * Taking apart:
2901  *
2902  * Open questions:
2903  *
2904  */
2905 nxge_status_t
2906 nxge_alloc_txb(
2907 	p_nxge_t nxgep,
2908 	int channel)
2909 {
2910 	nxge_dma_common_t	**dma_buf_p;
2911 	nxge_dma_common_t	**dma_cntl_p;
2912 	uint32_t 		*num_chunks;
2913 	nxge_status_t		status = NXGE_OK;
2914 
2915 	nxge_tdc_sizes_t	sizes;
2916 
2917 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb"));
2918 
2919 	if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK)
2920 		return (NXGE_ERROR);
2921 
2922 	/*
2923 	 * Allocate memory for transmit buffers and descriptor rings.
2924 	 * Replace these allocation functions with the interface functions
2925 	 * provided by the partition manager Real Soon Now.
2926 	 */
2927 	dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
2928 	num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel];
2929 
2930 	dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
2931 
2932 	/*
2933 	 * Allocate memory for transmit buffers and descriptor rings.
2934 	 * Replace allocation functions with interface functions provided
2935 	 * by the partition manager when it is available.
2936 	 *
2937 	 * Allocate memory for the transmit buffer pool.
2938 	 */
2939 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
2940 	    "sizes: tx: %ld, cr:%ld, th:%ld",
2941 	    sizes.tx_size, sizes.cr_size, sizes.threshhold));
2942 
2943 	*num_chunks = 0;
2944 	status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p,
2945 	    sizes.tx_size, sizes.threshhold, num_chunks);
2946 	if (status != NXGE_OK) {
2947 		cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!");
2948 		return (status);
2949 	}
2950 
2951 	/*
2952 	 * Allocate memory for descriptor rings and mailbox.
2953 	 */
2954 	status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p,
2955 	    sizes.cr_size);
2956 	if (status != NXGE_OK) {
2957 		nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks);
2958 		cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!");
2959 		return (status);
2960 	}
2961 
2962 	return (NXGE_OK);
2963 }
2964 
2965 void
2966 nxge_free_txb(
2967 	p_nxge_t nxgep,
2968 	int channel)
2969 {
2970 	nxge_dma_common_t	*data;
2971 	nxge_dma_common_t	*control;
2972 	uint32_t 		num_chunks;
2973 
2974 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb"));
2975 
2976 	data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel];
2977 	num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel];
2978 	nxge_free_tx_buf_dma(nxgep, data, num_chunks);
2979 
2980 	nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0;
2981 	nxgep->tx_buf_pool_p->num_chunks[channel] = 0;
2982 
2983 	control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel];
2984 	nxge_free_tx_cntl_dma(nxgep, control);
2985 
2986 	nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0;
2987 
2988 	KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
2989 	KMEM_FREE(control, sizeof (nxge_dma_common_t));
2990 
2991 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb"));
2992 }
2993 
2994 /*
2995  * nxge_alloc_tx_mem_pool
2996  *
2997  *	This function allocates all of the per-port TDC control data structures.
2998  *	The per-channel (TDC) data structures are allocated when needed.
2999  *
3000  * Arguments:
3001  * 	nxgep
3002  *
3003  * Notes:
3004  *
3005  * Context:
3006  *	Any domain
3007  */
3008 nxge_status_t
3009 nxge_alloc_tx_mem_pool(p_nxge_t nxgep)
3010 {
3011 	nxge_hw_pt_cfg_t	*p_cfgp;
3012 	nxge_dma_pool_t		*dma_poolp;
3013 	nxge_dma_common_t	**dma_buf_p;
3014 	nxge_dma_pool_t		*dma_cntl_poolp;
3015 	nxge_dma_common_t	**dma_cntl_p;
3016 	uint32_t		*num_chunks; /* per dma */
3017 	int			tdc_max;
3018 
3019 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool"));
3020 
3021 	p_cfgp = &nxgep->pt_config.hw_config;
3022 	tdc_max = NXGE_MAX_TDCS;
3023 
3024 	/*
3025 	 * Allocate memory for each transmit DMA channel.
3026 	 */
3027 	dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
3028 	    KM_SLEEP);
3029 	dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
3030 	    sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP);
3031 
3032 	dma_cntl_poolp = (p_nxge_dma_pool_t)
3033 	    KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
3034 	dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
3035 	    sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP);
3036 
3037 	if (nxge_tx_ring_size > TDC_DEFAULT_MAX) {
3038 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
3039 		    "nxge_alloc_tx_mem_pool: TDC too high %d, "
3040 		    "set to default %d",
3041 		    nxge_tx_ring_size, TDC_DEFAULT_MAX));
3042 		nxge_tx_ring_size = TDC_DEFAULT_MAX;
3043 	}
3044 
3045 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
3046 	/*
3047 	 * N2/NIU has limitation on the descriptor sizes (contiguous
3048 	 * memory allocation on data buffers to 4M (contig_mem_alloc)
3049 	 * and little endian for control buffers (must use the ddi/dki mem alloc
3050 	 * function). The transmit ring is limited to 8K (includes the
3051 	 * mailbox).
3052 	 */
3053 	if (nxgep->niu_type == N2_NIU) {
3054 		if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) ||
3055 		    (!ISP2(nxge_tx_ring_size))) {
3056 			nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX;
3057 		}
3058 	}
3059 #endif
3060 
3061 	nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size;
3062 
3063 	num_chunks = (uint32_t *)KMEM_ZALLOC(
3064 	    sizeof (uint32_t) * tdc_max, KM_SLEEP);
3065 
3066 	dma_poolp->ndmas = p_cfgp->tdc.owned;
3067 	dma_poolp->num_chunks = num_chunks;
3068 	dma_poolp->dma_buf_pool_p = dma_buf_p;
3069 	nxgep->tx_buf_pool_p = dma_poolp;
3070 
3071 	dma_poolp->buf_allocated = B_TRUE;
3072 
3073 	dma_cntl_poolp->ndmas = p_cfgp->tdc.owned;
3074 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
3075 	nxgep->tx_cntl_pool_p = dma_cntl_poolp;
3076 
3077 	dma_cntl_poolp->buf_allocated = B_TRUE;
3078 
3079 	nxgep->tx_rings =
3080 	    KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP);
3081 	nxgep->tx_rings->rings =
3082 	    KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP);
3083 	nxgep->tx_mbox_areas_p =
3084 	    KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP);
3085 	nxgep->tx_mbox_areas_p->txmbox_areas_p =
3086 	    KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP);
3087 
3088 	nxgep->tx_rings->ndmas = p_cfgp->tdc.owned;
3089 
3090 	NXGE_DEBUG_MSG((nxgep, MEM_CTL,
3091 	    "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d",
3092 	    tdc_max, dma_poolp->ndmas));
3093 
3094 	return (NXGE_OK);
3095 }
3096 
3097 nxge_status_t
3098 nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
3099     p_nxge_dma_common_t *dmap, size_t alloc_size,
3100     size_t block_size, uint32_t *num_chunks)
3101 {
3102 	p_nxge_dma_common_t 	tx_dmap;
3103 	nxge_status_t		status = NXGE_OK;
3104 	size_t			total_alloc_size;
3105 	size_t			allocated = 0;
3106 	int			i, size_index, array_size;
3107 
3108 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma"));
3109 
3110 	tx_dmap = (p_nxge_dma_common_t)
3111 	    KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
3112 	    KM_SLEEP);
3113 
3114 	total_alloc_size = alloc_size;
3115 	i = 0;
3116 	size_index = 0;
3117 	array_size =  sizeof (alloc_sizes) /  sizeof (size_t);
3118 	while ((size_index < array_size) &&
3119 	    (alloc_sizes[size_index] < alloc_size))
3120 		size_index++;
3121 	if (size_index >= array_size) {
3122 		size_index = array_size - 1;
3123 	}
3124 
3125 	while ((allocated < total_alloc_size) &&
3126 	    (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
3127 
3128 		tx_dmap[i].dma_chunk_index = i;
3129 		tx_dmap[i].block_size = block_size;
3130 		tx_dmap[i].alength = alloc_sizes[size_index];
3131 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
3132 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
3133 		tx_dmap[i].dma_channel = dma_channel;
3134 		tx_dmap[i].contig_alloc_type = B_FALSE;
3135 		tx_dmap[i].kmem_alloc_type = B_FALSE;
3136 
3137 		/*
3138 		 * N2/NIU: data buffers must be contiguous as the driver
3139 		 *	   needs to call Hypervisor api to set up
3140 		 *	   logical pages.
3141 		 */
3142 		if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
3143 			tx_dmap[i].contig_alloc_type = B_TRUE;
3144 		}
3145 
3146 		status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
3147 		    &nxge_tx_dma_attr,
3148 		    tx_dmap[i].alength,
3149 		    &nxge_dev_buf_dma_acc_attr,
3150 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
3151 		    (p_nxge_dma_common_t)(&tx_dmap[i]));
3152 		if (status != NXGE_OK) {
3153 			size_index--;
3154 		} else {
3155 			i++;
3156 			allocated += alloc_sizes[size_index];
3157 		}
3158 	}
3159 
3160 	if (allocated < total_alloc_size) {
3161 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3162 		    "==> nxge_alloc_tx_buf_dma: not enough channel %d: "
3163 		    "allocated 0x%x requested 0x%x",
3164 		    dma_channel,
3165 		    allocated, total_alloc_size));
3166 		status = NXGE_ERROR;
3167 		goto nxge_alloc_tx_mem_fail1;
3168 	}
3169 
3170 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3171 	    "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: "
3172 	    "allocated 0x%x requested 0x%x",
3173 	    dma_channel,
3174 	    allocated, total_alloc_size));
3175 
3176 	*num_chunks = i;
3177 	*dmap = tx_dmap;
3178 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3179 	    "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
3180 	    *dmap, i));
3181 	goto nxge_alloc_tx_mem_exit;
3182 
3183 nxge_alloc_tx_mem_fail1:
3184 	KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
3185 
3186 nxge_alloc_tx_mem_exit:
3187 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3188 	    "<== nxge_alloc_tx_buf_dma status 0x%08x", status));
3189 
3190 	return (status);
3191 }
3192 
3193 /*ARGSUSED*/
3194 static void
3195 nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
3196     uint32_t num_chunks)
3197 {
3198 	int		i;
3199 
3200 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma"));
3201 
3202 	if (dmap == 0)
3203 		return;
3204 
3205 	for (i = 0; i < num_chunks; i++) {
3206 		nxge_dma_mem_free(dmap++);
3207 	}
3208 
3209 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma"));
3210 }
3211 
3212 /*ARGSUSED*/
3213 nxge_status_t
3214 nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
3215     p_nxge_dma_common_t *dmap, size_t size)
3216 {
3217 	p_nxge_dma_common_t 	tx_dmap;
3218 	nxge_status_t		status = NXGE_OK;
3219 
3220 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma"));
3221 	tx_dmap = (p_nxge_dma_common_t)
3222 	    KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
3223 
3224 	tx_dmap->contig_alloc_type = B_FALSE;
3225 	tx_dmap->kmem_alloc_type = B_FALSE;
3226 
3227 	status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
3228 	    &nxge_desc_dma_attr,
3229 	    size,
3230 	    &nxge_dev_desc_dma_acc_attr,
3231 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3232 	    tx_dmap);
3233 	if (status != NXGE_OK) {
3234 		goto nxge_alloc_tx_cntl_dma_fail1;
3235 	}
3236 
3237 	*dmap = tx_dmap;
3238 	goto nxge_alloc_tx_cntl_dma_exit;
3239 
3240 nxge_alloc_tx_cntl_dma_fail1:
3241 	KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t));
3242 
3243 nxge_alloc_tx_cntl_dma_exit:
3244 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3245 	    "<== nxge_alloc_tx_cntl_dma status 0x%08x", status));
3246 
3247 	return (status);
3248 }
3249 
3250 /*ARGSUSED*/
3251 static void
3252 nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
3253 {
3254 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma"));
3255 
3256 	if (dmap == 0)
3257 		return;
3258 
3259 	nxge_dma_mem_free(dmap);
3260 
3261 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma"));
3262 }
3263 
3264 /*
3265  * nxge_free_tx_mem_pool
3266  *
3267  *	This function frees all of the per-port TDC control data structures.
3268  *	The per-channel (TDC) data structures are freed when the channel
3269  *	is stopped.
3270  *
3271  * Arguments:
3272  * 	nxgep
3273  *
3274  * Notes:
3275  *
3276  * Context:
3277  *	Any domain
3278  */
3279 static void
3280 nxge_free_tx_mem_pool(p_nxge_t nxgep)
3281 {
3282 	int tdc_max = NXGE_MAX_TDCS;
3283 
3284 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool"));
3285 
3286 	if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) {
3287 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3288 		    "<== nxge_free_tx_mem_pool "
3289 		    "(null tx buf pool or buf not allocated"));
3290 		return;
3291 	}
3292 	if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) {
3293 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
3294 		    "<== nxge_free_tx_mem_pool "
3295 		    "(null tx cntl buf pool or cntl buf not allocated"));
3296 		return;
3297 	}
3298 
3299 	/* 1. Free the mailboxes. */
3300 	KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p,
3301 	    sizeof (p_tx_mbox_t) * tdc_max);
3302 	KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t));
3303 
3304 	nxgep->tx_mbox_areas_p = 0;
3305 
3306 	/* 2. Free the transmit ring arrays. */
3307 	KMEM_FREE(nxgep->tx_rings->rings,
3308 	    sizeof (p_tx_ring_t) * tdc_max);
3309 	KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t));
3310 
3311 	nxgep->tx_rings = 0;
3312 
3313 	/* 3. Free the completion ring data structures. */
3314 	KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p,
3315 	    sizeof (p_nxge_dma_common_t) * tdc_max);
3316 	KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t));
3317 
3318 	nxgep->tx_cntl_pool_p = 0;
3319 
3320 	/* 4. Free the data ring data structures. */
3321 	KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks,
3322 	    sizeof (uint32_t) * tdc_max);
3323 	KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p,
3324 	    sizeof (p_nxge_dma_common_t) * tdc_max);
3325 	KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t));
3326 
3327 	nxgep->tx_buf_pool_p = 0;
3328 
3329 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool"));
3330 }
3331 
3332 /*ARGSUSED*/
3333 static nxge_status_t
3334 nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method,
3335 	struct ddi_dma_attr *dma_attrp,
3336 	size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
3337 	p_nxge_dma_common_t dma_p)
3338 {
3339 	caddr_t 		kaddrp;
3340 	int			ddi_status = DDI_SUCCESS;
3341 	boolean_t		contig_alloc_type;
3342 	boolean_t		kmem_alloc_type;
3343 
3344 	contig_alloc_type = dma_p->contig_alloc_type;
3345 
3346 	if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) {
3347 		/*
3348 		 * contig_alloc_type for contiguous memory only allowed
3349 		 * for N2/NIU.
3350 		 */
3351 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3352 		    "nxge_dma_mem_alloc: alloc type not allowed (%d)",
3353 		    dma_p->contig_alloc_type));
3354 		return (NXGE_ERROR | NXGE_DDI_FAILED);
3355 	}
3356 
3357 	dma_p->dma_handle = NULL;
3358 	dma_p->acc_handle = NULL;
3359 	dma_p->kaddrp = dma_p->last_kaddrp = NULL;
3360 	dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL;
3361 	ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp,
3362 	    DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
3363 	if (ddi_status != DDI_SUCCESS) {
3364 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3365 		    "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
3366 		return (NXGE_ERROR | NXGE_DDI_FAILED);
3367 	}
3368 
3369 	kmem_alloc_type = dma_p->kmem_alloc_type;
3370 
3371 	switch (contig_alloc_type) {
3372 	case B_FALSE:
3373 		switch (kmem_alloc_type) {
3374 		case B_FALSE:
3375 			ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle,
3376 			    length,
3377 			    acc_attr_p,
3378 			    xfer_flags,
3379 			    DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
3380 			    &dma_p->acc_handle);
3381 			if (ddi_status != DDI_SUCCESS) {
3382 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3383 				    "nxge_dma_mem_alloc: "
3384 				    "ddi_dma_mem_alloc failed"));
3385 				ddi_dma_free_handle(&dma_p->dma_handle);
3386 				dma_p->dma_handle = NULL;
3387 				return (NXGE_ERROR | NXGE_DDI_FAILED);
3388 			}
3389 			if (dma_p->alength < length) {
3390 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3391 				    "nxge_dma_mem_alloc:di_dma_mem_alloc "
3392 				    "< length."));
3393 				ddi_dma_mem_free(&dma_p->acc_handle);
3394 				ddi_dma_free_handle(&dma_p->dma_handle);
3395 				dma_p->acc_handle = NULL;
3396 				dma_p->dma_handle = NULL;
3397 				return (NXGE_ERROR);
3398 			}
3399 
3400 			ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle,
3401 			    NULL,
3402 			    kaddrp, dma_p->alength, xfer_flags,
3403 			    DDI_DMA_DONTWAIT,
3404 			    0, &dma_p->dma_cookie, &dma_p->ncookies);
3405 			if (ddi_status != DDI_DMA_MAPPED) {
3406 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3407 				    "nxge_dma_mem_alloc: ddi_dma_addr_bind "
3408 				    "failed "
3409 				    "(staus 0x%x ncookies %d.)", ddi_status,
3410 				    dma_p->ncookies));
3411 				if (dma_p->acc_handle) {
3412 					ddi_dma_mem_free(&dma_p->acc_handle);
3413 					dma_p->acc_handle = NULL;
3414 				}
3415 				ddi_dma_free_handle(&dma_p->dma_handle);
3416 				dma_p->dma_handle = NULL;
3417 				return (NXGE_ERROR | NXGE_DDI_FAILED);
3418 			}
3419 
3420 			if (dma_p->ncookies != 1) {
3421 				NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3422 				    "nxge_dma_mem_alloc:ddi_dma_addr_bind "
3423 				    "> 1 cookie"
3424 				    "(staus 0x%x ncookies %d.)", ddi_status,
3425 				    dma_p->ncookies));
3426 				(void) ddi_dma_unbind_handle(dma_p->dma_handle);
3427 				if (dma_p->acc_handle) {
3428 					ddi_dma_mem_free(&dma_p->acc_handle);
3429 					dma_p->acc_handle = NULL;
3430 				}
3431 				ddi_dma_free_handle(&dma_p->dma_handle);
3432 				dma_p->dma_handle = NULL;
3433 				dma_p->acc_handle = NULL;
3434 				return (NXGE_ERROR);
3435 			}
3436 			break;
3437 
3438 		case B_TRUE:
3439 			kaddrp = KMEM_ALLOC(length, KM_NOSLEEP);
3440 			if (kaddrp == NULL) {
3441 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3442 				    "nxge_dma_mem_alloc:ddi_dma_mem_alloc "
3443 				    "kmem alloc failed"));
3444 				return (NXGE_ERROR);
3445 			}
3446 
3447 			dma_p->alength = length;
3448 			ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle,
3449 			    NULL, kaddrp, dma_p->alength, xfer_flags,
3450 			    DDI_DMA_DONTWAIT, 0,
3451 			    &dma_p->dma_cookie, &dma_p->ncookies);
3452 			if (ddi_status != DDI_DMA_MAPPED) {
3453 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3454 				    "nxge_dma_mem_alloc:ddi_dma_addr_bind: "
3455 				    "(kmem_alloc) failed kaddrp $%p length %d "
3456 				    "(staus 0x%x (%d) ncookies %d.)",
3457 				    kaddrp, length,
3458 				    ddi_status, ddi_status, dma_p->ncookies));
3459 				KMEM_FREE(kaddrp, length);
3460 				dma_p->acc_handle = NULL;
3461 				ddi_dma_free_handle(&dma_p->dma_handle);
3462 				dma_p->dma_handle = NULL;
3463 				dma_p->kaddrp = NULL;
3464 				return (NXGE_ERROR | NXGE_DDI_FAILED);
3465 			}
3466 
3467 			if (dma_p->ncookies != 1) {
3468 				NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3469 				    "nxge_dma_mem_alloc:ddi_dma_addr_bind "
3470 				    "(kmem_alloc) > 1 cookie"
3471 				    "(staus 0x%x ncookies %d.)", ddi_status,
3472 				    dma_p->ncookies));
3473 				(void) ddi_dma_unbind_handle(dma_p->dma_handle);
3474 				KMEM_FREE(kaddrp, length);
3475 				ddi_dma_free_handle(&dma_p->dma_handle);
3476 				dma_p->dma_handle = NULL;
3477 				dma_p->acc_handle = NULL;
3478 				dma_p->kaddrp = NULL;
3479 				return (NXGE_ERROR);
3480 			}
3481 
3482 			dma_p->kaddrp = kaddrp;
3483 
3484 			NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
3485 			    "nxge_dma_mem_alloc: kmem_alloc dmap $%p "
3486 			    "kaddr $%p alength %d",
3487 			    dma_p,
3488 			    kaddrp,
3489 			    dma_p->alength));
3490 			break;
3491 		}
3492 		break;
3493 
3494 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
3495 	case B_TRUE:
3496 		kaddrp = (caddr_t)contig_mem_alloc(length);
3497 		if (kaddrp == NULL) {
3498 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3499 			    "nxge_dma_mem_alloc:contig_mem_alloc failed."));
3500 			ddi_dma_free_handle(&dma_p->dma_handle);
3501 			return (NXGE_ERROR | NXGE_DDI_FAILED);
3502 		}
3503 
3504 		dma_p->alength = length;
3505 		ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
3506 		    kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
3507 		    &dma_p->dma_cookie, &dma_p->ncookies);
3508 		if (ddi_status != DDI_DMA_MAPPED) {
3509 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3510 			    "nxge_dma_mem_alloc:di_dma_addr_bind failed "
3511 			    "(status 0x%x ncookies %d.)", ddi_status,
3512 			    dma_p->ncookies));
3513 
3514 			NXGE_DEBUG_MSG((nxgep, DMA_CTL,
3515 			    "==> nxge_dma_mem_alloc: (not mapped)"
3516 			    "length %lu (0x%x) "
3517 			    "free contig kaddrp $%p "
3518 			    "va_to_pa $%p",
3519 			    length, length,
3520 			    kaddrp,
3521 			    va_to_pa(kaddrp)));
3522 
3523 
3524 			contig_mem_free((void *)kaddrp, length);
3525 			ddi_dma_free_handle(&dma_p->dma_handle);
3526 
3527 			dma_p->dma_handle = NULL;
3528 			dma_p->acc_handle = NULL;
3529 			dma_p->alength = NULL;
3530 			dma_p->kaddrp = NULL;
3531 
3532 			return (NXGE_ERROR | NXGE_DDI_FAILED);
3533 		}
3534 
3535 		if (dma_p->ncookies != 1 ||
3536 		    (dma_p->dma_cookie.dmac_laddress == NULL)) {
3537 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3538 			    "nxge_dma_mem_alloc:di_dma_addr_bind > 1 "
3539 			    "cookie or "
3540 			    "dmac_laddress is NULL $%p size %d "
3541 			    " (status 0x%x ncookies %d.)",
3542 			    ddi_status,
3543 			    dma_p->dma_cookie.dmac_laddress,
3544 			    dma_p->dma_cookie.dmac_size,
3545 			    dma_p->ncookies));
3546 
3547 			contig_mem_free((void *)kaddrp, length);
3548 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
3549 			ddi_dma_free_handle(&dma_p->dma_handle);
3550 
3551 			dma_p->alength = 0;
3552 			dma_p->dma_handle = NULL;
3553 			dma_p->acc_handle = NULL;
3554 			dma_p->kaddrp = NULL;
3555 
3556 			return (NXGE_ERROR | NXGE_DDI_FAILED);
3557 		}
3558 		break;
3559 
3560 #else
3561 	case B_TRUE:
3562 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3563 		    "nxge_dma_mem_alloc: invalid alloc type for !sun4v"));
3564 		return (NXGE_ERROR | NXGE_DDI_FAILED);
3565 #endif
3566 	}
3567 
3568 	dma_p->kaddrp = kaddrp;
3569 	dma_p->last_kaddrp = (unsigned char *)kaddrp +
3570 	    dma_p->alength - RXBUF_64B_ALIGNED;
3571 #if defined(__i386)
3572 	dma_p->ioaddr_pp =
3573 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
3574 #else
3575 	dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress;
3576 #endif
3577 	dma_p->last_ioaddr_pp =
3578 #if defined(__i386)
3579 	    (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress +
3580 #else
3581 	    (unsigned char *)dma_p->dma_cookie.dmac_laddress +
3582 #endif
3583 	    dma_p->alength - RXBUF_64B_ALIGNED;
3584 
3585 	NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
3586 
3587 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
3588 	dma_p->orig_ioaddr_pp =
3589 	    (unsigned char *)dma_p->dma_cookie.dmac_laddress;
3590 	dma_p->orig_alength = length;
3591 	dma_p->orig_kaddrp = kaddrp;
3592 	dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp);
3593 #endif
3594 
3595 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: "
3596 	    "dma buffer allocated: dma_p $%p "
3597 	    "return dmac_ladress from cookie $%p cookie dmac_size %d "
3598 	    "dma_p->ioaddr_p $%p "
3599 	    "dma_p->orig_ioaddr_p $%p "
3600 	    "orig_vatopa $%p "
3601 	    "alength %d (0x%x) "
3602 	    "kaddrp $%p "
3603 	    "length %d (0x%x)",
3604 	    dma_p,
3605 	    dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size,
3606 	    dma_p->ioaddr_pp,
3607 	    dma_p->orig_ioaddr_pp,
3608 	    dma_p->orig_vatopa,
3609 	    dma_p->alength, dma_p->alength,
3610 	    kaddrp,
3611 	    length, length));
3612 
3613 	return (NXGE_OK);
3614 }
3615 
3616 static void
3617 nxge_dma_mem_free(p_nxge_dma_common_t dma_p)
3618 {
3619 	if (dma_p->dma_handle != NULL) {
3620 		if (dma_p->ncookies) {
3621 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
3622 			dma_p->ncookies = 0;
3623 		}
3624 		ddi_dma_free_handle(&dma_p->dma_handle);
3625 		dma_p->dma_handle = NULL;
3626 	}
3627 
3628 	if (dma_p->acc_handle != NULL) {
3629 		ddi_dma_mem_free(&dma_p->acc_handle);
3630 		dma_p->acc_handle = NULL;
3631 		NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
3632 	}
3633 
3634 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
3635 	if (dma_p->contig_alloc_type &&
3636 	    dma_p->orig_kaddrp && dma_p->orig_alength) {
3637 		NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: "
3638 		    "kaddrp $%p (orig_kaddrp $%p)"
3639 		    "mem type %d ",
3640 		    "orig_alength %d "
3641 		    "alength 0x%x (%d)",
3642 		    dma_p->kaddrp,
3643 		    dma_p->orig_kaddrp,
3644 		    dma_p->contig_alloc_type,
3645 		    dma_p->orig_alength,
3646 		    dma_p->alength, dma_p->alength));
3647 
3648 		contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength);
3649 		dma_p->orig_alength = NULL;
3650 		dma_p->orig_kaddrp = NULL;
3651 		dma_p->contig_alloc_type = B_FALSE;
3652 	}
3653 #endif
3654 	dma_p->kaddrp = NULL;
3655 	dma_p->alength = NULL;
3656 }
3657 
3658 static void
3659 nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p)
3660 {
3661 	uint64_t kaddr;
3662 	uint32_t buf_size;
3663 
3664 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf"));
3665 
3666 	if (dma_p->dma_handle != NULL) {
3667 		if (dma_p->ncookies) {
3668 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
3669 			dma_p->ncookies = 0;
3670 		}
3671 		ddi_dma_free_handle(&dma_p->dma_handle);
3672 		dma_p->dma_handle = NULL;
3673 	}
3674 
3675 	if (dma_p->acc_handle != NULL) {
3676 		ddi_dma_mem_free(&dma_p->acc_handle);
3677 		dma_p->acc_handle = NULL;
3678 		NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
3679 	}
3680 
3681 	NXGE_DEBUG_MSG((NULL, DMA_CTL,
3682 	    "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d",
3683 	    dma_p,
3684 	    dma_p->buf_alloc_state));
3685 
3686 	if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) {
3687 		NXGE_DEBUG_MSG((NULL, DMA_CTL,
3688 		    "<== nxge_dma_free_rx_data_buf: "
3689 		    "outstanding data buffers"));
3690 		return;
3691 	}
3692 
3693 #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
3694 	if (dma_p->contig_alloc_type &&
3695 	    dma_p->orig_kaddrp && dma_p->orig_alength) {
3696 		NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: "
3697 		    "kaddrp $%p (orig_kaddrp $%p)"
3698 		    "mem type %d ",
3699 		    "orig_alength %d "
3700 		    "alength 0x%x (%d)",
3701 		    dma_p->kaddrp,
3702 		    dma_p->orig_kaddrp,
3703 		    dma_p->contig_alloc_type,
3704 		    dma_p->orig_alength,
3705 		    dma_p->alength, dma_p->alength));
3706 
3707 		kaddr = (uint64_t)dma_p->orig_kaddrp;
3708 		buf_size = dma_p->orig_alength;
3709 		nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size);
3710 		dma_p->orig_alength = NULL;
3711 		dma_p->orig_kaddrp = NULL;
3712 		dma_p->contig_alloc_type = B_FALSE;
3713 		dma_p->kaddrp = NULL;
3714 		dma_p->alength = NULL;
3715 		return;
3716 	}
3717 #endif
3718 
3719 	if (dma_p->kmem_alloc_type) {
3720 		NXGE_DEBUG_MSG((NULL, DMA_CTL,
3721 		    "nxge_dma_free_rx_data_buf: free kmem "
3722 		    "kaddrp $%p (orig_kaddrp $%p)"
3723 		    "alloc type %d "
3724 		    "orig_alength %d "
3725 		    "alength 0x%x (%d)",
3726 		    dma_p->kaddrp,
3727 		    dma_p->orig_kaddrp,
3728 		    dma_p->kmem_alloc_type,
3729 		    dma_p->orig_alength,
3730 		    dma_p->alength, dma_p->alength));
3731 #if defined(__i386)
3732 		kaddr = (uint64_t)(uint32_t)dma_p->kaddrp;
3733 #else
3734 		kaddr = (uint64_t)dma_p->kaddrp;
3735 #endif
3736 		buf_size = dma_p->orig_alength;
3737 		NXGE_DEBUG_MSG((NULL, DMA_CTL,
3738 		    "nxge_dma_free_rx_data_buf: free dmap $%p "
3739 		    "kaddr $%p buf_size %d",
3740 		    dma_p,
3741 		    kaddr, buf_size));
3742 		nxge_free_buf(KMEM_ALLOC, kaddr, buf_size);
3743 		dma_p->alength = 0;
3744 		dma_p->orig_alength = 0;
3745 		dma_p->kaddrp = NULL;
3746 		dma_p->kmem_alloc_type = B_FALSE;
3747 	}
3748 
3749 	NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf"));
3750 }
3751 
3752 /*
3753  *	nxge_m_start() -- start transmitting and receiving.
3754  *
3755  *	This function is called by the MAC layer when the first
3756  *	stream is open to prepare the hardware ready for sending
3757  *	and transmitting packets.
3758  */
3759 static int
3760 nxge_m_start(void *arg)
3761 {
3762 	p_nxge_t 	nxgep = (p_nxge_t)arg;
3763 
3764 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start"));
3765 
3766 	/*
3767 	 * Are we already started?
3768 	 */
3769 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
3770 		return (0);
3771 	}
3772 
3773 	if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) {
3774 		(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
3775 	}
3776 
3777 	/*
3778 	 * Make sure RX MAC is disabled while we initialize.
3779 	 */
3780 	if (!isLDOMguest(nxgep)) {
3781 		(void) nxge_rx_mac_disable(nxgep);
3782 	}
3783 
3784 	/*
3785 	 * Grab the global lock.
3786 	 */
3787 	MUTEX_ENTER(nxgep->genlock);
3788 
3789 	/*
3790 	 * Initialize the driver and hardware.
3791 	 */
3792 	if (nxge_init(nxgep) != NXGE_OK) {
3793 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3794 		    "<== nxge_m_start: initialization failed"));
3795 		MUTEX_EXIT(nxgep->genlock);
3796 		return (EIO);
3797 	}
3798 
3799 	/*
3800 	 * Start timer to check the system error and tx hangs
3801 	 */
3802 	if (!isLDOMguest(nxgep))
3803 		nxgep->nxge_timerid = nxge_start_timer(nxgep,
3804 		    nxge_check_hw_state, NXGE_CHECK_TIMER);
3805 #if defined(sun4v)
3806 	else
3807 		nxge_hio_start_timer(nxgep);
3808 #endif
3809 
3810 	nxgep->link_notify = B_TRUE;
3811 	nxgep->link_check_count = 0;
3812 	nxgep->nxge_mac_state = NXGE_MAC_STARTED;
3813 
3814 	/*
3815 	 * Let the global lock go, since we are intialized.
3816 	 */
3817 	MUTEX_EXIT(nxgep->genlock);
3818 
3819 	/*
3820 	 * Let the MAC start receiving packets, now that
3821 	 * we are initialized.
3822 	 */
3823 	if (!isLDOMguest(nxgep)) {
3824 		if (nxge_rx_mac_enable(nxgep) != NXGE_OK) {
3825 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3826 			    "<== nxge_m_start: enable of RX mac failed"));
3827 			return (EIO);
3828 		}
3829 
3830 		/*
3831 		 * Enable hardware interrupts.
3832 		 */
3833 		nxge_intr_hw_enable(nxgep);
3834 	}
3835 #if defined(sun4v)
3836 	else {
3837 		/*
3838 		 * In guest domain we enable RDCs and their interrupts as
3839 		 * the last step.
3840 		 */
3841 		if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) {
3842 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3843 			    "<== nxge_m_start: enable of RDCs failed"));
3844 			return (EIO);
3845 		}
3846 
3847 		if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) {
3848 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3849 			    "<== nxge_m_start: intrs enable for RDCs failed"));
3850 			return (EIO);
3851 		}
3852 	}
3853 #endif
3854 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start"));
3855 	return (0);
3856 }
3857 
3858 static boolean_t
3859 nxge_check_groups_stopped(p_nxge_t nxgep)
3860 {
3861 	int	i;
3862 
3863 	for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
3864 		if (nxgep->rx_hio_groups[i].started)
3865 			return (B_FALSE);
3866 	}
3867 
3868 	return (B_TRUE);
3869 }
3870 
3871 /*
3872  *	nxge_m_stop(): stop transmitting and receiving.
3873  */
3874 static void
3875 nxge_m_stop(void *arg)
3876 {
3877 	p_nxge_t 	nxgep = (p_nxge_t)arg;
3878 	boolean_t	groups_stopped;
3879 
3880 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop"));
3881 
3882 	/*
3883 	 * Are the groups stopped?
3884 	 */
3885 	groups_stopped = nxge_check_groups_stopped(nxgep);
3886 	ASSERT(groups_stopped == B_TRUE);
3887 	if (!groups_stopped) {
3888 		cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n",
3889 		    nxgep->instance);
3890 		return;
3891 	}
3892 
3893 	if (!isLDOMguest(nxgep)) {
3894 		/*
3895 		 * Disable the RX mac.
3896 		 */
3897 		(void) nxge_rx_mac_disable(nxgep);
3898 
3899 		/*
3900 		 * Wait for the IPP to drain.
3901 		 */
3902 		(void) nxge_ipp_drain(nxgep);
3903 
3904 		/*
3905 		 * Disable hardware interrupts.
3906 		 */
3907 		nxge_intr_hw_disable(nxgep);
3908 	}
3909 #if defined(sun4v)
3910 	else {
3911 		(void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE);
3912 	}
3913 #endif
3914 
3915 	/*
3916 	 * Grab the global lock.
3917 	 */
3918 	MUTEX_ENTER(nxgep->genlock);
3919 
3920 	nxgep->nxge_mac_state = NXGE_MAC_STOPPING;
3921 	if (nxgep->nxge_timerid) {
3922 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
3923 		nxgep->nxge_timerid = 0;
3924 	}
3925 
3926 	/*
3927 	 * Clean up.
3928 	 */
3929 	nxge_uninit(nxgep);
3930 
3931 	nxgep->nxge_mac_state = NXGE_MAC_STOPPED;
3932 
3933 	/*
3934 	 * Let go of the global lock.
3935 	 */
3936 	MUTEX_EXIT(nxgep->genlock);
3937 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop"));
3938 }
3939 
3940 static int
3941 nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
3942 {
3943 	p_nxge_t 	nxgep = (p_nxge_t)arg;
3944 	struct 		ether_addr addrp;
3945 
3946 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3947 	    "==> nxge_m_multicst: add %d", add));
3948 
3949 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
3950 	if (add) {
3951 		if (nxge_add_mcast_addr(nxgep, &addrp)) {
3952 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3953 			    "<== nxge_m_multicst: add multicast failed"));
3954 			return (EINVAL);
3955 		}
3956 	} else {
3957 		if (nxge_del_mcast_addr(nxgep, &addrp)) {
3958 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3959 			    "<== nxge_m_multicst: del multicast failed"));
3960 			return (EINVAL);
3961 		}
3962 	}
3963 
3964 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst"));
3965 
3966 	return (0);
3967 }
3968 
3969 static int
3970 nxge_m_promisc(void *arg, boolean_t on)
3971 {
3972 	p_nxge_t 	nxgep = (p_nxge_t)arg;
3973 
3974 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3975 	    "==> nxge_m_promisc: on %d", on));
3976 
3977 	if (nxge_set_promisc(nxgep, on)) {
3978 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3979 		    "<== nxge_m_promisc: set promisc failed"));
3980 		return (EINVAL);
3981 	}
3982 
3983 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3984 	    "<== nxge_m_promisc: on %d", on));
3985 
3986 	return (0);
3987 }
3988 
3989 static void
3990 nxge_m_ioctl(void *arg,  queue_t *wq, mblk_t *mp)
3991 {
3992 	p_nxge_t 	nxgep = (p_nxge_t)arg;
3993 	struct 		iocblk *iocp;
3994 	boolean_t 	need_privilege;
3995 	int 		err;
3996 	int 		cmd;
3997 
3998 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl"));
3999 
4000 	iocp = (struct iocblk *)mp->b_rptr;
4001 	iocp->ioc_error = 0;
4002 	need_privilege = B_TRUE;
4003 	cmd = iocp->ioc_cmd;
4004 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd));
4005 	switch (cmd) {
4006 	default:
4007 		miocnak(wq, mp, 0, EINVAL);
4008 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid"));
4009 		return;
4010 
4011 	case LB_GET_INFO_SIZE:
4012 	case LB_GET_INFO:
4013 	case LB_GET_MODE:
4014 		need_privilege = B_FALSE;
4015 		break;
4016 	case LB_SET_MODE:
4017 		break;
4018 
4019 
4020 	case NXGE_GET_MII:
4021 	case NXGE_PUT_MII:
4022 	case NXGE_GET64:
4023 	case NXGE_PUT64:
4024 	case NXGE_GET_TX_RING_SZ:
4025 	case NXGE_GET_TX_DESC:
4026 	case NXGE_TX_SIDE_RESET:
4027 	case NXGE_RX_SIDE_RESET:
4028 	case NXGE_GLOBAL_RESET:
4029 	case NXGE_RESET_MAC:
4030 	case NXGE_TX_REGS_DUMP:
4031 	case NXGE_RX_REGS_DUMP:
4032 	case NXGE_INT_REGS_DUMP:
4033 	case NXGE_VIR_INT_REGS_DUMP:
4034 	case NXGE_PUT_TCAM:
4035 	case NXGE_GET_TCAM:
4036 	case NXGE_RTRACE:
4037 	case NXGE_RDUMP:
4038 	case NXGE_RX_CLASS:
4039 	case NXGE_RX_HASH:
4040 
4041 		need_privilege = B_FALSE;
4042 		break;
4043 	case NXGE_INJECT_ERR:
4044 		cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n");
4045 		nxge_err_inject(nxgep, wq, mp);
4046 		break;
4047 	}
4048 
4049 	if (need_privilege) {
4050 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
4051 		if (err != 0) {
4052 			miocnak(wq, mp, 0, err);
4053 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4054 			    "<== nxge_m_ioctl: no priv"));
4055 			return;
4056 		}
4057 	}
4058 
4059 	switch (cmd) {
4060 
4061 	case LB_GET_MODE:
4062 	case LB_SET_MODE:
4063 	case LB_GET_INFO_SIZE:
4064 	case LB_GET_INFO:
4065 		nxge_loopback_ioctl(nxgep, wq, mp, iocp);
4066 		break;
4067 
4068 	case NXGE_GET_MII:
4069 	case NXGE_PUT_MII:
4070 	case NXGE_PUT_TCAM:
4071 	case NXGE_GET_TCAM:
4072 	case NXGE_GET64:
4073 	case NXGE_PUT64:
4074 	case NXGE_GET_TX_RING_SZ:
4075 	case NXGE_GET_TX_DESC:
4076 	case NXGE_TX_SIDE_RESET:
4077 	case NXGE_RX_SIDE_RESET:
4078 	case NXGE_GLOBAL_RESET:
4079 	case NXGE_RESET_MAC:
4080 	case NXGE_TX_REGS_DUMP:
4081 	case NXGE_RX_REGS_DUMP:
4082 	case NXGE_INT_REGS_DUMP:
4083 	case NXGE_VIR_INT_REGS_DUMP:
4084 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4085 		    "==> nxge_m_ioctl: cmd 0x%x", cmd));
4086 		nxge_hw_ioctl(nxgep, wq, mp, iocp);
4087 		break;
4088 	case NXGE_RX_CLASS:
4089 		if (nxge_rxclass_ioctl(nxgep, wq, mp->b_cont) < 0)
4090 			miocnak(wq, mp, 0, EINVAL);
4091 		else
4092 			miocack(wq, mp, sizeof (rx_class_cfg_t), 0);
4093 		break;
4094 	case NXGE_RX_HASH:
4095 
4096 		if (nxge_rxhash_ioctl(nxgep, wq, mp->b_cont) < 0)
4097 			miocnak(wq, mp, 0, EINVAL);
4098 		else
4099 			miocack(wq, mp, sizeof (cfg_cmd_t), 0);
4100 		break;
4101 	}
4102 
4103 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl"));
4104 }
4105 
4106 extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
4107 
4108 void
4109 nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory)
4110 {
4111 	p_nxge_mmac_stats_t mmac_stats;
4112 	int i;
4113 	nxge_mmac_t *mmac_info;
4114 
4115 	mmac_info = &nxgep->nxge_mmac_info;
4116 
4117 	mmac_stats = &nxgep->statsp->mmac_stats;
4118 	mmac_stats->mmac_max_cnt = mmac_info->num_mmac;
4119 	mmac_stats->mmac_avail_cnt = mmac_info->naddrfree;
4120 
4121 	for (i = 0; i < ETHERADDRL; i++) {
4122 		if (factory) {
4123 			mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
4124 			    = mmac_info->factory_mac_pool[slot][
4125 			    (ETHERADDRL-1) - i];
4126 		} else {
4127 			mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
4128 			    = mmac_info->mac_pool[slot].addr[
4129 			    (ETHERADDRL - 1) - i];
4130 		}
4131 	}
4132 }
4133 
4134 /*
4135  * nxge_altmac_set() -- Set an alternate MAC address
4136  */
4137 static int
4138 nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot,
4139 	int rdctbl, boolean_t usetbl)
4140 {
4141 	uint8_t addrn;
4142 	uint8_t portn;
4143 	npi_mac_addr_t altmac;
4144 	hostinfo_t mac_rdc;
4145 	p_nxge_class_pt_cfg_t clscfgp;
4146 
4147 
4148 	altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff);
4149 	altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff);
4150 	altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff);
4151 
4152 	portn = nxgep->mac.portnum;
4153 	addrn = (uint8_t)slot - 1;
4154 
4155 	if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET,
4156 	    nxgep->function_num, addrn, &altmac) != NPI_SUCCESS)
4157 		return (EIO);
4158 
4159 	/*
4160 	 * Set the rdc table number for the host info entry
4161 	 * for this mac address slot.
4162 	 */
4163 	clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
4164 	mac_rdc.value = 0;
4165 	if (usetbl)
4166 		mac_rdc.bits.w0.rdc_tbl_num = rdctbl;
4167 	else
4168 		mac_rdc.bits.w0.rdc_tbl_num =
4169 		    clscfgp->mac_host_info[addrn].rdctbl;
4170 	mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr;
4171 
4172 	if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET,
4173 	    nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) {
4174 		return (EIO);
4175 	}
4176 
4177 	/*
4178 	 * Enable comparison with the alternate MAC address.
4179 	 * While the first alternate addr is enabled by bit 1 of register
4180 	 * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register
4181 	 * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn
4182 	 * accordingly before calling npi_mac_altaddr_entry.
4183 	 */
4184 	if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
4185 		addrn = (uint8_t)slot - 1;
4186 	else
4187 		addrn = (uint8_t)slot;
4188 
4189 	if (npi_mac_altaddr_enable(nxgep->npi_handle,
4190 	    nxgep->function_num, addrn) != NPI_SUCCESS) {
4191 		return (EIO);
4192 	}
4193 
4194 	return (0);
4195 }
4196 
4197 /*
4198  * nxeg_m_mmac_add_g() - find an unused address slot, set the address
4199  * value to the one specified, enable the port to start filtering on
4200  * the new MAC address.  Returns 0 on success.
4201  */
4202 int
4203 nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl,
4204 	boolean_t usetbl)
4205 {
4206 	p_nxge_t nxgep = arg;
4207 	int slot;
4208 	nxge_mmac_t *mmac_info;
4209 	int err;
4210 	nxge_status_t status;
4211 
4212 	mutex_enter(nxgep->genlock);
4213 
4214 	/*
4215 	 * Make sure that nxge is initialized, if _start() has
4216 	 * not been called.
4217 	 */
4218 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
4219 		status = nxge_init(nxgep);
4220 		if (status != NXGE_OK) {
4221 			mutex_exit(nxgep->genlock);
4222 			return (ENXIO);
4223 		}
4224 	}
4225 
4226 	mmac_info = &nxgep->nxge_mmac_info;
4227 	if (mmac_info->naddrfree == 0) {
4228 		mutex_exit(nxgep->genlock);
4229 		return (ENOSPC);
4230 	}
4231 
4232 	/*
4233 	 * 	Search for the first available slot. Because naddrfree
4234 	 * is not zero, we are guaranteed to find one.
4235 	 *	Each of the first two ports of Neptune has 16 alternate
4236 	 * MAC slots but only the first 7 (of 15) slots have assigned factory
4237 	 * MAC addresses. We first search among the slots without bundled
4238 	 * factory MACs. If we fail to find one in that range, then we
4239 	 * search the slots with bundled factory MACs.  A factory MAC
4240 	 * will be wasted while the slot is used with a user MAC address.
4241 	 * But the slot could be used by factory MAC again after calling
4242 	 * nxge_m_mmac_remove and nxge_m_mmac_reserve.
4243 	 */
4244 	for (slot = 0; slot <= mmac_info->num_mmac; slot++) {
4245 		if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
4246 			break;
4247 	}
4248 
4249 	ASSERT(slot <= mmac_info->num_mmac);
4250 
4251 	if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl,
4252 	    usetbl)) != 0) {
4253 		mutex_exit(nxgep->genlock);
4254 		return (err);
4255 	}
4256 
4257 	bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL);
4258 	mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED;
4259 	mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR;
4260 	mmac_info->naddrfree--;
4261 	nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
4262 
4263 	mutex_exit(nxgep->genlock);
4264 	return (0);
4265 }
4266 
4267 /*
4268  * Remove the specified mac address and update the HW not to filter
4269  * the mac address anymore.
4270  */
4271 int
4272 nxge_m_mmac_remove(void *arg, int slot)
4273 {
4274 	p_nxge_t nxgep = arg;
4275 	nxge_mmac_t *mmac_info;
4276 	uint8_t addrn;
4277 	uint8_t portn;
4278 	int err = 0;
4279 	nxge_status_t status;
4280 
4281 	mutex_enter(nxgep->genlock);
4282 
4283 	/*
4284 	 * Make sure that nxge is initialized, if _start() has
4285 	 * not been called.
4286 	 */
4287 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
4288 		status = nxge_init(nxgep);
4289 		if (status != NXGE_OK) {
4290 			mutex_exit(nxgep->genlock);
4291 			return (ENXIO);
4292 		}
4293 	}
4294 
4295 	mmac_info = &nxgep->nxge_mmac_info;
4296 	if (slot < 1 || slot > mmac_info->num_mmac) {
4297 		mutex_exit(nxgep->genlock);
4298 		return (EINVAL);
4299 	}
4300 
4301 	portn = nxgep->mac.portnum;
4302 	if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
4303 		addrn = (uint8_t)slot - 1;
4304 	else
4305 		addrn = (uint8_t)slot;
4306 
4307 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
4308 		if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn)
4309 		    == NPI_SUCCESS) {
4310 			mmac_info->naddrfree++;
4311 			mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED;
4312 			/*
4313 			 * Regardless if the MAC we just stopped filtering
4314 			 * is a user addr or a facory addr, we must set
4315 			 * the MMAC_VENDOR_ADDR flag if this slot has an
4316 			 * associated factory MAC to indicate that a factory
4317 			 * MAC is available.
4318 			 */
4319 			if (slot <= mmac_info->num_factory_mmac) {
4320 				mmac_info->mac_pool[slot].flags
4321 				    |= MMAC_VENDOR_ADDR;
4322 			}
4323 			/*
4324 			 * Clear mac_pool[slot].addr so that kstat shows 0
4325 			 * alternate MAC address if the slot is not used.
4326 			 * (But nxge_m_mmac_get returns the factory MAC even
4327 			 * when the slot is not used!)
4328 			 */
4329 			bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL);
4330 			nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
4331 		} else {
4332 			err = EIO;
4333 		}
4334 	} else {
4335 		err = EINVAL;
4336 	}
4337 
4338 	mutex_exit(nxgep->genlock);
4339 	return (err);
4340 }
4341 
4342 /*
4343  * The callback to query all the factory addresses. naddr must be the same as
4344  * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and
4345  * mcm_addr is the space allocated for keep all the addresses, whose size is
4346  * naddr * MAXMACADDRLEN.
4347  */
4348 static void
4349 nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr)
4350 {
4351 	nxge_t		*nxgep = arg;
4352 	nxge_mmac_t	*mmac_info;
4353 	int		i;
4354 
4355 	mutex_enter(nxgep->genlock);
4356 
4357 	mmac_info = &nxgep->nxge_mmac_info;
4358 	ASSERT(naddr == mmac_info->num_factory_mmac);
4359 
4360 	for (i = 0; i < naddr; i++) {
4361 		bcopy(mmac_info->factory_mac_pool[i + 1],
4362 		    addr + i * MAXMACADDRLEN, ETHERADDRL);
4363 	}
4364 
4365 	mutex_exit(nxgep->genlock);
4366 }
4367 
4368 
4369 static boolean_t
4370 nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
4371 {
4372 	nxge_t *nxgep = arg;
4373 	uint32_t *txflags = cap_data;
4374 
4375 	switch (cap) {
4376 	case MAC_CAPAB_HCKSUM:
4377 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4378 		    "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload));
4379 		if (nxge_cksum_offload <= 1) {
4380 			*txflags = HCKSUM_INET_PARTIAL;
4381 		}
4382 		break;
4383 
4384 	case MAC_CAPAB_MULTIFACTADDR: {
4385 		mac_capab_multifactaddr_t	*mfacp = cap_data;
4386 
4387 		if (!isLDOMguest(nxgep)) {
4388 			mutex_enter(nxgep->genlock);
4389 			mfacp->mcm_naddr =
4390 			    nxgep->nxge_mmac_info.num_factory_mmac;
4391 			mfacp->mcm_getaddr = nxge_m_getfactaddr;
4392 			mutex_exit(nxgep->genlock);
4393 		}
4394 		break;
4395 	}
4396 
4397 	case MAC_CAPAB_LSO: {
4398 		mac_capab_lso_t *cap_lso = cap_data;
4399 
4400 		if (nxgep->soft_lso_enable) {
4401 			if (nxge_cksum_offload <= 1) {
4402 				cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
4403 				if (nxge_lso_max > NXGE_LSO_MAXLEN) {
4404 					nxge_lso_max = NXGE_LSO_MAXLEN;
4405 				}
4406 				cap_lso->lso_basic_tcp_ipv4.lso_max =
4407 				    nxge_lso_max;
4408 			}
4409 			break;
4410 		} else {
4411 			return (B_FALSE);
4412 		}
4413 	}
4414 
4415 	case MAC_CAPAB_RINGS: {
4416 		mac_capab_rings_t	*cap_rings = cap_data;
4417 		p_nxge_hw_pt_cfg_t	p_cfgp = &nxgep->pt_config.hw_config;
4418 
4419 		mutex_enter(nxgep->genlock);
4420 		if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
4421 			if (isLDOMguest(nxgep))  {
4422 				cap_rings->mr_group_type =
4423 				    MAC_GROUP_TYPE_STATIC;
4424 				cap_rings->mr_rnum =
4425 				    NXGE_HIO_SHARE_MAX_CHANNELS;
4426 				cap_rings->mr_rget = nxge_fill_ring;
4427 				cap_rings->mr_gnum = 1;
4428 				cap_rings->mr_gget = nxge_hio_group_get;
4429 				cap_rings->mr_gaddring = NULL;
4430 				cap_rings->mr_gremring = NULL;
4431 			} else {
4432 				/*
4433 				 * Service Domain.
4434 				 */
4435 				cap_rings->mr_group_type =
4436 				    MAC_GROUP_TYPE_DYNAMIC;
4437 				cap_rings->mr_rnum = p_cfgp->max_rdcs;
4438 				cap_rings->mr_rget = nxge_fill_ring;
4439 				cap_rings->mr_gnum = p_cfgp->max_rdc_grpids;
4440 				cap_rings->mr_gget = nxge_hio_group_get;
4441 				cap_rings->mr_gaddring = nxge_group_add_ring;
4442 				cap_rings->mr_gremring = nxge_group_rem_ring;
4443 			}
4444 
4445 			NXGE_DEBUG_MSG((nxgep, RX_CTL,
4446 			    "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]",
4447 			    p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids));
4448 		} else {
4449 			/*
4450 			 * TX Rings.
4451 			 */
4452 			if (isLDOMguest(nxgep)) {
4453 				cap_rings->mr_group_type =
4454 				    MAC_GROUP_TYPE_STATIC;
4455 				cap_rings->mr_rnum =
4456 				    NXGE_HIO_SHARE_MAX_CHANNELS;
4457 				cap_rings->mr_rget = nxge_fill_ring;
4458 				cap_rings->mr_gnum = 0;
4459 				cap_rings->mr_gget = NULL;
4460 				cap_rings->mr_gaddring = NULL;
4461 				cap_rings->mr_gremring = NULL;
4462 			} else {
4463 				/*
4464 				 * Service Domain.
4465 				 */
4466 				cap_rings->mr_group_type =
4467 				    MAC_GROUP_TYPE_DYNAMIC;
4468 				cap_rings->mr_rnum = p_cfgp->tdc.count;
4469 				cap_rings->mr_rget = nxge_fill_ring;
4470 
4471 				/*
4472 				 * Share capable.
4473 				 *
4474 				 * Do not report the default group: hence -1
4475 				 */
4476 				cap_rings->mr_gnum =
4477 				    NXGE_MAX_TDC_GROUPS / nxgep->nports - 1;
4478 				cap_rings->mr_gget = nxge_hio_group_get;
4479 				cap_rings->mr_gaddring = nxge_group_add_ring;
4480 				cap_rings->mr_gremring = nxge_group_rem_ring;
4481 			}
4482 
4483 			NXGE_DEBUG_MSG((nxgep, TX_CTL,
4484 			    "==> nxge_m_getcapab: tx rings # of rings %d",
4485 			    p_cfgp->tdc.count));
4486 		}
4487 		mutex_exit(nxgep->genlock);
4488 		break;
4489 	}
4490 
4491 #if defined(sun4v)
4492 	case MAC_CAPAB_SHARES: {
4493 		mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data;
4494 
4495 		/*
4496 		 * Only the service domain driver responds to
4497 		 * this capability request.
4498 		 */
4499 		mutex_enter(nxgep->genlock);
4500 		if (isLDOMservice(nxgep)) {
4501 			mshares->ms_snum = 3;
4502 			mshares->ms_handle = (void *)nxgep;
4503 			mshares->ms_salloc = nxge_hio_share_alloc;
4504 			mshares->ms_sfree = nxge_hio_share_free;
4505 			mshares->ms_sadd = nxge_hio_share_add_group;
4506 			mshares->ms_sremove = nxge_hio_share_rem_group;
4507 			mshares->ms_squery = nxge_hio_share_query;
4508 			mshares->ms_sbind = nxge_hio_share_bind;
4509 			mshares->ms_sunbind = nxge_hio_share_unbind;
4510 			mutex_exit(nxgep->genlock);
4511 		} else {
4512 			mutex_exit(nxgep->genlock);
4513 			return (B_FALSE);
4514 		}
4515 		break;
4516 	}
4517 #endif
4518 	default:
4519 		return (B_FALSE);
4520 	}
4521 	return (B_TRUE);
4522 }
4523 
4524 static boolean_t
4525 nxge_param_locked(mac_prop_id_t pr_num)
4526 {
4527 	/*
4528 	 * All adv_* parameters are locked (read-only) while
4529 	 * the device is in any sort of loopback mode ...
4530 	 */
4531 	switch (pr_num) {
4532 		case MAC_PROP_ADV_1000FDX_CAP:
4533 		case MAC_PROP_EN_1000FDX_CAP:
4534 		case MAC_PROP_ADV_1000HDX_CAP:
4535 		case MAC_PROP_EN_1000HDX_CAP:
4536 		case MAC_PROP_ADV_100FDX_CAP:
4537 		case MAC_PROP_EN_100FDX_CAP:
4538 		case MAC_PROP_ADV_100HDX_CAP:
4539 		case MAC_PROP_EN_100HDX_CAP:
4540 		case MAC_PROP_ADV_10FDX_CAP:
4541 		case MAC_PROP_EN_10FDX_CAP:
4542 		case MAC_PROP_ADV_10HDX_CAP:
4543 		case MAC_PROP_EN_10HDX_CAP:
4544 		case MAC_PROP_AUTONEG:
4545 		case MAC_PROP_FLOWCTRL:
4546 			return (B_TRUE);
4547 	}
4548 	return (B_FALSE);
4549 }
4550 
4551 /*
4552  * callback functions for set/get of properties
4553  */
4554 static int
4555 nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4556     uint_t pr_valsize, const void *pr_val)
4557 {
4558 	nxge_t		*nxgep = barg;
4559 	p_nxge_param_t	param_arr = nxgep->param_arr;
4560 	p_nxge_stats_t	statsp = nxgep->statsp;
4561 	int		err = 0;
4562 
4563 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop"));
4564 
4565 	mutex_enter(nxgep->genlock);
4566 	if (statsp->port_stats.lb_mode != nxge_lb_normal &&
4567 	    nxge_param_locked(pr_num)) {
4568 		/*
4569 		 * All adv_* parameters are locked (read-only)
4570 		 * while the device is in any sort of loopback mode.
4571 		 */
4572 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4573 		    "==> nxge_m_setprop: loopback mode: read only"));
4574 		mutex_exit(nxgep->genlock);
4575 		return (EBUSY);
4576 	}
4577 
4578 	switch (pr_num) {
4579 	case MAC_PROP_EN_1000FDX_CAP:
4580 		nxgep->param_en_1000fdx =
4581 		    param_arr[param_anar_1000fdx].value = *(uint8_t *)pr_val;
4582 		goto reprogram;
4583 
4584 	case MAC_PROP_EN_100FDX_CAP:
4585 		nxgep->param_en_100fdx =
4586 		    param_arr[param_anar_100fdx].value = *(uint8_t *)pr_val;
4587 		goto reprogram;
4588 
4589 	case MAC_PROP_EN_10FDX_CAP:
4590 		nxgep->param_en_10fdx =
4591 		    param_arr[param_anar_10fdx].value = *(uint8_t *)pr_val;
4592 		goto reprogram;
4593 
4594 	case MAC_PROP_AUTONEG:
4595 		param_arr[param_autoneg].value = *(uint8_t *)pr_val;
4596 		goto reprogram;
4597 
4598 	case MAC_PROP_MTU: {
4599 		uint32_t cur_mtu, new_mtu, old_framesize;
4600 
4601 		cur_mtu = nxgep->mac.default_mtu;
4602 		ASSERT(pr_valsize >= sizeof (new_mtu));
4603 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
4604 
4605 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4606 		    "==> nxge_m_setprop: set MTU: %d is_jumbo %d",
4607 		    new_mtu, nxgep->mac.is_jumbo));
4608 
4609 		if (new_mtu == cur_mtu) {
4610 			err = 0;
4611 			break;
4612 		}
4613 
4614 		if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
4615 			err = EBUSY;
4616 			break;
4617 		}
4618 
4619 		if ((new_mtu < NXGE_DEFAULT_MTU) ||
4620 		    (new_mtu > NXGE_MAXIMUM_MTU)) {
4621 			err = EINVAL;
4622 			break;
4623 		}
4624 
4625 		old_framesize = (uint32_t)nxgep->mac.maxframesize;
4626 		nxgep->mac.maxframesize = (uint16_t)
4627 		    (new_mtu + NXGE_EHEADER_VLAN_CRC);
4628 		if (nxge_mac_set_framesize(nxgep)) {
4629 			nxgep->mac.maxframesize =
4630 			    (uint16_t)old_framesize;
4631 			err = EINVAL;
4632 			break;
4633 		}
4634 
4635 		nxgep->mac.default_mtu = new_mtu;
4636 		nxgep->mac.is_jumbo = (new_mtu > NXGE_DEFAULT_MTU);
4637 
4638 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4639 		    "==> nxge_m_setprop: set MTU: %d maxframe %d",
4640 		    new_mtu, nxgep->mac.maxframesize));
4641 		break;
4642 	}
4643 
4644 	case MAC_PROP_FLOWCTRL: {
4645 		link_flowctrl_t	fl;
4646 
4647 		ASSERT(pr_valsize >= sizeof (fl));
4648 		bcopy(pr_val, &fl, sizeof (fl));
4649 
4650 		switch (fl) {
4651 		case LINK_FLOWCTRL_NONE:
4652 			param_arr[param_anar_pause].value = 0;
4653 			break;
4654 
4655 		case LINK_FLOWCTRL_RX:
4656 			param_arr[param_anar_pause].value = 1;
4657 			break;
4658 
4659 		case LINK_FLOWCTRL_TX:
4660 		case LINK_FLOWCTRL_BI:
4661 			err = EINVAL;
4662 			break;
4663 		default:
4664 			err = EINVAL;
4665 			break;
4666 		}
4667 reprogram:
4668 		if ((err == 0) && !isLDOMguest(nxgep)) {
4669 			if (!nxge_param_link_update(nxgep)) {
4670 				err = EINVAL;
4671 			}
4672 		} else {
4673 			err = EINVAL;
4674 		}
4675 		break;
4676 	}
4677 
4678 	case MAC_PROP_PRIVATE:
4679 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4680 		    "==> nxge_m_setprop: private property"));
4681 		err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, pr_val);
4682 		break;
4683 
4684 	default:
4685 		err = ENOTSUP;
4686 		break;
4687 	}
4688 
4689 	mutex_exit(nxgep->genlock);
4690 
4691 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4692 	    "<== nxge_m_setprop (return %d)", err));
4693 	return (err);
4694 }
4695 
4696 static int
4697 nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4698     uint_t pr_valsize, void *pr_val)
4699 {
4700 	nxge_t 		*nxgep = barg;
4701 	p_nxge_param_t	param_arr = nxgep->param_arr;
4702 	p_nxge_stats_t	statsp = nxgep->statsp;
4703 
4704 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4705 	    "==> nxge_m_getprop: pr_num %d", pr_num));
4706 
4707 	switch (pr_num) {
4708 	case MAC_PROP_DUPLEX:
4709 		*(uint8_t *)pr_val = statsp->mac_stats.link_duplex;
4710 		break;
4711 
4712 	case MAC_PROP_SPEED: {
4713 		uint64_t val = statsp->mac_stats.link_speed * 1000000ull;
4714 
4715 		ASSERT(pr_valsize >= sizeof (val));
4716 		bcopy(&val, pr_val, sizeof (val));
4717 		break;
4718 	}
4719 
4720 	case MAC_PROP_STATUS: {
4721 		link_state_t state = statsp->mac_stats.link_up ?
4722 		    LINK_STATE_UP : LINK_STATE_DOWN;
4723 
4724 		ASSERT(pr_valsize >= sizeof (state));
4725 		bcopy(&state, pr_val, sizeof (state));
4726 		break;
4727 	}
4728 
4729 	case MAC_PROP_AUTONEG:
4730 		*(uint8_t *)pr_val = param_arr[param_autoneg].value;
4731 		break;
4732 
4733 	case MAC_PROP_FLOWCTRL: {
4734 		link_flowctrl_t fl = param_arr[param_anar_pause].value != 0 ?
4735 		    LINK_FLOWCTRL_RX : LINK_FLOWCTRL_NONE;
4736 
4737 		ASSERT(pr_valsize >= sizeof (fl));
4738 		bcopy(&fl, pr_val, sizeof (fl));
4739 		break;
4740 	}
4741 
4742 	case MAC_PROP_ADV_1000FDX_CAP:
4743 		*(uint8_t *)pr_val = param_arr[param_anar_1000fdx].value;
4744 		break;
4745 
4746 	case MAC_PROP_EN_1000FDX_CAP:
4747 		*(uint8_t *)pr_val = nxgep->param_en_1000fdx;
4748 		break;
4749 
4750 	case MAC_PROP_ADV_100FDX_CAP:
4751 		*(uint8_t *)pr_val = param_arr[param_anar_100fdx].value;
4752 		break;
4753 
4754 	case MAC_PROP_EN_100FDX_CAP:
4755 		*(uint8_t *)pr_val = nxgep->param_en_100fdx;
4756 		break;
4757 
4758 	case MAC_PROP_ADV_10FDX_CAP:
4759 		*(uint8_t *)pr_val = param_arr[param_anar_10fdx].value;
4760 		break;
4761 
4762 	case MAC_PROP_EN_10FDX_CAP:
4763 		*(uint8_t *)pr_val = nxgep->param_en_10fdx;
4764 		break;
4765 
4766 	case MAC_PROP_PRIVATE:
4767 		return (nxge_get_priv_prop(nxgep, pr_name, pr_valsize,
4768 		    pr_val));
4769 
4770 	default:
4771 		return (ENOTSUP);
4772 	}
4773 
4774 	return (0);
4775 }
4776 
4777 static void
4778 nxge_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
4779     mac_prop_info_handle_t prh)
4780 {
4781 	nxge_t		*nxgep = barg;
4782 	p_nxge_stats_t	statsp = nxgep->statsp;
4783 
4784 	/*
4785 	 * By default permissions are read/write unless specified
4786 	 * otherwise by the driver.
4787 	 */
4788 
4789 	switch (pr_num) {
4790 	case MAC_PROP_DUPLEX:
4791 	case MAC_PROP_SPEED:
4792 	case MAC_PROP_STATUS:
4793 	case MAC_PROP_EN_1000HDX_CAP:
4794 	case MAC_PROP_EN_100HDX_CAP:
4795 	case MAC_PROP_EN_10HDX_CAP:
4796 	case MAC_PROP_ADV_1000FDX_CAP:
4797 	case MAC_PROP_ADV_1000HDX_CAP:
4798 	case MAC_PROP_ADV_100FDX_CAP:
4799 	case MAC_PROP_ADV_100HDX_CAP:
4800 	case MAC_PROP_ADV_10FDX_CAP:
4801 	case MAC_PROP_ADV_10HDX_CAP:
4802 		/*
4803 		 * Note that read-only properties don't need to
4804 		 * provide default values since they cannot be
4805 		 * changed by the administrator.
4806 		 */
4807 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4808 		break;
4809 
4810 	case MAC_PROP_EN_1000FDX_CAP:
4811 	case MAC_PROP_EN_100FDX_CAP:
4812 	case MAC_PROP_EN_10FDX_CAP:
4813 		mac_prop_info_set_default_uint8(prh, 1);
4814 		break;
4815 
4816 	case MAC_PROP_AUTONEG:
4817 		mac_prop_info_set_default_uint8(prh, 1);
4818 		break;
4819 
4820 	case MAC_PROP_FLOWCTRL:
4821 		mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_RX);
4822 		break;
4823 
4824 	case MAC_PROP_MTU:
4825 		mac_prop_info_set_range_uint32(prh,
4826 		    NXGE_DEFAULT_MTU, NXGE_MAXIMUM_MTU);
4827 		break;
4828 
4829 	case MAC_PROP_PRIVATE:
4830 		nxge_priv_propinfo(pr_name, prh);
4831 		break;
4832 	}
4833 
4834 	mutex_enter(nxgep->genlock);
4835 	if (statsp->port_stats.lb_mode != nxge_lb_normal &&
4836 	    nxge_param_locked(pr_num)) {
4837 		/*
4838 		 * Some properties are locked (read-only) while the
4839 		 * device is in any sort of loopback mode.
4840 		 */
4841 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4842 	}
4843 	mutex_exit(nxgep->genlock);
4844 }
4845 
4846 static void
4847 nxge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh)
4848 {
4849 	char valstr[64];
4850 
4851 	bzero(valstr, sizeof (valstr));
4852 
4853 	if (strcmp(pr_name, "_function_number") == 0 ||
4854 	    strcmp(pr_name, "_fw_version") == 0 ||
4855 	    strcmp(pr_name, "_port_mode") == 0 ||
4856 	    strcmp(pr_name, "_hot_swap_phy") == 0) {
4857 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
4858 
4859 	} else if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
4860 		(void) snprintf(valstr, sizeof (valstr),
4861 		    "%d", RXDMA_RCR_TO_DEFAULT);
4862 
4863 	} else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
4864 		(void) snprintf(valstr, sizeof (valstr),
4865 		    "%d", RXDMA_RCR_PTHRES_DEFAULT);
4866 
4867 	} else 	if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 ||
4868 	    strcmp(pr_name, "_class_opt_ipv4_udp") == 0 ||
4869 	    strcmp(pr_name, "_class_opt_ipv4_ah") == 0 ||
4870 	    strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 ||
4871 	    strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 ||
4872 	    strcmp(pr_name, "_class_opt_ipv6_udp") == 0 ||
4873 	    strcmp(pr_name, "_class_opt_ipv6_ah") == 0 ||
4874 	    strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
4875 		(void) snprintf(valstr, sizeof (valstr), "%x",
4876 		    NXGE_CLASS_FLOW_GEN_SERVER);
4877 
4878 	} else if (strcmp(pr_name, "_soft_lso_enable") == 0) {
4879 		(void) snprintf(valstr, sizeof (valstr), "%d", 0);
4880 
4881 	} else 	if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
4882 		(void) snprintf(valstr, sizeof (valstr), "%d", 1);
4883 
4884 	} else if (strcmp(pr_name, "_adv_pause_cap") == 0) {
4885 		(void) snprintf(valstr, sizeof (valstr), "%d", 1);
4886 	}
4887 
4888 	if (strlen(valstr) > 0)
4889 		mac_prop_info_set_default_str(prh, valstr);
4890 }
4891 
4892 /* ARGSUSED */
4893 static int
4894 nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize,
4895     const void *pr_val)
4896 {
4897 	p_nxge_param_t	param_arr = nxgep->param_arr;
4898 	int		err = 0;
4899 	long		result;
4900 
4901 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4902 	    "==> nxge_set_priv_prop: name %s", pr_name));
4903 
4904 	/* Blanking */
4905 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
4906 		err = nxge_param_rx_intr_time(nxgep, NULL, NULL,
4907 		    (char *)pr_val,
4908 		    (caddr_t)&param_arr[param_rxdma_intr_time]);
4909 		if (err) {
4910 			NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4911 			    "<== nxge_set_priv_prop: "
4912 			    "unable to set (%s)", pr_name));
4913 			err = EINVAL;
4914 		} else {
4915 			err = 0;
4916 			NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4917 			    "<== nxge_set_priv_prop: "
4918 			    "set (%s)", pr_name));
4919 		}
4920 
4921 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4922 		    "<== nxge_set_priv_prop: name %s (value %d)",
4923 		    pr_name, result));
4924 
4925 		return (err);
4926 	}
4927 
4928 	if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
4929 		err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL,
4930 		    (char *)pr_val,
4931 		    (caddr_t)&param_arr[param_rxdma_intr_pkts]);
4932 		if (err) {
4933 			NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4934 			    "<== nxge_set_priv_prop: "
4935 			    "unable to set (%s)", pr_name));
4936 			err = EINVAL;
4937 		} else {
4938 			err = 0;
4939 			NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4940 			    "<== nxge_set_priv_prop: "
4941 			    "set (%s)", pr_name));
4942 		}
4943 
4944 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4945 		    "<== nxge_set_priv_prop: name %s (value %d)",
4946 		    pr_name, result));
4947 
4948 		return (err);
4949 	}
4950 
4951 	/* Classification */
4952 	if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
4953 		if (pr_val == NULL) {
4954 			err = EINVAL;
4955 			return (err);
4956 		}
4957 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4958 
4959 		err = nxge_param_set_ip_opt(nxgep, NULL,
4960 		    NULL, (char *)pr_val,
4961 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
4962 
4963 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4964 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
4965 		    pr_name, result));
4966 
4967 		return (err);
4968 	}
4969 
4970 	if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
4971 		if (pr_val == NULL) {
4972 			err = EINVAL;
4973 			return (err);
4974 		}
4975 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4976 
4977 		err = nxge_param_set_ip_opt(nxgep, NULL,
4978 		    NULL, (char *)pr_val,
4979 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
4980 
4981 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4982 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
4983 		    pr_name, result));
4984 
4985 		return (err);
4986 	}
4987 	if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
4988 		if (pr_val == NULL) {
4989 			err = EINVAL;
4990 			return (err);
4991 		}
4992 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
4993 
4994 		err = nxge_param_set_ip_opt(nxgep, NULL,
4995 		    NULL, (char *)pr_val,
4996 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
4997 
4998 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
4999 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5000 		    pr_name, result));
5001 
5002 		return (err);
5003 	}
5004 	if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
5005 		if (pr_val == NULL) {
5006 			err = EINVAL;
5007 			return (err);
5008 		}
5009 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5010 
5011 		err = nxge_param_set_ip_opt(nxgep, NULL,
5012 		    NULL, (char *)pr_val,
5013 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
5014 
5015 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5016 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5017 		    pr_name, result));
5018 
5019 		return (err);
5020 	}
5021 
5022 	if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
5023 		if (pr_val == NULL) {
5024 			err = EINVAL;
5025 			return (err);
5026 		}
5027 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5028 
5029 		err = nxge_param_set_ip_opt(nxgep, NULL,
5030 		    NULL, (char *)pr_val,
5031 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
5032 
5033 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5034 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5035 		    pr_name, result));
5036 
5037 		return (err);
5038 	}
5039 
5040 	if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
5041 		if (pr_val == NULL) {
5042 			err = EINVAL;
5043 			return (err);
5044 		}
5045 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5046 
5047 		err = nxge_param_set_ip_opt(nxgep, NULL,
5048 		    NULL, (char *)pr_val,
5049 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
5050 
5051 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5052 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5053 		    pr_name, result));
5054 
5055 		return (err);
5056 	}
5057 	if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
5058 		if (pr_val == NULL) {
5059 			err = EINVAL;
5060 			return (err);
5061 		}
5062 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5063 
5064 		err = nxge_param_set_ip_opt(nxgep, NULL,
5065 		    NULL, (char *)pr_val,
5066 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
5067 
5068 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5069 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5070 		    pr_name, result));
5071 
5072 		return (err);
5073 	}
5074 	if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
5075 		if (pr_val == NULL) {
5076 			err = EINVAL;
5077 			return (err);
5078 		}
5079 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5080 
5081 		err = nxge_param_set_ip_opt(nxgep, NULL,
5082 		    NULL, (char *)pr_val,
5083 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
5084 
5085 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5086 		    "<== nxge_set_priv_prop: name %s (value 0x%x)",
5087 		    pr_name, result));
5088 
5089 		return (err);
5090 	}
5091 
5092 	if (strcmp(pr_name, "_soft_lso_enable") == 0) {
5093 		if (pr_val == NULL) {
5094 			NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5095 			    "==> nxge_set_priv_prop: name %s (null)", pr_name));
5096 			err = EINVAL;
5097 			return (err);
5098 		}
5099 
5100 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
5101 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5102 		    "<== nxge_set_priv_prop: name %s "
5103 		    "(lso %d pr_val %s value %d)",
5104 		    pr_name, nxgep->soft_lso_enable, pr_val, result));
5105 
5106 		if (result > 1 || result < 0) {
5107 			err = EINVAL;
5108 		} else {
5109 			if (nxgep->soft_lso_enable == (uint32_t)result) {
5110 				NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5111 				    "no change (%d %d)",
5112 				    nxgep->soft_lso_enable, result));
5113 				return (0);
5114 			}
5115 		}
5116 
5117 		nxgep->soft_lso_enable = (int)result;
5118 
5119 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5120 		    "<== nxge_set_priv_prop: name %s (value %d)",
5121 		    pr_name, result));
5122 
5123 		return (err);
5124 	}
5125 	/*
5126 	 * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the
5127 	 * following code to be executed.
5128 	 */
5129 	if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
5130 		err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val,
5131 		    (caddr_t)&param_arr[param_anar_10gfdx]);
5132 		return (err);
5133 	}
5134 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
5135 		err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val,
5136 		    (caddr_t)&param_arr[param_anar_pause]);
5137 		return (err);
5138 	}
5139 
5140 	return (ENOTSUP);
5141 }
5142 
5143 static int
5144 nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize,
5145     void *pr_val)
5146 {
5147 	p_nxge_param_t	param_arr = nxgep->param_arr;
5148 	char		valstr[MAXNAMELEN];
5149 	int		err = ENOTSUP;
5150 	uint_t		strsize;
5151 
5152 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5153 	    "==> nxge_get_priv_prop: property %s", pr_name));
5154 
5155 	/* function number */
5156 	if (strcmp(pr_name, "_function_number") == 0) {
5157 		(void) snprintf(valstr, sizeof (valstr), "%d",
5158 		    nxgep->function_num);
5159 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5160 		    "==> nxge_get_priv_prop: name %s "
5161 		    "(value %d valstr %s)",
5162 		    pr_name, nxgep->function_num, valstr));
5163 
5164 		err = 0;
5165 		goto done;
5166 	}
5167 
5168 	/* Neptune firmware version */
5169 	if (strcmp(pr_name, "_fw_version") == 0) {
5170 		(void) snprintf(valstr, sizeof (valstr), "%s",
5171 		    nxgep->vpd_info.ver);
5172 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5173 		    "==> nxge_get_priv_prop: name %s "
5174 		    "(value %d valstr %s)",
5175 		    pr_name, nxgep->vpd_info.ver, valstr));
5176 
5177 		err = 0;
5178 		goto done;
5179 	}
5180 
5181 	/* port PHY mode */
5182 	if (strcmp(pr_name, "_port_mode") == 0) {
5183 		switch (nxgep->mac.portmode) {
5184 		case PORT_1G_COPPER:
5185 			(void) snprintf(valstr, sizeof (valstr), "1G copper %s",
5186 			    nxgep->hot_swappable_phy ?
5187 			    "[Hot Swappable]" : "");
5188 			break;
5189 		case PORT_1G_FIBER:
5190 			(void) snprintf(valstr, sizeof (valstr), "1G fiber %s",
5191 			    nxgep->hot_swappable_phy ?
5192 			    "[hot swappable]" : "");
5193 			break;
5194 		case PORT_10G_COPPER:
5195 			(void) snprintf(valstr, sizeof (valstr),
5196 			    "10G copper %s",
5197 			    nxgep->hot_swappable_phy ?
5198 			    "[hot swappable]" : "");
5199 			break;
5200 		case PORT_10G_FIBER:
5201 			(void) snprintf(valstr, sizeof (valstr), "10G fiber %s",
5202 			    nxgep->hot_swappable_phy ?
5203 			    "[hot swappable]" : "");
5204 			break;
5205 		case PORT_10G_SERDES:
5206 			(void) snprintf(valstr, sizeof (valstr),
5207 			    "10G serdes %s", nxgep->hot_swappable_phy ?
5208 			    "[hot swappable]" : "");
5209 			break;
5210 		case PORT_1G_SERDES:
5211 			(void) snprintf(valstr, sizeof (valstr), "1G serdes %s",
5212 			    nxgep->hot_swappable_phy ?
5213 			    "[hot swappable]" : "");
5214 			break;
5215 		case PORT_1G_TN1010:
5216 			(void) snprintf(valstr, sizeof (valstr),
5217 			    "1G TN1010 copper %s", nxgep->hot_swappable_phy ?
5218 			    "[hot swappable]" : "");
5219 			break;
5220 		case PORT_10G_TN1010:
5221 			(void) snprintf(valstr, sizeof (valstr),
5222 			    "10G TN1010 copper %s", nxgep->hot_swappable_phy ?
5223 			    "[hot swappable]" : "");
5224 			break;
5225 		case PORT_1G_RGMII_FIBER:
5226 			(void) snprintf(valstr, sizeof (valstr),
5227 			    "1G rgmii fiber %s", nxgep->hot_swappable_phy ?
5228 			    "[hot swappable]" : "");
5229 			break;
5230 		case PORT_HSP_MODE:
5231 			(void) snprintf(valstr, sizeof (valstr),
5232 			    "phy not present[hot swappable]");
5233 			break;
5234 		default:
5235 			(void) snprintf(valstr, sizeof (valstr), "unknown %s",
5236 			    nxgep->hot_swappable_phy ?
5237 			    "[hot swappable]" : "");
5238 			break;
5239 		}
5240 
5241 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5242 		    "==> nxge_get_priv_prop: name %s (value %s)",
5243 		    pr_name, valstr));
5244 
5245 		err = 0;
5246 		goto done;
5247 	}
5248 
5249 	/* Hot swappable PHY */
5250 	if (strcmp(pr_name, "_hot_swap_phy") == 0) {
5251 		(void) snprintf(valstr, sizeof (valstr), "%s",
5252 		    nxgep->hot_swappable_phy ?
5253 		    "yes" : "no");
5254 
5255 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5256 		    "==> nxge_get_priv_prop: name %s "
5257 		    "(value %d valstr %s)",
5258 		    pr_name, nxgep->hot_swappable_phy, valstr));
5259 
5260 		err = 0;
5261 		goto done;
5262 	}
5263 
5264 
5265 	/* Receive Interrupt Blanking Parameters */
5266 	if (strcmp(pr_name, "_rxdma_intr_time") == 0) {
5267 		err = 0;
5268 		(void) snprintf(valstr, sizeof (valstr), "%d",
5269 		    nxgep->intr_timeout);
5270 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5271 		    "==> nxge_get_priv_prop: name %s (value %d)",
5272 		    pr_name,
5273 		    (uint32_t)nxgep->intr_timeout));
5274 		goto done;
5275 	}
5276 
5277 	if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) {
5278 		err = 0;
5279 		(void) snprintf(valstr, sizeof (valstr), "%d",
5280 		    nxgep->intr_threshold);
5281 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5282 		    "==> nxge_get_priv_prop: name %s (value %d)",
5283 		    pr_name, (uint32_t)nxgep->intr_threshold));
5284 
5285 		goto done;
5286 	}
5287 
5288 	/* Classification and Load Distribution Configuration */
5289 	if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) {
5290 		err = nxge_dld_get_ip_opt(nxgep,
5291 		    (caddr_t)&param_arr[param_class_opt_ipv4_tcp]);
5292 
5293 		(void) snprintf(valstr, sizeof (valstr), "%x",
5294 		    (int)param_arr[param_class_opt_ipv4_tcp].value);
5295 
5296 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5297 		    "==> nxge_get_priv_prop: %s", valstr));
5298 		goto done;
5299 	}
5300 
5301 	if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) {
5302 		err = nxge_dld_get_ip_opt(nxgep,
5303 		    (caddr_t)&param_arr[param_class_opt_ipv4_udp]);
5304 
5305 		(void) snprintf(valstr, sizeof (valstr), "%x",
5306 		    (int)param_arr[param_class_opt_ipv4_udp].value);
5307 
5308 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5309 		    "==> nxge_get_priv_prop: %s", valstr));
5310 		goto done;
5311 	}
5312 	if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) {
5313 		err = nxge_dld_get_ip_opt(nxgep,
5314 		    (caddr_t)&param_arr[param_class_opt_ipv4_ah]);
5315 
5316 		(void) snprintf(valstr, sizeof (valstr), "%x",
5317 		    (int)param_arr[param_class_opt_ipv4_ah].value);
5318 
5319 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5320 		    "==> nxge_get_priv_prop: %s", valstr));
5321 		goto done;
5322 	}
5323 
5324 	if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) {
5325 		err = nxge_dld_get_ip_opt(nxgep,
5326 		    (caddr_t)&param_arr[param_class_opt_ipv4_sctp]);
5327 
5328 		(void) snprintf(valstr, sizeof (valstr), "%x",
5329 		    (int)param_arr[param_class_opt_ipv4_sctp].value);
5330 
5331 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5332 		    "==> nxge_get_priv_prop: %s", valstr));
5333 		goto done;
5334 	}
5335 
5336 	if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) {
5337 		err = nxge_dld_get_ip_opt(nxgep,
5338 		    (caddr_t)&param_arr[param_class_opt_ipv6_tcp]);
5339 
5340 		(void) snprintf(valstr, sizeof (valstr), "%x",
5341 		    (int)param_arr[param_class_opt_ipv6_tcp].value);
5342 
5343 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5344 		    "==> nxge_get_priv_prop: %s", valstr));
5345 		goto done;
5346 	}
5347 
5348 	if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) {
5349 		err = nxge_dld_get_ip_opt(nxgep,
5350 		    (caddr_t)&param_arr[param_class_opt_ipv6_udp]);
5351 
5352 		(void) snprintf(valstr, sizeof (valstr), "%x",
5353 		    (int)param_arr[param_class_opt_ipv6_udp].value);
5354 
5355 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5356 		    "==> nxge_get_priv_prop: %s", valstr));
5357 		goto done;
5358 	}
5359 
5360 	if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) {
5361 		err = nxge_dld_get_ip_opt(nxgep,
5362 		    (caddr_t)&param_arr[param_class_opt_ipv6_ah]);
5363 
5364 		(void) snprintf(valstr, sizeof (valstr), "%x",
5365 		    (int)param_arr[param_class_opt_ipv6_ah].value);
5366 
5367 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5368 		    "==> nxge_get_priv_prop: %s", valstr));
5369 		goto done;
5370 	}
5371 
5372 	if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) {
5373 		err = nxge_dld_get_ip_opt(nxgep,
5374 		    (caddr_t)&param_arr[param_class_opt_ipv6_sctp]);
5375 
5376 		(void) snprintf(valstr, sizeof (valstr), "%x",
5377 		    (int)param_arr[param_class_opt_ipv6_sctp].value);
5378 
5379 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5380 		    "==> nxge_get_priv_prop: %s", valstr));
5381 		goto done;
5382 	}
5383 
5384 	/* Software LSO */
5385 	if (strcmp(pr_name, "_soft_lso_enable") == 0) {
5386 		(void) snprintf(valstr, sizeof (valstr),
5387 		    "%d", nxgep->soft_lso_enable);
5388 		err = 0;
5389 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5390 		    "==> nxge_get_priv_prop: name %s (value %d)",
5391 		    pr_name, nxgep->soft_lso_enable));
5392 
5393 		goto done;
5394 	}
5395 	if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) {
5396 		err = 0;
5397 		if (nxgep->param_arr[param_anar_10gfdx].value != 0) {
5398 			(void) snprintf(valstr, sizeof (valstr), "%d", 1);
5399 			goto done;
5400 		} else {
5401 			(void) snprintf(valstr, sizeof (valstr), "%d", 0);
5402 			goto done;
5403 		}
5404 	}
5405 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
5406 		err = 0;
5407 		if (nxgep->param_arr[param_anar_pause].value != 0) {
5408 			(void) snprintf(valstr, sizeof (valstr), "%d", 1);
5409 			goto done;
5410 		} else {
5411 			(void) snprintf(valstr, sizeof (valstr), "%d", 0);
5412 			goto done;
5413 		}
5414 	}
5415 
5416 done:
5417 	if (err == 0) {
5418 		strsize = (uint_t)strlen(valstr);
5419 		if (pr_valsize < strsize) {
5420 			err = ENOBUFS;
5421 		} else {
5422 			(void) strlcpy(pr_val, valstr, pr_valsize);
5423 		}
5424 	}
5425 
5426 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
5427 	    "<== nxge_get_priv_prop: return %d", err));
5428 	return (err);
5429 }
5430 
5431 /*
5432  * Module loading and removing entry points.
5433  */
5434 
5435 DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach,
5436     nodev, NULL, D_MP, NULL, nxge_quiesce);
5437 
5438 #define	NXGE_DESC_VER		"Sun NIU 10Gb Ethernet"
5439 
5440 /*
5441  * Module linkage information for the kernel.
5442  */
5443 static struct modldrv 	nxge_modldrv = {
5444 	&mod_driverops,
5445 	NXGE_DESC_VER,
5446 	&nxge_dev_ops
5447 };
5448 
5449 static struct modlinkage modlinkage = {
5450 	MODREV_1, (void *) &nxge_modldrv, NULL
5451 };
5452 
5453 int
5454 _init(void)
5455 {
5456 	int		status;
5457 
5458 	MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL);
5459 
5460 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
5461 
5462 	mac_init_ops(&nxge_dev_ops, "nxge");
5463 
5464 	status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0);
5465 	if (status != 0) {
5466 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
5467 		    "failed to init device soft state"));
5468 		goto _init_exit;
5469 	}
5470 
5471 	status = mod_install(&modlinkage);
5472 	if (status != 0) {
5473 		ddi_soft_state_fini(&nxge_list);
5474 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed"));
5475 		goto _init_exit;
5476 	}
5477 
5478 	MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL);
5479 
5480 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status));
5481 	return (status);
5482 
5483 _init_exit:
5484 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status));
5485 	MUTEX_DESTROY(&nxgedebuglock);
5486 	return (status);
5487 }
5488 
5489 int
5490 _fini(void)
5491 {
5492 	int		status;
5493 
5494 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
5495 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
5496 
5497 	if (nxge_mblks_pending)
5498 		return (EBUSY);
5499 
5500 	status = mod_remove(&modlinkage);
5501 	if (status != DDI_SUCCESS) {
5502 		NXGE_DEBUG_MSG((NULL, MOD_CTL,
5503 		    "Module removal failed 0x%08x",
5504 		    status));
5505 		goto _fini_exit;
5506 	}
5507 
5508 	mac_fini_ops(&nxge_dev_ops);
5509 
5510 	ddi_soft_state_fini(&nxge_list);
5511 
5512 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status));
5513 
5514 	MUTEX_DESTROY(&nxge_common_lock);
5515 	MUTEX_DESTROY(&nxgedebuglock);
5516 	return (status);
5517 
5518 _fini_exit:
5519 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status));
5520 	return (status);
5521 }
5522 
5523 int
5524 _info(struct modinfo *modinfop)
5525 {
5526 	int		status;
5527 
5528 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
5529 	status = mod_info(&modlinkage, modinfop);
5530 	NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
5531 
5532 	return (status);
5533 }
5534 
5535 /*ARGSUSED*/
5536 static int
5537 nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
5538 {
5539 	p_nxge_ring_handle_t	rhp = (p_nxge_ring_handle_t)rdriver;
5540 	p_nxge_t		nxgep = rhp->nxgep;
5541 	uint32_t		channel;
5542 	p_tx_ring_t		ring;
5543 
5544 	channel = nxgep->pt_config.hw_config.tdc.start + rhp->index;
5545 	ring = nxgep->tx_rings->rings[channel];
5546 
5547 	MUTEX_ENTER(&ring->lock);
5548 	ASSERT(ring->tx_ring_handle == NULL);
5549 	ring->tx_ring_handle = rhp->ring_handle;
5550 	MUTEX_EXIT(&ring->lock);
5551 
5552 	return (0);
5553 }
5554 
5555 static void
5556 nxge_tx_ring_stop(mac_ring_driver_t rdriver)
5557 {
5558 	p_nxge_ring_handle_t	rhp = (p_nxge_ring_handle_t)rdriver;
5559 	p_nxge_t		nxgep = rhp->nxgep;
5560 	uint32_t		channel;
5561 	p_tx_ring_t		ring;
5562 
5563 	channel = nxgep->pt_config.hw_config.tdc.start + rhp->index;
5564 	ring = nxgep->tx_rings->rings[channel];
5565 
5566 	MUTEX_ENTER(&ring->lock);
5567 	ASSERT(ring->tx_ring_handle != NULL);
5568 	ring->tx_ring_handle = (mac_ring_handle_t)NULL;
5569 	MUTEX_EXIT(&ring->lock);
5570 }
5571 
5572 int
5573 nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num)
5574 {
5575 	p_nxge_ring_handle_t	rhp = (p_nxge_ring_handle_t)rdriver;
5576 	p_nxge_t		nxgep = rhp->nxgep;
5577 	uint32_t		channel;
5578 	p_rx_rcr_ring_t		ring;
5579 	int			i;
5580 
5581 	channel = nxgep->pt_config.hw_config.start_rdc + rhp->index;
5582 	ring =  nxgep->rx_rcr_rings->rcr_rings[channel];
5583 
5584 	MUTEX_ENTER(&ring->lock);
5585 
5586 	if (ring->started) {
5587 		ASSERT(ring->started == B_FALSE);
5588 		MUTEX_EXIT(&ring->lock);
5589 		return (0);
5590 	}
5591 
5592 	/* set rcr_ring */
5593 	for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5594 		if ((nxgep->ldgvp->ldvp[i].is_rxdma) &&
5595 		    (nxgep->ldgvp->ldvp[i].channel == channel)) {
5596 			ring->ldvp = &nxgep->ldgvp->ldvp[i];
5597 			ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp;
5598 		}
5599 	}
5600 
5601 	ring->rcr_mac_handle = rhp->ring_handle;
5602 	ring->rcr_gen_num = mr_gen_num;
5603 	ring->started = B_TRUE;
5604 	rhp->ring_gen_num = mr_gen_num;
5605 	MUTEX_EXIT(&ring->lock);
5606 
5607 	return (0);
5608 }
5609 
5610 static void
5611 nxge_rx_ring_stop(mac_ring_driver_t rdriver)
5612 {
5613 	p_nxge_ring_handle_t	rhp = (p_nxge_ring_handle_t)rdriver;
5614 	p_nxge_t		nxgep = rhp->nxgep;
5615 	uint32_t		channel;
5616 	p_rx_rcr_ring_t		ring;
5617 
5618 	channel = nxgep->pt_config.hw_config.start_rdc + rhp->index;
5619 	ring =  nxgep->rx_rcr_rings->rcr_rings[channel];
5620 
5621 	MUTEX_ENTER(&ring->lock);
5622 	ASSERT(ring->started == B_TRUE);
5623 	ring->rcr_mac_handle = NULL;
5624 	ring->ldvp = NULL;
5625 	ring->ldgp = NULL;
5626 	ring->started = B_FALSE;
5627 	MUTEX_EXIT(&ring->lock);
5628 }
5629 
5630 static int
5631 nxge_ring_get_htable_idx(p_nxge_t nxgep, mac_ring_type_t type, uint32_t channel)
5632 {
5633 	int	i;
5634 
5635 #if defined(sun4v)
5636 	if (isLDOMguest(nxgep)) {
5637 		return (nxge_hio_get_dc_htable_idx(nxgep,
5638 		    (type == MAC_RING_TYPE_TX) ? VP_BOUND_TX : VP_BOUND_RX,
5639 		    channel));
5640 	}
5641 #endif
5642 
5643 	ASSERT(nxgep->ldgvp != NULL);
5644 
5645 	switch (type) {
5646 	case MAC_RING_TYPE_TX:
5647 		for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5648 			if ((nxgep->ldgvp->ldvp[i].is_txdma) &&
5649 			    (nxgep->ldgvp->ldvp[i].channel == channel)) {
5650 				return ((int)
5651 				    nxgep->ldgvp->ldvp[i].ldgp->htable_idx);
5652 			}
5653 		}
5654 		break;
5655 
5656 	case MAC_RING_TYPE_RX:
5657 		for (i = 0; i < nxgep->ldgvp->maxldvs; i++) {
5658 			if ((nxgep->ldgvp->ldvp[i].is_rxdma) &&
5659 			    (nxgep->ldgvp->ldvp[i].channel == channel)) {
5660 				return ((int)
5661 				    nxgep->ldgvp->ldvp[i].ldgp->htable_idx);
5662 			}
5663 		}
5664 	}
5665 
5666 	return (-1);
5667 }
5668 
5669 /*
5670  * Callback funtion for MAC layer to register all rings.
5671  */
5672 static void
5673 nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
5674     const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
5675 {
5676 	p_nxge_t		nxgep = (p_nxge_t)arg;
5677 	p_nxge_hw_pt_cfg_t	p_cfgp = &nxgep->pt_config.hw_config;
5678 	p_nxge_intr_t		intrp;
5679 	uint32_t		channel;
5680 	int			htable_idx;
5681 	p_nxge_ring_handle_t	rhandlep;
5682 
5683 	ASSERT(nxgep != NULL);
5684 	ASSERT(p_cfgp != NULL);
5685 	ASSERT(infop != NULL);
5686 
5687 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
5688 	    "==> nxge_fill_ring 0x%x index %d", rtype, index));
5689 
5690 
5691 	switch (rtype) {
5692 	case MAC_RING_TYPE_TX: {
5693 		mac_intr_t	*mintr = &infop->mri_intr;
5694 
5695 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
5696 		    "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d",
5697 		    rtype, index, p_cfgp->tdc.count));
5698 
5699 		ASSERT((index >= 0) && (index < p_cfgp->tdc.count));
5700 		rhandlep = &nxgep->tx_ring_handles[index];
5701 		rhandlep->nxgep = nxgep;
5702 		rhandlep->index = index;
5703 		rhandlep->ring_handle = rh;
5704 
5705 		channel = nxgep->pt_config.hw_config.tdc.start + index;
5706 		rhandlep->channel = channel;
5707 		intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5708 		htable_idx = nxge_ring_get_htable_idx(nxgep, rtype,
5709 		    channel);
5710 		if (htable_idx >= 0)
5711 			mintr->mi_ddi_handle = intrp->htable[htable_idx];
5712 		else
5713 			mintr->mi_ddi_handle = NULL;
5714 
5715 		infop->mri_driver = (mac_ring_driver_t)rhandlep;
5716 		infop->mri_start = nxge_tx_ring_start;
5717 		infop->mri_stop = nxge_tx_ring_stop;
5718 		infop->mri_tx = nxge_tx_ring_send;
5719 		infop->mri_stat = nxge_tx_ring_stat;
5720 		infop->mri_flags = MAC_RING_TX_SERIALIZE;
5721 		break;
5722 	}
5723 
5724 	case MAC_RING_TYPE_RX: {
5725 		mac_intr_t		nxge_mac_intr;
5726 		int			nxge_rindex;
5727 		p_nxge_intr_t		intrp;
5728 
5729 		intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5730 
5731 		NXGE_DEBUG_MSG((nxgep, RX_CTL,
5732 		    "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d",
5733 		    rtype, index, p_cfgp->max_rdcs));
5734 
5735 		/*
5736 		 * 'index' is the ring index within the group.
5737 		 * Find the ring index in the nxge instance.
5738 		 */
5739 		nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index);
5740 		channel = nxgep->pt_config.hw_config.start_rdc + index;
5741 		intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
5742 
5743 		ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs));
5744 		rhandlep = &nxgep->rx_ring_handles[nxge_rindex];
5745 		rhandlep->nxgep = nxgep;
5746 		rhandlep->index = nxge_rindex;
5747 		rhandlep->ring_handle = rh;
5748 		rhandlep->channel = channel;
5749 
5750 		/*
5751 		 * Entrypoint to enable interrupt (disable poll) and
5752 		 * disable interrupt (enable poll).
5753 		 */
5754 		bzero(&nxge_mac_intr, sizeof (nxge_mac_intr));
5755 		nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep;
5756 		nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll;
5757 		nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll;
5758 
5759 		htable_idx =  nxge_ring_get_htable_idx(nxgep, rtype,
5760 		    channel);
5761 		if (htable_idx >= 0)
5762 			nxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx];
5763 		else
5764 			nxge_mac_intr.mi_ddi_handle = NULL;
5765 
5766 		infop->mri_driver = (mac_ring_driver_t)rhandlep;
5767 		infop->mri_start = nxge_rx_ring_start;
5768 		infop->mri_stop = nxge_rx_ring_stop;
5769 		infop->mri_intr = nxge_mac_intr;
5770 		infop->mri_poll = nxge_rx_poll;
5771 		infop->mri_stat = nxge_rx_ring_stat;
5772 		infop->mri_flags = MAC_RING_RX_ENQUEUE;
5773 		break;
5774 	}
5775 
5776 	default:
5777 		break;
5778 	}
5779 
5780 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", rtype));
5781 }
5782 
5783 static void
5784 nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh,
5785     mac_ring_type_t type)
5786 {
5787 	nxge_ring_group_t	*rgroup = (nxge_ring_group_t *)gh;
5788 	nxge_ring_handle_t	*rhandle = (nxge_ring_handle_t *)rh;
5789 	nxge_t			*nxge;
5790 	nxge_grp_t		*grp;
5791 	nxge_rdc_grp_t		*rdc_grp;
5792 	uint16_t		channel;	/* device-wise ring id */
5793 	int			dev_gindex;
5794 	int			rv;
5795 
5796 	nxge = rgroup->nxgep;
5797 
5798 	switch (type) {
5799 	case MAC_RING_TYPE_TX:
5800 		/*
5801 		 * nxge_grp_dc_add takes a channel number which is a
5802 		 * "devise" ring ID.
5803 		 */
5804 		channel = nxge->pt_config.hw_config.tdc.start + rhandle->index;
5805 
5806 		/*
5807 		 * Remove the ring from the default group
5808 		 */
5809 		if (rgroup->gindex != 0) {
5810 			(void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel);
5811 		}
5812 
5813 		/*
5814 		 * nxge->tx_set.group[] is an array of groups indexed by
5815 		 * a "port" group ID.
5816 		 */
5817 		grp = nxge->tx_set.group[rgroup->gindex];
5818 		rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel);
5819 		if (rv != 0) {
5820 			NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5821 			    "nxge_group_add_ring: nxge_grp_dc_add failed"));
5822 		}
5823 		break;
5824 
5825 	case MAC_RING_TYPE_RX:
5826 		/*
5827 		 * nxge->rx_set.group[] is an array of groups indexed by
5828 		 * a "port" group ID.
5829 		 */
5830 		grp = nxge->rx_set.group[rgroup->gindex];
5831 
5832 		dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid +
5833 		    rgroup->gindex;
5834 		rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex];
5835 
5836 		/*
5837 		 * nxge_grp_dc_add takes a channel number which is a
5838 		 * "devise" ring ID.
5839 		 */
5840 		channel = nxge->pt_config.hw_config.start_rdc + rhandle->index;
5841 		rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel);
5842 		if (rv != 0) {
5843 			NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5844 			    "nxge_group_add_ring: nxge_grp_dc_add failed"));
5845 		}
5846 
5847 		rdc_grp->map |= (1 << channel);
5848 		rdc_grp->max_rdcs++;
5849 
5850 		(void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl);
5851 		break;
5852 	}
5853 }
5854 
5855 static void
5856 nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh,
5857     mac_ring_type_t type)
5858 {
5859 	nxge_ring_group_t	*rgroup = (nxge_ring_group_t *)gh;
5860 	nxge_ring_handle_t	*rhandle = (nxge_ring_handle_t *)rh;
5861 	nxge_t			*nxge;
5862 	uint16_t		channel;	/* device-wise ring id */
5863 	nxge_rdc_grp_t		*rdc_grp;
5864 	int			dev_gindex;
5865 
5866 	nxge = rgroup->nxgep;
5867 
5868 	switch (type) {
5869 	case MAC_RING_TYPE_TX:
5870 		dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid +
5871 		    rgroup->gindex;
5872 		channel = nxge->pt_config.hw_config.tdc.start + rhandle->index;
5873 		nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel);
5874 
5875 		/*
5876 		 * Add the ring back to the default group
5877 		 */
5878 		if (rgroup->gindex != 0) {
5879 			nxge_grp_t *grp;
5880 			grp = nxge->tx_set.group[0];
5881 			(void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel);
5882 		}
5883 		break;
5884 
5885 	case MAC_RING_TYPE_RX:
5886 		dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid +
5887 		    rgroup->gindex;
5888 		rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex];
5889 		channel = rdc_grp->start_rdc + rhandle->index;
5890 		nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel);
5891 
5892 		rdc_grp->map &= ~(1 << channel);
5893 		rdc_grp->max_rdcs--;
5894 
5895 		(void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl);
5896 		break;
5897 	}
5898 }
5899 
5900 
5901 /*ARGSUSED*/
5902 static nxge_status_t
5903 nxge_add_intrs(p_nxge_t nxgep)
5904 {
5905 
5906 	int		intr_types;
5907 	int		type = 0;
5908 	int		ddi_status = DDI_SUCCESS;
5909 	nxge_status_t	status = NXGE_OK;
5910 
5911 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs"));
5912 
5913 	nxgep->nxge_intr_type.intr_registered = B_FALSE;
5914 	nxgep->nxge_intr_type.intr_enabled = B_FALSE;
5915 	nxgep->nxge_intr_type.msi_intx_cnt = 0;
5916 	nxgep->nxge_intr_type.intr_added = 0;
5917 	nxgep->nxge_intr_type.niu_msi_enable = B_FALSE;
5918 	nxgep->nxge_intr_type.intr_type = 0;
5919 
5920 	if (nxgep->niu_type == N2_NIU) {
5921 		nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
5922 	} else if (nxge_msi_enable) {
5923 		nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
5924 	}
5925 
5926 	/* Get the supported interrupt types */
5927 	if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types))
5928 	    != DDI_SUCCESS) {
5929 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: "
5930 		    "ddi_intr_get_supported_types failed: status 0x%08x",
5931 		    ddi_status));
5932 		return (NXGE_ERROR | NXGE_DDI_FAILED);
5933 	}
5934 	nxgep->nxge_intr_type.intr_types = intr_types;
5935 
5936 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5937 	    "ddi_intr_get_supported_types: 0x%08x", intr_types));
5938 
5939 	/*
5940 	 * Solaris MSIX is not supported yet. use MSI for now.
5941 	 * nxge_msi_enable (1):
5942 	 *	1 - MSI		2 - MSI-X	others - FIXED
5943 	 */
5944 	switch (nxge_msi_enable) {
5945 	default:
5946 		type = DDI_INTR_TYPE_FIXED;
5947 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5948 		    "use fixed (intx emulation) type %08x",
5949 		    type));
5950 		break;
5951 
5952 	case 2:
5953 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5954 		    "ddi_intr_get_supported_types: 0x%08x", intr_types));
5955 		if (intr_types & DDI_INTR_TYPE_MSIX) {
5956 			type = DDI_INTR_TYPE_MSIX;
5957 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5958 			    "ddi_intr_get_supported_types: MSIX 0x%08x",
5959 			    type));
5960 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
5961 			type = DDI_INTR_TYPE_MSI;
5962 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5963 			    "ddi_intr_get_supported_types: MSI 0x%08x",
5964 			    type));
5965 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
5966 			type = DDI_INTR_TYPE_FIXED;
5967 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5968 			    "ddi_intr_get_supported_types: MSXED0x%08x",
5969 			    type));
5970 		}
5971 		break;
5972 
5973 	case 1:
5974 		if (intr_types & DDI_INTR_TYPE_MSI) {
5975 			type = DDI_INTR_TYPE_MSI;
5976 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
5977 			    "ddi_intr_get_supported_types: MSI 0x%08x",
5978 			    type));
5979 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
5980 			type = DDI_INTR_TYPE_MSIX;
5981 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5982 			    "ddi_intr_get_supported_types: MSIX 0x%08x",
5983 			    type));
5984 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
5985 			type = DDI_INTR_TYPE_FIXED;
5986 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
5987 			    "ddi_intr_get_supported_types: MSXED0x%08x",
5988 			    type));
5989 		}
5990 	}
5991 
5992 	nxgep->nxge_intr_type.intr_type = type;
5993 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
5994 	    type == DDI_INTR_TYPE_FIXED) &&
5995 	    nxgep->nxge_intr_type.niu_msi_enable) {
5996 		if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) {
5997 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5998 			    " nxge_add_intrs: "
5999 			    " nxge_add_intrs_adv failed: status 0x%08x",
6000 			    status));
6001 			return (status);
6002 		} else {
6003 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
6004 			    "interrupts registered : type %d", type));
6005 			nxgep->nxge_intr_type.intr_registered = B_TRUE;
6006 
6007 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6008 			    "\nAdded advanced nxge add_intr_adv "
6009 			    "intr type 0x%x\n", type));
6010 
6011 			return (status);
6012 		}
6013 	}
6014 
6015 	if (!nxgep->nxge_intr_type.intr_registered) {
6016 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: "
6017 		    "failed to register interrupts"));
6018 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6019 	}
6020 
6021 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs"));
6022 	return (status);
6023 }
6024 
6025 static nxge_status_t
6026 nxge_add_intrs_adv(p_nxge_t nxgep)
6027 {
6028 	int		intr_type;
6029 	p_nxge_intr_t	intrp;
6030 
6031 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv"));
6032 
6033 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6034 	intr_type = intrp->intr_type;
6035 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x",
6036 	    intr_type));
6037 
6038 	switch (intr_type) {
6039 	case DDI_INTR_TYPE_MSI: /* 0x2 */
6040 	case DDI_INTR_TYPE_MSIX: /* 0x4 */
6041 		return (nxge_add_intrs_adv_type(nxgep, intr_type));
6042 
6043 	case DDI_INTR_TYPE_FIXED: /* 0x1 */
6044 		return (nxge_add_intrs_adv_type_fix(nxgep, intr_type));
6045 
6046 	default:
6047 		return (NXGE_ERROR);
6048 	}
6049 }
6050 
6051 
6052 /*ARGSUSED*/
6053 static nxge_status_t
6054 nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type)
6055 {
6056 	dev_info_t		*dip = nxgep->dip;
6057 	p_nxge_ldg_t		ldgp;
6058 	p_nxge_intr_t		intrp;
6059 	uint_t			*inthandler;
6060 	void			*arg1, *arg2;
6061 	int			behavior;
6062 	int			nintrs, navail, nrequest;
6063 	int			nactual, nrequired;
6064 	int			inum = 0;
6065 	int			x, y;
6066 	int			ddi_status = DDI_SUCCESS;
6067 	nxge_status_t		status = NXGE_OK;
6068 
6069 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type"));
6070 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6071 	intrp->start_inum = 0;
6072 
6073 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
6074 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
6075 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6076 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
6077 		    "nintrs: %d", ddi_status, nintrs));
6078 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6079 	}
6080 
6081 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
6082 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
6083 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6084 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
6085 		    "nintrs: %d", ddi_status, navail));
6086 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6087 	}
6088 
6089 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
6090 	    "ddi_intr_get_navail() returned: nintrs %d, navail %d",
6091 	    nintrs, navail));
6092 
6093 	/* PSARC/2007/453 MSI-X interrupt limit override */
6094 	if (int_type == DDI_INTR_TYPE_MSIX) {
6095 		nrequest = nxge_create_msi_property(nxgep);
6096 		if (nrequest < navail) {
6097 			navail = nrequest;
6098 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
6099 			    "nxge_add_intrs_adv_type: nintrs %d "
6100 			    "navail %d (nrequest %d)",
6101 			    nintrs, navail, nrequest));
6102 		}
6103 	}
6104 
6105 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
6106 		/* MSI must be power of 2 */
6107 		if ((navail & 16) == 16) {
6108 			navail = 16;
6109 		} else if ((navail & 8) == 8) {
6110 			navail = 8;
6111 		} else if ((navail & 4) == 4) {
6112 			navail = 4;
6113 		} else if ((navail & 2) == 2) {
6114 			navail = 2;
6115 		} else {
6116 			navail = 1;
6117 		}
6118 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
6119 		    "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
6120 		    "navail %d", nintrs, navail));
6121 	}
6122 
6123 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
6124 	    DDI_INTR_ALLOC_NORMAL);
6125 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
6126 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
6127 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
6128 	    navail, &nactual, behavior);
6129 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
6130 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6131 		    " ddi_intr_alloc() failed: %d",
6132 		    ddi_status));
6133 		kmem_free(intrp->htable, intrp->intr_size);
6134 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6135 	}
6136 
6137 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
6138 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
6139 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6140 		    " ddi_intr_get_pri() failed: %d",
6141 		    ddi_status));
6142 		/* Free already allocated interrupts */
6143 		for (y = 0; y < nactual; y++) {
6144 			(void) ddi_intr_free(intrp->htable[y]);
6145 		}
6146 
6147 		kmem_free(intrp->htable, intrp->intr_size);
6148 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6149 	}
6150 
6151 	nrequired = 0;
6152 	switch (nxgep->niu_type) {
6153 	default:
6154 		status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
6155 		break;
6156 
6157 	case N2_NIU:
6158 		status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
6159 		break;
6160 	}
6161 
6162 	if (status != NXGE_OK) {
6163 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6164 		    "nxge_add_intrs_adv_typ:nxge_ldgv_init "
6165 		    "failed: 0x%x", status));
6166 		/* Free already allocated interrupts */
6167 		for (y = 0; y < nactual; y++) {
6168 			(void) ddi_intr_free(intrp->htable[y]);
6169 		}
6170 
6171 		kmem_free(intrp->htable, intrp->intr_size);
6172 		return (status);
6173 	}
6174 
6175 	ldgp = nxgep->ldgvp->ldgp;
6176 	for (x = 0; x < nrequired; x++, ldgp++) {
6177 		ldgp->vector = (uint8_t)x;
6178 		ldgp->intdata = SID_DATA(ldgp->func, x);
6179 		arg1 = ldgp->ldvp;
6180 		arg2 = nxgep;
6181 		if (ldgp->nldvs == 1) {
6182 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
6183 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
6184 			    "nxge_add_intrs_adv_type: "
6185 			    "arg1 0x%x arg2 0x%x: "
6186 			    "1-1 int handler (entry %d intdata 0x%x)\n",
6187 			    arg1, arg2,
6188 			    x, ldgp->intdata));
6189 		} else if (ldgp->nldvs > 1) {
6190 			inthandler = (uint_t *)ldgp->sys_intr_handler;
6191 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
6192 			    "nxge_add_intrs_adv_type: "
6193 			    "arg1 0x%x arg2 0x%x: "
6194 			    "nldevs %d int handler "
6195 			    "(entry %d intdata 0x%x)\n",
6196 			    arg1, arg2,
6197 			    ldgp->nldvs, x, ldgp->intdata));
6198 		}
6199 
6200 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
6201 		    "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
6202 		    "htable 0x%llx", x, intrp->htable[x]));
6203 
6204 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
6205 		    (ddi_intr_handler_t *)inthandler, arg1, arg2))
6206 		    != DDI_SUCCESS) {
6207 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6208 			    "==> nxge_add_intrs_adv_type: failed #%d "
6209 			    "status 0x%x", x, ddi_status));
6210 			for (y = 0; y < intrp->intr_added; y++) {
6211 				(void) ddi_intr_remove_handler(
6212 				    intrp->htable[y]);
6213 			}
6214 			/* Free already allocated intr */
6215 			for (y = 0; y < nactual; y++) {
6216 				(void) ddi_intr_free(intrp->htable[y]);
6217 			}
6218 			kmem_free(intrp->htable, intrp->intr_size);
6219 
6220 			(void) nxge_ldgv_uninit(nxgep);
6221 
6222 			return (NXGE_ERROR | NXGE_DDI_FAILED);
6223 		}
6224 
6225 		ldgp->htable_idx = x;
6226 		intrp->intr_added++;
6227 	}
6228 
6229 	intrp->msi_intx_cnt = nactual;
6230 
6231 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6232 	    "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
6233 	    navail, nactual,
6234 	    intrp->msi_intx_cnt,
6235 	    intrp->intr_added));
6236 
6237 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
6238 
6239 	(void) nxge_intr_ldgv_init(nxgep);
6240 
6241 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type"));
6242 
6243 	return (status);
6244 }
6245 
6246 /*ARGSUSED*/
6247 static nxge_status_t
6248 nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type)
6249 {
6250 	dev_info_t		*dip = nxgep->dip;
6251 	p_nxge_ldg_t		ldgp;
6252 	p_nxge_intr_t		intrp;
6253 	uint_t			*inthandler;
6254 	void			*arg1, *arg2;
6255 	int			behavior;
6256 	int			nintrs, navail;
6257 	int			nactual, nrequired;
6258 	int			inum = 0;
6259 	int			x, y;
6260 	int			ddi_status = DDI_SUCCESS;
6261 	nxge_status_t		status = NXGE_OK;
6262 
6263 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix"));
6264 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6265 	intrp->start_inum = 0;
6266 
6267 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
6268 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
6269 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
6270 		    "ddi_intr_get_nintrs() failed, status: 0x%x%, "
6271 		    "nintrs: %d", status, nintrs));
6272 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6273 	}
6274 
6275 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
6276 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
6277 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6278 		    "ddi_intr_get_navail() failed, status: 0x%x%, "
6279 		    "nintrs: %d", ddi_status, navail));
6280 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6281 	}
6282 
6283 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
6284 	    "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
6285 	    nintrs, navail));
6286 
6287 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
6288 	    DDI_INTR_ALLOC_NORMAL);
6289 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
6290 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
6291 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
6292 	    navail, &nactual, behavior);
6293 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
6294 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6295 		    " ddi_intr_alloc() failed: %d",
6296 		    ddi_status));
6297 		kmem_free(intrp->htable, intrp->intr_size);
6298 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6299 	}
6300 
6301 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
6302 	    (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
6303 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6304 		    " ddi_intr_get_pri() failed: %d",
6305 		    ddi_status));
6306 		/* Free already allocated interrupts */
6307 		for (y = 0; y < nactual; y++) {
6308 			(void) ddi_intr_free(intrp->htable[y]);
6309 		}
6310 
6311 		kmem_free(intrp->htable, intrp->intr_size);
6312 		return (NXGE_ERROR | NXGE_DDI_FAILED);
6313 	}
6314 
6315 	nrequired = 0;
6316 	switch (nxgep->niu_type) {
6317 	default:
6318 		status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
6319 		break;
6320 
6321 	case N2_NIU:
6322 		status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
6323 		break;
6324 	}
6325 
6326 	if (status != NXGE_OK) {
6327 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6328 		    "nxge_add_intrs_adv_type_fix:nxge_ldgv_init "
6329 		    "failed: 0x%x", status));
6330 		/* Free already allocated interrupts */
6331 		for (y = 0; y < nactual; y++) {
6332 			(void) ddi_intr_free(intrp->htable[y]);
6333 		}
6334 
6335 		kmem_free(intrp->htable, intrp->intr_size);
6336 		return (status);
6337 	}
6338 
6339 	ldgp = nxgep->ldgvp->ldgp;
6340 	for (x = 0; x < nrequired; x++, ldgp++) {
6341 		ldgp->vector = (uint8_t)x;
6342 		if (nxgep->niu_type != N2_NIU) {
6343 			ldgp->intdata = SID_DATA(ldgp->func, x);
6344 		}
6345 
6346 		arg1 = ldgp->ldvp;
6347 		arg2 = nxgep;
6348 		if (ldgp->nldvs == 1) {
6349 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
6350 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
6351 			    "nxge_add_intrs_adv_type_fix: "
6352 			    "1-1 int handler(%d) ldg %d ldv %d "
6353 			    "arg1 $%p arg2 $%p\n",
6354 			    x, ldgp->ldg, ldgp->ldvp->ldv,
6355 			    arg1, arg2));
6356 		} else if (ldgp->nldvs > 1) {
6357 			inthandler = (uint_t *)ldgp->sys_intr_handler;
6358 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
6359 			    "nxge_add_intrs_adv_type_fix: "
6360 			    "shared ldv %d int handler(%d) ldv %d ldg %d"
6361 			    "arg1 0x%016llx arg2 0x%016llx\n",
6362 			    x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
6363 			    arg1, arg2));
6364 		}
6365 
6366 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
6367 		    (ddi_intr_handler_t *)inthandler, arg1, arg2))
6368 		    != DDI_SUCCESS) {
6369 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6370 			    "==> nxge_add_intrs_adv_type_fix: failed #%d "
6371 			    "status 0x%x", x, ddi_status));
6372 			for (y = 0; y < intrp->intr_added; y++) {
6373 				(void) ddi_intr_remove_handler(
6374 				    intrp->htable[y]);
6375 			}
6376 			for (y = 0; y < nactual; y++) {
6377 				(void) ddi_intr_free(intrp->htable[y]);
6378 			}
6379 			/* Free already allocated intr */
6380 			kmem_free(intrp->htable, intrp->intr_size);
6381 
6382 			(void) nxge_ldgv_uninit(nxgep);
6383 
6384 			return (NXGE_ERROR | NXGE_DDI_FAILED);
6385 		}
6386 
6387 		ldgp->htable_idx = x;
6388 		intrp->intr_added++;
6389 	}
6390 
6391 	intrp->msi_intx_cnt = nactual;
6392 
6393 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
6394 
6395 	status = nxge_intr_ldgv_init(nxgep);
6396 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix"));
6397 
6398 	return (status);
6399 }
6400 
6401 static void
6402 nxge_remove_intrs(p_nxge_t nxgep)
6403 {
6404 	int		i, inum;
6405 	p_nxge_intr_t	intrp;
6406 
6407 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs"));
6408 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6409 	if (!intrp->intr_registered) {
6410 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
6411 		    "<== nxge_remove_intrs: interrupts not registered"));
6412 		return;
6413 	}
6414 
6415 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced"));
6416 
6417 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6418 		(void) ddi_intr_block_disable(intrp->htable,
6419 		    intrp->intr_added);
6420 	} else {
6421 		for (i = 0; i < intrp->intr_added; i++) {
6422 			(void) ddi_intr_disable(intrp->htable[i]);
6423 		}
6424 	}
6425 
6426 	for (inum = 0; inum < intrp->intr_added; inum++) {
6427 		if (intrp->htable[inum]) {
6428 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
6429 		}
6430 	}
6431 
6432 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
6433 		if (intrp->htable[inum]) {
6434 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
6435 			    "nxge_remove_intrs: ddi_intr_free inum %d "
6436 			    "msi_intx_cnt %d intr_added %d",
6437 			    inum,
6438 			    intrp->msi_intx_cnt,
6439 			    intrp->intr_added));
6440 
6441 			(void) ddi_intr_free(intrp->htable[inum]);
6442 		}
6443 	}
6444 
6445 	kmem_free(intrp->htable, intrp->intr_size);
6446 	intrp->intr_registered = B_FALSE;
6447 	intrp->intr_enabled = B_FALSE;
6448 	intrp->msi_intx_cnt = 0;
6449 	intrp->intr_added = 0;
6450 
6451 	(void) nxge_ldgv_uninit(nxgep);
6452 
6453 	(void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip,
6454 	    "#msix-request");
6455 
6456 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs"));
6457 }
6458 
6459 /*ARGSUSED*/
6460 static void
6461 nxge_intrs_enable(p_nxge_t nxgep)
6462 {
6463 	p_nxge_intr_t	intrp;
6464 	int		i;
6465 	int		status;
6466 
6467 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable"));
6468 
6469 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6470 
6471 	if (!intrp->intr_registered) {
6472 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: "
6473 		    "interrupts are not registered"));
6474 		return;
6475 	}
6476 
6477 	if (intrp->intr_enabled) {
6478 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
6479 		    "<== nxge_intrs_enable: already enabled"));
6480 		return;
6481 	}
6482 
6483 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6484 		status = ddi_intr_block_enable(intrp->htable,
6485 		    intrp->intr_added);
6486 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
6487 		    "block enable - status 0x%x total inums #%d\n",
6488 		    status, intrp->intr_added));
6489 	} else {
6490 		for (i = 0; i < intrp->intr_added; i++) {
6491 			status = ddi_intr_enable(intrp->htable[i]);
6492 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
6493 			    "ddi_intr_enable:enable - status 0x%x "
6494 			    "total inums %d enable inum #%d\n",
6495 			    status, intrp->intr_added, i));
6496 			if (status == DDI_SUCCESS) {
6497 				intrp->intr_enabled = B_TRUE;
6498 			}
6499 		}
6500 	}
6501 
6502 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable"));
6503 }
6504 
6505 /*ARGSUSED*/
6506 static void
6507 nxge_intrs_disable(p_nxge_t nxgep)
6508 {
6509 	p_nxge_intr_t	intrp;
6510 	int		i;
6511 
6512 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable"));
6513 
6514 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
6515 
6516 	if (!intrp->intr_registered) {
6517 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: "
6518 		    "interrupts are not registered"));
6519 		return;
6520 	}
6521 
6522 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
6523 		(void) ddi_intr_block_disable(intrp->htable,
6524 		    intrp->intr_added);
6525 	} else {
6526 		for (i = 0; i < intrp->intr_added; i++) {
6527 			(void) ddi_intr_disable(intrp->htable[i]);
6528 		}
6529 	}
6530 
6531 	intrp->intr_enabled = B_FALSE;
6532 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable"));
6533 }
6534 
6535 nxge_status_t
6536 nxge_mac_register(p_nxge_t nxgep)
6537 {
6538 	mac_register_t *macp;
6539 	int		status;
6540 
6541 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register"));
6542 
6543 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
6544 		return (NXGE_ERROR);
6545 
6546 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
6547 	macp->m_driver = nxgep;
6548 	macp->m_dip = nxgep->dip;
6549 	if (!isLDOMguest(nxgep)) {
6550 		macp->m_src_addr = nxgep->ouraddr.ether_addr_octet;
6551 	} else {
6552 		macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP);
6553 		macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP);
6554 		(void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN));
6555 	}
6556 	macp->m_callbacks = &nxge_m_callbacks;
6557 	macp->m_min_sdu = 0;
6558 	nxgep->mac.default_mtu = nxgep->mac.maxframesize -
6559 	    NXGE_EHEADER_VLAN_CRC;
6560 	macp->m_max_sdu = nxgep->mac.default_mtu;
6561 	macp->m_margin = VLAN_TAGSZ;
6562 	macp->m_priv_props = nxge_priv_props;
6563 	if (isLDOMguest(nxgep))
6564 		macp->m_v12n = MAC_VIRT_LEVEL1;
6565 	else
6566 		macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1;
6567 
6568 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6569 	    "==> nxge_mac_register: instance %d "
6570 	    "max_sdu %d margin %d maxframe %d (header %d)",
6571 	    nxgep->instance,
6572 	    macp->m_max_sdu, macp->m_margin,
6573 	    nxgep->mac.maxframesize,
6574 	    NXGE_EHEADER_VLAN_CRC));
6575 
6576 	status = mac_register(macp, &nxgep->mach);
6577 	if (isLDOMguest(nxgep)) {
6578 		KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN);
6579 		KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN);
6580 	}
6581 	mac_free(macp);
6582 
6583 	if (status != 0) {
6584 		cmn_err(CE_WARN,
6585 		    "!nxge_mac_register failed (status %d instance %d)",
6586 		    status, nxgep->instance);
6587 		return (NXGE_ERROR);
6588 	}
6589 
6590 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success "
6591 	    "(instance %d)", nxgep->instance));
6592 
6593 	return (NXGE_OK);
6594 }
6595 
6596 void
6597 nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
6598 {
6599 	ssize_t		size;
6600 	mblk_t		*nmp;
6601 	uint8_t		blk_id;
6602 	uint8_t		chan;
6603 	uint32_t	err_id;
6604 	err_inject_t	*eip;
6605 
6606 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject"));
6607 
6608 	size = 1024;
6609 	nmp = mp->b_cont;
6610 	eip = (err_inject_t *)nmp->b_rptr;
6611 	blk_id = eip->blk_id;
6612 	err_id = eip->err_id;
6613 	chan = eip->chan;
6614 	cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id);
6615 	cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id);
6616 	cmn_err(CE_NOTE, "!chan = 0x%x\n", chan);
6617 	switch (blk_id) {
6618 	case MAC_BLK_ID:
6619 		break;
6620 	case TXMAC_BLK_ID:
6621 		break;
6622 	case RXMAC_BLK_ID:
6623 		break;
6624 	case MIF_BLK_ID:
6625 		break;
6626 	case IPP_BLK_ID:
6627 		nxge_ipp_inject_err(nxgep, err_id);
6628 		break;
6629 	case TXC_BLK_ID:
6630 		nxge_txc_inject_err(nxgep, err_id);
6631 		break;
6632 	case TXDMA_BLK_ID:
6633 		nxge_txdma_inject_err(nxgep, err_id, chan);
6634 		break;
6635 	case RXDMA_BLK_ID:
6636 		nxge_rxdma_inject_err(nxgep, err_id, chan);
6637 		break;
6638 	case ZCP_BLK_ID:
6639 		nxge_zcp_inject_err(nxgep, err_id);
6640 		break;
6641 	case ESPC_BLK_ID:
6642 		break;
6643 	case FFLP_BLK_ID:
6644 		break;
6645 	case PHY_BLK_ID:
6646 		break;
6647 	case ETHER_SERDES_BLK_ID:
6648 		break;
6649 	case PCIE_SERDES_BLK_ID:
6650 		break;
6651 	case VIR_BLK_ID:
6652 		break;
6653 	}
6654 
6655 	nmp->b_wptr = nmp->b_rptr + size;
6656 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject"));
6657 
6658 	miocack(wq, mp, (int)size, 0);
6659 }
6660 
6661 static int
6662 nxge_init_common_dev(p_nxge_t nxgep)
6663 {
6664 	p_nxge_hw_list_t	hw_p;
6665 	dev_info_t 		*p_dip;
6666 
6667 	ASSERT(nxgep != NULL);
6668 
6669 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device"));
6670 
6671 	p_dip = nxgep->p_dip;
6672 	MUTEX_ENTER(&nxge_common_lock);
6673 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6674 	    "==> nxge_init_common_dev:func # %d",
6675 	    nxgep->function_num));
6676 	/*
6677 	 * Loop through existing per neptune hardware list.
6678 	 */
6679 	for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
6680 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6681 		    "==> nxge_init_common_device:func # %d "
6682 		    "hw_p $%p parent dip $%p",
6683 		    nxgep->function_num,
6684 		    hw_p,
6685 		    p_dip));
6686 		if (hw_p->parent_devp == p_dip) {
6687 			nxgep->nxge_hw_p = hw_p;
6688 			hw_p->ndevs++;
6689 			hw_p->nxge_p[nxgep->function_num] = nxgep;
6690 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6691 			    "==> nxge_init_common_device:func # %d "
6692 			    "hw_p $%p parent dip $%p "
6693 			    "ndevs %d (found)",
6694 			    nxgep->function_num,
6695 			    hw_p,
6696 			    p_dip,
6697 			    hw_p->ndevs));
6698 			break;
6699 		}
6700 	}
6701 
6702 	if (hw_p == NULL) {
6703 
6704 		char **prop_val;
6705 		uint_t prop_len;
6706 		int i;
6707 
6708 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6709 		    "==> nxge_init_common_device:func # %d "
6710 		    "parent dip $%p (new)",
6711 		    nxgep->function_num,
6712 		    p_dip));
6713 		hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP);
6714 		hw_p->parent_devp = p_dip;
6715 		hw_p->magic = NXGE_NEPTUNE_MAGIC;
6716 		nxgep->nxge_hw_p = hw_p;
6717 		hw_p->ndevs++;
6718 		hw_p->nxge_p[nxgep->function_num] = nxgep;
6719 		hw_p->next = nxge_hw_list;
6720 		if (nxgep->niu_type == N2_NIU) {
6721 			hw_p->niu_type = N2_NIU;
6722 			hw_p->platform_type = P_NEPTUNE_NIU;
6723 			hw_p->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
6724 		} else {
6725 			hw_p->niu_type = NIU_TYPE_NONE;
6726 			hw_p->platform_type = P_NEPTUNE_NONE;
6727 			hw_p->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
6728 		}
6729 
6730 		hw_p->tcam = KMEM_ZALLOC(sizeof (tcam_flow_spec_t) *
6731 		    hw_p->tcam_size, KM_SLEEP);
6732 
6733 		MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
6734 		MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
6735 		MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
6736 		MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL);
6737 
6738 		nxge_hw_list = hw_p;
6739 
6740 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0,
6741 		    "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
6742 			for (i = 0; i < prop_len; i++) {
6743 				if ((strcmp((caddr_t)prop_val[i],
6744 				    NXGE_ROCK_COMPATIBLE) == 0)) {
6745 					hw_p->platform_type = P_NEPTUNE_ROCK;
6746 					NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6747 					    "ROCK hw_p->platform_type %d",
6748 					    hw_p->platform_type));
6749 					break;
6750 				}
6751 				NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6752 				    "nxge_init_common_dev: read compatible"
6753 				    " property[%d] val[%s]",
6754 				    i, (caddr_t)prop_val[i]));
6755 			}
6756 		}
6757 
6758 		ddi_prop_free(prop_val);
6759 
6760 		(void) nxge_scan_ports_phy(nxgep, nxge_hw_list);
6761 	}
6762 
6763 	MUTEX_EXIT(&nxge_common_lock);
6764 
6765 	nxgep->platform_type = hw_p->platform_type;
6766 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d",
6767 	    nxgep->platform_type));
6768 	if (nxgep->niu_type != N2_NIU) {
6769 		nxgep->niu_type = hw_p->niu_type;
6770 	}
6771 
6772 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6773 	    "==> nxge_init_common_device (nxge_hw_list) $%p",
6774 	    nxge_hw_list));
6775 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device"));
6776 
6777 	return (NXGE_OK);
6778 }
6779 
6780 static void
6781 nxge_uninit_common_dev(p_nxge_t nxgep)
6782 {
6783 	p_nxge_hw_list_t	hw_p, h_hw_p;
6784 	p_nxge_dma_pt_cfg_t	p_dma_cfgp;
6785 	p_nxge_hw_pt_cfg_t	p_cfgp;
6786 	dev_info_t 		*p_dip;
6787 
6788 	ASSERT(nxgep != NULL);
6789 
6790 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device"));
6791 	if (nxgep->nxge_hw_p == NULL) {
6792 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6793 		    "<== nxge_uninit_common_device (no common)"));
6794 		return;
6795 	}
6796 
6797 	MUTEX_ENTER(&nxge_common_lock);
6798 	h_hw_p = nxge_hw_list;
6799 	for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
6800 		p_dip = hw_p->parent_devp;
6801 		if (nxgep->nxge_hw_p == hw_p &&
6802 		    p_dip == nxgep->p_dip &&
6803 		    nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC &&
6804 		    hw_p->magic == NXGE_NEPTUNE_MAGIC) {
6805 
6806 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6807 			    "==> nxge_uninit_common_device:func # %d "
6808 			    "hw_p $%p parent dip $%p "
6809 			    "ndevs %d (found)",
6810 			    nxgep->function_num,
6811 			    hw_p,
6812 			    p_dip,
6813 			    hw_p->ndevs));
6814 
6815 			/*
6816 			 * Release the RDC table, a shared resoruce
6817 			 * of the nxge hardware.  The RDC table was
6818 			 * assigned to this instance of nxge in
6819 			 * nxge_use_cfg_dma_config().
6820 			 */
6821 			if (!isLDOMguest(nxgep)) {
6822 				p_dma_cfgp =
6823 				    (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
6824 				p_cfgp =
6825 				    (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
6826 				(void) nxge_fzc_rdc_tbl_unbind(nxgep,
6827 				    p_cfgp->def_mac_rxdma_grpid);
6828 
6829 				/* Cleanup any outstanding groups.  */
6830 				nxge_grp_cleanup(nxgep);
6831 			}
6832 
6833 			if (hw_p->ndevs) {
6834 				hw_p->ndevs--;
6835 			}
6836 			hw_p->nxge_p[nxgep->function_num] = NULL;
6837 			if (!hw_p->ndevs) {
6838 				KMEM_FREE(hw_p->tcam,
6839 				    sizeof (tcam_flow_spec_t) *
6840 				    hw_p->tcam_size);
6841 				MUTEX_DESTROY(&hw_p->nxge_vlan_lock);
6842 				MUTEX_DESTROY(&hw_p->nxge_tcam_lock);
6843 				MUTEX_DESTROY(&hw_p->nxge_cfg_lock);
6844 				MUTEX_DESTROY(&hw_p->nxge_mdio_lock);
6845 				NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6846 				    "==> nxge_uninit_common_device: "
6847 				    "func # %d "
6848 				    "hw_p $%p parent dip $%p "
6849 				    "ndevs %d (last)",
6850 				    nxgep->function_num,
6851 				    hw_p,
6852 				    p_dip,
6853 				    hw_p->ndevs));
6854 
6855 				nxge_hio_uninit(nxgep);
6856 
6857 				if (hw_p == nxge_hw_list) {
6858 					NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6859 					    "==> nxge_uninit_common_device:"
6860 					    "remove head func # %d "
6861 					    "hw_p $%p parent dip $%p "
6862 					    "ndevs %d (head)",
6863 					    nxgep->function_num,
6864 					    hw_p,
6865 					    p_dip,
6866 					    hw_p->ndevs));
6867 					nxge_hw_list = hw_p->next;
6868 				} else {
6869 					NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6870 					    "==> nxge_uninit_common_device:"
6871 					    "remove middle func # %d "
6872 					    "hw_p $%p parent dip $%p "
6873 					    "ndevs %d (middle)",
6874 					    nxgep->function_num,
6875 					    hw_p,
6876 					    p_dip,
6877 					    hw_p->ndevs));
6878 					h_hw_p->next = hw_p->next;
6879 				}
6880 
6881 				nxgep->nxge_hw_p = NULL;
6882 				KMEM_FREE(hw_p, sizeof (nxge_hw_list_t));
6883 			}
6884 			break;
6885 		} else {
6886 			h_hw_p = hw_p;
6887 		}
6888 	}
6889 
6890 	MUTEX_EXIT(&nxge_common_lock);
6891 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6892 	    "==> nxge_uninit_common_device (nxge_hw_list) $%p",
6893 	    nxge_hw_list));
6894 
6895 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device"));
6896 }
6897 
6898 /*
6899  * Determines the number of ports from the niu_type or the platform type.
6900  * Returns the number of ports, or returns zero on failure.
6901  */
6902 
6903 int
6904 nxge_get_nports(p_nxge_t nxgep)
6905 {
6906 	int	nports = 0;
6907 
6908 	switch (nxgep->niu_type) {
6909 	case N2_NIU:
6910 	case NEPTUNE_2_10GF:
6911 		nports = 2;
6912 		break;
6913 	case NEPTUNE_4_1GC:
6914 	case NEPTUNE_2_10GF_2_1GC:
6915 	case NEPTUNE_1_10GF_3_1GC:
6916 	case NEPTUNE_1_1GC_1_10GF_2_1GC:
6917 	case NEPTUNE_2_10GF_2_1GRF:
6918 		nports = 4;
6919 		break;
6920 	default:
6921 		switch (nxgep->platform_type) {
6922 		case P_NEPTUNE_NIU:
6923 		case P_NEPTUNE_ATLAS_2PORT:
6924 			nports = 2;
6925 			break;
6926 		case P_NEPTUNE_ATLAS_4PORT:
6927 		case P_NEPTUNE_MARAMBA_P0:
6928 		case P_NEPTUNE_MARAMBA_P1:
6929 		case P_NEPTUNE_ROCK:
6930 		case P_NEPTUNE_ALONSO:
6931 			nports = 4;
6932 			break;
6933 		default:
6934 			break;
6935 		}
6936 		break;
6937 	}
6938 
6939 	return (nports);
6940 }
6941 
6942 /*
6943  * The following two functions are to support
6944  * PSARC/2007/453 MSI-X interrupt limit override.
6945  */
6946 static int
6947 nxge_create_msi_property(p_nxge_t nxgep)
6948 {
6949 	int	nmsi;
6950 	extern	int ncpus;
6951 
6952 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property"));
6953 
6954 	switch (nxgep->mac.portmode) {
6955 	case PORT_10G_COPPER:
6956 	case PORT_10G_FIBER:
6957 	case PORT_10G_TN1010:
6958 		(void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip,
6959 		    DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
6960 		/*
6961 		 * The maximum MSI-X requested will be 8.
6962 		 * If the # of CPUs is less than 8, we will request
6963 		 * # MSI-X based on the # of CPUs (default).
6964 		 */
6965 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6966 		    "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d",
6967 		    nxge_msix_10g_intrs));
6968 		if ((nxge_msix_10g_intrs == 0) ||
6969 		    (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) {
6970 			nmsi = NXGE_MSIX_REQUEST_10G;
6971 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6972 			    "==>nxge_create_msi_property (10G): reset to 8"));
6973 		} else {
6974 			nmsi = nxge_msix_10g_intrs;
6975 		}
6976 
6977 		/*
6978 		 * If # of interrupts requested is 8 (default),
6979 		 * the checking of the number of cpus will be
6980 		 * be maintained.
6981 		 */
6982 		if ((nmsi == NXGE_MSIX_REQUEST_10G) &&
6983 		    (ncpus < nmsi)) {
6984 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6985 			    "==>nxge_create_msi_property (10G): reset to 8"));
6986 			nmsi = ncpus;
6987 		}
6988 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6989 		    "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
6990 		    ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
6991 		    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
6992 		break;
6993 
6994 	default:
6995 		(void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip,
6996 		    DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
6997 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
6998 		    "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d",
6999 		    nxge_msix_1g_intrs));
7000 		if ((nxge_msix_1g_intrs == 0) ||
7001 		    (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) {
7002 			nmsi = NXGE_MSIX_REQUEST_1G;
7003 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
7004 			    "==>nxge_create_msi_property (1G): reset to 2"));
7005 		} else {
7006 			nmsi = nxge_msix_1g_intrs;
7007 		}
7008 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
7009 		    "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)",
7010 		    ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
7011 		    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
7012 		break;
7013 	}
7014 
7015 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property"));
7016 	return (nmsi);
7017 }
7018 
7019 /*
7020  * The following is a software around for the Neptune hardware's
7021  * interrupt bugs; The Neptune hardware may generate spurious interrupts when
7022  * an interrupr handler is removed.
7023  */
7024 #define	NXGE_PCI_PORT_LOGIC_OFFSET	0x98
7025 #define	NXGE_PIM_RESET			(1ULL << 29)
7026 #define	NXGE_GLU_RESET			(1ULL << 30)
7027 #define	NXGE_NIU_RESET			(1ULL << 31)
7028 #define	NXGE_PCI_RESET_ALL		(NXGE_PIM_RESET |	\
7029 					NXGE_GLU_RESET |	\
7030 					NXGE_NIU_RESET)
7031 
7032 #define	NXGE_WAIT_QUITE_TIME		200000
7033 #define	NXGE_WAIT_QUITE_RETRY		40
7034 #define	NXGE_PCI_RESET_WAIT		1000000 /* one second */
7035 
7036 static void
7037 nxge_niu_peu_reset(p_nxge_t nxgep)
7038 {
7039 	uint32_t	rvalue;
7040 	p_nxge_hw_list_t hw_p;
7041 	p_nxge_t	fnxgep;
7042 	int		i, j;
7043 
7044 	NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset"));
7045 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
7046 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7047 		    "==> nxge_niu_peu_reset: NULL hardware pointer"));
7048 		return;
7049 	}
7050 
7051 	NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7052 	    "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d",
7053 	    hw_p->flags, nxgep->nxge_link_poll_timerid,
7054 	    nxgep->nxge_timerid));
7055 
7056 	MUTEX_ENTER(&hw_p->nxge_cfg_lock);
7057 	/*
7058 	 * Make sure other instances from the same hardware
7059 	 * stop sending PIO and in quiescent state.
7060 	 */
7061 	for (i = 0; i < NXGE_MAX_PORTS; i++) {
7062 		fnxgep = hw_p->nxge_p[i];
7063 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7064 		    "==> nxge_niu_peu_reset: checking entry %d "
7065 		    "nxgep $%p", i, fnxgep));
7066 #ifdef	NXGE_DEBUG
7067 		if (fnxgep) {
7068 			NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7069 			    "==> nxge_niu_peu_reset: entry %d (function %d) "
7070 			    "link timer id %d hw timer id %d",
7071 			    i, fnxgep->function_num,
7072 			    fnxgep->nxge_link_poll_timerid,
7073 			    fnxgep->nxge_timerid));
7074 		}
7075 #endif
7076 		if (fnxgep && fnxgep != nxgep &&
7077 		    (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) {
7078 			NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7079 			    "==> nxge_niu_peu_reset: checking $%p "
7080 			    "(function %d) timer ids",
7081 			    fnxgep, fnxgep->function_num));
7082 			for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) {
7083 				NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7084 				    "==> nxge_niu_peu_reset: waiting"));
7085 				NXGE_DELAY(NXGE_WAIT_QUITE_TIME);
7086 				if (!fnxgep->nxge_timerid &&
7087 				    !fnxgep->nxge_link_poll_timerid) {
7088 					break;
7089 				}
7090 			}
7091 			NXGE_DELAY(NXGE_WAIT_QUITE_TIME);
7092 			if (fnxgep->nxge_timerid ||
7093 			    fnxgep->nxge_link_poll_timerid) {
7094 				MUTEX_EXIT(&hw_p->nxge_cfg_lock);
7095 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7096 				    "<== nxge_niu_peu_reset: cannot reset "
7097 				    "hardware (devices are still in use)"));
7098 				return;
7099 			}
7100 		}
7101 	}
7102 
7103 	if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) {
7104 		hw_p->flags |= COMMON_RESET_NIU_PCI;
7105 		rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh,
7106 		    NXGE_PCI_PORT_LOGIC_OFFSET);
7107 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7108 		    "nxge_niu_peu_reset: read offset 0x%x (%d) "
7109 		    "(data 0x%x)",
7110 		    NXGE_PCI_PORT_LOGIC_OFFSET,
7111 		    NXGE_PCI_PORT_LOGIC_OFFSET,
7112 		    rvalue));
7113 
7114 		rvalue |= NXGE_PCI_RESET_ALL;
7115 		pci_config_put32(nxgep->dev_regs->nxge_pciregh,
7116 		    NXGE_PCI_PORT_LOGIC_OFFSET, rvalue);
7117 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
7118 		    "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x",
7119 		    rvalue));
7120 
7121 		NXGE_DELAY(NXGE_PCI_RESET_WAIT);
7122 	}
7123 
7124 	MUTEX_EXIT(&hw_p->nxge_cfg_lock);
7125 	NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset"));
7126 }
7127 
7128 static void
7129 nxge_set_pci_replay_timeout(p_nxge_t nxgep)
7130 {
7131 	p_dev_regs_t	dev_regs;
7132 	uint32_t	value;
7133 
7134 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout"));
7135 
7136 	if (!nxge_set_replay_timer) {
7137 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7138 		    "==> nxge_set_pci_replay_timeout: will not change "
7139 		    "the timeout"));
7140 		return;
7141 	}
7142 
7143 	dev_regs = nxgep->dev_regs;
7144 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7145 	    "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p",
7146 	    dev_regs, dev_regs->nxge_pciregh));
7147 
7148 	if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) {
7149 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7150 		    "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or "
7151 		    "no PCI handle",
7152 		    dev_regs));
7153 		return;
7154 	}
7155 	value = (pci_config_get32(dev_regs->nxge_pciregh,
7156 	    PCI_REPLAY_TIMEOUT_CFG_OFFSET) |
7157 	    (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT));
7158 
7159 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7160 	    "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x "
7161 	    "(timeout value to set 0x%x at offset 0x%x) value 0x%x",
7162 	    pci_config_get32(dev_regs->nxge_pciregh,
7163 	    PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout,
7164 	    PCI_REPLAY_TIMEOUT_CFG_OFFSET, value));
7165 
7166 	pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET,
7167 	    value);
7168 
7169 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
7170 	    "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x",
7171 	    pci_config_get32(dev_regs->nxge_pciregh,
7172 	    PCI_REPLAY_TIMEOUT_CFG_OFFSET)));
7173 
7174 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout"));
7175 }
7176 
7177 /*
7178  * quiesce(9E) entry point.
7179  *
7180  * This function is called when the system is single-threaded at high
7181  * PIL with preemption disabled. Therefore, this function must not be
7182  * blocked.
7183  *
7184  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
7185  * DDI_FAILURE indicates an error condition and should almost never happen.
7186  */
7187 static int
7188 nxge_quiesce(dev_info_t *dip)
7189 {
7190 	int instance = ddi_get_instance(dip);
7191 	p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
7192 
7193 	if (nxgep == NULL)
7194 		return (DDI_FAILURE);
7195 
7196 	/* Turn off debugging */
7197 	nxge_debug_level = NO_DEBUG;
7198 	nxgep->nxge_debug_level = NO_DEBUG;
7199 	npi_debug_level = NO_DEBUG;
7200 
7201 	/*
7202 	 * Stop link monitor only when linkchkmod is interrupt based
7203 	 */
7204 	if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
7205 		(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
7206 	}
7207 
7208 	(void) nxge_intr_hw_disable(nxgep);
7209 
7210 	/*
7211 	 * Reset the receive MAC side.
7212 	 */
7213 	(void) nxge_rx_mac_disable(nxgep);
7214 
7215 	/* Disable and soft reset the IPP */
7216 	if (!isLDOMguest(nxgep))
7217 		(void) nxge_ipp_disable(nxgep);
7218 
7219 	/*
7220 	 * Reset the transmit/receive DMA side.
7221 	 */
7222 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
7223 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
7224 
7225 	/*
7226 	 * Reset the transmit MAC side.
7227 	 */
7228 	(void) nxge_tx_mac_disable(nxgep);
7229 
7230 	return (DDI_SUCCESS);
7231 }
7232