xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_main.c (revision 4202ea4b)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
2230ac2e7bSml  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish /*
2944961713Sgirish  * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
3044961713Sgirish  */
3144961713Sgirish #include	<sys/nxge/nxge_impl.h>
3214ea4bb7Ssd #include	<sys/pcie.h>
3344961713Sgirish 
3444961713Sgirish uint32_t 	nxge_use_partition = 0;		/* debug partition flag */
3544961713Sgirish uint32_t 	nxge_dma_obp_props_only = 1;	/* use obp published props */
3644961713Sgirish uint32_t 	nxge_use_rdc_intr = 1;		/* debug to assign rdc intr */
3744961713Sgirish /*
38ec090658Sml  * PSARC/2007/453 MSI-X interrupt limit override
39ec090658Sml  * (This PSARC case is limited to MSI-X vectors
40ec090658Sml  *  and SPARC platforms only).
4144961713Sgirish  */
42ec090658Sml #if defined(_BIG_ENDIAN)
43ec090658Sml uint32_t	nxge_msi_enable = 2;
44ec090658Sml #else
45ec090658Sml uint32_t	nxge_msi_enable = 1;
46ec090658Sml #endif
4744961713Sgirish 
4844961713Sgirish /*
4944961713Sgirish  * Globals: tunable parameters (/etc/system or adb)
5044961713Sgirish  *
5144961713Sgirish  */
5244961713Sgirish uint32_t 	nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
5344961713Sgirish uint32_t 	nxge_rbr_spare_size = 0;
5444961713Sgirish uint32_t 	nxge_rcr_size = NXGE_RCR_DEFAULT;
5544961713Sgirish uint32_t 	nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
56b3a0105bSspeer boolean_t 	nxge_no_msg = B_TRUE;		/* control message display */
5744961713Sgirish uint32_t 	nxge_no_link_notify = 0;	/* control DL_NOTIFY */
5844961713Sgirish uint32_t 	nxge_bcopy_thresh = TX_BCOPY_MAX;
5944961713Sgirish uint32_t 	nxge_dvma_thresh = TX_FASTDVMA_MIN;
6044961713Sgirish uint32_t 	nxge_dma_stream_thresh = TX_STREAM_MIN;
6144961713Sgirish uint32_t	nxge_jumbo_mtu	= TX_JUMBO_MTU;
6244961713Sgirish boolean_t	nxge_jumbo_enable = B_FALSE;
6344961713Sgirish uint16_t	nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT;
6444961713Sgirish uint16_t	nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD;
651f8914d5Sml nxge_tx_mode_t	nxge_tx_scheme = NXGE_USE_SERIAL;
6644961713Sgirish 
6730ac2e7bSml /* MAX LSO size */
6830ac2e7bSml #define		NXGE_LSO_MAXLEN	65535
6930ac2e7bSml uint32_t	nxge_lso_max = NXGE_LSO_MAXLEN;
7030ac2e7bSml 
7144961713Sgirish /*
7244961713Sgirish  * Debugging flags:
7344961713Sgirish  *		nxge_no_tx_lb : transmit load balancing
7444961713Sgirish  *		nxge_tx_lb_policy: 0 - TCP port (default)
7544961713Sgirish  *				   3 - DEST MAC
7644961713Sgirish  */
7744961713Sgirish uint32_t 	nxge_no_tx_lb = 0;
7844961713Sgirish uint32_t 	nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP;
7944961713Sgirish 
8044961713Sgirish /*
8144961713Sgirish  * Add tunable to reduce the amount of time spent in the
8244961713Sgirish  * ISR doing Rx Processing.
8344961713Sgirish  */
8444961713Sgirish uint32_t nxge_max_rx_pkts = 1024;
8544961713Sgirish 
8644961713Sgirish /*
8744961713Sgirish  * Tunables to manage the receive buffer blocks.
8844961713Sgirish  *
8944961713Sgirish  * nxge_rx_threshold_hi: copy all buffers.
9044961713Sgirish  * nxge_rx_bcopy_size_type: receive buffer block size type.
9144961713Sgirish  * nxge_rx_threshold_lo: copy only up to tunable block size type.
9244961713Sgirish  */
9344961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
9444961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
9544961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
9644961713Sgirish 
9744961713Sgirish rtrace_t npi_rtracebuf;
9844961713Sgirish 
9944961713Sgirish #if	defined(sun4v)
10044961713Sgirish /*
10144961713Sgirish  * Hypervisor N2/NIU services information.
10244961713Sgirish  */
10344961713Sgirish static hsvc_info_t niu_hsvc = {
10444961713Sgirish 	HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
10544961713Sgirish 	NIU_MINOR_VER, "nxge"
10644961713Sgirish };
10744961713Sgirish #endif
10844961713Sgirish 
10944961713Sgirish /*
11044961713Sgirish  * Function Prototypes
11144961713Sgirish  */
11244961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
11344961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
11444961713Sgirish static void nxge_unattach(p_nxge_t);
11544961713Sgirish 
11644961713Sgirish #if NXGE_PROPERTY
11744961713Sgirish static void nxge_remove_hard_properties(p_nxge_t);
11844961713Sgirish #endif
11944961713Sgirish 
12044961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
12144961713Sgirish 
12244961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t);
12344961713Sgirish static void nxge_destroy_mutexes(p_nxge_t);
12444961713Sgirish 
12544961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
12644961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep);
12744961713Sgirish #ifdef	NXGE_DEBUG
12844961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep);
12944961713Sgirish #endif
13044961713Sgirish 
13144961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
13244961713Sgirish static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep);
13344961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep);
13444961713Sgirish static void nxge_remove_soft_intrs(p_nxge_t nxgep);
13544961713Sgirish 
13644961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
13744961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
13844961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
13944961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep);
14044961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep);
14144961713Sgirish 
14244961713Sgirish static void nxge_suspend(p_nxge_t);
14344961713Sgirish static nxge_status_t nxge_resume(p_nxge_t);
14444961713Sgirish 
14544961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t);
14644961713Sgirish static void nxge_destroy_dev(p_nxge_t);
14744961713Sgirish 
14844961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
14944961713Sgirish static void nxge_free_mem_pool(p_nxge_t);
15044961713Sgirish 
15144961713Sgirish static nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
15244961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t);
15344961713Sgirish 
15444961713Sgirish static nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
15544961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t);
15644961713Sgirish 
15744961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
15844961713Sgirish 	struct ddi_dma_attr *,
15944961713Sgirish 	size_t, ddi_device_acc_attr_t *, uint_t,
16044961713Sgirish 	p_nxge_dma_common_t);
16144961713Sgirish 
16244961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t);
16344961713Sgirish 
16444961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
16544961713Sgirish 	p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
16644961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
16744961713Sgirish 
16844961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
16944961713Sgirish 	p_nxge_dma_common_t *, size_t);
17044961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
17144961713Sgirish 
17244961713Sgirish static nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
17344961713Sgirish 	p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
17444961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
17544961713Sgirish 
17644961713Sgirish static nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
17744961713Sgirish 	p_nxge_dma_common_t *,
17844961713Sgirish 	size_t);
17944961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
18044961713Sgirish 
18144961713Sgirish static int nxge_init_common_dev(p_nxge_t);
18244961713Sgirish static void nxge_uninit_common_dev(p_nxge_t);
18344961713Sgirish 
18444961713Sgirish /*
18544961713Sgirish  * The next declarations are for the GLDv3 interface.
18644961713Sgirish  */
18744961713Sgirish static int nxge_m_start(void *);
18844961713Sgirish static void nxge_m_stop(void *);
18944961713Sgirish static int nxge_m_unicst(void *, const uint8_t *);
19044961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
19144961713Sgirish static int nxge_m_promisc(void *, boolean_t);
19244961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
19344961713Sgirish static void nxge_m_resources(void *);
19444961713Sgirish mblk_t *nxge_m_tx(void *arg, mblk_t *);
19544961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t);
19658324dfcSspeer static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr,
19758324dfcSspeer 	mac_addr_slot_t slot);
19858324dfcSspeer static void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot,
19958324dfcSspeer 	boolean_t factory);
20058324dfcSspeer static int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
20158324dfcSspeer static int nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr);
20258324dfcSspeer static int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
20358324dfcSspeer static int nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr);
20458324dfcSspeer static int nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr);
20544961713Sgirish 
20644961713Sgirish #define	NXGE_NEPTUNE_MAGIC	0x4E584745UL
20744961713Sgirish #define	MAX_DUMP_SZ 256
20844961713Sgirish 
20944961713Sgirish #define	NXGE_M_CALLBACK_FLAGS	(MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
21044961713Sgirish 
21144961713Sgirish static	boolean_t	nxge_m_getcapab(void *, mac_capab_t, void *);
21244961713Sgirish static mac_callbacks_t nxge_m_callbacks = {
21344961713Sgirish 	NXGE_M_CALLBACK_FLAGS,
21444961713Sgirish 	nxge_m_stat,
21544961713Sgirish 	nxge_m_start,
21644961713Sgirish 	nxge_m_stop,
21744961713Sgirish 	nxge_m_promisc,
21844961713Sgirish 	nxge_m_multicst,
21944961713Sgirish 	nxge_m_unicst,
22044961713Sgirish 	nxge_m_tx,
22144961713Sgirish 	nxge_m_resources,
22244961713Sgirish 	nxge_m_ioctl,
22344961713Sgirish 	nxge_m_getcapab
22444961713Sgirish };
22544961713Sgirish 
22644961713Sgirish void
22744961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
22844961713Sgirish 
229ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */
230ec090658Sml #define	NXGE_MSIX_REQUEST_10G	8
231ec090658Sml #define	NXGE_MSIX_REQUEST_1G	2
232ec090658Sml static int nxge_create_msi_property(p_nxge_t);
233ec090658Sml 
23444961713Sgirish /*
23544961713Sgirish  * These global variables control the message
23644961713Sgirish  * output.
23744961713Sgirish  */
23844961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
23944961713Sgirish uint64_t nxge_debug_level = 0;
24044961713Sgirish 
24144961713Sgirish /*
24244961713Sgirish  * This list contains the instance structures for the Neptune
24344961713Sgirish  * devices present in the system. The lock exists to guarantee
24444961713Sgirish  * mutually exclusive access to the list.
24544961713Sgirish  */
24644961713Sgirish void 			*nxge_list = NULL;
24744961713Sgirish 
24844961713Sgirish void			*nxge_hw_list = NULL;
24944961713Sgirish nxge_os_mutex_t 	nxge_common_lock;
25044961713Sgirish 
25144961713Sgirish extern uint64_t 	npi_debug_level;
25244961713Sgirish 
25344961713Sgirish extern nxge_status_t	nxge_ldgv_init(p_nxge_t, int *, int *);
25444961713Sgirish extern nxge_status_t	nxge_ldgv_init_n2(p_nxge_t, int *, int *);
25544961713Sgirish extern nxge_status_t	nxge_ldgv_uninit(p_nxge_t);
25644961713Sgirish extern nxge_status_t	nxge_intr_ldgv_init(p_nxge_t);
25744961713Sgirish extern void		nxge_fm_init(p_nxge_t,
25844961713Sgirish 					ddi_device_acc_attr_t *,
25944961713Sgirish 					ddi_device_acc_attr_t *,
26044961713Sgirish 					ddi_dma_attr_t *);
26144961713Sgirish extern void		nxge_fm_fini(p_nxge_t);
26258324dfcSspeer extern npi_status_t	npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
26344961713Sgirish 
26444961713Sgirish /*
26544961713Sgirish  * Count used to maintain the number of buffers being used
26644961713Sgirish  * by Neptune instances and loaned up to the upper layers.
26744961713Sgirish  */
26844961713Sgirish uint32_t nxge_mblks_pending = 0;
26944961713Sgirish 
27044961713Sgirish /*
27144961713Sgirish  * Device register access attributes for PIO.
27244961713Sgirish  */
27344961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
27444961713Sgirish 	DDI_DEVICE_ATTR_V0,
27544961713Sgirish 	DDI_STRUCTURE_LE_ACC,
27644961713Sgirish 	DDI_STRICTORDER_ACC,
27744961713Sgirish };
27844961713Sgirish 
27944961713Sgirish /*
28044961713Sgirish  * Device descriptor access attributes for DMA.
28144961713Sgirish  */
28244961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
28344961713Sgirish 	DDI_DEVICE_ATTR_V0,
28444961713Sgirish 	DDI_STRUCTURE_LE_ACC,
28544961713Sgirish 	DDI_STRICTORDER_ACC
28644961713Sgirish };
28744961713Sgirish 
28844961713Sgirish /*
28944961713Sgirish  * Device buffer access attributes for DMA.
29044961713Sgirish  */
29144961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
29244961713Sgirish 	DDI_DEVICE_ATTR_V0,
29344961713Sgirish 	DDI_STRUCTURE_BE_ACC,
29444961713Sgirish 	DDI_STRICTORDER_ACC
29544961713Sgirish };
29644961713Sgirish 
29744961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = {
29844961713Sgirish 	DMA_ATTR_V0,		/* version number. */
29944961713Sgirish 	0,			/* low address */
30044961713Sgirish 	0xffffffffffffffff,	/* high address */
30144961713Sgirish 	0xffffffffffffffff,	/* address counter max */
30244961713Sgirish #ifndef NIU_PA_WORKAROUND
30344961713Sgirish 	0x100000,		/* alignment */
30444961713Sgirish #else
30544961713Sgirish 	0x2000,
30644961713Sgirish #endif
30744961713Sgirish 	0xfc00fc,		/* dlim_burstsizes */
30844961713Sgirish 	0x1,			/* minimum transfer size */
30944961713Sgirish 	0xffffffffffffffff,	/* maximum transfer size */
31044961713Sgirish 	0xffffffffffffffff,	/* maximum segment size */
31144961713Sgirish 	1,			/* scatter/gather list length */
31244961713Sgirish 	(unsigned int) 1,	/* granularity */
31344961713Sgirish 	0			/* attribute flags */
31444961713Sgirish };
31544961713Sgirish 
31644961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = {
31744961713Sgirish 	DMA_ATTR_V0,		/* version number. */
31844961713Sgirish 	0,			/* low address */
31944961713Sgirish 	0xffffffffffffffff,	/* high address */
32044961713Sgirish 	0xffffffffffffffff,	/* address counter max */
32144961713Sgirish #if defined(_BIG_ENDIAN)
32244961713Sgirish 	0x2000,			/* alignment */
32344961713Sgirish #else
32444961713Sgirish 	0x1000,			/* alignment */
32544961713Sgirish #endif
32644961713Sgirish 	0xfc00fc,		/* dlim_burstsizes */
32744961713Sgirish 	0x1,			/* minimum transfer size */
32844961713Sgirish 	0xffffffffffffffff,	/* maximum transfer size */
32944961713Sgirish 	0xffffffffffffffff,	/* maximum segment size */
33044961713Sgirish 	5,			/* scatter/gather list length */
33144961713Sgirish 	(unsigned int) 1,	/* granularity */
33244961713Sgirish 	0			/* attribute flags */
33344961713Sgirish };
33444961713Sgirish 
33544961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = {
33644961713Sgirish 	DMA_ATTR_V0,		/* version number. */
33744961713Sgirish 	0,			/* low address */
33844961713Sgirish 	0xffffffffffffffff,	/* high address */
33944961713Sgirish 	0xffffffffffffffff,	/* address counter max */
34044961713Sgirish 	0x2000,			/* alignment */
34144961713Sgirish 	0xfc00fc,		/* dlim_burstsizes */
34244961713Sgirish 	0x1,			/* minimum transfer size */
34344961713Sgirish 	0xffffffffffffffff,	/* maximum transfer size */
34444961713Sgirish 	0xffffffffffffffff,	/* maximum segment size */
34544961713Sgirish 	1,			/* scatter/gather list length */
34644961713Sgirish 	(unsigned int) 1,	/* granularity */
3470e2bd521Ssbehera 	DDI_DMA_RELAXED_ORDERING /* attribute flags */
34844961713Sgirish };
34944961713Sgirish 
35044961713Sgirish ddi_dma_lim_t nxge_dma_limits = {
35144961713Sgirish 	(uint_t)0,		/* dlim_addr_lo */
35244961713Sgirish 	(uint_t)0xffffffff,	/* dlim_addr_hi */
35344961713Sgirish 	(uint_t)0xffffffff,	/* dlim_cntr_max */
35444961713Sgirish 	(uint_t)0xfc00fc,	/* dlim_burstsizes for 32 and 64 bit xfers */
35544961713Sgirish 	0x1,			/* dlim_minxfer */
35644961713Sgirish 	1024			/* dlim_speed */
35744961713Sgirish };
35844961713Sgirish 
35944961713Sgirish dma_method_t nxge_force_dma = DVMA;
36044961713Sgirish 
36144961713Sgirish /*
36244961713Sgirish  * dma chunk sizes.
36344961713Sgirish  *
36444961713Sgirish  * Try to allocate the largest possible size
36544961713Sgirish  * so that fewer number of dma chunks would be managed
36644961713Sgirish  */
36744961713Sgirish #ifdef NIU_PA_WORKAROUND
36844961713Sgirish size_t alloc_sizes [] = {0x2000};
36944961713Sgirish #else
37044961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
37144961713Sgirish 		0x10000, 0x20000, 0x40000, 0x80000,
37230ac2e7bSml 		0x100000, 0x200000, 0x400000, 0x800000,
37330ac2e7bSml 		0x1000000, 0x2000000, 0x4000000};
37444961713Sgirish #endif
37544961713Sgirish 
37644961713Sgirish /*
37744961713Sgirish  * Translate "dev_t" to a pointer to the associated "dev_info_t".
37844961713Sgirish  */
37944961713Sgirish 
38044961713Sgirish static int
38144961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
38244961713Sgirish {
38344961713Sgirish 	p_nxge_t	nxgep = NULL;
38444961713Sgirish 	int		instance;
38544961713Sgirish 	int		status = DDI_SUCCESS;
38644961713Sgirish 	uint8_t		portn;
38758324dfcSspeer 	nxge_mmac_t	*mmac_info;
38844961713Sgirish 
38944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
39044961713Sgirish 
39144961713Sgirish 	/*
39244961713Sgirish 	 * Get the device instance since we'll need to setup
39344961713Sgirish 	 * or retrieve a soft state for this instance.
39444961713Sgirish 	 */
39544961713Sgirish 	instance = ddi_get_instance(dip);
39644961713Sgirish 
39744961713Sgirish 	switch (cmd) {
39844961713Sgirish 	case DDI_ATTACH:
39944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
40044961713Sgirish 		break;
40144961713Sgirish 
40244961713Sgirish 	case DDI_RESUME:
40344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
40444961713Sgirish 		nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
40544961713Sgirish 		if (nxgep == NULL) {
40644961713Sgirish 			status = DDI_FAILURE;
40744961713Sgirish 			break;
40844961713Sgirish 		}
40944961713Sgirish 		if (nxgep->dip != dip) {
41044961713Sgirish 			status = DDI_FAILURE;
41144961713Sgirish 			break;
41244961713Sgirish 		}
41344961713Sgirish 		if (nxgep->suspended == DDI_PM_SUSPEND) {
41444961713Sgirish 			status = ddi_dev_is_needed(nxgep->dip, 0, 1);
41544961713Sgirish 		} else {
41656d930aeSspeer 			status = nxge_resume(nxgep);
41744961713Sgirish 		}
41844961713Sgirish 		goto nxge_attach_exit;
41944961713Sgirish 
42044961713Sgirish 	case DDI_PM_RESUME:
42144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
42244961713Sgirish 		nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
42344961713Sgirish 		if (nxgep == NULL) {
42444961713Sgirish 			status = DDI_FAILURE;
42544961713Sgirish 			break;
42644961713Sgirish 		}
42744961713Sgirish 		if (nxgep->dip != dip) {
42844961713Sgirish 			status = DDI_FAILURE;
42944961713Sgirish 			break;
43044961713Sgirish 		}
43156d930aeSspeer 		status = nxge_resume(nxgep);
43244961713Sgirish 		goto nxge_attach_exit;
43344961713Sgirish 
43444961713Sgirish 	default:
43544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
43644961713Sgirish 		status = DDI_FAILURE;
43744961713Sgirish 		goto nxge_attach_exit;
43844961713Sgirish 	}
43944961713Sgirish 
44044961713Sgirish 
44144961713Sgirish 	if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
44244961713Sgirish 		status = DDI_FAILURE;
44344961713Sgirish 		goto nxge_attach_exit;
44444961713Sgirish 	}
44544961713Sgirish 
44644961713Sgirish 	nxgep = ddi_get_soft_state(nxge_list, instance);
44744961713Sgirish 	if (nxgep == NULL) {
4482e59129aSraghus 		status = NXGE_ERROR;
4492e59129aSraghus 		goto nxge_attach_fail2;
45044961713Sgirish 	}
45144961713Sgirish 
45298ecde52Stm 	nxgep->nxge_magic = NXGE_MAGIC;
45398ecde52Stm 
45444961713Sgirish 	nxgep->drv_state = 0;
45544961713Sgirish 	nxgep->dip = dip;
45644961713Sgirish 	nxgep->instance = instance;
45744961713Sgirish 	nxgep->p_dip = ddi_get_parent(dip);
45844961713Sgirish 	nxgep->nxge_debug_level = nxge_debug_level;
45944961713Sgirish 	npi_debug_level = nxge_debug_level;
46044961713Sgirish 
46144961713Sgirish 	nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_dev_desc_dma_acc_attr,
46244961713Sgirish 				&nxge_rx_dma_attr);
46344961713Sgirish 
46444961713Sgirish 	status = nxge_map_regs(nxgep);
46544961713Sgirish 	if (status != NXGE_OK) {
46644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
4672e59129aSraghus 		goto nxge_attach_fail3;
46844961713Sgirish 	}
46944961713Sgirish 
47044961713Sgirish 	status = nxge_init_common_dev(nxgep);
47144961713Sgirish 	if (status != NXGE_OK) {
47244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
47344961713Sgirish 			"nxge_init_common_dev failed"));
4742e59129aSraghus 		goto nxge_attach_fail4;
47544961713Sgirish 	}
47644961713Sgirish 
47759ac0c16Sdavemq 	if (nxgep->niu_type == NEPTUNE_2_10GF) {
47859ac0c16Sdavemq 		if (nxgep->function_num > 1) {
479*4202ea4bSsbehera 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported"
48059ac0c16Sdavemq 			    " function %d. Only functions 0 and 1 are "
48159ac0c16Sdavemq 			    "supported for this card.", nxgep->function_num));
48259ac0c16Sdavemq 			status = NXGE_ERROR;
4832e59129aSraghus 			goto nxge_attach_fail4;
48459ac0c16Sdavemq 		}
48559ac0c16Sdavemq 	}
48659ac0c16Sdavemq 
48744961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
48844961713Sgirish 	nxgep->mac.portnum = portn;
48944961713Sgirish 	if ((portn == 0) || (portn == 1))
49044961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_XMAC;
49144961713Sgirish 	else
49244961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
49358324dfcSspeer 	/*
49458324dfcSspeer 	 * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC)
49558324dfcSspeer 	 * internally, the rest 2 ports use BMAC (1G "Big" MAC).
49658324dfcSspeer 	 * The two types of MACs have different characterizations.
49758324dfcSspeer 	 */
49858324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
49958324dfcSspeer 	if (nxgep->function_num < 2) {
50058324dfcSspeer 		mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY;
50158324dfcSspeer 		mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY;
50258324dfcSspeer 	} else {
50358324dfcSspeer 		mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY;
50458324dfcSspeer 		mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY;
50558324dfcSspeer 	}
50644961713Sgirish 	/*
50744961713Sgirish 	 * Setup the Ndd parameters for the this instance.
50844961713Sgirish 	 */
50944961713Sgirish 	nxge_init_param(nxgep);
51044961713Sgirish 
51144961713Sgirish 	/*
51244961713Sgirish 	 * Setup Register Tracing Buffer.
51344961713Sgirish 	 */
51444961713Sgirish 	npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
51544961713Sgirish 
51644961713Sgirish 	/* init stats ptr */
51744961713Sgirish 	nxge_init_statsp(nxgep);
51856d930aeSspeer 
5192e59129aSraghus 	/*
5202e59129aSraghus 	 * read the vpd info from the eeprom into local data
5212e59129aSraghus 	 * structure and check for the VPD info validity
5222e59129aSraghus 	 */
5232e59129aSraghus 	nxge_vpd_info_get(nxgep);
52456d930aeSspeer 
5252e59129aSraghus 	status = nxge_xcvr_find(nxgep);
52644961713Sgirish 
52744961713Sgirish 	if (status != NXGE_OK) {
52856d930aeSspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
52944961713Sgirish 				    " Couldn't determine card type"
53044961713Sgirish 				    " .... exit "));
5312e59129aSraghus 		goto nxge_attach_fail5;
53244961713Sgirish 	}
53344961713Sgirish 
53444961713Sgirish 	status = nxge_get_config_properties(nxgep);
53544961713Sgirish 
53644961713Sgirish 	if (status != NXGE_OK) {
53744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "get_hw create failed"));
53844961713Sgirish 		goto nxge_attach_fail;
53944961713Sgirish 	}
54044961713Sgirish 
54144961713Sgirish 	/*
54244961713Sgirish 	 * Setup the Kstats for the driver.
54344961713Sgirish 	 */
54444961713Sgirish 	nxge_setup_kstats(nxgep);
54544961713Sgirish 
54644961713Sgirish 	nxge_setup_param(nxgep);
54744961713Sgirish 
54844961713Sgirish 	status = nxge_setup_system_dma_pages(nxgep);
54944961713Sgirish 	if (status != NXGE_OK) {
55044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
55144961713Sgirish 		goto nxge_attach_fail;
55244961713Sgirish 	}
55344961713Sgirish 
55444961713Sgirish #if	defined(sun4v)
55544961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
55644961713Sgirish 		nxgep->niu_hsvc_available = B_FALSE;
55744961713Sgirish 		bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t));
55844961713Sgirish 		if ((status =
55944961713Sgirish 			hsvc_register(&nxgep->niu_hsvc,
56044961713Sgirish 					&nxgep->niu_min_ver)) != 0) {
56144961713Sgirish 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
56244961713Sgirish 					"nxge_attach: "
56344961713Sgirish 					"%s: cannot negotiate "
56444961713Sgirish 					"hypervisor services "
56544961713Sgirish 					"revision %d "
56644961713Sgirish 					"group: 0x%lx "
56744961713Sgirish 					"major: 0x%lx minor: 0x%lx "
56844961713Sgirish 					"errno: %d",
56944961713Sgirish 					niu_hsvc.hsvc_modname,
57044961713Sgirish 					niu_hsvc.hsvc_rev,
57144961713Sgirish 					niu_hsvc.hsvc_group,
57244961713Sgirish 					niu_hsvc.hsvc_major,
57344961713Sgirish 					niu_hsvc.hsvc_minor,
57444961713Sgirish 					status));
57544961713Sgirish 				status = DDI_FAILURE;
57644961713Sgirish 				goto nxge_attach_fail;
57744961713Sgirish 		}
57844961713Sgirish 
57944961713Sgirish 		nxgep->niu_hsvc_available = B_TRUE;
58044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
58144961713Sgirish 			"NIU Hypervisor service enabled"));
58244961713Sgirish 	}
58344961713Sgirish #endif
58444961713Sgirish 
58544961713Sgirish 	nxge_hw_id_init(nxgep);
58644961713Sgirish 	nxge_hw_init_niu_common(nxgep);
58744961713Sgirish 
58844961713Sgirish 	status = nxge_setup_mutexes(nxgep);
58944961713Sgirish 	if (status != NXGE_OK) {
59044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
59144961713Sgirish 		goto nxge_attach_fail;
59244961713Sgirish 	}
59344961713Sgirish 
59444961713Sgirish 	status = nxge_setup_dev(nxgep);
59544961713Sgirish 	if (status != DDI_SUCCESS) {
59644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
59744961713Sgirish 		goto nxge_attach_fail;
59844961713Sgirish 	}
59944961713Sgirish 
60044961713Sgirish 	status = nxge_add_intrs(nxgep);
60144961713Sgirish 	if (status != DDI_SUCCESS) {
60244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
60344961713Sgirish 		goto nxge_attach_fail;
60444961713Sgirish 	}
60544961713Sgirish 	status = nxge_add_soft_intrs(nxgep);
60644961713Sgirish 	if (status != DDI_SUCCESS) {
60744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "add_soft_intr failed"));
60844961713Sgirish 		goto nxge_attach_fail;
60944961713Sgirish 	}
61044961713Sgirish 
61144961713Sgirish 	/*
61244961713Sgirish 	 * Enable interrupts.
61344961713Sgirish 	 */
61444961713Sgirish 	nxge_intrs_enable(nxgep);
61544961713Sgirish 
6162e59129aSraghus 	if ((status = nxge_mac_register(nxgep)) != NXGE_OK) {
61744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
61844961713Sgirish 			"unable to register to mac layer (%d)", status));
61944961713Sgirish 		goto nxge_attach_fail;
62044961713Sgirish 	}
62144961713Sgirish 
62244961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
62344961713Sgirish 
62444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "registered to mac (instance %d)",
62544961713Sgirish 		instance));
62644961713Sgirish 
62744961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
62844961713Sgirish 
62944961713Sgirish 	goto nxge_attach_exit;
63044961713Sgirish 
63144961713Sgirish nxge_attach_fail:
63244961713Sgirish 	nxge_unattach(nxgep);
6332e59129aSraghus 	goto nxge_attach_fail1;
6342e59129aSraghus 
6352e59129aSraghus nxge_attach_fail5:
6362e59129aSraghus 	/*
6372e59129aSraghus 	 * Tear down the ndd parameters setup.
6382e59129aSraghus 	 */
6392e59129aSraghus 	nxge_destroy_param(nxgep);
6402e59129aSraghus 
6412e59129aSraghus 	/*
6422e59129aSraghus 	 * Tear down the kstat setup.
6432e59129aSraghus 	 */
6442e59129aSraghus 	nxge_destroy_kstats(nxgep);
6452e59129aSraghus 
6462e59129aSraghus nxge_attach_fail4:
6472e59129aSraghus 	if (nxgep->nxge_hw_p) {
6482e59129aSraghus 		nxge_uninit_common_dev(nxgep);
6492e59129aSraghus 		nxgep->nxge_hw_p = NULL;
6502e59129aSraghus 	}
6512e59129aSraghus 
6522e59129aSraghus nxge_attach_fail3:
6532e59129aSraghus 	/*
6542e59129aSraghus 	 * Unmap the register setup.
6552e59129aSraghus 	 */
6562e59129aSraghus 	nxge_unmap_regs(nxgep);
6572e59129aSraghus 
6582e59129aSraghus 	nxge_fm_fini(nxgep);
6592e59129aSraghus 
6602e59129aSraghus nxge_attach_fail2:
6612e59129aSraghus 	ddi_soft_state_free(nxge_list, nxgep->instance);
6622e59129aSraghus 
6632e59129aSraghus nxge_attach_fail1:
66456d930aeSspeer 	if (status != NXGE_OK)
66556d930aeSspeer 		status = (NXGE_ERROR | NXGE_DDI_FAILED);
66644961713Sgirish 	nxgep = NULL;
66744961713Sgirish 
66844961713Sgirish nxge_attach_exit:
66944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
67044961713Sgirish 		status));
67144961713Sgirish 
67244961713Sgirish 	return (status);
67344961713Sgirish }
67444961713Sgirish 
67544961713Sgirish static int
67644961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
67744961713Sgirish {
67844961713Sgirish 	int 		status = DDI_SUCCESS;
67944961713Sgirish 	int 		instance;
68044961713Sgirish 	p_nxge_t 	nxgep = NULL;
68144961713Sgirish 
68244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
68344961713Sgirish 	instance = ddi_get_instance(dip);
68444961713Sgirish 	nxgep = ddi_get_soft_state(nxge_list, instance);
68544961713Sgirish 	if (nxgep == NULL) {
68644961713Sgirish 		status = DDI_FAILURE;
68744961713Sgirish 		goto nxge_detach_exit;
68844961713Sgirish 	}
68944961713Sgirish 
69044961713Sgirish 	switch (cmd) {
69144961713Sgirish 	case DDI_DETACH:
69244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
69344961713Sgirish 		break;
69444961713Sgirish 
69544961713Sgirish 	case DDI_PM_SUSPEND:
69644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
69744961713Sgirish 		nxgep->suspended = DDI_PM_SUSPEND;
69844961713Sgirish 		nxge_suspend(nxgep);
69944961713Sgirish 		break;
70044961713Sgirish 
70144961713Sgirish 	case DDI_SUSPEND:
70244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
70344961713Sgirish 		if (nxgep->suspended != DDI_PM_SUSPEND) {
70444961713Sgirish 			nxgep->suspended = DDI_SUSPEND;
70544961713Sgirish 			nxge_suspend(nxgep);
70644961713Sgirish 		}
70744961713Sgirish 		break;
70844961713Sgirish 
70944961713Sgirish 	default:
71044961713Sgirish 		status = DDI_FAILURE;
71144961713Sgirish 	}
71244961713Sgirish 
71344961713Sgirish 	if (cmd != DDI_DETACH)
71444961713Sgirish 		goto nxge_detach_exit;
71544961713Sgirish 
71644961713Sgirish 	/*
71744961713Sgirish 	 * Stop the xcvr polling.
71844961713Sgirish 	 */
71944961713Sgirish 	nxgep->suspended = cmd;
72044961713Sgirish 
72144961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
72244961713Sgirish 
72344961713Sgirish 	if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
72444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72544961713Sgirish 			"<== nxge_detach status = 0x%08X", status));
72644961713Sgirish 		return (DDI_FAILURE);
72744961713Sgirish 	}
72844961713Sgirish 
72944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
73044961713Sgirish 		"<== nxge_detach (mac_unregister) status = 0x%08X", status));
73144961713Sgirish 
73244961713Sgirish 	nxge_unattach(nxgep);
73344961713Sgirish 	nxgep = NULL;
73444961713Sgirish 
73544961713Sgirish nxge_detach_exit:
73644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X",
73744961713Sgirish 		status));
73844961713Sgirish 
73944961713Sgirish 	return (status);
74044961713Sgirish }
74144961713Sgirish 
74244961713Sgirish static void
74344961713Sgirish nxge_unattach(p_nxge_t nxgep)
74444961713Sgirish {
74544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach"));
74644961713Sgirish 
74744961713Sgirish 	if (nxgep == NULL || nxgep->dev_regs == NULL) {
74844961713Sgirish 		return;
74944961713Sgirish 	}
75044961713Sgirish 
75198ecde52Stm 	nxgep->nxge_magic = 0;
75298ecde52Stm 
75344961713Sgirish 	if (nxgep->nxge_timerid) {
75444961713Sgirish 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
75544961713Sgirish 		nxgep->nxge_timerid = 0;
75644961713Sgirish 	}
75744961713Sgirish 
75853560810Ssbehera 	if (nxgep->nxge_hw_p) {
75953560810Ssbehera 		nxge_uninit_common_dev(nxgep);
76053560810Ssbehera 		nxgep->nxge_hw_p = NULL;
76153560810Ssbehera 	}
76253560810Ssbehera 
76344961713Sgirish #if	defined(sun4v)
76444961713Sgirish 	if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) {
76544961713Sgirish 		(void) hsvc_unregister(&nxgep->niu_hsvc);
76644961713Sgirish 		nxgep->niu_hsvc_available = B_FALSE;
76744961713Sgirish 	}
76844961713Sgirish #endif
76944961713Sgirish 	/*
77044961713Sgirish 	 * Stop any further interrupts.
77144961713Sgirish 	 */
77244961713Sgirish 	nxge_remove_intrs(nxgep);
77344961713Sgirish 
77444961713Sgirish 	/* remove soft interrups */
77544961713Sgirish 	nxge_remove_soft_intrs(nxgep);
77644961713Sgirish 
77744961713Sgirish 	/*
77844961713Sgirish 	 * Stop the device and free resources.
77944961713Sgirish 	 */
78044961713Sgirish 	nxge_destroy_dev(nxgep);
78144961713Sgirish 
78244961713Sgirish 	/*
78344961713Sgirish 	 * Tear down the ndd parameters setup.
78444961713Sgirish 	 */
78544961713Sgirish 	nxge_destroy_param(nxgep);
78644961713Sgirish 
78744961713Sgirish 	/*
78844961713Sgirish 	 * Tear down the kstat setup.
78944961713Sgirish 	 */
79044961713Sgirish 	nxge_destroy_kstats(nxgep);
79144961713Sgirish 
79244961713Sgirish 	/*
79344961713Sgirish 	 * Destroy all mutexes.
79444961713Sgirish 	 */
79544961713Sgirish 	nxge_destroy_mutexes(nxgep);
79644961713Sgirish 
79744961713Sgirish 	/*
79844961713Sgirish 	 * Remove the list of ndd parameters which
79944961713Sgirish 	 * were setup during attach.
80044961713Sgirish 	 */
80144961713Sgirish 	if (nxgep->dip) {
80244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, OBP_CTL,
80344961713Sgirish 				    " nxge_unattach: remove all properties"));
80444961713Sgirish 
80544961713Sgirish 		(void) ddi_prop_remove_all(nxgep->dip);
80644961713Sgirish 	}
80744961713Sgirish 
80844961713Sgirish #if NXGE_PROPERTY
80944961713Sgirish 	nxge_remove_hard_properties(nxgep);
81044961713Sgirish #endif
81144961713Sgirish 
81244961713Sgirish 	/*
81344961713Sgirish 	 * Unmap the register setup.
81444961713Sgirish 	 */
81544961713Sgirish 	nxge_unmap_regs(nxgep);
81644961713Sgirish 
81744961713Sgirish 	nxge_fm_fini(nxgep);
81844961713Sgirish 
81944961713Sgirish 	ddi_soft_state_free(nxge_list, nxgep->instance);
82044961713Sgirish 
82144961713Sgirish 	NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach"));
82244961713Sgirish }
82344961713Sgirish 
82444961713Sgirish static char n2_siu_name[] = "niu";
82544961713Sgirish 
82644961713Sgirish static nxge_status_t
82744961713Sgirish nxge_map_regs(p_nxge_t nxgep)
82844961713Sgirish {
82944961713Sgirish 	int		ddi_status = DDI_SUCCESS;
83044961713Sgirish 	p_dev_regs_t 	dev_regs;
83144961713Sgirish 	char		buf[MAXPATHLEN + 1];
83244961713Sgirish 	char 		*devname;
83344961713Sgirish #ifdef	NXGE_DEBUG
83444961713Sgirish 	char 		*sysname;
83544961713Sgirish #endif
83644961713Sgirish 	off_t		regsize;
83744961713Sgirish 	nxge_status_t	status = NXGE_OK;
83814ea4bb7Ssd #if !defined(_BIG_ENDIAN)
83914ea4bb7Ssd 	off_t pci_offset;
84014ea4bb7Ssd 	uint16_t pcie_devctl;
84114ea4bb7Ssd #endif
84244961713Sgirish 
84344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs"));
84444961713Sgirish 	nxgep->dev_regs = NULL;
84544961713Sgirish 	dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
84644961713Sgirish 	dev_regs->nxge_regh = NULL;
84744961713Sgirish 	dev_regs->nxge_pciregh = NULL;
84844961713Sgirish 	dev_regs->nxge_msix_regh = NULL;
84944961713Sgirish 	dev_regs->nxge_vir_regh = NULL;
85044961713Sgirish 	dev_regs->nxge_vir2_regh = NULL;
85159ac0c16Sdavemq 	nxgep->niu_type = NIU_TYPE_NONE;
85244961713Sgirish 
85344961713Sgirish 	devname = ddi_pathname(nxgep->dip, buf);
85444961713Sgirish 	ASSERT(strlen(devname) > 0);
85544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
85644961713Sgirish 		"nxge_map_regs: pathname devname %s", devname));
85744961713Sgirish 
85844961713Sgirish 	if (strstr(devname, n2_siu_name)) {
85944961713Sgirish 		/* N2/NIU */
86044961713Sgirish 		nxgep->niu_type = N2_NIU;
86144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
86244961713Sgirish 			"nxge_map_regs: N2/NIU devname %s", devname));
86344961713Sgirish 		/* get function number */
86444961713Sgirish 		nxgep->function_num =
86544961713Sgirish 			(devname[strlen(devname) -1] == '1' ? 1 : 0);
86644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
86744961713Sgirish 			"nxge_map_regs: N2/NIU function number %d",
86844961713Sgirish 			nxgep->function_num));
86944961713Sgirish 	} else {
87044961713Sgirish 		int		*prop_val;
87144961713Sgirish 		uint_t 		prop_len;
87244961713Sgirish 		uint8_t 	func_num;
87344961713Sgirish 
87444961713Sgirish 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
87544961713Sgirish 				0, "reg",
87644961713Sgirish 				&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
87744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, VPD_CTL,
87844961713Sgirish 				"Reg property not found"));
87944961713Sgirish 			ddi_status = DDI_FAILURE;
88044961713Sgirish 			goto nxge_map_regs_fail0;
88144961713Sgirish 
88244961713Sgirish 		} else {
88344961713Sgirish 			func_num = (prop_val[0] >> 8) & 0x7;
88444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
88544961713Sgirish 				"Reg property found: fun # %d",
88644961713Sgirish 				func_num));
88744961713Sgirish 			nxgep->function_num = func_num;
88844961713Sgirish 			ddi_prop_free(prop_val);
88944961713Sgirish 		}
89044961713Sgirish 	}
89144961713Sgirish 
89244961713Sgirish 	switch (nxgep->niu_type) {
89344961713Sgirish 	default:
89444961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 0, &regsize);
89544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
89644961713Sgirish 			"nxge_map_regs: pci config size 0x%x", regsize));
89744961713Sgirish 
89844961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 0,
89944961713Sgirish 			(caddr_t *)&(dev_regs->nxge_pciregp), 0, 0,
90044961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh);
90144961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
90244961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
90344961713Sgirish 				"ddi_map_regs, nxge bus config regs failed"));
90444961713Sgirish 			goto nxge_map_regs_fail0;
90544961713Sgirish 		}
90644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
90744961713Sgirish 			"nxge_map_reg: PCI config addr 0x%0llx "
90844961713Sgirish 			" handle 0x%0llx", dev_regs->nxge_pciregp,
90944961713Sgirish 			dev_regs->nxge_pciregh));
91044961713Sgirish 			/*
91144961713Sgirish 			 * IMP IMP
91244961713Sgirish 			 * workaround  for bit swapping bug in HW
91344961713Sgirish 			 * which ends up in no-snoop = yes
91444961713Sgirish 			 * resulting, in DMA not synched properly
91544961713Sgirish 			 */
91644961713Sgirish #if !defined(_BIG_ENDIAN)
91714ea4bb7Ssd 		/* workarounds for x86 systems */
91814ea4bb7Ssd 		pci_offset = 0x80 + PCIE_DEVCTL;
91914ea4bb7Ssd 		pcie_devctl = 0x0;
92014ea4bb7Ssd 		pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP;
92114ea4bb7Ssd 		pcie_devctl |= PCIE_DEVCTL_RO_EN;
92214ea4bb7Ssd 		pci_config_put16(dev_regs->nxge_pciregh, pci_offset,
92314ea4bb7Ssd 				    pcie_devctl);
92444961713Sgirish #endif
92514ea4bb7Ssd 
92644961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
92744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
92844961713Sgirish 			"nxge_map_regs: pio size 0x%x", regsize));
92944961713Sgirish 		/* set up the device mapped register */
93044961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
93144961713Sgirish 			(caddr_t *)&(dev_regs->nxge_regp), 0, 0,
93244961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
93344961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
93444961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
93544961713Sgirish 				"ddi_map_regs for Neptune global reg failed"));
93644961713Sgirish 			goto nxge_map_regs_fail1;
93744961713Sgirish 		}
93844961713Sgirish 
93944961713Sgirish 		/* set up the msi/msi-x mapped register */
94044961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
94144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
94244961713Sgirish 			"nxge_map_regs: msix size 0x%x", regsize));
94344961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
94444961713Sgirish 			(caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0,
94544961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh);
94644961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
94744961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
94844961713Sgirish 				"ddi_map_regs for msi reg failed"));
94944961713Sgirish 			goto nxge_map_regs_fail2;
95044961713Sgirish 		}
95144961713Sgirish 
95244961713Sgirish 		/* set up the vio region mapped register */
95344961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
95444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
95544961713Sgirish 			"nxge_map_regs: vio size 0x%x", regsize));
95644961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
95744961713Sgirish 			(caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
95844961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
95944961713Sgirish 
96044961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
96144961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
96244961713Sgirish 				"ddi_map_regs for nxge vio reg failed"));
96344961713Sgirish 			goto nxge_map_regs_fail3;
96444961713Sgirish 		}
96544961713Sgirish 		nxgep->dev_regs = dev_regs;
96644961713Sgirish 
96744961713Sgirish 		NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh);
96844961713Sgirish 		NPI_PCI_ADD_HANDLE_SET(nxgep,
96944961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_pciregp);
97044961713Sgirish 		NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh);
97144961713Sgirish 		NPI_MSI_ADD_HANDLE_SET(nxgep,
97244961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_msix_regp);
97344961713Sgirish 
97444961713Sgirish 		NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
97544961713Sgirish 		NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
97644961713Sgirish 
97744961713Sgirish 		NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
97844961713Sgirish 		NPI_REG_ADD_HANDLE_SET(nxgep,
97944961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_regp);
98044961713Sgirish 
98144961713Sgirish 		NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
98244961713Sgirish 		NPI_VREG_ADD_HANDLE_SET(nxgep,
98344961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_vir_regp);
98444961713Sgirish 
98544961713Sgirish 		break;
98644961713Sgirish 
98744961713Sgirish 	case N2_NIU:
98844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU"));
98944961713Sgirish 		/*
99044961713Sgirish 		 * Set up the device mapped register (FWARC 2006/556)
99144961713Sgirish 		 * (changed back to 1: reg starts at 1!)
99244961713Sgirish 		 */
99344961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
99444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
99544961713Sgirish 			"nxge_map_regs: dev size 0x%x", regsize));
99644961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
99744961713Sgirish 				(caddr_t *)&(dev_regs->nxge_regp), 0, 0,
99844961713Sgirish 				&nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
99944961713Sgirish 
100044961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
100144961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
100244961713Sgirish 				"ddi_map_regs for N2/NIU, global reg failed "));
100344961713Sgirish 			goto nxge_map_regs_fail1;
100444961713Sgirish 		}
100544961713Sgirish 
100644961713Sgirish 		/* set up the vio region mapped register */
100744961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
100844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
100944961713Sgirish 			"nxge_map_regs: vio (1) size 0x%x", regsize));
101044961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
101144961713Sgirish 			(caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
101244961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
101344961713Sgirish 
101444961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
101544961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
101644961713Sgirish 				"ddi_map_regs for nxge vio reg failed"));
101744961713Sgirish 			goto nxge_map_regs_fail2;
101844961713Sgirish 		}
101944961713Sgirish 		/* set up the vio region mapped register */
102044961713Sgirish 		(void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
102144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
102244961713Sgirish 			"nxge_map_regs: vio (3) size 0x%x", regsize));
102344961713Sgirish 		ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
102444961713Sgirish 			(caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0,
102544961713Sgirish 			&nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh);
102644961713Sgirish 
102744961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
102844961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
102944961713Sgirish 				"ddi_map_regs for nxge vio2 reg failed"));
103044961713Sgirish 			goto nxge_map_regs_fail3;
103144961713Sgirish 		}
103244961713Sgirish 		nxgep->dev_regs = dev_regs;
103344961713Sgirish 
103444961713Sgirish 		NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
103544961713Sgirish 		NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
103644961713Sgirish 
103744961713Sgirish 		NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
103844961713Sgirish 		NPI_REG_ADD_HANDLE_SET(nxgep,
103944961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_regp);
104044961713Sgirish 
104144961713Sgirish 		NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
104244961713Sgirish 		NPI_VREG_ADD_HANDLE_SET(nxgep,
104344961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_vir_regp);
104444961713Sgirish 
104544961713Sgirish 		NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh);
104644961713Sgirish 		NPI_V2REG_ADD_HANDLE_SET(nxgep,
104744961713Sgirish 			(npi_reg_ptr_t)dev_regs->nxge_vir2_regp);
104844961713Sgirish 
104944961713Sgirish 		break;
105044961713Sgirish 	}
105144961713Sgirish 
105244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx "
105344961713Sgirish 		" handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh));
105444961713Sgirish 
105544961713Sgirish 	goto nxge_map_regs_exit;
105644961713Sgirish nxge_map_regs_fail3:
105744961713Sgirish 	if (dev_regs->nxge_msix_regh) {
105844961713Sgirish 		ddi_regs_map_free(&dev_regs->nxge_msix_regh);
105944961713Sgirish 	}
106044961713Sgirish 	if (dev_regs->nxge_vir_regh) {
106144961713Sgirish 		ddi_regs_map_free(&dev_regs->nxge_regh);
106244961713Sgirish 	}
106344961713Sgirish nxge_map_regs_fail2:
106444961713Sgirish 	if (dev_regs->nxge_regh) {
106544961713Sgirish 		ddi_regs_map_free(&dev_regs->nxge_regh);
106644961713Sgirish 	}
106744961713Sgirish nxge_map_regs_fail1:
106844961713Sgirish 	if (dev_regs->nxge_pciregh) {
106944961713Sgirish 		ddi_regs_map_free(&dev_regs->nxge_pciregh);
107044961713Sgirish 	}
107144961713Sgirish nxge_map_regs_fail0:
107244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory"));
107344961713Sgirish 	kmem_free(dev_regs, sizeof (dev_regs_t));
107444961713Sgirish 
107544961713Sgirish nxge_map_regs_exit:
107644961713Sgirish 	if (ddi_status != DDI_SUCCESS)
107744961713Sgirish 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
107844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs"));
107944961713Sgirish 	return (status);
108044961713Sgirish }
108144961713Sgirish 
108244961713Sgirish static void
108344961713Sgirish nxge_unmap_regs(p_nxge_t nxgep)
108444961713Sgirish {
108544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs"));
108644961713Sgirish 	if (nxgep->dev_regs) {
108744961713Sgirish 		if (nxgep->dev_regs->nxge_pciregh) {
108844961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
108944961713Sgirish 				"==> nxge_unmap_regs: bus"));
109044961713Sgirish 			ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh);
109144961713Sgirish 			nxgep->dev_regs->nxge_pciregh = NULL;
109244961713Sgirish 		}
109344961713Sgirish 		if (nxgep->dev_regs->nxge_regh) {
109444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
109544961713Sgirish 				"==> nxge_unmap_regs: device registers"));
109644961713Sgirish 			ddi_regs_map_free(&nxgep->dev_regs->nxge_regh);
109744961713Sgirish 			nxgep->dev_regs->nxge_regh = NULL;
109844961713Sgirish 		}
109944961713Sgirish 		if (nxgep->dev_regs->nxge_msix_regh) {
110044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
110144961713Sgirish 				"==> nxge_unmap_regs: device interrupts"));
110244961713Sgirish 			ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh);
110344961713Sgirish 			nxgep->dev_regs->nxge_msix_regh = NULL;
110444961713Sgirish 		}
110544961713Sgirish 		if (nxgep->dev_regs->nxge_vir_regh) {
110644961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
110744961713Sgirish 				"==> nxge_unmap_regs: vio region"));
110844961713Sgirish 			ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh);
110944961713Sgirish 			nxgep->dev_regs->nxge_vir_regh = NULL;
111044961713Sgirish 		}
111144961713Sgirish 		if (nxgep->dev_regs->nxge_vir2_regh) {
111244961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
111344961713Sgirish 				"==> nxge_unmap_regs: vio2 region"));
111444961713Sgirish 			ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh);
111544961713Sgirish 			nxgep->dev_regs->nxge_vir2_regh = NULL;
111644961713Sgirish 		}
111744961713Sgirish 
111844961713Sgirish 		kmem_free(nxgep->dev_regs, sizeof (dev_regs_t));
111944961713Sgirish 		nxgep->dev_regs = NULL;
112044961713Sgirish 	}
112144961713Sgirish 
112244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs"));
112344961713Sgirish }
112444961713Sgirish 
112544961713Sgirish static nxge_status_t
112644961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep)
112744961713Sgirish {
112844961713Sgirish 	int ddi_status = DDI_SUCCESS;
112944961713Sgirish 	nxge_status_t status = NXGE_OK;
113044961713Sgirish 	nxge_classify_t *classify_ptr;
113144961713Sgirish 	int partition;
113244961713Sgirish 
113344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes"));
113444961713Sgirish 
113544961713Sgirish 	/*
113644961713Sgirish 	 * Get the interrupt cookie so the mutexes can be
113758324dfcSspeer 	 * Initialized.
113844961713Sgirish 	 */
113944961713Sgirish 	ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0,
114044961713Sgirish 					&nxgep->interrupt_cookie);
114144961713Sgirish 	if (ddi_status != DDI_SUCCESS) {
114244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
114344961713Sgirish 			"<== nxge_setup_mutexes: failed 0x%x", ddi_status));
114444961713Sgirish 		goto nxge_setup_mutexes_exit;
114544961713Sgirish 	}
114644961713Sgirish 
114798ecde52Stm 	cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL);
114898ecde52Stm 	MUTEX_INIT(&nxgep->poll_lock, NULL,
114998ecde52Stm 	    MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
115098ecde52Stm 
115144961713Sgirish 	/*
115298ecde52Stm 	 * Initialize mutexes for this device.
115344961713Sgirish 	 */
115444961713Sgirish 	MUTEX_INIT(nxgep->genlock, NULL,
115544961713Sgirish 		MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
115644961713Sgirish 	MUTEX_INIT(&nxgep->ouraddr_lock, NULL,
115744961713Sgirish 		MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
115844961713Sgirish 	MUTEX_INIT(&nxgep->mif_lock, NULL,
115944961713Sgirish 		MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
116044961713Sgirish 	RW_INIT(&nxgep->filter_lock, NULL,
116144961713Sgirish 		RW_DRIVER, (void *)nxgep->interrupt_cookie);
116244961713Sgirish 
116344961713Sgirish 	classify_ptr = &nxgep->classifier;
116444961713Sgirish 		/*
116544961713Sgirish 		 * FFLP Mutexes are never used in interrupt context
116644961713Sgirish 		 * as fflp operation can take very long time to
116744961713Sgirish 		 * complete and hence not suitable to invoke from interrupt
116844961713Sgirish 		 * handlers.
116944961713Sgirish 		 */
117044961713Sgirish 	MUTEX_INIT(&classify_ptr->tcam_lock, NULL,
117159ac0c16Sdavemq 	    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
11722e59129aSraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
117344961713Sgirish 		MUTEX_INIT(&classify_ptr->fcram_lock, NULL,
117459ac0c16Sdavemq 		    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
117544961713Sgirish 		for (partition = 0; partition < MAX_PARTITION; partition++) {
117644961713Sgirish 			MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL,
117744961713Sgirish 			    NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
117844961713Sgirish 		}
117944961713Sgirish 	}
118044961713Sgirish 
118144961713Sgirish nxge_setup_mutexes_exit:
118244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
118359ac0c16Sdavemq 	    "<== nxge_setup_mutexes status = %x", status));
118444961713Sgirish 
118544961713Sgirish 	if (ddi_status != DDI_SUCCESS)
118644961713Sgirish 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
118744961713Sgirish 
118844961713Sgirish 	return (status);
118944961713Sgirish }
119044961713Sgirish 
119144961713Sgirish static void
119244961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep)
119344961713Sgirish {
119444961713Sgirish 	int partition;
119544961713Sgirish 	nxge_classify_t *classify_ptr;
119644961713Sgirish 
119744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes"));
119844961713Sgirish 	RW_DESTROY(&nxgep->filter_lock);
119944961713Sgirish 	MUTEX_DESTROY(&nxgep->mif_lock);
120044961713Sgirish 	MUTEX_DESTROY(&nxgep->ouraddr_lock);
120144961713Sgirish 	MUTEX_DESTROY(nxgep->genlock);
120244961713Sgirish 
120344961713Sgirish 	classify_ptr = &nxgep->classifier;
120444961713Sgirish 	MUTEX_DESTROY(&classify_ptr->tcam_lock);
120544961713Sgirish 
120698ecde52Stm 	/* Destroy all polling resources. */
120798ecde52Stm 	MUTEX_DESTROY(&nxgep->poll_lock);
120898ecde52Stm 	cv_destroy(&nxgep->poll_cv);
120998ecde52Stm 
121098ecde52Stm 	/* free data structures, based on HW type */
12112e59129aSraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
121244961713Sgirish 		MUTEX_DESTROY(&classify_ptr->fcram_lock);
121344961713Sgirish 		for (partition = 0; partition < MAX_PARTITION; partition++) {
121444961713Sgirish 			MUTEX_DESTROY(&classify_ptr->hash_lock[partition]);
121544961713Sgirish 		}
121644961713Sgirish 	}
121744961713Sgirish 
121844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes"));
121944961713Sgirish }
122044961713Sgirish 
122144961713Sgirish nxge_status_t
122244961713Sgirish nxge_init(p_nxge_t nxgep)
122344961713Sgirish {
122444961713Sgirish 	nxge_status_t	status = NXGE_OK;
122544961713Sgirish 
122644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init"));
122744961713Sgirish 
122814ea4bb7Ssd 	if (nxgep->drv_state & STATE_HW_INITIALIZED) {
122914ea4bb7Ssd 		return (status);
123014ea4bb7Ssd 	}
123114ea4bb7Ssd 
123244961713Sgirish 	/*
123344961713Sgirish 	 * Allocate system memory for the receive/transmit buffer blocks
123444961713Sgirish 	 * and receive/transmit descriptor rings.
123544961713Sgirish 	 */
123644961713Sgirish 	status = nxge_alloc_mem_pool(nxgep);
123744961713Sgirish 	if (status != NXGE_OK) {
123844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n"));
123944961713Sgirish 		goto nxge_init_fail1;
124044961713Sgirish 	}
124144961713Sgirish 
124244961713Sgirish 	/*
124344961713Sgirish 	 * Initialize and enable TXC registers
124444961713Sgirish 	 * (Globally enable TX controller,
124544961713Sgirish 	 *  enable a port, configure dma channel bitmap,
124644961713Sgirish 	 *  configure the max burst size).
124744961713Sgirish 	 */
124844961713Sgirish 	status = nxge_txc_init(nxgep);
124944961713Sgirish 	if (status != NXGE_OK) {
125044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txc failed\n"));
125144961713Sgirish 		goto nxge_init_fail2;
125244961713Sgirish 	}
125344961713Sgirish 
125444961713Sgirish 	/*
125544961713Sgirish 	 * Initialize and enable TXDMA channels.
125644961713Sgirish 	 */
125744961713Sgirish 	status = nxge_init_txdma_channels(nxgep);
125844961713Sgirish 	if (status != NXGE_OK) {
125944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n"));
126044961713Sgirish 		goto nxge_init_fail3;
126144961713Sgirish 	}
126244961713Sgirish 
126344961713Sgirish 	/*
126444961713Sgirish 	 * Initialize and enable RXDMA channels.
126544961713Sgirish 	 */
126644961713Sgirish 	status = nxge_init_rxdma_channels(nxgep);
126744961713Sgirish 	if (status != NXGE_OK) {
126844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n"));
126944961713Sgirish 		goto nxge_init_fail4;
127044961713Sgirish 	}
127144961713Sgirish 
127244961713Sgirish 	/*
127344961713Sgirish 	 * Initialize TCAM and FCRAM (Neptune).
127444961713Sgirish 	 */
127544961713Sgirish 	status = nxge_classify_init(nxgep);
127644961713Sgirish 	if (status != NXGE_OK) {
127744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n"));
127844961713Sgirish 		goto nxge_init_fail5;
127944961713Sgirish 	}
128044961713Sgirish 
128144961713Sgirish 	/*
128244961713Sgirish 	 * Initialize ZCP
128344961713Sgirish 	 */
128444961713Sgirish 	status = nxge_zcp_init(nxgep);
128544961713Sgirish 	if (status != NXGE_OK) {
128644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n"));
128744961713Sgirish 		goto nxge_init_fail5;
128844961713Sgirish 	}
128944961713Sgirish 
129044961713Sgirish 	/*
129144961713Sgirish 	 * Initialize IPP.
129244961713Sgirish 	 */
129344961713Sgirish 	status = nxge_ipp_init(nxgep);
129444961713Sgirish 	if (status != NXGE_OK) {
129544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n"));
129644961713Sgirish 		goto nxge_init_fail5;
129744961713Sgirish 	}
129844961713Sgirish 
129944961713Sgirish 	/*
130044961713Sgirish 	 * Initialize the MAC block.
130144961713Sgirish 	 */
130244961713Sgirish 	status = nxge_mac_init(nxgep);
130344961713Sgirish 	if (status != NXGE_OK) {
130444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n"));
130544961713Sgirish 		goto nxge_init_fail5;
130644961713Sgirish 	}
130744961713Sgirish 
130844961713Sgirish 	nxge_intrs_enable(nxgep);
130944961713Sgirish 
131044961713Sgirish 	/*
131144961713Sgirish 	 * Enable hardware interrupts.
131244961713Sgirish 	 */
131344961713Sgirish 	nxge_intr_hw_enable(nxgep);
131444961713Sgirish 	nxgep->drv_state |= STATE_HW_INITIALIZED;
131544961713Sgirish 
131644961713Sgirish 	goto nxge_init_exit;
131744961713Sgirish 
131844961713Sgirish nxge_init_fail5:
131944961713Sgirish 	nxge_uninit_rxdma_channels(nxgep);
132044961713Sgirish nxge_init_fail4:
132144961713Sgirish 	nxge_uninit_txdma_channels(nxgep);
132244961713Sgirish nxge_init_fail3:
132344961713Sgirish 	(void) nxge_txc_uninit(nxgep);
132444961713Sgirish nxge_init_fail2:
132544961713Sgirish 	nxge_free_mem_pool(nxgep);
132644961713Sgirish nxge_init_fail1:
132744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
132844961713Sgirish 		"<== nxge_init status (failed) = 0x%08x", status));
132944961713Sgirish 	return (status);
133044961713Sgirish 
133144961713Sgirish nxge_init_exit:
133244961713Sgirish 
133344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x",
133444961713Sgirish 		status));
133544961713Sgirish 	return (status);
133644961713Sgirish }
133744961713Sgirish 
133844961713Sgirish 
133944961713Sgirish timeout_id_t
134044961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec)
134144961713Sgirish {
134244961713Sgirish 	if ((nxgep->suspended == 0) ||
134344961713Sgirish 			(nxgep->suspended == DDI_RESUME)) {
134444961713Sgirish 		return (timeout(func, (caddr_t)nxgep,
134544961713Sgirish 			drv_usectohz(1000 * msec)));
134644961713Sgirish 	}
134744961713Sgirish 	return (NULL);
134844961713Sgirish }
134944961713Sgirish 
135044961713Sgirish /*ARGSUSED*/
135144961713Sgirish void
135244961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid)
135344961713Sgirish {
135444961713Sgirish 	if (timerid) {
135544961713Sgirish 		(void) untimeout(timerid);
135644961713Sgirish 	}
135744961713Sgirish }
135844961713Sgirish 
135944961713Sgirish void
136044961713Sgirish nxge_uninit(p_nxge_t nxgep)
136144961713Sgirish {
136244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit"));
136344961713Sgirish 
136444961713Sgirish 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
136544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
136644961713Sgirish 			"==> nxge_uninit: not initialized"));
136744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
136844961713Sgirish 			"<== nxge_uninit"));
136944961713Sgirish 		return;
137044961713Sgirish 	}
137144961713Sgirish 
137244961713Sgirish 	/* stop timer */
137344961713Sgirish 	if (nxgep->nxge_timerid) {
137444961713Sgirish 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
137544961713Sgirish 		nxgep->nxge_timerid = 0;
137644961713Sgirish 	}
137744961713Sgirish 
137844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
137944961713Sgirish 	(void) nxge_intr_hw_disable(nxgep);
138044961713Sgirish 
138144961713Sgirish 	/*
138244961713Sgirish 	 * Reset the receive MAC side.
138344961713Sgirish 	 */
138444961713Sgirish 	(void) nxge_rx_mac_disable(nxgep);
138544961713Sgirish 
138644961713Sgirish 	/* Disable and soft reset the IPP */
138744961713Sgirish 	(void) nxge_ipp_disable(nxgep);
138844961713Sgirish 
1389a3c5bd6dSspeer 	/* Free classification resources */
1390a3c5bd6dSspeer 	(void) nxge_classify_uninit(nxgep);
1391a3c5bd6dSspeer 
139244961713Sgirish 	/*
139344961713Sgirish 	 * Reset the transmit/receive DMA side.
139444961713Sgirish 	 */
139544961713Sgirish 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
139644961713Sgirish 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
139744961713Sgirish 
139844961713Sgirish 	nxge_uninit_txdma_channels(nxgep);
139944961713Sgirish 	nxge_uninit_rxdma_channels(nxgep);
140044961713Sgirish 
140144961713Sgirish 	/*
140244961713Sgirish 	 * Reset the transmit MAC side.
140344961713Sgirish 	 */
140444961713Sgirish 	(void) nxge_tx_mac_disable(nxgep);
140544961713Sgirish 
140644961713Sgirish 	nxge_free_mem_pool(nxgep);
140744961713Sgirish 
140844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
140944961713Sgirish 
141044961713Sgirish 	nxgep->drv_state &= ~STATE_HW_INITIALIZED;
141144961713Sgirish 
141244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: "
141344961713Sgirish 		"nxge_mblks_pending %d", nxge_mblks_pending));
141444961713Sgirish }
141544961713Sgirish 
141644961713Sgirish void
141744961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp)
141844961713Sgirish {
1419adfcba55Sjoycey #if defined(__i386)
1420adfcba55Sjoycey 	size_t		reg;
1421adfcba55Sjoycey #else
142244961713Sgirish 	uint64_t	reg;
1423adfcba55Sjoycey #endif
142444961713Sgirish 	uint64_t	regdata;
142544961713Sgirish 	int		i, retry;
142644961713Sgirish 
142744961713Sgirish 	bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
142844961713Sgirish 	regdata = 0;
142944961713Sgirish 	retry = 1;
143044961713Sgirish 
143144961713Sgirish 	for (i = 0; i < retry; i++) {
143244961713Sgirish 		NXGE_REG_RD64(nxgep->npi_handle, reg, &regdata);
143344961713Sgirish 	}
143444961713Sgirish 	bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
143544961713Sgirish }
143644961713Sgirish 
143744961713Sgirish void
143844961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp)
143944961713Sgirish {
1440adfcba55Sjoycey #if defined(__i386)
1441adfcba55Sjoycey 	size_t		reg;
1442adfcba55Sjoycey #else
144344961713Sgirish 	uint64_t	reg;
1444adfcba55Sjoycey #endif
144544961713Sgirish 	uint64_t	buf[2];
144644961713Sgirish 
144744961713Sgirish 	bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
14487a8b1321Sjoycey #if defined(__i386)
14497a8b1321Sjoycey 	reg = (size_t)buf[0];
14507a8b1321Sjoycey #else
145144961713Sgirish 	reg = buf[0];
14527a8b1321Sjoycey #endif
145344961713Sgirish 
145444961713Sgirish 	NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]);
145544961713Sgirish }
145644961713Sgirish 
145744961713Sgirish 
145844961713Sgirish nxge_os_mutex_t nxgedebuglock;
145944961713Sgirish int nxge_debug_init = 0;
146044961713Sgirish 
146144961713Sgirish /*ARGSUSED*/
146244961713Sgirish /*VARARGS*/
146344961713Sgirish void
146444961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...)
146544961713Sgirish {
146644961713Sgirish 	char msg_buffer[1048];
146744961713Sgirish 	char prefix_buffer[32];
146844961713Sgirish 	int instance;
146944961713Sgirish 	uint64_t debug_level;
147044961713Sgirish 	int cmn_level = CE_CONT;
147144961713Sgirish 	va_list ap;
147244961713Sgirish 
147344961713Sgirish 	debug_level = (nxgep == NULL) ? nxge_debug_level :
147444961713Sgirish 		nxgep->nxge_debug_level;
147544961713Sgirish 
147644961713Sgirish 	if ((level & debug_level) ||
147744961713Sgirish 		(level == NXGE_NOTE) ||
147844961713Sgirish 		(level == NXGE_ERR_CTL)) {
147944961713Sgirish 		/* do the msg processing */
148044961713Sgirish 		if (nxge_debug_init == 0) {
148144961713Sgirish 			MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL);
148244961713Sgirish 			nxge_debug_init = 1;
148344961713Sgirish 		}
148444961713Sgirish 
148544961713Sgirish 		MUTEX_ENTER(&nxgedebuglock);
148644961713Sgirish 
148744961713Sgirish 		if ((level & NXGE_NOTE)) {
148844961713Sgirish 			cmn_level = CE_NOTE;
148944961713Sgirish 		}
149044961713Sgirish 
149144961713Sgirish 		if (level & NXGE_ERR_CTL) {
149244961713Sgirish 			cmn_level = CE_WARN;
149344961713Sgirish 		}
149444961713Sgirish 
149544961713Sgirish 		va_start(ap, fmt);
149644961713Sgirish 		(void) vsprintf(msg_buffer, fmt, ap);
149744961713Sgirish 		va_end(ap);
149844961713Sgirish 		if (nxgep == NULL) {
149944961713Sgirish 			instance = -1;
150044961713Sgirish 			(void) sprintf(prefix_buffer, "%s :", "nxge");
150144961713Sgirish 		} else {
150244961713Sgirish 			instance = nxgep->instance;
150344961713Sgirish 			(void) sprintf(prefix_buffer,
150444961713Sgirish 						    "%s%d :", "nxge", instance);
150544961713Sgirish 		}
150644961713Sgirish 
150744961713Sgirish 		MUTEX_EXIT(&nxgedebuglock);
150844961713Sgirish 		cmn_err(cmn_level, "!%s %s\n",
150944961713Sgirish 				prefix_buffer, msg_buffer);
151044961713Sgirish 
151144961713Sgirish 	}
151244961713Sgirish }
151344961713Sgirish 
151444961713Sgirish char *
151544961713Sgirish nxge_dump_packet(char *addr, int size)
151644961713Sgirish {
151744961713Sgirish 	uchar_t *ap = (uchar_t *)addr;
151844961713Sgirish 	int i;
151944961713Sgirish 	static char etherbuf[1024];
152044961713Sgirish 	char *cp = etherbuf;
152144961713Sgirish 	char digits[] = "0123456789abcdef";
152244961713Sgirish 
152344961713Sgirish 	if (!size)
152444961713Sgirish 		size = 60;
152544961713Sgirish 
152644961713Sgirish 	if (size > MAX_DUMP_SZ) {
152744961713Sgirish 		/* Dump the leading bytes */
152844961713Sgirish 		for (i = 0; i < MAX_DUMP_SZ/2; i++) {
152944961713Sgirish 			if (*ap > 0x0f)
153044961713Sgirish 				*cp++ = digits[*ap >> 4];
153144961713Sgirish 			*cp++ = digits[*ap++ & 0xf];
153244961713Sgirish 			*cp++ = ':';
153344961713Sgirish 		}
153444961713Sgirish 		for (i = 0; i < 20; i++)
153544961713Sgirish 			*cp++ = '.';
153644961713Sgirish 		/* Dump the last MAX_DUMP_SZ/2 bytes */
153744961713Sgirish 		ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2));
153844961713Sgirish 		for (i = 0; i < MAX_DUMP_SZ/2; i++) {
153944961713Sgirish 			if (*ap > 0x0f)
154044961713Sgirish 				*cp++ = digits[*ap >> 4];
154144961713Sgirish 			*cp++ = digits[*ap++ & 0xf];
154244961713Sgirish 			*cp++ = ':';
154344961713Sgirish 		}
154444961713Sgirish 	} else {
154544961713Sgirish 		for (i = 0; i < size; i++) {
154644961713Sgirish 			if (*ap > 0x0f)
154744961713Sgirish 				*cp++ = digits[*ap >> 4];
154844961713Sgirish 			*cp++ = digits[*ap++ & 0xf];
154944961713Sgirish 			*cp++ = ':';
155044961713Sgirish 		}
155144961713Sgirish 	}
155244961713Sgirish 	*--cp = 0;
155344961713Sgirish 	return (etherbuf);
155444961713Sgirish }
155544961713Sgirish 
155644961713Sgirish #ifdef	NXGE_DEBUG
155744961713Sgirish static void
155844961713Sgirish nxge_test_map_regs(p_nxge_t nxgep)
155944961713Sgirish {
156044961713Sgirish 	ddi_acc_handle_t cfg_handle;
156144961713Sgirish 	p_pci_cfg_t	cfg_ptr;
156244961713Sgirish 	ddi_acc_handle_t dev_handle;
156344961713Sgirish 	char		*dev_ptr;
156444961713Sgirish 	ddi_acc_handle_t pci_config_handle;
156544961713Sgirish 	uint32_t	regval;
156644961713Sgirish 	int		i;
156744961713Sgirish 
156844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs"));
156944961713Sgirish 
157044961713Sgirish 	dev_handle = nxgep->dev_regs->nxge_regh;
157144961713Sgirish 	dev_ptr = (char *)nxgep->dev_regs->nxge_regp;
157244961713Sgirish 
15732e59129aSraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
157444961713Sgirish 		cfg_handle = nxgep->dev_regs->nxge_pciregh;
157544961713Sgirish 		cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
157644961713Sgirish 
157744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
157859ac0c16Sdavemq 		    "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr));
157944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
158059ac0c16Sdavemq 		    "Neptune PCI cfg_ptr vendor id ptr 0x%llx",
158159ac0c16Sdavemq 		    &cfg_ptr->vendorid));
158244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
158359ac0c16Sdavemq 		    "\tvendorid 0x%x devid 0x%x",
158459ac0c16Sdavemq 		    NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0),
158559ac0c16Sdavemq 		    NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid,    0)));
158644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
158759ac0c16Sdavemq 		    "PCI BAR: base 0x%x base14 0x%x base 18 0x%x "
158859ac0c16Sdavemq 		    "bar1c 0x%x",
158959ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base,   0),
159059ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0),
159159ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0),
159259ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0)));
159344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
159459ac0c16Sdavemq 		    "\nNeptune PCI BAR: base20 0x%x base24 0x%x "
159559ac0c16Sdavemq 		    "base 28 0x%x bar2c 0x%x\n",
159659ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0),
159759ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0),
159859ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0),
159959ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0)));
160044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
160159ac0c16Sdavemq 		    "\nNeptune PCI BAR: base30 0x%x\n",
160259ac0c16Sdavemq 		    NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0)));
160344961713Sgirish 
160444961713Sgirish 		cfg_handle = nxgep->dev_regs->nxge_pciregh;
160544961713Sgirish 		cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
160644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
160759ac0c16Sdavemq 		    "first  0x%llx second 0x%llx third 0x%llx "
160859ac0c16Sdavemq 		    "last 0x%llx ",
160959ac0c16Sdavemq 		    NXGE_PIO_READ64(dev_handle,
161059ac0c16Sdavemq 		    (uint64_t *)(dev_ptr + 0),  0),
161159ac0c16Sdavemq 		    NXGE_PIO_READ64(dev_handle,
161259ac0c16Sdavemq 		    (uint64_t *)(dev_ptr + 8),  0),
161359ac0c16Sdavemq 		    NXGE_PIO_READ64(dev_handle,
161459ac0c16Sdavemq 		    (uint64_t *)(dev_ptr + 16), 0),
161559ac0c16Sdavemq 		    NXGE_PIO_READ64(cfg_handle,
161659ac0c16Sdavemq 		    (uint64_t *)(dev_ptr + 24), 0)));
161744961713Sgirish 	}
161844961713Sgirish }
161944961713Sgirish 
162044961713Sgirish #endif
162144961713Sgirish 
162244961713Sgirish static void
162344961713Sgirish nxge_suspend(p_nxge_t nxgep)
162444961713Sgirish {
162544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend"));
162644961713Sgirish 
162744961713Sgirish 	nxge_intrs_disable(nxgep);
162844961713Sgirish 	nxge_destroy_dev(nxgep);
162944961713Sgirish 
163044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend"));
163144961713Sgirish }
163244961713Sgirish 
163344961713Sgirish static nxge_status_t
163444961713Sgirish nxge_resume(p_nxge_t nxgep)
163544961713Sgirish {
163644961713Sgirish 	nxge_status_t status = NXGE_OK;
163744961713Sgirish 
163844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume"));
163944961713Sgirish 
164091c98b31Sjoycey 	nxgep->suspended = DDI_RESUME;
164191c98b31Sjoycey 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
164291c98b31Sjoycey 	(void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START);
164391c98b31Sjoycey 	(void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
164491c98b31Sjoycey 	(void) nxge_rx_mac_enable(nxgep);
164591c98b31Sjoycey 	(void) nxge_tx_mac_enable(nxgep);
164691c98b31Sjoycey 	nxge_intrs_enable(nxgep);
164744961713Sgirish 	nxgep->suspended = 0;
164844961713Sgirish 
164944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
165044961713Sgirish 			"<== nxge_resume status = 0x%x", status));
165144961713Sgirish 	return (status);
165244961713Sgirish }
165344961713Sgirish 
165444961713Sgirish static nxge_status_t
165544961713Sgirish nxge_setup_dev(p_nxge_t nxgep)
165644961713Sgirish {
165744961713Sgirish 	nxge_status_t	status = NXGE_OK;
165844961713Sgirish 
165944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d",
166059ac0c16Sdavemq 	    nxgep->mac.portnum));
166144961713Sgirish 
166244961713Sgirish 	status = nxge_link_init(nxgep);
166314ea4bb7Ssd 
166414ea4bb7Ssd 	if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
166514ea4bb7Ssd 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
166614ea4bb7Ssd 			"port%d Bad register acc handle", nxgep->mac.portnum));
166714ea4bb7Ssd 		status = NXGE_ERROR;
166814ea4bb7Ssd 	}
166914ea4bb7Ssd 
167044961713Sgirish 	if (status != NXGE_OK) {
167144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
167244961713Sgirish 			    " nxge_setup_dev status "
167344961713Sgirish 			    "(xcvr init 0x%08x)", status));
167444961713Sgirish 		goto nxge_setup_dev_exit;
167544961713Sgirish 	}
167644961713Sgirish 
167744961713Sgirish nxge_setup_dev_exit:
167844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
167944961713Sgirish 		"<== nxge_setup_dev port %d status = 0x%08x",
168044961713Sgirish 		nxgep->mac.portnum, status));
168144961713Sgirish 
168244961713Sgirish 	return (status);
168344961713Sgirish }
168444961713Sgirish 
168544961713Sgirish static void
168644961713Sgirish nxge_destroy_dev(p_nxge_t nxgep)
168744961713Sgirish {
168844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev"));
168944961713Sgirish 
169044961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
169144961713Sgirish 
169244961713Sgirish 	(void) nxge_hw_stop(nxgep);
169344961713Sgirish 
169444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev"));
169544961713Sgirish }
169644961713Sgirish 
169744961713Sgirish static nxge_status_t
169844961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep)
169944961713Sgirish {
170044961713Sgirish 	int 			ddi_status = DDI_SUCCESS;
170144961713Sgirish 	uint_t 			count;
170244961713Sgirish 	ddi_dma_cookie_t 	cookie;
170344961713Sgirish 	uint_t 			iommu_pagesize;
170444961713Sgirish 	nxge_status_t		status = NXGE_OK;
170544961713Sgirish 
170644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages"));
170744961713Sgirish 	nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1);
170844961713Sgirish 	if (nxgep->niu_type != N2_NIU) {
170944961713Sgirish 		iommu_pagesize = dvma_pagesize(nxgep->dip);
171044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DDI_CTL,
171144961713Sgirish 			" nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
171244961713Sgirish 			" default_block_size %d iommu_pagesize %d",
171344961713Sgirish 			nxgep->sys_page_sz,
171444961713Sgirish 			ddi_ptob(nxgep->dip, (ulong_t)1),
171544961713Sgirish 			nxgep->rx_default_block_size,
171644961713Sgirish 			iommu_pagesize));
171744961713Sgirish 
171844961713Sgirish 		if (iommu_pagesize != 0) {
171944961713Sgirish 			if (nxgep->sys_page_sz == iommu_pagesize) {
172044961713Sgirish 				if (iommu_pagesize > 0x4000)
172144961713Sgirish 					nxgep->sys_page_sz = 0x4000;
172244961713Sgirish 			} else {
172344961713Sgirish 				if (nxgep->sys_page_sz > iommu_pagesize)
172444961713Sgirish 					nxgep->sys_page_sz = iommu_pagesize;
172544961713Sgirish 			}
172644961713Sgirish 		}
172744961713Sgirish 	}
172844961713Sgirish 	nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
172944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
173044961713Sgirish 		"==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
173144961713Sgirish 		"default_block_size %d page mask %d",
173244961713Sgirish 		nxgep->sys_page_sz,
173344961713Sgirish 		ddi_ptob(nxgep->dip, (ulong_t)1),
173444961713Sgirish 		nxgep->rx_default_block_size,
173544961713Sgirish 		nxgep->sys_page_mask));
173644961713Sgirish 
173744961713Sgirish 
173844961713Sgirish 	switch (nxgep->sys_page_sz) {
173944961713Sgirish 	default:
174044961713Sgirish 		nxgep->sys_page_sz = 0x1000;
174144961713Sgirish 		nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
174244961713Sgirish 		nxgep->rx_default_block_size = 0x1000;
174344961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_4K;
174444961713Sgirish 		break;
174544961713Sgirish 	case 0x1000:
174644961713Sgirish 		nxgep->rx_default_block_size = 0x1000;
174744961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_4K;
174844961713Sgirish 		break;
174944961713Sgirish 	case 0x2000:
175044961713Sgirish 		nxgep->rx_default_block_size = 0x2000;
175144961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_8K;
175244961713Sgirish 		break;
175344961713Sgirish 	case 0x4000:
175444961713Sgirish 		nxgep->rx_default_block_size = 0x4000;
175544961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_16K;
175644961713Sgirish 		break;
175744961713Sgirish 	case 0x8000:
175844961713Sgirish 		nxgep->rx_default_block_size = 0x8000;
175944961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_32K;
176044961713Sgirish 		break;
176144961713Sgirish 	}
176244961713Sgirish 
176344961713Sgirish #ifndef USE_RX_BIG_BUF
176444961713Sgirish 	nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz;
176544961713Sgirish #else
176644961713Sgirish 		nxgep->rx_default_block_size = 0x2000;
176744961713Sgirish 		nxgep->rx_bksize_code = RBR_BKSIZE_8K;
176844961713Sgirish #endif
176944961713Sgirish 	/*
177044961713Sgirish 	 * Get the system DMA burst size.
177144961713Sgirish 	 */
177244961713Sgirish 	ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
177344961713Sgirish 			DDI_DMA_DONTWAIT, 0,
177444961713Sgirish 			&nxgep->dmasparehandle);
177544961713Sgirish 	if (ddi_status != DDI_SUCCESS) {
177644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
177744961713Sgirish 			"ddi_dma_alloc_handle: failed "
177844961713Sgirish 			" status 0x%x", ddi_status));
177944961713Sgirish 		goto nxge_get_soft_properties_exit;
178044961713Sgirish 	}
178144961713Sgirish 
178244961713Sgirish 	ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL,
178344961713Sgirish 				(caddr_t)nxgep->dmasparehandle,
178444961713Sgirish 				sizeof (nxgep->dmasparehandle),
178544961713Sgirish 				DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
178644961713Sgirish 				DDI_DMA_DONTWAIT, 0,
178744961713Sgirish 				&cookie, &count);
178844961713Sgirish 	if (ddi_status != DDI_DMA_MAPPED) {
178944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
179044961713Sgirish 			"Binding spare handle to find system"
179144961713Sgirish 			" burstsize failed."));
179244961713Sgirish 		ddi_status = DDI_FAILURE;
179344961713Sgirish 		goto nxge_get_soft_properties_fail1;
179444961713Sgirish 	}
179544961713Sgirish 
179644961713Sgirish 	nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle);
179744961713Sgirish 	(void) ddi_dma_unbind_handle(nxgep->dmasparehandle);
179844961713Sgirish 
179944961713Sgirish nxge_get_soft_properties_fail1:
180044961713Sgirish 	ddi_dma_free_handle(&nxgep->dmasparehandle);
180144961713Sgirish 
180244961713Sgirish nxge_get_soft_properties_exit:
180344961713Sgirish 
180444961713Sgirish 	if (ddi_status != DDI_SUCCESS)
180544961713Sgirish 		status |= (NXGE_ERROR | NXGE_DDI_FAILED);
180644961713Sgirish 
180744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
180844961713Sgirish 		"<== nxge_setup_system_dma_pages status = 0x%08x", status));
180944961713Sgirish 	return (status);
181044961713Sgirish }
181144961713Sgirish 
181244961713Sgirish static nxge_status_t
181344961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep)
181444961713Sgirish {
181544961713Sgirish 	nxge_status_t	status = NXGE_OK;
181644961713Sgirish 
181744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool"));
181844961713Sgirish 
181944961713Sgirish 	status = nxge_alloc_rx_mem_pool(nxgep);
182044961713Sgirish 	if (status != NXGE_OK) {
182144961713Sgirish 		return (NXGE_ERROR);
182244961713Sgirish 	}
182344961713Sgirish 
182444961713Sgirish 	status = nxge_alloc_tx_mem_pool(nxgep);
182544961713Sgirish 	if (status != NXGE_OK) {
182644961713Sgirish 		nxge_free_rx_mem_pool(nxgep);
182744961713Sgirish 		return (NXGE_ERROR);
182844961713Sgirish 	}
182944961713Sgirish 
183044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool"));
183144961713Sgirish 	return (NXGE_OK);
183244961713Sgirish }
183344961713Sgirish 
183444961713Sgirish static void
183544961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep)
183644961713Sgirish {
183744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool"));
183844961713Sgirish 
183944961713Sgirish 	nxge_free_rx_mem_pool(nxgep);
184044961713Sgirish 	nxge_free_tx_mem_pool(nxgep);
184144961713Sgirish 
184244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool"));
184344961713Sgirish }
184444961713Sgirish 
184544961713Sgirish static nxge_status_t
184644961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep)
184744961713Sgirish {
184844961713Sgirish 	int			i, j;
184944961713Sgirish 	uint32_t		ndmas, st_rdc;
185044961713Sgirish 	p_nxge_dma_pt_cfg_t	p_all_cfgp;
185144961713Sgirish 	p_nxge_hw_pt_cfg_t	p_cfgp;
185244961713Sgirish 	p_nxge_dma_pool_t	dma_poolp;
185344961713Sgirish 	p_nxge_dma_common_t	*dma_buf_p;
185444961713Sgirish 	p_nxge_dma_pool_t	dma_cntl_poolp;
185544961713Sgirish 	p_nxge_dma_common_t	*dma_cntl_p;
185644961713Sgirish 	size_t			rx_buf_alloc_size;
185744961713Sgirish 	size_t			rx_cntl_alloc_size;
185844961713Sgirish 	uint32_t 		*num_chunks; /* per dma */
185944961713Sgirish 	nxge_status_t		status = NXGE_OK;
186044961713Sgirish 
186144961713Sgirish 	uint32_t		nxge_port_rbr_size;
186244961713Sgirish 	uint32_t		nxge_port_rbr_spare_size;
186344961713Sgirish 	uint32_t		nxge_port_rcr_size;
186444961713Sgirish 
186544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool"));
186644961713Sgirish 
186744961713Sgirish 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
186844961713Sgirish 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
186944961713Sgirish 	st_rdc = p_cfgp->start_rdc;
187044961713Sgirish 	ndmas = p_cfgp->max_rdcs;
187144961713Sgirish 
187244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
187344961713Sgirish 		" nxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
187444961713Sgirish 
187544961713Sgirish 	/*
187644961713Sgirish 	 * Allocate memory for each receive DMA channel.
187744961713Sgirish 	 */
187844961713Sgirish 	dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
187944961713Sgirish 			KM_SLEEP);
188044961713Sgirish 	dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
188144961713Sgirish 			sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
188244961713Sgirish 
188344961713Sgirish 	dma_cntl_poolp = (p_nxge_dma_pool_t)
188444961713Sgirish 				KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
188544961713Sgirish 	dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
188644961713Sgirish 			sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
188744961713Sgirish 
188844961713Sgirish 	num_chunks = (uint32_t *)KMEM_ZALLOC(
188944961713Sgirish 			sizeof (uint32_t) * ndmas, KM_SLEEP);
189044961713Sgirish 
189144961713Sgirish 	/*
189244961713Sgirish 	 * Assume that each DMA channel will be configured with default
189344961713Sgirish 	 * block size.
189444961713Sgirish 	 * rbr block counts are mod of batch count (16).
189544961713Sgirish 	 */
189644961713Sgirish 	nxge_port_rbr_size = p_all_cfgp->rbr_size;
189744961713Sgirish 	nxge_port_rcr_size = p_all_cfgp->rcr_size;
189844961713Sgirish 
189944961713Sgirish 	if (!nxge_port_rbr_size) {
190044961713Sgirish 		nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT;
190144961713Sgirish 	}
190244961713Sgirish 	if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) {
190344961713Sgirish 		nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH *
190444961713Sgirish 			(nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1));
190544961713Sgirish 	}
190644961713Sgirish 
190744961713Sgirish 	p_all_cfgp->rbr_size = nxge_port_rbr_size;
190844961713Sgirish 	nxge_port_rbr_spare_size = nxge_rbr_spare_size;
190944961713Sgirish 
191044961713Sgirish 	if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) {
191144961713Sgirish 		nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH *
191244961713Sgirish 			(nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1));
191344961713Sgirish 	}
191430ac2e7bSml 	if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) {
191530ac2e7bSml 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
191630ac2e7bSml 		    "nxge_alloc_rx_mem_pool: RBR size too high %d, "
191730ac2e7bSml 		    "set to default %d",
191830ac2e7bSml 		    nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS));
191930ac2e7bSml 		nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS;
192030ac2e7bSml 	}
192130ac2e7bSml 	if (nxge_port_rcr_size > RCR_DEFAULT_MAX) {
192230ac2e7bSml 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
192330ac2e7bSml 		    "nxge_alloc_rx_mem_pool: RCR too high %d, "
192430ac2e7bSml 		    "set to default %d",
192530ac2e7bSml 		    nxge_port_rcr_size, RCR_DEFAULT_MAX));
192630ac2e7bSml 		nxge_port_rcr_size = RCR_DEFAULT_MAX;
192730ac2e7bSml 	}
192844961713Sgirish 
192944961713Sgirish 	/*
193044961713Sgirish 	 * N2/NIU has limitation on the descriptor sizes (contiguous
193144961713Sgirish 	 * memory allocation on data buffers to 4M (contig_mem_alloc)
193244961713Sgirish 	 * and little endian for control buffers (must use the ddi/dki mem alloc
193344961713Sgirish 	 * function).
193444961713Sgirish 	 */
193544961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
193644961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
193744961713Sgirish 		nxge_port_rbr_spare_size = 0;
193844961713Sgirish 		if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) ||
193944961713Sgirish 				(!ISP2(nxge_port_rbr_size))) {
194044961713Sgirish 			nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX;
194144961713Sgirish 		}
194244961713Sgirish 		if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) ||
194344961713Sgirish 				(!ISP2(nxge_port_rcr_size))) {
194444961713Sgirish 			nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX;
194544961713Sgirish 		}
194644961713Sgirish 	}
194744961713Sgirish #endif
194844961713Sgirish 
194944961713Sgirish 	rx_buf_alloc_size = (nxgep->rx_default_block_size *
195044961713Sgirish 		(nxge_port_rbr_size + nxge_port_rbr_spare_size));
195144961713Sgirish 
195244961713Sgirish 	/*
195344961713Sgirish 	 * Addresses of receive block ring, receive completion ring and the
195444961713Sgirish 	 * mailbox must be all cache-aligned (64 bytes).
195544961713Sgirish 	 */
195644961713Sgirish 	rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size;
195744961713Sgirish 	rx_cntl_alloc_size *= (sizeof (rx_desc_t));
195844961713Sgirish 	rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size);
195944961713Sgirish 	rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
196044961713Sgirish 
196144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: "
196244961713Sgirish 		"nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d "
196344961713Sgirish 		"nxge_port_rcr_size = %d "
196444961713Sgirish 		"rx_cntl_alloc_size = %d",
196544961713Sgirish 		nxge_port_rbr_size, nxge_port_rbr_spare_size,
196644961713Sgirish 		nxge_port_rcr_size,
196744961713Sgirish 		rx_cntl_alloc_size));
196844961713Sgirish 
196944961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
197044961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
197144961713Sgirish 		if (!ISP2(rx_buf_alloc_size)) {
197244961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
197344961713Sgirish 				"==> nxge_alloc_rx_mem_pool: "
197444961713Sgirish 				" must be power of 2"));
197544961713Sgirish 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
197644961713Sgirish 			goto nxge_alloc_rx_mem_pool_exit;
197744961713Sgirish 		}
197844961713Sgirish 
197944961713Sgirish 		if (rx_buf_alloc_size > (1 << 22)) {
198044961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
198144961713Sgirish 				"==> nxge_alloc_rx_mem_pool: "
198244961713Sgirish 				" limit size to 4M"));
198344961713Sgirish 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
198444961713Sgirish 			goto nxge_alloc_rx_mem_pool_exit;
198544961713Sgirish 		}
198644961713Sgirish 
198744961713Sgirish 		if (rx_cntl_alloc_size < 0x2000) {
198844961713Sgirish 			rx_cntl_alloc_size = 0x2000;
198944961713Sgirish 		}
199044961713Sgirish 	}
199144961713Sgirish #endif
199244961713Sgirish 	nxgep->nxge_port_rbr_size = nxge_port_rbr_size;
199344961713Sgirish 	nxgep->nxge_port_rcr_size = nxge_port_rcr_size;
199444961713Sgirish 
199544961713Sgirish 	/*
199644961713Sgirish 	 * Allocate memory for receive buffers and descriptor rings.
199744961713Sgirish 	 * Replace allocation functions with interface functions provided
199844961713Sgirish 	 * by the partition manager when it is available.
199944961713Sgirish 	 */
200044961713Sgirish 	/*
200144961713Sgirish 	 * Allocate memory for the receive buffer blocks.
200244961713Sgirish 	 */
200344961713Sgirish 	for (i = 0; i < ndmas; i++) {
200444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
200544961713Sgirish 			" nxge_alloc_rx_mem_pool to alloc mem: "
200644961713Sgirish 			" dma %d dma_buf_p %llx &dma_buf_p %llx",
200744961713Sgirish 			i, dma_buf_p[i], &dma_buf_p[i]));
200844961713Sgirish 		num_chunks[i] = 0;
200944961713Sgirish 		status = nxge_alloc_rx_buf_dma(nxgep, st_rdc, &dma_buf_p[i],
201044961713Sgirish 				rx_buf_alloc_size,
201144961713Sgirish 				nxgep->rx_default_block_size, &num_chunks[i]);
201244961713Sgirish 		if (status != NXGE_OK) {
201344961713Sgirish 			break;
201444961713Sgirish 		}
201544961713Sgirish 		st_rdc++;
201644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
201744961713Sgirish 			" nxge_alloc_rx_mem_pool DONE  alloc mem: "
201844961713Sgirish 			"dma %d dma_buf_p %llx &dma_buf_p %llx", i,
201944961713Sgirish 			dma_buf_p[i], &dma_buf_p[i]));
202044961713Sgirish 	}
202144961713Sgirish 	if (i < ndmas) {
202244961713Sgirish 		goto nxge_alloc_rx_mem_fail1;
202344961713Sgirish 	}
202444961713Sgirish 	/*
202544961713Sgirish 	 * Allocate memory for descriptor rings and mailbox.
202644961713Sgirish 	 */
202744961713Sgirish 	st_rdc = p_cfgp->start_rdc;
202844961713Sgirish 	for (j = 0; j < ndmas; j++) {
202944961713Sgirish 		status = nxge_alloc_rx_cntl_dma(nxgep, st_rdc, &dma_cntl_p[j],
203044961713Sgirish 					rx_cntl_alloc_size);
203144961713Sgirish 		if (status != NXGE_OK) {
203244961713Sgirish 			break;
203344961713Sgirish 		}
203444961713Sgirish 		st_rdc++;
203544961713Sgirish 	}
203644961713Sgirish 	if (j < ndmas) {
203744961713Sgirish 		goto nxge_alloc_rx_mem_fail2;
203844961713Sgirish 	}
203944961713Sgirish 
204044961713Sgirish 	dma_poolp->ndmas = ndmas;
204144961713Sgirish 	dma_poolp->num_chunks = num_chunks;
204244961713Sgirish 	dma_poolp->buf_allocated = B_TRUE;
204344961713Sgirish 	nxgep->rx_buf_pool_p = dma_poolp;
204444961713Sgirish 	dma_poolp->dma_buf_pool_p = dma_buf_p;
204544961713Sgirish 
204644961713Sgirish 	dma_cntl_poolp->ndmas = ndmas;
204744961713Sgirish 	dma_cntl_poolp->buf_allocated = B_TRUE;
204844961713Sgirish 	nxgep->rx_cntl_pool_p = dma_cntl_poolp;
204944961713Sgirish 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
205044961713Sgirish 
205144961713Sgirish 	goto nxge_alloc_rx_mem_pool_exit;
205244961713Sgirish 
205344961713Sgirish nxge_alloc_rx_mem_fail2:
205444961713Sgirish 	/* Free control buffers */
205544961713Sgirish 	j--;
205644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
205744961713Sgirish 		"==> nxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
205844961713Sgirish 	for (; j >= 0; j--) {
205944961713Sgirish 		nxge_free_rx_cntl_dma(nxgep,
206056d930aeSspeer 			(p_nxge_dma_common_t)dma_cntl_p[j]);
206144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, DMA_CTL,
206244961713Sgirish 			"==> nxge_alloc_rx_mem_pool: control bufs freed (%d)",
206344961713Sgirish 			j));
206444961713Sgirish 	}
206544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
206644961713Sgirish 		"==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
206744961713Sgirish 
206844961713Sgirish nxge_alloc_rx_mem_fail1:
206944961713Sgirish 	/* Free data buffers */
207044961713Sgirish 	i--;
207144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
207244961713Sgirish 		"==> nxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
207344961713Sgirish 	for (; i >= 0; i--) {
207444961713Sgirish 		nxge_free_rx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i],
207544961713Sgirish 			num_chunks[i]);
207644961713Sgirish 	}
207744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
207844961713Sgirish 		"==> nxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
207944961713Sgirish 
208044961713Sgirish 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
208144961713Sgirish 	KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
208244961713Sgirish 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
208344961713Sgirish 	KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
208444961713Sgirish 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
208544961713Sgirish 
208644961713Sgirish nxge_alloc_rx_mem_pool_exit:
208744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
208844961713Sgirish 		"<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
208944961713Sgirish 
209044961713Sgirish 	return (status);
209144961713Sgirish }
209244961713Sgirish 
209344961713Sgirish static void
209444961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep)
209544961713Sgirish {
209644961713Sgirish 	uint32_t		i, ndmas;
209744961713Sgirish 	p_nxge_dma_pool_t	dma_poolp;
209844961713Sgirish 	p_nxge_dma_common_t	*dma_buf_p;
209944961713Sgirish 	p_nxge_dma_pool_t	dma_cntl_poolp;
210044961713Sgirish 	p_nxge_dma_common_t	*dma_cntl_p;
210144961713Sgirish 	uint32_t 		*num_chunks;
210244961713Sgirish 
210344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool"));
210444961713Sgirish 
210544961713Sgirish 	dma_poolp = nxgep->rx_buf_pool_p;
210644961713Sgirish 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
210744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
210844961713Sgirish 			"<== nxge_free_rx_mem_pool "
210944961713Sgirish 			"(null rx buf pool or buf not allocated"));
211044961713Sgirish 		return;
211144961713Sgirish 	}
211244961713Sgirish 
211344961713Sgirish 	dma_cntl_poolp = nxgep->rx_cntl_pool_p;
211444961713Sgirish 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
211544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
211644961713Sgirish 			"<== nxge_free_rx_mem_pool "
211744961713Sgirish 			"(null rx cntl buf pool or cntl buf not allocated"));
211844961713Sgirish 		return;
211944961713Sgirish 	}
212044961713Sgirish 
212144961713Sgirish 	dma_buf_p = dma_poolp->dma_buf_pool_p;
212244961713Sgirish 	num_chunks = dma_poolp->num_chunks;
212344961713Sgirish 
212444961713Sgirish 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
212544961713Sgirish 	ndmas = dma_cntl_poolp->ndmas;
212644961713Sgirish 
212744961713Sgirish 	for (i = 0; i < ndmas; i++) {
212844961713Sgirish 		nxge_free_rx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]);
212944961713Sgirish 	}
213044961713Sgirish 
213144961713Sgirish 	for (i = 0; i < ndmas; i++) {
213244961713Sgirish 		nxge_free_rx_cntl_dma(nxgep, dma_cntl_p[i]);
213344961713Sgirish 	}
213444961713Sgirish 
213544961713Sgirish 	for (i = 0; i < ndmas; i++) {
213644961713Sgirish 		KMEM_FREE(dma_buf_p[i],
213744961713Sgirish 			sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
213844961713Sgirish 		KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t));
213944961713Sgirish 	}
214044961713Sgirish 
214144961713Sgirish 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
214244961713Sgirish 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
214344961713Sgirish 	KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
214444961713Sgirish 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
214544961713Sgirish 	KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
214644961713Sgirish 
214744961713Sgirish 	nxgep->rx_buf_pool_p = NULL;
214844961713Sgirish 	nxgep->rx_cntl_pool_p = NULL;
214944961713Sgirish 
215044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool"));
215144961713Sgirish }
215244961713Sgirish 
215344961713Sgirish 
215444961713Sgirish static nxge_status_t
215544961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
215644961713Sgirish 	p_nxge_dma_common_t *dmap,
215744961713Sgirish 	size_t alloc_size, size_t block_size, uint32_t *num_chunks)
215844961713Sgirish {
215944961713Sgirish 	p_nxge_dma_common_t 	rx_dmap;
216044961713Sgirish 	nxge_status_t		status = NXGE_OK;
216144961713Sgirish 	size_t			total_alloc_size;
216244961713Sgirish 	size_t			allocated = 0;
216344961713Sgirish 	int			i, size_index, array_size;
216444961713Sgirish 
216544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma"));
216644961713Sgirish 
216744961713Sgirish 	rx_dmap = (p_nxge_dma_common_t)
216844961713Sgirish 			KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
216944961713Sgirish 			KM_SLEEP);
217044961713Sgirish 
217144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
217244961713Sgirish 		" alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
217344961713Sgirish 		dma_channel, alloc_size, block_size, dmap));
217444961713Sgirish 
217544961713Sgirish 	total_alloc_size = alloc_size;
217644961713Sgirish 
217744961713Sgirish #if defined(RX_USE_RECLAIM_POST)
217844961713Sgirish 	total_alloc_size = alloc_size + alloc_size/4;
217944961713Sgirish #endif
218044961713Sgirish 
218144961713Sgirish 	i = 0;
218244961713Sgirish 	size_index = 0;
218344961713Sgirish 	array_size =  sizeof (alloc_sizes)/sizeof (size_t);
218444961713Sgirish 	while ((alloc_sizes[size_index] < alloc_size) &&
218544961713Sgirish 			(size_index < array_size))
218644961713Sgirish 			size_index++;
218744961713Sgirish 	if (size_index >= array_size) {
218844961713Sgirish 		size_index = array_size - 1;
218944961713Sgirish 	}
219044961713Sgirish 
219144961713Sgirish 	while ((allocated < total_alloc_size) &&
219244961713Sgirish 			(size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
219344961713Sgirish 		rx_dmap[i].dma_chunk_index = i;
219444961713Sgirish 		rx_dmap[i].block_size = block_size;
219544961713Sgirish 		rx_dmap[i].alength = alloc_sizes[size_index];
219644961713Sgirish 		rx_dmap[i].orig_alength = rx_dmap[i].alength;
219744961713Sgirish 		rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
219844961713Sgirish 		rx_dmap[i].dma_channel = dma_channel;
219944961713Sgirish 		rx_dmap[i].contig_alloc_type = B_FALSE;
220044961713Sgirish 
220144961713Sgirish 		/*
220244961713Sgirish 		 * N2/NIU: data buffers must be contiguous as the driver
220344961713Sgirish 		 *	   needs to call Hypervisor api to set up
220444961713Sgirish 		 *	   logical pages.
220544961713Sgirish 		 */
220644961713Sgirish 		if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
220744961713Sgirish 			rx_dmap[i].contig_alloc_type = B_TRUE;
220844961713Sgirish 		}
220944961713Sgirish 
221044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
221144961713Sgirish 			"alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
221244961713Sgirish 			"i %d nblocks %d alength %d",
221344961713Sgirish 			dma_channel, i, &rx_dmap[i], block_size,
221444961713Sgirish 			i, rx_dmap[i].nblocks,
221544961713Sgirish 			rx_dmap[i].alength));
221644961713Sgirish 		status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
221744961713Sgirish 			&nxge_rx_dma_attr,
221844961713Sgirish 			rx_dmap[i].alength,
221944961713Sgirish 			&nxge_dev_buf_dma_acc_attr,
222044961713Sgirish 			DDI_DMA_READ | DDI_DMA_STREAMING,
222144961713Sgirish 			(p_nxge_dma_common_t)(&rx_dmap[i]));
222244961713Sgirish 		if (status != NXGE_OK) {
222344961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
222444961713Sgirish 				" nxge_alloc_rx_buf_dma: Alloc Failed "));
222544961713Sgirish 			size_index--;
222644961713Sgirish 		} else {
222744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DMA_CTL,
222844961713Sgirish 				" alloc_rx_buf_dma allocated rdc %d "
222944961713Sgirish 				"chunk %d size %x dvma %x bufp %llx ",
223044961713Sgirish 				dma_channel, i, rx_dmap[i].alength,
223144961713Sgirish 				rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
223244961713Sgirish 			i++;
223344961713Sgirish 			allocated += alloc_sizes[size_index];
223444961713Sgirish 		}
223544961713Sgirish 	}
223644961713Sgirish 
223744961713Sgirish 
223844961713Sgirish 	if (allocated < total_alloc_size) {
223930ac2e7bSml 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
224030ac2e7bSml 		    "==> nxge_alloc_rx_buf_dma: not enough for channe %d "
224130ac2e7bSml 		    "allocated 0x%x requested 0x%x",
224230ac2e7bSml 		    dma_channel,
224330ac2e7bSml 		    allocated, total_alloc_size));
224430ac2e7bSml 		status = NXGE_ERROR;
224544961713Sgirish 		goto nxge_alloc_rx_mem_fail1;
224644961713Sgirish 	}
224744961713Sgirish 
224830ac2e7bSml 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
224930ac2e7bSml 	    "==> nxge_alloc_rx_buf_dma: Allocated for channe %d "
225030ac2e7bSml 	    "allocated 0x%x requested 0x%x",
225130ac2e7bSml 	    dma_channel,
225230ac2e7bSml 	    allocated, total_alloc_size));
225330ac2e7bSml 
225444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
225544961713Sgirish 		" alloc_rx_buf_dma rdc %d allocated %d chunks",
225644961713Sgirish 		dma_channel, i));
225744961713Sgirish 	*num_chunks = i;
225844961713Sgirish 	*dmap = rx_dmap;
225944961713Sgirish 
226044961713Sgirish 	goto nxge_alloc_rx_mem_exit;
226144961713Sgirish 
226244961713Sgirish nxge_alloc_rx_mem_fail1:
226344961713Sgirish 	KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
226444961713Sgirish 
226544961713Sgirish nxge_alloc_rx_mem_exit:
226644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
226744961713Sgirish 		"<== nxge_alloc_rx_buf_dma status 0x%08x", status));
226844961713Sgirish 
226944961713Sgirish 	return (status);
227044961713Sgirish }
227144961713Sgirish 
227244961713Sgirish /*ARGSUSED*/
227344961713Sgirish static void
227444961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
227544961713Sgirish     uint32_t num_chunks)
227644961713Sgirish {
227744961713Sgirish 	int		i;
227844961713Sgirish 
227944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
228044961713Sgirish 		"==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks));
228144961713Sgirish 
228244961713Sgirish 	for (i = 0; i < num_chunks; i++) {
228344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
228444961713Sgirish 			"==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx",
228544961713Sgirish 				i, dmap));
228644961713Sgirish 		nxge_dma_mem_free(dmap++);
228744961713Sgirish 	}
228844961713Sgirish 
228944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma"));
229044961713Sgirish }
229144961713Sgirish 
229244961713Sgirish /*ARGSUSED*/
229344961713Sgirish static nxge_status_t
229444961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
229544961713Sgirish     p_nxge_dma_common_t *dmap, size_t size)
229644961713Sgirish {
229744961713Sgirish 	p_nxge_dma_common_t 	rx_dmap;
229844961713Sgirish 	nxge_status_t		status = NXGE_OK;
229944961713Sgirish 
230044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma"));
230144961713Sgirish 
230244961713Sgirish 	rx_dmap = (p_nxge_dma_common_t)
230344961713Sgirish 			KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
230444961713Sgirish 
230544961713Sgirish 	rx_dmap->contig_alloc_type = B_FALSE;
230644961713Sgirish 
230744961713Sgirish 	status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
230844961713Sgirish 			&nxge_desc_dma_attr,
230944961713Sgirish 			size,
231044961713Sgirish 			&nxge_dev_desc_dma_acc_attr,
231144961713Sgirish 			DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
231244961713Sgirish 			rx_dmap);
231344961713Sgirish 	if (status != NXGE_OK) {
231444961713Sgirish 		goto nxge_alloc_rx_cntl_dma_fail1;
231544961713Sgirish 	}
231644961713Sgirish 
231744961713Sgirish 	*dmap = rx_dmap;
231844961713Sgirish 	goto nxge_alloc_rx_cntl_dma_exit;
231944961713Sgirish 
232044961713Sgirish nxge_alloc_rx_cntl_dma_fail1:
232144961713Sgirish 	KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t));
232244961713Sgirish 
232344961713Sgirish nxge_alloc_rx_cntl_dma_exit:
232444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
232544961713Sgirish 		"<== nxge_alloc_rx_cntl_dma status 0x%08x", status));
232644961713Sgirish 
232744961713Sgirish 	return (status);
232844961713Sgirish }
232944961713Sgirish 
233044961713Sgirish /*ARGSUSED*/
233144961713Sgirish static void
233244961713Sgirish nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
233344961713Sgirish {
233444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma"));
233544961713Sgirish 
233644961713Sgirish 	nxge_dma_mem_free(dmap);
233744961713Sgirish 
233844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma"));
233944961713Sgirish }
234044961713Sgirish 
234144961713Sgirish static nxge_status_t
234244961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep)
234344961713Sgirish {
234444961713Sgirish 	nxge_status_t		status = NXGE_OK;
234544961713Sgirish 	int			i, j;
234644961713Sgirish 	uint32_t		ndmas, st_tdc;
234744961713Sgirish 	p_nxge_dma_pt_cfg_t	p_all_cfgp;
234844961713Sgirish 	p_nxge_hw_pt_cfg_t	p_cfgp;
234944961713Sgirish 	p_nxge_dma_pool_t	dma_poolp;
235044961713Sgirish 	p_nxge_dma_common_t	*dma_buf_p;
235144961713Sgirish 	p_nxge_dma_pool_t	dma_cntl_poolp;
235244961713Sgirish 	p_nxge_dma_common_t	*dma_cntl_p;
235344961713Sgirish 	size_t			tx_buf_alloc_size;
235444961713Sgirish 	size_t			tx_cntl_alloc_size;
235544961713Sgirish 	uint32_t		*num_chunks; /* per dma */
23561f8914d5Sml 	uint32_t		bcopy_thresh;
235744961713Sgirish 
235844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool"));
235944961713Sgirish 
236044961713Sgirish 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
236144961713Sgirish 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
236244961713Sgirish 	st_tdc = p_cfgp->start_tdc;
236344961713Sgirish 	ndmas = p_cfgp->max_tdcs;
236444961713Sgirish 
236544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool: "
236644961713Sgirish 		"p_cfgp 0x%016llx start_tdc %d ndmas %d nxgep->max_tdcs %d",
236744961713Sgirish 		p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, nxgep->max_tdcs));
236844961713Sgirish 	/*
236944961713Sgirish 	 * Allocate memory for each transmit DMA channel.
237044961713Sgirish 	 */
237144961713Sgirish 	dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
237244961713Sgirish 			KM_SLEEP);
237344961713Sgirish 	dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
237444961713Sgirish 			sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
237544961713Sgirish 
237644961713Sgirish 	dma_cntl_poolp = (p_nxge_dma_pool_t)
237744961713Sgirish 			KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
237844961713Sgirish 	dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
237944961713Sgirish 			sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
238044961713Sgirish 
238130ac2e7bSml 	if (nxge_tx_ring_size > TDC_DEFAULT_MAX) {
238230ac2e7bSml 		NXGE_DEBUG_MSG((nxgep, MEM_CTL,
238330ac2e7bSml 		    "nxge_alloc_tx_mem_pool: TDC too high %d, "
238430ac2e7bSml 		    "set to default %d",
238530ac2e7bSml 		    nxge_tx_ring_size, TDC_DEFAULT_MAX));
238630ac2e7bSml 		nxge_tx_ring_size = TDC_DEFAULT_MAX;
238730ac2e7bSml 	}
238830ac2e7bSml 
238944961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
239044961713Sgirish 	/*
239144961713Sgirish 	 * N2/NIU has limitation on the descriptor sizes (contiguous
239244961713Sgirish 	 * memory allocation on data buffers to 4M (contig_mem_alloc)
239344961713Sgirish 	 * and little endian for control buffers (must use the ddi/dki mem alloc
239444961713Sgirish 	 * function). The transmit ring is limited to 8K (includes the
239544961713Sgirish 	 * mailbox).
239644961713Sgirish 	 */
239744961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
239844961713Sgirish 		if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) ||
239944961713Sgirish 			(!ISP2(nxge_tx_ring_size))) {
240044961713Sgirish 			nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX;
240144961713Sgirish 		}
240244961713Sgirish 	}
240344961713Sgirish #endif
240444961713Sgirish 
240544961713Sgirish 	nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size;
240644961713Sgirish 
240744961713Sgirish 	/*
240844961713Sgirish 	 * Assume that each DMA channel will be configured with default
240944961713Sgirish 	 * transmit bufer size for copying transmit data.
241044961713Sgirish 	 * (For packet payload over this limit, packets will not be
241144961713Sgirish 	 *  copied.)
241244961713Sgirish 	 */
24131f8914d5Sml 	if (nxgep->niu_type == N2_NIU) {
24141f8914d5Sml 		bcopy_thresh = TX_BCOPY_SIZE;
24151f8914d5Sml 	} else {
24161f8914d5Sml 		bcopy_thresh = nxge_bcopy_thresh;
24171f8914d5Sml 	}
24181f8914d5Sml 	tx_buf_alloc_size = (bcopy_thresh * nxge_tx_ring_size);
241944961713Sgirish 
242044961713Sgirish 	/*
242144961713Sgirish 	 * Addresses of transmit descriptor ring and the
242244961713Sgirish 	 * mailbox must be all cache-aligned (64 bytes).
242344961713Sgirish 	 */
242444961713Sgirish 	tx_cntl_alloc_size = nxge_tx_ring_size;
242544961713Sgirish 	tx_cntl_alloc_size *= (sizeof (tx_desc_t));
242644961713Sgirish 	tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
242744961713Sgirish 
242844961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
242944961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
243044961713Sgirish 		if (!ISP2(tx_buf_alloc_size)) {
243144961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
243244961713Sgirish 				"==> nxge_alloc_tx_mem_pool: "
243344961713Sgirish 				" must be power of 2"));
243444961713Sgirish 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
243544961713Sgirish 			goto nxge_alloc_tx_mem_pool_exit;
243644961713Sgirish 		}
243744961713Sgirish 
243844961713Sgirish 		if (tx_buf_alloc_size > (1 << 22)) {
243944961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
244044961713Sgirish 				"==> nxge_alloc_tx_mem_pool: "
244144961713Sgirish 				" limit size to 4M"));
244244961713Sgirish 			status |= (NXGE_ERROR | NXGE_DDI_FAILED);
244344961713Sgirish 			goto nxge_alloc_tx_mem_pool_exit;
244444961713Sgirish 		}
244544961713Sgirish 
244644961713Sgirish 		if (tx_cntl_alloc_size < 0x2000) {
244744961713Sgirish 			tx_cntl_alloc_size = 0x2000;
244844961713Sgirish 		}
244944961713Sgirish 	}
245044961713Sgirish #endif
245144961713Sgirish 
245244961713Sgirish 	num_chunks = (uint32_t *)KMEM_ZALLOC(
245344961713Sgirish 			sizeof (uint32_t) * ndmas, KM_SLEEP);
245444961713Sgirish 
245544961713Sgirish 	/*
245644961713Sgirish 	 * Allocate memory for transmit buffers and descriptor rings.
245744961713Sgirish 	 * Replace allocation functions with interface functions provided
245844961713Sgirish 	 * by the partition manager when it is available.
245944961713Sgirish 	 *
246044961713Sgirish 	 * Allocate memory for the transmit buffer pool.
246144961713Sgirish 	 */
246244961713Sgirish 	for (i = 0; i < ndmas; i++) {
246344961713Sgirish 		num_chunks[i] = 0;
246444961713Sgirish 		status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i],
246544961713Sgirish 					tx_buf_alloc_size,
24661f8914d5Sml 					bcopy_thresh, &num_chunks[i]);
246744961713Sgirish 		if (status != NXGE_OK) {
246844961713Sgirish 			break;
246944961713Sgirish 		}
247044961713Sgirish 		st_tdc++;
247144961713Sgirish 	}
247244961713Sgirish 	if (i < ndmas) {
247344961713Sgirish 		goto nxge_alloc_tx_mem_pool_fail1;
247444961713Sgirish 	}
247544961713Sgirish 
247644961713Sgirish 	st_tdc = p_cfgp->start_tdc;
247744961713Sgirish 	/*
247844961713Sgirish 	 * Allocate memory for descriptor rings and mailbox.
247944961713Sgirish 	 */
248044961713Sgirish 	for (j = 0; j < ndmas; j++) {
248144961713Sgirish 		status = nxge_alloc_tx_cntl_dma(nxgep, st_tdc, &dma_cntl_p[j],
248244961713Sgirish 					tx_cntl_alloc_size);
248344961713Sgirish 		if (status != NXGE_OK) {
248444961713Sgirish 			break;
248544961713Sgirish 		}
248644961713Sgirish 		st_tdc++;
248744961713Sgirish 	}
248844961713Sgirish 	if (j < ndmas) {
248944961713Sgirish 		goto nxge_alloc_tx_mem_pool_fail2;
249044961713Sgirish 	}
249144961713Sgirish 
249244961713Sgirish 	dma_poolp->ndmas = ndmas;
249344961713Sgirish 	dma_poolp->num_chunks = num_chunks;
249444961713Sgirish 	dma_poolp->buf_allocated = B_TRUE;
249544961713Sgirish 	dma_poolp->dma_buf_pool_p = dma_buf_p;
249644961713Sgirish 	nxgep->tx_buf_pool_p = dma_poolp;
249744961713Sgirish 
249844961713Sgirish 	dma_cntl_poolp->ndmas = ndmas;
249944961713Sgirish 	dma_cntl_poolp->buf_allocated = B_TRUE;
250044961713Sgirish 	dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
250144961713Sgirish 	nxgep->tx_cntl_pool_p = dma_cntl_poolp;
250244961713Sgirish 
250344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL,
250444961713Sgirish 		"==> nxge_alloc_tx_mem_pool: start_tdc %d "
250544961713Sgirish 		"ndmas %d poolp->ndmas %d",
250644961713Sgirish 		st_tdc, ndmas, dma_poolp->ndmas));
250744961713Sgirish 
250844961713Sgirish 	goto nxge_alloc_tx_mem_pool_exit;
250944961713Sgirish 
251044961713Sgirish nxge_alloc_tx_mem_pool_fail2:
251144961713Sgirish 	/* Free control buffers */
251244961713Sgirish 	j--;
251344961713Sgirish 	for (; j >= 0; j--) {
251444961713Sgirish 		nxge_free_tx_cntl_dma(nxgep,
251556d930aeSspeer 			(p_nxge_dma_common_t)dma_cntl_p[j]);
251644961713Sgirish 	}
251744961713Sgirish 
251844961713Sgirish nxge_alloc_tx_mem_pool_fail1:
251944961713Sgirish 	/* Free data buffers */
252044961713Sgirish 	i--;
252144961713Sgirish 	for (; i >= 0; i--) {
252244961713Sgirish 		nxge_free_tx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i],
252344961713Sgirish 			num_chunks[i]);
252444961713Sgirish 	}
252544961713Sgirish 
252644961713Sgirish 	KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
252744961713Sgirish 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
252844961713Sgirish 	KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
252944961713Sgirish 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
253044961713Sgirish 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
253144961713Sgirish 
253244961713Sgirish nxge_alloc_tx_mem_pool_exit:
253344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL,
253444961713Sgirish 		"<== nxge_alloc_tx_mem_pool:status 0x%08x", status));
253544961713Sgirish 
253644961713Sgirish 	return (status);
253744961713Sgirish }
253844961713Sgirish 
253944961713Sgirish static nxge_status_t
254044961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
254144961713Sgirish     p_nxge_dma_common_t *dmap, size_t alloc_size,
254244961713Sgirish     size_t block_size, uint32_t *num_chunks)
254344961713Sgirish {
254444961713Sgirish 	p_nxge_dma_common_t 	tx_dmap;
254544961713Sgirish 	nxge_status_t		status = NXGE_OK;
254644961713Sgirish 	size_t			total_alloc_size;
254744961713Sgirish 	size_t			allocated = 0;
254844961713Sgirish 	int			i, size_index, array_size;
254944961713Sgirish 
255044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma"));
255144961713Sgirish 
255244961713Sgirish 	tx_dmap = (p_nxge_dma_common_t)
255344961713Sgirish 		KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
255444961713Sgirish 			KM_SLEEP);
255544961713Sgirish 
255644961713Sgirish 	total_alloc_size = alloc_size;
255744961713Sgirish 	i = 0;
255844961713Sgirish 	size_index = 0;
255944961713Sgirish 	array_size =  sizeof (alloc_sizes) /  sizeof (size_t);
256044961713Sgirish 	while ((alloc_sizes[size_index] < alloc_size) &&
256144961713Sgirish 		(size_index < array_size))
256244961713Sgirish 		size_index++;
256344961713Sgirish 	if (size_index >= array_size) {
256444961713Sgirish 		size_index = array_size - 1;
256544961713Sgirish 	}
256644961713Sgirish 
256744961713Sgirish 	while ((allocated < total_alloc_size) &&
256844961713Sgirish 			(size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
256944961713Sgirish 
257044961713Sgirish 		tx_dmap[i].dma_chunk_index = i;
257144961713Sgirish 		tx_dmap[i].block_size = block_size;
257244961713Sgirish 		tx_dmap[i].alength = alloc_sizes[size_index];
257344961713Sgirish 		tx_dmap[i].orig_alength = tx_dmap[i].alength;
257444961713Sgirish 		tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
257544961713Sgirish 		tx_dmap[i].dma_channel = dma_channel;
257644961713Sgirish 		tx_dmap[i].contig_alloc_type = B_FALSE;
257744961713Sgirish 
257844961713Sgirish 		/*
257944961713Sgirish 		 * N2/NIU: data buffers must be contiguous as the driver
258044961713Sgirish 		 *	   needs to call Hypervisor api to set up
258144961713Sgirish 		 *	   logical pages.
258244961713Sgirish 		 */
258344961713Sgirish 		if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
258444961713Sgirish 			tx_dmap[i].contig_alloc_type = B_TRUE;
258544961713Sgirish 		}
258644961713Sgirish 
258744961713Sgirish 		status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
258844961713Sgirish 			&nxge_tx_dma_attr,
258944961713Sgirish 			tx_dmap[i].alength,
259044961713Sgirish 			&nxge_dev_buf_dma_acc_attr,
259144961713Sgirish 			DDI_DMA_WRITE | DDI_DMA_STREAMING,
259244961713Sgirish 			(p_nxge_dma_common_t)(&tx_dmap[i]));
259344961713Sgirish 		if (status != NXGE_OK) {
259444961713Sgirish 			size_index--;
259544961713Sgirish 		} else {
259644961713Sgirish 			i++;
259744961713Sgirish 			allocated += alloc_sizes[size_index];
259844961713Sgirish 		}
259944961713Sgirish 	}
260044961713Sgirish 
260144961713Sgirish 	if (allocated < total_alloc_size) {
260230ac2e7bSml 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
260330ac2e7bSml 		    "==> nxge_alloc_tx_buf_dma: not enough channel %d: "
260430ac2e7bSml 		    "allocated 0x%x requested 0x%x",
260530ac2e7bSml 		    dma_channel,
260630ac2e7bSml 		    allocated, total_alloc_size));
260730ac2e7bSml 		status = NXGE_ERROR;
260844961713Sgirish 		goto nxge_alloc_tx_mem_fail1;
260944961713Sgirish 	}
261044961713Sgirish 
261130ac2e7bSml 	NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
261230ac2e7bSml 	    "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: "
261330ac2e7bSml 	    "allocated 0x%x requested 0x%x",
261430ac2e7bSml 	    dma_channel,
261530ac2e7bSml 	    allocated, total_alloc_size));
261630ac2e7bSml 
261744961713Sgirish 	*num_chunks = i;
261844961713Sgirish 	*dmap = tx_dmap;
261944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
262044961713Sgirish 		"==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
262144961713Sgirish 		*dmap, i));
262244961713Sgirish 	goto nxge_alloc_tx_mem_exit;
262344961713Sgirish 
262444961713Sgirish nxge_alloc_tx_mem_fail1:
262544961713Sgirish 	KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
262644961713Sgirish 
262744961713Sgirish nxge_alloc_tx_mem_exit:
262844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
262944961713Sgirish 		"<== nxge_alloc_tx_buf_dma status 0x%08x", status));
263044961713Sgirish 
263144961713Sgirish 	return (status);
263244961713Sgirish }
263344961713Sgirish 
263444961713Sgirish /*ARGSUSED*/
263544961713Sgirish static void
263644961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
263744961713Sgirish     uint32_t num_chunks)
263844961713Sgirish {
263944961713Sgirish 	int		i;
264044961713Sgirish 
264144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma"));
264244961713Sgirish 
264344961713Sgirish 	for (i = 0; i < num_chunks; i++) {
264444961713Sgirish 		nxge_dma_mem_free(dmap++);
264544961713Sgirish 	}
264644961713Sgirish 
264744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma"));
264844961713Sgirish }
264944961713Sgirish 
265044961713Sgirish /*ARGSUSED*/
265144961713Sgirish static nxge_status_t
265244961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
265344961713Sgirish     p_nxge_dma_common_t *dmap, size_t size)
265444961713Sgirish {
265544961713Sgirish 	p_nxge_dma_common_t 	tx_dmap;
265644961713Sgirish 	nxge_status_t		status = NXGE_OK;
265744961713Sgirish 
265844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma"));
265944961713Sgirish 	tx_dmap = (p_nxge_dma_common_t)
266044961713Sgirish 			KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
266144961713Sgirish 
266244961713Sgirish 	tx_dmap->contig_alloc_type = B_FALSE;
266344961713Sgirish 
266444961713Sgirish 	status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
266544961713Sgirish 			&nxge_desc_dma_attr,
266644961713Sgirish 			size,
266744961713Sgirish 			&nxge_dev_desc_dma_acc_attr,
266844961713Sgirish 			DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
266944961713Sgirish 			tx_dmap);
267044961713Sgirish 	if (status != NXGE_OK) {
267144961713Sgirish 		goto nxge_alloc_tx_cntl_dma_fail1;
267244961713Sgirish 	}
267344961713Sgirish 
267444961713Sgirish 	*dmap = tx_dmap;
267544961713Sgirish 	goto nxge_alloc_tx_cntl_dma_exit;
267644961713Sgirish 
267744961713Sgirish nxge_alloc_tx_cntl_dma_fail1:
267844961713Sgirish 	KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t));
267944961713Sgirish 
268044961713Sgirish nxge_alloc_tx_cntl_dma_exit:
268144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL,
268244961713Sgirish 		"<== nxge_alloc_tx_cntl_dma status 0x%08x", status));
268344961713Sgirish 
268444961713Sgirish 	return (status);
268544961713Sgirish }
268644961713Sgirish 
268744961713Sgirish /*ARGSUSED*/
268844961713Sgirish static void
268944961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
269044961713Sgirish {
269144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma"));
269244961713Sgirish 
269344961713Sgirish 	nxge_dma_mem_free(dmap);
269444961713Sgirish 
269544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma"));
269644961713Sgirish }
269744961713Sgirish 
269844961713Sgirish static void
269944961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep)
270044961713Sgirish {
270144961713Sgirish 	uint32_t		i, ndmas;
270244961713Sgirish 	p_nxge_dma_pool_t	dma_poolp;
270344961713Sgirish 	p_nxge_dma_common_t	*dma_buf_p;
270444961713Sgirish 	p_nxge_dma_pool_t	dma_cntl_poolp;
270544961713Sgirish 	p_nxge_dma_common_t	*dma_cntl_p;
270644961713Sgirish 	uint32_t 		*num_chunks;
270744961713Sgirish 
270844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_free_tx_mem_pool"));
270944961713Sgirish 
271044961713Sgirish 	dma_poolp = nxgep->tx_buf_pool_p;
271144961713Sgirish 	if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
271244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
271344961713Sgirish 			"<== nxge_free_tx_mem_pool "
271444961713Sgirish 			"(null rx buf pool or buf not allocated"));
271544961713Sgirish 		return;
271644961713Sgirish 	}
271744961713Sgirish 
271844961713Sgirish 	dma_cntl_poolp = nxgep->tx_cntl_pool_p;
271944961713Sgirish 	if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
272044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
272144961713Sgirish 			"<== nxge_free_tx_mem_pool "
272244961713Sgirish 			"(null tx cntl buf pool or cntl buf not allocated"));
272344961713Sgirish 		return;
272444961713Sgirish 	}
272544961713Sgirish 
272644961713Sgirish 	dma_buf_p = dma_poolp->dma_buf_pool_p;
272744961713Sgirish 	num_chunks = dma_poolp->num_chunks;
272844961713Sgirish 
272944961713Sgirish 	dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
273044961713Sgirish 	ndmas = dma_cntl_poolp->ndmas;
273144961713Sgirish 
273244961713Sgirish 	for (i = 0; i < ndmas; i++) {
273344961713Sgirish 		nxge_free_tx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]);
273444961713Sgirish 	}
273544961713Sgirish 
273644961713Sgirish 	for (i = 0; i < ndmas; i++) {
273744961713Sgirish 		nxge_free_tx_cntl_dma(nxgep, dma_cntl_p[i]);
273844961713Sgirish 	}
273944961713Sgirish 
274044961713Sgirish 	for (i = 0; i < ndmas; i++) {
274144961713Sgirish 		KMEM_FREE(dma_buf_p[i],
274244961713Sgirish 			sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
274344961713Sgirish 		KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t));
274444961713Sgirish 	}
274544961713Sgirish 
274644961713Sgirish 	KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
274744961713Sgirish 	KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
274844961713Sgirish 	KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
274944961713Sgirish 	KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
275044961713Sgirish 	KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
275144961713Sgirish 
275244961713Sgirish 	nxgep->tx_buf_pool_p = NULL;
275344961713Sgirish 	nxgep->tx_cntl_pool_p = NULL;
275444961713Sgirish 
275544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_free_tx_mem_pool"));
275644961713Sgirish }
275744961713Sgirish 
275844961713Sgirish /*ARGSUSED*/
275944961713Sgirish static nxge_status_t
276044961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method,
276144961713Sgirish 	struct ddi_dma_attr *dma_attrp,
276244961713Sgirish 	size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
276344961713Sgirish 	p_nxge_dma_common_t dma_p)
276444961713Sgirish {
276544961713Sgirish 	caddr_t 		kaddrp;
276644961713Sgirish 	int			ddi_status = DDI_SUCCESS;
276744961713Sgirish 	boolean_t		contig_alloc_type;
276844961713Sgirish 
276944961713Sgirish 	contig_alloc_type = dma_p->contig_alloc_type;
277044961713Sgirish 
277144961713Sgirish 	if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) {
277244961713Sgirish 		/*
277344961713Sgirish 		 * contig_alloc_type for contiguous memory only allowed
277444961713Sgirish 		 * for N2/NIU.
277544961713Sgirish 		 */
277644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
277744961713Sgirish 			"nxge_dma_mem_alloc: alloc type not allows (%d)",
277844961713Sgirish 			dma_p->contig_alloc_type));
277944961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
278044961713Sgirish 	}
278144961713Sgirish 
278244961713Sgirish 	dma_p->dma_handle = NULL;
278344961713Sgirish 	dma_p->acc_handle = NULL;
278444961713Sgirish 	dma_p->kaddrp = dma_p->last_kaddrp = NULL;
278544961713Sgirish 	dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL;
278644961713Sgirish 	ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp,
278744961713Sgirish 		DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
278844961713Sgirish 	if (ddi_status != DDI_SUCCESS) {
278944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
279044961713Sgirish 			"nxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
279144961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
279244961713Sgirish 	}
279344961713Sgirish 
279444961713Sgirish 	switch (contig_alloc_type) {
279544961713Sgirish 	case B_FALSE:
279644961713Sgirish 		ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length,
279744961713Sgirish 			acc_attr_p,
279844961713Sgirish 			xfer_flags,
279944961713Sgirish 			DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
280044961713Sgirish 			&dma_p->acc_handle);
280144961713Sgirish 		if (ddi_status != DDI_SUCCESS) {
280244961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
280344961713Sgirish 				"nxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
280444961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
280544961713Sgirish 			dma_p->dma_handle = NULL;
280644961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
280744961713Sgirish 		}
280844961713Sgirish 		if (dma_p->alength < length) {
280944961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
281044961713Sgirish 				"nxge_dma_mem_alloc:ddi_dma_mem_alloc "
281144961713Sgirish 				"< length."));
281244961713Sgirish 			ddi_dma_mem_free(&dma_p->acc_handle);
281344961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
281444961713Sgirish 			dma_p->acc_handle = NULL;
281544961713Sgirish 			dma_p->dma_handle = NULL;
281644961713Sgirish 			return (NXGE_ERROR);
281744961713Sgirish 		}
281844961713Sgirish 
281944961713Sgirish 		ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
282044961713Sgirish 			kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
282144961713Sgirish 			&dma_p->dma_cookie, &dma_p->ncookies);
282244961713Sgirish 		if (ddi_status != DDI_DMA_MAPPED) {
282344961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
282444961713Sgirish 				"nxge_dma_mem_alloc:di_dma_addr_bind failed "
282544961713Sgirish 				"(staus 0x%x ncookies %d.)", ddi_status,
282644961713Sgirish 				dma_p->ncookies));
282744961713Sgirish 			if (dma_p->acc_handle) {
282844961713Sgirish 				ddi_dma_mem_free(&dma_p->acc_handle);
282944961713Sgirish 				dma_p->acc_handle = NULL;
283044961713Sgirish 			}
283144961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
283244961713Sgirish 			dma_p->dma_handle = NULL;
283344961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
283444961713Sgirish 		}
283544961713Sgirish 
283644961713Sgirish 		if (dma_p->ncookies != 1) {
283744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DMA_CTL,
283844961713Sgirish 				"nxge_dma_mem_alloc:ddi_dma_addr_bind "
283944961713Sgirish 				"> 1 cookie"
284044961713Sgirish 				"(staus 0x%x ncookies %d.)", ddi_status,
284144961713Sgirish 				dma_p->ncookies));
284244961713Sgirish 			if (dma_p->acc_handle) {
284344961713Sgirish 				ddi_dma_mem_free(&dma_p->acc_handle);
284444961713Sgirish 				dma_p->acc_handle = NULL;
284544961713Sgirish 			}
284656d930aeSspeer 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
284744961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
284844961713Sgirish 			dma_p->dma_handle = NULL;
284944961713Sgirish 			return (NXGE_ERROR);
285044961713Sgirish 		}
285144961713Sgirish 		break;
285244961713Sgirish 
285344961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
285444961713Sgirish 	case B_TRUE:
285544961713Sgirish 		kaddrp = (caddr_t)contig_mem_alloc(length);
285644961713Sgirish 		if (kaddrp == NULL) {
285744961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
285844961713Sgirish 				"nxge_dma_mem_alloc:contig_mem_alloc failed."));
285944961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
286044961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
286144961713Sgirish 		}
286244961713Sgirish 
286344961713Sgirish 		dma_p->alength = length;
286444961713Sgirish 		ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
286544961713Sgirish 			kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
286644961713Sgirish 			&dma_p->dma_cookie, &dma_p->ncookies);
286744961713Sgirish 		if (ddi_status != DDI_DMA_MAPPED) {
286844961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
286944961713Sgirish 				"nxge_dma_mem_alloc:di_dma_addr_bind failed "
287044961713Sgirish 				"(status 0x%x ncookies %d.)", ddi_status,
287144961713Sgirish 				dma_p->ncookies));
287244961713Sgirish 
287344961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DMA_CTL,
287444961713Sgirish 				"==> nxge_dma_mem_alloc: (not mapped)"
287544961713Sgirish 				"length %lu (0x%x) "
287644961713Sgirish 				"free contig kaddrp $%p "
287744961713Sgirish 				"va_to_pa $%p",
287844961713Sgirish 				length, length,
287944961713Sgirish 				kaddrp,
288044961713Sgirish 				va_to_pa(kaddrp)));
288144961713Sgirish 
288244961713Sgirish 
288344961713Sgirish 			contig_mem_free((void *)kaddrp, length);
288444961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
288544961713Sgirish 
288644961713Sgirish 			dma_p->dma_handle = NULL;
288744961713Sgirish 			dma_p->acc_handle = NULL;
288844961713Sgirish 			dma_p->alength = NULL;
288944961713Sgirish 			dma_p->kaddrp = NULL;
289044961713Sgirish 
289144961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
289244961713Sgirish 		}
289344961713Sgirish 
289444961713Sgirish 		if (dma_p->ncookies != 1 ||
289544961713Sgirish 			(dma_p->dma_cookie.dmac_laddress == NULL)) {
289644961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
289744961713Sgirish 				"nxge_dma_mem_alloc:di_dma_addr_bind > 1 "
289844961713Sgirish 				"cookie or "
289944961713Sgirish 				"dmac_laddress is NULL $%p size %d "
290044961713Sgirish 				" (status 0x%x ncookies %d.)",
290144961713Sgirish 				ddi_status,
290244961713Sgirish 				dma_p->dma_cookie.dmac_laddress,
290344961713Sgirish 				dma_p->dma_cookie.dmac_size,
290444961713Sgirish 				dma_p->ncookies));
290544961713Sgirish 
290644961713Sgirish 			contig_mem_free((void *)kaddrp, length);
290756d930aeSspeer 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
290844961713Sgirish 			ddi_dma_free_handle(&dma_p->dma_handle);
290944961713Sgirish 
291044961713Sgirish 			dma_p->alength = 0;
291144961713Sgirish 			dma_p->dma_handle = NULL;
291244961713Sgirish 			dma_p->acc_handle = NULL;
291344961713Sgirish 			dma_p->kaddrp = NULL;
291444961713Sgirish 
291544961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
291644961713Sgirish 		}
291744961713Sgirish 		break;
291844961713Sgirish 
291944961713Sgirish #else
292044961713Sgirish 	case B_TRUE:
292144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
292244961713Sgirish 			"nxge_dma_mem_alloc: invalid alloc type for !sun4v"));
292344961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
292444961713Sgirish #endif
292544961713Sgirish 	}
292644961713Sgirish 
292744961713Sgirish 	dma_p->kaddrp = kaddrp;
292844961713Sgirish 	dma_p->last_kaddrp = (unsigned char *)kaddrp +
292944961713Sgirish 			dma_p->alength - RXBUF_64B_ALIGNED;
2930adfcba55Sjoycey #if defined(__i386)
2931adfcba55Sjoycey 	dma_p->ioaddr_pp =
2932adfcba55Sjoycey 		(unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress;
2933adfcba55Sjoycey #else
293444961713Sgirish 	dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress;
2935adfcba55Sjoycey #endif
293644961713Sgirish 	dma_p->last_ioaddr_pp =
2937adfcba55Sjoycey #if defined(__i386)
2938adfcba55Sjoycey 		(unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress +
2939adfcba55Sjoycey #else
294044961713Sgirish 		(unsigned char *)dma_p->dma_cookie.dmac_laddress +
2941adfcba55Sjoycey #endif
294244961713Sgirish 				dma_p->alength - RXBUF_64B_ALIGNED;
294344961713Sgirish 
294444961713Sgirish 	NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
294544961713Sgirish 
294644961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
294744961713Sgirish 	dma_p->orig_ioaddr_pp =
294844961713Sgirish 		(unsigned char *)dma_p->dma_cookie.dmac_laddress;
294944961713Sgirish 	dma_p->orig_alength = length;
295044961713Sgirish 	dma_p->orig_kaddrp = kaddrp;
295144961713Sgirish 	dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp);
295244961713Sgirish #endif
295344961713Sgirish 
295444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: "
295544961713Sgirish 		"dma buffer allocated: dma_p $%p "
295644961713Sgirish 		"return dmac_ladress from cookie $%p cookie dmac_size %d "
295744961713Sgirish 		"dma_p->ioaddr_p $%p "
295844961713Sgirish 		"dma_p->orig_ioaddr_p $%p "
295944961713Sgirish 		"orig_vatopa $%p "
296044961713Sgirish 		"alength %d (0x%x) "
296144961713Sgirish 		"kaddrp $%p "
296244961713Sgirish 		"length %d (0x%x)",
296344961713Sgirish 		dma_p,
296444961713Sgirish 		dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size,
296544961713Sgirish 		dma_p->ioaddr_pp,
296644961713Sgirish 		dma_p->orig_ioaddr_pp,
296744961713Sgirish 		dma_p->orig_vatopa,
296844961713Sgirish 		dma_p->alength, dma_p->alength,
296944961713Sgirish 		kaddrp,
297044961713Sgirish 		length, length));
297144961713Sgirish 
297244961713Sgirish 	return (NXGE_OK);
297344961713Sgirish }
297444961713Sgirish 
297544961713Sgirish static void
297644961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p)
297744961713Sgirish {
297844961713Sgirish 	if (dma_p->dma_handle != NULL) {
297944961713Sgirish 		if (dma_p->ncookies) {
298044961713Sgirish 			(void) ddi_dma_unbind_handle(dma_p->dma_handle);
298144961713Sgirish 			dma_p->ncookies = 0;
298244961713Sgirish 		}
298344961713Sgirish 		ddi_dma_free_handle(&dma_p->dma_handle);
298444961713Sgirish 		dma_p->dma_handle = NULL;
298544961713Sgirish 	}
298644961713Sgirish 
298744961713Sgirish 	if (dma_p->acc_handle != NULL) {
298844961713Sgirish 		ddi_dma_mem_free(&dma_p->acc_handle);
298944961713Sgirish 		dma_p->acc_handle = NULL;
299044961713Sgirish 		NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
299144961713Sgirish 	}
299244961713Sgirish 
299344961713Sgirish #if	defined(sun4v) && defined(NIU_LP_WORKAROUND)
299444961713Sgirish 	if (dma_p->contig_alloc_type &&
299544961713Sgirish 			dma_p->orig_kaddrp && dma_p->orig_alength) {
299644961713Sgirish 		NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: "
299744961713Sgirish 			"kaddrp $%p (orig_kaddrp $%p)"
299844961713Sgirish 			"mem type %d ",
299944961713Sgirish 			"orig_alength %d "
300044961713Sgirish 			"alength 0x%x (%d)",
300144961713Sgirish 			dma_p->kaddrp,
300244961713Sgirish 			dma_p->orig_kaddrp,
300344961713Sgirish 			dma_p->contig_alloc_type,
300444961713Sgirish 			dma_p->orig_alength,
300544961713Sgirish 			dma_p->alength, dma_p->alength));
300644961713Sgirish 
300744961713Sgirish 		contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength);
300844961713Sgirish 		dma_p->orig_alength = NULL;
300944961713Sgirish 		dma_p->orig_kaddrp = NULL;
301044961713Sgirish 		dma_p->contig_alloc_type = B_FALSE;
301144961713Sgirish 	}
301244961713Sgirish #endif
301344961713Sgirish 	dma_p->kaddrp = NULL;
301444961713Sgirish 	dma_p->alength = NULL;
301544961713Sgirish }
301644961713Sgirish 
301744961713Sgirish /*
301844961713Sgirish  *	nxge_m_start() -- start transmitting and receiving.
301944961713Sgirish  *
302044961713Sgirish  *	This function is called by the MAC layer when the first
302144961713Sgirish  *	stream is open to prepare the hardware ready for sending
302244961713Sgirish  *	and transmitting packets.
302344961713Sgirish  */
302444961713Sgirish static int
302544961713Sgirish nxge_m_start(void *arg)
302644961713Sgirish {
302744961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
302844961713Sgirish 
302944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start"));
303044961713Sgirish 
303144961713Sgirish 	MUTEX_ENTER(nxgep->genlock);
303214ea4bb7Ssd 	if (nxge_init(nxgep) != NXGE_OK) {
303344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
303444961713Sgirish 			"<== nxge_m_start: initialization failed"));
303544961713Sgirish 		MUTEX_EXIT(nxgep->genlock);
303644961713Sgirish 		return (EIO);
303744961713Sgirish 	}
303844961713Sgirish 
303914ea4bb7Ssd 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED)
304014ea4bb7Ssd 		goto nxge_m_start_exit;
304144961713Sgirish 	/*
304244961713Sgirish 	 * Start timer to check the system error and tx hangs
304344961713Sgirish 	 */
304444961713Sgirish 	nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state,
304544961713Sgirish 		NXGE_CHECK_TIMER);
304644961713Sgirish 
3047a3c5bd6dSspeer 	nxgep->link_notify = B_TRUE;
3048a3c5bd6dSspeer 
304944961713Sgirish 	nxgep->nxge_mac_state = NXGE_MAC_STARTED;
305044961713Sgirish 
305114ea4bb7Ssd nxge_m_start_exit:
305244961713Sgirish 	MUTEX_EXIT(nxgep->genlock);
305344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start"));
305444961713Sgirish 	return (0);
305544961713Sgirish }
305644961713Sgirish 
305744961713Sgirish /*
305844961713Sgirish  *	nxge_m_stop(): stop transmitting and receiving.
305944961713Sgirish  */
306044961713Sgirish static void
306144961713Sgirish nxge_m_stop(void *arg)
306244961713Sgirish {
306344961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
306444961713Sgirish 
306544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop"));
306644961713Sgirish 
306744961713Sgirish 	if (nxgep->nxge_timerid) {
306844961713Sgirish 		nxge_stop_timer(nxgep, nxgep->nxge_timerid);
306944961713Sgirish 		nxgep->nxge_timerid = 0;
307044961713Sgirish 	}
3071a3c5bd6dSspeer 
3072a3c5bd6dSspeer 	MUTEX_ENTER(nxgep->genlock);
307344961713Sgirish 	nxge_uninit(nxgep);
307444961713Sgirish 
307544961713Sgirish 	nxgep->nxge_mac_state = NXGE_MAC_STOPPED;
307644961713Sgirish 
307744961713Sgirish 	MUTEX_EXIT(nxgep->genlock);
307844961713Sgirish 
307944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop"));
308044961713Sgirish }
308144961713Sgirish 
308244961713Sgirish static int
308344961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr)
308444961713Sgirish {
308544961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
308644961713Sgirish 	struct 		ether_addr addrp;
308744961713Sgirish 
308844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst"));
308944961713Sgirish 
309044961713Sgirish 	bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL);
309144961713Sgirish 	if (nxge_set_mac_addr(nxgep, &addrp)) {
309244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
309344961713Sgirish 			"<== nxge_m_unicst: set unitcast failed"));
309444961713Sgirish 		return (EINVAL);
309544961713Sgirish 	}
309644961713Sgirish 
309744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst"));
309844961713Sgirish 
309944961713Sgirish 	return (0);
310044961713Sgirish }
310144961713Sgirish 
310244961713Sgirish static int
310344961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
310444961713Sgirish {
310544961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
310644961713Sgirish 	struct 		ether_addr addrp;
310744961713Sgirish 
310844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
310944961713Sgirish 		"==> nxge_m_multicst: add %d", add));
311044961713Sgirish 
311144961713Sgirish 	bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
311244961713Sgirish 	if (add) {
311344961713Sgirish 		if (nxge_add_mcast_addr(nxgep, &addrp)) {
311444961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
311544961713Sgirish 				"<== nxge_m_multicst: add multicast failed"));
311644961713Sgirish 			return (EINVAL);
311744961713Sgirish 		}
311844961713Sgirish 	} else {
311944961713Sgirish 		if (nxge_del_mcast_addr(nxgep, &addrp)) {
312044961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
312144961713Sgirish 				"<== nxge_m_multicst: del multicast failed"));
312244961713Sgirish 			return (EINVAL);
312344961713Sgirish 		}
312444961713Sgirish 	}
312544961713Sgirish 
312644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst"));
312744961713Sgirish 
312844961713Sgirish 	return (0);
312944961713Sgirish }
313044961713Sgirish 
313144961713Sgirish static int
313244961713Sgirish nxge_m_promisc(void *arg, boolean_t on)
313344961713Sgirish {
313444961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
313544961713Sgirish 
313644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
313744961713Sgirish 		"==> nxge_m_promisc: on %d", on));
313844961713Sgirish 
313944961713Sgirish 	if (nxge_set_promisc(nxgep, on)) {
314044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
314144961713Sgirish 			"<== nxge_m_promisc: set promisc failed"));
314244961713Sgirish 		return (EINVAL);
314344961713Sgirish 	}
314444961713Sgirish 
314544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
314644961713Sgirish 		"<== nxge_m_promisc: on %d", on));
314744961713Sgirish 
314844961713Sgirish 	return (0);
314944961713Sgirish }
315044961713Sgirish 
315144961713Sgirish static void
315244961713Sgirish nxge_m_ioctl(void *arg,  queue_t *wq, mblk_t *mp)
315344961713Sgirish {
315444961713Sgirish 	p_nxge_t 	nxgep = (p_nxge_t)arg;
315556d930aeSspeer 	struct 		iocblk *iocp;
315644961713Sgirish 	boolean_t 	need_privilege;
315744961713Sgirish 	int 		err;
315844961713Sgirish 	int 		cmd;
315944961713Sgirish 
316044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl"));
316144961713Sgirish 
316244961713Sgirish 	iocp = (struct iocblk *)mp->b_rptr;
316344961713Sgirish 	iocp->ioc_error = 0;
316444961713Sgirish 	need_privilege = B_TRUE;
316544961713Sgirish 	cmd = iocp->ioc_cmd;
316644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd));
316744961713Sgirish 	switch (cmd) {
316844961713Sgirish 	default:
316944961713Sgirish 		miocnak(wq, mp, 0, EINVAL);
317044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid"));
317144961713Sgirish 		return;
317244961713Sgirish 
317344961713Sgirish 	case LB_GET_INFO_SIZE:
317444961713Sgirish 	case LB_GET_INFO:
317544961713Sgirish 	case LB_GET_MODE:
317644961713Sgirish 		need_privilege = B_FALSE;
317744961713Sgirish 		break;
317844961713Sgirish 	case LB_SET_MODE:
317944961713Sgirish 		break;
318044961713Sgirish 
318144961713Sgirish 	case ND_GET:
318244961713Sgirish 		need_privilege = B_FALSE;
318344961713Sgirish 		break;
318444961713Sgirish 	case ND_SET:
318544961713Sgirish 		break;
318644961713Sgirish 
318744961713Sgirish 	case NXGE_GET_MII:
318844961713Sgirish 	case NXGE_PUT_MII:
318944961713Sgirish 	case NXGE_GET64:
319044961713Sgirish 	case NXGE_PUT64:
319144961713Sgirish 	case NXGE_GET_TX_RING_SZ:
319244961713Sgirish 	case NXGE_GET_TX_DESC:
319344961713Sgirish 	case NXGE_TX_SIDE_RESET:
319444961713Sgirish 	case NXGE_RX_SIDE_RESET:
319544961713Sgirish 	case NXGE_GLOBAL_RESET:
319644961713Sgirish 	case NXGE_RESET_MAC:
319744961713Sgirish 	case NXGE_TX_REGS_DUMP:
319844961713Sgirish 	case NXGE_RX_REGS_DUMP:
319944961713Sgirish 	case NXGE_INT_REGS_DUMP:
320044961713Sgirish 	case NXGE_VIR_INT_REGS_DUMP:
320144961713Sgirish 	case NXGE_PUT_TCAM:
320244961713Sgirish 	case NXGE_GET_TCAM:
320344961713Sgirish 	case NXGE_RTRACE:
320444961713Sgirish 	case NXGE_RDUMP:
320544961713Sgirish 
320644961713Sgirish 		need_privilege = B_FALSE;
320744961713Sgirish 		break;
320844961713Sgirish 	case NXGE_INJECT_ERR:
320944961713Sgirish 		cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n");
321044961713Sgirish 		nxge_err_inject(nxgep, wq, mp);
321144961713Sgirish 		break;
321244961713Sgirish 	}
321344961713Sgirish 
321444961713Sgirish 	if (need_privilege) {
321556d930aeSspeer 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
321644961713Sgirish 		if (err != 0) {
321744961713Sgirish 			miocnak(wq, mp, 0, err);
321844961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
321944961713Sgirish 				"<== nxge_m_ioctl: no priv"));
322044961713Sgirish 			return;
322144961713Sgirish 		}
322244961713Sgirish 	}
322344961713Sgirish 
322444961713Sgirish 	switch (cmd) {
322544961713Sgirish 	case ND_GET:
322644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_GET command"));
322744961713Sgirish 	case ND_SET:
322844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_SET command"));
322944961713Sgirish 		nxge_param_ioctl(nxgep, wq, mp, iocp);
323044961713Sgirish 		break;
323144961713Sgirish 
323244961713Sgirish 	case LB_GET_MODE:
323344961713Sgirish 	case LB_SET_MODE:
323444961713Sgirish 	case LB_GET_INFO_SIZE:
323544961713Sgirish 	case LB_GET_INFO:
323644961713Sgirish 		nxge_loopback_ioctl(nxgep, wq, mp, iocp);
323744961713Sgirish 		break;
323844961713Sgirish 
323944961713Sgirish 	case NXGE_GET_MII:
324044961713Sgirish 	case NXGE_PUT_MII:
324144961713Sgirish 	case NXGE_PUT_TCAM:
324244961713Sgirish 	case NXGE_GET_TCAM:
324344961713Sgirish 	case NXGE_GET64:
324444961713Sgirish 	case NXGE_PUT64:
324544961713Sgirish 	case NXGE_GET_TX_RING_SZ:
324644961713Sgirish 	case NXGE_GET_TX_DESC:
324744961713Sgirish 	case NXGE_TX_SIDE_RESET:
324844961713Sgirish 	case NXGE_RX_SIDE_RESET:
324944961713Sgirish 	case NXGE_GLOBAL_RESET:
325044961713Sgirish 	case NXGE_RESET_MAC:
325144961713Sgirish 	case NXGE_TX_REGS_DUMP:
325244961713Sgirish 	case NXGE_RX_REGS_DUMP:
325344961713Sgirish 	case NXGE_INT_REGS_DUMP:
325444961713Sgirish 	case NXGE_VIR_INT_REGS_DUMP:
325544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
325644961713Sgirish 			"==> nxge_m_ioctl: cmd 0x%x", cmd));
325744961713Sgirish 		nxge_hw_ioctl(nxgep, wq, mp, iocp);
325844961713Sgirish 		break;
325944961713Sgirish 	}
326044961713Sgirish 
326144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl"));
326244961713Sgirish }
326344961713Sgirish 
326444961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
326544961713Sgirish 
326644961713Sgirish static void
326744961713Sgirish nxge_m_resources(void *arg)
326844961713Sgirish {
326944961713Sgirish 	p_nxge_t		nxgep = arg;
327044961713Sgirish 	mac_rx_fifo_t 		mrf;
327144961713Sgirish 	p_rx_rcr_rings_t	rcr_rings;
327244961713Sgirish 	p_rx_rcr_ring_t		*rcr_p;
327344961713Sgirish 	uint32_t		i, ndmas;
327414ea4bb7Ssd 	nxge_status_t		status;
327544961713Sgirish 
327644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources"));
327744961713Sgirish 
327844961713Sgirish 	MUTEX_ENTER(nxgep->genlock);
327914ea4bb7Ssd 
328014ea4bb7Ssd 	/*
328158324dfcSspeer 	 * CR 6492541 Check to see if the drv_state has been initialized,
328214ea4bb7Ssd 	 * if not * call nxge_init().
328314ea4bb7Ssd 	 */
328414ea4bb7Ssd 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
328514ea4bb7Ssd 		status = nxge_init(nxgep);
328614ea4bb7Ssd 		if (status != NXGE_OK)
328714ea4bb7Ssd 			goto nxge_m_resources_exit;
328814ea4bb7Ssd 	}
328914ea4bb7Ssd 
329044961713Sgirish 	mrf.mrf_type = MAC_RX_FIFO;
329144961713Sgirish 	mrf.mrf_blank = nxge_rx_hw_blank;
329244961713Sgirish 	mrf.mrf_arg = (void *)nxgep;
329344961713Sgirish 
329444961713Sgirish 	mrf.mrf_normal_blank_time = 128;
329544961713Sgirish 	mrf.mrf_normal_pkt_count = 8;
329644961713Sgirish 	rcr_rings = nxgep->rx_rcr_rings;
329744961713Sgirish 	rcr_p = rcr_rings->rcr_rings;
329844961713Sgirish 	ndmas = rcr_rings->ndmas;
329944961713Sgirish 
330014ea4bb7Ssd 	/*
330114ea4bb7Ssd 	 * Export our receive resources to the MAC layer.
330214ea4bb7Ssd 	 */
330344961713Sgirish 	for (i = 0; i < ndmas; i++) {
330444961713Sgirish 		((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle =
330544961713Sgirish 				mac_resource_add(nxgep->mach,
330644961713Sgirish 				    (mac_resource_t *)&mrf);
330744961713Sgirish 
330844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
330944961713Sgirish 			"==> nxge_m_resources: vdma %d dma %d "
331044961713Sgirish 			"rcrptr 0x%016llx mac_handle 0x%016llx",
331144961713Sgirish 			i, ((p_rx_rcr_ring_t)rcr_p[i])->rdc,
331244961713Sgirish 			rcr_p[i],
331344961713Sgirish 			((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle));
331444961713Sgirish 	}
331544961713Sgirish 
331614ea4bb7Ssd nxge_m_resources_exit:
331744961713Sgirish 	MUTEX_EXIT(nxgep->genlock);
331844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources"));
331944961713Sgirish }
332044961713Sgirish 
332158324dfcSspeer static void
332258324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory)
332358324dfcSspeer {
332458324dfcSspeer 	p_nxge_mmac_stats_t mmac_stats;
332558324dfcSspeer 	int i;
332658324dfcSspeer 	nxge_mmac_t *mmac_info;
332758324dfcSspeer 
332858324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
332958324dfcSspeer 
333058324dfcSspeer 	mmac_stats = &nxgep->statsp->mmac_stats;
333158324dfcSspeer 	mmac_stats->mmac_max_cnt = mmac_info->num_mmac;
333258324dfcSspeer 	mmac_stats->mmac_avail_cnt = mmac_info->naddrfree;
333358324dfcSspeer 
333458324dfcSspeer 	for (i = 0; i < ETHERADDRL; i++) {
333558324dfcSspeer 		if (factory) {
333658324dfcSspeer 			mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
333758324dfcSspeer 			= mmac_info->factory_mac_pool[slot][(ETHERADDRL-1) - i];
333858324dfcSspeer 		} else {
333958324dfcSspeer 			mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i]
334058324dfcSspeer 			= mmac_info->mac_pool[slot].addr[(ETHERADDRL - 1) - i];
334158324dfcSspeer 		}
334258324dfcSspeer 	}
334358324dfcSspeer }
334458324dfcSspeer 
334558324dfcSspeer /*
334658324dfcSspeer  * nxge_altmac_set() -- Set an alternate MAC address
334758324dfcSspeer  */
334858324dfcSspeer static int
334958324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot)
335058324dfcSspeer {
335158324dfcSspeer 	uint8_t addrn;
335258324dfcSspeer 	uint8_t portn;
335358324dfcSspeer 	npi_mac_addr_t altmac;
33547b9fa28bSspeer 	hostinfo_t mac_rdc;
33557b9fa28bSspeer 	p_nxge_class_pt_cfg_t clscfgp;
335658324dfcSspeer 
335758324dfcSspeer 	altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff);
335858324dfcSspeer 	altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff);
335958324dfcSspeer 	altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff);
336058324dfcSspeer 
336158324dfcSspeer 	portn = nxgep->mac.portnum;
336258324dfcSspeer 	addrn = (uint8_t)slot - 1;
336358324dfcSspeer 
336458324dfcSspeer 	if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn,
336558324dfcSspeer 		addrn, &altmac) != NPI_SUCCESS)
336658324dfcSspeer 		return (EIO);
33677b9fa28bSspeer 
33687b9fa28bSspeer 	/*
33697b9fa28bSspeer 	 * Set the rdc table number for the host info entry
33707b9fa28bSspeer 	 * for this mac address slot.
33717b9fa28bSspeer 	 */
33727b9fa28bSspeer 	clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
33737b9fa28bSspeer 	mac_rdc.value = 0;
33747b9fa28bSspeer 	mac_rdc.bits.w0.rdc_tbl_num = clscfgp->mac_host_info[addrn].rdctbl;
33757b9fa28bSspeer 	mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr;
33767b9fa28bSspeer 
33777b9fa28bSspeer 	if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET,
33787b9fa28bSspeer 	    nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) {
33797b9fa28bSspeer 		return (EIO);
33807b9fa28bSspeer 	}
33817b9fa28bSspeer 
338258324dfcSspeer 	/*
338358324dfcSspeer 	 * Enable comparison with the alternate MAC address.
338458324dfcSspeer 	 * While the first alternate addr is enabled by bit 1 of register
338558324dfcSspeer 	 * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register
338658324dfcSspeer 	 * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn
338758324dfcSspeer 	 * accordingly before calling npi_mac_altaddr_entry.
338858324dfcSspeer 	 */
338958324dfcSspeer 	if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
339058324dfcSspeer 		addrn = (uint8_t)slot - 1;
339158324dfcSspeer 	else
339258324dfcSspeer 		addrn = (uint8_t)slot;
339358324dfcSspeer 
339458324dfcSspeer 	if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn)
339558324dfcSspeer 		!= NPI_SUCCESS)
339658324dfcSspeer 		return (EIO);
339758324dfcSspeer 
339858324dfcSspeer 	return (0);
339958324dfcSspeer }
340058324dfcSspeer 
340158324dfcSspeer /*
340258324dfcSspeer  * nxeg_m_mmac_add() - find an unused address slot, set the address
340358324dfcSspeer  * value to the one specified, enable the port to start filtering on
340458324dfcSspeer  * the new MAC address.  Returns 0 on success.
340558324dfcSspeer  */
340658324dfcSspeer static int
340758324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr)
340858324dfcSspeer {
340958324dfcSspeer 	p_nxge_t nxgep = arg;
341058324dfcSspeer 	mac_addr_slot_t slot;
341158324dfcSspeer 	nxge_mmac_t *mmac_info;
341258324dfcSspeer 	int err;
341358324dfcSspeer 	nxge_status_t status;
341458324dfcSspeer 
341558324dfcSspeer 	mutex_enter(nxgep->genlock);
341658324dfcSspeer 
341758324dfcSspeer 	/*
341858324dfcSspeer 	 * Make sure that nxge is initialized, if _start() has
341958324dfcSspeer 	 * not been called.
342058324dfcSspeer 	 */
342158324dfcSspeer 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
342258324dfcSspeer 		status = nxge_init(nxgep);
342358324dfcSspeer 		if (status != NXGE_OK) {
342458324dfcSspeer 			mutex_exit(nxgep->genlock);
342558324dfcSspeer 			return (ENXIO);
342658324dfcSspeer 		}
342758324dfcSspeer 	}
342858324dfcSspeer 
342958324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
343058324dfcSspeer 	if (mmac_info->naddrfree == 0) {
343158324dfcSspeer 		mutex_exit(nxgep->genlock);
343258324dfcSspeer 		return (ENOSPC);
343358324dfcSspeer 	}
343458324dfcSspeer 	if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr,
343558324dfcSspeer 		maddr->mma_addrlen)) {
343658324dfcSspeer 		mutex_exit(nxgep->genlock);
343758324dfcSspeer 		return (EINVAL);
343858324dfcSspeer 	}
343958324dfcSspeer 	/*
344058324dfcSspeer 	 * 	Search for the first available slot. Because naddrfree
344158324dfcSspeer 	 * is not zero, we are guaranteed to find one.
344258324dfcSspeer 	 * 	Slot 0 is for unique (primary) MAC. The first alternate
344358324dfcSspeer 	 * MAC slot is slot 1.
344458324dfcSspeer 	 *	Each of the first two ports of Neptune has 16 alternate
344556d930aeSspeer 	 * MAC slots but only the first 7 (or 15) slots have assigned factory
344658324dfcSspeer 	 * MAC addresses. We first search among the slots without bundled
344758324dfcSspeer 	 * factory MACs. If we fail to find one in that range, then we
344858324dfcSspeer 	 * search the slots with bundled factory MACs.  A factory MAC
344958324dfcSspeer 	 * will be wasted while the slot is used with a user MAC address.
345058324dfcSspeer 	 * But the slot could be used by factory MAC again after calling
345158324dfcSspeer 	 * nxge_m_mmac_remove and nxge_m_mmac_reserve.
345258324dfcSspeer 	 */
345358324dfcSspeer 	if (mmac_info->num_factory_mmac < mmac_info->num_mmac) {
345458324dfcSspeer 		for (slot = mmac_info->num_factory_mmac + 1;
345558324dfcSspeer 			slot <= mmac_info->num_mmac; slot++) {
345658324dfcSspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
345758324dfcSspeer 				break;
345858324dfcSspeer 		}
345958324dfcSspeer 		if (slot > mmac_info->num_mmac) {
346058324dfcSspeer 			for (slot = 1; slot <= mmac_info->num_factory_mmac;
346158324dfcSspeer 				slot++) {
346258324dfcSspeer 				if (!(mmac_info->mac_pool[slot].flags
346358324dfcSspeer 					& MMAC_SLOT_USED))
346458324dfcSspeer 					break;
346558324dfcSspeer 			}
346658324dfcSspeer 		}
346758324dfcSspeer 	} else {
346858324dfcSspeer 		for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
346958324dfcSspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
347058324dfcSspeer 				break;
347158324dfcSspeer 		}
347258324dfcSspeer 	}
347358324dfcSspeer 	ASSERT(slot <= mmac_info->num_mmac);
347458324dfcSspeer 	if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) {
347558324dfcSspeer 		mutex_exit(nxgep->genlock);
347658324dfcSspeer 		return (err);
347758324dfcSspeer 	}
347858324dfcSspeer 	bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL);
347958324dfcSspeer 	mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED;
348058324dfcSspeer 	mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR;
348158324dfcSspeer 	mmac_info->naddrfree--;
348258324dfcSspeer 	nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
348358324dfcSspeer 
348458324dfcSspeer 	maddr->mma_slot = slot;
348558324dfcSspeer 
348658324dfcSspeer 	mutex_exit(nxgep->genlock);
348758324dfcSspeer 	return (0);
348858324dfcSspeer }
348958324dfcSspeer 
349058324dfcSspeer /*
349158324dfcSspeer  * This function reserves an unused slot and programs the slot and the HW
349258324dfcSspeer  * with a factory mac address.
349358324dfcSspeer  */
349458324dfcSspeer static int
349558324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr)
349658324dfcSspeer {
349758324dfcSspeer 	p_nxge_t nxgep = arg;
349858324dfcSspeer 	mac_addr_slot_t slot;
349958324dfcSspeer 	nxge_mmac_t *mmac_info;
350058324dfcSspeer 	int err;
350158324dfcSspeer 	nxge_status_t status;
350258324dfcSspeer 
350358324dfcSspeer 	mutex_enter(nxgep->genlock);
350458324dfcSspeer 
350558324dfcSspeer 	/*
350658324dfcSspeer 	 * Make sure that nxge is initialized, if _start() has
350758324dfcSspeer 	 * not been called.
350858324dfcSspeer 	 */
350958324dfcSspeer 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
351058324dfcSspeer 		status = nxge_init(nxgep);
351158324dfcSspeer 		if (status != NXGE_OK) {
351258324dfcSspeer 			mutex_exit(nxgep->genlock);
351358324dfcSspeer 			return (ENXIO);
351458324dfcSspeer 		}
351558324dfcSspeer 	}
351658324dfcSspeer 
351758324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
351858324dfcSspeer 	if (mmac_info->naddrfree == 0) {
351958324dfcSspeer 		mutex_exit(nxgep->genlock);
352058324dfcSspeer 		return (ENOSPC);
352158324dfcSspeer 	}
352258324dfcSspeer 
352358324dfcSspeer 	slot = maddr->mma_slot;
352458324dfcSspeer 	if (slot == -1) {  /* -1: Take the first available slot */
352558324dfcSspeer 		for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) {
352658324dfcSspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
352758324dfcSspeer 				break;
352858324dfcSspeer 		}
352958324dfcSspeer 		if (slot > mmac_info->num_factory_mmac) {
353058324dfcSspeer 			mutex_exit(nxgep->genlock);
353158324dfcSspeer 			return (ENOSPC);
353258324dfcSspeer 		}
353358324dfcSspeer 	}
353458324dfcSspeer 	if (slot < 1 || slot > mmac_info->num_factory_mmac) {
353558324dfcSspeer 		/*
353658324dfcSspeer 		 * Do not support factory MAC at a slot greater than
353758324dfcSspeer 		 * num_factory_mmac even when there are available factory
353858324dfcSspeer 		 * MAC addresses because the alternate MACs are bundled with
353958324dfcSspeer 		 * slot[1] through slot[num_factory_mmac]
354058324dfcSspeer 		 */
354158324dfcSspeer 		mutex_exit(nxgep->genlock);
354258324dfcSspeer 		return (EINVAL);
354358324dfcSspeer 	}
354458324dfcSspeer 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
354558324dfcSspeer 		mutex_exit(nxgep->genlock);
354658324dfcSspeer 		return (EBUSY);
354758324dfcSspeer 	}
354858324dfcSspeer 	/* Verify the address to be reserved */
354958324dfcSspeer 	if (!mac_unicst_verify(nxgep->mach,
355058324dfcSspeer 		mmac_info->factory_mac_pool[slot], ETHERADDRL)) {
355158324dfcSspeer 		mutex_exit(nxgep->genlock);
355258324dfcSspeer 		return (EINVAL);
355358324dfcSspeer 	}
355458324dfcSspeer 	if (err = nxge_altmac_set(nxgep,
355558324dfcSspeer 		mmac_info->factory_mac_pool[slot], slot)) {
355658324dfcSspeer 		mutex_exit(nxgep->genlock);
355758324dfcSspeer 		return (err);
355858324dfcSspeer 	}
355958324dfcSspeer 	bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL);
356058324dfcSspeer 	mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR;
356158324dfcSspeer 	mmac_info->naddrfree--;
356258324dfcSspeer 
356358324dfcSspeer 	nxge_mmac_kstat_update(nxgep, slot, B_TRUE);
356458324dfcSspeer 	mutex_exit(nxgep->genlock);
356558324dfcSspeer 
356658324dfcSspeer 	/* Pass info back to the caller */
356758324dfcSspeer 	maddr->mma_slot = slot;
356858324dfcSspeer 	maddr->mma_addrlen = ETHERADDRL;
356958324dfcSspeer 	maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR;
357058324dfcSspeer 
357158324dfcSspeer 	return (0);
357258324dfcSspeer }
357358324dfcSspeer 
357458324dfcSspeer /*
357558324dfcSspeer  * Remove the specified mac address and update the HW not to filter
357658324dfcSspeer  * the mac address anymore.
357758324dfcSspeer  */
357858324dfcSspeer static int
357958324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot)
358058324dfcSspeer {
358158324dfcSspeer 	p_nxge_t nxgep = arg;
358258324dfcSspeer 	nxge_mmac_t *mmac_info;
358358324dfcSspeer 	uint8_t addrn;
358458324dfcSspeer 	uint8_t portn;
358558324dfcSspeer 	int err = 0;
358658324dfcSspeer 	nxge_status_t status;
358758324dfcSspeer 
358858324dfcSspeer 	mutex_enter(nxgep->genlock);
358958324dfcSspeer 
359058324dfcSspeer 	/*
359158324dfcSspeer 	 * Make sure that nxge is initialized, if _start() has
359258324dfcSspeer 	 * not been called.
359358324dfcSspeer 	 */
359458324dfcSspeer 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
359558324dfcSspeer 		status = nxge_init(nxgep);
359658324dfcSspeer 		if (status != NXGE_OK) {
359758324dfcSspeer 			mutex_exit(nxgep->genlock);
359858324dfcSspeer 			return (ENXIO);
359958324dfcSspeer 		}
360058324dfcSspeer 	}
360158324dfcSspeer 
360258324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
360358324dfcSspeer 	if (slot < 1 || slot > mmac_info->num_mmac) {
360458324dfcSspeer 		mutex_exit(nxgep->genlock);
360558324dfcSspeer 		return (EINVAL);
360658324dfcSspeer 	}
360758324dfcSspeer 
360858324dfcSspeer 	portn = nxgep->mac.portnum;
360958324dfcSspeer 	if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1)
361058324dfcSspeer 		addrn = (uint8_t)slot - 1;
361158324dfcSspeer 	else
361258324dfcSspeer 		addrn = (uint8_t)slot;
361358324dfcSspeer 
361458324dfcSspeer 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
361558324dfcSspeer 		if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn)
361658324dfcSspeer 				== NPI_SUCCESS) {
361758324dfcSspeer 			mmac_info->naddrfree++;
361858324dfcSspeer 			mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED;
361958324dfcSspeer 			/*
362058324dfcSspeer 			 * Regardless if the MAC we just stopped filtering
362158324dfcSspeer 			 * is a user addr or a facory addr, we must set
362258324dfcSspeer 			 * the MMAC_VENDOR_ADDR flag if this slot has an
362358324dfcSspeer 			 * associated factory MAC to indicate that a factory
362458324dfcSspeer 			 * MAC is available.
362558324dfcSspeer 			 */
362658324dfcSspeer 			if (slot <= mmac_info->num_factory_mmac) {
362758324dfcSspeer 				mmac_info->mac_pool[slot].flags
362858324dfcSspeer 					|= MMAC_VENDOR_ADDR;
362958324dfcSspeer 			}
363058324dfcSspeer 			/*
363158324dfcSspeer 			 * Clear mac_pool[slot].addr so that kstat shows 0
363258324dfcSspeer 			 * alternate MAC address if the slot is not used.
363358324dfcSspeer 			 * (But nxge_m_mmac_get returns the factory MAC even
363458324dfcSspeer 			 * when the slot is not used!)
363558324dfcSspeer 			 */
363658324dfcSspeer 			bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL);
363758324dfcSspeer 			nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
363858324dfcSspeer 		} else {
363958324dfcSspeer 			err = EIO;
364058324dfcSspeer 		}
364158324dfcSspeer 	} else {
364258324dfcSspeer 		err = EINVAL;
364358324dfcSspeer 	}
364458324dfcSspeer 
364558324dfcSspeer 	mutex_exit(nxgep->genlock);
364658324dfcSspeer 	return (err);
364758324dfcSspeer }
364858324dfcSspeer 
364958324dfcSspeer 
365058324dfcSspeer /*
365158324dfcSspeer  * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve().
365258324dfcSspeer  */
365358324dfcSspeer static int
365458324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr)
365558324dfcSspeer {
365658324dfcSspeer 	p_nxge_t nxgep = arg;
365758324dfcSspeer 	mac_addr_slot_t slot;
365858324dfcSspeer 	nxge_mmac_t *mmac_info;
365958324dfcSspeer 	int err = 0;
366058324dfcSspeer 	nxge_status_t status;
366158324dfcSspeer 
366258324dfcSspeer 	if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr,
366358324dfcSspeer 			maddr->mma_addrlen))
366458324dfcSspeer 		return (EINVAL);
366558324dfcSspeer 
366658324dfcSspeer 	slot = maddr->mma_slot;
366758324dfcSspeer 
366858324dfcSspeer 	mutex_enter(nxgep->genlock);
366958324dfcSspeer 
367058324dfcSspeer 	/*
367158324dfcSspeer 	 * Make sure that nxge is initialized, if _start() has
367258324dfcSspeer 	 * not been called.
367358324dfcSspeer 	 */
367458324dfcSspeer 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
367558324dfcSspeer 		status = nxge_init(nxgep);
367658324dfcSspeer 		if (status != NXGE_OK) {
367758324dfcSspeer 			mutex_exit(nxgep->genlock);
367858324dfcSspeer 			return (ENXIO);
367958324dfcSspeer 		}
368058324dfcSspeer 	}
368158324dfcSspeer 
368258324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
368358324dfcSspeer 	if (slot < 1 || slot > mmac_info->num_mmac) {
368458324dfcSspeer 		mutex_exit(nxgep->genlock);
368558324dfcSspeer 		return (EINVAL);
368658324dfcSspeer 	}
368758324dfcSspeer 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) {
368858324dfcSspeer 		if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot))
368958324dfcSspeer 			!= 0) {
369058324dfcSspeer 			bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr,
369158324dfcSspeer 				ETHERADDRL);
369258324dfcSspeer 			/*
369358324dfcSspeer 			 * Assume that the MAC passed down from the caller
369458324dfcSspeer 			 * is not a factory MAC address (The user should
369558324dfcSspeer 			 * call mmac_remove followed by mmac_reserve if
369658324dfcSspeer 			 * he wants to use the factory MAC for this slot).
369758324dfcSspeer 			 */
369858324dfcSspeer 			mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR;
369958324dfcSspeer 			nxge_mmac_kstat_update(nxgep, slot, B_FALSE);
370058324dfcSspeer 		}
370158324dfcSspeer 	} else {
370258324dfcSspeer 		err = EINVAL;
370358324dfcSspeer 	}
370458324dfcSspeer 	mutex_exit(nxgep->genlock);
370558324dfcSspeer 	return (err);
370658324dfcSspeer }
370758324dfcSspeer 
370858324dfcSspeer /*
370958324dfcSspeer  * nxge_m_mmac_get() - Get the MAC address and other information
371058324dfcSspeer  * related to the slot.  mma_flags should be set to 0 in the call.
371158324dfcSspeer  * Note: although kstat shows MAC address as zero when a slot is
371258324dfcSspeer  * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC
371358324dfcSspeer  * to the caller as long as the slot is not using a user MAC address.
371458324dfcSspeer  * The following table shows the rules,
371558324dfcSspeer  *
371658324dfcSspeer  *				   USED    VENDOR    mma_addr
371758324dfcSspeer  * ------------------------------------------------------------
371858324dfcSspeer  * (1) Slot uses a user MAC:        yes      no     user MAC
371958324dfcSspeer  * (2) Slot uses a factory MAC:     yes      yes    factory MAC
372058324dfcSspeer  * (3) Slot is not used but is
372158324dfcSspeer  *     factory MAC capable:         no       yes    factory MAC
372258324dfcSspeer  * (4) Slot is not used and is
372358324dfcSspeer  *     not factory MAC capable:     no       no        0
372458324dfcSspeer  * ------------------------------------------------------------
372558324dfcSspeer  */
372658324dfcSspeer static int
372758324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr)
372858324dfcSspeer {
372958324dfcSspeer 	nxge_t *nxgep = arg;
373058324dfcSspeer 	mac_addr_slot_t slot;
373158324dfcSspeer 	nxge_mmac_t *mmac_info;
373258324dfcSspeer 	nxge_status_t status;
373358324dfcSspeer 
373458324dfcSspeer 	slot = maddr->mma_slot;
373558324dfcSspeer 
373658324dfcSspeer 	mutex_enter(nxgep->genlock);
373758324dfcSspeer 
373858324dfcSspeer 	/*
373958324dfcSspeer 	 * Make sure that nxge is initialized, if _start() has
374058324dfcSspeer 	 * not been called.
374158324dfcSspeer 	 */
374258324dfcSspeer 	if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
374358324dfcSspeer 		status = nxge_init(nxgep);
374458324dfcSspeer 		if (status != NXGE_OK) {
374558324dfcSspeer 			mutex_exit(nxgep->genlock);
374658324dfcSspeer 			return (ENXIO);
374758324dfcSspeer 		}
374858324dfcSspeer 	}
374958324dfcSspeer 
375058324dfcSspeer 	mmac_info = &nxgep->nxge_mmac_info;
375158324dfcSspeer 
375258324dfcSspeer 	if (slot < 1 || slot > mmac_info->num_mmac) {
375358324dfcSspeer 		mutex_exit(nxgep->genlock);
375458324dfcSspeer 		return (EINVAL);
375558324dfcSspeer 	}
375658324dfcSspeer 	maddr->mma_flags = 0;
375758324dfcSspeer 	if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)
375858324dfcSspeer 		maddr->mma_flags |= MMAC_SLOT_USED;
375958324dfcSspeer 
376058324dfcSspeer 	if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) {
376158324dfcSspeer 		maddr->mma_flags |= MMAC_VENDOR_ADDR;
376258324dfcSspeer 		bcopy(mmac_info->factory_mac_pool[slot],
376358324dfcSspeer 			maddr->mma_addr, ETHERADDRL);
376458324dfcSspeer 		maddr->mma_addrlen = ETHERADDRL;
376558324dfcSspeer 	} else {
376658324dfcSspeer 		if (maddr->mma_flags & MMAC_SLOT_USED) {
376758324dfcSspeer 			bcopy(mmac_info->mac_pool[slot].addr,
376858324dfcSspeer 				maddr->mma_addr, ETHERADDRL);
376958324dfcSspeer 			maddr->mma_addrlen = ETHERADDRL;
377058324dfcSspeer 		} else {
377158324dfcSspeer 			bzero(maddr->mma_addr, ETHERADDRL);
377258324dfcSspeer 			maddr->mma_addrlen = 0;
377358324dfcSspeer 		}
377458324dfcSspeer 	}
377558324dfcSspeer 	mutex_exit(nxgep->genlock);
377658324dfcSspeer 	return (0);
377758324dfcSspeer }
377858324dfcSspeer 
377958324dfcSspeer 
378044961713Sgirish static boolean_t
378144961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
378244961713Sgirish {
378358324dfcSspeer 	nxge_t *nxgep = arg;
378458324dfcSspeer 	uint32_t *txflags = cap_data;
378558324dfcSspeer 	multiaddress_capab_t *mmacp = cap_data;
378644961713Sgirish 
378758324dfcSspeer 	switch (cap) {
378858324dfcSspeer 	case MAC_CAPAB_HCKSUM:
378944961713Sgirish 		*txflags = HCKSUM_INET_PARTIAL;
379044961713Sgirish 		break;
379144961713Sgirish 	case MAC_CAPAB_POLL:
379244961713Sgirish 		/*
379344961713Sgirish 		 * There's nothing for us to fill in, simply returning
379444961713Sgirish 		 * B_TRUE stating that we support polling is sufficient.
379544961713Sgirish 		 */
379644961713Sgirish 		break;
379744961713Sgirish 
379858324dfcSspeer 	case MAC_CAPAB_MULTIADDRESS:
379958324dfcSspeer 		mutex_enter(nxgep->genlock);
380058324dfcSspeer 
380158324dfcSspeer 		mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac;
380258324dfcSspeer 		mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree;
380358324dfcSspeer 		mmacp->maddr_flag = 0; /* 0 is requried by PSARC2006/265 */
380458324dfcSspeer 		/*
380558324dfcSspeer 		 * maddr_handle is driver's private data, passed back to
380658324dfcSspeer 		 * entry point functions as arg.
380758324dfcSspeer 		 */
380858324dfcSspeer 		mmacp->maddr_handle	= nxgep;
380958324dfcSspeer 		mmacp->maddr_add	= nxge_m_mmac_add;
381058324dfcSspeer 		mmacp->maddr_remove	= nxge_m_mmac_remove;
381158324dfcSspeer 		mmacp->maddr_modify	= nxge_m_mmac_modify;
381258324dfcSspeer 		mmacp->maddr_get	= nxge_m_mmac_get;
381358324dfcSspeer 		mmacp->maddr_reserve	= nxge_m_mmac_reserve;
381458324dfcSspeer 
381558324dfcSspeer 		mutex_exit(nxgep->genlock);
381658324dfcSspeer 		break;
381730ac2e7bSml 	case MAC_CAPAB_LSO: {
381830ac2e7bSml 		mac_capab_lso_t *cap_lso = cap_data;
381930ac2e7bSml 
38203d16f8e7Sml 		if (nxgep->soft_lso_enable) {
382130ac2e7bSml 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
382230ac2e7bSml 			if (nxge_lso_max > NXGE_LSO_MAXLEN) {
382330ac2e7bSml 				nxge_lso_max = NXGE_LSO_MAXLEN;
382430ac2e7bSml 			}
382530ac2e7bSml 			cap_lso->lso_basic_tcp_ipv4.lso_max = nxge_lso_max;
382630ac2e7bSml 			break;
382730ac2e7bSml 		} else {
382830ac2e7bSml 			return (B_FALSE);
382930ac2e7bSml 		}
383030ac2e7bSml 	}
383130ac2e7bSml 
383244961713Sgirish 	default:
383344961713Sgirish 		return (B_FALSE);
383444961713Sgirish 	}
383544961713Sgirish 	return (B_TRUE);
383644961713Sgirish }
383744961713Sgirish 
383844961713Sgirish /*
383944961713Sgirish  * Module loading and removing entry points.
384044961713Sgirish  */
384144961713Sgirish 
384244961713Sgirish static	struct cb_ops 	nxge_cb_ops = {
384344961713Sgirish 	nodev,			/* cb_open */
384444961713Sgirish 	nodev,			/* cb_close */
384544961713Sgirish 	nodev,			/* cb_strategy */
384644961713Sgirish 	nodev,			/* cb_print */
384744961713Sgirish 	nodev,			/* cb_dump */
384844961713Sgirish 	nodev,			/* cb_read */
384944961713Sgirish 	nodev,			/* cb_write */
385044961713Sgirish 	nodev,			/* cb_ioctl */
385144961713Sgirish 	nodev,			/* cb_devmap */
385244961713Sgirish 	nodev,			/* cb_mmap */
385344961713Sgirish 	nodev,			/* cb_segmap */
385444961713Sgirish 	nochpoll,		/* cb_chpoll */
385544961713Sgirish 	ddi_prop_op,		/* cb_prop_op */
385644961713Sgirish 	NULL,
385744961713Sgirish 	D_MP, 			/* cb_flag */
385844961713Sgirish 	CB_REV,			/* rev */
385944961713Sgirish 	nodev,			/* int (*cb_aread)() */
386044961713Sgirish 	nodev			/* int (*cb_awrite)() */
386144961713Sgirish };
386244961713Sgirish 
386344961713Sgirish static struct dev_ops nxge_dev_ops = {
386444961713Sgirish 	DEVO_REV,		/* devo_rev */
386544961713Sgirish 	0,			/* devo_refcnt */
386644961713Sgirish 	nulldev,
386758324dfcSspeer 	nulldev,		/* devo_identify */
386858324dfcSspeer 	nulldev,		/* devo_probe */
386958324dfcSspeer 	nxge_attach,		/* devo_attach */
387058324dfcSspeer 	nxge_detach,		/* devo_detach */
387158324dfcSspeer 	nodev,			/* devo_reset */
387258324dfcSspeer 	&nxge_cb_ops,		/* devo_cb_ops */
387358324dfcSspeer 	(struct bus_ops *)NULL, /* devo_bus_ops	*/
387458324dfcSspeer 	ddi_power		/* devo_power */
387544961713Sgirish };
387644961713Sgirish 
387744961713Sgirish extern	struct	mod_ops	mod_driverops;
387844961713Sgirish 
38792e59129aSraghus #define	NXGE_DESC_VER		"Sun NIU 10Gb Ethernet"
388044961713Sgirish 
388144961713Sgirish /*
388244961713Sgirish  * Module linkage information for the kernel.
388344961713Sgirish  */
388444961713Sgirish static struct modldrv 	nxge_modldrv = {
388544961713Sgirish 	&mod_driverops,
388644961713Sgirish 	NXGE_DESC_VER,
388744961713Sgirish 	&nxge_dev_ops
388844961713Sgirish };
388944961713Sgirish 
389044961713Sgirish static struct modlinkage modlinkage = {
389144961713Sgirish 	MODREV_1, (void *) &nxge_modldrv, NULL
389244961713Sgirish };
389344961713Sgirish 
389444961713Sgirish int
389544961713Sgirish _init(void)
389644961713Sgirish {
389744961713Sgirish 	int		status;
389844961713Sgirish 
389944961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
390044961713Sgirish 	mac_init_ops(&nxge_dev_ops, "nxge");
390144961713Sgirish 	status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0);
390244961713Sgirish 	if (status != 0) {
390344961713Sgirish 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
390444961713Sgirish 			"failed to init device soft state"));
390544961713Sgirish 		goto _init_exit;
390644961713Sgirish 	}
390744961713Sgirish 	status = mod_install(&modlinkage);
390844961713Sgirish 	if (status != 0) {
390944961713Sgirish 		ddi_soft_state_fini(&nxge_list);
391044961713Sgirish 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed"));
391144961713Sgirish 		goto _init_exit;
391244961713Sgirish 	}
391344961713Sgirish 
391444961713Sgirish 	MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL);
391544961713Sgirish 
391644961713Sgirish _init_exit:
391744961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
391844961713Sgirish 
391944961713Sgirish 	return (status);
392044961713Sgirish }
392144961713Sgirish 
392244961713Sgirish int
392344961713Sgirish _fini(void)
392444961713Sgirish {
392544961713Sgirish 	int		status;
392644961713Sgirish 
392744961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
392844961713Sgirish 
392944961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
3930a3c5bd6dSspeer 
3931a3c5bd6dSspeer 	if (nxge_mblks_pending)
3932a3c5bd6dSspeer 		return (EBUSY);
3933a3c5bd6dSspeer 
393444961713Sgirish 	status = mod_remove(&modlinkage);
393544961713Sgirish 	if (status != DDI_SUCCESS) {
393644961713Sgirish 		NXGE_DEBUG_MSG((NULL, MOD_CTL,
393744961713Sgirish 			    "Module removal failed 0x%08x",
393844961713Sgirish 			    status));
393944961713Sgirish 		goto _fini_exit;
394044961713Sgirish 	}
394144961713Sgirish 
394244961713Sgirish 	mac_fini_ops(&nxge_dev_ops);
394344961713Sgirish 
394444961713Sgirish 	ddi_soft_state_fini(&nxge_list);
394544961713Sgirish 
394644961713Sgirish 	MUTEX_DESTROY(&nxge_common_lock);
394744961713Sgirish _fini_exit:
394844961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
394944961713Sgirish 
395044961713Sgirish 	return (status);
395144961713Sgirish }
395244961713Sgirish 
395344961713Sgirish int
395444961713Sgirish _info(struct modinfo *modinfop)
395544961713Sgirish {
395644961713Sgirish 	int		status;
395744961713Sgirish 
395844961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
395944961713Sgirish 	status = mod_info(&modlinkage, modinfop);
396044961713Sgirish 	NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
396144961713Sgirish 
396244961713Sgirish 	return (status);
396344961713Sgirish }
396444961713Sgirish 
396544961713Sgirish /*ARGSUSED*/
396644961713Sgirish static nxge_status_t
396744961713Sgirish nxge_add_intrs(p_nxge_t nxgep)
396844961713Sgirish {
396944961713Sgirish 
397044961713Sgirish 	int		intr_types;
397144961713Sgirish 	int		type = 0;
397244961713Sgirish 	int		ddi_status = DDI_SUCCESS;
397344961713Sgirish 	nxge_status_t	status = NXGE_OK;
397444961713Sgirish 
397544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs"));
397644961713Sgirish 
397744961713Sgirish 	nxgep->nxge_intr_type.intr_registered = B_FALSE;
397844961713Sgirish 	nxgep->nxge_intr_type.intr_enabled = B_FALSE;
397944961713Sgirish 	nxgep->nxge_intr_type.msi_intx_cnt = 0;
398044961713Sgirish 	nxgep->nxge_intr_type.intr_added = 0;
398144961713Sgirish 	nxgep->nxge_intr_type.niu_msi_enable = B_FALSE;
398244961713Sgirish 	nxgep->nxge_intr_type.intr_type = 0;
398344961713Sgirish 
398444961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
398544961713Sgirish 		nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
398644961713Sgirish 	} else if (nxge_msi_enable) {
398744961713Sgirish 		nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
398844961713Sgirish 	}
398944961713Sgirish 
399044961713Sgirish 	/* Get the supported interrupt types */
399144961713Sgirish 	if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types))
399244961713Sgirish 			!= DDI_SUCCESS) {
399344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: "
399444961713Sgirish 			"ddi_intr_get_supported_types failed: status 0x%08x",
399544961713Sgirish 			ddi_status));
399644961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
399744961713Sgirish 	}
399844961713Sgirish 	nxgep->nxge_intr_type.intr_types = intr_types;
399944961713Sgirish 
400044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
400144961713Sgirish 		"ddi_intr_get_supported_types: 0x%08x", intr_types));
400244961713Sgirish 
400344961713Sgirish 	/*
400444961713Sgirish 	 * Solaris MSIX is not supported yet. use MSI for now.
400544961713Sgirish 	 * nxge_msi_enable (1):
400644961713Sgirish 	 *	1 - MSI		2 - MSI-X	others - FIXED
400744961713Sgirish 	 */
400844961713Sgirish 	switch (nxge_msi_enable) {
400944961713Sgirish 	default:
401044961713Sgirish 		type = DDI_INTR_TYPE_FIXED;
401144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
401244961713Sgirish 			"use fixed (intx emulation) type %08x",
401344961713Sgirish 			type));
401444961713Sgirish 		break;
401544961713Sgirish 
401644961713Sgirish 	case 2:
401744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
401844961713Sgirish 			"ddi_intr_get_supported_types: 0x%08x", intr_types));
401944961713Sgirish 		if (intr_types & DDI_INTR_TYPE_MSIX) {
402044961713Sgirish 			type = DDI_INTR_TYPE_MSIX;
402144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
402244961713Sgirish 				"ddi_intr_get_supported_types: MSIX 0x%08x",
402344961713Sgirish 				type));
402444961713Sgirish 		} else if (intr_types & DDI_INTR_TYPE_MSI) {
402544961713Sgirish 			type = DDI_INTR_TYPE_MSI;
402644961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
402744961713Sgirish 				"ddi_intr_get_supported_types: MSI 0x%08x",
402844961713Sgirish 				type));
402944961713Sgirish 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
403044961713Sgirish 			type = DDI_INTR_TYPE_FIXED;
403144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
403244961713Sgirish 				"ddi_intr_get_supported_types: MSXED0x%08x",
403344961713Sgirish 				type));
403444961713Sgirish 		}
403544961713Sgirish 		break;
403644961713Sgirish 
403744961713Sgirish 	case 1:
403844961713Sgirish 		if (intr_types & DDI_INTR_TYPE_MSI) {
403944961713Sgirish 			type = DDI_INTR_TYPE_MSI;
404044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
404144961713Sgirish 				"ddi_intr_get_supported_types: MSI 0x%08x",
404244961713Sgirish 				type));
404344961713Sgirish 		} else if (intr_types & DDI_INTR_TYPE_MSIX) {
404444961713Sgirish 			type = DDI_INTR_TYPE_MSIX;
404544961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
404644961713Sgirish 				"ddi_intr_get_supported_types: MSIX 0x%08x",
404744961713Sgirish 				type));
404844961713Sgirish 		} else if (intr_types & DDI_INTR_TYPE_FIXED) {
404944961713Sgirish 			type = DDI_INTR_TYPE_FIXED;
405044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
405144961713Sgirish 				"ddi_intr_get_supported_types: MSXED0x%08x",
405244961713Sgirish 				type));
405344961713Sgirish 		}
405444961713Sgirish 	}
405544961713Sgirish 
405644961713Sgirish 	nxgep->nxge_intr_type.intr_type = type;
405744961713Sgirish 	if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
405844961713Sgirish 		type == DDI_INTR_TYPE_FIXED) &&
405944961713Sgirish 			nxgep->nxge_intr_type.niu_msi_enable) {
406044961713Sgirish 		if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) {
406144961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
406244961713Sgirish 				    " nxge_add_intrs: "
406344961713Sgirish 				    " nxge_add_intrs_adv failed: status 0x%08x",
406444961713Sgirish 				    status));
406544961713Sgirish 			return (status);
406644961713Sgirish 		} else {
406744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
406844961713Sgirish 			"interrupts registered : type %d", type));
406944961713Sgirish 			nxgep->nxge_intr_type.intr_registered = B_TRUE;
407044961713Sgirish 
407144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
407244961713Sgirish 				"\nAdded advanced nxge add_intr_adv "
407344961713Sgirish 					"intr type 0x%x\n", type));
407444961713Sgirish 
407544961713Sgirish 			return (status);
407644961713Sgirish 		}
407744961713Sgirish 	}
407844961713Sgirish 
407944961713Sgirish 	if (!nxgep->nxge_intr_type.intr_registered) {
408044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: "
408144961713Sgirish 			"failed to register interrupts"));
408244961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
408344961713Sgirish 	}
408444961713Sgirish 
408544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs"));
408644961713Sgirish 	return (status);
408744961713Sgirish }
408844961713Sgirish 
408944961713Sgirish /*ARGSUSED*/
409044961713Sgirish static nxge_status_t
409144961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep)
409244961713Sgirish {
409344961713Sgirish 
409444961713Sgirish 	int		ddi_status = DDI_SUCCESS;
409544961713Sgirish 	nxge_status_t	status = NXGE_OK;
409644961713Sgirish 
409744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs"));
409844961713Sgirish 
409944961713Sgirish 	nxgep->resched_id = NULL;
410044961713Sgirish 	nxgep->resched_running = B_FALSE;
410144961713Sgirish 	ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW,
410244961713Sgirish 			&nxgep->resched_id,
410344961713Sgirish 		NULL, NULL, nxge_reschedule, (caddr_t)nxgep);
410444961713Sgirish 	if (ddi_status != DDI_SUCCESS) {
410544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: "
410644961713Sgirish 			"ddi_add_softintrs failed: status 0x%08x",
410744961713Sgirish 			ddi_status));
410844961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
410944961713Sgirish 	}
411044961713Sgirish 
411144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs"));
411244961713Sgirish 
411344961713Sgirish 	return (status);
411444961713Sgirish }
411544961713Sgirish 
411644961713Sgirish static nxge_status_t
411744961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep)
411844961713Sgirish {
411944961713Sgirish 	int		intr_type;
412044961713Sgirish 	p_nxge_intr_t	intrp;
412144961713Sgirish 
412244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv"));
412344961713Sgirish 
412444961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
412544961713Sgirish 	intr_type = intrp->intr_type;
412644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x",
412744961713Sgirish 		intr_type));
412844961713Sgirish 
412944961713Sgirish 	switch (intr_type) {
413044961713Sgirish 	case DDI_INTR_TYPE_MSI: /* 0x2 */
413144961713Sgirish 	case DDI_INTR_TYPE_MSIX: /* 0x4 */
413244961713Sgirish 		return (nxge_add_intrs_adv_type(nxgep, intr_type));
413344961713Sgirish 
413444961713Sgirish 	case DDI_INTR_TYPE_FIXED: /* 0x1 */
413544961713Sgirish 		return (nxge_add_intrs_adv_type_fix(nxgep, intr_type));
413644961713Sgirish 
413744961713Sgirish 	default:
413844961713Sgirish 		return (NXGE_ERROR);
413944961713Sgirish 	}
414044961713Sgirish }
414144961713Sgirish 
414244961713Sgirish 
414344961713Sgirish /*ARGSUSED*/
414444961713Sgirish static nxge_status_t
414544961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type)
414644961713Sgirish {
414744961713Sgirish 	dev_info_t		*dip = nxgep->dip;
414844961713Sgirish 	p_nxge_ldg_t		ldgp;
414944961713Sgirish 	p_nxge_intr_t		intrp;
415044961713Sgirish 	uint_t			*inthandler;
415144961713Sgirish 	void			*arg1, *arg2;
415244961713Sgirish 	int			behavior;
4153ec090658Sml 	int			nintrs, navail, nrequest;
415444961713Sgirish 	int			nactual, nrequired;
415544961713Sgirish 	int			inum = 0;
415644961713Sgirish 	int			x, y;
415744961713Sgirish 	int			ddi_status = DDI_SUCCESS;
415844961713Sgirish 	nxge_status_t		status = NXGE_OK;
415944961713Sgirish 
416044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type"));
416144961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
416244961713Sgirish 	intrp->start_inum = 0;
416344961713Sgirish 
416444961713Sgirish 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
416544961713Sgirish 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
416644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
416744961713Sgirish 			"ddi_intr_get_nintrs() failed, status: 0x%x%, "
416844961713Sgirish 			    "nintrs: %d", ddi_status, nintrs));
416944961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
417044961713Sgirish 	}
417144961713Sgirish 
417244961713Sgirish 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
417344961713Sgirish 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
417444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
417544961713Sgirish 			"ddi_intr_get_navail() failed, status: 0x%x%, "
417644961713Sgirish 			    "nintrs: %d", ddi_status, navail));
417744961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
417844961713Sgirish 	}
417944961713Sgirish 
418044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
418144961713Sgirish 		"ddi_intr_get_navail() returned: nintrs %d, navail %d",
418244961713Sgirish 		    nintrs, navail));
418344961713Sgirish 
4184ec090658Sml 	/* PSARC/2007/453 MSI-X interrupt limit override */
4185ec090658Sml 	if (int_type == DDI_INTR_TYPE_MSIX) {
4186ec090658Sml 		nrequest = nxge_create_msi_property(nxgep);
4187ec090658Sml 		if (nrequest < navail) {
4188ec090658Sml 			navail = nrequest;
4189ec090658Sml 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
4190ec090658Sml 			    "nxge_add_intrs_adv_type: nintrs %d "
4191ec090658Sml 			    "navail %d (nrequest %d)",
4192ec090658Sml 			    nintrs, navail, nrequest));
4193ec090658Sml 		}
4194ec090658Sml 	}
4195ec090658Sml 
419644961713Sgirish 	if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
419744961713Sgirish 		/* MSI must be power of 2 */
419844961713Sgirish 		if ((navail & 16) == 16) {
419944961713Sgirish 			navail = 16;
420044961713Sgirish 		} else if ((navail & 8) == 8) {
420144961713Sgirish 			navail = 8;
420244961713Sgirish 		} else if ((navail & 4) == 4) {
420344961713Sgirish 			navail = 4;
420444961713Sgirish 		} else if ((navail & 2) == 2) {
420544961713Sgirish 			navail = 2;
420644961713Sgirish 		} else {
420744961713Sgirish 			navail = 1;
420844961713Sgirish 		}
420944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
421044961713Sgirish 			"ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
421144961713Sgirish 			"navail %d", nintrs, navail));
421244961713Sgirish 	}
421344961713Sgirish 
421444961713Sgirish 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
421544961713Sgirish 			DDI_INTR_ALLOC_NORMAL);
421644961713Sgirish 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
421744961713Sgirish 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
421844961713Sgirish 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
421944961713Sgirish 		    navail, &nactual, behavior);
422044961713Sgirish 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
422144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
422244961713Sgirish 				    " ddi_intr_alloc() failed: %d",
422344961713Sgirish 				    ddi_status));
422444961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
422544961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
422644961713Sgirish 	}
422744961713Sgirish 
422844961713Sgirish 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
422944961713Sgirish 			(uint_t *)&intrp->pri)) != DDI_SUCCESS) {
423044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
423144961713Sgirish 				    " ddi_intr_get_pri() failed: %d",
423244961713Sgirish 				    ddi_status));
423344961713Sgirish 		/* Free already allocated interrupts */
423444961713Sgirish 		for (y = 0; y < nactual; y++) {
423544961713Sgirish 			(void) ddi_intr_free(intrp->htable[y]);
423644961713Sgirish 		}
423744961713Sgirish 
423844961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
423944961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
424044961713Sgirish 	}
424144961713Sgirish 
424244961713Sgirish 	nrequired = 0;
424344961713Sgirish 	switch (nxgep->niu_type) {
424444961713Sgirish 	default:
424544961713Sgirish 		status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
424644961713Sgirish 		break;
424744961713Sgirish 
424844961713Sgirish 	case N2_NIU:
424944961713Sgirish 		status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
425044961713Sgirish 		break;
425144961713Sgirish 	}
425244961713Sgirish 
425344961713Sgirish 	if (status != NXGE_OK) {
425444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
425544961713Sgirish 			"nxge_add_intrs_adv_typ:nxge_ldgv_init "
425644961713Sgirish 			"failed: 0x%x", status));
425744961713Sgirish 		/* Free already allocated interrupts */
425844961713Sgirish 		for (y = 0; y < nactual; y++) {
425944961713Sgirish 			(void) ddi_intr_free(intrp->htable[y]);
426044961713Sgirish 		}
426144961713Sgirish 
426244961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
426344961713Sgirish 		return (status);
426444961713Sgirish 	}
426544961713Sgirish 
426644961713Sgirish 	ldgp = nxgep->ldgvp->ldgp;
426744961713Sgirish 	for (x = 0; x < nrequired; x++, ldgp++) {
426844961713Sgirish 		ldgp->vector = (uint8_t)x;
426944961713Sgirish 		ldgp->intdata = SID_DATA(ldgp->func, x);
427044961713Sgirish 		arg1 = ldgp->ldvp;
427144961713Sgirish 		arg2 = nxgep;
427244961713Sgirish 		if (ldgp->nldvs == 1) {
427344961713Sgirish 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
427444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
427544961713Sgirish 				"nxge_add_intrs_adv_type: "
427644961713Sgirish 				"arg1 0x%x arg2 0x%x: "
427744961713Sgirish 				"1-1 int handler (entry %d intdata 0x%x)\n",
427844961713Sgirish 				arg1, arg2,
427944961713Sgirish 				x, ldgp->intdata));
428044961713Sgirish 		} else if (ldgp->nldvs > 1) {
428144961713Sgirish 			inthandler = (uint_t *)ldgp->sys_intr_handler;
428244961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
428344961713Sgirish 				"nxge_add_intrs_adv_type: "
428444961713Sgirish 				"arg1 0x%x arg2 0x%x: "
428544961713Sgirish 				"nldevs %d int handler "
428644961713Sgirish 				"(entry %d intdata 0x%x)\n",
428744961713Sgirish 				arg1, arg2,
428844961713Sgirish 				ldgp->nldvs, x, ldgp->intdata));
428944961713Sgirish 		}
429044961713Sgirish 
429144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
429244961713Sgirish 			"==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
429344961713Sgirish 			"htable 0x%llx", x, intrp->htable[x]));
429444961713Sgirish 
429544961713Sgirish 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
429644961713Sgirish 			(ddi_intr_handler_t *)inthandler, arg1, arg2))
429744961713Sgirish 				!= DDI_SUCCESS) {
429844961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
429944961713Sgirish 				"==> nxge_add_intrs_adv_type: failed #%d "
430044961713Sgirish 				"status 0x%x", x, ddi_status));
430144961713Sgirish 			for (y = 0; y < intrp->intr_added; y++) {
430244961713Sgirish 				(void) ddi_intr_remove_handler(
430344961713Sgirish 						intrp->htable[y]);
430444961713Sgirish 			}
430544961713Sgirish 			/* Free already allocated intr */
430644961713Sgirish 			for (y = 0; y < nactual; y++) {
430744961713Sgirish 				(void) ddi_intr_free(intrp->htable[y]);
430844961713Sgirish 			}
430944961713Sgirish 			kmem_free(intrp->htable, intrp->intr_size);
431044961713Sgirish 
431144961713Sgirish 			(void) nxge_ldgv_uninit(nxgep);
431244961713Sgirish 
431344961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
431444961713Sgirish 		}
431544961713Sgirish 		intrp->intr_added++;
431644961713Sgirish 	}
431744961713Sgirish 
431844961713Sgirish 	intrp->msi_intx_cnt = nactual;
431944961713Sgirish 
432044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL,
432144961713Sgirish 		"Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
432244961713Sgirish 		navail, nactual,
432344961713Sgirish 		intrp->msi_intx_cnt,
432444961713Sgirish 		intrp->intr_added));
432544961713Sgirish 
432644961713Sgirish 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
432744961713Sgirish 
432844961713Sgirish 	(void) nxge_intr_ldgv_init(nxgep);
432944961713Sgirish 
433044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type"));
433144961713Sgirish 
433244961713Sgirish 	return (status);
433344961713Sgirish }
433444961713Sgirish 
433544961713Sgirish /*ARGSUSED*/
433644961713Sgirish static nxge_status_t
433744961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type)
433844961713Sgirish {
433944961713Sgirish 	dev_info_t		*dip = nxgep->dip;
434044961713Sgirish 	p_nxge_ldg_t		ldgp;
434144961713Sgirish 	p_nxge_intr_t		intrp;
434244961713Sgirish 	uint_t			*inthandler;
434344961713Sgirish 	void			*arg1, *arg2;
434444961713Sgirish 	int			behavior;
434544961713Sgirish 	int			nintrs, navail;
434644961713Sgirish 	int			nactual, nrequired;
434744961713Sgirish 	int			inum = 0;
434844961713Sgirish 	int			x, y;
434944961713Sgirish 	int			ddi_status = DDI_SUCCESS;
435044961713Sgirish 	nxge_status_t		status = NXGE_OK;
435144961713Sgirish 
435244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix"));
435344961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
435444961713Sgirish 	intrp->start_inum = 0;
435544961713Sgirish 
435644961713Sgirish 	ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
435744961713Sgirish 	if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
435844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
435944961713Sgirish 			"ddi_intr_get_nintrs() failed, status: 0x%x%, "
436044961713Sgirish 			    "nintrs: %d", status, nintrs));
436144961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
436244961713Sgirish 	}
436344961713Sgirish 
436444961713Sgirish 	ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
436544961713Sgirish 	if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
436644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
436744961713Sgirish 			"ddi_intr_get_navail() failed, status: 0x%x%, "
436844961713Sgirish 			    "nintrs: %d", ddi_status, navail));
436944961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
437044961713Sgirish 	}
437144961713Sgirish 
437244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
437344961713Sgirish 		"ddi_intr_get_navail() returned: nintrs %d, naavail %d",
437444961713Sgirish 		    nintrs, navail));
437544961713Sgirish 
437644961713Sgirish 	behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
437744961713Sgirish 			DDI_INTR_ALLOC_NORMAL);
437844961713Sgirish 	intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
437944961713Sgirish 	intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
438044961713Sgirish 	ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
438144961713Sgirish 		    navail, &nactual, behavior);
438244961713Sgirish 	if (ddi_status != DDI_SUCCESS || nactual == 0) {
438344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
438444961713Sgirish 			    " ddi_intr_alloc() failed: %d",
438544961713Sgirish 			    ddi_status));
438644961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
438744961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
438844961713Sgirish 	}
438944961713Sgirish 
439044961713Sgirish 	if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
439144961713Sgirish 			(uint_t *)&intrp->pri)) != DDI_SUCCESS) {
439244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
439344961713Sgirish 				    " ddi_intr_get_pri() failed: %d",
439444961713Sgirish 				    ddi_status));
439544961713Sgirish 		/* Free already allocated interrupts */
439644961713Sgirish 		for (y = 0; y < nactual; y++) {
439744961713Sgirish 			(void) ddi_intr_free(intrp->htable[y]);
439844961713Sgirish 		}
439944961713Sgirish 
440044961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
440144961713Sgirish 		return (NXGE_ERROR | NXGE_DDI_FAILED);
440244961713Sgirish 	}
440344961713Sgirish 
440444961713Sgirish 	nrequired = 0;
440544961713Sgirish 	switch (nxgep->niu_type) {
440644961713Sgirish 	default:
440744961713Sgirish 		status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
440844961713Sgirish 		break;
440944961713Sgirish 
441044961713Sgirish 	case N2_NIU:
441144961713Sgirish 		status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
441244961713Sgirish 		break;
441344961713Sgirish 	}
441444961713Sgirish 
441544961713Sgirish 	if (status != NXGE_OK) {
441644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
441744961713Sgirish 			"nxge_add_intrs_adv_type_fix:nxge_ldgv_init "
441844961713Sgirish 			"failed: 0x%x", status));
441944961713Sgirish 		/* Free already allocated interrupts */
442044961713Sgirish 		for (y = 0; y < nactual; y++) {
442144961713Sgirish 			(void) ddi_intr_free(intrp->htable[y]);
442244961713Sgirish 		}
442344961713Sgirish 
442444961713Sgirish 		kmem_free(intrp->htable, intrp->intr_size);
442544961713Sgirish 		return (status);
442644961713Sgirish 	}
442744961713Sgirish 
442844961713Sgirish 	ldgp = nxgep->ldgvp->ldgp;
442944961713Sgirish 	for (x = 0; x < nrequired; x++, ldgp++) {
443044961713Sgirish 		ldgp->vector = (uint8_t)x;
443144961713Sgirish 		if (nxgep->niu_type != N2_NIU) {
443244961713Sgirish 			ldgp->intdata = SID_DATA(ldgp->func, x);
443344961713Sgirish 		}
443444961713Sgirish 
443544961713Sgirish 		arg1 = ldgp->ldvp;
443644961713Sgirish 		arg2 = nxgep;
443744961713Sgirish 		if (ldgp->nldvs == 1) {
443844961713Sgirish 			inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
443944961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
444044961713Sgirish 				"nxge_add_intrs_adv_type_fix: "
444144961713Sgirish 				"1-1 int handler(%d) ldg %d ldv %d "
444244961713Sgirish 				"arg1 $%p arg2 $%p\n",
444344961713Sgirish 				x, ldgp->ldg, ldgp->ldvp->ldv,
444444961713Sgirish 				arg1, arg2));
444544961713Sgirish 		} else if (ldgp->nldvs > 1) {
444644961713Sgirish 			inthandler = (uint_t *)ldgp->sys_intr_handler;
444744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL,
444844961713Sgirish 				"nxge_add_intrs_adv_type_fix: "
444944961713Sgirish 				"shared ldv %d int handler(%d) ldv %d ldg %d"
445044961713Sgirish 				"arg1 0x%016llx arg2 0x%016llx\n",
445144961713Sgirish 				x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
445244961713Sgirish 				arg1, arg2));
445344961713Sgirish 		}
445444961713Sgirish 
445544961713Sgirish 		if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
445644961713Sgirish 			(ddi_intr_handler_t *)inthandler, arg1, arg2))
445744961713Sgirish 				!= DDI_SUCCESS) {
445844961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
445944961713Sgirish 				"==> nxge_add_intrs_adv_type_fix: failed #%d "
446044961713Sgirish 				"status 0x%x", x, ddi_status));
446144961713Sgirish 			for (y = 0; y < intrp->intr_added; y++) {
446244961713Sgirish 				(void) ddi_intr_remove_handler(
446344961713Sgirish 						intrp->htable[y]);
446444961713Sgirish 			}
446544961713Sgirish 			for (y = 0; y < nactual; y++) {
446644961713Sgirish 				(void) ddi_intr_free(intrp->htable[y]);
446744961713Sgirish 			}
446844961713Sgirish 			/* Free already allocated intr */
446944961713Sgirish 			kmem_free(intrp->htable, intrp->intr_size);
447044961713Sgirish 
447144961713Sgirish 			(void) nxge_ldgv_uninit(nxgep);
447244961713Sgirish 
447344961713Sgirish 			return (NXGE_ERROR | NXGE_DDI_FAILED);
447444961713Sgirish 		}
447544961713Sgirish 		intrp->intr_added++;
447644961713Sgirish 	}
447744961713Sgirish 
447844961713Sgirish 	intrp->msi_intx_cnt = nactual;
447944961713Sgirish 
448044961713Sgirish 	(void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
448144961713Sgirish 
448244961713Sgirish 	status = nxge_intr_ldgv_init(nxgep);
448344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix"));
448444961713Sgirish 
448544961713Sgirish 	return (status);
448644961713Sgirish }
448744961713Sgirish 
448844961713Sgirish static void
448944961713Sgirish nxge_remove_intrs(p_nxge_t nxgep)
449044961713Sgirish {
449144961713Sgirish 	int		i, inum;
449244961713Sgirish 	p_nxge_intr_t	intrp;
449344961713Sgirish 
449444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs"));
449544961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
449644961713Sgirish 	if (!intrp->intr_registered) {
449744961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
449844961713Sgirish 			"<== nxge_remove_intrs: interrupts not registered"));
449944961713Sgirish 		return;
450044961713Sgirish 	}
450144961713Sgirish 
450244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced"));
450344961713Sgirish 
450444961713Sgirish 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
450544961713Sgirish 		(void) ddi_intr_block_disable(intrp->htable,
450644961713Sgirish 			intrp->intr_added);
450744961713Sgirish 	} else {
450844961713Sgirish 		for (i = 0; i < intrp->intr_added; i++) {
450944961713Sgirish 			(void) ddi_intr_disable(intrp->htable[i]);
451044961713Sgirish 		}
451144961713Sgirish 	}
451244961713Sgirish 
451344961713Sgirish 	for (inum = 0; inum < intrp->intr_added; inum++) {
451444961713Sgirish 		if (intrp->htable[inum]) {
451544961713Sgirish 			(void) ddi_intr_remove_handler(intrp->htable[inum]);
451644961713Sgirish 		}
451744961713Sgirish 	}
451844961713Sgirish 
451944961713Sgirish 	for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
452044961713Sgirish 		if (intrp->htable[inum]) {
452144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
452244961713Sgirish 				"nxge_remove_intrs: ddi_intr_free inum %d "
452344961713Sgirish 				"msi_intx_cnt %d intr_added %d",
452444961713Sgirish 				inum,
452544961713Sgirish 				intrp->msi_intx_cnt,
452644961713Sgirish 				intrp->intr_added));
452744961713Sgirish 
452844961713Sgirish 			(void) ddi_intr_free(intrp->htable[inum]);
452944961713Sgirish 		}
453044961713Sgirish 	}
453144961713Sgirish 
453244961713Sgirish 	kmem_free(intrp->htable, intrp->intr_size);
453344961713Sgirish 	intrp->intr_registered = B_FALSE;
453444961713Sgirish 	intrp->intr_enabled = B_FALSE;
453544961713Sgirish 	intrp->msi_intx_cnt = 0;
453644961713Sgirish 	intrp->intr_added = 0;
453744961713Sgirish 
4538a3c5bd6dSspeer 	(void) nxge_ldgv_uninit(nxgep);
4539a3c5bd6dSspeer 
4540ec090658Sml 	(void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip,
4541ec090658Sml 	    "#msix-request");
4542ec090658Sml 
454344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs"));
454444961713Sgirish }
454544961713Sgirish 
454644961713Sgirish /*ARGSUSED*/
454744961713Sgirish static void
454844961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep)
454944961713Sgirish {
455044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs"));
455144961713Sgirish 	if (nxgep->resched_id) {
455244961713Sgirish 		ddi_remove_softintr(nxgep->resched_id);
455344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
455444961713Sgirish 			"==> nxge_remove_soft_intrs: removed"));
455544961713Sgirish 		nxgep->resched_id = NULL;
455644961713Sgirish 	}
455744961713Sgirish 
455844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs"));
455944961713Sgirish }
456044961713Sgirish 
456144961713Sgirish /*ARGSUSED*/
456244961713Sgirish static void
456344961713Sgirish nxge_intrs_enable(p_nxge_t nxgep)
456444961713Sgirish {
456544961713Sgirish 	p_nxge_intr_t	intrp;
456644961713Sgirish 	int		i;
456744961713Sgirish 	int		status;
456844961713Sgirish 
456944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable"));
457044961713Sgirish 
457144961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
457244961713Sgirish 
457344961713Sgirish 	if (!intrp->intr_registered) {
457444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: "
457544961713Sgirish 			"interrupts are not registered"));
457644961713Sgirish 		return;
457744961713Sgirish 	}
457844961713Sgirish 
457944961713Sgirish 	if (intrp->intr_enabled) {
458044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL,
458144961713Sgirish 			"<== nxge_intrs_enable: already enabled"));
458244961713Sgirish 		return;
458344961713Sgirish 	}
458444961713Sgirish 
458544961713Sgirish 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
458644961713Sgirish 		status = ddi_intr_block_enable(intrp->htable,
458744961713Sgirish 			intrp->intr_added);
458844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
458944961713Sgirish 			"block enable - status 0x%x total inums #%d\n",
459044961713Sgirish 			status, intrp->intr_added));
459144961713Sgirish 	} else {
459244961713Sgirish 		for (i = 0; i < intrp->intr_added; i++) {
459344961713Sgirish 			status = ddi_intr_enable(intrp->htable[i]);
459444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
459544961713Sgirish 				"ddi_intr_enable:enable - status 0x%x "
459644961713Sgirish 				"total inums %d enable inum #%d\n",
459744961713Sgirish 				status, intrp->intr_added, i));
459844961713Sgirish 			if (status == DDI_SUCCESS) {
459944961713Sgirish 				intrp->intr_enabled = B_TRUE;
460044961713Sgirish 			}
460144961713Sgirish 		}
460244961713Sgirish 	}
460344961713Sgirish 
460444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable"));
460544961713Sgirish }
460644961713Sgirish 
460744961713Sgirish /*ARGSUSED*/
460844961713Sgirish static void
460944961713Sgirish nxge_intrs_disable(p_nxge_t nxgep)
461044961713Sgirish {
461144961713Sgirish 	p_nxge_intr_t	intrp;
461244961713Sgirish 	int		i;
461344961713Sgirish 
461444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable"));
461544961713Sgirish 
461644961713Sgirish 	intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
461744961713Sgirish 
461844961713Sgirish 	if (!intrp->intr_registered) {
461944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: "
462044961713Sgirish 			"interrupts are not registered"));
462144961713Sgirish 		return;
462244961713Sgirish 	}
462344961713Sgirish 
462444961713Sgirish 	if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
462544961713Sgirish 		(void) ddi_intr_block_disable(intrp->htable,
462644961713Sgirish 			intrp->intr_added);
462744961713Sgirish 	} else {
462844961713Sgirish 		for (i = 0; i < intrp->intr_added; i++) {
462944961713Sgirish 			(void) ddi_intr_disable(intrp->htable[i]);
463044961713Sgirish 		}
463144961713Sgirish 	}
463244961713Sgirish 
463344961713Sgirish 	intrp->intr_enabled = B_FALSE;
463444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable"));
463544961713Sgirish }
463644961713Sgirish 
463744961713Sgirish static nxge_status_t
463844961713Sgirish nxge_mac_register(p_nxge_t nxgep)
463944961713Sgirish {
464044961713Sgirish 	mac_register_t *macp;
464144961713Sgirish 	int		status;
464244961713Sgirish 
464344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register"));
464444961713Sgirish 
464544961713Sgirish 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
464644961713Sgirish 		return (NXGE_ERROR);
464744961713Sgirish 
464844961713Sgirish 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
464944961713Sgirish 	macp->m_driver = nxgep;
465044961713Sgirish 	macp->m_dip = nxgep->dip;
465144961713Sgirish 	macp->m_src_addr = nxgep->ouraddr.ether_addr_octet;
465244961713Sgirish 	macp->m_callbacks = &nxge_m_callbacks;
465344961713Sgirish 	macp->m_min_sdu = 0;
465444961713Sgirish 	macp->m_max_sdu = nxgep->mac.maxframesize -
465544961713Sgirish 		sizeof (struct ether_header) - ETHERFCSL - 4;
4656d62bc4baSyz 	macp->m_margin = VLAN_TAGSZ;
465744961713Sgirish 
465844961713Sgirish 	status = mac_register(macp, &nxgep->mach);
465944961713Sgirish 	mac_free(macp);
466044961713Sgirish 
466144961713Sgirish 	if (status != 0) {
466244961713Sgirish 		cmn_err(CE_WARN,
466344961713Sgirish 			"!nxge_mac_register failed (status %d instance %d)",
466444961713Sgirish 			status, nxgep->instance);
466544961713Sgirish 		return (NXGE_ERROR);
466644961713Sgirish 	}
466744961713Sgirish 
466844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success "
466944961713Sgirish 		"(instance %d)", nxgep->instance));
467044961713Sgirish 
467144961713Sgirish 	return (NXGE_OK);
467244961713Sgirish }
467344961713Sgirish 
467444961713Sgirish void
467544961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
467644961713Sgirish {
467744961713Sgirish 	ssize_t		size;
467844961713Sgirish 	mblk_t		*nmp;
467944961713Sgirish 	uint8_t		blk_id;
468044961713Sgirish 	uint8_t		chan;
468144961713Sgirish 	uint32_t	err_id;
468244961713Sgirish 	err_inject_t	*eip;
468344961713Sgirish 
468444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject"));
468544961713Sgirish 
468644961713Sgirish 	size = 1024;
468744961713Sgirish 	nmp = mp->b_cont;
468844961713Sgirish 	eip = (err_inject_t *)nmp->b_rptr;
468944961713Sgirish 	blk_id = eip->blk_id;
469044961713Sgirish 	err_id = eip->err_id;
469144961713Sgirish 	chan = eip->chan;
469244961713Sgirish 	cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id);
469344961713Sgirish 	cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id);
469444961713Sgirish 	cmn_err(CE_NOTE, "!chan = 0x%x\n", chan);
469544961713Sgirish 	switch (blk_id) {
469644961713Sgirish 	case MAC_BLK_ID:
469744961713Sgirish 		break;
469844961713Sgirish 	case TXMAC_BLK_ID:
469944961713Sgirish 		break;
470044961713Sgirish 	case RXMAC_BLK_ID:
470144961713Sgirish 		break;
470244961713Sgirish 	case MIF_BLK_ID:
470344961713Sgirish 		break;
470444961713Sgirish 	case IPP_BLK_ID:
470544961713Sgirish 		nxge_ipp_inject_err(nxgep, err_id);
470644961713Sgirish 		break;
470744961713Sgirish 	case TXC_BLK_ID:
470844961713Sgirish 		nxge_txc_inject_err(nxgep, err_id);
470944961713Sgirish 		break;
471044961713Sgirish 	case TXDMA_BLK_ID:
471144961713Sgirish 		nxge_txdma_inject_err(nxgep, err_id, chan);
471244961713Sgirish 		break;
471344961713Sgirish 	case RXDMA_BLK_ID:
471444961713Sgirish 		nxge_rxdma_inject_err(nxgep, err_id, chan);
471544961713Sgirish 		break;
471644961713Sgirish 	case ZCP_BLK_ID:
471744961713Sgirish 		nxge_zcp_inject_err(nxgep, err_id);
471844961713Sgirish 		break;
471944961713Sgirish 	case ESPC_BLK_ID:
472044961713Sgirish 		break;
472144961713Sgirish 	case FFLP_BLK_ID:
472244961713Sgirish 		break;
472344961713Sgirish 	case PHY_BLK_ID:
472444961713Sgirish 		break;
472544961713Sgirish 	case ETHER_SERDES_BLK_ID:
472644961713Sgirish 		break;
472744961713Sgirish 	case PCIE_SERDES_BLK_ID:
472844961713Sgirish 		break;
472944961713Sgirish 	case VIR_BLK_ID:
473044961713Sgirish 		break;
473144961713Sgirish 	}
473244961713Sgirish 
473344961713Sgirish 	nmp->b_wptr = nmp->b_rptr + size;
473444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject"));
473544961713Sgirish 
473644961713Sgirish 	miocack(wq, mp, (int)size, 0);
473744961713Sgirish }
473844961713Sgirish 
473944961713Sgirish static int
474044961713Sgirish nxge_init_common_dev(p_nxge_t nxgep)
474144961713Sgirish {
474244961713Sgirish 	p_nxge_hw_list_t	hw_p;
474344961713Sgirish 	dev_info_t 		*p_dip;
474444961713Sgirish 
474544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device"));
474644961713Sgirish 
474744961713Sgirish 	p_dip = nxgep->p_dip;
474844961713Sgirish 	MUTEX_ENTER(&nxge_common_lock);
474944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
475044961713Sgirish 		"==> nxge_init_common_dev:func # %d",
475144961713Sgirish 			nxgep->function_num));
475244961713Sgirish 	/*
475344961713Sgirish 	 * Loop through existing per neptune hardware list.
475444961713Sgirish 	 */
475544961713Sgirish 	for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
475644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
475744961713Sgirish 			"==> nxge_init_common_device:func # %d "
475844961713Sgirish 			"hw_p $%p parent dip $%p",
475944961713Sgirish 			nxgep->function_num,
476044961713Sgirish 			hw_p,
476144961713Sgirish 			p_dip));
476244961713Sgirish 		if (hw_p->parent_devp == p_dip) {
476344961713Sgirish 			nxgep->nxge_hw_p = hw_p;
476444961713Sgirish 			hw_p->ndevs++;
476544961713Sgirish 			hw_p->nxge_p[nxgep->function_num] = nxgep;
476644961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
476744961713Sgirish 				"==> nxge_init_common_device:func # %d "
476844961713Sgirish 				"hw_p $%p parent dip $%p "
476944961713Sgirish 				"ndevs %d (found)",
477044961713Sgirish 				nxgep->function_num,
477144961713Sgirish 				hw_p,
477244961713Sgirish 				p_dip,
477344961713Sgirish 				hw_p->ndevs));
477444961713Sgirish 			break;
477544961713Sgirish 		}
477644961713Sgirish 	}
477744961713Sgirish 
477844961713Sgirish 	if (hw_p == NULL) {
477944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
478044961713Sgirish 			"==> nxge_init_common_device:func # %d "
478144961713Sgirish 			"parent dip $%p (new)",
478244961713Sgirish 			nxgep->function_num,
478344961713Sgirish 			p_dip));
478444961713Sgirish 		hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP);
478544961713Sgirish 		hw_p->parent_devp = p_dip;
478644961713Sgirish 		hw_p->magic = NXGE_NEPTUNE_MAGIC;
478744961713Sgirish 		nxgep->nxge_hw_p = hw_p;
478844961713Sgirish 		hw_p->ndevs++;
478944961713Sgirish 		hw_p->nxge_p[nxgep->function_num] = nxgep;
479044961713Sgirish 		hw_p->next = nxge_hw_list;
479159ac0c16Sdavemq 		if (nxgep->niu_type == N2_NIU) {
479259ac0c16Sdavemq 			hw_p->niu_type = N2_NIU;
479359ac0c16Sdavemq 			hw_p->platform_type = P_NEPTUNE_NIU;
479459ac0c16Sdavemq 		} else {
479559ac0c16Sdavemq 			hw_p->niu_type = NIU_TYPE_NONE;
47962e59129aSraghus 			hw_p->platform_type = P_NEPTUNE_NONE;
479759ac0c16Sdavemq 		}
479844961713Sgirish 
479944961713Sgirish 		MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
480044961713Sgirish 		MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
480144961713Sgirish 		MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
480244961713Sgirish 		MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL);
480344961713Sgirish 		MUTEX_INIT(&hw_p->nxge_mii_lock, NULL, MUTEX_DRIVER, NULL);
480444961713Sgirish 
480544961713Sgirish 		nxge_hw_list = hw_p;
480659ac0c16Sdavemq 
480759ac0c16Sdavemq 		(void) nxge_scan_ports_phy(nxgep, nxge_hw_list);
480844961713Sgirish 	}
480944961713Sgirish 
481044961713Sgirish 	MUTEX_EXIT(&nxge_common_lock);
481159ac0c16Sdavemq 
48122e59129aSraghus 	nxgep->platform_type = hw_p->platform_type;
481359ac0c16Sdavemq 	if (nxgep->niu_type != N2_NIU) {
481459ac0c16Sdavemq 		nxgep->niu_type = hw_p->niu_type;
481559ac0c16Sdavemq 	}
481659ac0c16Sdavemq 
481744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
481844961713Sgirish 		"==> nxge_init_common_device (nxge_hw_list) $%p",
481944961713Sgirish 		nxge_hw_list));
482044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device"));
482144961713Sgirish 
482244961713Sgirish 	return (NXGE_OK);
482344961713Sgirish }
482444961713Sgirish 
482544961713Sgirish static void
482644961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep)
482744961713Sgirish {
482844961713Sgirish 	p_nxge_hw_list_t	hw_p, h_hw_p;
482944961713Sgirish 	dev_info_t 		*p_dip;
483044961713Sgirish 
483144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device"));
483244961713Sgirish 	if (nxgep->nxge_hw_p == NULL) {
483344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
483444961713Sgirish 			"<== nxge_uninit_common_device (no common)"));
483544961713Sgirish 		return;
483644961713Sgirish 	}
483744961713Sgirish 
483844961713Sgirish 	MUTEX_ENTER(&nxge_common_lock);
483944961713Sgirish 	h_hw_p = nxge_hw_list;
484044961713Sgirish 	for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
484144961713Sgirish 		p_dip = hw_p->parent_devp;
484244961713Sgirish 		if (nxgep->nxge_hw_p == hw_p &&
484344961713Sgirish 			p_dip == nxgep->p_dip &&
484444961713Sgirish 			nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC &&
484544961713Sgirish 			hw_p->magic == NXGE_NEPTUNE_MAGIC) {
484644961713Sgirish 
484744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MOD_CTL,
484844961713Sgirish 				"==> nxge_uninit_common_device:func # %d "
484944961713Sgirish 				"hw_p $%p parent dip $%p "
485044961713Sgirish 				"ndevs %d (found)",
485144961713Sgirish 				nxgep->function_num,
485244961713Sgirish 				hw_p,
485344961713Sgirish 				p_dip,
485444961713Sgirish 				hw_p->ndevs));
485544961713Sgirish 
485644961713Sgirish 			nxgep->nxge_hw_p = NULL;
485744961713Sgirish 			if (hw_p->ndevs) {
485844961713Sgirish 				hw_p->ndevs--;
485944961713Sgirish 			}
486044961713Sgirish 			hw_p->nxge_p[nxgep->function_num] = NULL;
486144961713Sgirish 			if (!hw_p->ndevs) {
486244961713Sgirish 				MUTEX_DESTROY(&hw_p->nxge_vlan_lock);
486344961713Sgirish 				MUTEX_DESTROY(&hw_p->nxge_tcam_lock);
486444961713Sgirish 				MUTEX_DESTROY(&hw_p->nxge_cfg_lock);
486544961713Sgirish 				MUTEX_DESTROY(&hw_p->nxge_mdio_lock);
486644961713Sgirish 				MUTEX_DESTROY(&hw_p->nxge_mii_lock);
486744961713Sgirish 				NXGE_DEBUG_MSG((nxgep, MOD_CTL,
486844961713Sgirish 					"==> nxge_uninit_common_device: "
486944961713Sgirish 					"func # %d "
487044961713Sgirish 					"hw_p $%p parent dip $%p "
487144961713Sgirish 					"ndevs %d (last)",
487244961713Sgirish 					nxgep->function_num,
487344961713Sgirish 					hw_p,
487444961713Sgirish 					p_dip,
487544961713Sgirish 					hw_p->ndevs));
487644961713Sgirish 
487744961713Sgirish 				if (hw_p == nxge_hw_list) {
487844961713Sgirish 					NXGE_DEBUG_MSG((nxgep, MOD_CTL,
487944961713Sgirish 						"==> nxge_uninit_common_device:"
488044961713Sgirish 						"remove head func # %d "
488144961713Sgirish 						"hw_p $%p parent dip $%p "
488244961713Sgirish 						"ndevs %d (head)",
488344961713Sgirish 						nxgep->function_num,
488444961713Sgirish 						hw_p,
488544961713Sgirish 						p_dip,
488644961713Sgirish 						hw_p->ndevs));
488744961713Sgirish 					nxge_hw_list = hw_p->next;
488844961713Sgirish 				} else {
488944961713Sgirish 					NXGE_DEBUG_MSG((nxgep, MOD_CTL,
489044961713Sgirish 						"==> nxge_uninit_common_device:"
489144961713Sgirish 						"remove middle func # %d "
489244961713Sgirish 						"hw_p $%p parent dip $%p "
489344961713Sgirish 						"ndevs %d (middle)",
489444961713Sgirish 						nxgep->function_num,
489544961713Sgirish 						hw_p,
489644961713Sgirish 						p_dip,
489744961713Sgirish 						hw_p->ndevs));
489844961713Sgirish 					h_hw_p->next = hw_p->next;
489944961713Sgirish 				}
490044961713Sgirish 
490144961713Sgirish 				KMEM_FREE(hw_p, sizeof (nxge_hw_list_t));
490244961713Sgirish 			}
490344961713Sgirish 			break;
490444961713Sgirish 		} else {
490544961713Sgirish 			h_hw_p = hw_p;
490644961713Sgirish 		}
490744961713Sgirish 	}
490844961713Sgirish 
490944961713Sgirish 	MUTEX_EXIT(&nxge_common_lock);
491044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL,
491144961713Sgirish 		"==> nxge_uninit_common_device (nxge_hw_list) $%p",
491244961713Sgirish 		nxge_hw_list));
491344961713Sgirish 
491444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device"));
491544961713Sgirish }
491659ac0c16Sdavemq 
491759ac0c16Sdavemq /*
49182e59129aSraghus  * Determines the number of ports from the niu_type or the platform type.
491959ac0c16Sdavemq  * Returns the number of ports, or returns zero on failure.
492059ac0c16Sdavemq  */
492159ac0c16Sdavemq 
492259ac0c16Sdavemq int
49232e59129aSraghus nxge_get_nports(p_nxge_t nxgep)
492459ac0c16Sdavemq {
492559ac0c16Sdavemq 	int	nports = 0;
492659ac0c16Sdavemq 
49272e59129aSraghus 	switch (nxgep->niu_type) {
492859ac0c16Sdavemq 	case N2_NIU:
492959ac0c16Sdavemq 	case NEPTUNE_2_10GF:
493059ac0c16Sdavemq 		nports = 2;
493159ac0c16Sdavemq 		break;
493259ac0c16Sdavemq 	case NEPTUNE_4_1GC:
493359ac0c16Sdavemq 	case NEPTUNE_2_10GF_2_1GC:
493459ac0c16Sdavemq 	case NEPTUNE_1_10GF_3_1GC:
493559ac0c16Sdavemq 	case NEPTUNE_1_1GC_1_10GF_2_1GC:
493659ac0c16Sdavemq 		nports = 4;
493759ac0c16Sdavemq 		break;
493859ac0c16Sdavemq 	default:
49392e59129aSraghus 		switch (nxgep->platform_type) {
49402e59129aSraghus 		case P_NEPTUNE_NIU:
49412e59129aSraghus 		case P_NEPTUNE_ATLAS_2PORT:
49422e59129aSraghus 			nports = 2;
49432e59129aSraghus 			break;
49442e59129aSraghus 		case P_NEPTUNE_ATLAS_4PORT:
49452e59129aSraghus 		case P_NEPTUNE_MARAMBA_P0:
49462e59129aSraghus 		case P_NEPTUNE_MARAMBA_P1:
4947d81011f0Ssbehera 		case P_NEPTUNE_ALONSO:
49482e59129aSraghus 			nports = 4;
49492e59129aSraghus 			break;
49502e59129aSraghus 		default:
49512e59129aSraghus 			break;
49522e59129aSraghus 		}
495359ac0c16Sdavemq 		break;
495459ac0c16Sdavemq 	}
495559ac0c16Sdavemq 
495659ac0c16Sdavemq 	return (nports);
495759ac0c16Sdavemq }
4958ec090658Sml 
4959ec090658Sml /*
4960ec090658Sml  * The following two functions are to support
4961ec090658Sml  * PSARC/2007/453 MSI-X interrupt limit override.
4962ec090658Sml  */
4963ec090658Sml static int
4964ec090658Sml nxge_create_msi_property(p_nxge_t nxgep)
4965ec090658Sml {
4966ec090658Sml 	int	nmsi;
4967ec090658Sml 	extern	int ncpus;
4968ec090658Sml 
4969ec090658Sml 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property"));
4970ec090658Sml 
4971ec090658Sml 	switch (nxgep->mac.portmode) {
4972ec090658Sml 	case PORT_10G_COPPER:
4973ec090658Sml 	case PORT_10G_FIBER:
4974ec090658Sml 		(void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip,
4975ec090658Sml 		    DDI_PROP_CANSLEEP, "#msix-request", NULL, 0);
4976ec090658Sml 		/*
4977ec090658Sml 		 * The maximum MSI-X requested will be 8.
4978ec090658Sml 		 * If the # of CPUs is less than 8, we will reqeust
4979ec090658Sml 		 * # MSI-X based on the # of CPUs.
4980ec090658Sml 		 */
4981ec090658Sml 		if (ncpus >= NXGE_MSIX_REQUEST_10G) {
4982ec090658Sml 			nmsi = NXGE_MSIX_REQUEST_10G;
4983ec090658Sml 		} else {
4984ec090658Sml 			nmsi = ncpus;
4985ec090658Sml 		}
4986ec090658Sml 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
4987ec090658Sml 		    "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)",
4988ec090658Sml 		    ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
4989ec090658Sml 		    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
4990ec090658Sml 		break;
4991ec090658Sml 
4992ec090658Sml 	default:
4993ec090658Sml 		nmsi = NXGE_MSIX_REQUEST_1G;
4994ec090658Sml 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
4995ec090658Sml 		    "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)",
4996ec090658Sml 		    ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip,
4997ec090658Sml 		    DDI_PROP_CANSLEEP, "#msix-request"), nmsi));
4998ec090658Sml 		break;
4999ec090658Sml 	}
5000ec090658Sml 
5001ec090658Sml 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property"));
5002ec090658Sml 	return (nmsi);
5003ec090658Sml }
5004